sanitizer_common_syscalls.inc revision 9d34659cd3570423fb1fa49248887e2bd4b762f9
1//===-- sanitizer_common_syscalls.inc ---------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Common syscalls handlers for tools like AddressSanitizer,
11// ThreadSanitizer, MemorySanitizer, etc.
12//
13// This file should be included into the tool's interceptor file,
14// which has to define it's own macros:
15//   COMMON_SYSCALL_PRE_READ_RANGE
16//          Called in prehook for regions that will be read by the kernel and
17//          must be initialized.
18//   COMMON_SYSCALL_PRE_WRITE_RANGE
19//          Called in prehook for regions that will be written to by the kernel
20//          and must be addressable. The actual write range may be smaller than
21//          reported in the prehook. See POST_WRITE_RANGE.
22//   COMMON_SYSCALL_POST_READ_RANGE
23//          Called in posthook for regions that were read by the kernel. Does
24//          not make much sense.
25//   COMMON_SYSCALL_POST_WRITE_RANGE
26//          Called in posthook for regions that were written to by the kernel
27//          and are now initialized.
28//===----------------------------------------------------------------------===//
29
30#define PRE_SYSCALL(name)                                                      \
31  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_##name
32#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
33#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
34
35#define POST_SYSCALL(name)                                                     \
36  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_##name
37#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
38#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
39
40// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
41
42extern "C" {
43struct sanitizer_kernel_iovec {
44  void *iov_base;
45  unsigned long iov_len;
46};
47
48struct sanitizer_kernel_msghdr {
49  void *msg_name;
50  int msg_namelen;
51  struct sanitizer_kernel_iovec *msg_iov;
52  unsigned long msg_iovlen;
53  void *msg_control;
54  unsigned long msg_controllen;
55  unsigned msg_flags;
56};
57
58struct sanitizer_kernel_timespec {
59  long tv_sec;
60  long tv_nsec;
61};
62
63struct sanitizer_kernel_timeval {
64  long tv_sec;
65  long tv_usec;
66};
67
68struct sanitizer_kernel_rusage {
69  struct sanitizer_kernel_timeval ru_timeval[2];
70  long ru_long[14];
71};
72
73PRE_SYSCALL(recvmsg)(int sockfd, struct sanitizer_kernel_msghdr *msg,
74                     int flags) {
75  PRE_READ(msg, sizeof(*msg));
76}
77
78POST_SYSCALL(recvmsg)(long res, int sockfd, struct sanitizer_kernel_msghdr *msg,
79                      int flags) {
80  if (res > 0)
81    for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
82      POST_WRITE(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
83    }
84  POST_WRITE(msg->msg_control, msg->msg_controllen);
85}
86
87PRE_SYSCALL(rt_sigpending)(void *p, unsigned long s) { PRE_WRITE(p, s); }
88
89POST_SYSCALL(rt_sigpending)(long res, void *p, unsigned long s) {
90  if (res == 0) {
91    POST_WRITE(p, s);
92  }
93}
94
95PRE_SYSCALL(getdents)(int fd, void *dirp, int count) { PRE_WRITE(dirp, count); }
96
97POST_SYSCALL(getdents)(long res, int fd, void *dirp, int count) {
98  if (res > 0) {
99    POST_WRITE(dirp, res);
100  }
101}
102
103PRE_SYSCALL(getdents64)(int fd, void *dirp, int count) {
104  PRE_WRITE(dirp, count);
105}
106
107POST_SYSCALL(getdents64)(long res, int fd, void *dirp, int count) {
108  if (res > 0) {
109    POST_WRITE(dirp, res);
110  }
111}
112
113PRE_SYSCALL(wait4)(int pid, int *status, int options,
114                   struct sanitizer_kernel_rusage *r) {
115  if (status) {
116    PRE_WRITE(status, sizeof(*status));
117  }
118  if (r) {
119    PRE_WRITE(r, sizeof(*r));
120  }
121}
122
123POST_SYSCALL(wait4)(long res, int pid, int *status, int options,
124                    struct sanitizer_kernel_rusage *r) {
125  if (res > 0) {
126    if (status) {
127      POST_WRITE(status, sizeof(*status));
128    }
129    if (r) {
130      POST_WRITE(r, sizeof(*r));
131    }
132  }
133}
134
135PRE_SYSCALL(waitpid)(int pid, int *status, int options) {
136  if (status) {
137    PRE_WRITE(status, sizeof(*status));
138  }
139}
140
141POST_SYSCALL(waitpid)(long res, int pid, int *status, int options) {
142  if (res > 0 && status) {
143    POST_WRITE(status, sizeof(*status));
144  }
145}
146
147PRE_SYSCALL(clock_gettime)(int clk_id, struct sanitizer_kernel_timespec *tp) {
148  if (tp) PRE_WRITE(tp, sizeof(*tp));
149}
150
151POST_SYSCALL(clock_gettime)(long res, int clk_id,
152                            struct sanitizer_kernel_timespec *tp) {
153  if (res == 0 && tp) POST_WRITE(tp, sizeof(*tp));
154}
155
156PRE_SYSCALL(clock_getres)(int clk_id, struct sanitizer_kernel_timespec *tp) {
157  if (tp) PRE_WRITE(tp, sizeof(*tp));
158}
159
160POST_SYSCALL(clock_getres)(long res, int clk_id,
161                           struct sanitizer_kernel_timespec *tp) {
162  if (res == 0 && tp) POST_WRITE(tp, sizeof(*tp));
163}
164
165PRE_SYSCALL(read)(unsigned int fd, char *buf, uptr count) {
166  if (buf) PRE_WRITE(buf, count);
167}
168
169POST_SYSCALL(read)(long res, unsigned int fd, char *buf, uptr count) {
170  if (res > 0 && buf) POST_WRITE(buf, res);
171}
172
173}  // extern "C"
174
175#undef PRE_SYSCALL
176#undef PRE_READ
177#undef PRE_WRITE
178#undef POST_SYSCALL
179#undef POST_READ
180#undef POST_WRITE
181