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