[ASan/Win tests] Bring back -GS- as SEH tests fail otherwise
[blocksruntime.git] / lib / dfsan / dfsan_custom.cc
blobd06a003210c6f2d9d0f3f33ac994c2289acfb7d5
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.
12 // This file defines the custom functions listed in done_abilist.txt.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_common/sanitizer_internal_defs.h"
16 #include "sanitizer_common/sanitizer_linux.h"
18 #include "dfsan/dfsan.h"
20 #include <arpa/inet.h>
21 #include <ctype.h>
22 #include <dlfcn.h>
23 #include <link.h>
24 #include <poll.h>
25 #include <pthread.h>
26 #include <pwd.h>
27 #include <sched.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/resource.h>
33 #include <sys/select.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <time.h>
38 #include <unistd.h>
40 using namespace __dfsan;
42 extern "C" {
43 SANITIZER_INTERFACE_ATTRIBUTE int
44 __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
45 dfsan_label buf_label, dfsan_label *ret_label) {
46 int ret = stat(path, buf);
47 if (ret == 0)
48 dfsan_set_label(0, buf, sizeof(struct stat));
49 *ret_label = 0;
50 return ret;
53 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
54 dfsan_label fd_label,
55 dfsan_label buf_label,
56 dfsan_label *ret_label) {
57 int ret = fstat(fd, buf);
58 if (ret == 0)
59 dfsan_set_label(0, buf, sizeof(struct stat));
60 *ret_label = 0;
61 return ret;
64 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
65 dfsan_label s_label,
66 dfsan_label c_label,
67 dfsan_label *ret_label) {
68 for (size_t i = 0;; ++i) {
69 if (s[i] == c || s[i] == 0) {
70 if (flags().strict_data_dependencies) {
71 *ret_label = s_label;
72 } else {
73 *ret_label = dfsan_union(dfsan_read_label(s, i + 1),
74 dfsan_union(s_label, c_label));
76 return s[i] == 0 ? 0 : const_cast<char *>(s+i);
81 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
82 size_t n, dfsan_label s1_label,
83 dfsan_label s2_label,
84 dfsan_label n_label,
85 dfsan_label *ret_label) {
86 const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
87 for (size_t i = 0; i != n; ++i) {
88 if (cs1[i] != cs2[i]) {
89 if (flags().strict_data_dependencies) {
90 *ret_label = 0;
91 } else {
92 *ret_label = dfsan_union(dfsan_read_label(cs1, i + 1),
93 dfsan_read_label(cs2, i + 1));
95 return cs1[i] - cs2[i];
99 if (flags().strict_data_dependencies) {
100 *ret_label = 0;
101 } else {
102 *ret_label = dfsan_union(dfsan_read_label(cs1, n),
103 dfsan_read_label(cs2, n));
105 return 0;
108 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
109 dfsan_label s1_label,
110 dfsan_label s2_label,
111 dfsan_label *ret_label) {
112 for (size_t i = 0;; ++i) {
113 if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0) {
114 if (flags().strict_data_dependencies) {
115 *ret_label = 0;
116 } else {
117 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
118 dfsan_read_label(s2, i + 1));
120 return s1[i] - s2[i];
123 return 0;
126 SANITIZER_INTERFACE_ATTRIBUTE int
127 __dfsw_strcasecmp(const char *s1, const char *s2, dfsan_label s1_label,
128 dfsan_label s2_label, dfsan_label *ret_label) {
129 for (size_t i = 0;; ++i) {
130 if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0) {
131 if (flags().strict_data_dependencies) {
132 *ret_label = 0;
133 } else {
134 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
135 dfsan_read_label(s2, i + 1));
137 return s1[i] - s2[i];
140 return 0;
143 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
144 size_t n, dfsan_label s1_label,
145 dfsan_label s2_label,
146 dfsan_label n_label,
147 dfsan_label *ret_label) {
148 if (n == 0) {
149 *ret_label = 0;
150 return 0;
153 for (size_t i = 0;; ++i) {
154 if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || i == n - 1) {
155 if (flags().strict_data_dependencies) {
156 *ret_label = 0;
157 } else {
158 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
159 dfsan_read_label(s2, i + 1));
161 return s1[i] - s2[i];
164 return 0;
167 SANITIZER_INTERFACE_ATTRIBUTE int
168 __dfsw_strncasecmp(const char *s1, const char *s2, size_t n,
169 dfsan_label s1_label, dfsan_label s2_label,
170 dfsan_label n_label, dfsan_label *ret_label) {
171 if (n == 0) {
172 *ret_label = 0;
173 return 0;
176 for (size_t i = 0;; ++i) {
177 if (tolower(s1[i]) != tolower(s2[i]) || s1[i] == 0 || s2[i] == 0 ||
178 i == n - 1) {
179 if (flags().strict_data_dependencies) {
180 *ret_label = 0;
181 } else {
182 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1),
183 dfsan_read_label(s2, i + 1));
185 return s1[i] - s2[i];
188 return 0;
191 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_calloc(size_t nmemb, size_t size,
192 dfsan_label nmemb_label,
193 dfsan_label size_label,
194 dfsan_label *ret_label) {
195 void *p = calloc(nmemb, size);
196 dfsan_set_label(0, p, nmemb * size);
197 *ret_label = 0;
198 return p;
201 SANITIZER_INTERFACE_ATTRIBUTE size_t
202 __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
203 size_t ret = strlen(s);
204 if (flags().strict_data_dependencies) {
205 *ret_label = 0;
206 } else {
207 *ret_label = dfsan_read_label(s, ret + 1);
209 return ret;
213 static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
214 dfsan_label *sdest = shadow_for(dest), *ssrc = shadow_for((void *)src);
215 internal_memcpy((void *)sdest, (void *)ssrc, n * sizeof(dfsan_label));
216 return internal_memcpy(dest, src, n);
219 static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
220 internal_memset(s, c, n);
221 dfsan_set_label(c_label, s, n);
224 SANITIZER_INTERFACE_ATTRIBUTE
225 void *__dfsw_memcpy(void *dest, const void *src, size_t n,
226 dfsan_label dest_label, dfsan_label src_label,
227 dfsan_label n_label, dfsan_label *ret_label) {
228 *ret_label = dest_label;
229 return dfsan_memcpy(dest, src, n);
232 SANITIZER_INTERFACE_ATTRIBUTE
233 void *__dfsw_memset(void *s, int c, size_t n,
234 dfsan_label s_label, dfsan_label c_label,
235 dfsan_label n_label, dfsan_label *ret_label) {
236 dfsan_memset(s, c, c_label, n);
237 *ret_label = s_label;
238 return s;
241 SANITIZER_INTERFACE_ATTRIBUTE char *
242 __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
243 size_t len = strlen(s);
244 void *p = malloc(len+1);
245 dfsan_memcpy(p, s, len+1);
246 *ret_label = 0;
247 return static_cast<char *>(p);
250 SANITIZER_INTERFACE_ATTRIBUTE char *
251 __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
252 dfsan_label s2_label, dfsan_label n_label,
253 dfsan_label *ret_label) {
254 size_t len = strlen(s2);
255 if (len < n) {
256 dfsan_memcpy(s1, s2, len+1);
257 dfsan_memset(s1+len+1, 0, 0, n-len-1);
258 } else {
259 dfsan_memcpy(s1, s2, n);
262 *ret_label = s1_label;
263 return s1;
266 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
267 __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
268 dfsan_label fd_label, dfsan_label buf_label,
269 dfsan_label count_label, dfsan_label offset_label,
270 dfsan_label *ret_label) {
271 ssize_t ret = pread(fd, buf, count, offset);
272 if (ret > 0)
273 dfsan_set_label(0, buf, ret);
274 *ret_label = 0;
275 return ret;
278 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
279 __dfsw_read(int fd, void *buf, size_t count,
280 dfsan_label fd_label, dfsan_label buf_label,
281 dfsan_label count_label,
282 dfsan_label *ret_label) {
283 ssize_t ret = read(fd, buf, count);
284 if (ret > 0)
285 dfsan_set_label(0, buf, ret);
286 *ret_label = 0;
287 return ret;
290 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
291 struct timespec *tp,
292 dfsan_label clk_id_label,
293 dfsan_label tp_label,
294 dfsan_label *ret_label) {
295 int ret = clock_gettime(clk_id, tp);
296 if (ret == 0)
297 dfsan_set_label(0, tp, sizeof(struct timespec));
298 *ret_label = 0;
299 return ret;
302 static void unpoison(const void *ptr, uptr size) {
303 dfsan_set_label(0, const_cast<void *>(ptr), size);
306 // dlopen() ultimately calls mmap() down inside the loader, which generally
307 // doesn't participate in dynamic symbol resolution. Therefore we won't
308 // intercept its calls to mmap, and we have to hook it here.
309 SANITIZER_INTERFACE_ATTRIBUTE void *
310 __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
311 dfsan_label flag_label, dfsan_label *ret_label) {
312 link_map *map = (link_map *)dlopen(filename, flag);
313 if (map)
314 ForEachMappedRegion(map, unpoison);
315 *ret_label = 0;
316 return (void *)map;
319 struct pthread_create_info {
320 void *(*start_routine_trampoline)(void *, void *, dfsan_label, dfsan_label *);
321 void *start_routine;
322 void *arg;
325 static void *pthread_create_cb(void *p) {
326 pthread_create_info pci(*(pthread_create_info *)p);
327 free(p);
328 dfsan_label ret_label;
329 return pci.start_routine_trampoline(pci.start_routine, pci.arg, 0,
330 &ret_label);
333 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
334 pthread_t *thread, const pthread_attr_t *attr,
335 void *(*start_routine_trampoline)(void *, void *, dfsan_label,
336 dfsan_label *),
337 void *start_routine, void *arg, dfsan_label thread_label,
338 dfsan_label attr_label, dfsan_label start_routine_label,
339 dfsan_label arg_label, dfsan_label *ret_label) {
340 pthread_create_info *pci =
341 (pthread_create_info *)malloc(sizeof(pthread_create_info));
342 pci->start_routine_trampoline = start_routine_trampoline;
343 pci->start_routine = start_routine;
344 pci->arg = arg;
345 int rv = pthread_create(thread, attr, pthread_create_cb, (void *)pci);
346 if (rv != 0)
347 free(pci);
348 *ret_label = 0;
349 return rv;
352 struct dl_iterate_phdr_info {
353 int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
354 size_t size, void *data, dfsan_label info_label,
355 dfsan_label size_label, dfsan_label data_label,
356 dfsan_label *ret_label);
357 void *callback;
358 void *data;
361 int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
362 dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
363 dfsan_set_label(0, *info);
364 dfsan_set_label(0, (void *)info->dlpi_name, strlen(info->dlpi_name) + 1);
365 dfsan_set_label(0, (void *)info->dlpi_phdr,
366 sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
367 dfsan_label ret_label;
368 return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
369 0, &ret_label);
372 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
373 int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
374 size_t size, void *data, dfsan_label info_label,
375 dfsan_label size_label, dfsan_label data_label,
376 dfsan_label *ret_label),
377 void *callback, void *data, dfsan_label callback_label,
378 dfsan_label data_label, dfsan_label *ret_label) {
379 dl_iterate_phdr_info dipi = { callback_trampoline, callback, data };
380 *ret_label = 0;
381 return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
384 SANITIZER_INTERFACE_ATTRIBUTE
385 char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
386 dfsan_label buf_label, dfsan_label *ret_label) {
387 char *ret = ctime_r(timep, buf);
388 if (ret) {
389 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
390 strlen(buf) + 1);
391 *ret_label = buf_label;
392 } else {
393 *ret_label = 0;
395 return ret;
398 SANITIZER_INTERFACE_ATTRIBUTE
399 char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
400 dfsan_label size_label, dfsan_label stream_label,
401 dfsan_label *ret_label) {
402 char *ret = fgets(s, size, stream);
403 if (ret) {
404 dfsan_set_label(0, ret, strlen(ret) + 1);
405 *ret_label = s_label;
406 } else {
407 *ret_label = 0;
409 return ret;
412 SANITIZER_INTERFACE_ATTRIBUTE
413 char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
414 dfsan_label size_label, dfsan_label *ret_label) {
415 char *ret = getcwd(buf, size);
416 if (ret) {
417 dfsan_set_label(0, ret, strlen(ret) + 1);
418 *ret_label = buf_label;
419 } else {
420 *ret_label = 0;
422 return ret;
425 SANITIZER_INTERFACE_ATTRIBUTE
426 char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
427 char *ret = get_current_dir_name();
428 if (ret) {
429 dfsan_set_label(0, ret, strlen(ret) + 1);
431 *ret_label = 0;
432 return ret;
435 SANITIZER_INTERFACE_ATTRIBUTE
436 int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
437 dfsan_label len_label, dfsan_label *ret_label) {
438 int ret = gethostname(name, len);
439 if (ret == 0) {
440 dfsan_set_label(0, name, strlen(name) + 1);
442 *ret_label = 0;
443 return ret;
446 SANITIZER_INTERFACE_ATTRIBUTE
447 int __dfsw_getrlimit(int resource, struct rlimit *rlim,
448 dfsan_label resource_label, dfsan_label rlim_label,
449 dfsan_label *ret_label) {
450 int ret = getrlimit(resource, rlim);
451 if (ret == 0) {
452 dfsan_set_label(0, rlim, sizeof(struct rlimit));
454 *ret_label = 0;
455 return ret;
458 SANITIZER_INTERFACE_ATTRIBUTE
459 int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
460 dfsan_label usage_label, dfsan_label *ret_label) {
461 int ret = getrusage(who, usage);
462 if (ret == 0) {
463 dfsan_set_label(0, usage, sizeof(struct rusage));
465 *ret_label = 0;
466 return ret;
469 SANITIZER_INTERFACE_ATTRIBUTE
470 char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
471 dfsan_label src_label, dfsan_label *ret_label) {
472 char *ret = strcpy(dest, src);
473 if (ret) {
474 internal_memcpy(shadow_for(dest), shadow_for(src),
475 sizeof(dfsan_label) * (strlen(src) + 1));
477 *ret_label = dst_label;
478 return ret;
481 SANITIZER_INTERFACE_ATTRIBUTE
482 long int __dfsw_strtol(const char *nptr, char **endptr, int base,
483 dfsan_label nptr_label, dfsan_label endptr_label,
484 dfsan_label base_label, dfsan_label *ret_label) {
485 char *tmp_endptr;
486 long int ret = strtol(nptr, &tmp_endptr, base);
487 if (endptr) {
488 *endptr = tmp_endptr;
490 if (tmp_endptr > nptr) {
491 // If *tmp_endptr is '\0' include its label as well.
492 *ret_label = dfsan_union(
493 base_label,
494 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
495 } else {
496 *ret_label = 0;
498 return ret;
501 SANITIZER_INTERFACE_ATTRIBUTE
502 double __dfsw_strtod(const char *nptr, char **endptr,
503 dfsan_label nptr_label, dfsan_label endptr_label,
504 dfsan_label *ret_label) {
505 char *tmp_endptr;
506 double ret = strtod(nptr, &tmp_endptr);
507 if (endptr) {
508 *endptr = tmp_endptr;
510 if (tmp_endptr > nptr) {
511 // If *tmp_endptr is '\0' include its label as well.
512 *ret_label = dfsan_read_label(
513 nptr,
514 tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
515 } else {
516 *ret_label = 0;
518 return ret;
521 SANITIZER_INTERFACE_ATTRIBUTE
522 long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
523 dfsan_label nptr_label, dfsan_label endptr_label,
524 dfsan_label base_label, dfsan_label *ret_label) {
525 char *tmp_endptr;
526 long long int ret = strtoll(nptr, &tmp_endptr, base);
527 if (endptr) {
528 *endptr = tmp_endptr;
530 if (tmp_endptr > nptr) {
531 // If *tmp_endptr is '\0' include its label as well.
532 *ret_label = dfsan_union(
533 base_label,
534 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
535 } else {
536 *ret_label = 0;
538 return ret;
541 SANITIZER_INTERFACE_ATTRIBUTE
542 unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
543 dfsan_label nptr_label, dfsan_label endptr_label,
544 dfsan_label base_label, dfsan_label *ret_label) {
545 char *tmp_endptr;
546 unsigned long int ret = strtoul(nptr, &tmp_endptr, base);
547 if (endptr) {
548 *endptr = tmp_endptr;
550 if (tmp_endptr > nptr) {
551 // If *tmp_endptr is '\0' include its label as well.
552 *ret_label = dfsan_union(
553 base_label,
554 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
555 } else {
556 *ret_label = 0;
558 return ret;
561 SANITIZER_INTERFACE_ATTRIBUTE
562 long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
563 dfsan_label nptr_label,
564 int base, dfsan_label endptr_label,
565 dfsan_label base_label,
566 dfsan_label *ret_label) {
567 char *tmp_endptr;
568 long long unsigned int ret = strtoull(nptr, &tmp_endptr, base);
569 if (endptr) {
570 *endptr = tmp_endptr;
572 if (tmp_endptr > nptr) {
573 // If *tmp_endptr is '\0' include its label as well.
574 *ret_label = dfsan_union(
575 base_label,
576 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
577 } else {
578 *ret_label = 0;
580 return ret;
583 SANITIZER_INTERFACE_ATTRIBUTE
584 time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
585 time_t ret = time(t);
586 if (ret != (time_t) -1 && t) {
587 dfsan_set_label(0, t, sizeof(time_t));
589 *ret_label = 0;
590 return ret;
593 SANITIZER_INTERFACE_ATTRIBUTE
594 int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
595 dfsan_label src_label, dfsan_label dst_label,
596 dfsan_label *ret_label) {
597 int ret = inet_pton(af, src, dst);
598 if (ret == 1) {
599 dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
600 af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
602 *ret_label = 0;
603 return ret;
606 SANITIZER_INTERFACE_ATTRIBUTE
607 struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
608 dfsan_label timep_label, dfsan_label result_label,
609 dfsan_label *ret_label) {
610 struct tm *ret = localtime_r(timep, result);
611 if (ret) {
612 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
613 sizeof(struct tm));
614 *ret_label = result_label;
615 } else {
616 *ret_label = 0;
618 return ret;
621 SANITIZER_INTERFACE_ATTRIBUTE
622 int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
623 char *buf, size_t buflen, struct passwd **result,
624 dfsan_label uid_label, dfsan_label pwd_label,
625 dfsan_label buf_label, dfsan_label buflen_label,
626 dfsan_label result_label, dfsan_label *ret_label) {
627 // Store the data in pwd, the strings referenced from pwd in buf, and the
628 // address of pwd in *result. On failure, NULL is stored in *result.
629 int ret = getpwuid_r(uid, pwd, buf, buflen, result);
630 if (ret == 0) {
631 dfsan_set_label(0, pwd, sizeof(struct passwd));
632 dfsan_set_label(0, buf, strlen(buf) + 1);
634 *ret_label = 0;
635 dfsan_set_label(0, result, sizeof(struct passwd*));
636 return ret;
639 SANITIZER_INTERFACE_ATTRIBUTE
640 int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
641 dfsan_label dfs_label, dfsan_label nfds_label,
642 dfsan_label timeout_label, dfsan_label *ret_label) {
643 int ret = poll(fds, nfds, timeout);
644 if (ret >= 0) {
645 for (; nfds > 0; --nfds) {
646 dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
649 *ret_label = 0;
650 return ret;
653 SANITIZER_INTERFACE_ATTRIBUTE
654 int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
655 fd_set *exceptfds, struct timeval *timeout,
656 dfsan_label nfds_label, dfsan_label readfds_label,
657 dfsan_label writefds_label, dfsan_label exceptfds_label,
658 dfsan_label timeout_label, dfsan_label *ret_label) {
659 int ret = select(nfds, readfds, writefds, exceptfds, timeout);
660 // Clear everything (also on error) since their content is either set or
661 // undefined.
662 if (readfds) {
663 dfsan_set_label(0, readfds, sizeof(fd_set));
665 if (writefds) {
666 dfsan_set_label(0, writefds, sizeof(fd_set));
668 if (exceptfds) {
669 dfsan_set_label(0, exceptfds, sizeof(fd_set));
671 dfsan_set_label(0, timeout, sizeof(struct timeval));
672 *ret_label = 0;
673 return ret;
676 SANITIZER_INTERFACE_ATTRIBUTE
677 int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
678 dfsan_label pid_label,
679 dfsan_label cpusetsize_label,
680 dfsan_label mask_label, dfsan_label *ret_label) {
681 int ret = sched_getaffinity(pid, cpusetsize, mask);
682 if (ret == 0) {
683 dfsan_set_label(0, mask, cpusetsize);
685 *ret_label = 0;
686 return ret;
689 SANITIZER_INTERFACE_ATTRIBUTE
690 int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
691 dfsan_label *ret_label) {
692 int ret = sigemptyset(set);
693 dfsan_set_label(0, set, sizeof(sigset_t));
694 return ret;
697 SANITIZER_INTERFACE_ATTRIBUTE
698 int __dfsw_sigaction(int signum, const struct sigaction *act,
699 struct sigaction *oldact, dfsan_label signum_label,
700 dfsan_label act_label, dfsan_label oldact_label,
701 dfsan_label *ret_label) {
702 int ret = sigaction(signum, act, oldact);
703 if (oldact) {
704 dfsan_set_label(0, oldact, sizeof(struct sigaction));
706 *ret_label = 0;
707 return ret;
710 SANITIZER_INTERFACE_ATTRIBUTE
711 int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
712 dfsan_label tv_label, dfsan_label tz_label,
713 dfsan_label *ret_label) {
714 int ret = gettimeofday(tv, tz);
715 if (tv) {
716 dfsan_set_label(0, tv, sizeof(struct timeval));
718 if (tz) {
719 dfsan_set_label(0, tz, sizeof(struct timezone));
721 *ret_label = 0;
722 return ret;
725 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
726 dfsan_label s_label,
727 dfsan_label c_label,
728 dfsan_label n_label,
729 dfsan_label *ret_label) {
730 void *ret = memchr(s, c, n);
731 if (flags().strict_data_dependencies) {
732 *ret_label = ret ? s_label : 0;
733 } else {
734 size_t len =
735 ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
736 : n;
737 *ret_label =
738 dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
740 return ret;
743 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
744 dfsan_label s_label,
745 dfsan_label c_label,
746 dfsan_label *ret_label) {
747 char *ret = strrchr(s, c);
748 if (flags().strict_data_dependencies) {
749 *ret_label = ret ? s_label : 0;
750 } else {
751 *ret_label =
752 dfsan_union(dfsan_read_label(s, strlen(s) + 1),
753 dfsan_union(s_label, c_label));
756 return ret;
759 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
760 dfsan_label haystack_label,
761 dfsan_label needle_label,
762 dfsan_label *ret_label) {
763 char *ret = strstr(haystack, needle);
764 if (flags().strict_data_dependencies) {
765 *ret_label = ret ? haystack_label : 0;
766 } else {
767 size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
768 *ret_label =
769 dfsan_union(dfsan_read_label(haystack, len),
770 dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
771 dfsan_union(haystack_label, needle_label)));
774 return ret;
777 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
778 struct timespec *rem,
779 dfsan_label req_label,
780 dfsan_label rem_label,
781 dfsan_label *ret_label) {
782 int ret = nanosleep(req, rem);
783 *ret_label = 0;
784 if (ret == -1) {
785 // Interrupted by a signal, rem is filled with the remaining time.
786 dfsan_set_label(0, rem, sizeof(struct timespec));
788 return ret;
791 SANITIZER_INTERFACE_ATTRIBUTE int
792 __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
793 dfsan_label domain_label, dfsan_label type_label,
794 dfsan_label protocol_label, dfsan_label sv_label,
795 dfsan_label *ret_label) {
796 int ret = socketpair(domain, type, protocol, sv);
797 *ret_label = 0;
798 if (ret == 0) {
799 dfsan_set_label(0, sv, sizeof(*sv) * 2);
801 return ret;
804 // Type of the trampoline function passed to the custom version of
805 // dfsan_set_write_callback.
806 typedef void (*write_trampoline_t)(
807 void *callback,
808 int fd, const void *buf, ssize_t count,
809 dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label);
811 // Calls to dfsan_set_write_callback() set the values in this struct.
812 // Calls to the custom version of write() read (and invoke) them.
813 static struct {
814 write_trampoline_t write_callback_trampoline = NULL;
815 void *write_callback = NULL;
816 } write_callback_info;
818 SANITIZER_INTERFACE_ATTRIBUTE void
819 __dfsw_dfsan_set_write_callback(
820 write_trampoline_t write_callback_trampoline,
821 void *write_callback,
822 dfsan_label write_callback_label,
823 dfsan_label *ret_label) {
824 write_callback_info.write_callback_trampoline = write_callback_trampoline;
825 write_callback_info.write_callback = write_callback;
828 SANITIZER_INTERFACE_ATTRIBUTE int
829 __dfsw_write(int fd, const void *buf, size_t count,
830 dfsan_label fd_label, dfsan_label buf_label,
831 dfsan_label count_label, dfsan_label *ret_label) {
832 if (write_callback_info.write_callback != NULL) {
833 write_callback_info.write_callback_trampoline(
834 write_callback_info.write_callback,
835 fd, buf, count,
836 fd_label, buf_label, count_label);
839 *ret_label = 0;
840 return write(fd, buf, count);