1 //===-- dfsan_custom.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of DataFlowSanitizer.
10 //
11 // This file defines the custom functions listed in done_abilist.txt.
12 //===----------------------------------------------------------------------===//
13 
14 #include <arpa/inet.h>
15 #include <assert.h>
16 #include <ctype.h>
17 #include <dlfcn.h>
18 #include <link.h>
19 #include <poll.h>
20 #include <pthread.h>
21 #include <pwd.h>
22 #include <sched.h>
23 #include <signal.h>
24 #include <stdarg.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/epoll.h>
30 #include <sys/resource.h>
31 #include <sys/select.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <time.h>
37 #include <unistd.h>
38 
39 #include "dfsan/dfsan.h"
40 #include "dfsan/dfsan_chained_origin_depot.h"
41 #include "dfsan/dfsan_thread.h"
42 #include "sanitizer_common/sanitizer_common.h"
43 #include "sanitizer_common/sanitizer_internal_defs.h"
44 #include "sanitizer_common/sanitizer_linux.h"
45 #include "sanitizer_common/sanitizer_stackdepot.h"
46 
47 using namespace __dfsan;
48 
49 #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
50   do {                                                                         \
51     if (f)                                                                     \
52       f(__VA_ARGS__);                                                          \
53   } while (false)
54 #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
55 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
56 
57 // Async-safe, non-reentrant spin lock.
58 class SignalSpinLocker {
59  public:
60   SignalSpinLocker() {
61     sigset_t all_set;
62     sigfillset(&all_set);
63     pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
64     sigactions_mu.Lock();
65   }
66   ~SignalSpinLocker() {
67     sigactions_mu.Unlock();
68     pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
69   }
70 
71  private:
72   static StaticSpinMutex sigactions_mu;
73   sigset_t saved_thread_mask_;
74 
75   SignalSpinLocker(const SignalSpinLocker &) = delete;
76   SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
77 };
78 
79 StaticSpinMutex SignalSpinLocker::sigactions_mu;
80 
81 extern "C" {
82 SANITIZER_INTERFACE_ATTRIBUTE int
83 __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
84             dfsan_label buf_label, dfsan_label *ret_label) {
85   int ret = stat(path, buf);
86   if (ret == 0)
87     dfsan_set_label(0, buf, sizeof(struct stat));
88   *ret_label = 0;
89   return ret;
90 }
91 
92 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
93     const char *path, struct stat *buf, dfsan_label path_label,
94     dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
95     dfsan_origin buf_origin, dfsan_origin *ret_origin) {
96   int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
97   return ret;
98 }
99 
100 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
101                                                dfsan_label fd_label,
102                                                dfsan_label buf_label,
103                                                dfsan_label *ret_label) {
104   int ret = fstat(fd, buf);
105   if (ret == 0)
106     dfsan_set_label(0, buf, sizeof(struct stat));
107   *ret_label = 0;
108   return ret;
109 }
110 
111 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
112     int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
113     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
114     dfsan_origin *ret_origin) {
115   int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
116   return ret;
117 }
118 
119 static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
120                                      dfsan_label s_label, dfsan_label c_label,
121                                      dfsan_label *ret_label) {
122   char *match_pos = nullptr;
123   for (size_t i = 0;; ++i) {
124     if (s[i] == c || s[i] == 0) {
125       // If s[i] is the \0 at the end of the string, and \0 is not the
126       // character we are searching for, then return null.
127       *bytes_read = i + 1;
128       match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
129       break;
130     }
131   }
132   if (flags().strict_data_dependencies)
133     *ret_label = s_label;
134   else
135     *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
136                              dfsan_union(s_label, c_label));
137   return match_pos;
138 }
139 
140 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
141                                                   dfsan_label s_label,
142                                                   dfsan_label c_label,
143                                                   dfsan_label *ret_label) {
144   size_t bytes_read;
145   return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
146                                  ret_label);
147 }
148 
149 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
150     const char *s, int c, dfsan_label s_label, dfsan_label c_label,
151     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
152     dfsan_origin *ret_origin) {
153   size_t bytes_read;
154   char *r =
155       dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
156   if (flags().strict_data_dependencies) {
157     *ret_origin = s_origin;
158   } else if (*ret_label) {
159     dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
160     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
161   }
162   return r;
163 }
164 
165 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
166                                                    const char *accept,
167                                                    dfsan_label s_label,
168                                                    dfsan_label accept_label,
169                                                    dfsan_label *ret_label) {
170   const char *ret = strpbrk(s, accept);
171   if (flags().strict_data_dependencies) {
172     *ret_label = ret ? s_label : 0;
173   } else {
174     size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
175     *ret_label =
176         dfsan_union(dfsan_read_label(s, s_bytes_read),
177                     dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
178                                 dfsan_union(s_label, accept_label)));
179   }
180   return const_cast<char *>(ret);
181 }
182 
183 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
184     const char *s, const char *accept, dfsan_label s_label,
185     dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
186     dfsan_origin accept_origin, dfsan_origin *ret_origin) {
187   const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
188   if (flags().strict_data_dependencies) {
189     if (ret)
190       *ret_origin = s_origin;
191   } else {
192     if (*ret_label) {
193       size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
194       dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
195       if (o) {
196         *ret_origin = o;
197       } else {
198         o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
199         *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
200       }
201     }
202   }
203   return const_cast<char *>(ret);
204 }
205 
206 static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
207                              size_t *bytes_read) {
208   const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
209   for (size_t i = 0; i != n; ++i) {
210     if (cs1[i] != cs2[i]) {
211       *bytes_read = i + 1;
212       return cs1[i] - cs2[i];
213     }
214   }
215   *bytes_read = n;
216   return 0;
217 }
218 
219 static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
220                                           size_t pos) {
221   if (flags().strict_data_dependencies)
222     return 0;
223   return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
224 }
225 
226 static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
227                                     dfsan_label *ret_label,
228                                     dfsan_origin *ret_origin) {
229   *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
230   if (*ret_label == 0)
231     return;
232   dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
233   *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
234 }
235 
236 static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
237                                    dfsan_label *ret_label) {
238   size_t bytes_read;
239   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
240   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
241   return r;
242 }
243 
244 static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
245                                     dfsan_label *ret_label,
246                                     dfsan_origin *ret_origin) {
247   size_t bytes_read;
248   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
249   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
250   return r;
251 }
252 
253 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
254                               const void *s1, const void *s2, size_t n,
255                               dfsan_label s1_label, dfsan_label s2_label,
256                               dfsan_label n_label)
257 
258 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
259                               const void *s1, const void *s2, size_t n,
260                               dfsan_label s1_label, dfsan_label s2_label,
261                               dfsan_label n_label, dfsan_origin s1_origin,
262                               dfsan_origin s2_origin, dfsan_origin n_origin)
263 
264 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
265                                                 size_t n, dfsan_label s1_label,
266                                                 dfsan_label s2_label,
267                                                 dfsan_label n_label,
268                                                 dfsan_label *ret_label) {
269   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
270                              s1_label, s2_label, n_label);
271   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
272 }
273 
274 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
275     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
276     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
277     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
278     dfsan_origin *ret_origin) {
279   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
280                              s2, n, s1_label, s2_label, n_label, s1_origin,
281                              s2_origin, n_origin);
282   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
283 }
284 
285 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
286                                               size_t n, dfsan_label s1_label,
287                                               dfsan_label s2_label,
288                                               dfsan_label n_label,
289                                               dfsan_label *ret_label) {
290   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
291 }
292 
293 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
294     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
295     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
296     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
297     dfsan_origin *ret_origin) {
298   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
299 }
300 
301 // When n == 0, compare strings without byte limit.
302 // When n > 0, compare the first (at most) n bytes of s1 and s2.
303 static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
304                          size_t *bytes_read) {
305   for (size_t i = 0;; ++i) {
306     if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
307       *bytes_read = i + 1;
308       return s1[i] - s2[i];
309     }
310   }
311 }
312 
313 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
314                               const char *s1, const char *s2,
315                               dfsan_label s1_label, dfsan_label s2_label)
316 
317 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
318                               const char *s1, const char *s2,
319                               dfsan_label s1_label, dfsan_label s2_label,
320                               dfsan_origin s1_origin, dfsan_origin s2_origin)
321 
322 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
323                                                 dfsan_label s1_label,
324                                                 dfsan_label s2_label,
325                                                 dfsan_label *ret_label) {
326   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
327                              s1_label, s2_label);
328   size_t bytes_read;
329   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
330   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
331   return r;
332 }
333 
334 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
335     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
336     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
337     dfsan_origin *ret_origin) {
338   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
339                              s2, s1_label, s2_label, s1_origin, s2_origin);
340   size_t bytes_read;
341   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
342   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
343   return r;
344 }
345 
346 // When n == 0, compare strings without byte limit.
347 // When n > 0, compare the first (at most) n bytes of s1 and s2.
348 static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
349                              size_t *bytes_read) {
350   for (size_t i = 0;; ++i) {
351     char s1_lower = tolower(s1[i]);
352     char s2_lower = tolower(s2[i]);
353 
354     if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
355         (n > 0 && i == n - 1)) {
356       *bytes_read = i + 1;
357       return s1_lower - s2_lower;
358     }
359   }
360 }
361 
362 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
363                                                     const char *s2,
364                                                     dfsan_label s1_label,
365                                                     dfsan_label s2_label,
366                                                     dfsan_label *ret_label) {
367   size_t bytes_read;
368   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
369   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
370   return r;
371 }
372 
373 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
374     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
375     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
376     dfsan_origin *ret_origin) {
377   size_t bytes_read;
378   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
379   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
380   return r;
381 }
382 
383 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
384                               const char *s1, const char *s2, size_t n,
385                               dfsan_label s1_label, dfsan_label s2_label,
386                               dfsan_label n_label)
387 
388 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
389                               const char *s1, const char *s2, size_t n,
390                               dfsan_label s1_label, dfsan_label s2_label,
391                               dfsan_label n_label, dfsan_origin s1_origin,
392                               dfsan_origin s2_origin, dfsan_origin n_origin)
393 
394 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
395                                                  size_t n, dfsan_label s1_label,
396                                                  dfsan_label s2_label,
397                                                  dfsan_label n_label,
398                                                  dfsan_label *ret_label) {
399   if (n == 0) {
400     *ret_label = 0;
401     return 0;
402   }
403 
404   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
405                              n, s1_label, s2_label, n_label);
406 
407   size_t bytes_read;
408   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
409   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
410   return r;
411 }
412 
413 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
414     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
415     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
416     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
417     dfsan_origin *ret_origin) {
418   if (n == 0) {
419     *ret_label = 0;
420     return 0;
421   }
422 
423   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
424                              s1, s2, n, s1_label, s2_label, n_label, s1_origin,
425                              s2_origin, n_origin);
426 
427   size_t bytes_read;
428   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
429   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
430   return r;
431 }
432 
433 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
434     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
435     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
436   if (n == 0) {
437     *ret_label = 0;
438     return 0;
439   }
440 
441   size_t bytes_read;
442   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
443   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
444   return r;
445 }
446 
447 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
448     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
449     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
450     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
451     dfsan_origin *ret_origin) {
452   if (n == 0) {
453     *ret_label = 0;
454     return 0;
455   }
456 
457   size_t bytes_read;
458   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
459   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
460   return r;
461 }
462 
463 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_calloc(size_t nmemb, size_t size,
464                                                   dfsan_label nmemb_label,
465                                                   dfsan_label size_label,
466                                                   dfsan_label *ret_label) {
467   void *p = calloc(nmemb, size);
468   dfsan_set_label(0, p, nmemb * size);
469   *ret_label = 0;
470   return p;
471 }
472 
473 SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_calloc(
474     size_t nmemb, size_t size, dfsan_label nmemb_label, dfsan_label size_label,
475     dfsan_label *ret_label, dfsan_origin nmemb_origin, dfsan_origin size_origin,
476     dfsan_origin *ret_origin) {
477   void *p = __dfsw_calloc(nmemb, size, nmemb_label, size_label, ret_label);
478   *ret_origin = 0;
479   return p;
480 }
481 
482 SANITIZER_INTERFACE_ATTRIBUTE size_t
483 __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
484   size_t ret = strlen(s);
485   if (flags().strict_data_dependencies) {
486     *ret_label = 0;
487   } else {
488     *ret_label = dfsan_read_label(s, ret + 1);
489   }
490   return ret;
491 }
492 
493 SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
494                                                    dfsan_label s_label,
495                                                    dfsan_label *ret_label,
496                                                    dfsan_origin s_origin,
497                                                    dfsan_origin *ret_origin) {
498   size_t ret = __dfsw_strlen(s, s_label, ret_label);
499   if (!flags().strict_data_dependencies)
500     *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
501   return ret;
502 }
503 
504 static void *dfsan_memmove(void *dest, const void *src, size_t n) {
505   dfsan_label *sdest = shadow_for(dest);
506   const dfsan_label *ssrc = shadow_for(src);
507   internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
508   return internal_memmove(dest, src, n);
509 }
510 
511 static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
512   dfsan_mem_origin_transfer(dest, src, n);
513   return dfsan_memmove(dest, src, n);
514 }
515 
516 static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
517   dfsan_label *sdest = shadow_for(dest);
518   const dfsan_label *ssrc = shadow_for(src);
519   internal_memcpy((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
520   return internal_memcpy(dest, src, n);
521 }
522 
523 static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
524   dfsan_mem_origin_transfer(dest, src, n);
525   return dfsan_memcpy(dest, src, n);
526 }
527 
528 static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
529   internal_memset(s, c, n);
530   dfsan_set_label(c_label, s, n);
531 }
532 
533 static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
534                                      dfsan_origin c_origin, size_t n) {
535   internal_memset(s, c, n);
536   dfsan_set_label_origin(c_label, c_origin, s, n);
537 }
538 
539 SANITIZER_INTERFACE_ATTRIBUTE
540 void *__dfsw_memcpy(void *dest, const void *src, size_t n,
541                     dfsan_label dest_label, dfsan_label src_label,
542                     dfsan_label n_label, dfsan_label *ret_label) {
543   *ret_label = dest_label;
544   return dfsan_memcpy(dest, src, n);
545 }
546 
547 SANITIZER_INTERFACE_ATTRIBUTE
548 void *__dfso_memcpy(void *dest, const void *src, size_t n,
549                     dfsan_label dest_label, dfsan_label src_label,
550                     dfsan_label n_label, dfsan_label *ret_label,
551                     dfsan_origin dest_origin, dfsan_origin src_origin,
552                     dfsan_origin n_origin, dfsan_origin *ret_origin) {
553   *ret_label = dest_label;
554   *ret_origin = dest_origin;
555   return dfsan_memcpy_with_origin(dest, src, n);
556 }
557 
558 SANITIZER_INTERFACE_ATTRIBUTE
559 void *__dfsw_memmove(void *dest, const void *src, size_t n,
560                      dfsan_label dest_label, dfsan_label src_label,
561                      dfsan_label n_label, dfsan_label *ret_label) {
562   *ret_label = dest_label;
563   return dfsan_memmove(dest, src, n);
564 }
565 
566 SANITIZER_INTERFACE_ATTRIBUTE
567 void *__dfso_memmove(void *dest, const void *src, size_t n,
568                      dfsan_label dest_label, dfsan_label src_label,
569                      dfsan_label n_label, dfsan_label *ret_label,
570                      dfsan_origin dest_origin, dfsan_origin src_origin,
571                      dfsan_origin n_origin, dfsan_origin *ret_origin) {
572   *ret_label = dest_label;
573   *ret_origin = dest_origin;
574   return dfsan_memmove_with_origin(dest, src, n);
575 }
576 
577 SANITIZER_INTERFACE_ATTRIBUTE
578 void *__dfsw_memset(void *s, int c, size_t n,
579                     dfsan_label s_label, dfsan_label c_label,
580                     dfsan_label n_label, dfsan_label *ret_label) {
581   dfsan_memset(s, c, c_label, n);
582   *ret_label = s_label;
583   return s;
584 }
585 
586 SANITIZER_INTERFACE_ATTRIBUTE
587 void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
588                     dfsan_label c_label, dfsan_label n_label,
589                     dfsan_label *ret_label, dfsan_origin s_origin,
590                     dfsan_origin c_origin, dfsan_origin n_origin,
591                     dfsan_origin *ret_origin) {
592   dfsan_memset_with_origin(s, c, c_label, c_origin, n);
593   *ret_label = s_label;
594   *ret_origin = s_origin;
595   return s;
596 }
597 
598 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
599                                                   dfsan_label dest_label,
600                                                   dfsan_label src_label,
601                                                   dfsan_label *ret_label) {
602   size_t dest_len = strlen(dest);
603   char *ret = strcat(dest, src);  // NOLINT
604   dfsan_label *sdest = shadow_for(dest + dest_len);
605   const dfsan_label *ssrc = shadow_for(src);
606   internal_memcpy((void *)sdest, (const void *)ssrc,
607                   strlen(src) * sizeof(dfsan_label));
608   *ret_label = dest_label;
609   return ret;
610 }
611 
612 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
613     char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
614     dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
615     dfsan_origin *ret_origin) {
616   size_t dest_len = strlen(dest);
617   char *ret = strcat(dest, src);  // NOLINT
618   dfsan_label *sdest = shadow_for(dest + dest_len);
619   const dfsan_label *ssrc = shadow_for(src);
620   size_t src_len = strlen(src);
621   dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
622   internal_memcpy((void *)sdest, (const void *)ssrc,
623                   src_len * sizeof(dfsan_label));
624   *ret_label = dest_label;
625   *ret_origin = dest_origin;
626   return ret;
627 }
628 
629 SANITIZER_INTERFACE_ATTRIBUTE char *
630 __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
631   size_t len = strlen(s);
632   void *p = malloc(len+1);
633   dfsan_memcpy(p, s, len+1);
634   *ret_label = 0;
635   return static_cast<char *>(p);
636 }
637 
638 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
639                                                   dfsan_label s_label,
640                                                   dfsan_label *ret_label,
641                                                   dfsan_origin s_origin,
642                                                   dfsan_origin *ret_origin) {
643   size_t len = strlen(s);
644   void *p = malloc(len + 1);
645   dfsan_memcpy_with_origin(p, s, len + 1);
646   *ret_label = 0;
647   *ret_origin = 0;
648   return static_cast<char *>(p);
649 }
650 
651 SANITIZER_INTERFACE_ATTRIBUTE char *
652 __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
653                dfsan_label s2_label, dfsan_label n_label,
654                dfsan_label *ret_label) {
655   size_t len = strlen(s2);
656   if (len < n) {
657     dfsan_memcpy(s1, s2, len+1);
658     dfsan_memset(s1+len+1, 0, 0, n-len-1);
659   } else {
660     dfsan_memcpy(s1, s2, n);
661   }
662 
663   *ret_label = s1_label;
664   return s1;
665 }
666 
667 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
668     char *s1, const char *s2, size_t n, dfsan_label s1_label,
669     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
670     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
671     dfsan_origin *ret_origin) {
672   size_t len = strlen(s2);
673   if (len < n) {
674     dfsan_memcpy_with_origin(s1, s2, len + 1);
675     dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
676   } else {
677     dfsan_memcpy_with_origin(s1, s2, n);
678   }
679 
680   *ret_label = s1_label;
681   *ret_origin = s1_origin;
682   return s1;
683 }
684 
685 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
686 __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
687              dfsan_label fd_label, dfsan_label buf_label,
688              dfsan_label count_label, dfsan_label offset_label,
689              dfsan_label *ret_label) {
690   ssize_t ret = pread(fd, buf, count, offset);
691   if (ret > 0)
692     dfsan_set_label(0, buf, ret);
693   *ret_label = 0;
694   return ret;
695 }
696 
697 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
698     int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
699     dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
700     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
701     dfsan_origin count_origin, dfsan_label offset_origin,
702     dfsan_origin *ret_origin) {
703   ssize_t ret = __dfsw_pread(fd, buf, count, offset, fd_label, buf_label,
704                              count_label, offset_label, ret_label);
705   return ret;
706 }
707 
708 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
709 __dfsw_read(int fd, void *buf, size_t count,
710              dfsan_label fd_label, dfsan_label buf_label,
711              dfsan_label count_label,
712              dfsan_label *ret_label) {
713   ssize_t ret = read(fd, buf, count);
714   if (ret > 0)
715     dfsan_set_label(0, buf, ret);
716   *ret_label = 0;
717   return ret;
718 }
719 
720 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
721     int fd, void *buf, size_t count, dfsan_label fd_label,
722     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
723     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
724     dfsan_origin *ret_origin) {
725   ssize_t ret =
726       __dfsw_read(fd, buf, count, fd_label, buf_label, count_label, ret_label);
727   return ret;
728 }
729 
730 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
731                                                        struct timespec *tp,
732                                                        dfsan_label clk_id_label,
733                                                        dfsan_label tp_label,
734                                                        dfsan_label *ret_label) {
735   int ret = clock_gettime(clk_id, tp);
736   if (ret == 0)
737     dfsan_set_label(0, tp, sizeof(struct timespec));
738   *ret_label = 0;
739   return ret;
740 }
741 
742 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
743     clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
744     dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
745     dfsan_origin tp_origin, dfsan_origin *ret_origin) {
746   int ret = __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
747   return ret;
748 }
749 
750 static void dfsan_set_zero_label(const void *ptr, uptr size) {
751   dfsan_set_label(0, const_cast<void *>(ptr), size);
752 }
753 
754 // dlopen() ultimately calls mmap() down inside the loader, which generally
755 // doesn't participate in dynamic symbol resolution.  Therefore we won't
756 // intercept its calls to mmap, and we have to hook it here.
757 SANITIZER_INTERFACE_ATTRIBUTE void *
758 __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
759               dfsan_label flag_label, dfsan_label *ret_label) {
760   void *handle = dlopen(filename, flag);
761   link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
762   if (map)
763     ForEachMappedRegion(map, dfsan_set_zero_label);
764   *ret_label = 0;
765   return handle;
766 }
767 
768 SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
769     const char *filename, int flag, dfsan_label filename_label,
770     dfsan_label flag_label, dfsan_label *ret_label,
771     dfsan_origin filename_origin, dfsan_origin flag_origin,
772     dfsan_origin *ret_origin) {
773   void *handle =
774       __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
775   return handle;
776 }
777 
778 static void *DFsanThreadStartFunc(void *arg) {
779   DFsanThread *t = (DFsanThread *)arg;
780   SetCurrentThread(t);
781   return t->ThreadStart();
782 }
783 
784 static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
785                                 void *start_routine_trampoline,
786                                 void *start_routine, void *arg,
787                                 dfsan_label *ret_label,
788                                 bool track_origins = false) {
789   pthread_attr_t myattr;
790   if (!attr) {
791     pthread_attr_init(&myattr);
792     attr = &myattr;
793   }
794 
795   // Ensure that the thread stack is large enough to hold all TLS data.
796   AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
797 
798   DFsanThread *t =
799       DFsanThread::Create(start_routine_trampoline,
800                           (thread_callback_t)start_routine, arg, track_origins);
801   int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
802 
803   if (attr == &myattr)
804     pthread_attr_destroy(&myattr);
805   *ret_label = 0;
806   return res;
807 }
808 
809 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
810     pthread_t *thread, const pthread_attr_t *attr,
811     void *(*start_routine_trampoline)(void *, void *, dfsan_label,
812                                       dfsan_label *),
813     void *start_routine, void *arg, dfsan_label thread_label,
814     dfsan_label attr_label, dfsan_label start_routine_label,
815     dfsan_label arg_label, dfsan_label *ret_label) {
816   return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
817                               start_routine, arg, ret_label);
818 }
819 
820 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
821     pthread_t *thread, const pthread_attr_t *attr,
822     void *(*start_routine_trampoline)(void *, void *, dfsan_label,
823                                       dfsan_label *, dfsan_origin,
824                                       dfsan_origin *),
825     void *start_routine, void *arg, dfsan_label thread_label,
826     dfsan_label attr_label, dfsan_label start_routine_label,
827     dfsan_label arg_label, dfsan_label *ret_label, dfsan_origin thread_origin,
828     dfsan_origin attr_origin, dfsan_origin start_routine_origin,
829     dfsan_origin arg_origin, dfsan_origin *ret_origin) {
830   return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
831                               start_routine, arg, ret_label, true);
832 }
833 
834 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
835                                                       void **retval,
836                                                       dfsan_label thread_label,
837                                                       dfsan_label retval_label,
838                                                       dfsan_label *ret_label) {
839   int ret = pthread_join(thread, retval);
840   if (ret == 0 && retval)
841     dfsan_set_label(0, retval, sizeof(*retval));
842   *ret_label = 0;
843   return ret;
844 }
845 
846 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
847     pthread_t thread, void **retval, dfsan_label thread_label,
848     dfsan_label retval_label, dfsan_label *ret_label,
849     dfsan_origin thread_origin, dfsan_origin retval_origin,
850     dfsan_origin *ret_origin) {
851   return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
852                              ret_label);
853 }
854 
855 struct dl_iterate_phdr_info {
856   int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
857                              size_t size, void *data, dfsan_label info_label,
858                              dfsan_label size_label, dfsan_label data_label,
859                              dfsan_label *ret_label);
860   void *callback;
861   void *data;
862 };
863 
864 struct dl_iterate_phdr_origin_info {
865   int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
866                              size_t size, void *data, dfsan_label info_label,
867                              dfsan_label size_label, dfsan_label data_label,
868                              dfsan_label *ret_label, dfsan_origin info_origin,
869                              dfsan_origin size_origin, dfsan_origin data_origin,
870                              dfsan_origin *ret_origin);
871   void *callback;
872   void *data;
873 };
874 
875 int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
876   dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
877   dfsan_set_label(0, *info);
878   dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
879                   strlen(info->dlpi_name) + 1);
880   dfsan_set_label(
881       0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
882       sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
883   dfsan_label ret_label;
884   return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
885                                    0, &ret_label);
886 }
887 
888 int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size,
889                               void *data) {
890   dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data;
891   dfsan_set_label(0, *info);
892   dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
893                   strlen(info->dlpi_name) + 1);
894   dfsan_set_label(
895       0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
896       sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
897   dfsan_label ret_label;
898   dfsan_origin ret_origin;
899   return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
900                                    0, &ret_label, 0, 0, 0, &ret_origin);
901 }
902 
903 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
904     int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
905                                size_t size, void *data, dfsan_label info_label,
906                                dfsan_label size_label, dfsan_label data_label,
907                                dfsan_label *ret_label),
908     void *callback, void *data, dfsan_label callback_label,
909     dfsan_label data_label, dfsan_label *ret_label) {
910   dl_iterate_phdr_info dipi = { callback_trampoline, callback, data };
911   *ret_label = 0;
912   return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
913 }
914 
915 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
916     int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
917                                size_t size, void *data, dfsan_label info_label,
918                                dfsan_label size_label, dfsan_label data_label,
919                                dfsan_label *ret_label, dfsan_origin info_origin,
920                                dfsan_origin size_origin,
921                                dfsan_origin data_origin,
922                                dfsan_origin *ret_origin),
923     void *callback, void *data, dfsan_label callback_label,
924     dfsan_label data_label, dfsan_label *ret_label,
925     dfsan_origin callback_origin, dfsan_origin data_origin,
926     dfsan_origin *ret_origin) {
927   dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data};
928   *ret_label = 0;
929   return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi);
930 }
931 
932 // This function is only available for glibc 2.27 or newer.  Mark it weak so
933 // linking succeeds with older glibcs.
934 SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
935                                                       size_t *alignp);
936 
937 SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
938     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
939     dfsan_label alignp_label) {
940   assert(_dl_get_tls_static_info);
941   _dl_get_tls_static_info(sizep, alignp);
942   dfsan_set_label(0, sizep, sizeof(*sizep));
943   dfsan_set_label(0, alignp, sizeof(*alignp));
944 }
945 
946 SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
947     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
948     dfsan_label alignp_label, dfsan_origin sizep_origin,
949     dfsan_origin alignp_origin) {
950   __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
951 }
952 
953 SANITIZER_INTERFACE_ATTRIBUTE
954 char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
955                      dfsan_label buf_label, dfsan_label *ret_label) {
956   char *ret = ctime_r(timep, buf);
957   if (ret) {
958     dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
959                     strlen(buf) + 1);
960     *ret_label = buf_label;
961   } else {
962     *ret_label = 0;
963   }
964   return ret;
965 }
966 
967 SANITIZER_INTERFACE_ATTRIBUTE
968 char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
969                    dfsan_label size_label, dfsan_label stream_label,
970                    dfsan_label *ret_label) {
971   char *ret = fgets(s, size, stream);
972   if (ret) {
973     dfsan_set_label(0, ret, strlen(ret) + 1);
974     *ret_label = s_label;
975   } else {
976     *ret_label = 0;
977   }
978   return ret;
979 }
980 
981 SANITIZER_INTERFACE_ATTRIBUTE
982 char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
983                     dfsan_label size_label, dfsan_label *ret_label) {
984   char *ret = getcwd(buf, size);
985   if (ret) {
986     dfsan_set_label(0, ret, strlen(ret) + 1);
987     *ret_label = buf_label;
988   } else {
989     *ret_label = 0;
990   }
991   return ret;
992 }
993 
994 SANITIZER_INTERFACE_ATTRIBUTE
995 char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
996   char *ret = get_current_dir_name();
997   if (ret) {
998     dfsan_set_label(0, ret, strlen(ret) + 1);
999   }
1000   *ret_label = 0;
1001   return ret;
1002 }
1003 
1004 SANITIZER_INTERFACE_ATTRIBUTE
1005 int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
1006                        dfsan_label len_label, dfsan_label *ret_label) {
1007   int ret = gethostname(name, len);
1008   if (ret == 0) {
1009     dfsan_set_label(0, name, strlen(name) + 1);
1010   }
1011   *ret_label = 0;
1012   return ret;
1013 }
1014 
1015 SANITIZER_INTERFACE_ATTRIBUTE
1016 int __dfsw_getrlimit(int resource, struct rlimit *rlim,
1017                      dfsan_label resource_label, dfsan_label rlim_label,
1018                      dfsan_label *ret_label) {
1019   int ret = getrlimit(resource, rlim);
1020   if (ret == 0) {
1021     dfsan_set_label(0, rlim, sizeof(struct rlimit));
1022   }
1023   *ret_label = 0;
1024   return ret;
1025 }
1026 
1027 SANITIZER_INTERFACE_ATTRIBUTE
1028 int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1029                      dfsan_label usage_label, dfsan_label *ret_label) {
1030   int ret = getrusage(who, usage);
1031   if (ret == 0) {
1032     dfsan_set_label(0, usage, sizeof(struct rusage));
1033   }
1034   *ret_label = 0;
1035   return ret;
1036 }
1037 
1038 SANITIZER_INTERFACE_ATTRIBUTE
1039 char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
1040                     dfsan_label src_label, dfsan_label *ret_label) {
1041   char *ret = strcpy(dest, src);  // NOLINT
1042   if (ret) {
1043     internal_memcpy(shadow_for(dest), shadow_for(src),
1044                     sizeof(dfsan_label) * (strlen(src) + 1));
1045   }
1046   *ret_label = dst_label;
1047   return ret;
1048 }
1049 
1050 SANITIZER_INTERFACE_ATTRIBUTE
1051 long int __dfsw_strtol(const char *nptr, char **endptr, int base,
1052                        dfsan_label nptr_label, dfsan_label endptr_label,
1053                        dfsan_label base_label, dfsan_label *ret_label) {
1054   char *tmp_endptr;
1055   long int ret = strtol(nptr, &tmp_endptr, base);
1056   if (endptr) {
1057     *endptr = tmp_endptr;
1058   }
1059   if (tmp_endptr > nptr) {
1060     // If *tmp_endptr is '\0' include its label as well.
1061     *ret_label = dfsan_union(
1062         base_label,
1063         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
1064   } else {
1065     *ret_label = 0;
1066   }
1067   return ret;
1068 }
1069 
1070 SANITIZER_INTERFACE_ATTRIBUTE
1071 double __dfsw_strtod(const char *nptr, char **endptr,
1072                        dfsan_label nptr_label, dfsan_label endptr_label,
1073                        dfsan_label *ret_label) {
1074   char *tmp_endptr;
1075   double ret = strtod(nptr, &tmp_endptr);
1076   if (endptr) {
1077     *endptr = tmp_endptr;
1078   }
1079   if (tmp_endptr > nptr) {
1080     // If *tmp_endptr is '\0' include its label as well.
1081     *ret_label = dfsan_read_label(
1082         nptr,
1083         tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1084   } else {
1085     *ret_label = 0;
1086   }
1087   return ret;
1088 }
1089 
1090 SANITIZER_INTERFACE_ATTRIBUTE
1091 long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
1092                        dfsan_label nptr_label, dfsan_label endptr_label,
1093                        dfsan_label base_label, dfsan_label *ret_label) {
1094   char *tmp_endptr;
1095   long long int ret = strtoll(nptr, &tmp_endptr, base);
1096   if (endptr) {
1097     *endptr = tmp_endptr;
1098   }
1099   if (tmp_endptr > nptr) {
1100     // If *tmp_endptr is '\0' include its label as well.
1101     *ret_label = dfsan_union(
1102         base_label,
1103         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
1104   } else {
1105     *ret_label = 0;
1106   }
1107   return ret;
1108 }
1109 
1110 SANITIZER_INTERFACE_ATTRIBUTE
1111 unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
1112                        dfsan_label nptr_label, dfsan_label endptr_label,
1113                        dfsan_label base_label, dfsan_label *ret_label) {
1114   char *tmp_endptr;
1115   unsigned long int ret = strtoul(nptr, &tmp_endptr, base);
1116   if (endptr) {
1117     *endptr = tmp_endptr;
1118   }
1119   if (tmp_endptr > nptr) {
1120     // If *tmp_endptr is '\0' include its label as well.
1121     *ret_label = dfsan_union(
1122         base_label,
1123         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
1124   } else {
1125     *ret_label = 0;
1126   }
1127   return ret;
1128 }
1129 
1130 SANITIZER_INTERFACE_ATTRIBUTE
1131 long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
1132                                        int base, dfsan_label nptr_label,
1133                                        dfsan_label endptr_label,
1134                                        dfsan_label base_label,
1135                                        dfsan_label *ret_label) {
1136   char *tmp_endptr;
1137   long long unsigned int ret = strtoull(nptr, &tmp_endptr, base);
1138   if (endptr) {
1139     *endptr = tmp_endptr;
1140   }
1141   if (tmp_endptr > nptr) {
1142     // If *tmp_endptr is '\0' include its label as well.
1143     *ret_label = dfsan_union(
1144         base_label,
1145         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
1146   } else {
1147     *ret_label = 0;
1148   }
1149   return ret;
1150 }
1151 
1152 SANITIZER_INTERFACE_ATTRIBUTE
1153 time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
1154   time_t ret = time(t);
1155   if (ret != (time_t) -1 && t) {
1156     dfsan_set_label(0, t, sizeof(time_t));
1157   }
1158   *ret_label = 0;
1159   return ret;
1160 }
1161 
1162 SANITIZER_INTERFACE_ATTRIBUTE
1163 int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1164                      dfsan_label src_label, dfsan_label dst_label,
1165                      dfsan_label *ret_label) {
1166   int ret = inet_pton(af, src, dst);
1167   if (ret == 1) {
1168     dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
1169                     af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1170   }
1171   *ret_label = 0;
1172   return ret;
1173 }
1174 
1175 SANITIZER_INTERFACE_ATTRIBUTE
1176 struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
1177                               dfsan_label timep_label, dfsan_label result_label,
1178                               dfsan_label *ret_label) {
1179   struct tm *ret = localtime_r(timep, result);
1180   if (ret) {
1181     dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
1182                     sizeof(struct tm));
1183     *ret_label = result_label;
1184   } else {
1185     *ret_label = 0;
1186   }
1187   return ret;
1188 }
1189 
1190 SANITIZER_INTERFACE_ATTRIBUTE
1191 int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
1192                       char *buf, size_t buflen, struct passwd **result,
1193                       dfsan_label uid_label, dfsan_label pwd_label,
1194                       dfsan_label buf_label, dfsan_label buflen_label,
1195                       dfsan_label result_label, dfsan_label *ret_label) {
1196   // Store the data in pwd, the strings referenced from pwd in buf, and the
1197   // address of pwd in *result.  On failure, NULL is stored in *result.
1198   int ret = getpwuid_r(uid, pwd, buf, buflen, result);
1199   if (ret == 0) {
1200     dfsan_set_label(0, pwd, sizeof(struct passwd));
1201     dfsan_set_label(0, buf, strlen(buf) + 1);
1202   }
1203   *ret_label = 0;
1204   dfsan_set_label(0, result, sizeof(struct passwd*));
1205   return ret;
1206 }
1207 
1208 SANITIZER_INTERFACE_ATTRIBUTE
1209 int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1210                       int timeout, dfsan_label epfd_label,
1211                       dfsan_label events_label, dfsan_label maxevents_label,
1212                       dfsan_label timeout_label, dfsan_label *ret_label) {
1213   int ret = epoll_wait(epfd, events, maxevents, timeout);
1214   if (ret > 0)
1215     dfsan_set_label(0, events, ret * sizeof(*events));
1216   *ret_label = 0;
1217   return ret;
1218 }
1219 
1220 SANITIZER_INTERFACE_ATTRIBUTE
1221 int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1222                 dfsan_label dfs_label, dfsan_label nfds_label,
1223                 dfsan_label timeout_label, dfsan_label *ret_label) {
1224   int ret = poll(fds, nfds, timeout);
1225   if (ret >= 0) {
1226     for (; nfds > 0; --nfds) {
1227       dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
1228     }
1229   }
1230   *ret_label = 0;
1231   return ret;
1232 }
1233 
1234 SANITIZER_INTERFACE_ATTRIBUTE
1235 int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
1236                   fd_set *exceptfds, struct timeval *timeout,
1237                   dfsan_label nfds_label, dfsan_label readfds_label,
1238                   dfsan_label writefds_label, dfsan_label exceptfds_label,
1239                   dfsan_label timeout_label, dfsan_label *ret_label) {
1240   int ret = select(nfds, readfds, writefds, exceptfds, timeout);
1241   // Clear everything (also on error) since their content is either set or
1242   // undefined.
1243   if (readfds) {
1244     dfsan_set_label(0, readfds, sizeof(fd_set));
1245   }
1246   if (writefds) {
1247     dfsan_set_label(0, writefds, sizeof(fd_set));
1248   }
1249   if (exceptfds) {
1250     dfsan_set_label(0, exceptfds, sizeof(fd_set));
1251   }
1252   dfsan_set_label(0, timeout, sizeof(struct timeval));
1253   *ret_label = 0;
1254   return ret;
1255 }
1256 
1257 SANITIZER_INTERFACE_ATTRIBUTE
1258 int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1259                              dfsan_label pid_label,
1260                              dfsan_label cpusetsize_label,
1261                              dfsan_label mask_label, dfsan_label *ret_label) {
1262   int ret = sched_getaffinity(pid, cpusetsize, mask);
1263   if (ret == 0) {
1264     dfsan_set_label(0, mask, cpusetsize);
1265   }
1266   *ret_label = 0;
1267   return ret;
1268 }
1269 
1270 SANITIZER_INTERFACE_ATTRIBUTE
1271 int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
1272                        dfsan_label *ret_label) {
1273   int ret = sigemptyset(set);
1274   dfsan_set_label(0, set, sizeof(sigset_t));
1275   return ret;
1276 }
1277 
1278 SANITIZER_INTERFACE_ATTRIBUTE
1279 int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
1280                        dfsan_label *ret_label, dfsan_origin set_origin,
1281                        dfsan_origin *ret_origin) {
1282   return __dfsw_sigemptyset(set, set_label, ret_label);
1283 }
1284 
1285 class SignalHandlerScope {
1286  public:
1287   SignalHandlerScope() {
1288     if (DFsanThread *t = GetCurrentThread())
1289       t->EnterSignalHandler();
1290   }
1291   ~SignalHandlerScope() {
1292     if (DFsanThread *t = GetCurrentThread())
1293       t->LeaveSignalHandler();
1294   }
1295 };
1296 
1297 // Clear DFSan runtime TLS state at the end of a scope.
1298 //
1299 // Implementation must be async-signal-safe and use small data size, because
1300 // instances of this class may live on the signal handler stack.
1301 //
1302 // DFSan uses TLS to pass metadata of arguments and return values. When an
1303 // instrumented function accesses the TLS, if a signal callback happens, and the
1304 // callback calls other instrumented functions with updating the same TLS, the
1305 // TLS is in an inconsistent state after the callback ends. This may cause
1306 // either under-tainting or over-tainting.
1307 //
1308 // The current implementation simply resets TLS at restore. This prevents from
1309 // over-tainting. Although under-tainting may still happen, a taint flow can be
1310 // found eventually if we run a DFSan-instrumented program multiple times. The
1311 // alternative option is saving the entire TLS. However the TLS storage takes
1312 // 2k bytes, and signal calls could be nested. So it does not seem worth.
1313 class ScopedClearThreadLocalState {
1314  public:
1315   ScopedClearThreadLocalState() {}
1316   ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1317 };
1318 
1319 // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1320 const int kMaxSignals = 1024;
1321 static atomic_uintptr_t sigactions[kMaxSignals];
1322 
1323 static void SignalHandler(int signo) {
1324   SignalHandlerScope signal_handler_scope;
1325   ScopedClearThreadLocalState scoped_clear_tls;
1326 
1327   // Clear shadows for all inputs provided by system. This is why DFSan
1328   // instrumentation generates a trampoline function to each function pointer,
1329   // and uses the trampoline to clear shadows. However sigaction does not use
1330   // a function pointer directly, so we have to do this manually.
1331   dfsan_clear_arg_tls(0, sizeof(dfsan_label));
1332 
1333   typedef void (*signal_cb)(int x);
1334   signal_cb cb =
1335       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1336   cb(signo);
1337 }
1338 
1339 static void SignalAction(int signo, siginfo_t *si, void *uc) {
1340   SignalHandlerScope signal_handler_scope;
1341   ScopedClearThreadLocalState scoped_clear_tls;
1342 
1343   // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1344   dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
1345   dfsan_set_label(0, si, sizeof(*si));
1346   dfsan_set_label(0, uc, sizeof(ucontext_t));
1347 
1348   typedef void (*sigaction_cb)(int, siginfo_t *, void *);
1349   sigaction_cb cb =
1350       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1351   cb(signo, si, uc);
1352 }
1353 
1354 SANITIZER_INTERFACE_ATTRIBUTE
1355 int __dfsw_sigaction(int signum, const struct sigaction *act,
1356                      struct sigaction *oldact, dfsan_label signum_label,
1357                      dfsan_label act_label, dfsan_label oldact_label,
1358                      dfsan_label *ret_label) {
1359   CHECK_LT(signum, kMaxSignals);
1360   SignalSpinLocker lock;
1361   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1362   struct sigaction new_act;
1363   struct sigaction *pnew_act = act ? &new_act : nullptr;
1364   if (act) {
1365     internal_memcpy(pnew_act, act, sizeof(struct sigaction));
1366     if (pnew_act->sa_flags & SA_SIGINFO) {
1367       uptr cb = (uptr)(pnew_act->sa_sigaction);
1368       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1369         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1370         pnew_act->sa_sigaction = SignalAction;
1371       }
1372     } else {
1373       uptr cb = (uptr)(pnew_act->sa_handler);
1374       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1375         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1376         pnew_act->sa_handler = SignalHandler;
1377       }
1378     }
1379   }
1380 
1381   int ret = sigaction(signum, pnew_act, oldact);
1382 
1383   if (ret == 0 && oldact) {
1384     if (oldact->sa_flags & SA_SIGINFO) {
1385       if (oldact->sa_sigaction == SignalAction)
1386         oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
1387     } else {
1388       if (oldact->sa_handler == SignalHandler)
1389         oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
1390     }
1391   }
1392 
1393   if (oldact) {
1394     dfsan_set_label(0, oldact, sizeof(struct sigaction));
1395   }
1396   *ret_label = 0;
1397   return ret;
1398 }
1399 
1400 SANITIZER_INTERFACE_ATTRIBUTE
1401 int __dfso_sigaction(int signum, const struct sigaction *act,
1402                      struct sigaction *oldact, dfsan_label signum_label,
1403                      dfsan_label act_label, dfsan_label oldact_label,
1404                      dfsan_label *ret_label, dfsan_origin signum_origin,
1405                      dfsan_origin act_origin, dfsan_origin oldact_origin,
1406                      dfsan_origin *ret_origin) {
1407   return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
1408                           oldact_label, ret_label);
1409 }
1410 
1411 static sighandler_t dfsan_signal(int signum, sighandler_t handler,
1412                                  dfsan_label *ret_label) {
1413   CHECK_LT(signum, kMaxSignals);
1414   SignalSpinLocker lock;
1415   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1416   if (handler != SIG_IGN && handler != SIG_DFL) {
1417     atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
1418     handler = &SignalHandler;
1419   }
1420 
1421   sighandler_t ret = signal(signum, handler);
1422 
1423   if (ret == SignalHandler)
1424     ret = (sighandler_t)old_cb;
1425 
1426   *ret_label = 0;
1427   return ret;
1428 }
1429 
1430 SANITIZER_INTERFACE_ATTRIBUTE
1431 sighandler_t __dfsw_signal(int signum,
1432                            void *(*handler_trampoline)(void *, int, dfsan_label,
1433                                                        dfsan_label *),
1434                            sighandler_t handler, dfsan_label signum_label,
1435                            dfsan_label handler_label, dfsan_label *ret_label) {
1436   return dfsan_signal(signum, handler, ret_label);
1437 }
1438 
1439 SANITIZER_INTERFACE_ATTRIBUTE
1440 sighandler_t __dfso_signal(
1441     int signum,
1442     void *(*handler_trampoline)(void *, int, dfsan_label, dfsan_label *,
1443                                 dfsan_origin, dfsan_origin *),
1444     sighandler_t handler, dfsan_label signum_label, dfsan_label handler_label,
1445     dfsan_label *ret_label, dfsan_origin signum_origin,
1446     dfsan_origin handler_origin, dfsan_origin *ret_origin) {
1447   return dfsan_signal(signum, handler, ret_label);
1448 }
1449 
1450 SANITIZER_INTERFACE_ATTRIBUTE
1451 int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1452                        dfsan_label old_ss_label, dfsan_label *ret_label) {
1453   int ret = sigaltstack(ss, old_ss);
1454   if (ret != -1 && old_ss)
1455     dfsan_set_label(0, old_ss, sizeof(*old_ss));
1456   *ret_label = 0;
1457   return ret;
1458 }
1459 
1460 SANITIZER_INTERFACE_ATTRIBUTE
1461 int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1462                        dfsan_label old_ss_label, dfsan_label *ret_label,
1463                        dfsan_origin ss_origin, dfsan_origin old_ss_origin,
1464                        dfsan_origin *ret_origin) {
1465   return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
1466 }
1467 
1468 SANITIZER_INTERFACE_ATTRIBUTE
1469 int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
1470                         dfsan_label tv_label, dfsan_label tz_label,
1471                         dfsan_label *ret_label) {
1472   int ret = gettimeofday(tv, tz);
1473   if (tv) {
1474     dfsan_set_label(0, tv, sizeof(struct timeval));
1475   }
1476   if (tz) {
1477     dfsan_set_label(0, tz, sizeof(struct timezone));
1478   }
1479   *ret_label = 0;
1480   return ret;
1481 }
1482 
1483 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
1484                                                   dfsan_label s_label,
1485                                                   dfsan_label c_label,
1486                                                   dfsan_label n_label,
1487                                                   dfsan_label *ret_label) {
1488   void *ret = memchr(s, c, n);
1489   if (flags().strict_data_dependencies) {
1490     *ret_label = ret ? s_label : 0;
1491   } else {
1492     size_t len =
1493         ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1494             : n;
1495     *ret_label =
1496         dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
1497   }
1498   return ret;
1499 }
1500 
1501 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
1502                                                    dfsan_label s_label,
1503                                                    dfsan_label c_label,
1504                                                    dfsan_label *ret_label) {
1505   char *ret = strrchr(s, c);
1506   if (flags().strict_data_dependencies) {
1507     *ret_label = ret ? s_label : 0;
1508   } else {
1509     *ret_label =
1510         dfsan_union(dfsan_read_label(s, strlen(s) + 1),
1511                     dfsan_union(s_label, c_label));
1512   }
1513 
1514   return ret;
1515 }
1516 
1517 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
1518                                                   dfsan_label haystack_label,
1519                                                   dfsan_label needle_label,
1520                                                   dfsan_label *ret_label) {
1521   char *ret = strstr(haystack, needle);
1522   if (flags().strict_data_dependencies) {
1523     *ret_label = ret ? haystack_label : 0;
1524   } else {
1525     size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
1526     *ret_label =
1527         dfsan_union(dfsan_read_label(haystack, len),
1528                     dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
1529                                 dfsan_union(haystack_label, needle_label)));
1530   }
1531 
1532   return ret;
1533 }
1534 
1535 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
1536                                                    struct timespec *rem,
1537                                                    dfsan_label req_label,
1538                                                    dfsan_label rem_label,
1539                                                    dfsan_label *ret_label) {
1540   int ret = nanosleep(req, rem);
1541   *ret_label = 0;
1542   if (ret == -1) {
1543     // Interrupted by a signal, rem is filled with the remaining time.
1544     dfsan_set_label(0, rem, sizeof(struct timespec));
1545   }
1546   return ret;
1547 }
1548 
1549 static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
1550   dfsan_set_label(0, msg, sizeof(*msg));
1551   dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
1552   dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
1553   for (size_t i = 0; bytes_written > 0; ++i) {
1554     assert(i < msg->msg_iovlen);
1555     struct iovec *iov = &msg->msg_iov[i];
1556     size_t iov_written =
1557         bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
1558     dfsan_set_label(0, iov->iov_base, iov_written);
1559     bytes_written -= iov_written;
1560   }
1561 }
1562 
1563 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
1564     int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1565     struct timespec *timeout, dfsan_label sockfd_label,
1566     dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1567     dfsan_label timeout_label, dfsan_label *ret_label) {
1568   int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
1569   for (int i = 0; i < ret; ++i) {
1570     dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
1571     clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
1572   }
1573   *ret_label = 0;
1574   return ret;
1575 }
1576 
1577 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
1578     int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1579     dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
1580   ssize_t ret = recvmsg(sockfd, msg, flags);
1581   if (ret >= 0)
1582     clear_msghdr_labels(ret, msg);
1583   *ret_label = 0;
1584   return ret;
1585 }
1586 
1587 SANITIZER_INTERFACE_ATTRIBUTE int
1588 __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
1589                   dfsan_label domain_label, dfsan_label type_label,
1590                   dfsan_label protocol_label, dfsan_label sv_label,
1591                   dfsan_label *ret_label) {
1592   int ret = socketpair(domain, type, protocol, sv);
1593   *ret_label = 0;
1594   if (ret == 0) {
1595     dfsan_set_label(0, sv, sizeof(*sv) * 2);
1596   }
1597   return ret;
1598 }
1599 
1600 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
1601     int sockfd, int level, int optname, void *optval, socklen_t *optlen,
1602     dfsan_label sockfd_label, dfsan_label level_label,
1603     dfsan_label optname_label, dfsan_label optval_label,
1604     dfsan_label optlen_label, dfsan_label *ret_label) {
1605   int ret = getsockopt(sockfd, level, optname, optval, optlen);
1606   if (ret != -1 && optval && optlen) {
1607     dfsan_set_label(0, optlen, sizeof(*optlen));
1608     dfsan_set_label(0, optval, *optlen);
1609   }
1610   *ret_label = 0;
1611   return ret;
1612 }
1613 
1614 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
1615     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
1616     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
1617     dfsan_label *ret_label) {
1618   socklen_t origlen = addrlen ? *addrlen : 0;
1619   int ret = getsockname(sockfd, addr, addrlen);
1620   if (ret != -1 && addr && addrlen) {
1621     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
1622     dfsan_set_label(0, addrlen, sizeof(*addrlen));
1623     dfsan_set_label(0, addr, written_bytes);
1624   }
1625   *ret_label = 0;
1626   return ret;
1627 }
1628 
1629 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
1630     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
1631     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
1632     dfsan_label *ret_label) {
1633   socklen_t origlen = addrlen ? *addrlen : 0;
1634   int ret = getpeername(sockfd, addr, addrlen);
1635   if (ret != -1 && addr && addrlen) {
1636     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
1637     dfsan_set_label(0, addrlen, sizeof(*addrlen));
1638     dfsan_set_label(0, addr, written_bytes);
1639   }
1640   *ret_label = 0;
1641   return ret;
1642 }
1643 
1644 // Type of the trampoline function passed to the custom version of
1645 // dfsan_set_write_callback.
1646 typedef void (*write_trampoline_t)(
1647     void *callback,
1648     int fd, const void *buf, ssize_t count,
1649     dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label);
1650 
1651 typedef void (*write_origin_trampoline_t)(
1652     void *callback, int fd, const void *buf, ssize_t count,
1653     dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
1654     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin);
1655 
1656 // Calls to dfsan_set_write_callback() set the values in this struct.
1657 // Calls to the custom version of write() read (and invoke) them.
1658 static struct {
1659   write_trampoline_t write_callback_trampoline = nullptr;
1660   void *write_callback = nullptr;
1661 } write_callback_info;
1662 
1663 static struct {
1664   write_origin_trampoline_t write_callback_trampoline = nullptr;
1665   void *write_callback = nullptr;
1666 } write_origin_callback_info;
1667 
1668 SANITIZER_INTERFACE_ATTRIBUTE void
1669 __dfsw_dfsan_set_write_callback(
1670     write_trampoline_t write_callback_trampoline,
1671     void *write_callback,
1672     dfsan_label write_callback_label,
1673     dfsan_label *ret_label) {
1674   write_callback_info.write_callback_trampoline = write_callback_trampoline;
1675   write_callback_info.write_callback = write_callback;
1676 }
1677 
1678 SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
1679     write_origin_trampoline_t write_callback_trampoline, void *write_callback,
1680     dfsan_label write_callback_label, dfsan_label *ret_label,
1681     dfsan_origin write_callback_origin, dfsan_origin *ret_origin) {
1682   write_origin_callback_info.write_callback_trampoline =
1683       write_callback_trampoline;
1684   write_origin_callback_info.write_callback = write_callback;
1685 }
1686 
1687 SANITIZER_INTERFACE_ATTRIBUTE int
1688 __dfsw_write(int fd, const void *buf, size_t count,
1689              dfsan_label fd_label, dfsan_label buf_label,
1690              dfsan_label count_label, dfsan_label *ret_label) {
1691   if (write_callback_info.write_callback) {
1692     write_callback_info.write_callback_trampoline(
1693         write_callback_info.write_callback,
1694         fd, buf, count,
1695         fd_label, buf_label, count_label);
1696   }
1697 
1698   *ret_label = 0;
1699   return write(fd, buf, count);
1700 }
1701 
1702 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
1703     int fd, const void *buf, size_t count, dfsan_label fd_label,
1704     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
1705     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
1706     dfsan_origin *ret_origin) {
1707   if (write_origin_callback_info.write_callback) {
1708     write_origin_callback_info.write_callback_trampoline(
1709         write_origin_callback_info.write_callback, fd, buf, count, fd_label,
1710         buf_label, count_label, fd_origin, buf_origin, count_origin);
1711   }
1712 
1713   *ret_label = 0;
1714   return write(fd, buf, count);
1715 }
1716 } // namespace __dfsan
1717 
1718 // Type used to extract a dfsan_label with va_arg()
1719 typedef int dfsan_label_va;
1720 
1721 // Formats a chunk either a constant string or a single format directive (e.g.,
1722 // '%.3f').
1723 struct Formatter {
1724   Formatter(char *str_, const char *fmt_, size_t size_)
1725       : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
1726         width(-1) {}
1727 
1728   int format() {
1729     char *tmp_fmt = build_format_string();
1730     int retval =
1731         snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
1732                  0 /* used only to avoid warnings */);
1733     free(tmp_fmt);
1734     return retval;
1735   }
1736 
1737   template <typename T> int format(T arg) {
1738     char *tmp_fmt = build_format_string();
1739     int retval;
1740     if (width >= 0) {
1741       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
1742                         tmp_fmt, width, arg);
1743     } else {
1744       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
1745                         tmp_fmt, arg);
1746     }
1747     free(tmp_fmt);
1748     return retval;
1749   }
1750 
1751   char *build_format_string() {
1752     size_t fmt_size = fmt_cur - fmt_start + 1;
1753     char *new_fmt = (char *)malloc(fmt_size + 1);
1754     assert(new_fmt);
1755     internal_memcpy(new_fmt, fmt_start, fmt_size);
1756     new_fmt[fmt_size] = '\0';
1757     return new_fmt;
1758   }
1759 
1760   char *str_cur() { return str + str_off; }
1761 
1762   size_t num_written_bytes(int retval) {
1763     if (retval < 0) {
1764       return 0;
1765     }
1766 
1767     size_t num_avail = str_off < size ? size - str_off : 0;
1768     if (num_avail == 0) {
1769       return 0;
1770     }
1771 
1772     size_t num_written = retval;
1773     // A return value of {v,}snprintf of size or more means that the output was
1774     // truncated.
1775     if (num_written >= num_avail) {
1776       num_written -= num_avail;
1777     }
1778 
1779     return num_written;
1780   }
1781 
1782   char *str;
1783   size_t str_off;
1784   size_t size;
1785   const char *fmt_start;
1786   const char *fmt_cur;
1787   int width;
1788 };
1789 
1790 // Formats the input and propagates the input labels to the output. The output
1791 // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
1792 // 'ap' are the format string and the list of arguments for formatting. Returns
1793 // the return value vsnprintf would return.
1794 //
1795 // The function tokenizes the format string in chunks representing either a
1796 // constant string or a single format directive (e.g., '%.3f') and formats each
1797 // chunk independently into the output string. This approach allows to figure
1798 // out which bytes of the output string depends on which argument and thus to
1799 // propagate labels more precisely.
1800 //
1801 // WARNING: This implementation does not support conversion specifiers with
1802 // positional arguments.
1803 static int format_buffer(char *str, size_t size, const char *fmt,
1804                          dfsan_label *va_labels, dfsan_label *ret_label,
1805                          va_list ap) {
1806   Formatter formatter(str, fmt, size);
1807 
1808   while (*formatter.fmt_cur) {
1809     formatter.fmt_start = formatter.fmt_cur;
1810     formatter.width = -1;
1811     int retval = 0;
1812 
1813     if (*formatter.fmt_cur != '%') {
1814       // Ordinary character. Consume all the characters until a '%' or the end
1815       // of the string.
1816       for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
1817            ++formatter.fmt_cur) {}
1818       retval = formatter.format();
1819       dfsan_set_label(0, formatter.str_cur(),
1820                       formatter.num_written_bytes(retval));
1821     } else {
1822       // Conversion directive. Consume all the characters until a conversion
1823       // specifier or the end of the string.
1824       bool end_fmt = false;
1825       for (; *formatter.fmt_cur && !end_fmt; ) {
1826         switch (*++formatter.fmt_cur) {
1827         case 'd':
1828         case 'i':
1829         case 'o':
1830         case 'u':
1831         case 'x':
1832         case 'X':
1833           switch (*(formatter.fmt_cur - 1)) {
1834           case 'h':
1835             // Also covers the 'hh' case (since the size of the arg is still
1836             // an int).
1837             retval = formatter.format(va_arg(ap, int));
1838             break;
1839           case 'l':
1840             if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
1841                 *(formatter.fmt_cur - 2) == 'l') {
1842               retval = formatter.format(va_arg(ap, long long int));
1843             } else {
1844               retval = formatter.format(va_arg(ap, long int));
1845             }
1846             break;
1847           case 'q':
1848             retval = formatter.format(va_arg(ap, long long int));
1849             break;
1850           case 'j':
1851             retval = formatter.format(va_arg(ap, intmax_t));
1852             break;
1853           case 'z':
1854           case 't':
1855             retval = formatter.format(va_arg(ap, size_t));
1856             break;
1857           default:
1858             retval = formatter.format(va_arg(ap, int));
1859           }
1860           dfsan_set_label(*va_labels++, formatter.str_cur(),
1861                           formatter.num_written_bytes(retval));
1862           end_fmt = true;
1863           break;
1864 
1865         case 'a':
1866         case 'A':
1867         case 'e':
1868         case 'E':
1869         case 'f':
1870         case 'F':
1871         case 'g':
1872         case 'G':
1873           if (*(formatter.fmt_cur - 1) == 'L') {
1874             retval = formatter.format(va_arg(ap, long double));
1875           } else {
1876             retval = formatter.format(va_arg(ap, double));
1877           }
1878           dfsan_set_label(*va_labels++, formatter.str_cur(),
1879                           formatter.num_written_bytes(retval));
1880           end_fmt = true;
1881           break;
1882 
1883         case 'c':
1884           retval = formatter.format(va_arg(ap, int));
1885           dfsan_set_label(*va_labels++, formatter.str_cur(),
1886                           formatter.num_written_bytes(retval));
1887           end_fmt = true;
1888           break;
1889 
1890         case 's': {
1891           char *arg = va_arg(ap, char *);
1892           retval = formatter.format(arg);
1893           va_labels++;
1894           internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg),
1895                           sizeof(dfsan_label) *
1896                               formatter.num_written_bytes(retval));
1897           end_fmt = true;
1898           break;
1899         }
1900 
1901         case 'p':
1902           retval = formatter.format(va_arg(ap, void *));
1903           dfsan_set_label(*va_labels++, formatter.str_cur(),
1904                           formatter.num_written_bytes(retval));
1905           end_fmt = true;
1906           break;
1907 
1908         case 'n': {
1909           int *ptr = va_arg(ap, int *);
1910           *ptr = (int)formatter.str_off;
1911           va_labels++;
1912           dfsan_set_label(0, ptr, sizeof(ptr));
1913           end_fmt = true;
1914           break;
1915         }
1916 
1917         case '%':
1918           retval = formatter.format();
1919           dfsan_set_label(0, formatter.str_cur(),
1920                           formatter.num_written_bytes(retval));
1921           end_fmt = true;
1922           break;
1923 
1924         case '*':
1925           formatter.width = va_arg(ap, int);
1926           va_labels++;
1927           break;
1928 
1929         default:
1930           break;
1931         }
1932       }
1933     }
1934 
1935     if (retval < 0) {
1936       return retval;
1937     }
1938 
1939     formatter.fmt_cur++;
1940     formatter.str_off += retval;
1941   }
1942 
1943   *ret_label = 0;
1944 
1945   // Number of bytes written in total.
1946   return formatter.str_off;
1947 }
1948 
1949 extern "C" {
1950 SANITIZER_INTERFACE_ATTRIBUTE
1951 int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
1952                    dfsan_label format_label, dfsan_label *va_labels,
1953                    dfsan_label *ret_label, ...) {
1954   va_list ap;
1955   va_start(ap, ret_label);
1956   int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, ap);
1957   va_end(ap);
1958   return ret;
1959 }
1960 
1961 SANITIZER_INTERFACE_ATTRIBUTE
1962 int __dfsw_snprintf(char *str, size_t size, const char *format,
1963                     dfsan_label str_label, dfsan_label size_label,
1964                     dfsan_label format_label, dfsan_label *va_labels,
1965                     dfsan_label *ret_label, ...) {
1966   va_list ap;
1967   va_start(ap, ret_label);
1968   int ret = format_buffer(str, size, format, va_labels, ret_label, ap);
1969   va_end(ap);
1970   return ret;
1971 }
1972 
1973 static void BeforeFork() {
1974   StackDepotLockAll();
1975   GetChainedOriginDepot()->LockAll();
1976 }
1977 
1978 static void AfterFork() {
1979   GetChainedOriginDepot()->UnlockAll();
1980   StackDepotUnlockAll();
1981 }
1982 
1983 SANITIZER_INTERFACE_ATTRIBUTE
1984 pid_t __dfsw_fork(dfsan_label *ret_label) {
1985   pid_t pid = fork();
1986   *ret_label = 0;
1987   return pid;
1988 }
1989 
1990 SANITIZER_INTERFACE_ATTRIBUTE
1991 pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
1992   BeforeFork();
1993   pid_t pid = __dfsw_fork(ret_label);
1994   AfterFork();
1995   return pid;
1996 }
1997 
1998 // Default empty implementations (weak). Users should redefine them.
1999 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
2000 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
2001                              u32 *) {}
2002 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {}
2003 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
2004 
2005 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
2006 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
2007 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
2008 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
2009 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
2010 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
2011                              void) {}
2012 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
2013                              void) {}
2014 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
2015                              void) {}
2016 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
2017                              void) {}
2018 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
2019 }  // extern "C"
2020