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