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

source code of compiler-rt/lib/dfsan/dfsan_custom.cpp