dfsan_custom.cc revision c85d6274d127d988539ed6a35242d3f82c4eb5bf
1//===-- dfsan.cc ----------------------------------------------------------===//
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// This file is a part of DataFlowSanitizer.
11//
12// This file defines the custom functions listed in done_abilist.txt.
13//===----------------------------------------------------------------------===//
14#include "sanitizer_common/sanitizer_internal_defs.h"
15#include "sanitizer_common/sanitizer_linux.h"
16
17#include "dfsan/dfsan.h"
18
19#include <ctype.h>
20#include <dlfcn.h>
21#include <link.h>
22#include <pthread.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <time.h>
28#include <unistd.h>
29
30using namespace __dfsan;
31
32extern "C" {
33
34SANITIZER_INTERFACE_ATTRIBUTE int
35__dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
36            dfsan_label buf_label, dfsan_label *ret_label) {
37  int ret = stat(path, buf);
38  if (ret == 0)
39    dfsan_set_label(0, buf, sizeof(struct stat));
40  *ret_label = 0;
41  return ret;
42}
43
44SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
45                                               dfsan_label fd_label,
46                                               dfsan_label buf_label,
47                                               dfsan_label *ret_label) {
48  int ret = fstat(fd, buf);
49  if (ret == 0)
50    dfsan_set_label(0, buf, sizeof(struct stat));
51  *ret_label = 0;
52  return ret;
53}
54
55SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
56                                                  dfsan_label s_label,
57                                                  dfsan_label c_label,
58                                                  dfsan_label *ret_label) {
59  for (size_t i = 0;; ++i) {
60    if (s[i] == c || s[i] == 0) {
61      *ret_label = dfsan_union(dfsan_read_label(s, i+1), c_label);
62      return s[i] == 0 ? 0 : const_cast<char *>(s+i);
63    }
64  }
65}
66
67SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
68                                                size_t n, dfsan_label s1_label,
69                                                dfsan_label s2_label,
70                                                dfsan_label n_label,
71                                                dfsan_label *ret_label) {
72  const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
73  for (size_t i = 0; i != n; ++i) {
74    if (cs1[i] != cs2[i]) {
75      *ret_label = dfsan_union(dfsan_read_label(cs1, i+1),
76                               dfsan_read_label(cs2, i+1));
77      return cs1[i] - cs2[i];
78    }
79  }
80  *ret_label = dfsan_union(dfsan_read_label(cs1, n),
81                           dfsan_read_label(cs2, n));
82  return 0;
83}
84
85SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
86                                                dfsan_label s1_label,
87                                                dfsan_label s2_label,
88                                                dfsan_label *ret_label) {
89  for (size_t i = 0;; ++i) {
90    if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0) {
91      *ret_label = dfsan_union(dfsan_read_label(s1, i+1),
92                               dfsan_read_label(s2, i+1));
93      return s1[i] - s2[i];
94    }
95  }
96  return 0;
97}
98
99SANITIZER_INTERFACE_ATTRIBUTE int
100__dfsw_strcasecmp(const char *s1, const char *s2, dfsan_label s1_label,
101                  dfsan_label s2_label, dfsan_label *ret_label) {
102  for (size_t i = 0;; ++i) {
103    if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0) {
104      *ret_label = dfsan_union(dfsan_read_label(s1, i+1),
105                               dfsan_read_label(s2, i+1));
106      return s1[i] - s2[i];
107    }
108  }
109  return 0;
110}
111
112SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
113                                                 size_t n, dfsan_label s1_label,
114                                                 dfsan_label s2_label,
115                                                 dfsan_label n_label,
116                                                 dfsan_label *ret_label) {
117  if (n == 0) {
118    *ret_label = 0;
119    return 0;
120  }
121
122  for (size_t i = 0;; ++i) {
123    if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || i == n-1) {
124      *ret_label = dfsan_union(dfsan_read_label(s1, i+1),
125                               dfsan_read_label(s2, i+1));
126      return s1[i] - s2[i];
127    }
128  }
129  return 0;
130}
131
132SANITIZER_INTERFACE_ATTRIBUTE int
133__dfsw_strncasecmp(const char *s1, const char *s2, size_t n,
134                   dfsan_label s1_label, dfsan_label s2_label,
135                   dfsan_label n_label, dfsan_label *ret_label) {
136  if (n == 0) {
137    *ret_label = 0;
138    return 0;
139  }
140
141  for (size_t i = 0;; ++i) {
142    if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0 ||
143        i == n - 1) {
144      *ret_label = dfsan_union(dfsan_read_label(s1, i+1),
145                               dfsan_read_label(s2, i+1));
146      return s1[i] - s2[i];
147    }
148  }
149  return 0;
150}
151
152SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_calloc(size_t nmemb, size_t size,
153                                                  dfsan_label nmemb_label,
154                                                  dfsan_label size_label,
155                                                  dfsan_label *ret_label) {
156  void *p = calloc(nmemb, size);
157  dfsan_set_label(0, p, nmemb * size);
158  *ret_label = 0;
159  return p;
160}
161
162SANITIZER_INTERFACE_ATTRIBUTE size_t
163__dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
164  size_t ret = strlen(s);
165  *ret_label = dfsan_read_label(s, ret+1);
166  return ret;
167}
168
169
170static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
171  dfsan_label *sdest = shadow_for(dest), *ssrc = shadow_for((void *)src);
172  internal_memcpy((void *)sdest, (void *)ssrc, n * sizeof(dfsan_label));
173  return internal_memcpy(dest, src, n);
174}
175
176static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
177  internal_memset(s, c, n);
178  dfsan_set_label(c_label, s, n);
179}
180
181SANITIZER_INTERFACE_ATTRIBUTE
182void *__dfsw_memcpy(void *dest, const void *src, size_t n,
183                    dfsan_label dest_label, dfsan_label src_label,
184                    dfsan_label n_label, dfsan_label *ret_label) {
185  *ret_label = 0;
186  return dfsan_memcpy(dest, src, n);
187}
188
189SANITIZER_INTERFACE_ATTRIBUTE
190void *__dfsw_memset(void *s, int c, size_t n,
191                    dfsan_label s_label, dfsan_label c_label,
192                    dfsan_label n_label, dfsan_label *ret_label) {
193  dfsan_memset(s, c, c_label, n);
194  *ret_label = 0;
195  return s;
196}
197
198SANITIZER_INTERFACE_ATTRIBUTE char *
199__dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
200  size_t len = strlen(s);
201  void *p = malloc(len+1);
202  dfsan_memcpy(p, s, len+1);
203  *ret_label = 0;
204  return static_cast<char *>(p);
205}
206
207SANITIZER_INTERFACE_ATTRIBUTE char *
208__dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
209               dfsan_label s2_label, dfsan_label n_label,
210               dfsan_label *ret_label) {
211  size_t len = strlen(s2);
212  if (len < n) {
213    dfsan_memcpy(s1, s2, len+1);
214    dfsan_memset(s1+len+1, 0, 0, n-len-1);
215  } else {
216    dfsan_memcpy(s1, s2, n);
217  }
218
219  *ret_label = 0;
220  return s1;
221}
222
223SANITIZER_INTERFACE_ATTRIBUTE ssize_t
224__dfsw_pread(int fd, void *buf, size_t count, off_t offset,
225             dfsan_label fd_label, dfsan_label buf_label,
226             dfsan_label count_label, dfsan_label offset_label,
227             dfsan_label *ret_label) {
228  ssize_t ret = pread(fd, buf, count, offset);
229  if (ret > 0)
230    dfsan_set_label(0, buf, ret);
231  *ret_label = 0;
232  return ret;
233}
234
235SANITIZER_INTERFACE_ATTRIBUTE ssize_t
236__dfsw_read(int fd, void *buf, size_t count,
237             dfsan_label fd_label, dfsan_label buf_label,
238             dfsan_label count_label,
239             dfsan_label *ret_label) {
240  ssize_t ret = read(fd, buf, count);
241  if (ret > 0)
242    dfsan_set_label(0, buf, ret);
243  *ret_label = 0;
244  return ret;
245}
246
247SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
248                                                       struct timespec *tp,
249                                                       dfsan_label clk_id_label,
250                                                       dfsan_label tp_label,
251                                                       dfsan_label *ret_label) {
252  int ret = clock_gettime(clk_id, tp);
253  if (ret == 0)
254    dfsan_set_label(0, tp, sizeof(struct timespec));
255  *ret_label = 0;
256  return ret;
257}
258
259static void unpoison(const void *ptr, uptr size) {
260  dfsan_set_label(0, const_cast<void *>(ptr), size);
261}
262
263// dlopen() ultimately calls mmap() down inside the loader, which generally
264// doesn't participate in dynamic symbol resolution.  Therefore we won't
265// intercept its calls to mmap, and we have to hook it here.
266SANITIZER_INTERFACE_ATTRIBUTE void *
267__dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
268              dfsan_label flag_label, dfsan_label *ret_label) {
269  link_map *map = (link_map *)dlopen(filename, flag);
270  if (map)
271    ForEachMappedRegion(map, unpoison);
272  *ret_label = 0;
273  return (void *)map;
274}
275
276struct pthread_create_info {
277  void *(*start_routine_trampoline)(void *, void *, dfsan_label, dfsan_label *);
278  void *start_routine;
279  void *arg;
280};
281
282static void *pthread_create_cb(void *p) {
283  pthread_create_info pci(*(pthread_create_info *)p);
284  free(p);
285  dfsan_label ret_label;
286  return pci.start_routine_trampoline(pci.start_routine, pci.arg, 0,
287                                      &ret_label);
288}
289
290SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
291    pthread_t *thread, const pthread_attr_t *attr,
292    void *(*start_routine_trampoline)(void *, void *, dfsan_label,
293                                      dfsan_label *),
294    void *start_routine, void *arg, dfsan_label thread_label,
295    dfsan_label attr_label, dfsan_label start_routine_label,
296    dfsan_label arg_label, dfsan_label *ret_label) {
297  pthread_create_info *pci =
298      (pthread_create_info *)malloc(sizeof(pthread_create_info));
299  pci->start_routine_trampoline = start_routine_trampoline;
300  pci->start_routine = start_routine;
301  pci->arg = arg;
302  int rv = pthread_create(thread, attr, pthread_create_cb, (void *)pci);
303  if (rv != 0)
304    free(pci);
305  *ret_label = 0;
306  return rv;
307}
308
309struct dl_iterate_phdr_info {
310  int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
311                             size_t size, void *data, dfsan_label info_label,
312                             dfsan_label size_label, dfsan_label data_label,
313                             dfsan_label *ret_label);
314  void *callback;
315  void *data;
316};
317
318int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
319  dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
320  dfsan_set_label(0, *info);
321  dfsan_set_label(0, (void *)info->dlpi_name, strlen(info->dlpi_name) + 1);
322  dfsan_set_label(0, (void *)info->dlpi_phdr,
323                  sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
324  dfsan_label ret_label;
325  return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
326                                   0, &ret_label);
327}
328
329SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
330    int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
331                               size_t size, void *data, dfsan_label info_label,
332                               dfsan_label size_label, dfsan_label data_label,
333                               dfsan_label *ret_label),
334    void *callback, void *data, dfsan_label callback_label,
335    dfsan_label data_label, dfsan_label *ret_label) {
336  dl_iterate_phdr_info dipi = { callback_trampoline, callback, data };
337  *ret_label = 0;
338  return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
339}
340
341}
342