[PATCH] TidySigaction in sanitizer_linux
Sergey Matveev
earthdok at google.com
Mon Apr 1 08:47:44 PDT 2013
Hi kcc, glider, samsonov,
Add a wrapper for sigaction() that prevents it from copying garbage
stack values into unused portions of oldact.
http://llvm-reviews.chandlerc.com/D603
Files:
lib/sanitizer_common/sanitizer_linux.cc
lib/sanitizer_common/sanitizer_linux.h
lib/sanitizer_common/sanitizer_stoptheworld_linux.cc
Index: lib/sanitizer_common/sanitizer_linux.cc
===================================================================
--- lib/sanitizer_common/sanitizer_linux.cc
+++ lib/sanitizer_common/sanitizer_linux.cc
@@ -647,6 +647,19 @@
return syscall(__NR_sigaltstack, ss, oss);
}
+int TidySigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact) {
+ // XXX: This assumes the number of signals is 64, which is currently true on
+ // platforms we care about.
+ const uptr kKernelSigsetSize = 8;
+ int res = sigaction(signum, act, oldact);
+ if (oldact) {
+ internal_memset((void *)((uptr)&oldact->sa_mask + kKernelSigsetSize), 0,
+ sizeof(oldact->sa_mask) - kKernelSigsetSize);
+ }
+ return res;
+}
+
// ThreadLister implementation.
ThreadLister::ThreadLister(int pid)
: pid_(pid),
Index: lib/sanitizer_common/sanitizer_linux.h
===================================================================
--- lib/sanitizer_common/sanitizer_linux.h
+++ lib/sanitizer_common/sanitizer_linux.h
@@ -16,6 +16,7 @@
#include "sanitizer_internal_defs.h"
struct sigaltstack;
+struct sigaction;
namespace __sanitizer {
// Dirent structure for getdents(). Note that this structure is different from
@@ -27,6 +28,16 @@
int internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
int internal_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
+// At least in some libc implementations, sigaction() has a side-effect where
+// it copies 120 bytes from stack directly into oldact without ever touching
+// them. This happens because libc allocates a 128-byte signal mask for POSIX
+// compliance, but the syscall only writes to the first 8 bytes. The net effect
+// is that out-of-scope stack values end up in oldact, which can cause problems
+// in LSan. We fix this by wrapping sigaction() calls in a function that wipes
+// the unused portion of the signal mask.
+int TidySigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact);
+
// This class reads thread IDs from /proc/<pid>/task using only syscalls.
class ThreadLister {
public:
Index: lib/sanitizer_common/sanitizer_stoptheworld_linux.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld_linux.cc
+++ lib/sanitizer_common/sanitizer_stoptheworld_linux.cc
@@ -292,11 +292,10 @@
internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
new_sigaction.sa_handler = SIG_DFL;
sigfillset(&new_sigaction.sa_mask);
- sigaction(kUnblockedSignals[signal_index], &new_sigaction,
- &old_sigactions[signal_index]);
+ CHECK_EQ(0, TidySigaction(kUnblockedSignals[signal_index], &new_sigaction,
+ &old_sigactions[signal_index]));
}
- int sigprocmask_status = sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
- CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail
+ CHECK_EQ(0, sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset));
// Make this process dumpable. Processes that are not dumpable cannot be
// attached to.
int process_was_dumpable = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
@@ -339,10 +338,10 @@
// Restore the signal handlers.
for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
signal_index++) {
- sigaction(kUnblockedSignals[signal_index],
- &old_sigactions[signal_index], NULL);
+ CHECK_EQ(0, TidySigaction(kUnblockedSignals[signal_index],
+ &old_sigactions[signal_index], NULL));
}
- sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset);
+ CHECK_EQ(0, sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset));
}
// Platform-specific methods from SuspendedThreadsList.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D603.1.patch
Type: text/x-patch
Size: 3821 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130401/c0707f88/attachment.bin>
More information about the llvm-commits
mailing list