1d89ec533Spatrick //===-- dfsan_custom.cpp --------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of DataFlowSanitizer.
103cab2bb3Spatrick //
113cab2bb3Spatrick // This file defines the custom functions listed in done_abilist.txt.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
143cab2bb3Spatrick #include <arpa/inet.h>
153cab2bb3Spatrick #include <assert.h>
163cab2bb3Spatrick #include <ctype.h>
173cab2bb3Spatrick #include <dlfcn.h>
183cab2bb3Spatrick #include <link.h>
193cab2bb3Spatrick #include <poll.h>
203cab2bb3Spatrick #include <pthread.h>
213cab2bb3Spatrick #include <pwd.h>
223cab2bb3Spatrick #include <sched.h>
233cab2bb3Spatrick #include <signal.h>
243cab2bb3Spatrick #include <stdarg.h>
253cab2bb3Spatrick #include <stdint.h>
263cab2bb3Spatrick #include <stdio.h>
273cab2bb3Spatrick #include <stdlib.h>
283cab2bb3Spatrick #include <string.h>
29d89ec533Spatrick #include <sys/epoll.h>
303cab2bb3Spatrick #include <sys/resource.h>
313cab2bb3Spatrick #include <sys/select.h>
32d89ec533Spatrick #include <sys/socket.h>
333cab2bb3Spatrick #include <sys/stat.h>
343cab2bb3Spatrick #include <sys/time.h>
353cab2bb3Spatrick #include <sys/types.h>
363cab2bb3Spatrick #include <time.h>
373cab2bb3Spatrick #include <unistd.h>
383cab2bb3Spatrick
39d89ec533Spatrick #include "dfsan/dfsan.h"
40d89ec533Spatrick #include "dfsan/dfsan_chained_origin_depot.h"
41d89ec533Spatrick #include "dfsan/dfsan_flags.h"
42d89ec533Spatrick #include "dfsan/dfsan_thread.h"
43d89ec533Spatrick #include "sanitizer_common/sanitizer_common.h"
44d89ec533Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
45d89ec533Spatrick #include "sanitizer_common/sanitizer_linux.h"
46d89ec533Spatrick #include "sanitizer_common/sanitizer_stackdepot.h"
47d89ec533Spatrick
483cab2bb3Spatrick using namespace __dfsan;
493cab2bb3Spatrick
503cab2bb3Spatrick #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \
513cab2bb3Spatrick do { \
523cab2bb3Spatrick if (f) \
533cab2bb3Spatrick f(__VA_ARGS__); \
543cab2bb3Spatrick } while (false)
553cab2bb3Spatrick #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
563cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
573cab2bb3Spatrick
58d89ec533Spatrick // Async-safe, non-reentrant spin lock.
59d89ec533Spatrick class SignalSpinLocker {
60d89ec533Spatrick public:
SignalSpinLocker()61d89ec533Spatrick SignalSpinLocker() {
62d89ec533Spatrick sigset_t all_set;
63d89ec533Spatrick sigfillset(&all_set);
64d89ec533Spatrick pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
65d89ec533Spatrick sigactions_mu.Lock();
66d89ec533Spatrick }
~SignalSpinLocker()67d89ec533Spatrick ~SignalSpinLocker() {
68d89ec533Spatrick sigactions_mu.Unlock();
69d89ec533Spatrick pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
70d89ec533Spatrick }
71d89ec533Spatrick
72d89ec533Spatrick private:
73d89ec533Spatrick static StaticSpinMutex sigactions_mu;
74d89ec533Spatrick sigset_t saved_thread_mask_;
75d89ec533Spatrick
76d89ec533Spatrick SignalSpinLocker(const SignalSpinLocker &) = delete;
77d89ec533Spatrick SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
78d89ec533Spatrick };
79d89ec533Spatrick
80d89ec533Spatrick StaticSpinMutex SignalSpinLocker::sigactions_mu;
81d89ec533Spatrick
823cab2bb3Spatrick extern "C" {
833cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_stat(const char * path,struct stat * buf,dfsan_label path_label,dfsan_label buf_label,dfsan_label * ret_label)843cab2bb3Spatrick __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
853cab2bb3Spatrick dfsan_label buf_label, dfsan_label *ret_label) {
863cab2bb3Spatrick int ret = stat(path, buf);
873cab2bb3Spatrick if (ret == 0)
883cab2bb3Spatrick dfsan_set_label(0, buf, sizeof(struct stat));
893cab2bb3Spatrick *ret_label = 0;
903cab2bb3Spatrick return ret;
913cab2bb3Spatrick }
923cab2bb3Spatrick
__dfso_stat(const char * path,struct stat * buf,dfsan_label path_label,dfsan_label buf_label,dfsan_label * ret_label,dfsan_origin path_origin,dfsan_origin buf_origin,dfsan_origin * ret_origin)93d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
94d89ec533Spatrick const char *path, struct stat *buf, dfsan_label path_label,
95d89ec533Spatrick dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
96d89ec533Spatrick dfsan_origin buf_origin, dfsan_origin *ret_origin) {
97d89ec533Spatrick int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
98d89ec533Spatrick return ret;
99d89ec533Spatrick }
100d89ec533Spatrick
__dfsw_fstat(int fd,struct stat * buf,dfsan_label fd_label,dfsan_label buf_label,dfsan_label * ret_label)1013cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
1023cab2bb3Spatrick dfsan_label fd_label,
1033cab2bb3Spatrick dfsan_label buf_label,
1043cab2bb3Spatrick dfsan_label *ret_label) {
1053cab2bb3Spatrick int ret = fstat(fd, buf);
1063cab2bb3Spatrick if (ret == 0)
1073cab2bb3Spatrick dfsan_set_label(0, buf, sizeof(struct stat));
1083cab2bb3Spatrick *ret_label = 0;
1093cab2bb3Spatrick return ret;
1103cab2bb3Spatrick }
1113cab2bb3Spatrick
__dfso_fstat(int fd,struct stat * buf,dfsan_label fd_label,dfsan_label buf_label,dfsan_label * ret_label,dfsan_origin fd_origin,dfsan_origin buf_origin,dfsan_origin * ret_origin)112d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
113d89ec533Spatrick int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
114d89ec533Spatrick dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
115d89ec533Spatrick dfsan_origin *ret_origin) {
116d89ec533Spatrick int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
117d89ec533Spatrick return ret;
118d89ec533Spatrick }
119d89ec533Spatrick
dfsan_strchr_with_label(const char * s,int c,size_t * bytes_read,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label)120d89ec533Spatrick static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
121d89ec533Spatrick dfsan_label s_label, dfsan_label c_label,
122d89ec533Spatrick dfsan_label *ret_label) {
123d89ec533Spatrick char *match_pos = nullptr;
124d89ec533Spatrick for (size_t i = 0;; ++i) {
125d89ec533Spatrick if (s[i] == c || s[i] == 0) {
126d89ec533Spatrick // If s[i] is the \0 at the end of the string, and \0 is not the
127d89ec533Spatrick // character we are searching for, then return null.
128d89ec533Spatrick *bytes_read = i + 1;
129d89ec533Spatrick match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
130d89ec533Spatrick break;
131d89ec533Spatrick }
132d89ec533Spatrick }
133d89ec533Spatrick if (flags().strict_data_dependencies)
134d89ec533Spatrick *ret_label = s_label;
135d89ec533Spatrick else
136d89ec533Spatrick *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
137d89ec533Spatrick dfsan_union(s_label, c_label));
138d89ec533Spatrick return match_pos;
139d89ec533Spatrick }
140d89ec533Spatrick
__dfsw_strchr(const char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label)1413cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
1423cab2bb3Spatrick dfsan_label s_label,
1433cab2bb3Spatrick dfsan_label c_label,
1443cab2bb3Spatrick dfsan_label *ret_label) {
145d89ec533Spatrick size_t bytes_read;
146d89ec533Spatrick return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
147d89ec533Spatrick ret_label);
1483cab2bb3Spatrick }
1491f9cb04fSpatrick
__dfso_strchr(const char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin c_origin,dfsan_origin * ret_origin)150d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
151d89ec533Spatrick const char *s, int c, dfsan_label s_label, dfsan_label c_label,
152d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
153d89ec533Spatrick dfsan_origin *ret_origin) {
154d89ec533Spatrick size_t bytes_read;
155d89ec533Spatrick char *r =
156d89ec533Spatrick dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
157d89ec533Spatrick if (flags().strict_data_dependencies) {
158d89ec533Spatrick *ret_origin = s_origin;
159d89ec533Spatrick } else if (*ret_label) {
160d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
161d89ec533Spatrick *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1621f9cb04fSpatrick }
163d89ec533Spatrick return r;
164d89ec533Spatrick }
165d89ec533Spatrick
__dfsw_strpbrk(const char * s,const char * accept,dfsan_label s_label,dfsan_label accept_label,dfsan_label * ret_label)166d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
167d89ec533Spatrick const char *accept,
168d89ec533Spatrick dfsan_label s_label,
169d89ec533Spatrick dfsan_label accept_label,
170d89ec533Spatrick dfsan_label *ret_label) {
171d89ec533Spatrick const char *ret = strpbrk(s, accept);
172d89ec533Spatrick if (flags().strict_data_dependencies) {
173d89ec533Spatrick *ret_label = ret ? s_label : 0;
174d89ec533Spatrick } else {
175d89ec533Spatrick size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
176d89ec533Spatrick *ret_label =
177d89ec533Spatrick dfsan_union(dfsan_read_label(s, s_bytes_read),
178d89ec533Spatrick dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
179d89ec533Spatrick dfsan_union(s_label, accept_label)));
180d89ec533Spatrick }
181d89ec533Spatrick return const_cast<char *>(ret);
182d89ec533Spatrick }
183d89ec533Spatrick
__dfso_strpbrk(const char * s,const char * accept,dfsan_label s_label,dfsan_label accept_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin accept_origin,dfsan_origin * ret_origin)184d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
185d89ec533Spatrick const char *s, const char *accept, dfsan_label s_label,
186d89ec533Spatrick dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
187d89ec533Spatrick dfsan_origin accept_origin, dfsan_origin *ret_origin) {
188d89ec533Spatrick const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
189d89ec533Spatrick if (flags().strict_data_dependencies) {
190d89ec533Spatrick if (ret)
191d89ec533Spatrick *ret_origin = s_origin;
192d89ec533Spatrick } else {
193d89ec533Spatrick if (*ret_label) {
194d89ec533Spatrick size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
195d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
196d89ec533Spatrick if (o) {
197d89ec533Spatrick *ret_origin = o;
198d89ec533Spatrick } else {
199d89ec533Spatrick o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
200d89ec533Spatrick *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
2013cab2bb3Spatrick }
2023cab2bb3Spatrick }
2033cab2bb3Spatrick }
204d89ec533Spatrick return const_cast<char *>(ret);
205d89ec533Spatrick }
206d89ec533Spatrick
dfsan_memcmp_bcmp(const void * s1,const void * s2,size_t n,size_t * bytes_read)207d89ec533Spatrick static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
208d89ec533Spatrick size_t *bytes_read) {
209d89ec533Spatrick const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
210d89ec533Spatrick for (size_t i = 0; i != n; ++i) {
211d89ec533Spatrick if (cs1[i] != cs2[i]) {
212d89ec533Spatrick *bytes_read = i + 1;
213d89ec533Spatrick return cs1[i] - cs2[i];
214d89ec533Spatrick }
215d89ec533Spatrick }
216d89ec533Spatrick *bytes_read = n;
217d89ec533Spatrick return 0;
218d89ec533Spatrick }
219d89ec533Spatrick
dfsan_get_memcmp_label(const void * s1,const void * s2,size_t pos)220d89ec533Spatrick static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
221d89ec533Spatrick size_t pos) {
222d89ec533Spatrick if (flags().strict_data_dependencies)
223d89ec533Spatrick return 0;
224d89ec533Spatrick return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
225d89ec533Spatrick }
226d89ec533Spatrick
dfsan_get_memcmp_origin(const void * s1,const void * s2,size_t pos,dfsan_label * ret_label,dfsan_origin * ret_origin)227d89ec533Spatrick static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
228d89ec533Spatrick dfsan_label *ret_label,
229d89ec533Spatrick dfsan_origin *ret_origin) {
230d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
231d89ec533Spatrick if (*ret_label == 0)
232d89ec533Spatrick return;
233d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
234d89ec533Spatrick *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
235d89ec533Spatrick }
236d89ec533Spatrick
dfsan_memcmp_bcmp_label(const void * s1,const void * s2,size_t n,dfsan_label * ret_label)237d89ec533Spatrick static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
238d89ec533Spatrick dfsan_label *ret_label) {
239d89ec533Spatrick size_t bytes_read;
240d89ec533Spatrick int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
241d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
242d89ec533Spatrick return r;
243d89ec533Spatrick }
244d89ec533Spatrick
dfsan_memcmp_bcmp_origin(const void * s1,const void * s2,size_t n,dfsan_label * ret_label,dfsan_origin * ret_origin)245d89ec533Spatrick static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
246d89ec533Spatrick dfsan_label *ret_label,
247d89ec533Spatrick dfsan_origin *ret_origin) {
248d89ec533Spatrick size_t bytes_read;
249d89ec533Spatrick int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
250d89ec533Spatrick dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
251d89ec533Spatrick return r;
252d89ec533Spatrick }
2533cab2bb3Spatrick
DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp,uptr caller_pc,const void * s1,const void * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label)2543cab2bb3Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
2553cab2bb3Spatrick const void *s1, const void *s2, size_t n,
2563cab2bb3Spatrick dfsan_label s1_label, dfsan_label s2_label,
2573cab2bb3Spatrick dfsan_label n_label)
2583cab2bb3Spatrick
259d89ec533Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
260d89ec533Spatrick const void *s1, const void *s2, size_t n,
261d89ec533Spatrick dfsan_label s1_label, dfsan_label s2_label,
262d89ec533Spatrick dfsan_label n_label, dfsan_origin s1_origin,
263d89ec533Spatrick dfsan_origin s2_origin, dfsan_origin n_origin)
264d89ec533Spatrick
2653cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
2663cab2bb3Spatrick size_t n, dfsan_label s1_label,
2673cab2bb3Spatrick dfsan_label s2_label,
2683cab2bb3Spatrick dfsan_label n_label,
2693cab2bb3Spatrick dfsan_label *ret_label) {
2703cab2bb3Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
2713cab2bb3Spatrick s1_label, s2_label, n_label);
272d89ec533Spatrick return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
2733cab2bb3Spatrick }
2743cab2bb3Spatrick
__dfso_memcmp(const void * s1,const void * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)275d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
276d89ec533Spatrick const void *s1, const void *s2, size_t n, dfsan_label s1_label,
277d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
278d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
279d89ec533Spatrick dfsan_origin *ret_origin) {
280d89ec533Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
281d89ec533Spatrick s2, n, s1_label, s2_label, n_label, s1_origin,
282d89ec533Spatrick s2_origin, n_origin);
283d89ec533Spatrick return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
2843cab2bb3Spatrick }
285d89ec533Spatrick
__dfsw_bcmp(const void * s1,const void * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label)286d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
287d89ec533Spatrick size_t n, dfsan_label s1_label,
288d89ec533Spatrick dfsan_label s2_label,
289d89ec533Spatrick dfsan_label n_label,
290d89ec533Spatrick dfsan_label *ret_label) {
291d89ec533Spatrick return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
292d89ec533Spatrick }
293d89ec533Spatrick
__dfso_bcmp(const void * s1,const void * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)294d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
295d89ec533Spatrick const void *s1, const void *s2, size_t n, dfsan_label s1_label,
296d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
297d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
298d89ec533Spatrick dfsan_origin *ret_origin) {
299d89ec533Spatrick return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
300d89ec533Spatrick }
301d89ec533Spatrick
302d89ec533Spatrick // When n == 0, compare strings without byte limit.
303d89ec533Spatrick // When n > 0, compare the first (at most) n bytes of s1 and s2.
dfsan_strncmp(const char * s1,const char * s2,size_t n,size_t * bytes_read)304d89ec533Spatrick static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
305d89ec533Spatrick size_t *bytes_read) {
306d89ec533Spatrick for (size_t i = 0;; ++i) {
307d89ec533Spatrick if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
308d89ec533Spatrick *bytes_read = i + 1;
309d89ec533Spatrick return s1[i] - s2[i];
310d89ec533Spatrick }
311d89ec533Spatrick }
3123cab2bb3Spatrick }
3133cab2bb3Spatrick
DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp,uptr caller_pc,const char * s1,const char * s2,dfsan_label s1_label,dfsan_label s2_label)3143cab2bb3Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
3153cab2bb3Spatrick const char *s1, const char *s2,
3163cab2bb3Spatrick dfsan_label s1_label, dfsan_label s2_label)
3173cab2bb3Spatrick
318d89ec533Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
319d89ec533Spatrick const char *s1, const char *s2,
320d89ec533Spatrick dfsan_label s1_label, dfsan_label s2_label,
321d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin)
322d89ec533Spatrick
3233cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
3243cab2bb3Spatrick dfsan_label s1_label,
3253cab2bb3Spatrick dfsan_label s2_label,
3263cab2bb3Spatrick dfsan_label *ret_label) {
3273cab2bb3Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
3283cab2bb3Spatrick s1_label, s2_label);
329d89ec533Spatrick size_t bytes_read;
330d89ec533Spatrick int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
331d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
332d89ec533Spatrick return r;
3333cab2bb3Spatrick }
3343cab2bb3Spatrick
__dfso_strcmp(const char * s1,const char * s2,dfsan_label s1_label,dfsan_label s2_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin * ret_origin)335d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
336d89ec533Spatrick const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
337d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
338d89ec533Spatrick dfsan_origin *ret_origin) {
339d89ec533Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
340d89ec533Spatrick s2, s1_label, s2_label, s1_origin, s2_origin);
341d89ec533Spatrick size_t bytes_read;
342d89ec533Spatrick int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
343d89ec533Spatrick dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
344d89ec533Spatrick return r;
345d89ec533Spatrick }
346d89ec533Spatrick
347d89ec533Spatrick // When n == 0, compare strings without byte limit.
348d89ec533Spatrick // When n > 0, compare the first (at most) n bytes of s1 and s2.
dfsan_strncasecmp(const char * s1,const char * s2,size_t n,size_t * bytes_read)349d89ec533Spatrick static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
350d89ec533Spatrick size_t *bytes_read) {
3513cab2bb3Spatrick for (size_t i = 0;; ++i) {
3521f9cb04fSpatrick char s1_lower = tolower(s1[i]);
3531f9cb04fSpatrick char s2_lower = tolower(s2[i]);
3541f9cb04fSpatrick
355d89ec533Spatrick if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
356d89ec533Spatrick (n > 0 && i == n - 1)) {
357d89ec533Spatrick *bytes_read = i + 1;
3581f9cb04fSpatrick return s1_lower - s2_lower;
3593cab2bb3Spatrick }
3603cab2bb3Spatrick }
361d89ec533Spatrick }
362d89ec533Spatrick
__dfsw_strcasecmp(const char * s1,const char * s2,dfsan_label s1_label,dfsan_label s2_label,dfsan_label * ret_label)363d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
364d89ec533Spatrick const char *s2,
365d89ec533Spatrick dfsan_label s1_label,
366d89ec533Spatrick dfsan_label s2_label,
367d89ec533Spatrick dfsan_label *ret_label) {
368d89ec533Spatrick size_t bytes_read;
369d89ec533Spatrick int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
370d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
371d89ec533Spatrick return r;
372d89ec533Spatrick }
373d89ec533Spatrick
__dfso_strcasecmp(const char * s1,const char * s2,dfsan_label s1_label,dfsan_label s2_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin * ret_origin)374d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
375d89ec533Spatrick const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
376d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
377d89ec533Spatrick dfsan_origin *ret_origin) {
378d89ec533Spatrick size_t bytes_read;
379d89ec533Spatrick int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
380d89ec533Spatrick dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
381d89ec533Spatrick return r;
3823cab2bb3Spatrick }
3833cab2bb3Spatrick
DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp,uptr caller_pc,const char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label)3843cab2bb3Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
3853cab2bb3Spatrick const char *s1, const char *s2, size_t n,
3863cab2bb3Spatrick dfsan_label s1_label, dfsan_label s2_label,
3873cab2bb3Spatrick dfsan_label n_label)
3883cab2bb3Spatrick
389d89ec533Spatrick DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
390d89ec533Spatrick const char *s1, const char *s2, size_t n,
391d89ec533Spatrick dfsan_label s1_label, dfsan_label s2_label,
392d89ec533Spatrick dfsan_label n_label, dfsan_origin s1_origin,
393d89ec533Spatrick dfsan_origin s2_origin, dfsan_origin n_origin)
394d89ec533Spatrick
3953cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
3963cab2bb3Spatrick size_t n, dfsan_label s1_label,
3973cab2bb3Spatrick dfsan_label s2_label,
3983cab2bb3Spatrick dfsan_label n_label,
3993cab2bb3Spatrick dfsan_label *ret_label) {
4003cab2bb3Spatrick if (n == 0) {
4013cab2bb3Spatrick *ret_label = 0;
4023cab2bb3Spatrick return 0;
4033cab2bb3Spatrick }
4043cab2bb3Spatrick
4053cab2bb3Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
4063cab2bb3Spatrick n, s1_label, s2_label, n_label);
4073cab2bb3Spatrick
408d89ec533Spatrick size_t bytes_read;
409d89ec533Spatrick int r = dfsan_strncmp(s1, s2, n, &bytes_read);
410d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
411d89ec533Spatrick return r;
4123cab2bb3Spatrick }
4133cab2bb3Spatrick
__dfso_strncmp(const char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)414d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
415d89ec533Spatrick const char *s1, const char *s2, size_t n, dfsan_label s1_label,
416d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
417d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
418d89ec533Spatrick dfsan_origin *ret_origin) {
4193cab2bb3Spatrick if (n == 0) {
4203cab2bb3Spatrick *ret_label = 0;
4213cab2bb3Spatrick return 0;
4223cab2bb3Spatrick }
4233cab2bb3Spatrick
424d89ec533Spatrick CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
425d89ec533Spatrick s1, s2, n, s1_label, s2_label, n_label, s1_origin,
426d89ec533Spatrick s2_origin, n_origin);
4271f9cb04fSpatrick
428d89ec533Spatrick size_t bytes_read;
429d89ec533Spatrick int r = dfsan_strncmp(s1, s2, n, &bytes_read);
430d89ec533Spatrick dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
431d89ec533Spatrick return r;
432d89ec533Spatrick }
433d89ec533Spatrick
__dfsw_strncasecmp(const char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label)434d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
435d89ec533Spatrick const char *s1, const char *s2, size_t n, dfsan_label s1_label,
436d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
437d89ec533Spatrick if (n == 0) {
4383cab2bb3Spatrick *ret_label = 0;
4393cab2bb3Spatrick return 0;
4403cab2bb3Spatrick }
4413cab2bb3Spatrick
442d89ec533Spatrick size_t bytes_read;
443d89ec533Spatrick int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
444d89ec533Spatrick *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
445d89ec533Spatrick return r;
4463cab2bb3Spatrick }
4473cab2bb3Spatrick
__dfso_strncasecmp(const char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)448d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
449d89ec533Spatrick const char *s1, const char *s2, size_t n, dfsan_label s1_label,
450d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
451d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
452d89ec533Spatrick dfsan_origin *ret_origin) {
453d89ec533Spatrick if (n == 0) {
454d89ec533Spatrick *ret_label = 0;
455d89ec533Spatrick return 0;
456d89ec533Spatrick }
457d89ec533Spatrick
458d89ec533Spatrick size_t bytes_read;
459d89ec533Spatrick int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
460d89ec533Spatrick dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
461d89ec533Spatrick return r;
462d89ec533Spatrick }
463d89ec533Spatrick
464d89ec533Spatrick
4653cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE size_t
__dfsw_strlen(const char * s,dfsan_label s_label,dfsan_label * ret_label)4663cab2bb3Spatrick __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
4673cab2bb3Spatrick size_t ret = strlen(s);
4683cab2bb3Spatrick if (flags().strict_data_dependencies) {
4693cab2bb3Spatrick *ret_label = 0;
4703cab2bb3Spatrick } else {
4713cab2bb3Spatrick *ret_label = dfsan_read_label(s, ret + 1);
4723cab2bb3Spatrick }
4733cab2bb3Spatrick return ret;
4743cab2bb3Spatrick }
4753cab2bb3Spatrick
__dfso_strlen(const char * s,dfsan_label s_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin * ret_origin)476d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
477d89ec533Spatrick dfsan_label s_label,
478d89ec533Spatrick dfsan_label *ret_label,
479d89ec533Spatrick dfsan_origin s_origin,
480d89ec533Spatrick dfsan_origin *ret_origin) {
481d89ec533Spatrick size_t ret = __dfsw_strlen(s, s_label, ret_label);
482d89ec533Spatrick if (!flags().strict_data_dependencies)
483d89ec533Spatrick *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
484d89ec533Spatrick return ret;
485d89ec533Spatrick }
486d89ec533Spatrick
dfsan_memmove(void * dest,const void * src,size_t n)487d89ec533Spatrick static void *dfsan_memmove(void *dest, const void *src, size_t n) {
488d89ec533Spatrick dfsan_label *sdest = shadow_for(dest);
489d89ec533Spatrick const dfsan_label *ssrc = shadow_for(src);
490d89ec533Spatrick internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
491d89ec533Spatrick return internal_memmove(dest, src, n);
492d89ec533Spatrick }
493d89ec533Spatrick
dfsan_memmove_with_origin(void * dest,const void * src,size_t n)494d89ec533Spatrick static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
495d89ec533Spatrick dfsan_mem_origin_transfer(dest, src, n);
496d89ec533Spatrick return dfsan_memmove(dest, src, n);
497d89ec533Spatrick }
4983cab2bb3Spatrick
dfsan_memcpy(void * dest,const void * src,size_t n)4993cab2bb3Spatrick static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
500*810390e3Srobert dfsan_mem_shadow_transfer(dest, src, n);
5013cab2bb3Spatrick return internal_memcpy(dest, src, n);
5023cab2bb3Spatrick }
5033cab2bb3Spatrick
dfsan_memcpy_with_origin(void * dest,const void * src,size_t n)504d89ec533Spatrick static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
505d89ec533Spatrick dfsan_mem_origin_transfer(dest, src, n);
506d89ec533Spatrick return dfsan_memcpy(dest, src, n);
507d89ec533Spatrick }
508d89ec533Spatrick
dfsan_memset(void * s,int c,dfsan_label c_label,size_t n)5093cab2bb3Spatrick static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
5103cab2bb3Spatrick internal_memset(s, c, n);
5113cab2bb3Spatrick dfsan_set_label(c_label, s, n);
5123cab2bb3Spatrick }
5133cab2bb3Spatrick
dfsan_memset_with_origin(void * s,int c,dfsan_label c_label,dfsan_origin c_origin,size_t n)514d89ec533Spatrick static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
515d89ec533Spatrick dfsan_origin c_origin, size_t n) {
516d89ec533Spatrick internal_memset(s, c, n);
517d89ec533Spatrick dfsan_set_label_origin(c_label, c_origin, s, n);
518d89ec533Spatrick }
519d89ec533Spatrick
5203cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_memcpy(void * dest,const void * src,size_t n,dfsan_label dest_label,dfsan_label src_label,dfsan_label n_label,dfsan_label * ret_label)5213cab2bb3Spatrick void *__dfsw_memcpy(void *dest, const void *src, size_t n,
5223cab2bb3Spatrick dfsan_label dest_label, dfsan_label src_label,
5233cab2bb3Spatrick dfsan_label n_label, dfsan_label *ret_label) {
5243cab2bb3Spatrick *ret_label = dest_label;
5253cab2bb3Spatrick return dfsan_memcpy(dest, src, n);
5263cab2bb3Spatrick }
5273cab2bb3Spatrick
5283cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_memcpy(void * dest,const void * src,size_t n,dfsan_label dest_label,dfsan_label src_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin dest_origin,dfsan_origin src_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)529d89ec533Spatrick void *__dfso_memcpy(void *dest, const void *src, size_t n,
530d89ec533Spatrick dfsan_label dest_label, dfsan_label src_label,
531d89ec533Spatrick dfsan_label n_label, dfsan_label *ret_label,
532d89ec533Spatrick dfsan_origin dest_origin, dfsan_origin src_origin,
533d89ec533Spatrick dfsan_origin n_origin, dfsan_origin *ret_origin) {
534d89ec533Spatrick *ret_label = dest_label;
535d89ec533Spatrick *ret_origin = dest_origin;
536d89ec533Spatrick return dfsan_memcpy_with_origin(dest, src, n);
537d89ec533Spatrick }
538d89ec533Spatrick
539d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_memmove(void * dest,const void * src,size_t n,dfsan_label dest_label,dfsan_label src_label,dfsan_label n_label,dfsan_label * ret_label)540d89ec533Spatrick void *__dfsw_memmove(void *dest, const void *src, size_t n,
541d89ec533Spatrick dfsan_label dest_label, dfsan_label src_label,
542d89ec533Spatrick dfsan_label n_label, dfsan_label *ret_label) {
543d89ec533Spatrick *ret_label = dest_label;
544d89ec533Spatrick return dfsan_memmove(dest, src, n);
545d89ec533Spatrick }
546d89ec533Spatrick
547d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_memmove(void * dest,const void * src,size_t n,dfsan_label dest_label,dfsan_label src_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin dest_origin,dfsan_origin src_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)548d89ec533Spatrick void *__dfso_memmove(void *dest, const void *src, size_t n,
549d89ec533Spatrick dfsan_label dest_label, dfsan_label src_label,
550d89ec533Spatrick dfsan_label n_label, dfsan_label *ret_label,
551d89ec533Spatrick dfsan_origin dest_origin, dfsan_origin src_origin,
552d89ec533Spatrick dfsan_origin n_origin, dfsan_origin *ret_origin) {
553d89ec533Spatrick *ret_label = dest_label;
554d89ec533Spatrick *ret_origin = dest_origin;
555d89ec533Spatrick return dfsan_memmove_with_origin(dest, src, n);
556d89ec533Spatrick }
557d89ec533Spatrick
558d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_memset(void * s,int c,size_t n,dfsan_label s_label,dfsan_label c_label,dfsan_label n_label,dfsan_label * ret_label)5593cab2bb3Spatrick void *__dfsw_memset(void *s, int c, size_t n,
5603cab2bb3Spatrick dfsan_label s_label, dfsan_label c_label,
5613cab2bb3Spatrick dfsan_label n_label, dfsan_label *ret_label) {
5623cab2bb3Spatrick dfsan_memset(s, c, c_label, n);
5633cab2bb3Spatrick *ret_label = s_label;
5643cab2bb3Spatrick return s;
5653cab2bb3Spatrick }
5663cab2bb3Spatrick
567d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_memset(void * s,int c,size_t n,dfsan_label s_label,dfsan_label c_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin c_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)568d89ec533Spatrick void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
569d89ec533Spatrick dfsan_label c_label, dfsan_label n_label,
570d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s_origin,
571d89ec533Spatrick dfsan_origin c_origin, dfsan_origin n_origin,
572d89ec533Spatrick dfsan_origin *ret_origin) {
573d89ec533Spatrick dfsan_memset_with_origin(s, c, c_label, c_origin, n);
574d89ec533Spatrick *ret_label = s_label;
575d89ec533Spatrick *ret_origin = s_origin;
576d89ec533Spatrick return s;
577d89ec533Spatrick }
578d89ec533Spatrick
__dfsw_strcat(char * dest,const char * src,dfsan_label dest_label,dfsan_label src_label,dfsan_label * ret_label)579d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
580d89ec533Spatrick dfsan_label dest_label,
581d89ec533Spatrick dfsan_label src_label,
582d89ec533Spatrick dfsan_label *ret_label) {
583d89ec533Spatrick size_t dest_len = strlen(dest);
584*810390e3Srobert char *ret = strcat(dest, src);
585*810390e3Srobert dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));
586d89ec533Spatrick *ret_label = dest_label;
587d89ec533Spatrick return ret;
588d89ec533Spatrick }
589d89ec533Spatrick
__dfso_strcat(char * dest,const char * src,dfsan_label dest_label,dfsan_label src_label,dfsan_label * ret_label,dfsan_origin dest_origin,dfsan_origin src_origin,dfsan_origin * ret_origin)590d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
591d89ec533Spatrick char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
592d89ec533Spatrick dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
593d89ec533Spatrick dfsan_origin *ret_origin) {
594d89ec533Spatrick size_t dest_len = strlen(dest);
595*810390e3Srobert char *ret = strcat(dest, src);
596d89ec533Spatrick size_t src_len = strlen(src);
597d89ec533Spatrick dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
598*810390e3Srobert dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
599d89ec533Spatrick *ret_label = dest_label;
600d89ec533Spatrick *ret_origin = dest_origin;
601d89ec533Spatrick return ret;
602d89ec533Spatrick }
603d89ec533Spatrick
6043cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *
__dfsw_strdup(const char * s,dfsan_label s_label,dfsan_label * ret_label)6053cab2bb3Spatrick __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
6063cab2bb3Spatrick size_t len = strlen(s);
6073cab2bb3Spatrick void *p = malloc(len+1);
6083cab2bb3Spatrick dfsan_memcpy(p, s, len+1);
6093cab2bb3Spatrick *ret_label = 0;
6103cab2bb3Spatrick return static_cast<char *>(p);
6113cab2bb3Spatrick }
6123cab2bb3Spatrick
__dfso_strdup(const char * s,dfsan_label s_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin * ret_origin)613d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
614d89ec533Spatrick dfsan_label s_label,
615d89ec533Spatrick dfsan_label *ret_label,
616d89ec533Spatrick dfsan_origin s_origin,
617d89ec533Spatrick dfsan_origin *ret_origin) {
618d89ec533Spatrick size_t len = strlen(s);
619d89ec533Spatrick void *p = malloc(len + 1);
620d89ec533Spatrick dfsan_memcpy_with_origin(p, s, len + 1);
621d89ec533Spatrick *ret_label = 0;
622d89ec533Spatrick return static_cast<char *>(p);
623d89ec533Spatrick }
624d89ec533Spatrick
6253cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *
__dfsw_strncpy(char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label)6263cab2bb3Spatrick __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
6273cab2bb3Spatrick dfsan_label s2_label, dfsan_label n_label,
6283cab2bb3Spatrick dfsan_label *ret_label) {
6293cab2bb3Spatrick size_t len = strlen(s2);
6303cab2bb3Spatrick if (len < n) {
6313cab2bb3Spatrick dfsan_memcpy(s1, s2, len+1);
6323cab2bb3Spatrick dfsan_memset(s1+len+1, 0, 0, n-len-1);
6333cab2bb3Spatrick } else {
6343cab2bb3Spatrick dfsan_memcpy(s1, s2, n);
6353cab2bb3Spatrick }
6363cab2bb3Spatrick
6373cab2bb3Spatrick *ret_label = s1_label;
6383cab2bb3Spatrick return s1;
6393cab2bb3Spatrick }
6403cab2bb3Spatrick
__dfso_strncpy(char * s1,const char * s2,size_t n,dfsan_label s1_label,dfsan_label s2_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s1_origin,dfsan_origin s2_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)641d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
642d89ec533Spatrick char *s1, const char *s2, size_t n, dfsan_label s1_label,
643d89ec533Spatrick dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
644d89ec533Spatrick dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
645d89ec533Spatrick dfsan_origin *ret_origin) {
646d89ec533Spatrick size_t len = strlen(s2);
647d89ec533Spatrick if (len < n) {
648d89ec533Spatrick dfsan_memcpy_with_origin(s1, s2, len + 1);
649d89ec533Spatrick dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
650d89ec533Spatrick } else {
651d89ec533Spatrick dfsan_memcpy_with_origin(s1, s2, n);
652d89ec533Spatrick }
653d89ec533Spatrick
654d89ec533Spatrick *ret_label = s1_label;
655d89ec533Spatrick *ret_origin = s1_origin;
656d89ec533Spatrick return s1;
657d89ec533Spatrick }
658d89ec533Spatrick
6593cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfsw_pread(int fd,void * buf,size_t count,off_t offset,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label offset_label,dfsan_label * ret_label)6603cab2bb3Spatrick __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
6613cab2bb3Spatrick dfsan_label fd_label, dfsan_label buf_label,
6623cab2bb3Spatrick dfsan_label count_label, dfsan_label offset_label,
6633cab2bb3Spatrick dfsan_label *ret_label) {
6643cab2bb3Spatrick ssize_t ret = pread(fd, buf, count, offset);
6653cab2bb3Spatrick if (ret > 0)
6663cab2bb3Spatrick dfsan_set_label(0, buf, ret);
6673cab2bb3Spatrick *ret_label = 0;
6683cab2bb3Spatrick return ret;
6693cab2bb3Spatrick }
6703cab2bb3Spatrick
__dfso_pread(int fd,void * buf,size_t count,off_t offset,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label offset_label,dfsan_label * ret_label,dfsan_origin fd_origin,dfsan_origin buf_origin,dfsan_origin count_origin,dfsan_label offset_origin,dfsan_origin * ret_origin)671d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
672d89ec533Spatrick int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
673d89ec533Spatrick dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
674d89ec533Spatrick dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
675d89ec533Spatrick dfsan_origin count_origin, dfsan_label offset_origin,
676d89ec533Spatrick dfsan_origin *ret_origin) {
677d89ec533Spatrick return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
678d89ec533Spatrick offset_label, ret_label);
679d89ec533Spatrick }
680d89ec533Spatrick
6813cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t
__dfsw_read(int fd,void * buf,size_t count,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label * ret_label)6823cab2bb3Spatrick __dfsw_read(int fd, void *buf, size_t count,
6833cab2bb3Spatrick dfsan_label fd_label, dfsan_label buf_label,
6843cab2bb3Spatrick dfsan_label count_label,
6853cab2bb3Spatrick dfsan_label *ret_label) {
6863cab2bb3Spatrick ssize_t ret = read(fd, buf, count);
6873cab2bb3Spatrick if (ret > 0)
6883cab2bb3Spatrick dfsan_set_label(0, buf, ret);
6893cab2bb3Spatrick *ret_label = 0;
6903cab2bb3Spatrick return ret;
6913cab2bb3Spatrick }
6923cab2bb3Spatrick
__dfso_read(int fd,void * buf,size_t count,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label * ret_label,dfsan_origin fd_origin,dfsan_origin buf_origin,dfsan_origin count_origin,dfsan_origin * ret_origin)693d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
694d89ec533Spatrick int fd, void *buf, size_t count, dfsan_label fd_label,
695d89ec533Spatrick dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
696d89ec533Spatrick dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
697d89ec533Spatrick dfsan_origin *ret_origin) {
698d89ec533Spatrick return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
699d89ec533Spatrick ret_label);
700d89ec533Spatrick }
701d89ec533Spatrick
__dfsw_clock_gettime(clockid_t clk_id,struct timespec * tp,dfsan_label clk_id_label,dfsan_label tp_label,dfsan_label * ret_label)7023cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
7033cab2bb3Spatrick struct timespec *tp,
7043cab2bb3Spatrick dfsan_label clk_id_label,
7053cab2bb3Spatrick dfsan_label tp_label,
7063cab2bb3Spatrick dfsan_label *ret_label) {
7073cab2bb3Spatrick int ret = clock_gettime(clk_id, tp);
7083cab2bb3Spatrick if (ret == 0)
7093cab2bb3Spatrick dfsan_set_label(0, tp, sizeof(struct timespec));
7103cab2bb3Spatrick *ret_label = 0;
7113cab2bb3Spatrick return ret;
7123cab2bb3Spatrick }
7133cab2bb3Spatrick
__dfso_clock_gettime(clockid_t clk_id,struct timespec * tp,dfsan_label clk_id_label,dfsan_label tp_label,dfsan_label * ret_label,dfsan_origin clk_id_origin,dfsan_origin tp_origin,dfsan_origin * ret_origin)714d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
715d89ec533Spatrick clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
716d89ec533Spatrick dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
717d89ec533Spatrick dfsan_origin tp_origin, dfsan_origin *ret_origin) {
718d89ec533Spatrick return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
719d89ec533Spatrick }
720d89ec533Spatrick
dfsan_set_zero_label(const void * ptr,uptr size)721d89ec533Spatrick static void dfsan_set_zero_label(const void *ptr, uptr size) {
7223cab2bb3Spatrick dfsan_set_label(0, const_cast<void *>(ptr), size);
7233cab2bb3Spatrick }
7243cab2bb3Spatrick
7253cab2bb3Spatrick // dlopen() ultimately calls mmap() down inside the loader, which generally
7263cab2bb3Spatrick // doesn't participate in dynamic symbol resolution. Therefore we won't
7273cab2bb3Spatrick // intercept its calls to mmap, and we have to hook it here.
7283cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE void *
__dfsw_dlopen(const char * filename,int flag,dfsan_label filename_label,dfsan_label flag_label,dfsan_label * ret_label)7293cab2bb3Spatrick __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
7303cab2bb3Spatrick dfsan_label flag_label, dfsan_label *ret_label) {
7313cab2bb3Spatrick void *handle = dlopen(filename, flag);
7323cab2bb3Spatrick link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
7333cab2bb3Spatrick if (map)
734d89ec533Spatrick ForEachMappedRegion(map, dfsan_set_zero_label);
7353cab2bb3Spatrick *ret_label = 0;
7363cab2bb3Spatrick return handle;
7373cab2bb3Spatrick }
7383cab2bb3Spatrick
__dfso_dlopen(const char * filename,int flag,dfsan_label filename_label,dfsan_label flag_label,dfsan_label * ret_label,dfsan_origin filename_origin,dfsan_origin flag_origin,dfsan_origin * ret_origin)739d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
740d89ec533Spatrick const char *filename, int flag, dfsan_label filename_label,
741d89ec533Spatrick dfsan_label flag_label, dfsan_label *ret_label,
742d89ec533Spatrick dfsan_origin filename_origin, dfsan_origin flag_origin,
743d89ec533Spatrick dfsan_origin *ret_origin) {
744d89ec533Spatrick return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
745d89ec533Spatrick }
7463cab2bb3Spatrick
DFsanThreadStartFunc(void * arg)747d89ec533Spatrick static void *DFsanThreadStartFunc(void *arg) {
748d89ec533Spatrick DFsanThread *t = (DFsanThread *)arg;
749d89ec533Spatrick SetCurrentThread(t);
750*810390e3Srobert t->Init();
751*810390e3Srobert SetSigProcMask(&t->starting_sigset_, nullptr);
752d89ec533Spatrick return t->ThreadStart();
753d89ec533Spatrick }
754d89ec533Spatrick
dfsan_pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * start_routine,void * arg,dfsan_label * ret_label,bool track_origins=false)755d89ec533Spatrick static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
756d89ec533Spatrick void *start_routine, void *arg,
757d89ec533Spatrick dfsan_label *ret_label,
758d89ec533Spatrick bool track_origins = false) {
759d89ec533Spatrick pthread_attr_t myattr;
760d89ec533Spatrick if (!attr) {
761d89ec533Spatrick pthread_attr_init(&myattr);
762d89ec533Spatrick attr = &myattr;
763d89ec533Spatrick }
764d89ec533Spatrick
765d89ec533Spatrick // Ensure that the thread stack is large enough to hold all TLS data.
766d89ec533Spatrick AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
767d89ec533Spatrick
768d89ec533Spatrick DFsanThread *t =
769*810390e3Srobert DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
770*810390e3Srobert ScopedBlockSignals block(&t->starting_sigset_);
771d89ec533Spatrick int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
772d89ec533Spatrick
773d89ec533Spatrick if (attr == &myattr)
774d89ec533Spatrick pthread_attr_destroy(&myattr);
775d89ec533Spatrick *ret_label = 0;
776d89ec533Spatrick return res;
7773cab2bb3Spatrick }
7783cab2bb3Spatrick
__dfsw_pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * start_routine,void * arg,dfsan_label thread_label,dfsan_label attr_label,dfsan_label start_routine_label,dfsan_label arg_label,dfsan_label * ret_label)7793cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
780*810390e3Srobert pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
781*810390e3Srobert void *arg, dfsan_label thread_label, dfsan_label attr_label,
782*810390e3Srobert dfsan_label start_routine_label, dfsan_label arg_label,
783*810390e3Srobert dfsan_label *ret_label) {
784*810390e3Srobert return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
785d89ec533Spatrick }
786d89ec533Spatrick
__dfso_pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * start_routine,void * arg,dfsan_label thread_label,dfsan_label attr_label,dfsan_label start_routine_label,dfsan_label arg_label,dfsan_label * ret_label,dfsan_origin thread_origin,dfsan_origin attr_origin,dfsan_origin start_routine_origin,dfsan_origin arg_origin,dfsan_origin * ret_origin)787d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
788*810390e3Srobert pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
789*810390e3Srobert void *arg, dfsan_label thread_label, dfsan_label attr_label,
790*810390e3Srobert dfsan_label start_routine_label, dfsan_label arg_label,
791*810390e3Srobert dfsan_label *ret_label, dfsan_origin thread_origin,
792d89ec533Spatrick dfsan_origin attr_origin, dfsan_origin start_routine_origin,
793d89ec533Spatrick dfsan_origin arg_origin, dfsan_origin *ret_origin) {
794*810390e3Srobert return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
795*810390e3Srobert true);
796d89ec533Spatrick }
797d89ec533Spatrick
__dfsw_pthread_join(pthread_t thread,void ** retval,dfsan_label thread_label,dfsan_label retval_label,dfsan_label * ret_label)798d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
799d89ec533Spatrick void **retval,
800d89ec533Spatrick dfsan_label thread_label,
801d89ec533Spatrick dfsan_label retval_label,
802d89ec533Spatrick dfsan_label *ret_label) {
803d89ec533Spatrick int ret = pthread_join(thread, retval);
804d89ec533Spatrick if (ret == 0 && retval)
805d89ec533Spatrick dfsan_set_label(0, retval, sizeof(*retval));
8063cab2bb3Spatrick *ret_label = 0;
807d89ec533Spatrick return ret;
808d89ec533Spatrick }
809d89ec533Spatrick
__dfso_pthread_join(pthread_t thread,void ** retval,dfsan_label thread_label,dfsan_label retval_label,dfsan_label * ret_label,dfsan_origin thread_origin,dfsan_origin retval_origin,dfsan_origin * ret_origin)810d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
811d89ec533Spatrick pthread_t thread, void **retval, dfsan_label thread_label,
812d89ec533Spatrick dfsan_label retval_label, dfsan_label *ret_label,
813d89ec533Spatrick dfsan_origin thread_origin, dfsan_origin retval_origin,
814d89ec533Spatrick dfsan_origin *ret_origin) {
815d89ec533Spatrick return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
816d89ec533Spatrick ret_label);
8173cab2bb3Spatrick }
8183cab2bb3Spatrick
8193cab2bb3Spatrick struct dl_iterate_phdr_info {
820*810390e3Srobert int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
821d89ec533Spatrick void *data;
822d89ec533Spatrick };
823d89ec533Spatrick
dl_iterate_phdr_cb(struct dl_phdr_info * info,size_t size,void * data)8243cab2bb3Spatrick int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
8253cab2bb3Spatrick dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
8263cab2bb3Spatrick dfsan_set_label(0, *info);
8273cab2bb3Spatrick dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
8283cab2bb3Spatrick strlen(info->dlpi_name) + 1);
8293cab2bb3Spatrick dfsan_set_label(
8303cab2bb3Spatrick 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
8313cab2bb3Spatrick sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
8323cab2bb3Spatrick
833*810390e3Srobert dfsan_clear_thread_local_state();
834*810390e3Srobert return dipi->callback(info, size, dipi->data);
835d89ec533Spatrick }
836d89ec533Spatrick
__dfsw_dl_iterate_phdr(int (* callback)(struct dl_phdr_info * info,size_t size,void * data),void * data,dfsan_label callback_label,dfsan_label data_label,dfsan_label * ret_label)8373cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
838*810390e3Srobert int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
839*810390e3Srobert void *data, dfsan_label callback_label, dfsan_label data_label,
840*810390e3Srobert dfsan_label *ret_label) {
841*810390e3Srobert dl_iterate_phdr_info dipi = {callback, data};
8423cab2bb3Spatrick *ret_label = 0;
8433cab2bb3Spatrick return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
8443cab2bb3Spatrick }
8453cab2bb3Spatrick
__dfso_dl_iterate_phdr(int (* callback)(struct dl_phdr_info * info,size_t size,void * data),void * data,dfsan_label callback_label,dfsan_label data_label,dfsan_label * ret_label,dfsan_origin callback_origin,dfsan_origin data_origin,dfsan_origin * ret_origin)846d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
847*810390e3Srobert int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
848*810390e3Srobert void *data, dfsan_label callback_label, dfsan_label data_label,
849*810390e3Srobert dfsan_label *ret_label, dfsan_origin callback_origin,
850*810390e3Srobert dfsan_origin data_origin, dfsan_origin *ret_origin) {
851*810390e3Srobert dl_iterate_phdr_info dipi = {callback, data};
852d89ec533Spatrick *ret_label = 0;
853*810390e3Srobert return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
854d89ec533Spatrick }
855d89ec533Spatrick
856d89ec533Spatrick // This function is only available for glibc 2.27 or newer. Mark it weak so
857d89ec533Spatrick // linking succeeds with older glibcs.
858d89ec533Spatrick SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
859d89ec533Spatrick size_t *alignp);
860d89ec533Spatrick
__dfsw__dl_get_tls_static_info(size_t * sizep,size_t * alignp,dfsan_label sizep_label,dfsan_label alignp_label)861d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
862d89ec533Spatrick size_t *sizep, size_t *alignp, dfsan_label sizep_label,
863d89ec533Spatrick dfsan_label alignp_label) {
864d89ec533Spatrick assert(_dl_get_tls_static_info);
865d89ec533Spatrick _dl_get_tls_static_info(sizep, alignp);
866d89ec533Spatrick dfsan_set_label(0, sizep, sizeof(*sizep));
867d89ec533Spatrick dfsan_set_label(0, alignp, sizeof(*alignp));
868d89ec533Spatrick }
869d89ec533Spatrick
__dfso__dl_get_tls_static_info(size_t * sizep,size_t * alignp,dfsan_label sizep_label,dfsan_label alignp_label,dfsan_origin sizep_origin,dfsan_origin alignp_origin)870d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
871d89ec533Spatrick size_t *sizep, size_t *alignp, dfsan_label sizep_label,
872d89ec533Spatrick dfsan_label alignp_label, dfsan_origin sizep_origin,
873d89ec533Spatrick dfsan_origin alignp_origin) {
874d89ec533Spatrick __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
875d89ec533Spatrick }
876d89ec533Spatrick
8773cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_ctime_r(const time_t * timep,char * buf,dfsan_label timep_label,dfsan_label buf_label,dfsan_label * ret_label)8783cab2bb3Spatrick char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
8793cab2bb3Spatrick dfsan_label buf_label, dfsan_label *ret_label) {
8803cab2bb3Spatrick char *ret = ctime_r(timep, buf);
8813cab2bb3Spatrick if (ret) {
8823cab2bb3Spatrick dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
8833cab2bb3Spatrick strlen(buf) + 1);
8843cab2bb3Spatrick *ret_label = buf_label;
8853cab2bb3Spatrick } else {
8863cab2bb3Spatrick *ret_label = 0;
8873cab2bb3Spatrick }
8883cab2bb3Spatrick return ret;
8893cab2bb3Spatrick }
8903cab2bb3Spatrick
8913cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_ctime_r(const time_t * timep,char * buf,dfsan_label timep_label,dfsan_label buf_label,dfsan_label * ret_label,dfsan_origin timep_origin,dfsan_origin buf_origin,dfsan_origin * ret_origin)892d89ec533Spatrick char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
893d89ec533Spatrick dfsan_label buf_label, dfsan_label *ret_label,
894d89ec533Spatrick dfsan_origin timep_origin, dfsan_origin buf_origin,
895d89ec533Spatrick dfsan_origin *ret_origin) {
896d89ec533Spatrick char *ret = ctime_r(timep, buf);
897d89ec533Spatrick if (ret) {
898d89ec533Spatrick dfsan_set_label_origin(
899d89ec533Spatrick dfsan_read_label(timep, sizeof(time_t)),
900d89ec533Spatrick dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
901d89ec533Spatrick strlen(buf) + 1);
902d89ec533Spatrick *ret_label = buf_label;
903d89ec533Spatrick *ret_origin = buf_origin;
904d89ec533Spatrick } else {
905d89ec533Spatrick *ret_label = 0;
906d89ec533Spatrick }
907d89ec533Spatrick return ret;
908d89ec533Spatrick }
909d89ec533Spatrick
910d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_fgets(char * s,int size,FILE * stream,dfsan_label s_label,dfsan_label size_label,dfsan_label stream_label,dfsan_label * ret_label)9113cab2bb3Spatrick char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
9123cab2bb3Spatrick dfsan_label size_label, dfsan_label stream_label,
9133cab2bb3Spatrick dfsan_label *ret_label) {
9143cab2bb3Spatrick char *ret = fgets(s, size, stream);
9153cab2bb3Spatrick if (ret) {
9163cab2bb3Spatrick dfsan_set_label(0, ret, strlen(ret) + 1);
9173cab2bb3Spatrick *ret_label = s_label;
9183cab2bb3Spatrick } else {
9193cab2bb3Spatrick *ret_label = 0;
9203cab2bb3Spatrick }
9213cab2bb3Spatrick return ret;
9223cab2bb3Spatrick }
9233cab2bb3Spatrick
9243cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_fgets(char * s,int size,FILE * stream,dfsan_label s_label,dfsan_label size_label,dfsan_label stream_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin size_origin,dfsan_origin stream_origin,dfsan_origin * ret_origin)925d89ec533Spatrick char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
926d89ec533Spatrick dfsan_label size_label, dfsan_label stream_label,
927d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s_origin,
928d89ec533Spatrick dfsan_origin size_origin, dfsan_origin stream_origin,
929d89ec533Spatrick dfsan_origin *ret_origin) {
930d89ec533Spatrick char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
931d89ec533Spatrick ret_label);
932d89ec533Spatrick if (ret)
933d89ec533Spatrick *ret_origin = s_origin;
934d89ec533Spatrick return ret;
935d89ec533Spatrick }
936d89ec533Spatrick
937d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getcwd(char * buf,size_t size,dfsan_label buf_label,dfsan_label size_label,dfsan_label * ret_label)9383cab2bb3Spatrick char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
9393cab2bb3Spatrick dfsan_label size_label, dfsan_label *ret_label) {
9403cab2bb3Spatrick char *ret = getcwd(buf, size);
9413cab2bb3Spatrick if (ret) {
9423cab2bb3Spatrick dfsan_set_label(0, ret, strlen(ret) + 1);
9433cab2bb3Spatrick *ret_label = buf_label;
9443cab2bb3Spatrick } else {
9453cab2bb3Spatrick *ret_label = 0;
9463cab2bb3Spatrick }
9473cab2bb3Spatrick return ret;
9483cab2bb3Spatrick }
9493cab2bb3Spatrick
9503cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_getcwd(char * buf,size_t size,dfsan_label buf_label,dfsan_label size_label,dfsan_label * ret_label,dfsan_origin buf_origin,dfsan_origin size_origin,dfsan_origin * ret_origin)951d89ec533Spatrick char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
952d89ec533Spatrick dfsan_label size_label, dfsan_label *ret_label,
953d89ec533Spatrick dfsan_origin buf_origin, dfsan_origin size_origin,
954d89ec533Spatrick dfsan_origin *ret_origin) {
955d89ec533Spatrick char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
956d89ec533Spatrick if (ret)
957d89ec533Spatrick *ret_origin = buf_origin;
958d89ec533Spatrick return ret;
959d89ec533Spatrick }
960d89ec533Spatrick
961d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_get_current_dir_name(dfsan_label * ret_label)9623cab2bb3Spatrick char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
9633cab2bb3Spatrick char *ret = get_current_dir_name();
964d89ec533Spatrick if (ret)
9653cab2bb3Spatrick dfsan_set_label(0, ret, strlen(ret) + 1);
9663cab2bb3Spatrick *ret_label = 0;
9673cab2bb3Spatrick return ret;
9683cab2bb3Spatrick }
9693cab2bb3Spatrick
9703cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_get_current_dir_name(dfsan_label * ret_label,dfsan_origin * ret_origin)971d89ec533Spatrick char *__dfso_get_current_dir_name(dfsan_label *ret_label,
972d89ec533Spatrick dfsan_origin *ret_origin) {
973d89ec533Spatrick return __dfsw_get_current_dir_name(ret_label);
974d89ec533Spatrick }
975d89ec533Spatrick
976*810390e3Srobert // This function is only available for glibc 2.25 or newer. Mark it weak so
977*810390e3Srobert // linking succeeds with older glibcs.
978*810390e3Srobert SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);
979*810390e3Srobert
__dfsw_getentropy(void * buffer,size_t length,dfsan_label buffer_label,dfsan_label length_label,dfsan_label * ret_label)980*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,
981*810390e3Srobert dfsan_label buffer_label,
982*810390e3Srobert dfsan_label length_label,
983*810390e3Srobert dfsan_label *ret_label) {
984*810390e3Srobert int ret = getentropy(buffer, length);
985*810390e3Srobert if (ret == 0) {
986*810390e3Srobert dfsan_set_label(0, buffer, length);
987*810390e3Srobert }
988*810390e3Srobert *ret_label = 0;
989*810390e3Srobert return ret;
990*810390e3Srobert }
991*810390e3Srobert
__dfso_getentropy(void * buffer,size_t length,dfsan_label buffer_label,dfsan_label length_label,dfsan_label * ret_label,dfsan_origin buffer_origin,dfsan_origin length_origin,dfsan_origin * ret_origin)992*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,
993*810390e3Srobert dfsan_label buffer_label,
994*810390e3Srobert dfsan_label length_label,
995*810390e3Srobert dfsan_label *ret_label,
996*810390e3Srobert dfsan_origin buffer_origin,
997*810390e3Srobert dfsan_origin length_origin,
998*810390e3Srobert dfsan_origin *ret_origin) {
999*810390e3Srobert return __dfsw_getentropy(buffer, length, buffer_label, length_label,
1000*810390e3Srobert ret_label);
1001*810390e3Srobert }
1002*810390e3Srobert
1003d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_gethostname(char * name,size_t len,dfsan_label name_label,dfsan_label len_label,dfsan_label * ret_label)10043cab2bb3Spatrick int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
10053cab2bb3Spatrick dfsan_label len_label, dfsan_label *ret_label) {
10063cab2bb3Spatrick int ret = gethostname(name, len);
10073cab2bb3Spatrick if (ret == 0) {
10083cab2bb3Spatrick dfsan_set_label(0, name, strlen(name) + 1);
10093cab2bb3Spatrick }
10103cab2bb3Spatrick *ret_label = 0;
10113cab2bb3Spatrick return ret;
10123cab2bb3Spatrick }
10133cab2bb3Spatrick
10143cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_gethostname(char * name,size_t len,dfsan_label name_label,dfsan_label len_label,dfsan_label * ret_label,dfsan_origin name_origin,dfsan_origin len_origin,dfsan_label * ret_origin)1015d89ec533Spatrick int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
1016d89ec533Spatrick dfsan_label len_label, dfsan_label *ret_label,
1017d89ec533Spatrick dfsan_origin name_origin, dfsan_origin len_origin,
1018d89ec533Spatrick dfsan_label *ret_origin) {
1019d89ec533Spatrick return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
1020d89ec533Spatrick }
1021d89ec533Spatrick
1022d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getrlimit(int resource,struct rlimit * rlim,dfsan_label resource_label,dfsan_label rlim_label,dfsan_label * ret_label)10233cab2bb3Spatrick int __dfsw_getrlimit(int resource, struct rlimit *rlim,
10243cab2bb3Spatrick dfsan_label resource_label, dfsan_label rlim_label,
10253cab2bb3Spatrick dfsan_label *ret_label) {
10263cab2bb3Spatrick int ret = getrlimit(resource, rlim);
10273cab2bb3Spatrick if (ret == 0) {
10283cab2bb3Spatrick dfsan_set_label(0, rlim, sizeof(struct rlimit));
10293cab2bb3Spatrick }
10303cab2bb3Spatrick *ret_label = 0;
10313cab2bb3Spatrick return ret;
10323cab2bb3Spatrick }
10333cab2bb3Spatrick
10343cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_getrlimit(int resource,struct rlimit * rlim,dfsan_label resource_label,dfsan_label rlim_label,dfsan_label * ret_label,dfsan_origin resource_origin,dfsan_origin rlim_origin,dfsan_origin * ret_origin)1035d89ec533Spatrick int __dfso_getrlimit(int resource, struct rlimit *rlim,
1036d89ec533Spatrick dfsan_label resource_label, dfsan_label rlim_label,
1037d89ec533Spatrick dfsan_label *ret_label, dfsan_origin resource_origin,
1038d89ec533Spatrick dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
1039d89ec533Spatrick return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
1040d89ec533Spatrick ret_label);
1041d89ec533Spatrick }
1042d89ec533Spatrick
1043d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getrusage(int who,struct rusage * usage,dfsan_label who_label,dfsan_label usage_label,dfsan_label * ret_label)10443cab2bb3Spatrick int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
10453cab2bb3Spatrick dfsan_label usage_label, dfsan_label *ret_label) {
10463cab2bb3Spatrick int ret = getrusage(who, usage);
10473cab2bb3Spatrick if (ret == 0) {
10483cab2bb3Spatrick dfsan_set_label(0, usage, sizeof(struct rusage));
10493cab2bb3Spatrick }
10503cab2bb3Spatrick *ret_label = 0;
10513cab2bb3Spatrick return ret;
10523cab2bb3Spatrick }
10533cab2bb3Spatrick
10543cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_getrusage(int who,struct rusage * usage,dfsan_label who_label,dfsan_label usage_label,dfsan_label * ret_label,dfsan_origin who_origin,dfsan_origin usage_origin,dfsan_label * ret_origin)1055d89ec533Spatrick int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1056d89ec533Spatrick dfsan_label usage_label, dfsan_label *ret_label,
1057d89ec533Spatrick dfsan_origin who_origin, dfsan_origin usage_origin,
1058d89ec533Spatrick dfsan_label *ret_origin) {
1059d89ec533Spatrick return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
1060d89ec533Spatrick }
1061d89ec533Spatrick
1062d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strcpy(char * dest,const char * src,dfsan_label dst_label,dfsan_label src_label,dfsan_label * ret_label)10633cab2bb3Spatrick char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
10643cab2bb3Spatrick dfsan_label src_label, dfsan_label *ret_label) {
1065*810390e3Srobert char *ret = strcpy(dest, src);
10663cab2bb3Spatrick if (ret) {
1067*810390e3Srobert dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);
10683cab2bb3Spatrick }
10693cab2bb3Spatrick *ret_label = dst_label;
10703cab2bb3Spatrick return ret;
10713cab2bb3Spatrick }
10723cab2bb3Spatrick
10733cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strcpy(char * dest,const char * src,dfsan_label dst_label,dfsan_label src_label,dfsan_label * ret_label,dfsan_origin dst_origin,dfsan_origin src_origin,dfsan_origin * ret_origin)1074d89ec533Spatrick char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
1075d89ec533Spatrick dfsan_label src_label, dfsan_label *ret_label,
1076d89ec533Spatrick dfsan_origin dst_origin, dfsan_origin src_origin,
1077d89ec533Spatrick dfsan_origin *ret_origin) {
1078*810390e3Srobert char *ret = strcpy(dest, src);
1079d89ec533Spatrick if (ret) {
1080d89ec533Spatrick size_t str_len = strlen(src) + 1;
1081d89ec533Spatrick dfsan_mem_origin_transfer(dest, src, str_len);
1082*810390e3Srobert dfsan_mem_shadow_transfer(dest, src, str_len);
10833cab2bb3Spatrick }
1084d89ec533Spatrick *ret_label = dst_label;
1085d89ec533Spatrick *ret_origin = dst_origin;
1086d89ec533Spatrick return ret;
1087d89ec533Spatrick }
1088d89ec533Spatrick
dfsan_strtol(const char * nptr,char ** endptr,int base,char ** tmp_endptr)1089d89ec533Spatrick static long int dfsan_strtol(const char *nptr, char **endptr, int base,
1090d89ec533Spatrick char **tmp_endptr) {
1091d89ec533Spatrick assert(tmp_endptr);
1092d89ec533Spatrick long int ret = strtol(nptr, tmp_endptr, base);
1093d89ec533Spatrick if (endptr)
1094d89ec533Spatrick *endptr = *tmp_endptr;
1095d89ec533Spatrick return ret;
1096d89ec533Spatrick }
1097d89ec533Spatrick
dfsan_strtolong_label(const char * nptr,const char * tmp_endptr,dfsan_label base_label,dfsan_label * ret_label)1098d89ec533Spatrick static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
1099d89ec533Spatrick dfsan_label base_label,
1100d89ec533Spatrick dfsan_label *ret_label) {
11013cab2bb3Spatrick if (tmp_endptr > nptr) {
11023cab2bb3Spatrick // If *tmp_endptr is '\0' include its label as well.
11033cab2bb3Spatrick *ret_label = dfsan_union(
11043cab2bb3Spatrick base_label,
11053cab2bb3Spatrick dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
11063cab2bb3Spatrick } else {
11073cab2bb3Spatrick *ret_label = 0;
11083cab2bb3Spatrick }
1109d89ec533Spatrick }
1110d89ec533Spatrick
dfsan_strtolong_origin(const char * nptr,const char * tmp_endptr,dfsan_label base_label,dfsan_label * ret_label,dfsan_origin base_origin,dfsan_origin * ret_origin)1111d89ec533Spatrick static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
1112d89ec533Spatrick dfsan_label base_label,
1113d89ec533Spatrick dfsan_label *ret_label,
1114d89ec533Spatrick dfsan_origin base_origin,
1115d89ec533Spatrick dfsan_origin *ret_origin) {
1116d89ec533Spatrick if (tmp_endptr > nptr) {
1117d89ec533Spatrick // When multiple inputs are tainted, we propagate one of its origins.
1118d89ec533Spatrick // Because checking if base_label is tainted does not need additional
1119d89ec533Spatrick // computation, we prefer to propagating base_origin.
1120d89ec533Spatrick *ret_origin = base_label
1121d89ec533Spatrick ? base_origin
1122d89ec533Spatrick : dfsan_read_origin_of_first_taint(
1123d89ec533Spatrick nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1124d89ec533Spatrick }
1125d89ec533Spatrick }
1126d89ec533Spatrick
1127d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtol(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label)1128d89ec533Spatrick long int __dfsw_strtol(const char *nptr, char **endptr, int base,
1129d89ec533Spatrick dfsan_label nptr_label, dfsan_label endptr_label,
1130d89ec533Spatrick dfsan_label base_label, dfsan_label *ret_label) {
1131d89ec533Spatrick char *tmp_endptr;
1132d89ec533Spatrick long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1133d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
11343cab2bb3Spatrick return ret;
11353cab2bb3Spatrick }
11363cab2bb3Spatrick
11373cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strtol(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label,dfsan_origin nptr_origin,dfsan_origin endptr_origin,dfsan_origin base_origin,dfsan_origin * ret_origin)1138d89ec533Spatrick long int __dfso_strtol(const char *nptr, char **endptr, int base,
11393cab2bb3Spatrick dfsan_label nptr_label, dfsan_label endptr_label,
1140d89ec533Spatrick dfsan_label base_label, dfsan_label *ret_label,
1141d89ec533Spatrick dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1142d89ec533Spatrick dfsan_origin base_origin, dfsan_origin *ret_origin) {
11433cab2bb3Spatrick char *tmp_endptr;
1144d89ec533Spatrick long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1145d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1146d89ec533Spatrick dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1147d89ec533Spatrick ret_origin);
1148d89ec533Spatrick return ret;
11493cab2bb3Spatrick }
1150d89ec533Spatrick
dfsan_strtod(const char * nptr,char ** endptr,char ** tmp_endptr)1151d89ec533Spatrick static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
1152d89ec533Spatrick assert(tmp_endptr);
1153d89ec533Spatrick double ret = strtod(nptr, tmp_endptr);
1154d89ec533Spatrick if (endptr)
1155d89ec533Spatrick *endptr = *tmp_endptr;
1156d89ec533Spatrick return ret;
1157d89ec533Spatrick }
1158d89ec533Spatrick
dfsan_strtod_label(const char * nptr,const char * tmp_endptr,dfsan_label * ret_label)1159d89ec533Spatrick static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
1160d89ec533Spatrick dfsan_label *ret_label) {
11613cab2bb3Spatrick if (tmp_endptr > nptr) {
11623cab2bb3Spatrick // If *tmp_endptr is '\0' include its label as well.
11633cab2bb3Spatrick *ret_label = dfsan_read_label(
11643cab2bb3Spatrick nptr,
11653cab2bb3Spatrick tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
11663cab2bb3Spatrick } else {
11673cab2bb3Spatrick *ret_label = 0;
11683cab2bb3Spatrick }
1169d89ec533Spatrick }
1170d89ec533Spatrick
1171d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtod(const char * nptr,char ** endptr,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label * ret_label)1172d89ec533Spatrick double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1173d89ec533Spatrick dfsan_label endptr_label, dfsan_label *ret_label) {
1174d89ec533Spatrick char *tmp_endptr;
1175d89ec533Spatrick double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1176d89ec533Spatrick dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1177d89ec533Spatrick return ret;
1178d89ec533Spatrick }
1179d89ec533Spatrick
1180d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strtod(const char * nptr,char ** endptr,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label * ret_label,dfsan_origin nptr_origin,dfsan_origin endptr_origin,dfsan_origin * ret_origin)1181d89ec533Spatrick double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1182d89ec533Spatrick dfsan_label endptr_label, dfsan_label *ret_label,
1183d89ec533Spatrick dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1184d89ec533Spatrick dfsan_origin *ret_origin) {
1185d89ec533Spatrick char *tmp_endptr;
1186d89ec533Spatrick double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1187d89ec533Spatrick dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1188d89ec533Spatrick if (tmp_endptr > nptr) {
1189d89ec533Spatrick // If *tmp_endptr is '\0' include its label as well.
1190d89ec533Spatrick *ret_origin = dfsan_read_origin_of_first_taint(
1191d89ec533Spatrick nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1192d89ec533Spatrick } else {
1193d89ec533Spatrick *ret_origin = 0;
1194d89ec533Spatrick }
1195d89ec533Spatrick return ret;
1196d89ec533Spatrick }
1197d89ec533Spatrick
dfsan_strtoll(const char * nptr,char ** endptr,int base,char ** tmp_endptr)1198d89ec533Spatrick static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
1199d89ec533Spatrick char **tmp_endptr) {
1200d89ec533Spatrick assert(tmp_endptr);
1201d89ec533Spatrick long long int ret = strtoll(nptr, tmp_endptr, base);
1202d89ec533Spatrick if (endptr)
1203d89ec533Spatrick *endptr = *tmp_endptr;
12043cab2bb3Spatrick return ret;
12053cab2bb3Spatrick }
12063cab2bb3Spatrick
12073cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtoll(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label)12083cab2bb3Spatrick long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
12093cab2bb3Spatrick dfsan_label nptr_label, dfsan_label endptr_label,
12103cab2bb3Spatrick dfsan_label base_label, dfsan_label *ret_label) {
12113cab2bb3Spatrick char *tmp_endptr;
1212d89ec533Spatrick long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1213d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1214d89ec533Spatrick return ret;
12153cab2bb3Spatrick }
1216d89ec533Spatrick
1217d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strtoll(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label,dfsan_origin nptr_origin,dfsan_origin endptr_origin,dfsan_origin base_origin,dfsan_origin * ret_origin)1218d89ec533Spatrick long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
1219d89ec533Spatrick dfsan_label nptr_label, dfsan_label endptr_label,
1220d89ec533Spatrick dfsan_label base_label, dfsan_label *ret_label,
1221d89ec533Spatrick dfsan_origin nptr_origin,
1222d89ec533Spatrick dfsan_origin endptr_origin,
1223d89ec533Spatrick dfsan_origin base_origin,
1224d89ec533Spatrick dfsan_origin *ret_origin) {
1225d89ec533Spatrick char *tmp_endptr;
1226d89ec533Spatrick long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1227d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1228d89ec533Spatrick dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1229d89ec533Spatrick ret_origin);
1230d89ec533Spatrick return ret;
12313cab2bb3Spatrick }
1232d89ec533Spatrick
dfsan_strtoul(const char * nptr,char ** endptr,int base,char ** tmp_endptr)1233d89ec533Spatrick static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
1234d89ec533Spatrick int base, char **tmp_endptr) {
1235d89ec533Spatrick assert(tmp_endptr);
1236d89ec533Spatrick unsigned long int ret = strtoul(nptr, tmp_endptr, base);
1237d89ec533Spatrick if (endptr)
1238d89ec533Spatrick *endptr = *tmp_endptr;
12393cab2bb3Spatrick return ret;
12403cab2bb3Spatrick }
12413cab2bb3Spatrick
12423cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtoul(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label)12433cab2bb3Spatrick unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
12443cab2bb3Spatrick dfsan_label nptr_label, dfsan_label endptr_label,
12453cab2bb3Spatrick dfsan_label base_label, dfsan_label *ret_label) {
12463cab2bb3Spatrick char *tmp_endptr;
1247d89ec533Spatrick unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1248d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1249d89ec533Spatrick return ret;
12503cab2bb3Spatrick }
1251d89ec533Spatrick
1252d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strtoul(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label,dfsan_origin nptr_origin,dfsan_origin endptr_origin,dfsan_origin base_origin,dfsan_origin * ret_origin)1253d89ec533Spatrick unsigned long int __dfso_strtoul(
1254d89ec533Spatrick const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1255d89ec533Spatrick dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1256d89ec533Spatrick dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1257d89ec533Spatrick dfsan_origin base_origin, dfsan_origin *ret_origin) {
1258d89ec533Spatrick char *tmp_endptr;
1259d89ec533Spatrick unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1260d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1261d89ec533Spatrick dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1262d89ec533Spatrick ret_origin);
1263d89ec533Spatrick return ret;
12643cab2bb3Spatrick }
1265d89ec533Spatrick
dfsan_strtoull(const char * nptr,char ** endptr,int base,char ** tmp_endptr)1266d89ec533Spatrick static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
1267d89ec533Spatrick int base, char **tmp_endptr) {
1268d89ec533Spatrick assert(tmp_endptr);
1269d89ec533Spatrick long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
1270d89ec533Spatrick if (endptr)
1271d89ec533Spatrick *endptr = *tmp_endptr;
12723cab2bb3Spatrick return ret;
12733cab2bb3Spatrick }
12743cab2bb3Spatrick
12753cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtoull(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label)12763cab2bb3Spatrick long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
1277d89ec533Spatrick int base, dfsan_label nptr_label,
1278d89ec533Spatrick dfsan_label endptr_label,
12793cab2bb3Spatrick dfsan_label base_label,
12803cab2bb3Spatrick dfsan_label *ret_label) {
12813cab2bb3Spatrick char *tmp_endptr;
1282d89ec533Spatrick long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1283d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1284d89ec533Spatrick return ret;
12853cab2bb3Spatrick }
1286d89ec533Spatrick
1287d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_strtoull(const char * nptr,char ** endptr,int base,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label base_label,dfsan_label * ret_label,dfsan_origin nptr_origin,dfsan_origin endptr_origin,dfsan_origin base_origin,dfsan_origin * ret_origin)1288d89ec533Spatrick long long unsigned int __dfso_strtoull(
1289d89ec533Spatrick const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1290d89ec533Spatrick dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1291d89ec533Spatrick dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1292d89ec533Spatrick dfsan_origin base_origin, dfsan_origin *ret_origin) {
1293d89ec533Spatrick char *tmp_endptr;
1294d89ec533Spatrick long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1295d89ec533Spatrick dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1296d89ec533Spatrick dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1297d89ec533Spatrick ret_origin);
12983cab2bb3Spatrick return ret;
12993cab2bb3Spatrick }
13003cab2bb3Spatrick
13013cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_time(time_t * t,dfsan_label t_label,dfsan_label * ret_label)13023cab2bb3Spatrick time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
13033cab2bb3Spatrick time_t ret = time(t);
13043cab2bb3Spatrick if (ret != (time_t) -1 && t) {
13053cab2bb3Spatrick dfsan_set_label(0, t, sizeof(time_t));
13063cab2bb3Spatrick }
13073cab2bb3Spatrick *ret_label = 0;
13083cab2bb3Spatrick return ret;
13093cab2bb3Spatrick }
13103cab2bb3Spatrick
13113cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_time(time_t * t,dfsan_label t_label,dfsan_label * ret_label,dfsan_origin t_origin,dfsan_origin * ret_origin)1312d89ec533Spatrick time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
1313d89ec533Spatrick dfsan_origin t_origin, dfsan_origin *ret_origin) {
1314d89ec533Spatrick return __dfsw_time(t, t_label, ret_label);
1315d89ec533Spatrick }
1316d89ec533Spatrick
1317d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_inet_pton(int af,const char * src,void * dst,dfsan_label af_label,dfsan_label src_label,dfsan_label dst_label,dfsan_label * ret_label)13183cab2bb3Spatrick int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
13193cab2bb3Spatrick dfsan_label src_label, dfsan_label dst_label,
13203cab2bb3Spatrick dfsan_label *ret_label) {
13213cab2bb3Spatrick int ret = inet_pton(af, src, dst);
13223cab2bb3Spatrick if (ret == 1) {
13233cab2bb3Spatrick dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
13243cab2bb3Spatrick af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
13253cab2bb3Spatrick }
13263cab2bb3Spatrick *ret_label = 0;
13273cab2bb3Spatrick return ret;
13283cab2bb3Spatrick }
13293cab2bb3Spatrick
13303cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_inet_pton(int af,const char * src,void * dst,dfsan_label af_label,dfsan_label src_label,dfsan_label dst_label,dfsan_label * ret_label,dfsan_origin af_origin,dfsan_origin src_origin,dfsan_origin dst_origin,dfsan_origin * ret_origin)1331d89ec533Spatrick int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1332d89ec533Spatrick dfsan_label src_label, dfsan_label dst_label,
1333d89ec533Spatrick dfsan_label *ret_label, dfsan_origin af_origin,
1334d89ec533Spatrick dfsan_origin src_origin, dfsan_origin dst_origin,
1335d89ec533Spatrick dfsan_origin *ret_origin) {
1336d89ec533Spatrick int ret = inet_pton(af, src, dst);
1337d89ec533Spatrick if (ret == 1) {
1338d89ec533Spatrick int src_len = strlen(src) + 1;
1339d89ec533Spatrick dfsan_set_label_origin(
1340d89ec533Spatrick dfsan_read_label(src, src_len),
1341d89ec533Spatrick dfsan_read_origin_of_first_taint(src, src_len), dst,
1342d89ec533Spatrick af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1343d89ec533Spatrick }
1344d89ec533Spatrick *ret_label = 0;
1345d89ec533Spatrick return ret;
1346d89ec533Spatrick }
1347d89ec533Spatrick
1348d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_localtime_r(const time_t * timep,struct tm * result,dfsan_label timep_label,dfsan_label result_label,dfsan_label * ret_label)13493cab2bb3Spatrick struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
13503cab2bb3Spatrick dfsan_label timep_label, dfsan_label result_label,
13513cab2bb3Spatrick dfsan_label *ret_label) {
13523cab2bb3Spatrick struct tm *ret = localtime_r(timep, result);
13533cab2bb3Spatrick if (ret) {
13543cab2bb3Spatrick dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
13553cab2bb3Spatrick sizeof(struct tm));
13563cab2bb3Spatrick *ret_label = result_label;
13573cab2bb3Spatrick } else {
13583cab2bb3Spatrick *ret_label = 0;
13593cab2bb3Spatrick }
13603cab2bb3Spatrick return ret;
13613cab2bb3Spatrick }
13623cab2bb3Spatrick
13633cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_localtime_r(const time_t * timep,struct tm * result,dfsan_label timep_label,dfsan_label result_label,dfsan_label * ret_label,dfsan_origin timep_origin,dfsan_origin result_origin,dfsan_origin * ret_origin)1364d89ec533Spatrick struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
1365d89ec533Spatrick dfsan_label timep_label, dfsan_label result_label,
1366d89ec533Spatrick dfsan_label *ret_label, dfsan_origin timep_origin,
1367d89ec533Spatrick dfsan_origin result_origin,
1368d89ec533Spatrick dfsan_origin *ret_origin) {
1369d89ec533Spatrick struct tm *ret = localtime_r(timep, result);
1370d89ec533Spatrick if (ret) {
1371d89ec533Spatrick dfsan_set_label_origin(
1372d89ec533Spatrick dfsan_read_label(timep, sizeof(time_t)),
1373d89ec533Spatrick dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
1374d89ec533Spatrick sizeof(struct tm));
1375d89ec533Spatrick *ret_label = result_label;
1376d89ec533Spatrick *ret_origin = result_origin;
1377d89ec533Spatrick } else {
1378d89ec533Spatrick *ret_label = 0;
1379d89ec533Spatrick }
1380d89ec533Spatrick return ret;
1381d89ec533Spatrick }
1382d89ec533Spatrick
1383d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getpwuid_r(id_t uid,struct passwd * pwd,char * buf,size_t buflen,struct passwd ** result,dfsan_label uid_label,dfsan_label pwd_label,dfsan_label buf_label,dfsan_label buflen_label,dfsan_label result_label,dfsan_label * ret_label)13843cab2bb3Spatrick int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
13853cab2bb3Spatrick char *buf, size_t buflen, struct passwd **result,
13863cab2bb3Spatrick dfsan_label uid_label, dfsan_label pwd_label,
13873cab2bb3Spatrick dfsan_label buf_label, dfsan_label buflen_label,
13883cab2bb3Spatrick dfsan_label result_label, dfsan_label *ret_label) {
13893cab2bb3Spatrick // Store the data in pwd, the strings referenced from pwd in buf, and the
13903cab2bb3Spatrick // address of pwd in *result. On failure, NULL is stored in *result.
13913cab2bb3Spatrick int ret = getpwuid_r(uid, pwd, buf, buflen, result);
13923cab2bb3Spatrick if (ret == 0) {
13933cab2bb3Spatrick dfsan_set_label(0, pwd, sizeof(struct passwd));
13943cab2bb3Spatrick dfsan_set_label(0, buf, strlen(buf) + 1);
13953cab2bb3Spatrick }
13963cab2bb3Spatrick *ret_label = 0;
13973cab2bb3Spatrick dfsan_set_label(0, result, sizeof(struct passwd*));
13983cab2bb3Spatrick return ret;
13993cab2bb3Spatrick }
14003cab2bb3Spatrick
14013cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_getpwuid_r(id_t uid,struct passwd * pwd,char * buf,size_t buflen,struct passwd ** result,dfsan_label uid_label,dfsan_label pwd_label,dfsan_label buf_label,dfsan_label buflen_label,dfsan_label result_label,dfsan_label * ret_label,dfsan_origin uid_origin,dfsan_origin pwd_origin,dfsan_origin buf_origin,dfsan_origin buflen_origin,dfsan_origin result_origin,dfsan_origin * ret_origin)1402d89ec533Spatrick int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
1403d89ec533Spatrick struct passwd **result, dfsan_label uid_label,
1404d89ec533Spatrick dfsan_label pwd_label, dfsan_label buf_label,
1405d89ec533Spatrick dfsan_label buflen_label, dfsan_label result_label,
1406d89ec533Spatrick dfsan_label *ret_label, dfsan_origin uid_origin,
1407d89ec533Spatrick dfsan_origin pwd_origin, dfsan_origin buf_origin,
1408d89ec533Spatrick dfsan_origin buflen_origin, dfsan_origin result_origin,
1409d89ec533Spatrick dfsan_origin *ret_origin) {
1410d89ec533Spatrick return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
1411d89ec533Spatrick buf_label, buflen_label, result_label, ret_label);
1412d89ec533Spatrick }
1413d89ec533Spatrick
1414d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout,dfsan_label epfd_label,dfsan_label events_label,dfsan_label maxevents_label,dfsan_label timeout_label,dfsan_label * ret_label)1415d89ec533Spatrick int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1416d89ec533Spatrick int timeout, dfsan_label epfd_label,
1417d89ec533Spatrick dfsan_label events_label, dfsan_label maxevents_label,
1418d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label) {
1419d89ec533Spatrick int ret = epoll_wait(epfd, events, maxevents, timeout);
1420d89ec533Spatrick if (ret > 0)
1421d89ec533Spatrick dfsan_set_label(0, events, ret * sizeof(*events));
1422d89ec533Spatrick *ret_label = 0;
1423d89ec533Spatrick return ret;
1424d89ec533Spatrick }
1425d89ec533Spatrick
1426d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout,dfsan_label epfd_label,dfsan_label events_label,dfsan_label maxevents_label,dfsan_label timeout_label,dfsan_label * ret_label,dfsan_origin epfd_origin,dfsan_origin events_origin,dfsan_origin maxevents_origin,dfsan_origin timeout_origin,dfsan_origin * ret_origin)1427d89ec533Spatrick int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1428d89ec533Spatrick int timeout, dfsan_label epfd_label,
1429d89ec533Spatrick dfsan_label events_label, dfsan_label maxevents_label,
1430d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label,
1431d89ec533Spatrick dfsan_origin epfd_origin, dfsan_origin events_origin,
1432d89ec533Spatrick dfsan_origin maxevents_origin,
1433d89ec533Spatrick dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1434d89ec533Spatrick return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
1435d89ec533Spatrick events_label, maxevents_label, timeout_label,
1436d89ec533Spatrick ret_label);
1437d89ec533Spatrick }
1438d89ec533Spatrick
1439d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_poll(struct pollfd * fds,nfds_t nfds,int timeout,dfsan_label dfs_label,dfsan_label nfds_label,dfsan_label timeout_label,dfsan_label * ret_label)14403cab2bb3Spatrick int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
14413cab2bb3Spatrick dfsan_label dfs_label, dfsan_label nfds_label,
14423cab2bb3Spatrick dfsan_label timeout_label, dfsan_label *ret_label) {
14433cab2bb3Spatrick int ret = poll(fds, nfds, timeout);
14443cab2bb3Spatrick if (ret >= 0) {
14453cab2bb3Spatrick for (; nfds > 0; --nfds) {
14463cab2bb3Spatrick dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
14473cab2bb3Spatrick }
14483cab2bb3Spatrick }
14493cab2bb3Spatrick *ret_label = 0;
14503cab2bb3Spatrick return ret;
14513cab2bb3Spatrick }
14523cab2bb3Spatrick
14533cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_poll(struct pollfd * fds,nfds_t nfds,int timeout,dfsan_label dfs_label,dfsan_label nfds_label,dfsan_label timeout_label,dfsan_label * ret_label,dfsan_origin dfs_origin,dfsan_origin nfds_origin,dfsan_origin timeout_origin,dfsan_origin * ret_origin)1454d89ec533Spatrick int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1455d89ec533Spatrick dfsan_label dfs_label, dfsan_label nfds_label,
1456d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label,
1457d89ec533Spatrick dfsan_origin dfs_origin, dfsan_origin nfds_origin,
1458d89ec533Spatrick dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1459d89ec533Spatrick return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
1460d89ec533Spatrick ret_label);
1461d89ec533Spatrick }
1462d89ec533Spatrick
1463d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout,dfsan_label nfds_label,dfsan_label readfds_label,dfsan_label writefds_label,dfsan_label exceptfds_label,dfsan_label timeout_label,dfsan_label * ret_label)14643cab2bb3Spatrick int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
14653cab2bb3Spatrick fd_set *exceptfds, struct timeval *timeout,
14663cab2bb3Spatrick dfsan_label nfds_label, dfsan_label readfds_label,
14673cab2bb3Spatrick dfsan_label writefds_label, dfsan_label exceptfds_label,
14683cab2bb3Spatrick dfsan_label timeout_label, dfsan_label *ret_label) {
14693cab2bb3Spatrick int ret = select(nfds, readfds, writefds, exceptfds, timeout);
14703cab2bb3Spatrick // Clear everything (also on error) since their content is either set or
14713cab2bb3Spatrick // undefined.
14723cab2bb3Spatrick if (readfds) {
14733cab2bb3Spatrick dfsan_set_label(0, readfds, sizeof(fd_set));
14743cab2bb3Spatrick }
14753cab2bb3Spatrick if (writefds) {
14763cab2bb3Spatrick dfsan_set_label(0, writefds, sizeof(fd_set));
14773cab2bb3Spatrick }
14783cab2bb3Spatrick if (exceptfds) {
14793cab2bb3Spatrick dfsan_set_label(0, exceptfds, sizeof(fd_set));
14803cab2bb3Spatrick }
14813cab2bb3Spatrick dfsan_set_label(0, timeout, sizeof(struct timeval));
14823cab2bb3Spatrick *ret_label = 0;
14833cab2bb3Spatrick return ret;
14843cab2bb3Spatrick }
14853cab2bb3Spatrick
14863cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout,dfsan_label nfds_label,dfsan_label readfds_label,dfsan_label writefds_label,dfsan_label exceptfds_label,dfsan_label timeout_label,dfsan_label * ret_label,dfsan_origin nfds_origin,dfsan_origin readfds_origin,dfsan_origin writefds_origin,dfsan_origin exceptfds_origin,dfsan_origin timeout_origin,dfsan_origin * ret_origin)1487d89ec533Spatrick int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
1488d89ec533Spatrick fd_set *exceptfds, struct timeval *timeout,
1489d89ec533Spatrick dfsan_label nfds_label, dfsan_label readfds_label,
1490d89ec533Spatrick dfsan_label writefds_label, dfsan_label exceptfds_label,
1491d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label,
1492d89ec533Spatrick dfsan_origin nfds_origin, dfsan_origin readfds_origin,
1493d89ec533Spatrick dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
1494d89ec533Spatrick dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1495d89ec533Spatrick return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
1496d89ec533Spatrick readfds_label, writefds_label, exceptfds_label,
1497d89ec533Spatrick timeout_label, ret_label);
1498d89ec533Spatrick }
1499d89ec533Spatrick
1500d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sched_getaffinity(pid_t pid,size_t cpusetsize,cpu_set_t * mask,dfsan_label pid_label,dfsan_label cpusetsize_label,dfsan_label mask_label,dfsan_label * ret_label)15013cab2bb3Spatrick int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
15023cab2bb3Spatrick dfsan_label pid_label,
15033cab2bb3Spatrick dfsan_label cpusetsize_label,
15043cab2bb3Spatrick dfsan_label mask_label, dfsan_label *ret_label) {
15053cab2bb3Spatrick int ret = sched_getaffinity(pid, cpusetsize, mask);
15063cab2bb3Spatrick if (ret == 0) {
15073cab2bb3Spatrick dfsan_set_label(0, mask, cpusetsize);
15083cab2bb3Spatrick }
15093cab2bb3Spatrick *ret_label = 0;
15103cab2bb3Spatrick return ret;
15113cab2bb3Spatrick }
15123cab2bb3Spatrick
15133cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sched_getaffinity(pid_t pid,size_t cpusetsize,cpu_set_t * mask,dfsan_label pid_label,dfsan_label cpusetsize_label,dfsan_label mask_label,dfsan_label * ret_label,dfsan_origin pid_origin,dfsan_origin cpusetsize_origin,dfsan_origin mask_origin,dfsan_origin * ret_origin)1514d89ec533Spatrick int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1515d89ec533Spatrick dfsan_label pid_label,
1516d89ec533Spatrick dfsan_label cpusetsize_label,
1517d89ec533Spatrick dfsan_label mask_label, dfsan_label *ret_label,
1518d89ec533Spatrick dfsan_origin pid_origin,
1519d89ec533Spatrick dfsan_origin cpusetsize_origin,
1520d89ec533Spatrick dfsan_origin mask_origin,
1521d89ec533Spatrick dfsan_origin *ret_origin) {
1522d89ec533Spatrick return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
1523d89ec533Spatrick cpusetsize_label, mask_label, ret_label);
1524d89ec533Spatrick }
1525d89ec533Spatrick
1526d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sigemptyset(sigset_t * set,dfsan_label set_label,dfsan_label * ret_label)15273cab2bb3Spatrick int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
15283cab2bb3Spatrick dfsan_label *ret_label) {
15293cab2bb3Spatrick int ret = sigemptyset(set);
15303cab2bb3Spatrick dfsan_set_label(0, set, sizeof(sigset_t));
1531d89ec533Spatrick *ret_label = 0;
15323cab2bb3Spatrick return ret;
15333cab2bb3Spatrick }
15343cab2bb3Spatrick
15353cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sigemptyset(sigset_t * set,dfsan_label set_label,dfsan_label * ret_label,dfsan_origin set_origin,dfsan_origin * ret_origin)1536d89ec533Spatrick int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
1537d89ec533Spatrick dfsan_label *ret_label, dfsan_origin set_origin,
1538d89ec533Spatrick dfsan_origin *ret_origin) {
1539d89ec533Spatrick return __dfsw_sigemptyset(set, set_label, ret_label);
1540d89ec533Spatrick }
1541d89ec533Spatrick
1542d89ec533Spatrick class SignalHandlerScope {
1543d89ec533Spatrick public:
SignalHandlerScope()1544d89ec533Spatrick SignalHandlerScope() {
1545d89ec533Spatrick if (DFsanThread *t = GetCurrentThread())
1546d89ec533Spatrick t->EnterSignalHandler();
1547d89ec533Spatrick }
~SignalHandlerScope()1548d89ec533Spatrick ~SignalHandlerScope() {
1549d89ec533Spatrick if (DFsanThread *t = GetCurrentThread())
1550d89ec533Spatrick t->LeaveSignalHandler();
1551d89ec533Spatrick }
1552d89ec533Spatrick };
1553d89ec533Spatrick
1554d89ec533Spatrick // Clear DFSan runtime TLS state at the end of a scope.
1555d89ec533Spatrick //
1556d89ec533Spatrick // Implementation must be async-signal-safe and use small data size, because
1557d89ec533Spatrick // instances of this class may live on the signal handler stack.
1558d89ec533Spatrick //
1559d89ec533Spatrick // DFSan uses TLS to pass metadata of arguments and return values. When an
1560d89ec533Spatrick // instrumented function accesses the TLS, if a signal callback happens, and the
1561d89ec533Spatrick // callback calls other instrumented functions with updating the same TLS, the
1562d89ec533Spatrick // TLS is in an inconsistent state after the callback ends. This may cause
1563d89ec533Spatrick // either under-tainting or over-tainting.
1564d89ec533Spatrick //
1565d89ec533Spatrick // The current implementation simply resets TLS at restore. This prevents from
1566d89ec533Spatrick // over-tainting. Although under-tainting may still happen, a taint flow can be
1567d89ec533Spatrick // found eventually if we run a DFSan-instrumented program multiple times. The
1568d89ec533Spatrick // alternative option is saving the entire TLS. However the TLS storage takes
1569d89ec533Spatrick // 2k bytes, and signal calls could be nested. So it does not seem worth.
1570d89ec533Spatrick class ScopedClearThreadLocalState {
1571d89ec533Spatrick public:
ScopedClearThreadLocalState()1572d89ec533Spatrick ScopedClearThreadLocalState() {}
~ScopedClearThreadLocalState()1573d89ec533Spatrick ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1574d89ec533Spatrick };
1575d89ec533Spatrick
1576d89ec533Spatrick // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1577d89ec533Spatrick const int kMaxSignals = 1024;
1578d89ec533Spatrick static atomic_uintptr_t sigactions[kMaxSignals];
1579d89ec533Spatrick
SignalHandler(int signo)1580d89ec533Spatrick static void SignalHandler(int signo) {
1581d89ec533Spatrick SignalHandlerScope signal_handler_scope;
1582d89ec533Spatrick ScopedClearThreadLocalState scoped_clear_tls;
1583d89ec533Spatrick
1584*810390e3Srobert // Clear shadows for all inputs provided by system.
1585d89ec533Spatrick dfsan_clear_arg_tls(0, sizeof(dfsan_label));
1586d89ec533Spatrick
1587d89ec533Spatrick typedef void (*signal_cb)(int x);
1588d89ec533Spatrick signal_cb cb =
1589d89ec533Spatrick (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1590d89ec533Spatrick cb(signo);
1591d89ec533Spatrick }
1592d89ec533Spatrick
SignalAction(int signo,siginfo_t * si,void * uc)1593d89ec533Spatrick static void SignalAction(int signo, siginfo_t *si, void *uc) {
1594d89ec533Spatrick SignalHandlerScope signal_handler_scope;
1595d89ec533Spatrick ScopedClearThreadLocalState scoped_clear_tls;
1596d89ec533Spatrick
1597d89ec533Spatrick // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1598d89ec533Spatrick dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
1599d89ec533Spatrick dfsan_set_label(0, si, sizeof(*si));
1600d89ec533Spatrick dfsan_set_label(0, uc, sizeof(ucontext_t));
1601d89ec533Spatrick
1602d89ec533Spatrick typedef void (*sigaction_cb)(int, siginfo_t *, void *);
1603d89ec533Spatrick sigaction_cb cb =
1604d89ec533Spatrick (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1605d89ec533Spatrick cb(signo, si, uc);
1606d89ec533Spatrick }
1607d89ec533Spatrick
1608d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact,dfsan_label signum_label,dfsan_label act_label,dfsan_label oldact_label,dfsan_label * ret_label)16093cab2bb3Spatrick int __dfsw_sigaction(int signum, const struct sigaction *act,
16103cab2bb3Spatrick struct sigaction *oldact, dfsan_label signum_label,
16113cab2bb3Spatrick dfsan_label act_label, dfsan_label oldact_label,
16123cab2bb3Spatrick dfsan_label *ret_label) {
1613d89ec533Spatrick CHECK_LT(signum, kMaxSignals);
1614d89ec533Spatrick SignalSpinLocker lock;
1615d89ec533Spatrick uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1616d89ec533Spatrick struct sigaction new_act;
1617d89ec533Spatrick struct sigaction *pnew_act = act ? &new_act : nullptr;
1618d89ec533Spatrick if (act) {
1619d89ec533Spatrick internal_memcpy(pnew_act, act, sizeof(struct sigaction));
1620d89ec533Spatrick if (pnew_act->sa_flags & SA_SIGINFO) {
1621d89ec533Spatrick uptr cb = (uptr)(pnew_act->sa_sigaction);
1622d89ec533Spatrick if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1623d89ec533Spatrick atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1624d89ec533Spatrick pnew_act->sa_sigaction = SignalAction;
1625d89ec533Spatrick }
1626d89ec533Spatrick } else {
1627d89ec533Spatrick uptr cb = (uptr)(pnew_act->sa_handler);
1628d89ec533Spatrick if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1629d89ec533Spatrick atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1630d89ec533Spatrick pnew_act->sa_handler = SignalHandler;
1631d89ec533Spatrick }
1632d89ec533Spatrick }
1633d89ec533Spatrick }
1634d89ec533Spatrick
1635d89ec533Spatrick int ret = sigaction(signum, pnew_act, oldact);
1636d89ec533Spatrick
1637d89ec533Spatrick if (ret == 0 && oldact) {
1638d89ec533Spatrick if (oldact->sa_flags & SA_SIGINFO) {
1639d89ec533Spatrick if (oldact->sa_sigaction == SignalAction)
1640d89ec533Spatrick oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
1641d89ec533Spatrick } else {
1642d89ec533Spatrick if (oldact->sa_handler == SignalHandler)
1643d89ec533Spatrick oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
1644d89ec533Spatrick }
1645d89ec533Spatrick }
1646d89ec533Spatrick
16473cab2bb3Spatrick if (oldact) {
16483cab2bb3Spatrick dfsan_set_label(0, oldact, sizeof(struct sigaction));
16493cab2bb3Spatrick }
16503cab2bb3Spatrick *ret_label = 0;
16513cab2bb3Spatrick return ret;
16523cab2bb3Spatrick }
16533cab2bb3Spatrick
16543cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact,dfsan_label signum_label,dfsan_label act_label,dfsan_label oldact_label,dfsan_label * ret_label,dfsan_origin signum_origin,dfsan_origin act_origin,dfsan_origin oldact_origin,dfsan_origin * ret_origin)1655d89ec533Spatrick int __dfso_sigaction(int signum, const struct sigaction *act,
1656d89ec533Spatrick struct sigaction *oldact, dfsan_label signum_label,
1657d89ec533Spatrick dfsan_label act_label, dfsan_label oldact_label,
1658d89ec533Spatrick dfsan_label *ret_label, dfsan_origin signum_origin,
1659d89ec533Spatrick dfsan_origin act_origin, dfsan_origin oldact_origin,
1660d89ec533Spatrick dfsan_origin *ret_origin) {
1661d89ec533Spatrick return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
1662d89ec533Spatrick oldact_label, ret_label);
1663d89ec533Spatrick }
1664d89ec533Spatrick
dfsan_signal(int signum,sighandler_t handler,dfsan_label * ret_label)1665d89ec533Spatrick static sighandler_t dfsan_signal(int signum, sighandler_t handler,
1666d89ec533Spatrick dfsan_label *ret_label) {
1667d89ec533Spatrick CHECK_LT(signum, kMaxSignals);
1668d89ec533Spatrick SignalSpinLocker lock;
1669d89ec533Spatrick uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1670d89ec533Spatrick if (handler != SIG_IGN && handler != SIG_DFL) {
1671d89ec533Spatrick atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
1672d89ec533Spatrick handler = &SignalHandler;
1673d89ec533Spatrick }
1674d89ec533Spatrick
1675d89ec533Spatrick sighandler_t ret = signal(signum, handler);
1676d89ec533Spatrick
1677d89ec533Spatrick if (ret == SignalHandler)
1678d89ec533Spatrick ret = (sighandler_t)old_cb;
1679d89ec533Spatrick
1680d89ec533Spatrick *ret_label = 0;
1681d89ec533Spatrick return ret;
1682d89ec533Spatrick }
1683d89ec533Spatrick
1684d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_signal(int signum,sighandler_t handler,dfsan_label signum_label,dfsan_label handler_label,dfsan_label * ret_label)1685*810390e3Srobert sighandler_t __dfsw_signal(int signum, sighandler_t handler,
1686*810390e3Srobert dfsan_label signum_label, dfsan_label handler_label,
1687*810390e3Srobert dfsan_label *ret_label) {
1688d89ec533Spatrick return dfsan_signal(signum, handler, ret_label);
1689d89ec533Spatrick }
1690d89ec533Spatrick
1691d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_signal(int signum,sighandler_t handler,dfsan_label signum_label,dfsan_label handler_label,dfsan_label * ret_label,dfsan_origin signum_origin,dfsan_origin handler_origin,dfsan_origin * ret_origin)1692*810390e3Srobert sighandler_t __dfso_signal(int signum, sighandler_t handler,
1693*810390e3Srobert dfsan_label signum_label, dfsan_label handler_label,
1694d89ec533Spatrick dfsan_label *ret_label, dfsan_origin signum_origin,
1695*810390e3Srobert dfsan_origin handler_origin,
1696*810390e3Srobert dfsan_origin *ret_origin) {
1697d89ec533Spatrick return dfsan_signal(signum, handler, ret_label);
1698d89ec533Spatrick }
1699d89ec533Spatrick
1700d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sigaltstack(const stack_t * ss,stack_t * old_ss,dfsan_label ss_label,dfsan_label old_ss_label,dfsan_label * ret_label)1701d89ec533Spatrick int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1702d89ec533Spatrick dfsan_label old_ss_label, dfsan_label *ret_label) {
1703d89ec533Spatrick int ret = sigaltstack(ss, old_ss);
1704d89ec533Spatrick if (ret != -1 && old_ss)
1705d89ec533Spatrick dfsan_set_label(0, old_ss, sizeof(*old_ss));
1706d89ec533Spatrick *ret_label = 0;
1707d89ec533Spatrick return ret;
1708d89ec533Spatrick }
1709d89ec533Spatrick
1710d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sigaltstack(const stack_t * ss,stack_t * old_ss,dfsan_label ss_label,dfsan_label old_ss_label,dfsan_label * ret_label,dfsan_origin ss_origin,dfsan_origin old_ss_origin,dfsan_origin * ret_origin)1711d89ec533Spatrick int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1712d89ec533Spatrick dfsan_label old_ss_label, dfsan_label *ret_label,
1713d89ec533Spatrick dfsan_origin ss_origin, dfsan_origin old_ss_origin,
1714d89ec533Spatrick dfsan_origin *ret_origin) {
1715d89ec533Spatrick return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
1716d89ec533Spatrick }
1717d89ec533Spatrick
1718d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_gettimeofday(struct timeval * tv,struct timezone * tz,dfsan_label tv_label,dfsan_label tz_label,dfsan_label * ret_label)17193cab2bb3Spatrick int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
17203cab2bb3Spatrick dfsan_label tv_label, dfsan_label tz_label,
17213cab2bb3Spatrick dfsan_label *ret_label) {
17223cab2bb3Spatrick int ret = gettimeofday(tv, tz);
17233cab2bb3Spatrick if (tv) {
17243cab2bb3Spatrick dfsan_set_label(0, tv, sizeof(struct timeval));
17253cab2bb3Spatrick }
17263cab2bb3Spatrick if (tz) {
17273cab2bb3Spatrick dfsan_set_label(0, tz, sizeof(struct timezone));
17283cab2bb3Spatrick }
17293cab2bb3Spatrick *ret_label = 0;
17303cab2bb3Spatrick return ret;
17313cab2bb3Spatrick }
17323cab2bb3Spatrick
1733d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_gettimeofday(struct timeval * tv,struct timezone * tz,dfsan_label tv_label,dfsan_label tz_label,dfsan_label * ret_label,dfsan_origin tv_origin,dfsan_origin tz_origin,dfsan_origin * ret_origin)1734d89ec533Spatrick int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
1735d89ec533Spatrick dfsan_label tv_label, dfsan_label tz_label,
1736d89ec533Spatrick dfsan_label *ret_label, dfsan_origin tv_origin,
1737d89ec533Spatrick dfsan_origin tz_origin, dfsan_origin *ret_origin) {
1738d89ec533Spatrick return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
1739d89ec533Spatrick }
1740d89ec533Spatrick
__dfsw_memchr(void * s,int c,size_t n,dfsan_label s_label,dfsan_label c_label,dfsan_label n_label,dfsan_label * ret_label)17413cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
17423cab2bb3Spatrick dfsan_label s_label,
17433cab2bb3Spatrick dfsan_label c_label,
17443cab2bb3Spatrick dfsan_label n_label,
17453cab2bb3Spatrick dfsan_label *ret_label) {
17463cab2bb3Spatrick void *ret = memchr(s, c, n);
17473cab2bb3Spatrick if (flags().strict_data_dependencies) {
17483cab2bb3Spatrick *ret_label = ret ? s_label : 0;
17493cab2bb3Spatrick } else {
17503cab2bb3Spatrick size_t len =
17513cab2bb3Spatrick ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
17523cab2bb3Spatrick : n;
17533cab2bb3Spatrick *ret_label =
17543cab2bb3Spatrick dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
17553cab2bb3Spatrick }
17563cab2bb3Spatrick return ret;
17573cab2bb3Spatrick }
17583cab2bb3Spatrick
__dfso_memchr(void * s,int c,size_t n,dfsan_label s_label,dfsan_label c_label,dfsan_label n_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin c_origin,dfsan_origin n_origin,dfsan_origin * ret_origin)1759d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
1760d89ec533Spatrick void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
1761d89ec533Spatrick dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
1762d89ec533Spatrick dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
1763d89ec533Spatrick void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
1764d89ec533Spatrick if (flags().strict_data_dependencies) {
1765d89ec533Spatrick if (ret)
1766d89ec533Spatrick *ret_origin = s_origin;
1767d89ec533Spatrick } else {
1768d89ec533Spatrick size_t len =
1769d89ec533Spatrick ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1770d89ec533Spatrick : n;
1771d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
1772d89ec533Spatrick *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1773d89ec533Spatrick }
1774d89ec533Spatrick return ret;
1775d89ec533Spatrick }
1776d89ec533Spatrick
__dfsw_strrchr(char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label)17773cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
17783cab2bb3Spatrick dfsan_label s_label,
17793cab2bb3Spatrick dfsan_label c_label,
17803cab2bb3Spatrick dfsan_label *ret_label) {
17813cab2bb3Spatrick char *ret = strrchr(s, c);
17823cab2bb3Spatrick if (flags().strict_data_dependencies) {
17833cab2bb3Spatrick *ret_label = ret ? s_label : 0;
17843cab2bb3Spatrick } else {
17853cab2bb3Spatrick *ret_label =
17863cab2bb3Spatrick dfsan_union(dfsan_read_label(s, strlen(s) + 1),
17873cab2bb3Spatrick dfsan_union(s_label, c_label));
17883cab2bb3Spatrick }
17893cab2bb3Spatrick
17903cab2bb3Spatrick return ret;
17913cab2bb3Spatrick }
17923cab2bb3Spatrick
__dfso_strrchr(char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin c_origin,dfsan_origin * ret_origin)1793d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
1794d89ec533Spatrick char *s, int c, dfsan_label s_label, dfsan_label c_label,
1795d89ec533Spatrick dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
1796d89ec533Spatrick dfsan_origin *ret_origin) {
1797d89ec533Spatrick char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
1798d89ec533Spatrick if (flags().strict_data_dependencies) {
1799d89ec533Spatrick if (ret)
1800d89ec533Spatrick *ret_origin = s_origin;
1801d89ec533Spatrick } else {
1802d89ec533Spatrick size_t s_len = strlen(s) + 1;
1803d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
1804d89ec533Spatrick *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1805d89ec533Spatrick }
1806d89ec533Spatrick
1807d89ec533Spatrick return ret;
1808d89ec533Spatrick }
1809d89ec533Spatrick
__dfsw_strstr(char * haystack,char * needle,dfsan_label haystack_label,dfsan_label needle_label,dfsan_label * ret_label)18103cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
18113cab2bb3Spatrick dfsan_label haystack_label,
18123cab2bb3Spatrick dfsan_label needle_label,
18133cab2bb3Spatrick dfsan_label *ret_label) {
18143cab2bb3Spatrick char *ret = strstr(haystack, needle);
18153cab2bb3Spatrick if (flags().strict_data_dependencies) {
18163cab2bb3Spatrick *ret_label = ret ? haystack_label : 0;
18173cab2bb3Spatrick } else {
18183cab2bb3Spatrick size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
18193cab2bb3Spatrick *ret_label =
18203cab2bb3Spatrick dfsan_union(dfsan_read_label(haystack, len),
18213cab2bb3Spatrick dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
18223cab2bb3Spatrick dfsan_union(haystack_label, needle_label)));
18233cab2bb3Spatrick }
18243cab2bb3Spatrick
18253cab2bb3Spatrick return ret;
18263cab2bb3Spatrick }
18273cab2bb3Spatrick
__dfso_strstr(char * haystack,char * needle,dfsan_label haystack_label,dfsan_label needle_label,dfsan_label * ret_label,dfsan_origin haystack_origin,dfsan_origin needle_origin,dfsan_origin * ret_origin)1828d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
1829d89ec533Spatrick dfsan_label haystack_label,
1830d89ec533Spatrick dfsan_label needle_label,
1831d89ec533Spatrick dfsan_label *ret_label,
1832d89ec533Spatrick dfsan_origin haystack_origin,
1833d89ec533Spatrick dfsan_origin needle_origin,
1834d89ec533Spatrick dfsan_origin *ret_origin) {
1835d89ec533Spatrick char *ret =
1836d89ec533Spatrick __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
1837d89ec533Spatrick if (flags().strict_data_dependencies) {
1838d89ec533Spatrick if (ret)
1839d89ec533Spatrick *ret_origin = haystack_origin;
1840d89ec533Spatrick } else {
1841d89ec533Spatrick size_t needle_len = strlen(needle);
1842d89ec533Spatrick size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
1843d89ec533Spatrick dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
1844d89ec533Spatrick if (o) {
1845d89ec533Spatrick *ret_origin = o;
1846d89ec533Spatrick } else {
1847d89ec533Spatrick o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
1848d89ec533Spatrick *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
1849d89ec533Spatrick }
1850d89ec533Spatrick }
1851d89ec533Spatrick
1852d89ec533Spatrick return ret;
1853d89ec533Spatrick }
1854d89ec533Spatrick
__dfsw_nanosleep(const struct timespec * req,struct timespec * rem,dfsan_label req_label,dfsan_label rem_label,dfsan_label * ret_label)18553cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
18563cab2bb3Spatrick struct timespec *rem,
18573cab2bb3Spatrick dfsan_label req_label,
18583cab2bb3Spatrick dfsan_label rem_label,
18593cab2bb3Spatrick dfsan_label *ret_label) {
18603cab2bb3Spatrick int ret = nanosleep(req, rem);
18613cab2bb3Spatrick *ret_label = 0;
18623cab2bb3Spatrick if (ret == -1) {
18633cab2bb3Spatrick // Interrupted by a signal, rem is filled with the remaining time.
18643cab2bb3Spatrick dfsan_set_label(0, rem, sizeof(struct timespec));
18653cab2bb3Spatrick }
18663cab2bb3Spatrick return ret;
18673cab2bb3Spatrick }
18683cab2bb3Spatrick
__dfso_nanosleep(const struct timespec * req,struct timespec * rem,dfsan_label req_label,dfsan_label rem_label,dfsan_label * ret_label,dfsan_origin req_origin,dfsan_origin rem_origin,dfsan_origin * ret_origin)1869d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
1870d89ec533Spatrick const struct timespec *req, struct timespec *rem, dfsan_label req_label,
1871d89ec533Spatrick dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
1872d89ec533Spatrick dfsan_origin rem_origin, dfsan_origin *ret_origin) {
1873d89ec533Spatrick return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
1874d89ec533Spatrick }
1875d89ec533Spatrick
clear_msghdr_labels(size_t bytes_written,struct msghdr * msg)1876d89ec533Spatrick static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
1877d89ec533Spatrick dfsan_set_label(0, msg, sizeof(*msg));
1878d89ec533Spatrick dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
1879d89ec533Spatrick dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
1880d89ec533Spatrick for (size_t i = 0; bytes_written > 0; ++i) {
1881d89ec533Spatrick assert(i < msg->msg_iovlen);
1882d89ec533Spatrick struct iovec *iov = &msg->msg_iov[i];
1883d89ec533Spatrick size_t iov_written =
1884d89ec533Spatrick bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
1885d89ec533Spatrick dfsan_set_label(0, iov->iov_base, iov_written);
1886d89ec533Spatrick bytes_written -= iov_written;
1887d89ec533Spatrick }
1888d89ec533Spatrick }
1889d89ec533Spatrick
__dfsw_recvmmsg(int sockfd,struct mmsghdr * msgvec,unsigned int vlen,int flags,struct timespec * timeout,dfsan_label sockfd_label,dfsan_label msgvec_label,dfsan_label vlen_label,dfsan_label flags_label,dfsan_label timeout_label,dfsan_label * ret_label)1890d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
1891d89ec533Spatrick int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1892d89ec533Spatrick struct timespec *timeout, dfsan_label sockfd_label,
1893d89ec533Spatrick dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1894d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label) {
1895d89ec533Spatrick int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
1896d89ec533Spatrick for (int i = 0; i < ret; ++i) {
1897d89ec533Spatrick dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
1898d89ec533Spatrick clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
1899d89ec533Spatrick }
1900d89ec533Spatrick *ret_label = 0;
1901d89ec533Spatrick return ret;
1902d89ec533Spatrick }
1903d89ec533Spatrick
__dfso_recvmmsg(int sockfd,struct mmsghdr * msgvec,unsigned int vlen,int flags,struct timespec * timeout,dfsan_label sockfd_label,dfsan_label msgvec_label,dfsan_label vlen_label,dfsan_label flags_label,dfsan_label timeout_label,dfsan_label * ret_label,dfsan_origin sockfd_origin,dfsan_origin msgvec_origin,dfsan_origin vlen_origin,dfsan_origin flags_origin,dfsan_origin timeout_origin,dfsan_origin * ret_origin)1904d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
1905d89ec533Spatrick int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1906d89ec533Spatrick struct timespec *timeout, dfsan_label sockfd_label,
1907d89ec533Spatrick dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1908d89ec533Spatrick dfsan_label timeout_label, dfsan_label *ret_label,
1909d89ec533Spatrick dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
1910d89ec533Spatrick dfsan_origin vlen_origin, dfsan_origin flags_origin,
1911d89ec533Spatrick dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1912d89ec533Spatrick return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
1913d89ec533Spatrick msgvec_label, vlen_label, flags_label, timeout_label,
1914d89ec533Spatrick ret_label);
1915d89ec533Spatrick }
1916d89ec533Spatrick
__dfsw_recvmsg(int sockfd,struct msghdr * msg,int flags,dfsan_label sockfd_label,dfsan_label msg_label,dfsan_label flags_label,dfsan_label * ret_label)1917d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
1918d89ec533Spatrick int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1919d89ec533Spatrick dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
1920d89ec533Spatrick ssize_t ret = recvmsg(sockfd, msg, flags);
1921d89ec533Spatrick if (ret >= 0)
1922d89ec533Spatrick clear_msghdr_labels(ret, msg);
1923d89ec533Spatrick *ret_label = 0;
1924d89ec533Spatrick return ret;
1925d89ec533Spatrick }
1926d89ec533Spatrick
__dfso_recvmsg(int sockfd,struct msghdr * msg,int flags,dfsan_label sockfd_label,dfsan_label msg_label,dfsan_label flags_label,dfsan_label * ret_label,dfsan_origin sockfd_origin,dfsan_origin msg_origin,dfsan_origin flags_origin,dfsan_origin * ret_origin)1927d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
1928d89ec533Spatrick int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1929d89ec533Spatrick dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
1930d89ec533Spatrick dfsan_origin sockfd_origin, dfsan_origin msg_origin,
1931d89ec533Spatrick dfsan_origin flags_origin, dfsan_origin *ret_origin) {
1932d89ec533Spatrick return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
1933d89ec533Spatrick flags_label, ret_label);
1934d89ec533Spatrick }
1935d89ec533Spatrick
19363cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_socketpair(int domain,int type,int protocol,int sv[2],dfsan_label domain_label,dfsan_label type_label,dfsan_label protocol_label,dfsan_label sv_label,dfsan_label * ret_label)19373cab2bb3Spatrick __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
19383cab2bb3Spatrick dfsan_label domain_label, dfsan_label type_label,
19393cab2bb3Spatrick dfsan_label protocol_label, dfsan_label sv_label,
19403cab2bb3Spatrick dfsan_label *ret_label) {
19413cab2bb3Spatrick int ret = socketpair(domain, type, protocol, sv);
19423cab2bb3Spatrick *ret_label = 0;
19433cab2bb3Spatrick if (ret == 0) {
19443cab2bb3Spatrick dfsan_set_label(0, sv, sizeof(*sv) * 2);
19453cab2bb3Spatrick }
19463cab2bb3Spatrick return ret;
19473cab2bb3Spatrick }
19483cab2bb3Spatrick
__dfso_socketpair(int domain,int type,int protocol,int sv[2],dfsan_label domain_label,dfsan_label type_label,dfsan_label protocol_label,dfsan_label sv_label,dfsan_label * ret_label,dfsan_origin domain_origin,dfsan_origin type_origin,dfsan_origin protocol_origin,dfsan_origin sv_origin,dfsan_origin * ret_origin)1949d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
1950d89ec533Spatrick int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
1951d89ec533Spatrick dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
1952d89ec533Spatrick dfsan_label *ret_label, dfsan_origin domain_origin,
1953d89ec533Spatrick dfsan_origin type_origin, dfsan_origin protocol_origin,
1954d89ec533Spatrick dfsan_origin sv_origin, dfsan_origin *ret_origin) {
1955d89ec533Spatrick return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
1956d89ec533Spatrick protocol_label, sv_label, ret_label);
1957d89ec533Spatrick }
1958d89ec533Spatrick
__dfsw_getsockopt(int sockfd,int level,int optname,void * optval,socklen_t * optlen,dfsan_label sockfd_label,dfsan_label level_label,dfsan_label optname_label,dfsan_label optval_label,dfsan_label optlen_label,dfsan_label * ret_label)1959d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
1960d89ec533Spatrick int sockfd, int level, int optname, void *optval, socklen_t *optlen,
1961d89ec533Spatrick dfsan_label sockfd_label, dfsan_label level_label,
1962d89ec533Spatrick dfsan_label optname_label, dfsan_label optval_label,
1963d89ec533Spatrick dfsan_label optlen_label, dfsan_label *ret_label) {
1964d89ec533Spatrick int ret = getsockopt(sockfd, level, optname, optval, optlen);
1965d89ec533Spatrick if (ret != -1 && optval && optlen) {
1966d89ec533Spatrick dfsan_set_label(0, optlen, sizeof(*optlen));
1967d89ec533Spatrick dfsan_set_label(0, optval, *optlen);
1968d89ec533Spatrick }
1969d89ec533Spatrick *ret_label = 0;
1970d89ec533Spatrick return ret;
1971d89ec533Spatrick }
1972d89ec533Spatrick
__dfso_getsockopt(int sockfd,int level,int optname,void * optval,socklen_t * optlen,dfsan_label sockfd_label,dfsan_label level_label,dfsan_label optname_label,dfsan_label optval_label,dfsan_label optlen_label,dfsan_label * ret_label,dfsan_origin sockfd_origin,dfsan_origin level_origin,dfsan_origin optname_origin,dfsan_origin optval_origin,dfsan_origin optlen_origin,dfsan_origin * ret_origin)1973d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
1974d89ec533Spatrick int sockfd, int level, int optname, void *optval, socklen_t *optlen,
1975d89ec533Spatrick dfsan_label sockfd_label, dfsan_label level_label,
1976d89ec533Spatrick dfsan_label optname_label, dfsan_label optval_label,
1977d89ec533Spatrick dfsan_label optlen_label, dfsan_label *ret_label,
1978d89ec533Spatrick dfsan_origin sockfd_origin, dfsan_origin level_origin,
1979d89ec533Spatrick dfsan_origin optname_origin, dfsan_origin optval_origin,
1980d89ec533Spatrick dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
1981d89ec533Spatrick return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
1982d89ec533Spatrick level_label, optname_label, optval_label,
1983d89ec533Spatrick optlen_label, ret_label);
1984d89ec533Spatrick }
1985d89ec533Spatrick
__dfsw_getsockname(int sockfd,struct sockaddr * addr,socklen_t * addrlen,dfsan_label sockfd_label,dfsan_label addr_label,dfsan_label addrlen_label,dfsan_label * ret_label)1986d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
1987d89ec533Spatrick int sockfd, struct sockaddr *addr, socklen_t *addrlen,
1988d89ec533Spatrick dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
1989d89ec533Spatrick dfsan_label *ret_label) {
1990d89ec533Spatrick socklen_t origlen = addrlen ? *addrlen : 0;
1991d89ec533Spatrick int ret = getsockname(sockfd, addr, addrlen);
1992d89ec533Spatrick if (ret != -1 && addr && addrlen) {
1993d89ec533Spatrick socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
1994d89ec533Spatrick dfsan_set_label(0, addrlen, sizeof(*addrlen));
1995d89ec533Spatrick dfsan_set_label(0, addr, written_bytes);
1996d89ec533Spatrick }
1997d89ec533Spatrick *ret_label = 0;
1998d89ec533Spatrick return ret;
1999d89ec533Spatrick }
2000d89ec533Spatrick
__dfso_getsockname(int sockfd,struct sockaddr * addr,socklen_t * addrlen,dfsan_label sockfd_label,dfsan_label addr_label,dfsan_label addrlen_label,dfsan_label * ret_label,dfsan_origin sockfd_origin,dfsan_origin addr_origin,dfsan_origin addrlen_origin,dfsan_origin * ret_origin)2001d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
2002d89ec533Spatrick int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2003d89ec533Spatrick dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2004d89ec533Spatrick dfsan_label *ret_label, dfsan_origin sockfd_origin,
2005d89ec533Spatrick dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2006d89ec533Spatrick dfsan_origin *ret_origin) {
2007d89ec533Spatrick return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
2008d89ec533Spatrick addrlen_label, ret_label);
2009d89ec533Spatrick }
2010d89ec533Spatrick
__dfsw_getpeername(int sockfd,struct sockaddr * addr,socklen_t * addrlen,dfsan_label sockfd_label,dfsan_label addr_label,dfsan_label addrlen_label,dfsan_label * ret_label)2011d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
2012d89ec533Spatrick int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2013d89ec533Spatrick dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2014d89ec533Spatrick dfsan_label *ret_label) {
2015d89ec533Spatrick socklen_t origlen = addrlen ? *addrlen : 0;
2016d89ec533Spatrick int ret = getpeername(sockfd, addr, addrlen);
2017d89ec533Spatrick if (ret != -1 && addr && addrlen) {
2018d89ec533Spatrick socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2019d89ec533Spatrick dfsan_set_label(0, addrlen, sizeof(*addrlen));
2020d89ec533Spatrick dfsan_set_label(0, addr, written_bytes);
2021d89ec533Spatrick }
2022d89ec533Spatrick *ret_label = 0;
2023d89ec533Spatrick return ret;
2024d89ec533Spatrick }
2025d89ec533Spatrick
__dfso_getpeername(int sockfd,struct sockaddr * addr,socklen_t * addrlen,dfsan_label sockfd_label,dfsan_label addr_label,dfsan_label addrlen_label,dfsan_label * ret_label,dfsan_origin sockfd_origin,dfsan_origin addr_origin,dfsan_origin addrlen_origin,dfsan_origin * ret_origin)2026d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
2027d89ec533Spatrick int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2028d89ec533Spatrick dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2029d89ec533Spatrick dfsan_label *ret_label, dfsan_origin sockfd_origin,
2030d89ec533Spatrick dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2031d89ec533Spatrick dfsan_origin *ret_origin) {
2032d89ec533Spatrick return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
2033d89ec533Spatrick addrlen_label, ret_label);
2034d89ec533Spatrick }
2035d89ec533Spatrick
2036*810390e3Srobert // Type of the function passed to dfsan_set_write_callback.
2037*810390e3Srobert typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
2038d89ec533Spatrick
20393cab2bb3Spatrick // Calls to dfsan_set_write_callback() set the values in this struct.
20403cab2bb3Spatrick // Calls to the custom version of write() read (and invoke) them.
20413cab2bb3Spatrick static struct {
2042*810390e3Srobert write_dfsan_callback_t write_callback = nullptr;
20433cab2bb3Spatrick } write_callback_info;
20443cab2bb3Spatrick
__dfsw_dfsan_set_write_callback(write_dfsan_callback_t write_callback,dfsan_label write_callback_label,dfsan_label * ret_label)2045*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
2046*810390e3Srobert write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
20473cab2bb3Spatrick dfsan_label *ret_label) {
20483cab2bb3Spatrick write_callback_info.write_callback = write_callback;
20493cab2bb3Spatrick }
20503cab2bb3Spatrick
__dfso_dfsan_set_write_callback(write_dfsan_callback_t write_callback,dfsan_label write_callback_label,dfsan_label * ret_label,dfsan_origin write_callback_origin,dfsan_origin * ret_origin)2051d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
2052*810390e3Srobert write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
2053*810390e3Srobert dfsan_label *ret_label, dfsan_origin write_callback_origin,
2054*810390e3Srobert dfsan_origin *ret_origin) {
2055*810390e3Srobert write_callback_info.write_callback = write_callback;
2056*810390e3Srobert }
2057*810390e3Srobert
setup_tls_args_for_write_callback(dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,bool origins,dfsan_origin fd_origin,dfsan_origin buf_origin,dfsan_origin count_origin)2058*810390e3Srobert static inline void setup_tls_args_for_write_callback(
2059*810390e3Srobert dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
2060*810390e3Srobert bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
2061*810390e3Srobert dfsan_origin count_origin) {
2062*810390e3Srobert // The callback code will expect argument shadow labels in the args TLS,
2063*810390e3Srobert // and origin labels in the origin args TLS.
2064*810390e3Srobert // Previously this was done by a trampoline, but we want to remove this:
2065*810390e3Srobert // https://github.com/llvm/llvm-project/issues/54172
2066*810390e3Srobert //
2067*810390e3Srobert // Instead, this code is manually setting up the args TLS data.
2068*810390e3Srobert //
2069*810390e3Srobert // The offsets used need to correspond with the instrumentation code,
2070*810390e3Srobert // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
2071*810390e3Srobert // DFSanFunction::getShadowForTLSArgument.
2072*810390e3Srobert // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
2073*810390e3Srobert // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
2074*810390e3Srobert //
2075*810390e3Srobert // Here the arguments are all primitives, but it can be more complex
2076*810390e3Srobert // to compute offsets for array/aggregate type arguments.
2077*810390e3Srobert //
2078*810390e3Srobert // TODO(browneee): Consider a builtin to improve maintainabliity.
2079*810390e3Srobert // With a builtin, we would provide the argument labels via builtin,
2080*810390e3Srobert // and the builtin would reuse parts of the instrumentation code to ensure
2081*810390e3Srobert // that this code and the instrumentation can never be out of sync.
2082*810390e3Srobert // Note: Currently DFSan instrumentation does not run on this code, so
2083*810390e3Srobert // the builtin may need to be handled outside DFSan instrumentation.
2084*810390e3Srobert dfsan_set_arg_tls(0, fd_label);
2085*810390e3Srobert dfsan_set_arg_tls(1, buf_label);
2086*810390e3Srobert dfsan_set_arg_tls(2, count_label);
2087*810390e3Srobert if (origins) {
2088*810390e3Srobert dfsan_set_arg_origin_tls(0, fd_origin);
2089*810390e3Srobert dfsan_set_arg_origin_tls(1, buf_origin);
2090*810390e3Srobert dfsan_set_arg_origin_tls(2, count_origin);
2091*810390e3Srobert }
2092d89ec533Spatrick }
2093d89ec533Spatrick
20943cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_write(int fd,const void * buf,size_t count,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label * ret_label)20953cab2bb3Spatrick __dfsw_write(int fd, const void *buf, size_t count,
20963cab2bb3Spatrick dfsan_label fd_label, dfsan_label buf_label,
20973cab2bb3Spatrick dfsan_label count_label, dfsan_label *ret_label) {
20983cab2bb3Spatrick if (write_callback_info.write_callback) {
2099*810390e3Srobert setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
2100*810390e3Srobert 0, 0, 0);
2101*810390e3Srobert write_callback_info.write_callback(fd, buf, count);
21023cab2bb3Spatrick }
21033cab2bb3Spatrick
21043cab2bb3Spatrick *ret_label = 0;
21053cab2bb3Spatrick return write(fd, buf, count);
21063cab2bb3Spatrick }
2107d89ec533Spatrick
__dfso_write(int fd,const void * buf,size_t count,dfsan_label fd_label,dfsan_label buf_label,dfsan_label count_label,dfsan_label * ret_label,dfsan_origin fd_origin,dfsan_origin buf_origin,dfsan_origin count_origin,dfsan_origin * ret_origin)2108d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
2109d89ec533Spatrick int fd, const void *buf, size_t count, dfsan_label fd_label,
2110d89ec533Spatrick dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
2111d89ec533Spatrick dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
2112d89ec533Spatrick dfsan_origin *ret_origin) {
2113*810390e3Srobert if (write_callback_info.write_callback) {
2114*810390e3Srobert setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
2115*810390e3Srobert fd_origin, buf_origin, count_origin);
2116*810390e3Srobert write_callback_info.write_callback(fd, buf, count);
2117d89ec533Spatrick }
2118d89ec533Spatrick
2119d89ec533Spatrick *ret_label = 0;
2120d89ec533Spatrick return write(fd, buf, count);
2121d89ec533Spatrick }
21223cab2bb3Spatrick } // namespace __dfsan
21233cab2bb3Spatrick
21243cab2bb3Spatrick // Type used to extract a dfsan_label with va_arg()
21253cab2bb3Spatrick typedef int dfsan_label_va;
21263cab2bb3Spatrick
21273cab2bb3Spatrick // Formats a chunk either a constant string or a single format directive (e.g.,
21283cab2bb3Spatrick // '%.3f').
21293cab2bb3Spatrick struct Formatter {
FormatterFormatter21303cab2bb3Spatrick Formatter(char *str_, const char *fmt_, size_t size_)
21313cab2bb3Spatrick : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
21323cab2bb3Spatrick width(-1) {}
21333cab2bb3Spatrick
formatFormatter21343cab2bb3Spatrick int format() {
21353cab2bb3Spatrick char *tmp_fmt = build_format_string();
21363cab2bb3Spatrick int retval =
21373cab2bb3Spatrick snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
21383cab2bb3Spatrick 0 /* used only to avoid warnings */);
21393cab2bb3Spatrick free(tmp_fmt);
21403cab2bb3Spatrick return retval;
21413cab2bb3Spatrick }
21423cab2bb3Spatrick
formatFormatter21433cab2bb3Spatrick template <typename T> int format(T arg) {
21443cab2bb3Spatrick char *tmp_fmt = build_format_string();
21453cab2bb3Spatrick int retval;
21463cab2bb3Spatrick if (width >= 0) {
21473cab2bb3Spatrick retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
21483cab2bb3Spatrick tmp_fmt, width, arg);
21493cab2bb3Spatrick } else {
21503cab2bb3Spatrick retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
21513cab2bb3Spatrick tmp_fmt, arg);
21523cab2bb3Spatrick }
21533cab2bb3Spatrick free(tmp_fmt);
21543cab2bb3Spatrick return retval;
21553cab2bb3Spatrick }
21563cab2bb3Spatrick
build_format_stringFormatter21573cab2bb3Spatrick char *build_format_string() {
21583cab2bb3Spatrick size_t fmt_size = fmt_cur - fmt_start + 1;
21593cab2bb3Spatrick char *new_fmt = (char *)malloc(fmt_size + 1);
21603cab2bb3Spatrick assert(new_fmt);
21613cab2bb3Spatrick internal_memcpy(new_fmt, fmt_start, fmt_size);
21623cab2bb3Spatrick new_fmt[fmt_size] = '\0';
21633cab2bb3Spatrick return new_fmt;
21643cab2bb3Spatrick }
21653cab2bb3Spatrick
str_curFormatter21663cab2bb3Spatrick char *str_cur() { return str + str_off; }
21673cab2bb3Spatrick
num_written_bytesFormatter21683cab2bb3Spatrick size_t num_written_bytes(int retval) {
21693cab2bb3Spatrick if (retval < 0) {
21703cab2bb3Spatrick return 0;
21713cab2bb3Spatrick }
21723cab2bb3Spatrick
21733cab2bb3Spatrick size_t num_avail = str_off < size ? size - str_off : 0;
21743cab2bb3Spatrick if (num_avail == 0) {
21753cab2bb3Spatrick return 0;
21763cab2bb3Spatrick }
21773cab2bb3Spatrick
21783cab2bb3Spatrick size_t num_written = retval;
21793cab2bb3Spatrick // A return value of {v,}snprintf of size or more means that the output was
21803cab2bb3Spatrick // truncated.
21813cab2bb3Spatrick if (num_written >= num_avail) {
21823cab2bb3Spatrick num_written -= num_avail;
21833cab2bb3Spatrick }
21843cab2bb3Spatrick
21853cab2bb3Spatrick return num_written;
21863cab2bb3Spatrick }
21873cab2bb3Spatrick
21883cab2bb3Spatrick char *str;
21893cab2bb3Spatrick size_t str_off;
21903cab2bb3Spatrick size_t size;
21913cab2bb3Spatrick const char *fmt_start;
21923cab2bb3Spatrick const char *fmt_cur;
21933cab2bb3Spatrick int width;
21943cab2bb3Spatrick };
21953cab2bb3Spatrick
21963cab2bb3Spatrick // Formats the input and propagates the input labels to the output. The output
21973cab2bb3Spatrick // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
21983cab2bb3Spatrick // 'ap' are the format string and the list of arguments for formatting. Returns
21993cab2bb3Spatrick // the return value vsnprintf would return.
22003cab2bb3Spatrick //
22013cab2bb3Spatrick // The function tokenizes the format string in chunks representing either a
22023cab2bb3Spatrick // constant string or a single format directive (e.g., '%.3f') and formats each
22033cab2bb3Spatrick // chunk independently into the output string. This approach allows to figure
22043cab2bb3Spatrick // out which bytes of the output string depends on which argument and thus to
22053cab2bb3Spatrick // propagate labels more precisely.
22063cab2bb3Spatrick //
22073cab2bb3Spatrick // WARNING: This implementation does not support conversion specifiers with
22083cab2bb3Spatrick // positional arguments.
format_buffer(char * str,size_t size,const char * fmt,dfsan_label * va_labels,dfsan_label * ret_label,dfsan_origin * va_origins,dfsan_origin * ret_origin,va_list ap)22093cab2bb3Spatrick static int format_buffer(char *str, size_t size, const char *fmt,
22103cab2bb3Spatrick dfsan_label *va_labels, dfsan_label *ret_label,
2211d89ec533Spatrick dfsan_origin *va_origins, dfsan_origin *ret_origin,
22123cab2bb3Spatrick va_list ap) {
22133cab2bb3Spatrick Formatter formatter(str, fmt, size);
22143cab2bb3Spatrick
22153cab2bb3Spatrick while (*formatter.fmt_cur) {
22163cab2bb3Spatrick formatter.fmt_start = formatter.fmt_cur;
22173cab2bb3Spatrick formatter.width = -1;
22183cab2bb3Spatrick int retval = 0;
22193cab2bb3Spatrick
22203cab2bb3Spatrick if (*formatter.fmt_cur != '%') {
22213cab2bb3Spatrick // Ordinary character. Consume all the characters until a '%' or the end
22223cab2bb3Spatrick // of the string.
22233cab2bb3Spatrick for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
22243cab2bb3Spatrick ++formatter.fmt_cur) {}
22253cab2bb3Spatrick retval = formatter.format();
22263cab2bb3Spatrick dfsan_set_label(0, formatter.str_cur(),
22273cab2bb3Spatrick formatter.num_written_bytes(retval));
22283cab2bb3Spatrick } else {
22293cab2bb3Spatrick // Conversion directive. Consume all the characters until a conversion
22303cab2bb3Spatrick // specifier or the end of the string.
22313cab2bb3Spatrick bool end_fmt = false;
22323cab2bb3Spatrick for (; *formatter.fmt_cur && !end_fmt; ) {
22333cab2bb3Spatrick switch (*++formatter.fmt_cur) {
22343cab2bb3Spatrick case 'd':
22353cab2bb3Spatrick case 'i':
22363cab2bb3Spatrick case 'o':
22373cab2bb3Spatrick case 'u':
22383cab2bb3Spatrick case 'x':
22393cab2bb3Spatrick case 'X':
22403cab2bb3Spatrick switch (*(formatter.fmt_cur - 1)) {
22413cab2bb3Spatrick case 'h':
22423cab2bb3Spatrick // Also covers the 'hh' case (since the size of the arg is still
22433cab2bb3Spatrick // an int).
22443cab2bb3Spatrick retval = formatter.format(va_arg(ap, int));
22453cab2bb3Spatrick break;
22463cab2bb3Spatrick case 'l':
22473cab2bb3Spatrick if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
22483cab2bb3Spatrick *(formatter.fmt_cur - 2) == 'l') {
22493cab2bb3Spatrick retval = formatter.format(va_arg(ap, long long int));
22503cab2bb3Spatrick } else {
22513cab2bb3Spatrick retval = formatter.format(va_arg(ap, long int));
22523cab2bb3Spatrick }
22533cab2bb3Spatrick break;
22543cab2bb3Spatrick case 'q':
22553cab2bb3Spatrick retval = formatter.format(va_arg(ap, long long int));
22563cab2bb3Spatrick break;
22573cab2bb3Spatrick case 'j':
22583cab2bb3Spatrick retval = formatter.format(va_arg(ap, intmax_t));
22593cab2bb3Spatrick break;
22603cab2bb3Spatrick case 'z':
22613cab2bb3Spatrick case 't':
22623cab2bb3Spatrick retval = formatter.format(va_arg(ap, size_t));
22633cab2bb3Spatrick break;
22643cab2bb3Spatrick default:
22653cab2bb3Spatrick retval = formatter.format(va_arg(ap, int));
22663cab2bb3Spatrick }
2267d89ec533Spatrick if (va_origins == nullptr)
22683cab2bb3Spatrick dfsan_set_label(*va_labels++, formatter.str_cur(),
22693cab2bb3Spatrick formatter.num_written_bytes(retval));
2270d89ec533Spatrick else
2271d89ec533Spatrick dfsan_set_label_origin(*va_labels++, *va_origins++,
2272d89ec533Spatrick formatter.str_cur(),
2273d89ec533Spatrick formatter.num_written_bytes(retval));
22743cab2bb3Spatrick end_fmt = true;
22753cab2bb3Spatrick break;
22763cab2bb3Spatrick
22773cab2bb3Spatrick case 'a':
22783cab2bb3Spatrick case 'A':
22793cab2bb3Spatrick case 'e':
22803cab2bb3Spatrick case 'E':
22813cab2bb3Spatrick case 'f':
22823cab2bb3Spatrick case 'F':
22833cab2bb3Spatrick case 'g':
22843cab2bb3Spatrick case 'G':
22853cab2bb3Spatrick if (*(formatter.fmt_cur - 1) == 'L') {
22863cab2bb3Spatrick retval = formatter.format(va_arg(ap, long double));
22873cab2bb3Spatrick } else {
22883cab2bb3Spatrick retval = formatter.format(va_arg(ap, double));
22893cab2bb3Spatrick }
2290d89ec533Spatrick if (va_origins == nullptr)
22913cab2bb3Spatrick dfsan_set_label(*va_labels++, formatter.str_cur(),
22923cab2bb3Spatrick formatter.num_written_bytes(retval));
2293d89ec533Spatrick else
2294d89ec533Spatrick dfsan_set_label_origin(*va_labels++, *va_origins++,
2295d89ec533Spatrick formatter.str_cur(),
2296d89ec533Spatrick formatter.num_written_bytes(retval));
22973cab2bb3Spatrick end_fmt = true;
22983cab2bb3Spatrick break;
22993cab2bb3Spatrick
23003cab2bb3Spatrick case 'c':
23013cab2bb3Spatrick retval = formatter.format(va_arg(ap, int));
2302d89ec533Spatrick if (va_origins == nullptr)
23033cab2bb3Spatrick dfsan_set_label(*va_labels++, formatter.str_cur(),
23043cab2bb3Spatrick formatter.num_written_bytes(retval));
2305d89ec533Spatrick else
2306d89ec533Spatrick dfsan_set_label_origin(*va_labels++, *va_origins++,
2307d89ec533Spatrick formatter.str_cur(),
2308d89ec533Spatrick formatter.num_written_bytes(retval));
23093cab2bb3Spatrick end_fmt = true;
23103cab2bb3Spatrick break;
23113cab2bb3Spatrick
23123cab2bb3Spatrick case 's': {
23133cab2bb3Spatrick char *arg = va_arg(ap, char *);
23143cab2bb3Spatrick retval = formatter.format(arg);
2315d89ec533Spatrick if (va_origins) {
2316d89ec533Spatrick va_origins++;
2317d89ec533Spatrick dfsan_mem_origin_transfer(formatter.str_cur(), arg,
2318d89ec533Spatrick formatter.num_written_bytes(retval));
2319d89ec533Spatrick }
23203cab2bb3Spatrick va_labels++;
2321*810390e3Srobert dfsan_mem_shadow_transfer(formatter.str_cur(), arg,
23223cab2bb3Spatrick formatter.num_written_bytes(retval));
23233cab2bb3Spatrick end_fmt = true;
23243cab2bb3Spatrick break;
23253cab2bb3Spatrick }
23263cab2bb3Spatrick
23273cab2bb3Spatrick case 'p':
23283cab2bb3Spatrick retval = formatter.format(va_arg(ap, void *));
2329d89ec533Spatrick if (va_origins == nullptr)
23303cab2bb3Spatrick dfsan_set_label(*va_labels++, formatter.str_cur(),
23313cab2bb3Spatrick formatter.num_written_bytes(retval));
2332d89ec533Spatrick else
2333d89ec533Spatrick dfsan_set_label_origin(*va_labels++, *va_origins++,
2334d89ec533Spatrick formatter.str_cur(),
2335d89ec533Spatrick formatter.num_written_bytes(retval));
23363cab2bb3Spatrick end_fmt = true;
23373cab2bb3Spatrick break;
23383cab2bb3Spatrick
23393cab2bb3Spatrick case 'n': {
23403cab2bb3Spatrick int *ptr = va_arg(ap, int *);
23413cab2bb3Spatrick *ptr = (int)formatter.str_off;
23423cab2bb3Spatrick va_labels++;
2343d89ec533Spatrick if (va_origins)
2344d89ec533Spatrick va_origins++;
23453cab2bb3Spatrick dfsan_set_label(0, ptr, sizeof(ptr));
23463cab2bb3Spatrick end_fmt = true;
23473cab2bb3Spatrick break;
23483cab2bb3Spatrick }
23493cab2bb3Spatrick
23503cab2bb3Spatrick case '%':
23513cab2bb3Spatrick retval = formatter.format();
23523cab2bb3Spatrick dfsan_set_label(0, formatter.str_cur(),
23533cab2bb3Spatrick formatter.num_written_bytes(retval));
23543cab2bb3Spatrick end_fmt = true;
23553cab2bb3Spatrick break;
23563cab2bb3Spatrick
23573cab2bb3Spatrick case '*':
23583cab2bb3Spatrick formatter.width = va_arg(ap, int);
23593cab2bb3Spatrick va_labels++;
2360d89ec533Spatrick if (va_origins)
2361d89ec533Spatrick va_origins++;
23623cab2bb3Spatrick break;
23633cab2bb3Spatrick
23643cab2bb3Spatrick default:
23653cab2bb3Spatrick break;
23663cab2bb3Spatrick }
23673cab2bb3Spatrick }
23683cab2bb3Spatrick }
23693cab2bb3Spatrick
23703cab2bb3Spatrick if (retval < 0) {
23713cab2bb3Spatrick return retval;
23723cab2bb3Spatrick }
23733cab2bb3Spatrick
23743cab2bb3Spatrick formatter.fmt_cur++;
23753cab2bb3Spatrick formatter.str_off += retval;
23763cab2bb3Spatrick }
23773cab2bb3Spatrick
23783cab2bb3Spatrick *ret_label = 0;
2379d89ec533Spatrick if (ret_origin)
2380d89ec533Spatrick *ret_origin = 0;
23813cab2bb3Spatrick
23823cab2bb3Spatrick // Number of bytes written in total.
23833cab2bb3Spatrick return formatter.str_off;
23843cab2bb3Spatrick }
23853cab2bb3Spatrick
23863cab2bb3Spatrick extern "C" {
23873cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sprintf(char * str,const char * format,dfsan_label str_label,dfsan_label format_label,dfsan_label * va_labels,dfsan_label * ret_label,...)23883cab2bb3Spatrick int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
23893cab2bb3Spatrick dfsan_label format_label, dfsan_label *va_labels,
23903cab2bb3Spatrick dfsan_label *ret_label, ...) {
23913cab2bb3Spatrick va_list ap;
23923cab2bb3Spatrick va_start(ap, ret_label);
2393d89ec533Spatrick int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
2394d89ec533Spatrick nullptr, ap);
2395d89ec533Spatrick va_end(ap);
2396d89ec533Spatrick return ret;
2397d89ec533Spatrick }
2398d89ec533Spatrick
2399d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sprintf(char * str,const char * format,dfsan_label str_label,dfsan_label format_label,dfsan_label * va_labels,dfsan_label * ret_label,dfsan_origin str_origin,dfsan_origin format_origin,dfsan_origin * va_origins,dfsan_origin * ret_origin,...)2400d89ec533Spatrick int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
2401d89ec533Spatrick dfsan_label format_label, dfsan_label *va_labels,
2402d89ec533Spatrick dfsan_label *ret_label, dfsan_origin str_origin,
2403d89ec533Spatrick dfsan_origin format_origin, dfsan_origin *va_origins,
2404d89ec533Spatrick dfsan_origin *ret_origin, ...) {
2405d89ec533Spatrick va_list ap;
2406d89ec533Spatrick va_start(ap, ret_origin);
2407d89ec533Spatrick int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins,
2408d89ec533Spatrick ret_origin, ap);
24093cab2bb3Spatrick va_end(ap);
24103cab2bb3Spatrick return ret;
24113cab2bb3Spatrick }
24123cab2bb3Spatrick
24133cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_snprintf(char * str,size_t size,const char * format,dfsan_label str_label,dfsan_label size_label,dfsan_label format_label,dfsan_label * va_labels,dfsan_label * ret_label,...)24143cab2bb3Spatrick int __dfsw_snprintf(char *str, size_t size, const char *format,
24153cab2bb3Spatrick dfsan_label str_label, dfsan_label size_label,
24163cab2bb3Spatrick dfsan_label format_label, dfsan_label *va_labels,
24173cab2bb3Spatrick dfsan_label *ret_label, ...) {
24183cab2bb3Spatrick va_list ap;
24193cab2bb3Spatrick va_start(ap, ret_label);
2420d89ec533Spatrick int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
2421d89ec533Spatrick nullptr, ap);
24223cab2bb3Spatrick va_end(ap);
24233cab2bb3Spatrick return ret;
24243cab2bb3Spatrick }
24253cab2bb3Spatrick
2426d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_snprintf(char * str,size_t size,const char * format,dfsan_label str_label,dfsan_label size_label,dfsan_label format_label,dfsan_label * va_labels,dfsan_label * ret_label,dfsan_origin str_origin,dfsan_origin size_origin,dfsan_origin format_origin,dfsan_origin * va_origins,dfsan_origin * ret_origin,...)2427d89ec533Spatrick int __dfso_snprintf(char *str, size_t size, const char *format,
2428d89ec533Spatrick dfsan_label str_label, dfsan_label size_label,
2429d89ec533Spatrick dfsan_label format_label, dfsan_label *va_labels,
2430d89ec533Spatrick dfsan_label *ret_label, dfsan_origin str_origin,
2431d89ec533Spatrick dfsan_origin size_origin, dfsan_origin format_origin,
2432d89ec533Spatrick dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
2433d89ec533Spatrick va_list ap;
2434d89ec533Spatrick va_start(ap, ret_origin);
2435d89ec533Spatrick int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
2436d89ec533Spatrick ret_origin, ap);
2437d89ec533Spatrick va_end(ap);
2438d89ec533Spatrick return ret;
2439d89ec533Spatrick }
2440d89ec533Spatrick
BeforeFork()2441d89ec533Spatrick static void BeforeFork() {
2442d89ec533Spatrick StackDepotLockAll();
2443d89ec533Spatrick GetChainedOriginDepot()->LockAll();
2444d89ec533Spatrick }
2445d89ec533Spatrick
AfterFork()2446d89ec533Spatrick static void AfterFork() {
2447d89ec533Spatrick GetChainedOriginDepot()->UnlockAll();
2448d89ec533Spatrick StackDepotUnlockAll();
2449d89ec533Spatrick }
2450d89ec533Spatrick
2451d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_fork(dfsan_label * ret_label)2452d89ec533Spatrick pid_t __dfsw_fork(dfsan_label *ret_label) {
2453d89ec533Spatrick pid_t pid = fork();
2454d89ec533Spatrick *ret_label = 0;
2455d89ec533Spatrick return pid;
2456d89ec533Spatrick }
2457d89ec533Spatrick
2458d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__dfso_fork(dfsan_label * ret_label,dfsan_origin * ret_origin)2459d89ec533Spatrick pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
2460d89ec533Spatrick BeforeFork();
2461d89ec533Spatrick pid_t pid = __dfsw_fork(ret_label);
2462d89ec533Spatrick AfterFork();
2463d89ec533Spatrick return pid;
2464d89ec533Spatrick }
2465d89ec533Spatrick
24663cab2bb3Spatrick // Default empty implementations (weak). Users should redefine them.
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_guard,u32 *)24673cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_guard_init,u32 *,u32 *)24683cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
24693cab2bb3Spatrick u32 *) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_pcs_init,const uptr * beg,const uptr * end)2470*810390e3Srobert SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,
2471*810390e3Srobert const uptr *end) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_indir,void)24723cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
24733cab2bb3Spatrick
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp,void)24743cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp1,void)24753cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp2,void)24763cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp4,void)24773cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp8,void)24783cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp1,void)24793cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
24803cab2bb3Spatrick void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp2,void)24813cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
24823cab2bb3Spatrick void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp4,void)24833cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
24843cab2bb3Spatrick void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp8,void)24853cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
24863cab2bb3Spatrick void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_switch,void)24873cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
24883cab2bb3Spatrick } // extern "C"
2489