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