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
15#include "sanitizer_common/sanitizer_internal_defs.h"
16#include "sanitizer_common/sanitizer_linux.h"
17
18#include "dfsan/dfsan.h"
19
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>
39
40using namespace __dfsan;
41
42extern "C" {
43SANITIZER_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;
51}
52
53SANITIZER_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;
62}
63
64SANITIZER_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));
75      }
76      return s[i] == 0 ? 0 : const_cast<char *>(s+i);
77    }
78  }
79}
80
81SANITIZER_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));
94      }
95      return cs1[i] - cs2[i];
96    }
97  }
98
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));
104  }
105  return 0;
106}
107
108SANITIZER_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));
119      }
120      return s1[i] - s2[i];
121    }
122  }
123  return 0;
124}
125
126SANITIZER_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));
136      }
137      return s1[i] - s2[i];
138    }
139  }
140  return 0;
141}
142
143SANITIZER_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;
151  }
152
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));
160      }
161      return s1[i] - s2[i];
162    }
163  }
164  return 0;
165}
166
167SANITIZER_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;
174  }
175
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));
184      }
185      return s1[i] - s2[i];
186    }
187  }
188  return 0;
189}
190
191SANITIZER_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;
199}
200
201SANITIZER_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);
208  }
209  return ret;
210}
211
212
213static 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);
217}
218
219static 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);
222}
223
224SANITIZER_INTERFACE_ATTRIBUTE
225void *__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);
230}
231
232SANITIZER_INTERFACE_ATTRIBUTE
233void *__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;
239}
240
241SANITIZER_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);
248}
249
250SANITIZER_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);
260  }
261
262  *ret_label = s1_label;
263  return s1;
264}
265
266SANITIZER_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;
276}
277
278SANITIZER_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;
288}
289
290SANITIZER_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;
300}
301
302static void unpoison(const void *ptr, uptr size) {
303  dfsan_set_label(0, const_cast<void *>(ptr), size);
304}
305
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.
309SANITIZER_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;
317}
318
319struct pthread_create_info {
320  void *(*start_routine_trampoline)(void *, void *, dfsan_label, dfsan_label *);
321  void *start_routine;
322  void *arg;
323};
324
325static 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);
331}
332
333SANITIZER_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;
350}
351
352struct 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;
359};
360
361int 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);
370}
371
372SANITIZER_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);
382}
383
384SANITIZER_INTERFACE_ATTRIBUTE
385char *__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;
394  }
395  return ret;
396}
397
398SANITIZER_INTERFACE_ATTRIBUTE
399char *__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;
408  }
409  return ret;
410}
411
412SANITIZER_INTERFACE_ATTRIBUTE
413char *__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;
421  }
422  return ret;
423}
424
425SANITIZER_INTERFACE_ATTRIBUTE
426char *__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);
430  }
431  *ret_label = 0;
432  return ret;
433}
434
435SANITIZER_INTERFACE_ATTRIBUTE
436int __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);
441  }
442  *ret_label = 0;
443  return ret;
444}
445
446SANITIZER_INTERFACE_ATTRIBUTE
447int __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));
453  }
454  *ret_label = 0;
455  return ret;
456}
457
458SANITIZER_INTERFACE_ATTRIBUTE
459int __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));
464  }
465  *ret_label = 0;
466  return ret;
467}
468
469SANITIZER_INTERFACE_ATTRIBUTE
470char *__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));
476  }
477  *ret_label = dst_label;
478  return ret;
479}
480
481SANITIZER_INTERFACE_ATTRIBUTE
482long 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;
489  }
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;
497  }
498  return ret;
499}
500
501SANITIZER_INTERFACE_ATTRIBUTE
502double __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;
509  }
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;
517  }
518  return ret;
519}
520
521SANITIZER_INTERFACE_ATTRIBUTE
522long 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;
529  }
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;
537  }
538  return ret;
539}
540
541SANITIZER_INTERFACE_ATTRIBUTE
542unsigned 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;
549  }
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;
557  }
558  return ret;
559}
560
561SANITIZER_INTERFACE_ATTRIBUTE
562long 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;
571  }
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;
579  }
580  return ret;
581}
582
583SANITIZER_INTERFACE_ATTRIBUTE
584time_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));
588  }
589  *ret_label = 0;
590  return ret;
591}
592
593SANITIZER_INTERFACE_ATTRIBUTE
594int __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));
601  }
602  *ret_label = 0;
603  return ret;
604}
605
606SANITIZER_INTERFACE_ATTRIBUTE
607struct 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;
617  }
618  return ret;
619}
620
621SANITIZER_INTERFACE_ATTRIBUTE
622int __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);
633  }
634  *ret_label = 0;
635  dfsan_set_label(0, result, sizeof(struct passwd*));
636  return ret;
637}
638
639SANITIZER_INTERFACE_ATTRIBUTE
640int __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));
647    }
648  }
649  *ret_label = 0;
650  return ret;
651}
652
653SANITIZER_INTERFACE_ATTRIBUTE
654int __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));
664  }
665  if (writefds) {
666    dfsan_set_label(0, writefds, sizeof(fd_set));
667  }
668  if (exceptfds) {
669    dfsan_set_label(0, exceptfds, sizeof(fd_set));
670  }
671  dfsan_set_label(0, timeout, sizeof(struct timeval));
672  *ret_label = 0;
673  return ret;
674}
675
676SANITIZER_INTERFACE_ATTRIBUTE
677int __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);
684  }
685  *ret_label = 0;
686  return ret;
687}
688
689SANITIZER_INTERFACE_ATTRIBUTE
690int __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;
695}
696
697SANITIZER_INTERFACE_ATTRIBUTE
698int __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));
705  }
706  *ret_label = 0;
707  return ret;
708}
709
710SANITIZER_INTERFACE_ATTRIBUTE
711int __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));
717  }
718  if (tz) {
719    dfsan_set_label(0, tz, sizeof(struct timezone));
720  }
721  *ret_label = 0;
722  return ret;
723}
724
725SANITIZER_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));
739  }
740  return ret;
741}
742
743SANITIZER_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));
754  }
755
756  return ret;
757}
758
759SANITIZER_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)));
772  }
773
774  return ret;
775}
776
777SANITIZER_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));
787  }
788  return ret;
789}
790
791SANITIZER_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);
800  }
801  return ret;
802}
803
804// Type of the trampoline function passed to the custom version of
805// dfsan_set_write_callback.
806typedef 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);
810
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.
813static struct {
814  write_trampoline_t write_callback_trampoline = NULL;
815  void *write_callback = NULL;
816} write_callback_info;
817
818SANITIZER_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;
826}
827
828SANITIZER_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);
837  }
838
839  *ret_label = 0;
840  return write(fd, buf, count);
841}
842}
843