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