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