xref: /llvm-project/compiler-rt/lib/dfsan/dfsan_custom.cpp (revision 36bd9aebc428413a94f77e8daa679d1937dc2b63)
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_flags.h"
42 #include "dfsan/dfsan_thread.h"
43 #include "sanitizer_common/sanitizer_common.h"
44 #include "sanitizer_common/sanitizer_internal_defs.h"
45 #include "sanitizer_common/sanitizer_linux.h"
46 #include "sanitizer_common/sanitizer_stackdepot.h"
47 
48 using namespace __dfsan;
49 
50 #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
51   do {                                                                         \
52     if (f)                                                                     \
53       f(__VA_ARGS__);                                                          \
54   } while (false)
55 #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
56 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
57 
58 #define WRAPPER_ALIAS(fun, real)                                          \
59   SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \
60   SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);
61 
62 // Async-safe, non-reentrant spin lock.
63 namespace {
64 class SignalSpinLocker {
65  public:
66   SignalSpinLocker() {
67     sigset_t all_set;
68     sigfillset(&all_set);
69     pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
70     sigactions_mu.Lock();
71   }
72   ~SignalSpinLocker() {
73     sigactions_mu.Unlock();
74     pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
75   }
76 
77  private:
78   static StaticSpinMutex sigactions_mu;
79   sigset_t saved_thread_mask_;
80 
81   SignalSpinLocker(const SignalSpinLocker &) = delete;
82   SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
83 };
84 }  // namespace
85 
86 StaticSpinMutex SignalSpinLocker::sigactions_mu;
87 
88 extern "C" {
89 SANITIZER_INTERFACE_ATTRIBUTE int
90 __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
91             dfsan_label buf_label, dfsan_label *ret_label) {
92   int ret = stat(path, buf);
93   if (ret == 0)
94     dfsan_set_label(0, buf, sizeof(struct stat));
95   *ret_label = 0;
96   return ret;
97 }
98 
99 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
100     const char *path, struct stat *buf, dfsan_label path_label,
101     dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
102     dfsan_origin buf_origin, dfsan_origin *ret_origin) {
103   int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
104   return ret;
105 }
106 
107 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
108                                                dfsan_label fd_label,
109                                                dfsan_label buf_label,
110                                                dfsan_label *ret_label) {
111   int ret = fstat(fd, buf);
112   if (ret == 0)
113     dfsan_set_label(0, buf, sizeof(struct stat));
114   *ret_label = 0;
115   return ret;
116 }
117 
118 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
119     int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
120     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
121     dfsan_origin *ret_origin) {
122   int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
123   return ret;
124 }
125 
126 static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
127                                      dfsan_label s_label, dfsan_label c_label,
128                                      dfsan_label *ret_label) {
129   char *match_pos = nullptr;
130   for (size_t i = 0;; ++i) {
131     if (s[i] == c || s[i] == 0) {
132       // If s[i] is the \0 at the end of the string, and \0 is not the
133       // character we are searching for, then return null.
134       *bytes_read = i + 1;
135       match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
136       break;
137     }
138   }
139   if (flags().strict_data_dependencies)
140     *ret_label = s_label;
141   else
142     *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
143                              dfsan_union(s_label, c_label));
144   return match_pos;
145 }
146 
147 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
148                                                   dfsan_label s_label,
149                                                   dfsan_label c_label,
150                                                   dfsan_label *ret_label) {
151   size_t bytes_read;
152   return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
153                                  ret_label);
154 }
155 
156 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
157     const char *s, int c, dfsan_label s_label, dfsan_label c_label,
158     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
159     dfsan_origin *ret_origin) {
160   size_t bytes_read;
161   char *r =
162       dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
163   if (flags().strict_data_dependencies) {
164     *ret_origin = s_origin;
165   } else if (*ret_label) {
166     dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
167     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
168   }
169   return r;
170 }
171 
172 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
173                                                    const char *accept,
174                                                    dfsan_label s_label,
175                                                    dfsan_label accept_label,
176                                                    dfsan_label *ret_label) {
177   const char *ret = strpbrk(s, accept);
178   if (flags().strict_data_dependencies) {
179     *ret_label = ret ? s_label : 0;
180   } else {
181     size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
182     *ret_label =
183         dfsan_union(dfsan_read_label(s, s_bytes_read),
184                     dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
185                                 dfsan_union(s_label, accept_label)));
186   }
187   return const_cast<char *>(ret);
188 }
189 
190 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
191     const char *s, const char *accept, dfsan_label s_label,
192     dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
193     dfsan_origin accept_origin, dfsan_origin *ret_origin) {
194   const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
195   if (flags().strict_data_dependencies) {
196     if (ret)
197       *ret_origin = s_origin;
198   } else {
199     if (*ret_label) {
200       size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
201       dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
202       if (o) {
203         *ret_origin = o;
204       } else {
205         o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
206         *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
207       }
208     }
209   }
210   return const_cast<char *>(ret);
211 }
212 
213 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim,
214                                                   dfsan_label s_label,
215                                                   dfsan_label delim_label,
216                                                   dfsan_label *ret_label) {
217   dfsan_label base_label = dfsan_read_label(s, sizeof(*s));
218   char *base = *s;
219   char *res = strsep(s, delim);
220   if (res != *s) {
221     char *token_start = res;
222     int token_length = strlen(res);
223     // the delimiter byte has been set to NULL
224     dfsan_set_label(0, token_start + token_length, 1);
225   }
226 
227   if (flags().strict_data_dependencies) {
228     *ret_label = res ? base_label : 0;
229   } else {
230     size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;
231     *ret_label = dfsan_union(
232         dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))),
233         dfsan_union(dfsan_read_label(delim, strlen(delim) + 1),
234                     dfsan_union(s_label, delim_label)));
235   }
236 
237   return res;
238 }
239 
240 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep(
241     char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label,
242     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin,
243     dfsan_origin *ret_origin) {
244   dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s));
245   char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label);
246   if (flags().strict_data_dependencies) {
247     if (res)
248       *ret_origin = base_origin;
249   } else {
250     if (*ret_label) {
251       if (base_origin) {
252         *ret_origin = base_origin;
253       } else {
254         dfsan_origin o =
255             dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1);
256         *ret_origin = o ? o : (s_label ? s_origin : delim_origin);
257       }
258     }
259   }
260 
261   return res;
262 }
263 
264 static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
265                              size_t *bytes_read) {
266   const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
267   for (size_t i = 0; i != n; ++i) {
268     if (cs1[i] != cs2[i]) {
269       *bytes_read = i + 1;
270       return cs1[i] - cs2[i];
271     }
272   }
273   *bytes_read = n;
274   return 0;
275 }
276 
277 static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
278                                           size_t pos) {
279   if (flags().strict_data_dependencies)
280     return 0;
281   return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
282 }
283 
284 static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
285                                     dfsan_label *ret_label,
286                                     dfsan_origin *ret_origin) {
287   *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
288   if (*ret_label == 0)
289     return;
290   dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
291   *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
292 }
293 
294 static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
295                                    dfsan_label *ret_label) {
296   size_t bytes_read;
297   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
298   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
299   return r;
300 }
301 
302 static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
303                                     dfsan_label *ret_label,
304                                     dfsan_origin *ret_origin) {
305   size_t bytes_read;
306   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
307   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
308   return r;
309 }
310 
311 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
312                               const void *s1, const void *s2, size_t n,
313                               dfsan_label s1_label, dfsan_label s2_label,
314                               dfsan_label n_label)
315 
316 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
317                               const void *s1, const void *s2, size_t n,
318                               dfsan_label s1_label, dfsan_label s2_label,
319                               dfsan_label n_label, dfsan_origin s1_origin,
320                               dfsan_origin s2_origin, dfsan_origin n_origin)
321 
322 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
323                                                 size_t n, dfsan_label s1_label,
324                                                 dfsan_label s2_label,
325                                                 dfsan_label n_label,
326                                                 dfsan_label *ret_label) {
327   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
328                              s1_label, s2_label, n_label);
329   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
330 }
331 
332 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
333     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
334     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
335     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
336     dfsan_origin *ret_origin) {
337   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
338                              s2, n, s1_label, s2_label, n_label, s1_origin,
339                              s2_origin, n_origin);
340   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
341 }
342 
343 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
344                                               size_t n, dfsan_label s1_label,
345                                               dfsan_label s2_label,
346                                               dfsan_label n_label,
347                                               dfsan_label *ret_label) {
348   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
349 }
350 
351 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
352     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
353     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
354     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
355     dfsan_origin *ret_origin) {
356   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
357 }
358 
359 // When n == 0, compare strings without byte limit.
360 // When n > 0, compare the first (at most) n bytes of s1 and s2.
361 static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
362                          size_t *bytes_read) {
363   for (size_t i = 0;; ++i) {
364     if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
365       *bytes_read = i + 1;
366       return s1[i] - s2[i];
367     }
368   }
369 }
370 
371 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
372                               const char *s1, const char *s2,
373                               dfsan_label s1_label, dfsan_label s2_label)
374 
375 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
376                               const char *s1, const char *s2,
377                               dfsan_label s1_label, dfsan_label s2_label,
378                               dfsan_origin s1_origin, dfsan_origin s2_origin)
379 
380 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
381                                                 dfsan_label s1_label,
382                                                 dfsan_label s2_label,
383                                                 dfsan_label *ret_label) {
384   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
385                              s1_label, s2_label);
386   size_t bytes_read;
387   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
388   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
389   return r;
390 }
391 
392 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
393     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
394     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
395     dfsan_origin *ret_origin) {
396   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
397                              s2, s1_label, s2_label, s1_origin, s2_origin);
398   size_t bytes_read;
399   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
400   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
401   return r;
402 }
403 
404 // When n == 0, compare strings without byte limit.
405 // When n > 0, compare the first (at most) n bytes of s1 and s2.
406 static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
407                              size_t *bytes_read) {
408   for (size_t i = 0;; ++i) {
409     char s1_lower = tolower(s1[i]);
410     char s2_lower = tolower(s2[i]);
411 
412     if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
413         (n > 0 && i == n - 1)) {
414       *bytes_read = i + 1;
415       return s1_lower - s2_lower;
416     }
417   }
418 }
419 
420 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
421                                                     const char *s2,
422                                                     dfsan_label s1_label,
423                                                     dfsan_label s2_label,
424                                                     dfsan_label *ret_label) {
425   size_t bytes_read;
426   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
427   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
428   return r;
429 }
430 
431 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
432     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
433     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
434     dfsan_origin *ret_origin) {
435   size_t bytes_read;
436   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
437   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
438   return r;
439 }
440 
441 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
442                               const char *s1, const char *s2, size_t n,
443                               dfsan_label s1_label, dfsan_label s2_label,
444                               dfsan_label n_label)
445 
446 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
447                               const char *s1, const char *s2, size_t n,
448                               dfsan_label s1_label, dfsan_label s2_label,
449                               dfsan_label n_label, dfsan_origin s1_origin,
450                               dfsan_origin s2_origin, dfsan_origin n_origin)
451 
452 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
453                                                  size_t n, dfsan_label s1_label,
454                                                  dfsan_label s2_label,
455                                                  dfsan_label n_label,
456                                                  dfsan_label *ret_label) {
457   if (n == 0) {
458     *ret_label = 0;
459     return 0;
460   }
461 
462   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
463                              n, s1_label, s2_label, n_label);
464 
465   size_t bytes_read;
466   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
467   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
468   return r;
469 }
470 
471 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
472     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
473     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
474     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
475     dfsan_origin *ret_origin) {
476   if (n == 0) {
477     *ret_label = 0;
478     return 0;
479   }
480 
481   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
482                              s1, s2, n, s1_label, s2_label, n_label, s1_origin,
483                              s2_origin, n_origin);
484 
485   size_t bytes_read;
486   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
487   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
488   return r;
489 }
490 
491 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
492     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
493     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
494   if (n == 0) {
495     *ret_label = 0;
496     return 0;
497   }
498 
499   size_t bytes_read;
500   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
501   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
502   return r;
503 }
504 
505 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
506     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
507     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
508     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
509     dfsan_origin *ret_origin) {
510   if (n == 0) {
511     *ret_label = 0;
512     return 0;
513   }
514 
515   size_t bytes_read;
516   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
517   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
518   return r;
519 }
520 
521 
522 SANITIZER_INTERFACE_ATTRIBUTE size_t
523 __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
524   size_t ret = strlen(s);
525   if (flags().strict_data_dependencies) {
526     *ret_label = 0;
527   } else {
528     *ret_label = dfsan_read_label(s, ret + 1);
529   }
530   return ret;
531 }
532 
533 SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
534                                                    dfsan_label s_label,
535                                                    dfsan_label *ret_label,
536                                                    dfsan_origin s_origin,
537                                                    dfsan_origin *ret_origin) {
538   size_t ret = __dfsw_strlen(s, s_label, ret_label);
539   if (!flags().strict_data_dependencies)
540     *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
541   return ret;
542 }
543 
544 SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s,
545                                                     size_t maxlen,
546                                                     dfsan_label s_label,
547                                                     dfsan_label maxlen_label,
548                                                     dfsan_label *ret_label) {
549   size_t ret = strnlen(s, maxlen);
550   if (flags().strict_data_dependencies) {
551     *ret_label = 0;
552   } else {
553     size_t full_len = strlen(s);
554     size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;
555     *ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len));
556   }
557   return ret;
558 }
559 
560 SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen(
561     const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label,
562     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin,
563     dfsan_origin *ret_origin) {
564   size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label);
565   if (!flags().strict_data_dependencies) {
566     size_t full_len = strlen(s);
567     size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;
568     dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len);
569     *ret_origin = o ? o : maxlen_origin;
570   }
571   return ret;
572 }
573 
574 static void *dfsan_memmove(void *dest, const void *src, size_t n) {
575   dfsan_label *sdest = shadow_for(dest);
576   const dfsan_label *ssrc = shadow_for(src);
577   internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
578   return internal_memmove(dest, src, n);
579 }
580 
581 static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
582   dfsan_mem_origin_transfer(dest, src, n);
583   return dfsan_memmove(dest, src, n);
584 }
585 
586 static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
587   dfsan_mem_shadow_transfer(dest, src, n);
588   return internal_memcpy(dest, src, n);
589 }
590 
591 static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
592   dfsan_mem_origin_transfer(dest, src, n);
593   return dfsan_memcpy(dest, src, n);
594 }
595 
596 static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
597   internal_memset(s, c, n);
598   dfsan_set_label(c_label, s, n);
599 }
600 
601 static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
602                                      dfsan_origin c_origin, size_t n) {
603   internal_memset(s, c, n);
604   dfsan_set_label_origin(c_label, c_origin, s, n);
605 }
606 
607 SANITIZER_INTERFACE_ATTRIBUTE
608 void *__dfsw_memcpy(void *dest, const void *src, size_t n,
609                     dfsan_label dest_label, dfsan_label src_label,
610                     dfsan_label n_label, dfsan_label *ret_label) {
611   *ret_label = dest_label;
612   return dfsan_memcpy(dest, src, n);
613 }
614 
615 SANITIZER_INTERFACE_ATTRIBUTE
616 void *__dfso_memcpy(void *dest, const void *src, size_t n,
617                     dfsan_label dest_label, dfsan_label src_label,
618                     dfsan_label n_label, dfsan_label *ret_label,
619                     dfsan_origin dest_origin, dfsan_origin src_origin,
620                     dfsan_origin n_origin, dfsan_origin *ret_origin) {
621   *ret_label = dest_label;
622   *ret_origin = dest_origin;
623   return dfsan_memcpy_with_origin(dest, src, n);
624 }
625 
626 SANITIZER_INTERFACE_ATTRIBUTE
627 void *__dfsw_memmove(void *dest, const void *src, size_t n,
628                      dfsan_label dest_label, dfsan_label src_label,
629                      dfsan_label n_label, dfsan_label *ret_label) {
630   *ret_label = dest_label;
631   return dfsan_memmove(dest, src, n);
632 }
633 
634 SANITIZER_INTERFACE_ATTRIBUTE
635 void *__dfso_memmove(void *dest, const void *src, size_t n,
636                      dfsan_label dest_label, dfsan_label src_label,
637                      dfsan_label n_label, dfsan_label *ret_label,
638                      dfsan_origin dest_origin, dfsan_origin src_origin,
639                      dfsan_origin n_origin, dfsan_origin *ret_origin) {
640   *ret_label = dest_label;
641   *ret_origin = dest_origin;
642   return dfsan_memmove_with_origin(dest, src, n);
643 }
644 
645 SANITIZER_INTERFACE_ATTRIBUTE
646 void *__dfsw_memset(void *s, int c, size_t n,
647                     dfsan_label s_label, dfsan_label c_label,
648                     dfsan_label n_label, dfsan_label *ret_label) {
649   dfsan_memset(s, c, c_label, n);
650   *ret_label = s_label;
651   return s;
652 }
653 
654 SANITIZER_INTERFACE_ATTRIBUTE
655 void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
656                     dfsan_label c_label, dfsan_label n_label,
657                     dfsan_label *ret_label, dfsan_origin s_origin,
658                     dfsan_origin c_origin, dfsan_origin n_origin,
659                     dfsan_origin *ret_origin) {
660   dfsan_memset_with_origin(s, c, c_label, c_origin, n);
661   *ret_label = s_label;
662   *ret_origin = s_origin;
663   return s;
664 }
665 
666 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
667                                                   dfsan_label dest_label,
668                                                   dfsan_label src_label,
669                                                   dfsan_label *ret_label) {
670   size_t dest_len = strlen(dest);
671   char *ret = strcat(dest, src);
672   dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));
673   *ret_label = dest_label;
674   return ret;
675 }
676 
677 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
678     char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
679     dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
680     dfsan_origin *ret_origin) {
681   size_t dest_len = strlen(dest);
682   char *ret = strcat(dest, src);
683   size_t src_len = strlen(src);
684   dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
685   dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
686   *ret_label = dest_label;
687   *ret_origin = dest_origin;
688   return ret;
689 }
690 
691 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat(
692     char *dest, const char *src, size_t num, dfsan_label dest_label,
693     dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) {
694   size_t src_len = strlen(src);
695   src_len = src_len < num ? src_len : num;
696   size_t dest_len = strlen(dest);
697 
698   char *ret = strncat(dest, src, num);
699   dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
700   *ret_label = dest_label;
701   return ret;
702 }
703 
704 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat(
705     char *dest, const char *src, size_t num, dfsan_label dest_label,
706     dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label,
707     dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin,
708     dfsan_origin *ret_origin) {
709   size_t src_len = strlen(src);
710   src_len = src_len < num ? src_len : num;
711   size_t dest_len = strlen(dest);
712 
713   char *ret = strncat(dest, src, num);
714 
715   dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
716   dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
717   *ret_label = dest_label;
718   *ret_origin = dest_origin;
719   return ret;
720 }
721 
722 SANITIZER_INTERFACE_ATTRIBUTE char *
723 __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
724   size_t len = strlen(s);
725   void *p = malloc(len+1);
726   dfsan_memcpy(p, s, len+1);
727   *ret_label = 0;
728   return static_cast<char *>(p);
729 }
730 
731 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
732                                                   dfsan_label s_label,
733                                                   dfsan_label *ret_label,
734                                                   dfsan_origin s_origin,
735                                                   dfsan_origin *ret_origin) {
736   size_t len = strlen(s);
737   void *p = malloc(len + 1);
738   dfsan_memcpy_with_origin(p, s, len + 1);
739   *ret_label = 0;
740   return static_cast<char *>(p);
741 }
742 
743 SANITIZER_INTERFACE_ATTRIBUTE char *
744 __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
745                dfsan_label s2_label, dfsan_label n_label,
746                dfsan_label *ret_label) {
747   size_t len = strlen(s2);
748   if (len < n) {
749     dfsan_memcpy(s1, s2, len+1);
750     dfsan_memset(s1+len+1, 0, 0, n-len-1);
751   } else {
752     dfsan_memcpy(s1, s2, n);
753   }
754 
755   *ret_label = s1_label;
756   return s1;
757 }
758 
759 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
760     char *s1, const char *s2, size_t n, dfsan_label s1_label,
761     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
762     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
763     dfsan_origin *ret_origin) {
764   size_t len = strlen(s2);
765   if (len < n) {
766     dfsan_memcpy_with_origin(s1, s2, len + 1);
767     dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
768   } else {
769     dfsan_memcpy_with_origin(s1, s2, n);
770   }
771 
772   *ret_label = s1_label;
773   *ret_origin = s1_origin;
774   return s1;
775 }
776 
777 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
778 __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
779              dfsan_label fd_label, dfsan_label buf_label,
780              dfsan_label count_label, dfsan_label offset_label,
781              dfsan_label *ret_label) {
782   ssize_t ret = pread(fd, buf, count, offset);
783   if (ret > 0)
784     dfsan_set_label(0, buf, ret);
785   *ret_label = 0;
786   return ret;
787 }
788 
789 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
790     int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
791     dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
792     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
793     dfsan_origin count_origin, dfsan_label offset_origin,
794     dfsan_origin *ret_origin) {
795   return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
796                       offset_label, ret_label);
797 }
798 
799 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
800 __dfsw_read(int fd, void *buf, size_t count,
801              dfsan_label fd_label, dfsan_label buf_label,
802              dfsan_label count_label,
803              dfsan_label *ret_label) {
804   ssize_t ret = read(fd, buf, count);
805   if (ret > 0)
806     dfsan_set_label(0, buf, ret);
807   *ret_label = 0;
808   return ret;
809 }
810 
811 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
812     int fd, void *buf, size_t count, dfsan_label fd_label,
813     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
814     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
815     dfsan_origin *ret_origin) {
816   return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
817                      ret_label);
818 }
819 
820 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
821                                                        struct timespec *tp,
822                                                        dfsan_label clk_id_label,
823                                                        dfsan_label tp_label,
824                                                        dfsan_label *ret_label) {
825   int ret = clock_gettime(clk_id, tp);
826   if (ret == 0)
827     dfsan_set_label(0, tp, sizeof(struct timespec));
828   *ret_label = 0;
829   return ret;
830 }
831 
832 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
833     clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
834     dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
835     dfsan_origin tp_origin, dfsan_origin *ret_origin) {
836   return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
837 }
838 
839 static void dfsan_set_zero_label(const void *ptr, uptr size) {
840   dfsan_set_label(0, const_cast<void *>(ptr), size);
841 }
842 
843 // dlopen() ultimately calls mmap() down inside the loader, which generally
844 // doesn't participate in dynamic symbol resolution.  Therefore we won't
845 // intercept its calls to mmap, and we have to hook it here.
846 SANITIZER_INTERFACE_ATTRIBUTE void *
847 __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
848               dfsan_label flag_label, dfsan_label *ret_label) {
849   void *handle = dlopen(filename, flag);
850   link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
851   if (filename && map)
852     ForEachMappedRegion(map, dfsan_set_zero_label);
853   *ret_label = 0;
854   return handle;
855 }
856 
857 SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
858     const char *filename, int flag, dfsan_label filename_label,
859     dfsan_label flag_label, dfsan_label *ret_label,
860     dfsan_origin filename_origin, dfsan_origin flag_origin,
861     dfsan_origin *ret_origin) {
862   return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
863 }
864 
865 static void *DFsanThreadStartFunc(void *arg) {
866   DFsanThread *t = (DFsanThread *)arg;
867   SetCurrentThread(t);
868   t->Init();
869   SetSigProcMask(&t->starting_sigset_, nullptr);
870   return t->ThreadStart();
871 }
872 
873 static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
874                                 void *start_routine, void *arg,
875                                 dfsan_label *ret_label,
876                                 bool track_origins = false) {
877   pthread_attr_t myattr;
878   if (!attr) {
879     pthread_attr_init(&myattr);
880     attr = &myattr;
881   }
882 
883   // Ensure that the thread stack is large enough to hold all TLS data.
884   AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
885 
886   DFsanThread *t =
887       DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
888   ScopedBlockSignals block(&t->starting_sigset_);
889   int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
890 
891   if (attr == &myattr)
892     pthread_attr_destroy(&myattr);
893   *ret_label = 0;
894   return res;
895 }
896 
897 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
898     pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
899     void *arg, dfsan_label thread_label, dfsan_label attr_label,
900     dfsan_label start_routine_label, dfsan_label arg_label,
901     dfsan_label *ret_label) {
902   return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
903 }
904 
905 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
906     pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
907     void *arg, dfsan_label thread_label, dfsan_label attr_label,
908     dfsan_label start_routine_label, dfsan_label arg_label,
909     dfsan_label *ret_label, dfsan_origin thread_origin,
910     dfsan_origin attr_origin, dfsan_origin start_routine_origin,
911     dfsan_origin arg_origin, dfsan_origin *ret_origin) {
912   return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
913                               true);
914 }
915 
916 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
917                                                       void **retval,
918                                                       dfsan_label thread_label,
919                                                       dfsan_label retval_label,
920                                                       dfsan_label *ret_label) {
921   int ret = pthread_join(thread, retval);
922   if (ret == 0 && retval)
923     dfsan_set_label(0, retval, sizeof(*retval));
924   *ret_label = 0;
925   return ret;
926 }
927 
928 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
929     pthread_t thread, void **retval, dfsan_label thread_label,
930     dfsan_label retval_label, dfsan_label *ret_label,
931     dfsan_origin thread_origin, dfsan_origin retval_origin,
932     dfsan_origin *ret_origin) {
933   return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
934                              ret_label);
935 }
936 
937 struct dl_iterate_phdr_info {
938   int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
939   void *data;
940 };
941 
942 static int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size,
943                               void *data) {
944   dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
945   dfsan_set_label(0, *info);
946   dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
947                   strlen(info->dlpi_name) + 1);
948   dfsan_set_label(
949       0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
950       sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
951 
952   dfsan_clear_thread_local_state();
953   return dipi->callback(info, size, dipi->data);
954 }
955 
956 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
957     int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
958     void *data, dfsan_label callback_label, dfsan_label data_label,
959     dfsan_label *ret_label) {
960   dl_iterate_phdr_info dipi = {callback, data};
961   *ret_label = 0;
962   return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
963 }
964 
965 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
966     int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
967     void *data, dfsan_label callback_label, dfsan_label data_label,
968     dfsan_label *ret_label, dfsan_origin callback_origin,
969     dfsan_origin data_origin, dfsan_origin *ret_origin) {
970   dl_iterate_phdr_info dipi = {callback, data};
971   *ret_label = 0;
972   return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
973 }
974 
975 // This function is only available for glibc 2.27 or newer.  Mark it weak so
976 // linking succeeds with older glibcs.
977 SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
978                                                       size_t *alignp);
979 
980 SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
981     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
982     dfsan_label alignp_label) {
983   assert(_dl_get_tls_static_info);
984   _dl_get_tls_static_info(sizep, alignp);
985   dfsan_set_label(0, sizep, sizeof(*sizep));
986   dfsan_set_label(0, alignp, sizeof(*alignp));
987 }
988 
989 SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
990     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
991     dfsan_label alignp_label, dfsan_origin sizep_origin,
992     dfsan_origin alignp_origin) {
993   __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
994 }
995 
996 SANITIZER_INTERFACE_ATTRIBUTE
997 char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
998                      dfsan_label buf_label, dfsan_label *ret_label) {
999   char *ret = ctime_r(timep, buf);
1000   if (ret) {
1001     dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
1002                     strlen(buf) + 1);
1003     *ret_label = buf_label;
1004   } else {
1005     *ret_label = 0;
1006   }
1007   return ret;
1008 }
1009 
1010 SANITIZER_INTERFACE_ATTRIBUTE
1011 char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
1012                      dfsan_label buf_label, dfsan_label *ret_label,
1013                      dfsan_origin timep_origin, dfsan_origin buf_origin,
1014                      dfsan_origin *ret_origin) {
1015   char *ret = ctime_r(timep, buf);
1016   if (ret) {
1017     dfsan_set_label_origin(
1018         dfsan_read_label(timep, sizeof(time_t)),
1019         dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
1020         strlen(buf) + 1);
1021     *ret_label = buf_label;
1022     *ret_origin = buf_origin;
1023   } else {
1024     *ret_label = 0;
1025   }
1026   return ret;
1027 }
1028 
1029 SANITIZER_INTERFACE_ATTRIBUTE
1030 char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
1031                    dfsan_label size_label, dfsan_label stream_label,
1032                    dfsan_label *ret_label) {
1033   char *ret = fgets(s, size, stream);
1034   if (ret) {
1035     dfsan_set_label(0, ret, strlen(ret) + 1);
1036     *ret_label = s_label;
1037   } else {
1038     *ret_label = 0;
1039   }
1040   return ret;
1041 }
1042 
1043 SANITIZER_INTERFACE_ATTRIBUTE
1044 char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
1045                    dfsan_label size_label, dfsan_label stream_label,
1046                    dfsan_label *ret_label, dfsan_origin s_origin,
1047                    dfsan_origin size_origin, dfsan_origin stream_origin,
1048                    dfsan_origin *ret_origin) {
1049   char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
1050                            ret_label);
1051   if (ret)
1052     *ret_origin = s_origin;
1053   return ret;
1054 }
1055 
1056 SANITIZER_INTERFACE_ATTRIBUTE
1057 char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
1058                     dfsan_label size_label, dfsan_label *ret_label) {
1059   char *ret = getcwd(buf, size);
1060   if (ret) {
1061     dfsan_set_label(0, ret, strlen(ret) + 1);
1062     *ret_label = buf_label;
1063   } else {
1064     *ret_label = 0;
1065   }
1066   return ret;
1067 }
1068 
1069 SANITIZER_INTERFACE_ATTRIBUTE
1070 char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
1071                     dfsan_label size_label, dfsan_label *ret_label,
1072                     dfsan_origin buf_origin, dfsan_origin size_origin,
1073                     dfsan_origin *ret_origin) {
1074   char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
1075   if (ret)
1076     *ret_origin = buf_origin;
1077   return ret;
1078 }
1079 
1080 SANITIZER_INTERFACE_ATTRIBUTE
1081 char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
1082   char *ret = get_current_dir_name();
1083   if (ret)
1084     dfsan_set_label(0, ret, strlen(ret) + 1);
1085   *ret_label = 0;
1086   return ret;
1087 }
1088 
1089 SANITIZER_INTERFACE_ATTRIBUTE
1090 char *__dfso_get_current_dir_name(dfsan_label *ret_label,
1091                                   dfsan_origin *ret_origin) {
1092   return __dfsw_get_current_dir_name(ret_label);
1093 }
1094 
1095 // This function is only available for glibc 2.25 or newer.  Mark it weak so
1096 // linking succeeds with older glibcs.
1097 SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);
1098 
1099 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,
1100                                                     dfsan_label buffer_label,
1101                                                     dfsan_label length_label,
1102                                                     dfsan_label *ret_label) {
1103   int ret = getentropy(buffer, length);
1104   if (ret == 0) {
1105     dfsan_set_label(0, buffer, length);
1106   }
1107   *ret_label = 0;
1108   return ret;
1109 }
1110 
1111 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,
1112                                                     dfsan_label buffer_label,
1113                                                     dfsan_label length_label,
1114                                                     dfsan_label *ret_label,
1115                                                     dfsan_origin buffer_origin,
1116                                                     dfsan_origin length_origin,
1117                                                     dfsan_origin *ret_origin) {
1118   return __dfsw_getentropy(buffer, length, buffer_label, length_label,
1119                            ret_label);
1120 }
1121 
1122 SANITIZER_INTERFACE_ATTRIBUTE
1123 int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
1124                        dfsan_label len_label, dfsan_label *ret_label) {
1125   int ret = gethostname(name, len);
1126   if (ret == 0) {
1127     dfsan_set_label(0, name, strlen(name) + 1);
1128   }
1129   *ret_label = 0;
1130   return ret;
1131 }
1132 
1133 SANITIZER_INTERFACE_ATTRIBUTE
1134 int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
1135                        dfsan_label len_label, dfsan_label *ret_label,
1136                        dfsan_origin name_origin, dfsan_origin len_origin,
1137                        dfsan_label *ret_origin) {
1138   return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
1139 }
1140 
1141 SANITIZER_INTERFACE_ATTRIBUTE
1142 int __dfsw_getrlimit(int resource, struct rlimit *rlim,
1143                      dfsan_label resource_label, dfsan_label rlim_label,
1144                      dfsan_label *ret_label) {
1145   int ret = getrlimit(resource, rlim);
1146   if (ret == 0) {
1147     dfsan_set_label(0, rlim, sizeof(struct rlimit));
1148   }
1149   *ret_label = 0;
1150   return ret;
1151 }
1152 
1153 SANITIZER_INTERFACE_ATTRIBUTE
1154 int __dfso_getrlimit(int resource, struct rlimit *rlim,
1155                      dfsan_label resource_label, dfsan_label rlim_label,
1156                      dfsan_label *ret_label, dfsan_origin resource_origin,
1157                      dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
1158   return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
1159                           ret_label);
1160 }
1161 
1162 SANITIZER_INTERFACE_ATTRIBUTE
1163 int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1164                      dfsan_label usage_label, dfsan_label *ret_label) {
1165   int ret = getrusage(who, usage);
1166   if (ret == 0) {
1167     dfsan_set_label(0, usage, sizeof(struct rusage));
1168   }
1169   *ret_label = 0;
1170   return ret;
1171 }
1172 
1173 SANITIZER_INTERFACE_ATTRIBUTE
1174 int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1175                      dfsan_label usage_label, dfsan_label *ret_label,
1176                      dfsan_origin who_origin, dfsan_origin usage_origin,
1177                      dfsan_label *ret_origin) {
1178   return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
1179 }
1180 
1181 SANITIZER_INTERFACE_ATTRIBUTE
1182 char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
1183                     dfsan_label src_label, dfsan_label *ret_label) {
1184   char *ret = strcpy(dest, src);
1185   if (ret) {
1186     dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);
1187   }
1188   *ret_label = dst_label;
1189   return ret;
1190 }
1191 
1192 SANITIZER_INTERFACE_ATTRIBUTE
1193 char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
1194                     dfsan_label src_label, dfsan_label *ret_label,
1195                     dfsan_origin dst_origin, dfsan_origin src_origin,
1196                     dfsan_origin *ret_origin) {
1197   char *ret = strcpy(dest, src);
1198   if (ret) {
1199     size_t str_len = strlen(src) + 1;
1200     dfsan_mem_origin_transfer(dest, src, str_len);
1201     dfsan_mem_shadow_transfer(dest, src, str_len);
1202   }
1203   *ret_label = dst_label;
1204   *ret_origin = dst_origin;
1205   return ret;
1206 }
1207 }
1208 
1209 template <typename Fn>
1210 static ALWAYS_INLINE auto dfsan_strtol_impl(
1211     Fn real, const char *nptr, char **endptr, int base,
1212     char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) {
1213   assert(tmp_endptr);
1214   auto ret = real(nptr, tmp_endptr, base);
1215   if (endptr)
1216     *endptr = *tmp_endptr;
1217   return ret;
1218 }
1219 
1220 extern "C" {
1221 static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
1222                                   dfsan_label base_label,
1223                                   dfsan_label *ret_label) {
1224   if (tmp_endptr > nptr) {
1225     // If *tmp_endptr is '\0' include its label as well.
1226     *ret_label = dfsan_union(
1227         base_label,
1228         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
1229   } else {
1230     *ret_label = 0;
1231   }
1232 }
1233 
1234 static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
1235                                    dfsan_label base_label,
1236                                    dfsan_label *ret_label,
1237                                    dfsan_origin base_origin,
1238                                    dfsan_origin *ret_origin) {
1239   if (tmp_endptr > nptr) {
1240     // When multiple inputs are tainted, we propagate one of its origins.
1241     // Because checking if base_label is tainted does not need additional
1242     // computation, we prefer to propagating base_origin.
1243     *ret_origin = base_label
1244                       ? base_origin
1245                       : dfsan_read_origin_of_first_taint(
1246                             nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1247   }
1248 }
1249 
1250 static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
1251   assert(tmp_endptr);
1252   double ret = strtod(nptr, tmp_endptr);
1253   if (endptr)
1254     *endptr = *tmp_endptr;
1255   return ret;
1256 }
1257 
1258 static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
1259                                dfsan_label *ret_label) {
1260   if (tmp_endptr > nptr) {
1261     // If *tmp_endptr is '\0' include its label as well.
1262     *ret_label = dfsan_read_label(
1263         nptr,
1264         tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1265   } else {
1266     *ret_label = 0;
1267   }
1268 }
1269 
1270 SANITIZER_INTERFACE_ATTRIBUTE
1271 double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1272                      dfsan_label endptr_label, dfsan_label *ret_label) {
1273   char *tmp_endptr;
1274   double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1275   dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1276   return ret;
1277 }
1278 
1279 SANITIZER_INTERFACE_ATTRIBUTE
1280 double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1281                      dfsan_label endptr_label, dfsan_label *ret_label,
1282                      dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1283                      dfsan_origin *ret_origin) {
1284   char *tmp_endptr;
1285   double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1286   dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1287   if (tmp_endptr > nptr) {
1288     // If *tmp_endptr is '\0' include its label as well.
1289     *ret_origin = dfsan_read_origin_of_first_taint(
1290         nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1291   } else {
1292     *ret_origin = 0;
1293   }
1294   return ret;
1295 }
1296 
1297 WRAPPER_ALIAS(__isoc23_strtod, strtod)
1298 
1299 #define WRAPPER_STRTO(ret_type, fun)                                     \
1300   SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun(                   \
1301       const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1302       dfsan_label endptr_label, dfsan_label base_label,                  \
1303       dfsan_label *ret_label) {                                          \
1304     char *tmp_endptr;                                                    \
1305     auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr);  \
1306     dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);      \
1307     return ret;                                                          \
1308   }                                                                      \
1309   SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun(                   \
1310       const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1311       dfsan_label endptr_label, dfsan_label base_label,                  \
1312       dfsan_label *ret_label, dfsan_origin nptr_origin,                  \
1313       dfsan_origin endptr_origin, dfsan_origin base_origin,              \
1314       dfsan_origin *ret_origin) {                                        \
1315     char *tmp_endptr;                                                    \
1316     auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr);  \
1317     dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);      \
1318     dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label,      \
1319                            base_origin, ret_origin);                     \
1320     return ret;                                                          \
1321   }
1322 
1323 WRAPPER_STRTO(long, strtol)
1324 WRAPPER_STRTO(long long, strtoll)
1325 WRAPPER_STRTO(unsigned long, strtoul)
1326 WRAPPER_STRTO(unsigned long long, strtoull)
1327 WRAPPER_ALIAS(__isoc23_strtol, strtol)
1328 WRAPPER_ALIAS(__isoc23_strtoll, strtoll)
1329 WRAPPER_ALIAS(__isoc23_strtoul, strtoul)
1330 WRAPPER_ALIAS(__isoc23_strtoull, strtoull)
1331 
1332 SANITIZER_INTERFACE_ATTRIBUTE
1333 time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
1334   time_t ret = time(t);
1335   if (ret != (time_t) -1 && t) {
1336     dfsan_set_label(0, t, sizeof(time_t));
1337   }
1338   *ret_label = 0;
1339   return ret;
1340 }
1341 
1342 SANITIZER_INTERFACE_ATTRIBUTE
1343 time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
1344                    dfsan_origin t_origin, dfsan_origin *ret_origin) {
1345   return __dfsw_time(t, t_label, ret_label);
1346 }
1347 
1348 SANITIZER_INTERFACE_ATTRIBUTE
1349 int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1350                      dfsan_label src_label, dfsan_label dst_label,
1351                      dfsan_label *ret_label) {
1352   int ret = inet_pton(af, src, dst);
1353   if (ret == 1) {
1354     dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
1355                     af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1356   }
1357   *ret_label = 0;
1358   return ret;
1359 }
1360 
1361 SANITIZER_INTERFACE_ATTRIBUTE
1362 int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1363                      dfsan_label src_label, dfsan_label dst_label,
1364                      dfsan_label *ret_label, dfsan_origin af_origin,
1365                      dfsan_origin src_origin, dfsan_origin dst_origin,
1366                      dfsan_origin *ret_origin) {
1367   int ret = inet_pton(af, src, dst);
1368   if (ret == 1) {
1369     int src_len = strlen(src) + 1;
1370     dfsan_set_label_origin(
1371         dfsan_read_label(src, src_len),
1372         dfsan_read_origin_of_first_taint(src, src_len), dst,
1373         af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1374   }
1375   *ret_label = 0;
1376   return ret;
1377 }
1378 
1379 SANITIZER_INTERFACE_ATTRIBUTE
1380 struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
1381                               dfsan_label timep_label, dfsan_label result_label,
1382                               dfsan_label *ret_label) {
1383   struct tm *ret = localtime_r(timep, result);
1384   if (ret) {
1385     dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
1386                     sizeof(struct tm));
1387     *ret_label = result_label;
1388   } else {
1389     *ret_label = 0;
1390   }
1391   return ret;
1392 }
1393 
1394 SANITIZER_INTERFACE_ATTRIBUTE
1395 struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
1396                               dfsan_label timep_label, dfsan_label result_label,
1397                               dfsan_label *ret_label, dfsan_origin timep_origin,
1398                               dfsan_origin result_origin,
1399                               dfsan_origin *ret_origin) {
1400   struct tm *ret = localtime_r(timep, result);
1401   if (ret) {
1402     dfsan_set_label_origin(
1403         dfsan_read_label(timep, sizeof(time_t)),
1404         dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
1405         sizeof(struct tm));
1406     *ret_label = result_label;
1407     *ret_origin = result_origin;
1408   } else {
1409     *ret_label = 0;
1410   }
1411   return ret;
1412 }
1413 
1414 SANITIZER_INTERFACE_ATTRIBUTE
1415 int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
1416                       char *buf, size_t buflen, struct passwd **result,
1417                       dfsan_label uid_label, dfsan_label pwd_label,
1418                       dfsan_label buf_label, dfsan_label buflen_label,
1419                       dfsan_label result_label, dfsan_label *ret_label) {
1420   // Store the data in pwd, the strings referenced from pwd in buf, and the
1421   // address of pwd in *result.  On failure, NULL is stored in *result.
1422   int ret = getpwuid_r(uid, pwd, buf, buflen, result);
1423   if (ret == 0) {
1424     dfsan_set_label(0, pwd, sizeof(struct passwd));
1425     dfsan_set_label(0, buf, strlen(buf) + 1);
1426   }
1427   *ret_label = 0;
1428   dfsan_set_label(0, result, sizeof(struct passwd*));
1429   return ret;
1430 }
1431 
1432 SANITIZER_INTERFACE_ATTRIBUTE
1433 int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
1434                       struct passwd **result, dfsan_label uid_label,
1435                       dfsan_label pwd_label, dfsan_label buf_label,
1436                       dfsan_label buflen_label, dfsan_label result_label,
1437                       dfsan_label *ret_label, dfsan_origin uid_origin,
1438                       dfsan_origin pwd_origin, dfsan_origin buf_origin,
1439                       dfsan_origin buflen_origin, dfsan_origin result_origin,
1440                       dfsan_origin *ret_origin) {
1441   return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
1442                            buf_label, buflen_label, result_label, ret_label);
1443 }
1444 
1445 SANITIZER_INTERFACE_ATTRIBUTE
1446 int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1447                       int timeout, dfsan_label epfd_label,
1448                       dfsan_label events_label, dfsan_label maxevents_label,
1449                       dfsan_label timeout_label, dfsan_label *ret_label) {
1450   int ret = epoll_wait(epfd, events, maxevents, timeout);
1451   if (ret > 0)
1452     dfsan_set_label(0, events, ret * sizeof(*events));
1453   *ret_label = 0;
1454   return ret;
1455 }
1456 
1457 SANITIZER_INTERFACE_ATTRIBUTE
1458 int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1459                       int timeout, dfsan_label epfd_label,
1460                       dfsan_label events_label, dfsan_label maxevents_label,
1461                       dfsan_label timeout_label, dfsan_label *ret_label,
1462                       dfsan_origin epfd_origin, dfsan_origin events_origin,
1463                       dfsan_origin maxevents_origin,
1464                       dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1465   return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
1466                            events_label, maxevents_label, timeout_label,
1467                            ret_label);
1468 }
1469 
1470 SANITIZER_INTERFACE_ATTRIBUTE
1471 int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1472                 dfsan_label dfs_label, dfsan_label nfds_label,
1473                 dfsan_label timeout_label, dfsan_label *ret_label) {
1474   int ret = poll(fds, nfds, timeout);
1475   if (ret >= 0) {
1476     for (; nfds > 0; --nfds) {
1477       dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
1478     }
1479   }
1480   *ret_label = 0;
1481   return ret;
1482 }
1483 
1484 SANITIZER_INTERFACE_ATTRIBUTE
1485 int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1486                 dfsan_label dfs_label, dfsan_label nfds_label,
1487                 dfsan_label timeout_label, dfsan_label *ret_label,
1488                 dfsan_origin dfs_origin, dfsan_origin nfds_origin,
1489                 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1490   return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
1491                      ret_label);
1492 }
1493 
1494 SANITIZER_INTERFACE_ATTRIBUTE
1495 int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
1496                   fd_set *exceptfds, struct timeval *timeout,
1497                   dfsan_label nfds_label, dfsan_label readfds_label,
1498                   dfsan_label writefds_label, dfsan_label exceptfds_label,
1499                   dfsan_label timeout_label, dfsan_label *ret_label) {
1500   int ret = select(nfds, readfds, writefds, exceptfds, timeout);
1501   // Clear everything (also on error) since their content is either set or
1502   // undefined.
1503   if (readfds) {
1504     dfsan_set_label(0, readfds, sizeof(fd_set));
1505   }
1506   if (writefds) {
1507     dfsan_set_label(0, writefds, sizeof(fd_set));
1508   }
1509   if (exceptfds) {
1510     dfsan_set_label(0, exceptfds, sizeof(fd_set));
1511   }
1512   dfsan_set_label(0, timeout, sizeof(struct timeval));
1513   *ret_label = 0;
1514   return ret;
1515 }
1516 
1517 SANITIZER_INTERFACE_ATTRIBUTE
1518 int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
1519                   fd_set *exceptfds, struct timeval *timeout,
1520                   dfsan_label nfds_label, dfsan_label readfds_label,
1521                   dfsan_label writefds_label, dfsan_label exceptfds_label,
1522                   dfsan_label timeout_label, dfsan_label *ret_label,
1523                   dfsan_origin nfds_origin, dfsan_origin readfds_origin,
1524                   dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
1525                   dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1526   return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
1527                        readfds_label, writefds_label, exceptfds_label,
1528                        timeout_label, ret_label);
1529 }
1530 
1531 SANITIZER_INTERFACE_ATTRIBUTE
1532 int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1533                              dfsan_label pid_label,
1534                              dfsan_label cpusetsize_label,
1535                              dfsan_label mask_label, dfsan_label *ret_label) {
1536   int ret = sched_getaffinity(pid, cpusetsize, mask);
1537   if (ret == 0) {
1538     dfsan_set_label(0, mask, cpusetsize);
1539   }
1540   *ret_label = 0;
1541   return ret;
1542 }
1543 
1544 SANITIZER_INTERFACE_ATTRIBUTE
1545 int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1546                              dfsan_label pid_label,
1547                              dfsan_label cpusetsize_label,
1548                              dfsan_label mask_label, dfsan_label *ret_label,
1549                              dfsan_origin pid_origin,
1550                              dfsan_origin cpusetsize_origin,
1551                              dfsan_origin mask_origin,
1552                              dfsan_origin *ret_origin) {
1553   return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
1554                                   cpusetsize_label, mask_label, ret_label);
1555 }
1556 
1557 SANITIZER_INTERFACE_ATTRIBUTE
1558 int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
1559                        dfsan_label *ret_label) {
1560   int ret = sigemptyset(set);
1561   dfsan_set_label(0, set, sizeof(sigset_t));
1562   *ret_label = 0;
1563   return ret;
1564 }
1565 
1566 SANITIZER_INTERFACE_ATTRIBUTE
1567 int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
1568                        dfsan_label *ret_label, dfsan_origin set_origin,
1569                        dfsan_origin *ret_origin) {
1570   return __dfsw_sigemptyset(set, set_label, ret_label);
1571 }
1572 
1573 class SignalHandlerScope {
1574  public:
1575   SignalHandlerScope() {
1576     if (DFsanThread *t = GetCurrentThread())
1577       t->EnterSignalHandler();
1578   }
1579   ~SignalHandlerScope() {
1580     if (DFsanThread *t = GetCurrentThread())
1581       t->LeaveSignalHandler();
1582   }
1583 };
1584 
1585 // Clear DFSan runtime TLS state at the end of a scope.
1586 //
1587 // Implementation must be async-signal-safe and use small data size, because
1588 // instances of this class may live on the signal handler stack.
1589 //
1590 // DFSan uses TLS to pass metadata of arguments and return values. When an
1591 // instrumented function accesses the TLS, if a signal callback happens, and the
1592 // callback calls other instrumented functions with updating the same TLS, the
1593 // TLS is in an inconsistent state after the callback ends. This may cause
1594 // either under-tainting or over-tainting.
1595 //
1596 // The current implementation simply resets TLS at restore. This prevents from
1597 // over-tainting. Although under-tainting may still happen, a taint flow can be
1598 // found eventually if we run a DFSan-instrumented program multiple times. The
1599 // alternative option is saving the entire TLS. However the TLS storage takes
1600 // 2k bytes, and signal calls could be nested. So it does not seem worth.
1601 class ScopedClearThreadLocalState {
1602  public:
1603   ScopedClearThreadLocalState() {}
1604   ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1605 };
1606 
1607 // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1608 const int kMaxSignals = 1024;
1609 static atomic_uintptr_t sigactions[kMaxSignals];
1610 
1611 static void SignalHandler(int signo) {
1612   SignalHandlerScope signal_handler_scope;
1613   ScopedClearThreadLocalState scoped_clear_tls;
1614 
1615   // Clear shadows for all inputs provided by system.
1616   dfsan_clear_arg_tls(0, sizeof(dfsan_label));
1617 
1618   typedef void (*signal_cb)(int x);
1619   signal_cb cb =
1620       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1621   cb(signo);
1622 }
1623 
1624 static void SignalAction(int signo, siginfo_t *si, void *uc) {
1625   SignalHandlerScope signal_handler_scope;
1626   ScopedClearThreadLocalState scoped_clear_tls;
1627 
1628   // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1629   dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
1630   dfsan_set_label(0, si, sizeof(*si));
1631   dfsan_set_label(0, uc, sizeof(ucontext_t));
1632 
1633   typedef void (*sigaction_cb)(int, siginfo_t *, void *);
1634   sigaction_cb cb =
1635       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1636   cb(signo, si, uc);
1637 }
1638 
1639 SANITIZER_INTERFACE_ATTRIBUTE
1640 int __dfsw_sigaction(int signum, const struct sigaction *act,
1641                      struct sigaction *oldact, dfsan_label signum_label,
1642                      dfsan_label act_label, dfsan_label oldact_label,
1643                      dfsan_label *ret_label) {
1644   CHECK_LT(signum, kMaxSignals);
1645   SignalSpinLocker lock;
1646   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1647   struct sigaction new_act;
1648   struct sigaction *pnew_act = act ? &new_act : nullptr;
1649   if (act) {
1650     internal_memcpy(pnew_act, act, sizeof(struct sigaction));
1651     if (pnew_act->sa_flags & SA_SIGINFO) {
1652       uptr cb = (uptr)(pnew_act->sa_sigaction);
1653       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1654         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1655         pnew_act->sa_sigaction = SignalAction;
1656       }
1657     } else {
1658       uptr cb = (uptr)(pnew_act->sa_handler);
1659       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1660         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1661         pnew_act->sa_handler = SignalHandler;
1662       }
1663     }
1664   }
1665 
1666   int ret = sigaction(signum, pnew_act, oldact);
1667 
1668   if (ret == 0 && oldact) {
1669     if (oldact->sa_flags & SA_SIGINFO) {
1670       if (oldact->sa_sigaction == SignalAction)
1671         oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
1672     } else {
1673       if (oldact->sa_handler == SignalHandler)
1674         oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
1675     }
1676   }
1677 
1678   if (oldact) {
1679     dfsan_set_label(0, oldact, sizeof(struct sigaction));
1680   }
1681   *ret_label = 0;
1682   return ret;
1683 }
1684 
1685 SANITIZER_INTERFACE_ATTRIBUTE
1686 int __dfso_sigaction(int signum, const struct sigaction *act,
1687                      struct sigaction *oldact, dfsan_label signum_label,
1688                      dfsan_label act_label, dfsan_label oldact_label,
1689                      dfsan_label *ret_label, dfsan_origin signum_origin,
1690                      dfsan_origin act_origin, dfsan_origin oldact_origin,
1691                      dfsan_origin *ret_origin) {
1692   return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
1693                           oldact_label, ret_label);
1694 }
1695 
1696 static sighandler_t dfsan_signal(int signum, sighandler_t handler,
1697                                  dfsan_label *ret_label) {
1698   CHECK_LT(signum, kMaxSignals);
1699   SignalSpinLocker lock;
1700   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1701   if (handler != SIG_IGN && handler != SIG_DFL) {
1702     atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
1703     handler = &SignalHandler;
1704   }
1705 
1706   sighandler_t ret = signal(signum, handler);
1707 
1708   if (ret == SignalHandler)
1709     ret = (sighandler_t)old_cb;
1710 
1711   *ret_label = 0;
1712   return ret;
1713 }
1714 
1715 SANITIZER_INTERFACE_ATTRIBUTE
1716 sighandler_t __dfsw_signal(int signum, sighandler_t handler,
1717                            dfsan_label signum_label, dfsan_label handler_label,
1718                            dfsan_label *ret_label) {
1719   return dfsan_signal(signum, handler, ret_label);
1720 }
1721 
1722 SANITIZER_INTERFACE_ATTRIBUTE
1723 sighandler_t __dfso_signal(int signum, sighandler_t handler,
1724                            dfsan_label signum_label, dfsan_label handler_label,
1725                            dfsan_label *ret_label, dfsan_origin signum_origin,
1726                            dfsan_origin handler_origin,
1727                            dfsan_origin *ret_origin) {
1728   return dfsan_signal(signum, handler, ret_label);
1729 }
1730 
1731 SANITIZER_INTERFACE_ATTRIBUTE
1732 int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1733                        dfsan_label old_ss_label, dfsan_label *ret_label) {
1734   int ret = sigaltstack(ss, old_ss);
1735   if (ret != -1 && old_ss)
1736     dfsan_set_label(0, old_ss, sizeof(*old_ss));
1737   *ret_label = 0;
1738   return ret;
1739 }
1740 
1741 SANITIZER_INTERFACE_ATTRIBUTE
1742 int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1743                        dfsan_label old_ss_label, dfsan_label *ret_label,
1744                        dfsan_origin ss_origin, dfsan_origin old_ss_origin,
1745                        dfsan_origin *ret_origin) {
1746   return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
1747 }
1748 
1749 SANITIZER_INTERFACE_ATTRIBUTE
1750 int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
1751                         dfsan_label tv_label, dfsan_label tz_label,
1752                         dfsan_label *ret_label) {
1753   int ret = gettimeofday(tv, tz);
1754   if (tv) {
1755     dfsan_set_label(0, tv, sizeof(struct timeval));
1756   }
1757   if (tz) {
1758     dfsan_set_label(0, tz, sizeof(struct timezone));
1759   }
1760   *ret_label = 0;
1761   return ret;
1762 }
1763 
1764 SANITIZER_INTERFACE_ATTRIBUTE
1765 int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
1766                         dfsan_label tv_label, dfsan_label tz_label,
1767                         dfsan_label *ret_label, dfsan_origin tv_origin,
1768                         dfsan_origin tz_origin, dfsan_origin *ret_origin) {
1769   return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
1770 }
1771 
1772 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
1773                                                   dfsan_label s_label,
1774                                                   dfsan_label c_label,
1775                                                   dfsan_label n_label,
1776                                                   dfsan_label *ret_label) {
1777   void *ret = memchr(s, c, n);
1778   if (flags().strict_data_dependencies) {
1779     *ret_label = ret ? s_label : 0;
1780   } else {
1781     size_t len =
1782         ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1783             : n;
1784     *ret_label =
1785         dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
1786   }
1787   return ret;
1788 }
1789 
1790 SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
1791     void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
1792     dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
1793     dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
1794   void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
1795   if (flags().strict_data_dependencies) {
1796     if (ret)
1797       *ret_origin = s_origin;
1798   } else {
1799     size_t len =
1800         ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1801             : n;
1802     dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
1803     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1804   }
1805   return ret;
1806 }
1807 
1808 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
1809                                                    dfsan_label s_label,
1810                                                    dfsan_label c_label,
1811                                                    dfsan_label *ret_label) {
1812   char *ret = strrchr(s, c);
1813   if (flags().strict_data_dependencies) {
1814     *ret_label = ret ? s_label : 0;
1815   } else {
1816     *ret_label =
1817         dfsan_union(dfsan_read_label(s, strlen(s) + 1),
1818                     dfsan_union(s_label, c_label));
1819   }
1820 
1821   return ret;
1822 }
1823 
1824 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
1825     char *s, int c, dfsan_label s_label, dfsan_label c_label,
1826     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
1827     dfsan_origin *ret_origin) {
1828   char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
1829   if (flags().strict_data_dependencies) {
1830     if (ret)
1831       *ret_origin = s_origin;
1832   } else {
1833     size_t s_len = strlen(s) + 1;
1834     dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
1835     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1836   }
1837 
1838   return ret;
1839 }
1840 
1841 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
1842                                                   dfsan_label haystack_label,
1843                                                   dfsan_label needle_label,
1844                                                   dfsan_label *ret_label) {
1845   char *ret = strstr(haystack, needle);
1846   if (flags().strict_data_dependencies) {
1847     *ret_label = ret ? haystack_label : 0;
1848   } else {
1849     size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
1850     *ret_label =
1851         dfsan_union(dfsan_read_label(haystack, len),
1852                     dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
1853                                 dfsan_union(haystack_label, needle_label)));
1854   }
1855 
1856   return ret;
1857 }
1858 
1859 SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
1860                                                   dfsan_label haystack_label,
1861                                                   dfsan_label needle_label,
1862                                                   dfsan_label *ret_label,
1863                                                   dfsan_origin haystack_origin,
1864                                                   dfsan_origin needle_origin,
1865                                                   dfsan_origin *ret_origin) {
1866   char *ret =
1867       __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
1868   if (flags().strict_data_dependencies) {
1869     if (ret)
1870       *ret_origin = haystack_origin;
1871   } else {
1872     size_t needle_len = strlen(needle);
1873     size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
1874     dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
1875     if (o) {
1876       *ret_origin = o;
1877     } else {
1878       o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
1879       *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
1880     }
1881   }
1882 
1883   return ret;
1884 }
1885 
1886 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
1887                                                    struct timespec *rem,
1888                                                    dfsan_label req_label,
1889                                                    dfsan_label rem_label,
1890                                                    dfsan_label *ret_label) {
1891   int ret = nanosleep(req, rem);
1892   *ret_label = 0;
1893   if (ret == -1) {
1894     // Interrupted by a signal, rem is filled with the remaining time.
1895     dfsan_set_label(0, rem, sizeof(struct timespec));
1896   }
1897   return ret;
1898 }
1899 
1900 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
1901     const struct timespec *req, struct timespec *rem, dfsan_label req_label,
1902     dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
1903     dfsan_origin rem_origin, dfsan_origin *ret_origin) {
1904   return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
1905 }
1906 
1907 static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg,
1908                                 int flags) {
1909   dfsan_set_label(0, msg, sizeof(*msg));
1910   dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
1911   dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
1912   for (size_t i = 0; i < msg->msg_iovlen; ++i) {
1913     struct iovec *iov = &msg->msg_iov[i];
1914     size_t iov_written = iov->iov_len;
1915 
1916     // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that
1917     // may not have changed, using bytes_written to bound the 0 label write.
1918     // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer,
1919     // and should not be used as a bound.
1920     if (!(MSG_TRUNC & flags)) {
1921       if (bytes_written < iov->iov_len) {
1922         iov_written = bytes_written;
1923       }
1924       bytes_written -= iov_written;
1925     }
1926 
1927     dfsan_set_label(0, iov->iov_base, iov_written);
1928   }
1929 }
1930 
1931 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
1932     int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1933     struct timespec *timeout, dfsan_label sockfd_label,
1934     dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1935     dfsan_label timeout_label, dfsan_label *ret_label) {
1936   int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
1937   for (int i = 0; i < ret; ++i) {
1938     dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
1939     clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags);
1940   }
1941   *ret_label = 0;
1942   return ret;
1943 }
1944 
1945 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
1946     int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1947     struct timespec *timeout, dfsan_label sockfd_label,
1948     dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1949     dfsan_label timeout_label, dfsan_label *ret_label,
1950     dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
1951     dfsan_origin vlen_origin, dfsan_origin flags_origin,
1952     dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1953   return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
1954                          msgvec_label, vlen_label, flags_label, timeout_label,
1955                          ret_label);
1956 }
1957 
1958 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
1959     int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1960     dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
1961   ssize_t ret = recvmsg(sockfd, msg, flags);
1962   if (ret >= 0)
1963     clear_msghdr_labels(ret, msg, flags);
1964   *ret_label = 0;
1965   return ret;
1966 }
1967 
1968 SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
1969     int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1970     dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
1971     dfsan_origin sockfd_origin, dfsan_origin msg_origin,
1972     dfsan_origin flags_origin, dfsan_origin *ret_origin) {
1973   return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
1974                         flags_label, ret_label);
1975 }
1976 
1977 SANITIZER_INTERFACE_ATTRIBUTE int
1978 __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
1979                   dfsan_label domain_label, dfsan_label type_label,
1980                   dfsan_label protocol_label, dfsan_label sv_label,
1981                   dfsan_label *ret_label) {
1982   int ret = socketpair(domain, type, protocol, sv);
1983   *ret_label = 0;
1984   if (ret == 0) {
1985     dfsan_set_label(0, sv, sizeof(*sv) * 2);
1986   }
1987   return ret;
1988 }
1989 
1990 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
1991     int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
1992     dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
1993     dfsan_label *ret_label, dfsan_origin domain_origin,
1994     dfsan_origin type_origin, dfsan_origin protocol_origin,
1995     dfsan_origin sv_origin, dfsan_origin *ret_origin) {
1996   return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
1997                            protocol_label, sv_label, ret_label);
1998 }
1999 
2000 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
2001     int sockfd, int level, int optname, void *optval, socklen_t *optlen,
2002     dfsan_label sockfd_label, dfsan_label level_label,
2003     dfsan_label optname_label, dfsan_label optval_label,
2004     dfsan_label optlen_label, dfsan_label *ret_label) {
2005   int ret = getsockopt(sockfd, level, optname, optval, optlen);
2006   if (ret != -1 && optval && optlen) {
2007     dfsan_set_label(0, optlen, sizeof(*optlen));
2008     dfsan_set_label(0, optval, *optlen);
2009   }
2010   *ret_label = 0;
2011   return ret;
2012 }
2013 
2014 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
2015     int sockfd, int level, int optname, void *optval, socklen_t *optlen,
2016     dfsan_label sockfd_label, dfsan_label level_label,
2017     dfsan_label optname_label, dfsan_label optval_label,
2018     dfsan_label optlen_label, dfsan_label *ret_label,
2019     dfsan_origin sockfd_origin, dfsan_origin level_origin,
2020     dfsan_origin optname_origin, dfsan_origin optval_origin,
2021     dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
2022   return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
2023                            level_label, optname_label, optval_label,
2024                            optlen_label, ret_label);
2025 }
2026 
2027 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
2028     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2029     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2030     dfsan_label *ret_label) {
2031   socklen_t origlen = addrlen ? *addrlen : 0;
2032   int ret = getsockname(sockfd, addr, addrlen);
2033   if (ret != -1 && addr && addrlen) {
2034     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2035     dfsan_set_label(0, addrlen, sizeof(*addrlen));
2036     dfsan_set_label(0, addr, written_bytes);
2037   }
2038   *ret_label = 0;
2039   return ret;
2040 }
2041 
2042 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
2043     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2044     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2045     dfsan_label *ret_label, dfsan_origin sockfd_origin,
2046     dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2047     dfsan_origin *ret_origin) {
2048   return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
2049                             addrlen_label, ret_label);
2050 }
2051 
2052 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
2053     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2054     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2055     dfsan_label *ret_label) {
2056   socklen_t origlen = addrlen ? *addrlen : 0;
2057   int ret = getpeername(sockfd, addr, addrlen);
2058   if (ret != -1 && addr && addrlen) {
2059     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2060     dfsan_set_label(0, addrlen, sizeof(*addrlen));
2061     dfsan_set_label(0, addr, written_bytes);
2062   }
2063   *ret_label = 0;
2064   return ret;
2065 }
2066 
2067 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
2068     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2069     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2070     dfsan_label *ret_label, dfsan_origin sockfd_origin,
2071     dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2072     dfsan_origin *ret_origin) {
2073   return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
2074                             addrlen_label, ret_label);
2075 }
2076 
2077 // Type of the function passed to dfsan_set_write_callback.
2078 typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
2079 
2080 // Calls to dfsan_set_write_callback() set the values in this struct.
2081 // Calls to the custom version of write() read (and invoke) them.
2082 static struct {
2083   write_dfsan_callback_t write_callback = nullptr;
2084 } write_callback_info;
2085 
2086 SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
2087     write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
2088     dfsan_label *ret_label) {
2089   write_callback_info.write_callback = write_callback;
2090 }
2091 
2092 SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
2093     write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
2094     dfsan_label *ret_label, dfsan_origin write_callback_origin,
2095     dfsan_origin *ret_origin) {
2096   write_callback_info.write_callback = write_callback;
2097 }
2098 
2099 static inline void setup_tls_args_for_write_callback(
2100     dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
2101     bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
2102     dfsan_origin count_origin) {
2103   // The callback code will expect argument shadow labels in the args TLS,
2104   // and origin labels in the origin args TLS.
2105   // Previously this was done by a trampoline, but we want to remove this:
2106   // https://github.com/llvm/llvm-project/issues/54172
2107   //
2108   // Instead, this code is manually setting up the args TLS data.
2109   //
2110   // The offsets used need to correspond with the instrumentation code,
2111   // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
2112   // DFSanFunction::getShadowForTLSArgument.
2113   // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
2114   // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
2115   //
2116   // Here the arguments are all primitives, but it can be more complex
2117   // to compute offsets for array/aggregate type arguments.
2118   //
2119   // TODO(browneee): Consider a builtin to improve maintainabliity.
2120   // With a builtin, we would provide the argument labels via builtin,
2121   // and the builtin would reuse parts of the instrumentation code to ensure
2122   // that this code and the instrumentation can never be out of sync.
2123   // Note: Currently DFSan instrumentation does not run on this code, so
2124   // the builtin may need to be handled outside DFSan instrumentation.
2125   dfsan_set_arg_tls(0, fd_label);
2126   dfsan_set_arg_tls(1, buf_label);
2127   dfsan_set_arg_tls(2, count_label);
2128   if (origins) {
2129     dfsan_set_arg_origin_tls(0, fd_origin);
2130     dfsan_set_arg_origin_tls(1, buf_origin);
2131     dfsan_set_arg_origin_tls(2, count_origin);
2132   }
2133 }
2134 
2135 SANITIZER_INTERFACE_ATTRIBUTE int
2136 __dfsw_write(int fd, const void *buf, size_t count,
2137              dfsan_label fd_label, dfsan_label buf_label,
2138              dfsan_label count_label, dfsan_label *ret_label) {
2139   if (write_callback_info.write_callback) {
2140     setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
2141                                       0, 0, 0);
2142     write_callback_info.write_callback(fd, buf, count);
2143   }
2144 
2145   *ret_label = 0;
2146   return write(fd, buf, count);
2147 }
2148 
2149 SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
2150     int fd, const void *buf, size_t count, dfsan_label fd_label,
2151     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
2152     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
2153     dfsan_origin *ret_origin) {
2154   if (write_callback_info.write_callback) {
2155     setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
2156                                       fd_origin, buf_origin, count_origin);
2157     write_callback_info.write_callback(fd, buf, count);
2158   }
2159 
2160   *ret_label = 0;
2161   return write(fd, buf, count);
2162 }
2163 }  // namespace __dfsan
2164 
2165 // Type used to extract a dfsan_label with va_arg()
2166 typedef int dfsan_label_va;
2167 
2168 // Formats a chunk either a constant string or a single format directive (e.g.,
2169 // '%.3f').
2170 struct Formatter {
2171   Formatter(char *str_, const char *fmt_, size_t size_)
2172       : str(str_),
2173         str_off(0),
2174         size(size_),
2175         fmt_start(fmt_),
2176         fmt_cur(fmt_),
2177         width(-1),
2178         num_scanned(-1),
2179         skip(false) {}
2180 
2181   int format() {
2182     char *tmp_fmt = build_format_string();
2183     int retval =
2184         snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
2185                  0 /* used only to avoid warnings */);
2186     free(tmp_fmt);
2187     return retval;
2188   }
2189 
2190   template <typename T> int format(T arg) {
2191     char *tmp_fmt = build_format_string();
2192     int retval;
2193     if (width >= 0) {
2194       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
2195                         tmp_fmt, width, arg);
2196     } else {
2197       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
2198                         tmp_fmt, arg);
2199     }
2200     free(tmp_fmt);
2201     return retval;
2202   }
2203 
2204   char *build_format_string() {
2205     size_t fmt_size = fmt_cur - fmt_start + 1;
2206     char *new_fmt = (char *)malloc(fmt_size + 1);
2207     assert(new_fmt);
2208     internal_memcpy(new_fmt, fmt_start, fmt_size);
2209     new_fmt[fmt_size] = '\0';
2210     return new_fmt;
2211   }
2212 
2213   char *str_cur() { return str + str_off; }
2214 
2215   size_t num_written_bytes(int retval) {
2216     if (retval < 0) {
2217       return 0;
2218     }
2219 
2220     size_t num_avail = str_off < size ? size - str_off : 0;
2221     if (num_avail == 0) {
2222       return 0;
2223     }
2224 
2225     size_t num_written = retval;
2226     // A return value of {v,}snprintf of size or more means that the output was
2227     // truncated.
2228     if (num_written >= num_avail) {
2229       num_written -= num_avail;
2230     }
2231 
2232     return num_written;
2233   }
2234 
2235   char *str;
2236   size_t str_off;
2237   size_t size;
2238   const char *fmt_start;
2239   const char *fmt_cur;
2240   int width;
2241   int num_scanned;
2242   bool skip;
2243 };
2244 
2245 // Formats the input and propagates the input labels to the output. The output
2246 // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
2247 // 'ap' are the format string and the list of arguments for formatting. Returns
2248 // the return value vsnprintf would return.
2249 //
2250 // The function tokenizes the format string in chunks representing either a
2251 // constant string or a single format directive (e.g., '%.3f') and formats each
2252 // chunk independently into the output string. This approach allows to figure
2253 // out which bytes of the output string depends on which argument and thus to
2254 // propagate labels more precisely.
2255 //
2256 // WARNING: This implementation does not support conversion specifiers with
2257 // positional arguments.
2258 static int format_buffer(char *str, size_t size, const char *fmt,
2259                          dfsan_label *va_labels, dfsan_label *ret_label,
2260                          dfsan_origin *va_origins, dfsan_origin *ret_origin,
2261                          va_list ap) {
2262   Formatter formatter(str, fmt, size);
2263 
2264   while (*formatter.fmt_cur) {
2265     formatter.fmt_start = formatter.fmt_cur;
2266     formatter.width = -1;
2267     int retval = 0;
2268 
2269     if (*formatter.fmt_cur != '%') {
2270       // Ordinary character. Consume all the characters until a '%' or the end
2271       // of the string.
2272       for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
2273            ++formatter.fmt_cur) {}
2274       retval = formatter.format();
2275       dfsan_set_label(0, formatter.str_cur(),
2276                       formatter.num_written_bytes(retval));
2277     } else {
2278       // Conversion directive. Consume all the characters until a conversion
2279       // specifier or the end of the string.
2280       bool end_fmt = false;
2281       for (; *formatter.fmt_cur && !end_fmt; ) {
2282         switch (*++formatter.fmt_cur) {
2283         case 'd':
2284         case 'i':
2285         case 'o':
2286         case 'u':
2287         case 'x':
2288         case 'X':
2289           switch (*(formatter.fmt_cur - 1)) {
2290           case 'h':
2291             // Also covers the 'hh' case (since the size of the arg is still
2292             // an int).
2293             retval = formatter.format(va_arg(ap, int));
2294             break;
2295           case 'l':
2296             if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
2297                 *(formatter.fmt_cur - 2) == 'l') {
2298               retval = formatter.format(va_arg(ap, long long int));
2299             } else {
2300               retval = formatter.format(va_arg(ap, long int));
2301             }
2302             break;
2303           case 'q':
2304             retval = formatter.format(va_arg(ap, long long int));
2305             break;
2306           case 'j':
2307             retval = formatter.format(va_arg(ap, intmax_t));
2308             break;
2309           case 'z':
2310           case 't':
2311             retval = formatter.format(va_arg(ap, size_t));
2312             break;
2313           default:
2314             retval = formatter.format(va_arg(ap, int));
2315           }
2316           if (va_origins == nullptr)
2317             dfsan_set_label(*va_labels++, formatter.str_cur(),
2318                             formatter.num_written_bytes(retval));
2319           else
2320             dfsan_set_label_origin(*va_labels++, *va_origins++,
2321                                    formatter.str_cur(),
2322                                    formatter.num_written_bytes(retval));
2323           end_fmt = true;
2324           break;
2325 
2326         case 'a':
2327         case 'A':
2328         case 'e':
2329         case 'E':
2330         case 'f':
2331         case 'F':
2332         case 'g':
2333         case 'G':
2334           if (*(formatter.fmt_cur - 1) == 'L') {
2335             retval = formatter.format(va_arg(ap, long double));
2336           } else {
2337             retval = formatter.format(va_arg(ap, double));
2338           }
2339           if (va_origins == nullptr)
2340             dfsan_set_label(*va_labels++, formatter.str_cur(),
2341                             formatter.num_written_bytes(retval));
2342           else
2343             dfsan_set_label_origin(*va_labels++, *va_origins++,
2344                                    formatter.str_cur(),
2345                                    formatter.num_written_bytes(retval));
2346           end_fmt = true;
2347           break;
2348 
2349         case 'c':
2350           retval = formatter.format(va_arg(ap, int));
2351           if (va_origins == nullptr)
2352             dfsan_set_label(*va_labels++, formatter.str_cur(),
2353                             formatter.num_written_bytes(retval));
2354           else
2355             dfsan_set_label_origin(*va_labels++, *va_origins++,
2356                                    formatter.str_cur(),
2357                                    formatter.num_written_bytes(retval));
2358           end_fmt = true;
2359           break;
2360 
2361         case 's': {
2362           char *arg = va_arg(ap, char *);
2363           retval = formatter.format(arg);
2364           if (va_origins) {
2365             va_origins++;
2366             dfsan_mem_origin_transfer(formatter.str_cur(), arg,
2367                                       formatter.num_written_bytes(retval));
2368           }
2369           va_labels++;
2370           dfsan_mem_shadow_transfer(formatter.str_cur(), arg,
2371                                     formatter.num_written_bytes(retval));
2372           end_fmt = true;
2373           break;
2374         }
2375 
2376         case 'p':
2377           retval = formatter.format(va_arg(ap, void *));
2378           if (va_origins == nullptr)
2379             dfsan_set_label(*va_labels++, formatter.str_cur(),
2380                             formatter.num_written_bytes(retval));
2381           else
2382             dfsan_set_label_origin(*va_labels++, *va_origins++,
2383                                    formatter.str_cur(),
2384                                    formatter.num_written_bytes(retval));
2385           end_fmt = true;
2386           break;
2387 
2388         case 'n': {
2389           int *ptr = va_arg(ap, int *);
2390           *ptr = (int)formatter.str_off;
2391           va_labels++;
2392           if (va_origins)
2393             va_origins++;
2394           dfsan_set_label(0, ptr, sizeof(ptr));
2395           end_fmt = true;
2396           break;
2397         }
2398 
2399         case '%':
2400           retval = formatter.format();
2401           dfsan_set_label(0, formatter.str_cur(),
2402                           formatter.num_written_bytes(retval));
2403           end_fmt = true;
2404           break;
2405 
2406         case '*':
2407           formatter.width = va_arg(ap, int);
2408           va_labels++;
2409           if (va_origins)
2410             va_origins++;
2411           break;
2412 
2413         default:
2414           break;
2415         }
2416       }
2417     }
2418 
2419     if (retval < 0) {
2420       return retval;
2421     }
2422 
2423     formatter.fmt_cur++;
2424     formatter.str_off += retval;
2425   }
2426 
2427   *ret_label = 0;
2428   if (ret_origin)
2429     *ret_origin = 0;
2430 
2431   // Number of bytes written in total.
2432   return formatter.str_off;
2433 }
2434 
2435 // Scans a chunk either a constant string or a single format directive (e.g.,
2436 // '%.3f').
2437 struct Scanner {
2438   Scanner(char *str_, const char *fmt_, size_t size_)
2439       : str(str_),
2440         str_off(0),
2441         size(size_),
2442         fmt_start(fmt_),
2443         fmt_cur(fmt_),
2444         width(-1),
2445         num_scanned(0),
2446         skip(false) {}
2447 
2448   // Consumes a chunk of ordinary characters.
2449   // Returns number of matching ordinary characters.
2450   // Returns -1 if the match failed.
2451   // In format strings, a space will match multiple spaces.
2452   int check_match_ordinary() {
2453     char *tmp_fmt = build_format_string_with_n();
2454     int read_count = -1;
2455     sscanf(str + str_off, tmp_fmt, &read_count);
2456     free(tmp_fmt);
2457     if (read_count > 0) {
2458       str_off += read_count;
2459     }
2460     return read_count;
2461   }
2462 
2463   int scan() {
2464     char *tmp_fmt = build_format_string_with_n();
2465     int read_count = 0;
2466     int retval = sscanf(str + str_off, tmp_fmt, &read_count);
2467     free(tmp_fmt);
2468     if (retval > 0) {
2469       num_scanned += retval;
2470     }
2471     return read_count;
2472   }
2473 
2474   template <typename T>
2475   int scan(T arg) {
2476     char *tmp_fmt = build_format_string_with_n();
2477     int read_count = 0;
2478     int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count);
2479     free(tmp_fmt);
2480     if (retval > 0) {
2481       num_scanned += retval;
2482     }
2483     return read_count;
2484   }
2485 
2486   // Adds %n onto current format string to measure length.
2487   char *build_format_string_with_n() {
2488     size_t fmt_size = fmt_cur - fmt_start + 1;
2489     // +2 for %n, +1 for \0
2490     char *new_fmt = (char *)malloc(fmt_size + 2 + 1);
2491     assert(new_fmt);
2492     internal_memcpy(new_fmt, fmt_start, fmt_size);
2493     new_fmt[fmt_size] = '%';
2494     new_fmt[fmt_size + 1] = 'n';
2495     new_fmt[fmt_size + 2] = '\0';
2496     return new_fmt;
2497   }
2498 
2499   char *str_cur() { return str + str_off; }
2500 
2501   size_t num_written_bytes(int retval) {
2502     if (retval < 0) {
2503       return 0;
2504     }
2505 
2506     size_t num_avail = str_off < size ? size - str_off : 0;
2507     if (num_avail == 0) {
2508       return 0;
2509     }
2510 
2511     size_t num_written = retval;
2512     // A return value of {v,}snprintf of size or more means that the output was
2513     // truncated.
2514     if (num_written >= num_avail) {
2515       num_written -= num_avail;
2516     }
2517 
2518     return num_written;
2519   }
2520 
2521   char *str;
2522   size_t str_off;
2523   size_t size;
2524   const char *fmt_start;
2525   const char *fmt_cur;
2526   int width;
2527   int num_scanned;
2528   bool skip;
2529 };
2530 
2531 // This function is an inverse of format_buffer: we take the input buffer,
2532 // scan it in search for format strings and store the results in the varargs.
2533 // The labels are propagated from the input buffer to the varargs.
2534 static int scan_buffer(char *str, size_t size, const char *fmt,
2535                        dfsan_label *va_labels, dfsan_label *ret_label,
2536                        dfsan_origin *str_origin, dfsan_origin *ret_origin,
2537                        va_list ap) {
2538   Scanner scanner(str, fmt, size);
2539   while (*scanner.fmt_cur) {
2540     scanner.fmt_start = scanner.fmt_cur;
2541     scanner.width = -1;
2542     scanner.skip = false;
2543     int read_count = 0;
2544     void *dst_ptr = 0;
2545     size_t write_size = 0;
2546     if (*scanner.fmt_cur != '%') {
2547       // Ordinary character and spaces.
2548       // Consume all the characters until a '%' or the end of the string.
2549       for (; *(scanner.fmt_cur + 1) && *(scanner.fmt_cur + 1) != '%';
2550            ++scanner.fmt_cur) {
2551       }
2552       if (scanner.check_match_ordinary() < 0) {
2553         // The ordinary characters did not match.
2554         break;
2555       }
2556     } else {
2557       // Conversion directive. Consume all the characters until a conversion
2558       // specifier or the end of the string.
2559       bool end_fmt = false;
2560       for (; *scanner.fmt_cur && !end_fmt;) {
2561         switch (*++scanner.fmt_cur) {
2562           case 'd':
2563           case 'i':
2564           case 'o':
2565           case 'u':
2566           case 'x':
2567           case 'X':
2568             if (scanner.skip) {
2569               read_count = scanner.scan();
2570             } else {
2571               switch (*(scanner.fmt_cur - 1)) {
2572                 case 'h':
2573                   // Also covers the 'hh' case (since the size of the arg is
2574                   // still an int).
2575                   dst_ptr = va_arg(ap, int *);
2576                   read_count = scanner.scan((int *)dst_ptr);
2577                   write_size = sizeof(int);
2578                   break;
2579                 case 'l':
2580                   if (scanner.fmt_cur - scanner.fmt_start >= 2 &&
2581                       *(scanner.fmt_cur - 2) == 'l') {
2582                     dst_ptr = va_arg(ap, long long int *);
2583                     read_count = scanner.scan((long long int *)dst_ptr);
2584                     write_size = sizeof(long long int);
2585                   } else {
2586                     dst_ptr = va_arg(ap, long int *);
2587                     read_count = scanner.scan((long int *)dst_ptr);
2588                     write_size = sizeof(long int);
2589                   }
2590                   break;
2591                 case 'q':
2592                   dst_ptr = va_arg(ap, long long int *);
2593                   read_count = scanner.scan((long long int *)dst_ptr);
2594                   write_size = sizeof(long long int);
2595                   break;
2596                 case 'j':
2597                   dst_ptr = va_arg(ap, intmax_t *);
2598                   read_count = scanner.scan((intmax_t *)dst_ptr);
2599                   write_size = sizeof(intmax_t);
2600                   break;
2601                 case 'z':
2602                 case 't':
2603                   dst_ptr = va_arg(ap, size_t *);
2604                   read_count = scanner.scan((size_t *)dst_ptr);
2605                   write_size = sizeof(size_t);
2606                   break;
2607                 default:
2608                   dst_ptr = va_arg(ap, int *);
2609                   read_count = scanner.scan((int *)dst_ptr);
2610                   write_size = sizeof(int);
2611               }
2612               // get the label associated with the string at the corresponding
2613               // place
2614               dfsan_label l = dfsan_read_label(
2615                   scanner.str_cur(), scanner.num_written_bytes(read_count));
2616               dfsan_set_label(l, dst_ptr, write_size);
2617               if (str_origin != nullptr) {
2618                 dfsan_set_label(l, dst_ptr, write_size);
2619                 size_t scan_count = scanner.num_written_bytes(read_count);
2620                 size_t size = scan_count > write_size ? write_size : scan_count;
2621                 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
2622               }
2623             }
2624             end_fmt = true;
2625 
2626             break;
2627 
2628           case 'a':
2629           case 'A':
2630           case 'e':
2631           case 'E':
2632           case 'f':
2633           case 'F':
2634           case 'g':
2635           case 'G':
2636             if (scanner.skip) {
2637               read_count = scanner.scan();
2638             } else {
2639               if (*(scanner.fmt_cur - 1) == 'L') {
2640                 dst_ptr = va_arg(ap, long double *);
2641                 read_count = scanner.scan((long double *)dst_ptr);
2642                 write_size = sizeof(long double);
2643               } else if (*(scanner.fmt_cur - 1) == 'l') {
2644                 dst_ptr = va_arg(ap, double *);
2645                 read_count = scanner.scan((double *)dst_ptr);
2646                 write_size = sizeof(double);
2647               } else {
2648                 dst_ptr = va_arg(ap, float *);
2649                 read_count = scanner.scan((float *)dst_ptr);
2650                 write_size = sizeof(float);
2651               }
2652               dfsan_label l = dfsan_read_label(
2653                   scanner.str_cur(), scanner.num_written_bytes(read_count));
2654               dfsan_set_label(l, dst_ptr, write_size);
2655               if (str_origin != nullptr) {
2656                 dfsan_set_label(l, dst_ptr, write_size);
2657                 size_t scan_count = scanner.num_written_bytes(read_count);
2658                 size_t size = scan_count > write_size ? write_size : scan_count;
2659                 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
2660               }
2661             }
2662             end_fmt = true;
2663             break;
2664 
2665           case 'c':
2666             if (scanner.skip) {
2667               read_count = scanner.scan();
2668             } else {
2669               dst_ptr = va_arg(ap, char *);
2670               read_count = scanner.scan((char *)dst_ptr);
2671               write_size = sizeof(char);
2672               dfsan_label l = dfsan_read_label(
2673                   scanner.str_cur(), scanner.num_written_bytes(read_count));
2674               dfsan_set_label(l, dst_ptr, write_size);
2675               if (str_origin != nullptr) {
2676                 size_t scan_count = scanner.num_written_bytes(read_count);
2677                 size_t size = scan_count > write_size ? write_size : scan_count;
2678                 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
2679               }
2680             }
2681             end_fmt = true;
2682             break;
2683 
2684           case 's': {
2685             if (scanner.skip) {
2686               read_count = scanner.scan();
2687             } else {
2688               dst_ptr = va_arg(ap, char *);
2689               read_count = scanner.scan((char *)dst_ptr);
2690               if (1 == read_count) {
2691                 // special case: we have parsed a single string and we need to
2692                 // update read_count with the string size
2693                 read_count = strlen((char *)dst_ptr);
2694               }
2695               if (str_origin)
2696                 dfsan_mem_origin_transfer(
2697                     dst_ptr, scanner.str_cur(),
2698                     scanner.num_written_bytes(read_count));
2699               va_labels++;
2700               dfsan_mem_shadow_transfer(dst_ptr, scanner.str_cur(),
2701                                         scanner.num_written_bytes(read_count));
2702             }
2703             end_fmt = true;
2704             break;
2705           }
2706 
2707           case 'p':
2708             if (scanner.skip) {
2709               read_count = scanner.scan();
2710             } else {
2711               dst_ptr = va_arg(ap, void *);
2712               read_count =
2713                   scanner.scan((int *)dst_ptr);  // note: changing void* to int*
2714                                                  // since we need to call sizeof
2715               write_size = sizeof(int);
2716 
2717               dfsan_label l = dfsan_read_label(
2718                   scanner.str_cur(), scanner.num_written_bytes(read_count));
2719               dfsan_set_label(l, dst_ptr, write_size);
2720               if (str_origin != nullptr) {
2721                 dfsan_set_label(l, dst_ptr, write_size);
2722                 size_t scan_count = scanner.num_written_bytes(read_count);
2723                 size_t size = scan_count > write_size ? write_size : scan_count;
2724                 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
2725               }
2726             }
2727             end_fmt = true;
2728             break;
2729 
2730           case 'n': {
2731             if (!scanner.skip) {
2732               int *ptr = va_arg(ap, int *);
2733               *ptr = (int)scanner.str_off;
2734               *va_labels++ = 0;
2735               dfsan_set_label(0, ptr, sizeof(*ptr));
2736               if (str_origin != nullptr)
2737                 *str_origin++ = 0;
2738             }
2739             end_fmt = true;
2740             break;
2741           }
2742 
2743           case '%':
2744             read_count = scanner.scan();
2745             end_fmt = true;
2746             break;
2747 
2748           case '*':
2749             scanner.skip = true;
2750             break;
2751 
2752           default:
2753             break;
2754         }
2755       }
2756     }
2757 
2758     if (read_count < 0) {
2759       // There was an error.
2760       return read_count;
2761     }
2762 
2763     scanner.fmt_cur++;
2764     scanner.str_off += read_count;
2765   }
2766 
2767   (void)va_labels; // Silence unused-but-set-parameter warning
2768   *ret_label = 0;
2769   if (ret_origin)
2770     *ret_origin = 0;
2771 
2772   // Number of items scanned in total.
2773   return scanner.num_scanned;
2774 }
2775 
2776 extern "C" {
2777 SANITIZER_INTERFACE_ATTRIBUTE
2778 int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
2779                    dfsan_label format_label, dfsan_label *va_labels,
2780                    dfsan_label *ret_label, ...) {
2781   va_list ap;
2782   va_start(ap, ret_label);
2783 
2784   int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, nullptr,
2785                           nullptr, ap);
2786   va_end(ap);
2787   return ret;
2788 }
2789 
2790 SANITIZER_INTERFACE_ATTRIBUTE
2791 int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
2792                    dfsan_label format_label, dfsan_label *va_labels,
2793                    dfsan_label *ret_label, dfsan_origin str_origin,
2794                    dfsan_origin format_origin, dfsan_origin *va_origins,
2795                    dfsan_origin *ret_origin, ...) {
2796   va_list ap;
2797   va_start(ap, ret_origin);
2798   int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label,
2799                           va_origins, ret_origin, ap);
2800   va_end(ap);
2801   return ret;
2802 }
2803 
2804 SANITIZER_INTERFACE_ATTRIBUTE
2805 int __dfsw_snprintf(char *str, size_t size, const char *format,
2806                     dfsan_label str_label, dfsan_label size_label,
2807                     dfsan_label format_label, dfsan_label *va_labels,
2808                     dfsan_label *ret_label, ...) {
2809   va_list ap;
2810   va_start(ap, ret_label);
2811   int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
2812                           nullptr, ap);
2813   va_end(ap);
2814   return ret;
2815 }
2816 
2817 SANITIZER_INTERFACE_ATTRIBUTE
2818 int __dfso_snprintf(char *str, size_t size, const char *format,
2819                     dfsan_label str_label, dfsan_label size_label,
2820                     dfsan_label format_label, dfsan_label *va_labels,
2821                     dfsan_label *ret_label, dfsan_origin str_origin,
2822                     dfsan_origin size_origin, dfsan_origin format_origin,
2823                     dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
2824   va_list ap;
2825   va_start(ap, ret_origin);
2826   int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
2827                           ret_origin, ap);
2828   va_end(ap);
2829   return ret;
2830 }
2831 
2832 SANITIZER_INTERFACE_ATTRIBUTE
2833 int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label,
2834                   dfsan_label format_label, dfsan_label *va_labels,
2835                   dfsan_label *ret_label, ...) {
2836   va_list ap;
2837   va_start(ap, ret_label);
2838   int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
2839                         nullptr, ap);
2840   va_end(ap);
2841   return ret;
2842 }
2843 
2844 SANITIZER_INTERFACE_ATTRIBUTE
2845 int __dfso_sscanf(char *str, const char *format, dfsan_label str_label,
2846                   dfsan_label format_label, dfsan_label *va_labels,
2847                   dfsan_label *ret_label, dfsan_origin str_origin,
2848                   dfsan_origin format_origin, dfsan_origin *va_origins,
2849                   dfsan_origin *ret_origin, ...) {
2850   va_list ap;
2851   va_start(ap, ret_origin);
2852   int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,
2853                         ret_origin, ap);
2854   va_end(ap);
2855   return ret;
2856 }
2857 
2858 WRAPPER_ALIAS(__isoc99_sscanf, sscanf)
2859 WRAPPER_ALIAS(__isoc23_sscanf, sscanf)
2860 
2861 static void BeforeFork() {
2862   VReport(2, "BeforeFork tid: %llu\n", GetTid());
2863   StackDepotLockBeforeFork();
2864   ChainedOriginDepotLockBeforeFork();
2865 }
2866 
2867 static void AfterFork(bool fork_child) {
2868   ChainedOriginDepotUnlockAfterFork(fork_child);
2869   StackDepotUnlockAfterFork(fork_child);
2870   VReport(2, "AfterFork tid: %llu\n", GetTid());
2871 }
2872 
2873 SANITIZER_INTERFACE_ATTRIBUTE
2874 pid_t __dfsw_fork(dfsan_label *ret_label) {
2875   pid_t pid = fork();
2876   *ret_label = 0;
2877   return pid;
2878 }
2879 
2880 SANITIZER_INTERFACE_ATTRIBUTE
2881 pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
2882   BeforeFork();
2883   pid_t pid = __dfsw_fork(ret_label);
2884   AfterFork(/* fork_child= */ pid == 0);
2885   return pid;
2886 }
2887 
2888 // Default empty implementations (weak). Users should redefine them.
2889 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
2890 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
2891                              u32 *) {}
2892 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,
2893                              const uptr *end) {}
2894 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
2895 
2896 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
2897 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
2898 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
2899 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
2900 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
2901 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
2902                              void) {}
2903 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
2904                              void) {}
2905 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
2906                              void) {}
2907 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
2908                              void) {}
2909 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
2910 }  // extern "C"
2911