summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_common_syscalls.inc
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-04-11 14:37:04 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-04-11 14:37:04 +0000
commit2887a64cb7b82fc2dcbe4b1fcc33562077ec371a (patch)
tree69c378d6436047ec01f50c61fa03c77edb753650 /lib/sanitizer_common/sanitizer_common_syscalls.inc
parent37f9464fc0fa4df2acf04264c52ba542d0e3d3fb (diff)
downloadcompiler-rt-2887a64cb7b82fc2dcbe4b1fcc33562077ec371a.tar.gz
[sanitizer] Syscall hooks.
Pre- and post- hooks for linux syscalls. Not wired into anything, but exposed through public interface. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@179288 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common_syscalls.inc')
-rw-r--r--lib/sanitizer_common/sanitizer_common_syscalls.inc102
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_common_syscalls.inc b/lib/sanitizer_common/sanitizer_common_syscalls.inc
new file mode 100644
index 000000000..40cffb47a
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_common_syscalls.inc
@@ -0,0 +1,102 @@
+//===-- sanitizer_common_syscalls.inc ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common syscalls handlers for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// This file should be included into the tool's interceptor file,
+// which has to define it's own macros:
+// COMMON_SYSCALL_PRE_READ_RANGE
+// Called in prehook for regions that will be read by the kernel and
+// must be initialized.
+// COMMON_SYSCALL_PRE_WRITE_RANGE
+// Called in prehook for regions that will be written to by the kernel
+// and must be addressable. The actual write range may be smaller than
+// reported in the prehook. See POST_WRITE_RANGE.
+// COMMON_SYSCALL_POST_READ_RANGE
+// Called in posthook for regions that were read by the kernel. Does
+// not make much sense.
+// COMMON_SYSCALL_POST_WRITE_RANGE
+// Called in posthook for regions that were written to by the kernel
+// and are now initialized.
+//===----------------------------------------------------------------------===//
+
+#define PRE_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_##name
+#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
+#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
+
+#define POST_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_##name
+#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
+#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
+
+// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
+
+extern "C" {
+
+struct sanitizer_kernel_iovec {
+ void *iov_base;
+ unsigned long iov_len;
+};
+
+struct sanitizer_kernel_msghdr {
+ void *msg_name;
+ int msg_namelen;
+ struct sanitizer_kernel_iovec *msg_iov;
+ unsigned long msg_iovlen;
+ void *msg_control;
+ unsigned long msg_controllen;
+ unsigned msg_flags;
+};
+
+PRE_SYSCALL(recvmsg)(int sockfd, struct sanitizer_kernel_msghdr *msg,
+ int flags) {
+ PRE_READ(msg, sizeof(*msg));
+}
+
+POST_SYSCALL(recvmsg)(int res, int sockfd, struct sanitizer_kernel_msghdr *msg,
+ int flags) {
+ if (res > 0)
+ for (unsigned long i = 0; i < msg->msg_iovlen; ++i)
+ POST_WRITE(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+ POST_WRITE(msg->msg_control, msg->msg_controllen);
+}
+
+PRE_SYSCALL(rt_sigpending)(void *p, unsigned long s) { PRE_WRITE(p, s); }
+
+POST_SYSCALL(rt_sigpending)(int res, void *p, unsigned long s) {
+ if (res == 0)
+ POST_WRITE(p, s);
+}
+
+PRE_SYSCALL(getdents)(int fd, void *dirp, int count) { PRE_WRITE(dirp, count); }
+
+POST_SYSCALL(getdents)(int res, int fd, void *dirp, int count) {
+ if (res > 0)
+ POST_WRITE(dirp, res);
+}
+
+PRE_SYSCALL(getdents64)(int fd, void *dirp, int count) {
+ PRE_WRITE(dirp, count);
+}
+
+POST_SYSCALL(getdents64)(int res, int fd, void *dirp, int count) {
+ if (res > 0)
+ POST_WRITE(dirp, res);
+}
+
+} // extern "C"
+
+#undef PRE_SYSCALL
+#undef PRE_READ
+#undef PRE_WRITE
+#undef POST_SYSCALL
+#undef POST_READ
+#undef POST_WRITE