1 //===-- dfsan_custom.cpp --------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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>
29 #include <sys/epoll.h>
30 #include <sys/resource.h>
31 #include <sys/select.h>
32 #include <sys/socket.h>
35 #include <sys/types.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, ...) \
55 #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
56 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
58 #define WRAPPER_ALIAS(fun, real) \
59 SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \
60 SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);
62 // Async-safe, non-reentrant spin lock.
64 class SignalSpinLocker
{
69 pthread_sigmask(SIG_SETMASK
, &all_set
, &saved_thread_mask_
);
73 sigactions_mu
.Unlock();
74 pthread_sigmask(SIG_SETMASK
, &saved_thread_mask_
, nullptr);
78 static StaticSpinMutex sigactions_mu
;
79 sigset_t saved_thread_mask_
;
81 SignalSpinLocker(const SignalSpinLocker
&) = delete;
82 SignalSpinLocker
&operator=(const SignalSpinLocker
&) = delete;
86 StaticSpinMutex
SignalSpinLocker::sigactions_mu
;
89 SANITIZER_INTERFACE_ATTRIBUTE
int
90 __dfsw_stat(const char *path
, struct stat
*buf
, dfsan_label path_label
,
91 dfsan_label buf_label
, dfsan_label
*ret_label
) {
92 int ret
= stat(path
, buf
);
94 dfsan_set_label(0, buf
, sizeof(struct stat
));
99 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_stat(
100 const char *path
, struct stat
*buf
, dfsan_label path_label
,
101 dfsan_label buf_label
, dfsan_label
*ret_label
, dfsan_origin path_origin
,
102 dfsan_origin buf_origin
, dfsan_origin
*ret_origin
) {
103 int ret
= __dfsw_stat(path
, buf
, path_label
, buf_label
, ret_label
);
107 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_fstat(int fd
, struct stat
*buf
,
108 dfsan_label fd_label
,
109 dfsan_label buf_label
,
110 dfsan_label
*ret_label
) {
111 int ret
= fstat(fd
, buf
);
113 dfsan_set_label(0, buf
, sizeof(struct stat
));
118 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_fstat(
119 int fd
, struct stat
*buf
, dfsan_label fd_label
, dfsan_label buf_label
,
120 dfsan_label
*ret_label
, dfsan_origin fd_origin
, dfsan_origin buf_origin
,
121 dfsan_origin
*ret_origin
) {
122 int ret
= __dfsw_fstat(fd
, buf
, fd_label
, buf_label
, ret_label
);
126 static char *dfsan_strchr_with_label(const char *s
, int c
, size_t *bytes_read
,
127 dfsan_label s_label
, dfsan_label c_label
,
128 dfsan_label
*ret_label
) {
129 char *match_pos
= nullptr;
130 for (size_t i
= 0;; ++i
) {
131 if (s
[i
] == c
|| s
[i
] == 0) {
132 // If s[i] is the \0 at the end of the string, and \0 is not the
133 // character we are searching for, then return null.
135 match_pos
= s
[i
] == 0 && c
!= 0 ? nullptr : const_cast<char *>(s
+ i
);
139 if (flags().strict_data_dependencies
)
140 *ret_label
= s_label
;
142 *ret_label
= dfsan_union(dfsan_read_label(s
, *bytes_read
),
143 dfsan_union(s_label
, c_label
));
147 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strchr(const char *s
, int c
,
150 dfsan_label
*ret_label
) {
152 return dfsan_strchr_with_label(s
, c
, &bytes_read
, s_label
, c_label
,
156 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strchr(
157 const char *s
, int c
, dfsan_label s_label
, dfsan_label c_label
,
158 dfsan_label
*ret_label
, dfsan_origin s_origin
, dfsan_origin c_origin
,
159 dfsan_origin
*ret_origin
) {
162 dfsan_strchr_with_label(s
, c
, &bytes_read
, s_label
, c_label
, ret_label
);
163 if (flags().strict_data_dependencies
) {
164 *ret_origin
= s_origin
;
165 } else if (*ret_label
) {
166 dfsan_origin o
= dfsan_read_origin_of_first_taint(s
, bytes_read
);
167 *ret_origin
= o
? o
: (s_label
? s_origin
: c_origin
);
172 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strpbrk(const char *s
,
175 dfsan_label accept_label
,
176 dfsan_label
*ret_label
) {
177 const char *ret
= strpbrk(s
, accept
);
178 if (flags().strict_data_dependencies
) {
179 *ret_label
= ret
? s_label
: 0;
181 size_t s_bytes_read
= (ret
? ret
- s
: strlen(s
)) + 1;
183 dfsan_union(dfsan_read_label(s
, s_bytes_read
),
184 dfsan_union(dfsan_read_label(accept
, strlen(accept
) + 1),
185 dfsan_union(s_label
, accept_label
)));
187 return const_cast<char *>(ret
);
190 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strpbrk(
191 const char *s
, const char *accept
, dfsan_label s_label
,
192 dfsan_label accept_label
, dfsan_label
*ret_label
, dfsan_origin s_origin
,
193 dfsan_origin accept_origin
, dfsan_origin
*ret_origin
) {
194 const char *ret
= __dfsw_strpbrk(s
, accept
, s_label
, accept_label
, ret_label
);
195 if (flags().strict_data_dependencies
) {
197 *ret_origin
= s_origin
;
200 size_t s_bytes_read
= (ret
? ret
- s
: strlen(s
)) + 1;
201 dfsan_origin o
= dfsan_read_origin_of_first_taint(s
, s_bytes_read
);
205 o
= dfsan_read_origin_of_first_taint(accept
, strlen(accept
) + 1);
206 *ret_origin
= o
? o
: (s_label
? s_origin
: accept_origin
);
210 return const_cast<char *>(ret
);
213 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strsep(char **s
, const char *delim
,
215 dfsan_label delim_label
,
216 dfsan_label
*ret_label
) {
217 dfsan_label base_label
= dfsan_read_label(s
, sizeof(*s
));
219 char *res
= strsep(s
, delim
);
221 char *token_start
= res
;
222 int token_length
= strlen(res
);
223 // the delimiter byte has been set to NULL
224 dfsan_set_label(0, token_start
+ token_length
, 1);
227 if (flags().strict_data_dependencies
) {
228 *ret_label
= res
? base_label
: 0;
230 size_t s_bytes_read
= (res
? strlen(res
) : strlen(base
)) + 1;
231 *ret_label
= dfsan_union(
232 dfsan_union(base_label
, dfsan_read_label(base
, sizeof(s_bytes_read
))),
233 dfsan_union(dfsan_read_label(delim
, strlen(delim
) + 1),
234 dfsan_union(s_label
, delim_label
)));
240 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strsep(
241 char **s
, const char *delim
, dfsan_label s_label
, dfsan_label delim_label
,
242 dfsan_label
*ret_label
, dfsan_origin s_origin
, dfsan_origin delim_origin
,
243 dfsan_origin
*ret_origin
) {
244 dfsan_origin base_origin
= dfsan_read_origin_of_first_taint(s
, sizeof(*s
));
245 char *res
= __dfsw_strsep(s
, delim
, s_label
, delim_label
, ret_label
);
246 if (flags().strict_data_dependencies
) {
248 *ret_origin
= base_origin
;
252 *ret_origin
= base_origin
;
255 dfsan_read_origin_of_first_taint(delim
, strlen(delim
) + 1);
256 *ret_origin
= o
? o
: (s_label
? s_origin
: delim_origin
);
264 static int dfsan_memcmp_bcmp(const void *s1
, const void *s2
, size_t n
,
265 size_t *bytes_read
) {
266 const char *cs1
= (const char *) s1
, *cs2
= (const char *) s2
;
267 for (size_t i
= 0; i
!= n
; ++i
) {
268 if (cs1
[i
] != cs2
[i
]) {
270 return cs1
[i
] - cs2
[i
];
277 static dfsan_label
dfsan_get_memcmp_label(const void *s1
, const void *s2
,
279 if (flags().strict_data_dependencies
)
281 return dfsan_union(dfsan_read_label(s1
, pos
), dfsan_read_label(s2
, pos
));
284 static void dfsan_get_memcmp_origin(const void *s1
, const void *s2
, size_t pos
,
285 dfsan_label
*ret_label
,
286 dfsan_origin
*ret_origin
) {
287 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, pos
);
290 dfsan_origin o
= dfsan_read_origin_of_first_taint(s1
, pos
);
291 *ret_origin
= o
? o
: dfsan_read_origin_of_first_taint(s2
, pos
);
294 static int dfsan_memcmp_bcmp_label(const void *s1
, const void *s2
, size_t n
,
295 dfsan_label
*ret_label
) {
297 int r
= dfsan_memcmp_bcmp(s1
, s2
, n
, &bytes_read
);
298 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, bytes_read
);
302 static int dfsan_memcmp_bcmp_origin(const void *s1
, const void *s2
, size_t n
,
303 dfsan_label
*ret_label
,
304 dfsan_origin
*ret_origin
) {
306 int r
= dfsan_memcmp_bcmp(s1
, s2
, n
, &bytes_read
);
307 dfsan_get_memcmp_origin(s1
, s2
, bytes_read
, ret_label
, ret_origin
);
311 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp
, uptr caller_pc
,
312 const void *s1
, const void *s2
, size_t n
,
313 dfsan_label s1_label
, dfsan_label s2_label
,
316 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp
, uptr caller_pc
,
317 const void *s1
, const void *s2
, size_t n
,
318 dfsan_label s1_label
, dfsan_label s2_label
,
319 dfsan_label n_label
, dfsan_origin s1_origin
,
320 dfsan_origin s2_origin
, dfsan_origin n_origin
)
322 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_memcmp(const void *s1
, const void *s2
,
323 size_t n
, dfsan_label s1_label
,
324 dfsan_label s2_label
,
326 dfsan_label
*ret_label
) {
327 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp
, GET_CALLER_PC(), s1
, s2
, n
,
328 s1_label
, s2_label
, n_label
);
329 return dfsan_memcmp_bcmp_label(s1
, s2
, n
, ret_label
);
332 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_memcmp(
333 const void *s1
, const void *s2
, size_t n
, dfsan_label s1_label
,
334 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
,
335 dfsan_origin s1_origin
, dfsan_origin s2_origin
, dfsan_origin n_origin
,
336 dfsan_origin
*ret_origin
) {
337 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp
, GET_CALLER_PC(), s1
,
338 s2
, n
, s1_label
, s2_label
, n_label
, s1_origin
,
339 s2_origin
, n_origin
);
340 return dfsan_memcmp_bcmp_origin(s1
, s2
, n
, ret_label
, ret_origin
);
343 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_bcmp(const void *s1
, const void *s2
,
344 size_t n
, dfsan_label s1_label
,
345 dfsan_label s2_label
,
347 dfsan_label
*ret_label
) {
348 return dfsan_memcmp_bcmp_label(s1
, s2
, n
, ret_label
);
351 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_bcmp(
352 const void *s1
, const void *s2
, size_t n
, dfsan_label s1_label
,
353 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
,
354 dfsan_origin s1_origin
, dfsan_origin s2_origin
, dfsan_origin n_origin
,
355 dfsan_origin
*ret_origin
) {
356 return dfsan_memcmp_bcmp_origin(s1
, s2
, n
, ret_label
, ret_origin
);
359 // When n == 0, compare strings without byte limit.
360 // When n > 0, compare the first (at most) n bytes of s1 and s2.
361 static int dfsan_strncmp(const char *s1
, const char *s2
, size_t n
,
362 size_t *bytes_read
) {
363 for (size_t i
= 0;; ++i
) {
364 if (s1
[i
] != s2
[i
] || s1
[i
] == 0 || s2
[i
] == 0 || (n
> 0 && i
== n
- 1)) {
366 return s1
[i
] - s2
[i
];
371 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp
, uptr caller_pc
,
372 const char *s1
, const char *s2
,
373 dfsan_label s1_label
, dfsan_label s2_label
)
375 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp
, uptr caller_pc
,
376 const char *s1
, const char *s2
,
377 dfsan_label s1_label
, dfsan_label s2_label
,
378 dfsan_origin s1_origin
, dfsan_origin s2_origin
)
380 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_strcmp(const char *s1
, const char *s2
,
381 dfsan_label s1_label
,
382 dfsan_label s2_label
,
383 dfsan_label
*ret_label
) {
384 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp
, GET_CALLER_PC(), s1
, s2
,
387 int r
= dfsan_strncmp(s1
, s2
, 0, &bytes_read
);
388 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, bytes_read
);
392 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_strcmp(
393 const char *s1
, const char *s2
, dfsan_label s1_label
, dfsan_label s2_label
,
394 dfsan_label
*ret_label
, dfsan_origin s1_origin
, dfsan_origin s2_origin
,
395 dfsan_origin
*ret_origin
) {
396 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp
, GET_CALLER_PC(), s1
,
397 s2
, s1_label
, s2_label
, s1_origin
, s2_origin
);
399 int r
= dfsan_strncmp(s1
, s2
, 0, &bytes_read
);
400 dfsan_get_memcmp_origin(s1
, s2
, bytes_read
, ret_label
, ret_origin
);
404 // When n == 0, compare strings without byte limit.
405 // When n > 0, compare the first (at most) n bytes of s1 and s2.
406 static int dfsan_strncasecmp(const char *s1
, const char *s2
, size_t n
,
407 size_t *bytes_read
) {
408 for (size_t i
= 0;; ++i
) {
409 char s1_lower
= tolower(s1
[i
]);
410 char s2_lower
= tolower(s2
[i
]);
412 if (s1_lower
!= s2_lower
|| s1
[i
] == 0 || s2
[i
] == 0 ||
413 (n
> 0 && i
== n
- 1)) {
415 return s1_lower
- s2_lower
;
420 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_strcasecmp(const char *s1
,
422 dfsan_label s1_label
,
423 dfsan_label s2_label
,
424 dfsan_label
*ret_label
) {
426 int r
= dfsan_strncasecmp(s1
, s2
, 0, &bytes_read
);
427 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, bytes_read
);
431 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_strcasecmp(
432 const char *s1
, const char *s2
, dfsan_label s1_label
, dfsan_label s2_label
,
433 dfsan_label
*ret_label
, dfsan_origin s1_origin
, dfsan_origin s2_origin
,
434 dfsan_origin
*ret_origin
) {
436 int r
= dfsan_strncasecmp(s1
, s2
, 0, &bytes_read
);
437 dfsan_get_memcmp_origin(s1
, s2
, bytes_read
, ret_label
, ret_origin
);
441 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp
, uptr caller_pc
,
442 const char *s1
, const char *s2
, size_t n
,
443 dfsan_label s1_label
, dfsan_label s2_label
,
446 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp
, uptr caller_pc
,
447 const char *s1
, const char *s2
, size_t n
,
448 dfsan_label s1_label
, dfsan_label s2_label
,
449 dfsan_label n_label
, dfsan_origin s1_origin
,
450 dfsan_origin s2_origin
, dfsan_origin n_origin
)
452 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_strncmp(const char *s1
, const char *s2
,
453 size_t n
, dfsan_label s1_label
,
454 dfsan_label s2_label
,
456 dfsan_label
*ret_label
) {
462 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp
, GET_CALLER_PC(), s1
, s2
,
463 n
, s1_label
, s2_label
, n_label
);
466 int r
= dfsan_strncmp(s1
, s2
, n
, &bytes_read
);
467 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, bytes_read
);
471 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_strncmp(
472 const char *s1
, const char *s2
, size_t n
, dfsan_label s1_label
,
473 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
,
474 dfsan_origin s1_origin
, dfsan_origin s2_origin
, dfsan_origin n_origin
,
475 dfsan_origin
*ret_origin
) {
481 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp
, GET_CALLER_PC(),
482 s1
, s2
, n
, s1_label
, s2_label
, n_label
, s1_origin
,
483 s2_origin
, n_origin
);
486 int r
= dfsan_strncmp(s1
, s2
, n
, &bytes_read
);
487 dfsan_get_memcmp_origin(s1
, s2
, bytes_read
, ret_label
, ret_origin
);
491 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_strncasecmp(
492 const char *s1
, const char *s2
, size_t n
, dfsan_label s1_label
,
493 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
) {
500 int r
= dfsan_strncasecmp(s1
, s2
, n
, &bytes_read
);
501 *ret_label
= dfsan_get_memcmp_label(s1
, s2
, bytes_read
);
505 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_strncasecmp(
506 const char *s1
, const char *s2
, size_t n
, dfsan_label s1_label
,
507 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
,
508 dfsan_origin s1_origin
, dfsan_origin s2_origin
, dfsan_origin n_origin
,
509 dfsan_origin
*ret_origin
) {
516 int r
= dfsan_strncasecmp(s1
, s2
, n
, &bytes_read
);
517 dfsan_get_memcmp_origin(s1
, s2
, bytes_read
, ret_label
, ret_origin
);
522 SANITIZER_INTERFACE_ATTRIBUTE
size_t
523 __dfsw_strlen(const char *s
, dfsan_label s_label
, dfsan_label
*ret_label
) {
524 size_t ret
= strlen(s
);
525 if (flags().strict_data_dependencies
) {
528 *ret_label
= dfsan_read_label(s
, ret
+ 1);
533 SANITIZER_INTERFACE_ATTRIBUTE
size_t __dfso_strlen(const char *s
,
535 dfsan_label
*ret_label
,
536 dfsan_origin s_origin
,
537 dfsan_origin
*ret_origin
) {
538 size_t ret
= __dfsw_strlen(s
, s_label
, ret_label
);
539 if (!flags().strict_data_dependencies
)
540 *ret_origin
= dfsan_read_origin_of_first_taint(s
, ret
+ 1);
544 SANITIZER_INTERFACE_ATTRIBUTE
size_t __dfsw_strnlen(const char *s
,
547 dfsan_label maxlen_label
,
548 dfsan_label
*ret_label
) {
549 size_t ret
= strnlen(s
, maxlen
);
550 if (flags().strict_data_dependencies
) {
553 size_t full_len
= strlen(s
);
554 size_t covered_len
= maxlen
> (full_len
+ 1) ? (full_len
+ 1) : maxlen
;
555 *ret_label
= dfsan_union(maxlen_label
, dfsan_read_label(s
, covered_len
));
560 SANITIZER_INTERFACE_ATTRIBUTE
size_t __dfso_strnlen(
561 const char *s
, size_t maxlen
, dfsan_label s_label
, dfsan_label maxlen_label
,
562 dfsan_label
*ret_label
, dfsan_origin s_origin
, dfsan_origin maxlen_origin
,
563 dfsan_origin
*ret_origin
) {
564 size_t ret
= __dfsw_strnlen(s
, maxlen
, s_label
, maxlen_label
, ret_label
);
565 if (!flags().strict_data_dependencies
) {
566 size_t full_len
= strlen(s
);
567 size_t covered_len
= maxlen
> (full_len
+ 1) ? (full_len
+ 1) : maxlen
;
568 dfsan_origin o
= dfsan_read_origin_of_first_taint(s
, covered_len
);
569 *ret_origin
= o
? o
: maxlen_origin
;
574 static void *dfsan_memmove(void *dest
, const void *src
, size_t n
) {
575 dfsan_label
*sdest
= shadow_for(dest
);
576 const dfsan_label
*ssrc
= shadow_for(src
);
577 internal_memmove((void *)sdest
, (const void *)ssrc
, n
* sizeof(dfsan_label
));
578 return internal_memmove(dest
, src
, n
);
581 static void *dfsan_memmove_with_origin(void *dest
, const void *src
, size_t n
) {
582 dfsan_mem_origin_transfer(dest
, src
, n
);
583 return dfsan_memmove(dest
, src
, n
);
586 static void *dfsan_memcpy(void *dest
, const void *src
, size_t n
) {
587 dfsan_mem_shadow_transfer(dest
, src
, n
);
588 return internal_memcpy(dest
, src
, n
);
591 static void *dfsan_memcpy_with_origin(void *dest
, const void *src
, size_t n
) {
592 dfsan_mem_origin_transfer(dest
, src
, n
);
593 return dfsan_memcpy(dest
, src
, n
);
596 static void dfsan_memset(void *s
, int c
, dfsan_label c_label
, size_t n
) {
597 internal_memset(s
, c
, n
);
598 dfsan_set_label(c_label
, s
, n
);
601 static void dfsan_memset_with_origin(void *s
, int c
, dfsan_label c_label
,
602 dfsan_origin c_origin
, size_t n
) {
603 internal_memset(s
, c
, n
);
604 dfsan_set_label_origin(c_label
, c_origin
, s
, n
);
607 SANITIZER_INTERFACE_ATTRIBUTE
608 void *__dfsw_memcpy(void *dest
, const void *src
, size_t n
,
609 dfsan_label dest_label
, dfsan_label src_label
,
610 dfsan_label n_label
, dfsan_label
*ret_label
) {
611 *ret_label
= dest_label
;
612 return dfsan_memcpy(dest
, src
, n
);
615 SANITIZER_INTERFACE_ATTRIBUTE
616 void *__dfso_memcpy(void *dest
, const void *src
, size_t n
,
617 dfsan_label dest_label
, dfsan_label src_label
,
618 dfsan_label n_label
, dfsan_label
*ret_label
,
619 dfsan_origin dest_origin
, dfsan_origin src_origin
,
620 dfsan_origin n_origin
, dfsan_origin
*ret_origin
) {
621 *ret_label
= dest_label
;
622 *ret_origin
= dest_origin
;
623 return dfsan_memcpy_with_origin(dest
, src
, n
);
626 SANITIZER_INTERFACE_ATTRIBUTE
627 void *__dfsw_memmove(void *dest
, const void *src
, size_t n
,
628 dfsan_label dest_label
, dfsan_label src_label
,
629 dfsan_label n_label
, dfsan_label
*ret_label
) {
630 *ret_label
= dest_label
;
631 return dfsan_memmove(dest
, src
, n
);
634 SANITIZER_INTERFACE_ATTRIBUTE
635 void *__dfso_memmove(void *dest
, const void *src
, size_t n
,
636 dfsan_label dest_label
, dfsan_label src_label
,
637 dfsan_label n_label
, dfsan_label
*ret_label
,
638 dfsan_origin dest_origin
, dfsan_origin src_origin
,
639 dfsan_origin n_origin
, dfsan_origin
*ret_origin
) {
640 *ret_label
= dest_label
;
641 *ret_origin
= dest_origin
;
642 return dfsan_memmove_with_origin(dest
, src
, n
);
645 SANITIZER_INTERFACE_ATTRIBUTE
646 void *__dfsw_memset(void *s
, int c
, size_t n
,
647 dfsan_label s_label
, dfsan_label c_label
,
648 dfsan_label n_label
, dfsan_label
*ret_label
) {
649 dfsan_memset(s
, c
, c_label
, n
);
650 *ret_label
= s_label
;
654 SANITIZER_INTERFACE_ATTRIBUTE
655 void *__dfso_memset(void *s
, int c
, size_t n
, dfsan_label s_label
,
656 dfsan_label c_label
, dfsan_label n_label
,
657 dfsan_label
*ret_label
, dfsan_origin s_origin
,
658 dfsan_origin c_origin
, dfsan_origin n_origin
,
659 dfsan_origin
*ret_origin
) {
660 dfsan_memset_with_origin(s
, c
, c_label
, c_origin
, n
);
661 *ret_label
= s_label
;
662 *ret_origin
= s_origin
;
666 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strcat(char *dest
, const char *src
,
667 dfsan_label dest_label
,
668 dfsan_label src_label
,
669 dfsan_label
*ret_label
) {
670 size_t dest_len
= strlen(dest
);
671 char *ret
= strcat(dest
, src
);
672 dfsan_mem_shadow_transfer(dest
+ dest_len
, src
, strlen(src
));
673 *ret_label
= dest_label
;
677 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strcat(
678 char *dest
, const char *src
, dfsan_label dest_label
, dfsan_label src_label
,
679 dfsan_label
*ret_label
, dfsan_origin dest_origin
, dfsan_origin src_origin
,
680 dfsan_origin
*ret_origin
) {
681 size_t dest_len
= strlen(dest
);
682 char *ret
= strcat(dest
, src
);
683 size_t src_len
= strlen(src
);
684 dfsan_mem_origin_transfer(dest
+ dest_len
, src
, src_len
);
685 dfsan_mem_shadow_transfer(dest
+ dest_len
, src
, src_len
);
686 *ret_label
= dest_label
;
687 *ret_origin
= dest_origin
;
691 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strncat(
692 char *dest
, const char *src
, size_t num
, dfsan_label dest_label
,
693 dfsan_label src_label
, dfsan_label num_label
, dfsan_label
*ret_label
) {
694 size_t src_len
= strlen(src
);
695 src_len
= src_len
< num
? src_len
: num
;
696 size_t dest_len
= strlen(dest
);
698 char *ret
= strncat(dest
, src
, num
);
699 dfsan_mem_shadow_transfer(dest
+ dest_len
, src
, src_len
);
700 *ret_label
= dest_label
;
704 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strncat(
705 char *dest
, const char *src
, size_t num
, dfsan_label dest_label
,
706 dfsan_label src_label
, dfsan_label num_label
, dfsan_label
*ret_label
,
707 dfsan_origin dest_origin
, dfsan_origin src_origin
, dfsan_origin num_origin
,
708 dfsan_origin
*ret_origin
) {
709 size_t src_len
= strlen(src
);
710 src_len
= src_len
< num
? src_len
: num
;
711 size_t dest_len
= strlen(dest
);
713 char *ret
= strncat(dest
, src
, num
);
715 dfsan_mem_origin_transfer(dest
+ dest_len
, src
, src_len
);
716 dfsan_mem_shadow_transfer(dest
+ dest_len
, src
, src_len
);
717 *ret_label
= dest_label
;
718 *ret_origin
= dest_origin
;
722 SANITIZER_INTERFACE_ATTRIBUTE
char *
723 __dfsw_strdup(const char *s
, dfsan_label s_label
, dfsan_label
*ret_label
) {
724 size_t len
= strlen(s
);
725 void *p
= malloc(len
+1);
726 dfsan_memcpy(p
, s
, len
+1);
728 return static_cast<char *>(p
);
731 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strdup(const char *s
,
733 dfsan_label
*ret_label
,
734 dfsan_origin s_origin
,
735 dfsan_origin
*ret_origin
) {
736 size_t len
= strlen(s
);
737 void *p
= malloc(len
+ 1);
738 dfsan_memcpy_with_origin(p
, s
, len
+ 1);
740 return static_cast<char *>(p
);
743 SANITIZER_INTERFACE_ATTRIBUTE
char *
744 __dfsw_strncpy(char *s1
, const char *s2
, size_t n
, dfsan_label s1_label
,
745 dfsan_label s2_label
, dfsan_label n_label
,
746 dfsan_label
*ret_label
) {
747 size_t len
= strlen(s2
);
749 dfsan_memcpy(s1
, s2
, len
+1);
750 dfsan_memset(s1
+len
+1, 0, 0, n
-len
-1);
752 dfsan_memcpy(s1
, s2
, n
);
755 *ret_label
= s1_label
;
759 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strncpy(
760 char *s1
, const char *s2
, size_t n
, dfsan_label s1_label
,
761 dfsan_label s2_label
, dfsan_label n_label
, dfsan_label
*ret_label
,
762 dfsan_origin s1_origin
, dfsan_origin s2_origin
, dfsan_origin n_origin
,
763 dfsan_origin
*ret_origin
) {
764 size_t len
= strlen(s2
);
766 dfsan_memcpy_with_origin(s1
, s2
, len
+ 1);
767 dfsan_memset_with_origin(s1
+ len
+ 1, 0, 0, 0, n
- len
- 1);
769 dfsan_memcpy_with_origin(s1
, s2
, n
);
772 *ret_label
= s1_label
;
773 *ret_origin
= s1_origin
;
777 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
778 __dfsw_pread(int fd
, void *buf
, size_t count
, off_t offset
,
779 dfsan_label fd_label
, dfsan_label buf_label
,
780 dfsan_label count_label
, dfsan_label offset_label
,
781 dfsan_label
*ret_label
) {
782 ssize_t ret
= pread(fd
, buf
, count
, offset
);
784 dfsan_set_label(0, buf
, ret
);
789 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfso_pread(
790 int fd
, void *buf
, size_t count
, off_t offset
, dfsan_label fd_label
,
791 dfsan_label buf_label
, dfsan_label count_label
, dfsan_label offset_label
,
792 dfsan_label
*ret_label
, dfsan_origin fd_origin
, dfsan_origin buf_origin
,
793 dfsan_origin count_origin
, dfsan_label offset_origin
,
794 dfsan_origin
*ret_origin
) {
795 return __dfsw_pread(fd
, buf
, count
, offset
, fd_label
, buf_label
, count_label
,
796 offset_label
, ret_label
);
799 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
800 __dfsw_read(int fd
, void *buf
, size_t count
,
801 dfsan_label fd_label
, dfsan_label buf_label
,
802 dfsan_label count_label
,
803 dfsan_label
*ret_label
) {
804 ssize_t ret
= read(fd
, buf
, count
);
806 dfsan_set_label(0, buf
, ret
);
811 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfso_read(
812 int fd
, void *buf
, size_t count
, dfsan_label fd_label
,
813 dfsan_label buf_label
, dfsan_label count_label
, dfsan_label
*ret_label
,
814 dfsan_origin fd_origin
, dfsan_origin buf_origin
, dfsan_origin count_origin
,
815 dfsan_origin
*ret_origin
) {
816 return __dfsw_read(fd
, buf
, count
, fd_label
, buf_label
, count_label
,
820 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_clock_gettime(clockid_t clk_id
,
822 dfsan_label clk_id_label
,
823 dfsan_label tp_label
,
824 dfsan_label
*ret_label
) {
825 int ret
= clock_gettime(clk_id
, tp
);
827 dfsan_set_label(0, tp
, sizeof(struct timespec
));
832 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_clock_gettime(
833 clockid_t clk_id
, struct timespec
*tp
, dfsan_label clk_id_label
,
834 dfsan_label tp_label
, dfsan_label
*ret_label
, dfsan_origin clk_id_origin
,
835 dfsan_origin tp_origin
, dfsan_origin
*ret_origin
) {
836 return __dfsw_clock_gettime(clk_id
, tp
, clk_id_label
, tp_label
, ret_label
);
839 static void dfsan_set_zero_label(const void *ptr
, uptr size
) {
840 dfsan_set_label(0, const_cast<void *>(ptr
), size
);
843 // dlopen() ultimately calls mmap() down inside the loader, which generally
844 // doesn't participate in dynamic symbol resolution. Therefore we won't
845 // intercept its calls to mmap, and we have to hook it here.
846 SANITIZER_INTERFACE_ATTRIBUTE
void *
847 __dfsw_dlopen(const char *filename
, int flag
, dfsan_label filename_label
,
848 dfsan_label flag_label
, dfsan_label
*ret_label
) {
849 void *handle
= dlopen(filename
, flag
);
850 link_map
*map
= GET_LINK_MAP_BY_DLOPEN_HANDLE(handle
);
852 ForEachMappedRegion(map
, dfsan_set_zero_label
);
857 SANITIZER_INTERFACE_ATTRIBUTE
void *__dfso_dlopen(
858 const char *filename
, int flag
, dfsan_label filename_label
,
859 dfsan_label flag_label
, dfsan_label
*ret_label
,
860 dfsan_origin filename_origin
, dfsan_origin flag_origin
,
861 dfsan_origin
*ret_origin
) {
862 return __dfsw_dlopen(filename
, flag
, filename_label
, flag_label
, ret_label
);
865 static void *DFsanThreadStartFunc(void *arg
) {
866 DFsanThread
*t
= (DFsanThread
*)arg
;
869 SetSigProcMask(&t
->starting_sigset_
, nullptr);
870 return t
->ThreadStart();
873 static int dfsan_pthread_create(pthread_t
*thread
, const pthread_attr_t
*attr
,
874 void *start_routine
, void *arg
,
875 dfsan_label
*ret_label
,
876 bool track_origins
= false) {
877 pthread_attr_t myattr
;
879 pthread_attr_init(&myattr
);
883 // Ensure that the thread stack is large enough to hold all TLS data.
884 AdjustStackSize((void *)(const_cast<pthread_attr_t
*>(attr
)));
887 DFsanThread::Create((thread_callback_t
)start_routine
, arg
, track_origins
);
888 ScopedBlockSignals
block(&t
->starting_sigset_
);
889 int res
= pthread_create(thread
, attr
, DFsanThreadStartFunc
, t
);
892 pthread_attr_destroy(&myattr
);
897 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_pthread_create(
898 pthread_t
*thread
, const pthread_attr_t
*attr
, void *start_routine
,
899 void *arg
, dfsan_label thread_label
, dfsan_label attr_label
,
900 dfsan_label start_routine_label
, dfsan_label arg_label
,
901 dfsan_label
*ret_label
) {
902 return dfsan_pthread_create(thread
, attr
, start_routine
, arg
, ret_label
);
905 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_pthread_create(
906 pthread_t
*thread
, const pthread_attr_t
*attr
, void *start_routine
,
907 void *arg
, dfsan_label thread_label
, dfsan_label attr_label
,
908 dfsan_label start_routine_label
, dfsan_label arg_label
,
909 dfsan_label
*ret_label
, dfsan_origin thread_origin
,
910 dfsan_origin attr_origin
, dfsan_origin start_routine_origin
,
911 dfsan_origin arg_origin
, dfsan_origin
*ret_origin
) {
912 return dfsan_pthread_create(thread
, attr
, start_routine
, arg
, ret_label
,
916 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_pthread_join(pthread_t thread
,
918 dfsan_label thread_label
,
919 dfsan_label retval_label
,
920 dfsan_label
*ret_label
) {
921 int ret
= pthread_join(thread
, retval
);
922 if (ret
== 0 && retval
)
923 dfsan_set_label(0, retval
, sizeof(*retval
));
928 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_pthread_join(
929 pthread_t thread
, void **retval
, dfsan_label thread_label
,
930 dfsan_label retval_label
, dfsan_label
*ret_label
,
931 dfsan_origin thread_origin
, dfsan_origin retval_origin
,
932 dfsan_origin
*ret_origin
) {
933 return __dfsw_pthread_join(thread
, retval
, thread_label
, retval_label
,
937 struct dl_iterate_phdr_info
{
938 int (*callback
)(struct dl_phdr_info
*info
, size_t size
, void *data
);
942 static int dl_iterate_phdr_cb(struct dl_phdr_info
*info
, size_t size
,
944 dl_iterate_phdr_info
*dipi
= (dl_iterate_phdr_info
*)data
;
945 dfsan_set_label(0, *info
);
946 dfsan_set_label(0, const_cast<char *>(info
->dlpi_name
),
947 strlen(info
->dlpi_name
) + 1);
949 0, const_cast<char *>(reinterpret_cast<const char *>(info
->dlpi_phdr
)),
950 sizeof(*info
->dlpi_phdr
) * info
->dlpi_phnum
);
952 dfsan_clear_thread_local_state();
953 return dipi
->callback(info
, size
, dipi
->data
);
956 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_dl_iterate_phdr(
957 int (*callback
)(struct dl_phdr_info
*info
, size_t size
, void *data
),
958 void *data
, dfsan_label callback_label
, dfsan_label data_label
,
959 dfsan_label
*ret_label
) {
960 dl_iterate_phdr_info dipi
= {callback
, data
};
962 return dl_iterate_phdr(dl_iterate_phdr_cb
, &dipi
);
965 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_dl_iterate_phdr(
966 int (*callback
)(struct dl_phdr_info
*info
, size_t size
, void *data
),
967 void *data
, dfsan_label callback_label
, dfsan_label data_label
,
968 dfsan_label
*ret_label
, dfsan_origin callback_origin
,
969 dfsan_origin data_origin
, dfsan_origin
*ret_origin
) {
970 dl_iterate_phdr_info dipi
= {callback
, data
};
972 return dl_iterate_phdr(dl_iterate_phdr_cb
, &dipi
);
975 // This function is only available for glibc 2.27 or newer. Mark it weak so
976 // linking succeeds with older glibcs.
977 SANITIZER_WEAK_ATTRIBUTE
void _dl_get_tls_static_info(size_t *sizep
,
980 SANITIZER_INTERFACE_ATTRIBUTE
void __dfsw__dl_get_tls_static_info(
981 size_t *sizep
, size_t *alignp
, dfsan_label sizep_label
,
982 dfsan_label alignp_label
) {
983 assert(_dl_get_tls_static_info
);
984 _dl_get_tls_static_info(sizep
, alignp
);
985 dfsan_set_label(0, sizep
, sizeof(*sizep
));
986 dfsan_set_label(0, alignp
, sizeof(*alignp
));
989 SANITIZER_INTERFACE_ATTRIBUTE
void __dfso__dl_get_tls_static_info(
990 size_t *sizep
, size_t *alignp
, dfsan_label sizep_label
,
991 dfsan_label alignp_label
, dfsan_origin sizep_origin
,
992 dfsan_origin alignp_origin
) {
993 __dfsw__dl_get_tls_static_info(sizep
, alignp
, sizep_label
, alignp_label
);
996 SANITIZER_INTERFACE_ATTRIBUTE
997 char *__dfsw_ctime_r(const time_t *timep
, char *buf
, dfsan_label timep_label
,
998 dfsan_label buf_label
, dfsan_label
*ret_label
) {
999 char *ret
= ctime_r(timep
, buf
);
1001 dfsan_set_label(dfsan_read_label(timep
, sizeof(time_t)), buf
,
1003 *ret_label
= buf_label
;
1010 SANITIZER_INTERFACE_ATTRIBUTE
1011 char *__dfso_ctime_r(const time_t *timep
, char *buf
, dfsan_label timep_label
,
1012 dfsan_label buf_label
, dfsan_label
*ret_label
,
1013 dfsan_origin timep_origin
, dfsan_origin buf_origin
,
1014 dfsan_origin
*ret_origin
) {
1015 char *ret
= ctime_r(timep
, buf
);
1017 dfsan_set_label_origin(
1018 dfsan_read_label(timep
, sizeof(time_t)),
1019 dfsan_read_origin_of_first_taint(timep
, sizeof(time_t)), buf
,
1021 *ret_label
= buf_label
;
1022 *ret_origin
= buf_origin
;
1029 SANITIZER_INTERFACE_ATTRIBUTE
1030 char *__dfsw_fgets(char *s
, int size
, FILE *stream
, dfsan_label s_label
,
1031 dfsan_label size_label
, dfsan_label stream_label
,
1032 dfsan_label
*ret_label
) {
1033 char *ret
= fgets(s
, size
, stream
);
1035 dfsan_set_label(0, ret
, strlen(ret
) + 1);
1036 *ret_label
= s_label
;
1043 SANITIZER_INTERFACE_ATTRIBUTE
1044 char *__dfso_fgets(char *s
, int size
, FILE *stream
, dfsan_label s_label
,
1045 dfsan_label size_label
, dfsan_label stream_label
,
1046 dfsan_label
*ret_label
, dfsan_origin s_origin
,
1047 dfsan_origin size_origin
, dfsan_origin stream_origin
,
1048 dfsan_origin
*ret_origin
) {
1049 char *ret
= __dfsw_fgets(s
, size
, stream
, s_label
, size_label
, stream_label
,
1052 *ret_origin
= s_origin
;
1056 SANITIZER_INTERFACE_ATTRIBUTE
1057 char *__dfsw_getcwd(char *buf
, size_t size
, dfsan_label buf_label
,
1058 dfsan_label size_label
, dfsan_label
*ret_label
) {
1059 char *ret
= getcwd(buf
, size
);
1061 dfsan_set_label(0, ret
, strlen(ret
) + 1);
1062 *ret_label
= buf_label
;
1069 SANITIZER_INTERFACE_ATTRIBUTE
1070 char *__dfso_getcwd(char *buf
, size_t size
, dfsan_label buf_label
,
1071 dfsan_label size_label
, dfsan_label
*ret_label
,
1072 dfsan_origin buf_origin
, dfsan_origin size_origin
,
1073 dfsan_origin
*ret_origin
) {
1074 char *ret
= __dfsw_getcwd(buf
, size
, buf_label
, size_label
, ret_label
);
1076 *ret_origin
= buf_origin
;
1080 SANITIZER_INTERFACE_ATTRIBUTE
1081 char *__dfsw_get_current_dir_name(dfsan_label
*ret_label
) {
1082 char *ret
= get_current_dir_name();
1084 dfsan_set_label(0, ret
, strlen(ret
) + 1);
1089 SANITIZER_INTERFACE_ATTRIBUTE
1090 char *__dfso_get_current_dir_name(dfsan_label
*ret_label
,
1091 dfsan_origin
*ret_origin
) {
1092 return __dfsw_get_current_dir_name(ret_label
);
1095 // This function is only available for glibc 2.25 or newer. Mark it weak so
1096 // linking succeeds with older glibcs.
1097 SANITIZER_WEAK_ATTRIBUTE
int getentropy(void *buffer
, size_t length
);
1099 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_getentropy(void *buffer
, size_t length
,
1100 dfsan_label buffer_label
,
1101 dfsan_label length_label
,
1102 dfsan_label
*ret_label
) {
1103 int ret
= getentropy(buffer
, length
);
1105 dfsan_set_label(0, buffer
, length
);
1111 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_getentropy(void *buffer
, size_t length
,
1112 dfsan_label buffer_label
,
1113 dfsan_label length_label
,
1114 dfsan_label
*ret_label
,
1115 dfsan_origin buffer_origin
,
1116 dfsan_origin length_origin
,
1117 dfsan_origin
*ret_origin
) {
1118 return __dfsw_getentropy(buffer
, length
, buffer_label
, length_label
,
1122 SANITIZER_INTERFACE_ATTRIBUTE
1123 int __dfsw_gethostname(char *name
, size_t len
, dfsan_label name_label
,
1124 dfsan_label len_label
, dfsan_label
*ret_label
) {
1125 int ret
= gethostname(name
, len
);
1127 dfsan_set_label(0, name
, strlen(name
) + 1);
1133 SANITIZER_INTERFACE_ATTRIBUTE
1134 int __dfso_gethostname(char *name
, size_t len
, dfsan_label name_label
,
1135 dfsan_label len_label
, dfsan_label
*ret_label
,
1136 dfsan_origin name_origin
, dfsan_origin len_origin
,
1137 dfsan_label
*ret_origin
) {
1138 return __dfsw_gethostname(name
, len
, name_label
, len_label
, ret_label
);
1141 SANITIZER_INTERFACE_ATTRIBUTE
1142 int __dfsw_getrlimit(int resource
, struct rlimit
*rlim
,
1143 dfsan_label resource_label
, dfsan_label rlim_label
,
1144 dfsan_label
*ret_label
) {
1145 int ret
= getrlimit(resource
, rlim
);
1147 dfsan_set_label(0, rlim
, sizeof(struct rlimit
));
1153 SANITIZER_INTERFACE_ATTRIBUTE
1154 int __dfso_getrlimit(int resource
, struct rlimit
*rlim
,
1155 dfsan_label resource_label
, dfsan_label rlim_label
,
1156 dfsan_label
*ret_label
, dfsan_origin resource_origin
,
1157 dfsan_origin rlim_origin
, dfsan_origin
*ret_origin
) {
1158 return __dfsw_getrlimit(resource
, rlim
, resource_label
, rlim_label
,
1162 SANITIZER_INTERFACE_ATTRIBUTE
1163 int __dfsw_getrusage(int who
, struct rusage
*usage
, dfsan_label who_label
,
1164 dfsan_label usage_label
, dfsan_label
*ret_label
) {
1165 int ret
= getrusage(who
, usage
);
1167 dfsan_set_label(0, usage
, sizeof(struct rusage
));
1173 SANITIZER_INTERFACE_ATTRIBUTE
1174 int __dfso_getrusage(int who
, struct rusage
*usage
, dfsan_label who_label
,
1175 dfsan_label usage_label
, dfsan_label
*ret_label
,
1176 dfsan_origin who_origin
, dfsan_origin usage_origin
,
1177 dfsan_label
*ret_origin
) {
1178 return __dfsw_getrusage(who
, usage
, who_label
, usage_label
, ret_label
);
1181 SANITIZER_INTERFACE_ATTRIBUTE
1182 char *__dfsw_strcpy(char *dest
, const char *src
, dfsan_label dst_label
,
1183 dfsan_label src_label
, dfsan_label
*ret_label
) {
1184 char *ret
= strcpy(dest
, src
);
1186 dfsan_mem_shadow_transfer(dest
, src
, strlen(src
) + 1);
1188 *ret_label
= dst_label
;
1192 SANITIZER_INTERFACE_ATTRIBUTE
1193 char *__dfso_strcpy(char *dest
, const char *src
, dfsan_label dst_label
,
1194 dfsan_label src_label
, dfsan_label
*ret_label
,
1195 dfsan_origin dst_origin
, dfsan_origin src_origin
,
1196 dfsan_origin
*ret_origin
) {
1197 char *ret
= strcpy(dest
, src
);
1199 size_t str_len
= strlen(src
) + 1;
1200 dfsan_mem_origin_transfer(dest
, src
, str_len
);
1201 dfsan_mem_shadow_transfer(dest
, src
, str_len
);
1203 *ret_label
= dst_label
;
1204 *ret_origin
= dst_origin
;
1209 template <typename Fn
>
1210 static ALWAYS_INLINE
auto dfsan_strtol_impl(
1211 Fn real
, const char *nptr
, char **endptr
, int base
,
1212 char **tmp_endptr
) -> decltype(real(nullptr, nullptr, 0)) {
1214 auto ret
= real(nptr
, tmp_endptr
, base
);
1216 *endptr
= *tmp_endptr
;
1221 static void dfsan_strtolong_label(const char *nptr
, const char *tmp_endptr
,
1222 dfsan_label base_label
,
1223 dfsan_label
*ret_label
) {
1224 if (tmp_endptr
> nptr
) {
1225 // If *tmp_endptr is '\0' include its label as well.
1226 *ret_label
= dfsan_union(
1228 dfsan_read_label(nptr
, tmp_endptr
- nptr
+ (*tmp_endptr
? 0 : 1)));
1234 static void dfsan_strtolong_origin(const char *nptr
, const char *tmp_endptr
,
1235 dfsan_label base_label
,
1236 dfsan_label
*ret_label
,
1237 dfsan_origin base_origin
,
1238 dfsan_origin
*ret_origin
) {
1239 if (tmp_endptr
> nptr
) {
1240 // When multiple inputs are tainted, we propagate one of its origins.
1241 // Because checking if base_label is tainted does not need additional
1242 // computation, we prefer to propagating base_origin.
1243 *ret_origin
= base_label
1245 : dfsan_read_origin_of_first_taint(
1246 nptr
, tmp_endptr
- nptr
+ (*tmp_endptr
? 0 : 1));
1250 static double dfsan_strtod(const char *nptr
, char **endptr
, char **tmp_endptr
) {
1252 double ret
= strtod(nptr
, tmp_endptr
);
1254 *endptr
= *tmp_endptr
;
1258 static void dfsan_strtod_label(const char *nptr
, const char *tmp_endptr
,
1259 dfsan_label
*ret_label
) {
1260 if (tmp_endptr
> nptr
) {
1261 // If *tmp_endptr is '\0' include its label as well.
1262 *ret_label
= dfsan_read_label(
1264 tmp_endptr
- nptr
+ (*tmp_endptr
? 0 : 1));
1270 SANITIZER_INTERFACE_ATTRIBUTE
1271 double __dfsw_strtod(const char *nptr
, char **endptr
, dfsan_label nptr_label
,
1272 dfsan_label endptr_label
, dfsan_label
*ret_label
) {
1274 double ret
= dfsan_strtod(nptr
, endptr
, &tmp_endptr
);
1275 dfsan_strtod_label(nptr
, tmp_endptr
, ret_label
);
1279 SANITIZER_INTERFACE_ATTRIBUTE
1280 double __dfso_strtod(const char *nptr
, char **endptr
, dfsan_label nptr_label
,
1281 dfsan_label endptr_label
, dfsan_label
*ret_label
,
1282 dfsan_origin nptr_origin
, dfsan_origin endptr_origin
,
1283 dfsan_origin
*ret_origin
) {
1285 double ret
= dfsan_strtod(nptr
, endptr
, &tmp_endptr
);
1286 dfsan_strtod_label(nptr
, tmp_endptr
, ret_label
);
1287 if (tmp_endptr
> nptr
) {
1288 // If *tmp_endptr is '\0' include its label as well.
1289 *ret_origin
= dfsan_read_origin_of_first_taint(
1290 nptr
, tmp_endptr
- nptr
+ (*tmp_endptr
? 0 : 1));
1297 WRAPPER_ALIAS(__isoc23_strtod
, strtod
)
1299 #define WRAPPER_STRTO(ret_type, fun) \
1300 SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \
1301 const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1302 dfsan_label endptr_label, dfsan_label base_label, \
1303 dfsan_label *ret_label) { \
1305 auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
1306 dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
1309 SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \
1310 const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1311 dfsan_label endptr_label, dfsan_label base_label, \
1312 dfsan_label *ret_label, dfsan_origin nptr_origin, \
1313 dfsan_origin endptr_origin, dfsan_origin base_origin, \
1314 dfsan_origin *ret_origin) { \
1316 auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
1317 dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
1318 dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \
1319 base_origin, ret_origin); \
1323 WRAPPER_STRTO(long, strtol
)
1324 WRAPPER_STRTO(long long, strtoll
)
1325 WRAPPER_STRTO(unsigned long, strtoul
)
1326 WRAPPER_STRTO(unsigned long long, strtoull
)
1327 WRAPPER_ALIAS(__isoc23_strtol
, strtol
)
1328 WRAPPER_ALIAS(__isoc23_strtoll
, strtoll
)
1329 WRAPPER_ALIAS(__isoc23_strtoul
, strtoul
)
1330 WRAPPER_ALIAS(__isoc23_strtoull
, strtoull
)
1332 SANITIZER_INTERFACE_ATTRIBUTE
1333 time_t __dfsw_time(time_t *t
, dfsan_label t_label
, dfsan_label
*ret_label
) {
1334 time_t ret
= time(t
);
1335 if (ret
!= (time_t) -1 && t
) {
1336 dfsan_set_label(0, t
, sizeof(time_t));
1342 SANITIZER_INTERFACE_ATTRIBUTE
1343 time_t __dfso_time(time_t *t
, dfsan_label t_label
, dfsan_label
*ret_label
,
1344 dfsan_origin t_origin
, dfsan_origin
*ret_origin
) {
1345 return __dfsw_time(t
, t_label
, ret_label
);
1348 SANITIZER_INTERFACE_ATTRIBUTE
1349 int __dfsw_inet_pton(int af
, const char *src
, void *dst
, dfsan_label af_label
,
1350 dfsan_label src_label
, dfsan_label dst_label
,
1351 dfsan_label
*ret_label
) {
1352 int ret
= inet_pton(af
, src
, dst
);
1354 dfsan_set_label(dfsan_read_label(src
, strlen(src
) + 1), dst
,
1355 af
== AF_INET
? sizeof(struct in_addr
) : sizeof(in6_addr
));
1361 SANITIZER_INTERFACE_ATTRIBUTE
1362 int __dfso_inet_pton(int af
, const char *src
, void *dst
, dfsan_label af_label
,
1363 dfsan_label src_label
, dfsan_label dst_label
,
1364 dfsan_label
*ret_label
, dfsan_origin af_origin
,
1365 dfsan_origin src_origin
, dfsan_origin dst_origin
,
1366 dfsan_origin
*ret_origin
) {
1367 int ret
= inet_pton(af
, src
, dst
);
1369 int src_len
= strlen(src
) + 1;
1370 dfsan_set_label_origin(
1371 dfsan_read_label(src
, src_len
),
1372 dfsan_read_origin_of_first_taint(src
, src_len
), dst
,
1373 af
== AF_INET
? sizeof(struct in_addr
) : sizeof(in6_addr
));
1379 SANITIZER_INTERFACE_ATTRIBUTE
1380 struct tm
*__dfsw_localtime_r(const time_t *timep
, struct tm
*result
,
1381 dfsan_label timep_label
, dfsan_label result_label
,
1382 dfsan_label
*ret_label
) {
1383 struct tm
*ret
= localtime_r(timep
, result
);
1385 dfsan_set_label(dfsan_read_label(timep
, sizeof(time_t)), result
,
1387 *ret_label
= result_label
;
1394 SANITIZER_INTERFACE_ATTRIBUTE
1395 struct tm
*__dfso_localtime_r(const time_t *timep
, struct tm
*result
,
1396 dfsan_label timep_label
, dfsan_label result_label
,
1397 dfsan_label
*ret_label
, dfsan_origin timep_origin
,
1398 dfsan_origin result_origin
,
1399 dfsan_origin
*ret_origin
) {
1400 struct tm
*ret
= localtime_r(timep
, result
);
1402 dfsan_set_label_origin(
1403 dfsan_read_label(timep
, sizeof(time_t)),
1404 dfsan_read_origin_of_first_taint(timep
, sizeof(time_t)), result
,
1406 *ret_label
= result_label
;
1407 *ret_origin
= result_origin
;
1414 SANITIZER_INTERFACE_ATTRIBUTE
1415 int __dfsw_getpwuid_r(id_t uid
, struct passwd
*pwd
,
1416 char *buf
, size_t buflen
, struct passwd
**result
,
1417 dfsan_label uid_label
, dfsan_label pwd_label
,
1418 dfsan_label buf_label
, dfsan_label buflen_label
,
1419 dfsan_label result_label
, dfsan_label
*ret_label
) {
1420 // Store the data in pwd, the strings referenced from pwd in buf, and the
1421 // address of pwd in *result. On failure, NULL is stored in *result.
1422 int ret
= getpwuid_r(uid
, pwd
, buf
, buflen
, result
);
1424 dfsan_set_label(0, pwd
, sizeof(struct passwd
));
1425 dfsan_set_label(0, buf
, strlen(buf
) + 1);
1428 dfsan_set_label(0, result
, sizeof(struct passwd
*));
1432 SANITIZER_INTERFACE_ATTRIBUTE
1433 int __dfso_getpwuid_r(id_t uid
, struct passwd
*pwd
, char *buf
, size_t buflen
,
1434 struct passwd
**result
, dfsan_label uid_label
,
1435 dfsan_label pwd_label
, dfsan_label buf_label
,
1436 dfsan_label buflen_label
, dfsan_label result_label
,
1437 dfsan_label
*ret_label
, dfsan_origin uid_origin
,
1438 dfsan_origin pwd_origin
, dfsan_origin buf_origin
,
1439 dfsan_origin buflen_origin
, dfsan_origin result_origin
,
1440 dfsan_origin
*ret_origin
) {
1441 return __dfsw_getpwuid_r(uid
, pwd
, buf
, buflen
, result
, uid_label
, pwd_label
,
1442 buf_label
, buflen_label
, result_label
, ret_label
);
1445 SANITIZER_INTERFACE_ATTRIBUTE
1446 int __dfsw_epoll_wait(int epfd
, struct epoll_event
*events
, int maxevents
,
1447 int timeout
, dfsan_label epfd_label
,
1448 dfsan_label events_label
, dfsan_label maxevents_label
,
1449 dfsan_label timeout_label
, dfsan_label
*ret_label
) {
1450 int ret
= epoll_wait(epfd
, events
, maxevents
, timeout
);
1452 dfsan_set_label(0, events
, ret
* sizeof(*events
));
1457 SANITIZER_INTERFACE_ATTRIBUTE
1458 int __dfso_epoll_wait(int epfd
, struct epoll_event
*events
, int maxevents
,
1459 int timeout
, dfsan_label epfd_label
,
1460 dfsan_label events_label
, dfsan_label maxevents_label
,
1461 dfsan_label timeout_label
, dfsan_label
*ret_label
,
1462 dfsan_origin epfd_origin
, dfsan_origin events_origin
,
1463 dfsan_origin maxevents_origin
,
1464 dfsan_origin timeout_origin
, dfsan_origin
*ret_origin
) {
1465 return __dfsw_epoll_wait(epfd
, events
, maxevents
, timeout
, epfd_label
,
1466 events_label
, maxevents_label
, timeout_label
,
1470 SANITIZER_INTERFACE_ATTRIBUTE
1471 int __dfsw_poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
,
1472 dfsan_label dfs_label
, dfsan_label nfds_label
,
1473 dfsan_label timeout_label
, dfsan_label
*ret_label
) {
1474 int ret
= poll(fds
, nfds
, timeout
);
1476 for (; nfds
> 0; --nfds
) {
1477 dfsan_set_label(0, &fds
[nfds
- 1].revents
, sizeof(fds
[nfds
- 1].revents
));
1484 SANITIZER_INTERFACE_ATTRIBUTE
1485 int __dfso_poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
,
1486 dfsan_label dfs_label
, dfsan_label nfds_label
,
1487 dfsan_label timeout_label
, dfsan_label
*ret_label
,
1488 dfsan_origin dfs_origin
, dfsan_origin nfds_origin
,
1489 dfsan_origin timeout_origin
, dfsan_origin
*ret_origin
) {
1490 return __dfsw_poll(fds
, nfds
, timeout
, dfs_label
, nfds_label
, timeout_label
,
1494 SANITIZER_INTERFACE_ATTRIBUTE
1495 int __dfsw_select(int nfds
, fd_set
*readfds
, fd_set
*writefds
,
1496 fd_set
*exceptfds
, struct timeval
*timeout
,
1497 dfsan_label nfds_label
, dfsan_label readfds_label
,
1498 dfsan_label writefds_label
, dfsan_label exceptfds_label
,
1499 dfsan_label timeout_label
, dfsan_label
*ret_label
) {
1500 int ret
= select(nfds
, readfds
, writefds
, exceptfds
, timeout
);
1501 // Clear everything (also on error) since their content is either set or
1504 dfsan_set_label(0, readfds
, sizeof(fd_set
));
1507 dfsan_set_label(0, writefds
, sizeof(fd_set
));
1510 dfsan_set_label(0, exceptfds
, sizeof(fd_set
));
1512 dfsan_set_label(0, timeout
, sizeof(struct timeval
));
1517 SANITIZER_INTERFACE_ATTRIBUTE
1518 int __dfso_select(int nfds
, fd_set
*readfds
, fd_set
*writefds
,
1519 fd_set
*exceptfds
, struct timeval
*timeout
,
1520 dfsan_label nfds_label
, dfsan_label readfds_label
,
1521 dfsan_label writefds_label
, dfsan_label exceptfds_label
,
1522 dfsan_label timeout_label
, dfsan_label
*ret_label
,
1523 dfsan_origin nfds_origin
, dfsan_origin readfds_origin
,
1524 dfsan_origin writefds_origin
, dfsan_origin exceptfds_origin
,
1525 dfsan_origin timeout_origin
, dfsan_origin
*ret_origin
) {
1526 return __dfsw_select(nfds
, readfds
, writefds
, exceptfds
, timeout
, nfds_label
,
1527 readfds_label
, writefds_label
, exceptfds_label
,
1528 timeout_label
, ret_label
);
1531 SANITIZER_INTERFACE_ATTRIBUTE
1532 int __dfsw_sched_getaffinity(pid_t pid
, size_t cpusetsize
, cpu_set_t
*mask
,
1533 dfsan_label pid_label
,
1534 dfsan_label cpusetsize_label
,
1535 dfsan_label mask_label
, dfsan_label
*ret_label
) {
1536 int ret
= sched_getaffinity(pid
, cpusetsize
, mask
);
1538 dfsan_set_label(0, mask
, cpusetsize
);
1544 SANITIZER_INTERFACE_ATTRIBUTE
1545 int __dfso_sched_getaffinity(pid_t pid
, size_t cpusetsize
, cpu_set_t
*mask
,
1546 dfsan_label pid_label
,
1547 dfsan_label cpusetsize_label
,
1548 dfsan_label mask_label
, dfsan_label
*ret_label
,
1549 dfsan_origin pid_origin
,
1550 dfsan_origin cpusetsize_origin
,
1551 dfsan_origin mask_origin
,
1552 dfsan_origin
*ret_origin
) {
1553 return __dfsw_sched_getaffinity(pid
, cpusetsize
, mask
, pid_label
,
1554 cpusetsize_label
, mask_label
, ret_label
);
1557 SANITIZER_INTERFACE_ATTRIBUTE
1558 int __dfsw_sigemptyset(sigset_t
*set
, dfsan_label set_label
,
1559 dfsan_label
*ret_label
) {
1560 int ret
= sigemptyset(set
);
1561 dfsan_set_label(0, set
, sizeof(sigset_t
));
1566 SANITIZER_INTERFACE_ATTRIBUTE
1567 int __dfso_sigemptyset(sigset_t
*set
, dfsan_label set_label
,
1568 dfsan_label
*ret_label
, dfsan_origin set_origin
,
1569 dfsan_origin
*ret_origin
) {
1570 return __dfsw_sigemptyset(set
, set_label
, ret_label
);
1573 class SignalHandlerScope
{
1575 SignalHandlerScope() {
1576 if (DFsanThread
*t
= GetCurrentThread())
1577 t
->EnterSignalHandler();
1579 ~SignalHandlerScope() {
1580 if (DFsanThread
*t
= GetCurrentThread())
1581 t
->LeaveSignalHandler();
1585 // Clear DFSan runtime TLS state at the end of a scope.
1587 // Implementation must be async-signal-safe and use small data size, because
1588 // instances of this class may live on the signal handler stack.
1590 // DFSan uses TLS to pass metadata of arguments and return values. When an
1591 // instrumented function accesses the TLS, if a signal callback happens, and the
1592 // callback calls other instrumented functions with updating the same TLS, the
1593 // TLS is in an inconsistent state after the callback ends. This may cause
1594 // either under-tainting or over-tainting.
1596 // The current implementation simply resets TLS at restore. This prevents from
1597 // over-tainting. Although under-tainting may still happen, a taint flow can be
1598 // found eventually if we run a DFSan-instrumented program multiple times. The
1599 // alternative option is saving the entire TLS. However the TLS storage takes
1600 // 2k bytes, and signal calls could be nested. So it does not seem worth.
1601 class ScopedClearThreadLocalState
{
1603 ScopedClearThreadLocalState() {}
1604 ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1607 // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1608 const int kMaxSignals
= 1024;
1609 static atomic_uintptr_t sigactions
[kMaxSignals
];
1611 static void SignalHandler(int signo
) {
1612 SignalHandlerScope signal_handler_scope
;
1613 ScopedClearThreadLocalState scoped_clear_tls
;
1615 // Clear shadows for all inputs provided by system.
1616 dfsan_clear_arg_tls(0, sizeof(dfsan_label
));
1618 typedef void (*signal_cb
)(int x
);
1620 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1624 static void SignalAction(int signo
, siginfo_t
*si
, void *uc
) {
1625 SignalHandlerScope signal_handler_scope
;
1626 ScopedClearThreadLocalState scoped_clear_tls
;
1628 // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1629 dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label
));
1630 dfsan_set_label(0, si
, sizeof(*si
));
1631 dfsan_set_label(0, uc
, sizeof(ucontext_t
));
1633 typedef void (*sigaction_cb
)(int, siginfo_t
*, void *);
1635 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1639 SANITIZER_INTERFACE_ATTRIBUTE
1640 int __dfsw_sigaction(int signum
, const struct sigaction
*act
,
1641 struct sigaction
*oldact
, dfsan_label signum_label
,
1642 dfsan_label act_label
, dfsan_label oldact_label
,
1643 dfsan_label
*ret_label
) {
1644 CHECK_LT(signum
, kMaxSignals
);
1645 SignalSpinLocker lock
;
1646 uptr old_cb
= atomic_load(&sigactions
[signum
], memory_order_relaxed
);
1647 struct sigaction new_act
;
1648 struct sigaction
*pnew_act
= act
? &new_act
: nullptr;
1650 internal_memcpy(pnew_act
, act
, sizeof(struct sigaction
));
1651 if (pnew_act
->sa_flags
& SA_SIGINFO
) {
1652 uptr cb
= (uptr
)(pnew_act
->sa_sigaction
);
1653 if (cb
!= (uptr
)SIG_IGN
&& cb
!= (uptr
)SIG_DFL
) {
1654 atomic_store(&sigactions
[signum
], cb
, memory_order_relaxed
);
1655 pnew_act
->sa_sigaction
= SignalAction
;
1658 uptr cb
= (uptr
)(pnew_act
->sa_handler
);
1659 if (cb
!= (uptr
)SIG_IGN
&& cb
!= (uptr
)SIG_DFL
) {
1660 atomic_store(&sigactions
[signum
], cb
, memory_order_relaxed
);
1661 pnew_act
->sa_handler
= SignalHandler
;
1666 int ret
= sigaction(signum
, pnew_act
, oldact
);
1668 if (ret
== 0 && oldact
) {
1669 if (oldact
->sa_flags
& SA_SIGINFO
) {
1670 if (oldact
->sa_sigaction
== SignalAction
)
1671 oldact
->sa_sigaction
= (decltype(oldact
->sa_sigaction
))old_cb
;
1673 if (oldact
->sa_handler
== SignalHandler
)
1674 oldact
->sa_handler
= (decltype(oldact
->sa_handler
))old_cb
;
1679 dfsan_set_label(0, oldact
, sizeof(struct sigaction
));
1685 SANITIZER_INTERFACE_ATTRIBUTE
1686 int __dfso_sigaction(int signum
, const struct sigaction
*act
,
1687 struct sigaction
*oldact
, dfsan_label signum_label
,
1688 dfsan_label act_label
, dfsan_label oldact_label
,
1689 dfsan_label
*ret_label
, dfsan_origin signum_origin
,
1690 dfsan_origin act_origin
, dfsan_origin oldact_origin
,
1691 dfsan_origin
*ret_origin
) {
1692 return __dfsw_sigaction(signum
, act
, oldact
, signum_label
, act_label
,
1693 oldact_label
, ret_label
);
1696 static sighandler_t
dfsan_signal(int signum
, sighandler_t handler
,
1697 dfsan_label
*ret_label
) {
1698 CHECK_LT(signum
, kMaxSignals
);
1699 SignalSpinLocker lock
;
1700 uptr old_cb
= atomic_load(&sigactions
[signum
], memory_order_relaxed
);
1701 if (handler
!= SIG_IGN
&& handler
!= SIG_DFL
) {
1702 atomic_store(&sigactions
[signum
], (uptr
)handler
, memory_order_relaxed
);
1703 handler
= &SignalHandler
;
1706 sighandler_t ret
= signal(signum
, handler
);
1708 if (ret
== SignalHandler
)
1709 ret
= (sighandler_t
)old_cb
;
1715 SANITIZER_INTERFACE_ATTRIBUTE
1716 sighandler_t
__dfsw_signal(int signum
, sighandler_t handler
,
1717 dfsan_label signum_label
, dfsan_label handler_label
,
1718 dfsan_label
*ret_label
) {
1719 return dfsan_signal(signum
, handler
, ret_label
);
1722 SANITIZER_INTERFACE_ATTRIBUTE
1723 sighandler_t
__dfso_signal(int signum
, sighandler_t handler
,
1724 dfsan_label signum_label
, dfsan_label handler_label
,
1725 dfsan_label
*ret_label
, dfsan_origin signum_origin
,
1726 dfsan_origin handler_origin
,
1727 dfsan_origin
*ret_origin
) {
1728 return dfsan_signal(signum
, handler
, ret_label
);
1731 SANITIZER_INTERFACE_ATTRIBUTE
1732 int __dfsw_sigaltstack(const stack_t
*ss
, stack_t
*old_ss
, dfsan_label ss_label
,
1733 dfsan_label old_ss_label
, dfsan_label
*ret_label
) {
1734 int ret
= sigaltstack(ss
, old_ss
);
1735 if (ret
!= -1 && old_ss
)
1736 dfsan_set_label(0, old_ss
, sizeof(*old_ss
));
1741 SANITIZER_INTERFACE_ATTRIBUTE
1742 int __dfso_sigaltstack(const stack_t
*ss
, stack_t
*old_ss
, dfsan_label ss_label
,
1743 dfsan_label old_ss_label
, dfsan_label
*ret_label
,
1744 dfsan_origin ss_origin
, dfsan_origin old_ss_origin
,
1745 dfsan_origin
*ret_origin
) {
1746 return __dfsw_sigaltstack(ss
, old_ss
, ss_label
, old_ss_label
, ret_label
);
1749 SANITIZER_INTERFACE_ATTRIBUTE
1750 int __dfsw_gettimeofday(struct timeval
*tv
, struct timezone
*tz
,
1751 dfsan_label tv_label
, dfsan_label tz_label
,
1752 dfsan_label
*ret_label
) {
1753 int ret
= gettimeofday(tv
, tz
);
1755 dfsan_set_label(0, tv
, sizeof(struct timeval
));
1758 dfsan_set_label(0, tz
, sizeof(struct timezone
));
1764 SANITIZER_INTERFACE_ATTRIBUTE
1765 int __dfso_gettimeofday(struct timeval
*tv
, struct timezone
*tz
,
1766 dfsan_label tv_label
, dfsan_label tz_label
,
1767 dfsan_label
*ret_label
, dfsan_origin tv_origin
,
1768 dfsan_origin tz_origin
, dfsan_origin
*ret_origin
) {
1769 return __dfsw_gettimeofday(tv
, tz
, tv_label
, tz_label
, ret_label
);
1772 SANITIZER_INTERFACE_ATTRIBUTE
void *__dfsw_memchr(void *s
, int c
, size_t n
,
1773 dfsan_label s_label
,
1774 dfsan_label c_label
,
1775 dfsan_label n_label
,
1776 dfsan_label
*ret_label
) {
1777 void *ret
= memchr(s
, c
, n
);
1778 if (flags().strict_data_dependencies
) {
1779 *ret_label
= ret
? s_label
: 0;
1782 ret
? reinterpret_cast<char *>(ret
) - reinterpret_cast<char *>(s
) + 1
1785 dfsan_union(dfsan_read_label(s
, len
), dfsan_union(s_label
, c_label
));
1790 SANITIZER_INTERFACE_ATTRIBUTE
void *__dfso_memchr(
1791 void *s
, int c
, size_t n
, dfsan_label s_label
, dfsan_label c_label
,
1792 dfsan_label n_label
, dfsan_label
*ret_label
, dfsan_origin s_origin
,
1793 dfsan_origin c_origin
, dfsan_origin n_origin
, dfsan_origin
*ret_origin
) {
1794 void *ret
= __dfsw_memchr(s
, c
, n
, s_label
, c_label
, n_label
, ret_label
);
1795 if (flags().strict_data_dependencies
) {
1797 *ret_origin
= s_origin
;
1800 ret
? reinterpret_cast<char *>(ret
) - reinterpret_cast<char *>(s
) + 1
1802 dfsan_origin o
= dfsan_read_origin_of_first_taint(s
, len
);
1803 *ret_origin
= o
? o
: (s_label
? s_origin
: c_origin
);
1808 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strrchr(char *s
, int c
,
1809 dfsan_label s_label
,
1810 dfsan_label c_label
,
1811 dfsan_label
*ret_label
) {
1812 char *ret
= strrchr(s
, c
);
1813 if (flags().strict_data_dependencies
) {
1814 *ret_label
= ret
? s_label
: 0;
1817 dfsan_union(dfsan_read_label(s
, strlen(s
) + 1),
1818 dfsan_union(s_label
, c_label
));
1824 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strrchr(
1825 char *s
, int c
, dfsan_label s_label
, dfsan_label c_label
,
1826 dfsan_label
*ret_label
, dfsan_origin s_origin
, dfsan_origin c_origin
,
1827 dfsan_origin
*ret_origin
) {
1828 char *ret
= __dfsw_strrchr(s
, c
, s_label
, c_label
, ret_label
);
1829 if (flags().strict_data_dependencies
) {
1831 *ret_origin
= s_origin
;
1833 size_t s_len
= strlen(s
) + 1;
1834 dfsan_origin o
= dfsan_read_origin_of_first_taint(s
, s_len
);
1835 *ret_origin
= o
? o
: (s_label
? s_origin
: c_origin
);
1841 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strstr(char *haystack
, char *needle
,
1842 dfsan_label haystack_label
,
1843 dfsan_label needle_label
,
1844 dfsan_label
*ret_label
) {
1845 char *ret
= strstr(haystack
, needle
);
1846 if (flags().strict_data_dependencies
) {
1847 *ret_label
= ret
? haystack_label
: 0;
1849 size_t len
= ret
? ret
+ strlen(needle
) - haystack
: strlen(haystack
) + 1;
1851 dfsan_union(dfsan_read_label(haystack
, len
),
1852 dfsan_union(dfsan_read_label(needle
, strlen(needle
) + 1),
1853 dfsan_union(haystack_label
, needle_label
)));
1859 SANITIZER_INTERFACE_ATTRIBUTE
char *__dfso_strstr(char *haystack
, char *needle
,
1860 dfsan_label haystack_label
,
1861 dfsan_label needle_label
,
1862 dfsan_label
*ret_label
,
1863 dfsan_origin haystack_origin
,
1864 dfsan_origin needle_origin
,
1865 dfsan_origin
*ret_origin
) {
1867 __dfsw_strstr(haystack
, needle
, haystack_label
, needle_label
, ret_label
);
1868 if (flags().strict_data_dependencies
) {
1870 *ret_origin
= haystack_origin
;
1872 size_t needle_len
= strlen(needle
);
1873 size_t len
= ret
? ret
+ needle_len
- haystack
: strlen(haystack
) + 1;
1874 dfsan_origin o
= dfsan_read_origin_of_first_taint(haystack
, len
);
1878 o
= dfsan_read_origin_of_first_taint(needle
, needle_len
+ 1);
1879 *ret_origin
= o
? o
: (haystack_label
? haystack_origin
: needle_origin
);
1886 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_nanosleep(const struct timespec
*req
,
1887 struct timespec
*rem
,
1888 dfsan_label req_label
,
1889 dfsan_label rem_label
,
1890 dfsan_label
*ret_label
) {
1891 int ret
= nanosleep(req
, rem
);
1894 // Interrupted by a signal, rem is filled with the remaining time.
1895 dfsan_set_label(0, rem
, sizeof(struct timespec
));
1900 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_nanosleep(
1901 const struct timespec
*req
, struct timespec
*rem
, dfsan_label req_label
,
1902 dfsan_label rem_label
, dfsan_label
*ret_label
, dfsan_origin req_origin
,
1903 dfsan_origin rem_origin
, dfsan_origin
*ret_origin
) {
1904 return __dfsw_nanosleep(req
, rem
, req_label
, rem_label
, ret_label
);
1907 static void clear_msghdr_labels(size_t bytes_written
, struct msghdr
*msg
,
1909 dfsan_set_label(0, msg
, sizeof(*msg
));
1910 dfsan_set_label(0, msg
->msg_name
, msg
->msg_namelen
);
1911 dfsan_set_label(0, msg
->msg_control
, msg
->msg_controllen
);
1912 for (size_t i
= 0; i
< msg
->msg_iovlen
; ++i
) {
1913 struct iovec
*iov
= &msg
->msg_iov
[i
];
1914 size_t iov_written
= iov
->iov_len
;
1916 // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that
1917 // may not have changed, using bytes_written to bound the 0 label write.
1918 // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer,
1919 // and should not be used as a bound.
1920 if (!(MSG_TRUNC
& flags
)) {
1921 if (bytes_written
< iov
->iov_len
) {
1922 iov_written
= bytes_written
;
1924 bytes_written
-= iov_written
;
1927 dfsan_set_label(0, iov
->iov_base
, iov_written
);
1931 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_recvmmsg(
1932 int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
,
1933 struct timespec
*timeout
, dfsan_label sockfd_label
,
1934 dfsan_label msgvec_label
, dfsan_label vlen_label
, dfsan_label flags_label
,
1935 dfsan_label timeout_label
, dfsan_label
*ret_label
) {
1936 int ret
= recvmmsg(sockfd
, msgvec
, vlen
, flags
, timeout
);
1937 for (int i
= 0; i
< ret
; ++i
) {
1938 dfsan_set_label(0, &msgvec
[i
].msg_len
, sizeof(msgvec
[i
].msg_len
));
1939 clear_msghdr_labels(msgvec
[i
].msg_len
, &msgvec
[i
].msg_hdr
, flags
);
1945 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_recvmmsg(
1946 int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
,
1947 struct timespec
*timeout
, dfsan_label sockfd_label
,
1948 dfsan_label msgvec_label
, dfsan_label vlen_label
, dfsan_label flags_label
,
1949 dfsan_label timeout_label
, dfsan_label
*ret_label
,
1950 dfsan_origin sockfd_origin
, dfsan_origin msgvec_origin
,
1951 dfsan_origin vlen_origin
, dfsan_origin flags_origin
,
1952 dfsan_origin timeout_origin
, dfsan_origin
*ret_origin
) {
1953 return __dfsw_recvmmsg(sockfd
, msgvec
, vlen
, flags
, timeout
, sockfd_label
,
1954 msgvec_label
, vlen_label
, flags_label
, timeout_label
,
1958 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfsw_recvmsg(
1959 int sockfd
, struct msghdr
*msg
, int flags
, dfsan_label sockfd_label
,
1960 dfsan_label msg_label
, dfsan_label flags_label
, dfsan_label
*ret_label
) {
1961 ssize_t ret
= recvmsg(sockfd
, msg
, flags
);
1963 clear_msghdr_labels(ret
, msg
, flags
);
1968 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfso_recvmsg(
1969 int sockfd
, struct msghdr
*msg
, int flags
, dfsan_label sockfd_label
,
1970 dfsan_label msg_label
, dfsan_label flags_label
, dfsan_label
*ret_label
,
1971 dfsan_origin sockfd_origin
, dfsan_origin msg_origin
,
1972 dfsan_origin flags_origin
, dfsan_origin
*ret_origin
) {
1973 return __dfsw_recvmsg(sockfd
, msg
, flags
, sockfd_label
, msg_label
,
1974 flags_label
, ret_label
);
1977 SANITIZER_INTERFACE_ATTRIBUTE
int
1978 __dfsw_socketpair(int domain
, int type
, int protocol
, int sv
[2],
1979 dfsan_label domain_label
, dfsan_label type_label
,
1980 dfsan_label protocol_label
, dfsan_label sv_label
,
1981 dfsan_label
*ret_label
) {
1982 int ret
= socketpair(domain
, type
, protocol
, sv
);
1985 dfsan_set_label(0, sv
, sizeof(*sv
) * 2);
1990 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_socketpair(
1991 int domain
, int type
, int protocol
, int sv
[2], dfsan_label domain_label
,
1992 dfsan_label type_label
, dfsan_label protocol_label
, dfsan_label sv_label
,
1993 dfsan_label
*ret_label
, dfsan_origin domain_origin
,
1994 dfsan_origin type_origin
, dfsan_origin protocol_origin
,
1995 dfsan_origin sv_origin
, dfsan_origin
*ret_origin
) {
1996 return __dfsw_socketpair(domain
, type
, protocol
, sv
, domain_label
, type_label
,
1997 protocol_label
, sv_label
, ret_label
);
2000 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_getsockopt(
2001 int sockfd
, int level
, int optname
, void *optval
, socklen_t
*optlen
,
2002 dfsan_label sockfd_label
, dfsan_label level_label
,
2003 dfsan_label optname_label
, dfsan_label optval_label
,
2004 dfsan_label optlen_label
, dfsan_label
*ret_label
) {
2005 int ret
= getsockopt(sockfd
, level
, optname
, optval
, optlen
);
2006 if (ret
!= -1 && optval
&& optlen
) {
2007 dfsan_set_label(0, optlen
, sizeof(*optlen
));
2008 dfsan_set_label(0, optval
, *optlen
);
2014 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_getsockopt(
2015 int sockfd
, int level
, int optname
, void *optval
, socklen_t
*optlen
,
2016 dfsan_label sockfd_label
, dfsan_label level_label
,
2017 dfsan_label optname_label
, dfsan_label optval_label
,
2018 dfsan_label optlen_label
, dfsan_label
*ret_label
,
2019 dfsan_origin sockfd_origin
, dfsan_origin level_origin
,
2020 dfsan_origin optname_origin
, dfsan_origin optval_origin
,
2021 dfsan_origin optlen_origin
, dfsan_origin
*ret_origin
) {
2022 return __dfsw_getsockopt(sockfd
, level
, optname
, optval
, optlen
, sockfd_label
,
2023 level_label
, optname_label
, optval_label
,
2024 optlen_label
, ret_label
);
2027 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_getsockname(
2028 int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
,
2029 dfsan_label sockfd_label
, dfsan_label addr_label
, dfsan_label addrlen_label
,
2030 dfsan_label
*ret_label
) {
2031 socklen_t origlen
= addrlen
? *addrlen
: 0;
2032 int ret
= getsockname(sockfd
, addr
, addrlen
);
2033 if (ret
!= -1 && addr
&& addrlen
) {
2034 socklen_t written_bytes
= origlen
< *addrlen
? origlen
: *addrlen
;
2035 dfsan_set_label(0, addrlen
, sizeof(*addrlen
));
2036 dfsan_set_label(0, addr
, written_bytes
);
2042 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_getsockname(
2043 int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
,
2044 dfsan_label sockfd_label
, dfsan_label addr_label
, dfsan_label addrlen_label
,
2045 dfsan_label
*ret_label
, dfsan_origin sockfd_origin
,
2046 dfsan_origin addr_origin
, dfsan_origin addrlen_origin
,
2047 dfsan_origin
*ret_origin
) {
2048 return __dfsw_getsockname(sockfd
, addr
, addrlen
, sockfd_label
, addr_label
,
2049 addrlen_label
, ret_label
);
2052 SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_getpeername(
2053 int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
,
2054 dfsan_label sockfd_label
, dfsan_label addr_label
, dfsan_label addrlen_label
,
2055 dfsan_label
*ret_label
) {
2056 socklen_t origlen
= addrlen
? *addrlen
: 0;
2057 int ret
= getpeername(sockfd
, addr
, addrlen
);
2058 if (ret
!= -1 && addr
&& addrlen
) {
2059 socklen_t written_bytes
= origlen
< *addrlen
? origlen
: *addrlen
;
2060 dfsan_set_label(0, addrlen
, sizeof(*addrlen
));
2061 dfsan_set_label(0, addr
, written_bytes
);
2067 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_getpeername(
2068 int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
,
2069 dfsan_label sockfd_label
, dfsan_label addr_label
, dfsan_label addrlen_label
,
2070 dfsan_label
*ret_label
, dfsan_origin sockfd_origin
,
2071 dfsan_origin addr_origin
, dfsan_origin addrlen_origin
,
2072 dfsan_origin
*ret_origin
) {
2073 return __dfsw_getpeername(sockfd
, addr
, addrlen
, sockfd_label
, addr_label
,
2074 addrlen_label
, ret_label
);
2077 // Type of the function passed to dfsan_set_write_callback.
2078 typedef void (*write_dfsan_callback_t
)(int fd
, const void *buf
, ssize_t count
);
2080 // Calls to dfsan_set_write_callback() set the values in this struct.
2081 // Calls to the custom version of write() read (and invoke) them.
2083 write_dfsan_callback_t write_callback
= nullptr;
2084 } write_callback_info
;
2086 SANITIZER_INTERFACE_ATTRIBUTE
void __dfsw_dfsan_set_write_callback(
2087 write_dfsan_callback_t write_callback
, dfsan_label write_callback_label
,
2088 dfsan_label
*ret_label
) {
2089 write_callback_info
.write_callback
= write_callback
;
2092 SANITIZER_INTERFACE_ATTRIBUTE
void __dfso_dfsan_set_write_callback(
2093 write_dfsan_callback_t write_callback
, dfsan_label write_callback_label
,
2094 dfsan_label
*ret_label
, dfsan_origin write_callback_origin
,
2095 dfsan_origin
*ret_origin
) {
2096 write_callback_info
.write_callback
= write_callback
;
2099 static inline void setup_tls_args_for_write_callback(
2100 dfsan_label fd_label
, dfsan_label buf_label
, dfsan_label count_label
,
2101 bool origins
, dfsan_origin fd_origin
, dfsan_origin buf_origin
,
2102 dfsan_origin count_origin
) {
2103 // The callback code will expect argument shadow labels in the args TLS,
2104 // and origin labels in the origin args TLS.
2105 // Previously this was done by a trampoline, but we want to remove this:
2106 // https://github.com/llvm/llvm-project/issues/54172
2108 // Instead, this code is manually setting up the args TLS data.
2110 // The offsets used need to correspond with the instrumentation code,
2111 // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
2112 // DFSanFunction::getShadowForTLSArgument.
2113 // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
2114 // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
2116 // Here the arguments are all primitives, but it can be more complex
2117 // to compute offsets for array/aggregate type arguments.
2119 // TODO(browneee): Consider a builtin to improve maintainabliity.
2120 // With a builtin, we would provide the argument labels via builtin,
2121 // and the builtin would reuse parts of the instrumentation code to ensure
2122 // that this code and the instrumentation can never be out of sync.
2123 // Note: Currently DFSan instrumentation does not run on this code, so
2124 // the builtin may need to be handled outside DFSan instrumentation.
2125 dfsan_set_arg_tls(0, fd_label
);
2126 dfsan_set_arg_tls(1, buf_label
);
2127 dfsan_set_arg_tls(2, count_label
);
2129 dfsan_set_arg_origin_tls(0, fd_origin
);
2130 dfsan_set_arg_origin_tls(1, buf_origin
);
2131 dfsan_set_arg_origin_tls(2, count_origin
);
2135 SANITIZER_INTERFACE_ATTRIBUTE
int
2136 __dfsw_write(int fd
, const void *buf
, size_t count
,
2137 dfsan_label fd_label
, dfsan_label buf_label
,
2138 dfsan_label count_label
, dfsan_label
*ret_label
) {
2139 if (write_callback_info
.write_callback
) {
2140 setup_tls_args_for_write_callback(fd_label
, buf_label
, count_label
, false,
2142 write_callback_info
.write_callback(fd
, buf
, count
);
2146 return write(fd
, buf
, count
);
2149 SANITIZER_INTERFACE_ATTRIBUTE
int __dfso_write(
2150 int fd
, const void *buf
, size_t count
, dfsan_label fd_label
,
2151 dfsan_label buf_label
, dfsan_label count_label
, dfsan_label
*ret_label
,
2152 dfsan_origin fd_origin
, dfsan_origin buf_origin
, dfsan_origin count_origin
,
2153 dfsan_origin
*ret_origin
) {
2154 if (write_callback_info
.write_callback
) {
2155 setup_tls_args_for_write_callback(fd_label
, buf_label
, count_label
, true,
2156 fd_origin
, buf_origin
, count_origin
);
2157 write_callback_info
.write_callback(fd
, buf
, count
);
2161 return write(fd
, buf
, count
);
2163 } // namespace __dfsan
2165 // Type used to extract a dfsan_label with va_arg()
2166 typedef int dfsan_label_va
;
2168 // Formats a chunk either a constant string or a single format directive (e.g.,
2171 Formatter(char *str_
, const char *fmt_
, size_t size_
)
2182 char *tmp_fmt
= build_format_string();
2184 snprintf(str
+ str_off
, str_off
< size
? size
- str_off
: 0, tmp_fmt
,
2185 0 /* used only to avoid warnings */);
2190 template <typename T
> int format(T arg
) {
2191 char *tmp_fmt
= build_format_string();
2194 retval
= snprintf(str
+ str_off
, str_off
< size
? size
- str_off
: 0,
2195 tmp_fmt
, width
, arg
);
2197 retval
= snprintf(str
+ str_off
, str_off
< size
? size
- str_off
: 0,
2204 char *build_format_string() {
2205 size_t fmt_size
= fmt_cur
- fmt_start
+ 1;
2206 char *new_fmt
= (char *)malloc(fmt_size
+ 1);
2208 internal_memcpy(new_fmt
, fmt_start
, fmt_size
);
2209 new_fmt
[fmt_size
] = '\0';
2213 char *str_cur() { return str
+ str_off
; }
2215 size_t num_written_bytes(int retval
) {
2220 size_t num_avail
= str_off
< size
? size
- str_off
: 0;
2221 if (num_avail
== 0) {
2225 size_t num_written
= retval
;
2226 // A return value of {v,}snprintf of size or more means that the output was
2228 if (num_written
>= num_avail
) {
2229 num_written
-= num_avail
;
2238 const char *fmt_start
;
2239 const char *fmt_cur
;
2245 // Formats the input and propagates the input labels to the output. The output
2246 // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
2247 // 'ap' are the format string and the list of arguments for formatting. Returns
2248 // the return value vsnprintf would return.
2250 // The function tokenizes the format string in chunks representing either a
2251 // constant string or a single format directive (e.g., '%.3f') and formats each
2252 // chunk independently into the output string. This approach allows to figure
2253 // out which bytes of the output string depends on which argument and thus to
2254 // propagate labels more precisely.
2256 // WARNING: This implementation does not support conversion specifiers with
2257 // positional arguments.
2258 static int format_buffer(char *str
, size_t size
, const char *fmt
,
2259 dfsan_label
*va_labels
, dfsan_label
*ret_label
,
2260 dfsan_origin
*va_origins
, dfsan_origin
*ret_origin
,
2262 Formatter
formatter(str
, fmt
, size
);
2264 while (*formatter
.fmt_cur
) {
2265 formatter
.fmt_start
= formatter
.fmt_cur
;
2266 formatter
.width
= -1;
2269 if (*formatter
.fmt_cur
!= '%') {
2270 // Ordinary character. Consume all the characters until a '%' or the end
2272 for (; *(formatter
.fmt_cur
+ 1) && *(formatter
.fmt_cur
+ 1) != '%';
2273 ++formatter
.fmt_cur
) {}
2274 retval
= formatter
.format();
2275 dfsan_set_label(0, formatter
.str_cur(),
2276 formatter
.num_written_bytes(retval
));
2278 // Conversion directive. Consume all the characters until a conversion
2279 // specifier or the end of the string.
2280 bool end_fmt
= false;
2281 for (; *formatter
.fmt_cur
&& !end_fmt
; ) {
2282 switch (*++formatter
.fmt_cur
) {
2289 switch (*(formatter
.fmt_cur
- 1)) {
2291 // Also covers the 'hh' case (since the size of the arg is still
2293 retval
= formatter
.format(va_arg(ap
, int));
2296 if (formatter
.fmt_cur
- formatter
.fmt_start
>= 2 &&
2297 *(formatter
.fmt_cur
- 2) == 'l') {
2298 retval
= formatter
.format(va_arg(ap
, long long int));
2300 retval
= formatter
.format(va_arg(ap
, long int));
2304 retval
= formatter
.format(va_arg(ap
, long long int));
2307 retval
= formatter
.format(va_arg(ap
, intmax_t));
2311 retval
= formatter
.format(va_arg(ap
, size_t));
2314 retval
= formatter
.format(va_arg(ap
, int));
2316 if (va_origins
== nullptr)
2317 dfsan_set_label(*va_labels
++, formatter
.str_cur(),
2318 formatter
.num_written_bytes(retval
));
2320 dfsan_set_label_origin(*va_labels
++, *va_origins
++,
2321 formatter
.str_cur(),
2322 formatter
.num_written_bytes(retval
));
2334 if (*(formatter
.fmt_cur
- 1) == 'L') {
2335 retval
= formatter
.format(va_arg(ap
, long double));
2337 retval
= formatter
.format(va_arg(ap
, double));
2339 if (va_origins
== nullptr)
2340 dfsan_set_label(*va_labels
++, formatter
.str_cur(),
2341 formatter
.num_written_bytes(retval
));
2343 dfsan_set_label_origin(*va_labels
++, *va_origins
++,
2344 formatter
.str_cur(),
2345 formatter
.num_written_bytes(retval
));
2350 retval
= formatter
.format(va_arg(ap
, int));
2351 if (va_origins
== nullptr)
2352 dfsan_set_label(*va_labels
++, formatter
.str_cur(),
2353 formatter
.num_written_bytes(retval
));
2355 dfsan_set_label_origin(*va_labels
++, *va_origins
++,
2356 formatter
.str_cur(),
2357 formatter
.num_written_bytes(retval
));
2362 char *arg
= va_arg(ap
, char *);
2363 retval
= formatter
.format(arg
);
2366 dfsan_mem_origin_transfer(formatter
.str_cur(), arg
,
2367 formatter
.num_written_bytes(retval
));
2370 dfsan_mem_shadow_transfer(formatter
.str_cur(), arg
,
2371 formatter
.num_written_bytes(retval
));
2377 retval
= formatter
.format(va_arg(ap
, void *));
2378 if (va_origins
== nullptr)
2379 dfsan_set_label(*va_labels
++, formatter
.str_cur(),
2380 formatter
.num_written_bytes(retval
));
2382 dfsan_set_label_origin(*va_labels
++, *va_origins
++,
2383 formatter
.str_cur(),
2384 formatter
.num_written_bytes(retval
));
2389 int *ptr
= va_arg(ap
, int *);
2390 *ptr
= (int)formatter
.str_off
;
2394 dfsan_set_label(0, ptr
, sizeof(ptr
));
2400 retval
= formatter
.format();
2401 dfsan_set_label(0, formatter
.str_cur(),
2402 formatter
.num_written_bytes(retval
));
2407 formatter
.width
= va_arg(ap
, int);
2423 formatter
.fmt_cur
++;
2424 formatter
.str_off
+= retval
;
2431 // Number of bytes written in total.
2432 return formatter
.str_off
;
2435 // Scans a chunk either a constant string or a single format directive (e.g.,
2438 Scanner(char *str_
, const char *fmt_
, size_t size_
)
2448 // Consumes a chunk of ordinary characters.
2449 // Returns number of matching ordinary characters.
2450 // Returns -1 if the match failed.
2451 // In format strings, a space will match multiple spaces.
2452 int check_match_ordinary() {
2453 char *tmp_fmt
= build_format_string_with_n();
2454 int read_count
= -1;
2455 sscanf(str
+ str_off
, tmp_fmt
, &read_count
);
2457 if (read_count
> 0) {
2458 str_off
+= read_count
;
2464 char *tmp_fmt
= build_format_string_with_n();
2466 int retval
= sscanf(str
+ str_off
, tmp_fmt
, &read_count
);
2469 num_scanned
+= retval
;
2474 template <typename T
>
2476 char *tmp_fmt
= build_format_string_with_n();
2478 int retval
= sscanf(str
+ str_off
, tmp_fmt
, arg
, &read_count
);
2481 num_scanned
+= retval
;
2486 // Adds %n onto current format string to measure length.
2487 char *build_format_string_with_n() {
2488 size_t fmt_size
= fmt_cur
- fmt_start
+ 1;
2489 // +2 for %n, +1 for \0
2490 char *new_fmt
= (char *)malloc(fmt_size
+ 2 + 1);
2492 internal_memcpy(new_fmt
, fmt_start
, fmt_size
);
2493 new_fmt
[fmt_size
] = '%';
2494 new_fmt
[fmt_size
+ 1] = 'n';
2495 new_fmt
[fmt_size
+ 2] = '\0';
2499 char *str_cur() { return str
+ str_off
; }
2501 size_t num_written_bytes(int retval
) {
2506 size_t num_avail
= str_off
< size
? size
- str_off
: 0;
2507 if (num_avail
== 0) {
2511 size_t num_written
= retval
;
2512 // A return value of {v,}snprintf of size or more means that the output was
2514 if (num_written
>= num_avail
) {
2515 num_written
-= num_avail
;
2524 const char *fmt_start
;
2525 const char *fmt_cur
;
2531 // This function is an inverse of format_buffer: we take the input buffer,
2532 // scan it in search for format strings and store the results in the varargs.
2533 // The labels are propagated from the input buffer to the varargs.
2534 static int scan_buffer(char *str
, size_t size
, const char *fmt
,
2535 dfsan_label
*va_labels
, dfsan_label
*ret_label
,
2536 dfsan_origin
*str_origin
, dfsan_origin
*ret_origin
,
2538 Scanner
scanner(str
, fmt
, size
);
2539 while (*scanner
.fmt_cur
) {
2540 scanner
.fmt_start
= scanner
.fmt_cur
;
2542 scanner
.skip
= false;
2545 size_t write_size
= 0;
2546 if (*scanner
.fmt_cur
!= '%') {
2547 // Ordinary character and spaces.
2548 // Consume all the characters until a '%' or the end of the string.
2549 for (; *(scanner
.fmt_cur
+ 1) && *(scanner
.fmt_cur
+ 1) != '%';
2550 ++scanner
.fmt_cur
) {
2552 if (scanner
.check_match_ordinary() < 0) {
2553 // The ordinary characters did not match.
2557 // Conversion directive. Consume all the characters until a conversion
2558 // specifier or the end of the string.
2559 bool end_fmt
= false;
2560 for (; *scanner
.fmt_cur
&& !end_fmt
;) {
2561 switch (*++scanner
.fmt_cur
) {
2569 read_count
= scanner
.scan();
2571 switch (*(scanner
.fmt_cur
- 1)) {
2573 // Also covers the 'hh' case (since the size of the arg is
2575 dst_ptr
= va_arg(ap
, int *);
2576 read_count
= scanner
.scan((int *)dst_ptr
);
2577 write_size
= sizeof(int);
2580 if (scanner
.fmt_cur
- scanner
.fmt_start
>= 2 &&
2581 *(scanner
.fmt_cur
- 2) == 'l') {
2582 dst_ptr
= va_arg(ap
, long long int *);
2583 read_count
= scanner
.scan((long long int *)dst_ptr
);
2584 write_size
= sizeof(long long int);
2586 dst_ptr
= va_arg(ap
, long int *);
2587 read_count
= scanner
.scan((long int *)dst_ptr
);
2588 write_size
= sizeof(long int);
2592 dst_ptr
= va_arg(ap
, long long int *);
2593 read_count
= scanner
.scan((long long int *)dst_ptr
);
2594 write_size
= sizeof(long long int);
2597 dst_ptr
= va_arg(ap
, intmax_t *);
2598 read_count
= scanner
.scan((intmax_t *)dst_ptr
);
2599 write_size
= sizeof(intmax_t);
2603 dst_ptr
= va_arg(ap
, size_t *);
2604 read_count
= scanner
.scan((size_t *)dst_ptr
);
2605 write_size
= sizeof(size_t);
2608 dst_ptr
= va_arg(ap
, int *);
2609 read_count
= scanner
.scan((int *)dst_ptr
);
2610 write_size
= sizeof(int);
2612 // get the label associated with the string at the corresponding
2614 dfsan_label l
= dfsan_read_label(
2615 scanner
.str_cur(), scanner
.num_written_bytes(read_count
));
2616 dfsan_set_label(l
, dst_ptr
, write_size
);
2617 if (str_origin
!= nullptr) {
2618 dfsan_set_label(l
, dst_ptr
, write_size
);
2619 size_t scan_count
= scanner
.num_written_bytes(read_count
);
2620 size_t size
= scan_count
> write_size
? write_size
: scan_count
;
2621 dfsan_mem_origin_transfer(dst_ptr
, scanner
.str_cur(), size
);
2637 read_count
= scanner
.scan();
2639 if (*(scanner
.fmt_cur
- 1) == 'L') {
2640 dst_ptr
= va_arg(ap
, long double *);
2641 read_count
= scanner
.scan((long double *)dst_ptr
);
2642 write_size
= sizeof(long double);
2643 } else if (*(scanner
.fmt_cur
- 1) == 'l') {
2644 dst_ptr
= va_arg(ap
, double *);
2645 read_count
= scanner
.scan((double *)dst_ptr
);
2646 write_size
= sizeof(double);
2648 dst_ptr
= va_arg(ap
, float *);
2649 read_count
= scanner
.scan((float *)dst_ptr
);
2650 write_size
= sizeof(float);
2652 dfsan_label l
= dfsan_read_label(
2653 scanner
.str_cur(), scanner
.num_written_bytes(read_count
));
2654 dfsan_set_label(l
, dst_ptr
, write_size
);
2655 if (str_origin
!= nullptr) {
2656 dfsan_set_label(l
, dst_ptr
, write_size
);
2657 size_t scan_count
= scanner
.num_written_bytes(read_count
);
2658 size_t size
= scan_count
> write_size
? write_size
: scan_count
;
2659 dfsan_mem_origin_transfer(dst_ptr
, scanner
.str_cur(), size
);
2667 read_count
= scanner
.scan();
2669 dst_ptr
= va_arg(ap
, char *);
2670 read_count
= scanner
.scan((char *)dst_ptr
);
2671 write_size
= sizeof(char);
2672 dfsan_label l
= dfsan_read_label(
2673 scanner
.str_cur(), scanner
.num_written_bytes(read_count
));
2674 dfsan_set_label(l
, dst_ptr
, write_size
);
2675 if (str_origin
!= nullptr) {
2676 size_t scan_count
= scanner
.num_written_bytes(read_count
);
2677 size_t size
= scan_count
> write_size
? write_size
: scan_count
;
2678 dfsan_mem_origin_transfer(dst_ptr
, scanner
.str_cur(), size
);
2686 read_count
= scanner
.scan();
2688 dst_ptr
= va_arg(ap
, char *);
2689 read_count
= scanner
.scan((char *)dst_ptr
);
2690 if (1 == read_count
) {
2691 // special case: we have parsed a single string and we need to
2692 // update read_count with the string size
2693 read_count
= strlen((char *)dst_ptr
);
2696 dfsan_mem_origin_transfer(
2697 dst_ptr
, scanner
.str_cur(),
2698 scanner
.num_written_bytes(read_count
));
2700 dfsan_mem_shadow_transfer(dst_ptr
, scanner
.str_cur(),
2701 scanner
.num_written_bytes(read_count
));
2709 read_count
= scanner
.scan();
2711 dst_ptr
= va_arg(ap
, void *);
2713 scanner
.scan((int *)dst_ptr
); // note: changing void* to int*
2714 // since we need to call sizeof
2715 write_size
= sizeof(int);
2717 dfsan_label l
= dfsan_read_label(
2718 scanner
.str_cur(), scanner
.num_written_bytes(read_count
));
2719 dfsan_set_label(l
, dst_ptr
, write_size
);
2720 if (str_origin
!= nullptr) {
2721 dfsan_set_label(l
, dst_ptr
, write_size
);
2722 size_t scan_count
= scanner
.num_written_bytes(read_count
);
2723 size_t size
= scan_count
> write_size
? write_size
: scan_count
;
2724 dfsan_mem_origin_transfer(dst_ptr
, scanner
.str_cur(), size
);
2731 if (!scanner
.skip
) {
2732 int *ptr
= va_arg(ap
, int *);
2733 *ptr
= (int)scanner
.str_off
;
2735 dfsan_set_label(0, ptr
, sizeof(*ptr
));
2736 if (str_origin
!= nullptr)
2744 read_count
= scanner
.scan();
2749 scanner
.skip
= true;
2758 if (read_count
< 0) {
2759 // There was an error.
2764 scanner
.str_off
+= read_count
;
2767 (void)va_labels
; // Silence unused-but-set-parameter warning
2772 // Number of items scanned in total.
2773 return scanner
.num_scanned
;
2777 SANITIZER_INTERFACE_ATTRIBUTE
2778 int __dfsw_sprintf(char *str
, const char *format
, dfsan_label str_label
,
2779 dfsan_label format_label
, dfsan_label
*va_labels
,
2780 dfsan_label
*ret_label
, ...) {
2782 va_start(ap
, ret_label
);
2784 int ret
= format_buffer(str
, INT32_MAX
, format
, va_labels
, ret_label
, nullptr,
2790 SANITIZER_INTERFACE_ATTRIBUTE
2791 int __dfso_sprintf(char *str
, const char *format
, dfsan_label str_label
,
2792 dfsan_label format_label
, dfsan_label
*va_labels
,
2793 dfsan_label
*ret_label
, dfsan_origin str_origin
,
2794 dfsan_origin format_origin
, dfsan_origin
*va_origins
,
2795 dfsan_origin
*ret_origin
, ...) {
2797 va_start(ap
, ret_origin
);
2798 int ret
= format_buffer(str
, INT32_MAX
, format
, va_labels
, ret_label
,
2799 va_origins
, ret_origin
, ap
);
2804 SANITIZER_INTERFACE_ATTRIBUTE
2805 int __dfsw_snprintf(char *str
, size_t size
, const char *format
,
2806 dfsan_label str_label
, dfsan_label size_label
,
2807 dfsan_label format_label
, dfsan_label
*va_labels
,
2808 dfsan_label
*ret_label
, ...) {
2810 va_start(ap
, ret_label
);
2811 int ret
= format_buffer(str
, size
, format
, va_labels
, ret_label
, nullptr,
2817 SANITIZER_INTERFACE_ATTRIBUTE
2818 int __dfso_snprintf(char *str
, size_t size
, const char *format
,
2819 dfsan_label str_label
, dfsan_label size_label
,
2820 dfsan_label format_label
, dfsan_label
*va_labels
,
2821 dfsan_label
*ret_label
, dfsan_origin str_origin
,
2822 dfsan_origin size_origin
, dfsan_origin format_origin
,
2823 dfsan_origin
*va_origins
, dfsan_origin
*ret_origin
, ...) {
2825 va_start(ap
, ret_origin
);
2826 int ret
= format_buffer(str
, size
, format
, va_labels
, ret_label
, va_origins
,
2832 SANITIZER_INTERFACE_ATTRIBUTE
2833 int __dfsw_sscanf(char *str
, const char *format
, dfsan_label str_label
,
2834 dfsan_label format_label
, dfsan_label
*va_labels
,
2835 dfsan_label
*ret_label
, ...) {
2837 va_start(ap
, ret_label
);
2838 int ret
= scan_buffer(str
, ~0ul, format
, va_labels
, ret_label
, nullptr,
2844 SANITIZER_INTERFACE_ATTRIBUTE
2845 int __dfso_sscanf(char *str
, const char *format
, dfsan_label str_label
,
2846 dfsan_label format_label
, dfsan_label
*va_labels
,
2847 dfsan_label
*ret_label
, dfsan_origin str_origin
,
2848 dfsan_origin format_origin
, dfsan_origin
*va_origins
,
2849 dfsan_origin
*ret_origin
, ...) {
2851 va_start(ap
, ret_origin
);
2852 int ret
= scan_buffer(str
, ~0ul, format
, va_labels
, ret_label
, &str_origin
,
2858 WRAPPER_ALIAS(__isoc99_sscanf
, sscanf
)
2859 WRAPPER_ALIAS(__isoc23_sscanf
, sscanf
)
2861 static void BeforeFork() {
2862 VReport(2, "BeforeFork tid: %llu\n", GetTid());
2863 StackDepotLockBeforeFork();
2864 ChainedOriginDepotLockBeforeFork();
2867 static void AfterFork(bool fork_child
) {
2868 ChainedOriginDepotUnlockAfterFork(fork_child
);
2869 StackDepotUnlockAfterFork(fork_child
);
2870 VReport(2, "AfterFork tid: %llu\n", GetTid());
2873 SANITIZER_INTERFACE_ATTRIBUTE
2874 pid_t
__dfsw_fork(dfsan_label
*ret_label
) {
2880 SANITIZER_INTERFACE_ATTRIBUTE
2881 pid_t
__dfso_fork(dfsan_label
*ret_label
, dfsan_origin
*ret_origin
) {
2883 pid_t pid
= __dfsw_fork(ret_label
);
2884 AfterFork(/* fork_child= */ pid
== 0);
2888 // Default empty implementations (weak). Users should redefine them.
2889 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard
, u32
*) {}
2890 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init
, u32
*,
2892 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init
, const uptr
*beg
,
2894 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir
, void) {}
2896 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp
, void) {}
2897 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1
, void) {}
2898 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2
, void) {}
2899 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4
, void) {}
2900 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8
, void) {}
2901 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1
,
2903 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2
,
2905 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4
,
2907 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8
,
2909 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch
, void) {}