1fe6060f1SDimitry Andric //===-- dfsan_custom.cpp --------------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of DataFlowSanitizer.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // This file defines the custom functions listed in done_abilist.txt.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric
1468d75effSDimitry Andric #include <arpa/inet.h>
1568d75effSDimitry Andric #include <assert.h>
1668d75effSDimitry Andric #include <ctype.h>
1768d75effSDimitry Andric #include <dlfcn.h>
1868d75effSDimitry Andric #include <link.h>
1968d75effSDimitry Andric #include <poll.h>
2068d75effSDimitry Andric #include <pthread.h>
2168d75effSDimitry Andric #include <pwd.h>
2268d75effSDimitry Andric #include <sched.h>
2368d75effSDimitry Andric #include <signal.h>
2468d75effSDimitry Andric #include <stdarg.h>
2568d75effSDimitry Andric #include <stdint.h>
2668d75effSDimitry Andric #include <stdio.h>
2768d75effSDimitry Andric #include <stdlib.h>
2868d75effSDimitry Andric #include <string.h>
29e8d8bef9SDimitry Andric #include <sys/epoll.h>
3068d75effSDimitry Andric #include <sys/resource.h>
3168d75effSDimitry Andric #include <sys/select.h>
32e8d8bef9SDimitry Andric #include <sys/socket.h>
3368d75effSDimitry Andric #include <sys/stat.h>
3468d75effSDimitry Andric #include <sys/time.h>
3568d75effSDimitry Andric #include <sys/types.h>
3668d75effSDimitry Andric #include <time.h>
3768d75effSDimitry Andric #include <unistd.h>
3868d75effSDimitry Andric
39e8d8bef9SDimitry Andric #include "dfsan/dfsan.h"
40fe6060f1SDimitry Andric #include "dfsan/dfsan_chained_origin_depot.h"
41fe6060f1SDimitry Andric #include "dfsan/dfsan_flags.h"
42fe6060f1SDimitry Andric #include "dfsan/dfsan_thread.h"
43e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_common.h"
44e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h"
45e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_linux.h"
46fe6060f1SDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h"
47e8d8bef9SDimitry Andric
4868d75effSDimitry Andric using namespace __dfsan;
4968d75effSDimitry Andric
5068d75effSDimitry Andric #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \
5168d75effSDimitry Andric do { \
5268d75effSDimitry Andric if (f) \
5368d75effSDimitry Andric f(__VA_ARGS__); \
5468d75effSDimitry Andric } while (false)
5568d75effSDimitry Andric #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
5668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
5768d75effSDimitry Andric
5874626c16SDimitry Andric #define WRAPPER_ALIAS(fun, real) \
5974626c16SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \
6074626c16SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);
6174626c16SDimitry Andric
62fe6060f1SDimitry Andric // Async-safe, non-reentrant spin lock.
63fe6060f1SDimitry Andric class SignalSpinLocker {
64fe6060f1SDimitry Andric public:
SignalSpinLocker()65fe6060f1SDimitry Andric SignalSpinLocker() {
66fe6060f1SDimitry Andric sigset_t all_set;
67fe6060f1SDimitry Andric sigfillset(&all_set);
68fe6060f1SDimitry Andric pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
69fe6060f1SDimitry Andric sigactions_mu.Lock();
70fe6060f1SDimitry Andric }
~SignalSpinLocker()71fe6060f1SDimitry Andric ~SignalSpinLocker() {
72fe6060f1SDimitry Andric sigactions_mu.Unlock();
73fe6060f1SDimitry Andric pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
74fe6060f1SDimitry Andric }
75fe6060f1SDimitry Andric
76fe6060f1SDimitry Andric private:
77fe6060f1SDimitry Andric static StaticSpinMutex sigactions_mu;
78fe6060f1SDimitry Andric sigset_t saved_thread_mask_;
79fe6060f1SDimitry Andric
80fe6060f1SDimitry Andric SignalSpinLocker(const SignalSpinLocker &) = delete;
81fe6060f1SDimitry Andric SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
82fe6060f1SDimitry Andric };
83fe6060f1SDimitry Andric
84fe6060f1SDimitry Andric StaticSpinMutex SignalSpinLocker::sigactions_mu;
85fe6060f1SDimitry Andric
8668d75effSDimitry Andric extern "C" {
8768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_stat(const char * path,struct stat * buf,dfsan_label path_label,dfsan_label buf_label,dfsan_label * ret_label)8868d75effSDimitry Andric __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
8968d75effSDimitry Andric dfsan_label buf_label, dfsan_label *ret_label) {
9068d75effSDimitry Andric int ret = stat(path, buf);
9168d75effSDimitry Andric if (ret == 0)
9268d75effSDimitry Andric dfsan_set_label(0, buf, sizeof(struct stat));
9368d75effSDimitry Andric *ret_label = 0;
9468d75effSDimitry Andric return ret;
9568d75effSDimitry Andric }
9668d75effSDimitry Andric
__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)97fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
98fe6060f1SDimitry Andric const char *path, struct stat *buf, dfsan_label path_label,
99fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
100fe6060f1SDimitry Andric dfsan_origin buf_origin, dfsan_origin *ret_origin) {
101fe6060f1SDimitry Andric int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
102fe6060f1SDimitry Andric return ret;
103fe6060f1SDimitry Andric }
104fe6060f1SDimitry Andric
__dfsw_fstat(int fd,struct stat * buf,dfsan_label fd_label,dfsan_label buf_label,dfsan_label * ret_label)10568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
10668d75effSDimitry Andric dfsan_label fd_label,
10768d75effSDimitry Andric dfsan_label buf_label,
10868d75effSDimitry Andric dfsan_label *ret_label) {
10968d75effSDimitry Andric int ret = fstat(fd, buf);
11068d75effSDimitry Andric if (ret == 0)
11168d75effSDimitry Andric dfsan_set_label(0, buf, sizeof(struct stat));
11268d75effSDimitry Andric *ret_label = 0;
11368d75effSDimitry Andric return ret;
11468d75effSDimitry Andric }
11568d75effSDimitry Andric
__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)116fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
117fe6060f1SDimitry Andric int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
118fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
119fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
120fe6060f1SDimitry Andric int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
121fe6060f1SDimitry Andric return ret;
122fe6060f1SDimitry Andric }
123fe6060f1SDimitry Andric
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)124fe6060f1SDimitry Andric static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
125fe6060f1SDimitry Andric dfsan_label s_label, dfsan_label c_label,
126fe6060f1SDimitry Andric dfsan_label *ret_label) {
127fe6060f1SDimitry Andric char *match_pos = nullptr;
128fe6060f1SDimitry Andric for (size_t i = 0;; ++i) {
129fe6060f1SDimitry Andric if (s[i] == c || s[i] == 0) {
130fe6060f1SDimitry Andric // If s[i] is the \0 at the end of the string, and \0 is not the
131fe6060f1SDimitry Andric // character we are searching for, then return null.
132fe6060f1SDimitry Andric *bytes_read = i + 1;
133fe6060f1SDimitry Andric match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
134fe6060f1SDimitry Andric break;
135fe6060f1SDimitry Andric }
136fe6060f1SDimitry Andric }
137fe6060f1SDimitry Andric if (flags().strict_data_dependencies)
138fe6060f1SDimitry Andric *ret_label = s_label;
139fe6060f1SDimitry Andric else
140fe6060f1SDimitry Andric *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
141fe6060f1SDimitry Andric dfsan_union(s_label, c_label));
142fe6060f1SDimitry Andric return match_pos;
143fe6060f1SDimitry Andric }
144fe6060f1SDimitry Andric
__dfsw_strchr(const char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label)14568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
14668d75effSDimitry Andric dfsan_label s_label,
14768d75effSDimitry Andric dfsan_label c_label,
14868d75effSDimitry Andric dfsan_label *ret_label) {
149fe6060f1SDimitry Andric size_t bytes_read;
150fe6060f1SDimitry Andric return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
151fe6060f1SDimitry Andric ret_label);
15268d75effSDimitry Andric }
1535ffd83dbSDimitry Andric
__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)154fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
155fe6060f1SDimitry Andric const char *s, int c, dfsan_label s_label, dfsan_label c_label,
156fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
157fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
158fe6060f1SDimitry Andric size_t bytes_read;
159fe6060f1SDimitry Andric char *r =
160fe6060f1SDimitry Andric dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
161fe6060f1SDimitry Andric if (flags().strict_data_dependencies) {
162fe6060f1SDimitry Andric *ret_origin = s_origin;
163fe6060f1SDimitry Andric } else if (*ret_label) {
164fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
165fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1665ffd83dbSDimitry Andric }
167fe6060f1SDimitry Andric return r;
16868d75effSDimitry Andric }
16968d75effSDimitry Andric
__dfsw_strpbrk(const char * s,const char * accept,dfsan_label s_label,dfsan_label accept_label,dfsan_label * ret_label)170e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
171e8d8bef9SDimitry Andric const char *accept,
172e8d8bef9SDimitry Andric dfsan_label s_label,
173e8d8bef9SDimitry Andric dfsan_label accept_label,
17468d75effSDimitry Andric dfsan_label *ret_label) {
175e8d8bef9SDimitry Andric const char *ret = strpbrk(s, accept);
176e8d8bef9SDimitry Andric if (flags().strict_data_dependencies) {
177e8d8bef9SDimitry Andric *ret_label = ret ? s_label : 0;
178e8d8bef9SDimitry Andric } else {
179e8d8bef9SDimitry Andric size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
180e8d8bef9SDimitry Andric *ret_label =
181e8d8bef9SDimitry Andric dfsan_union(dfsan_read_label(s, s_bytes_read),
182e8d8bef9SDimitry Andric dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
183e8d8bef9SDimitry Andric dfsan_union(s_label, accept_label)));
184e8d8bef9SDimitry Andric }
185e8d8bef9SDimitry Andric return const_cast<char *>(ret);
186e8d8bef9SDimitry Andric }
187e8d8bef9SDimitry Andric
__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)188fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
189fe6060f1SDimitry Andric const char *s, const char *accept, dfsan_label s_label,
190fe6060f1SDimitry Andric dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
191fe6060f1SDimitry Andric dfsan_origin accept_origin, dfsan_origin *ret_origin) {
192fe6060f1SDimitry Andric const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
193fe6060f1SDimitry Andric if (flags().strict_data_dependencies) {
194fe6060f1SDimitry Andric if (ret)
195fe6060f1SDimitry Andric *ret_origin = s_origin;
196fe6060f1SDimitry Andric } else {
197fe6060f1SDimitry Andric if (*ret_label) {
198fe6060f1SDimitry Andric size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
199fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
200fe6060f1SDimitry Andric if (o) {
201fe6060f1SDimitry Andric *ret_origin = o;
202fe6060f1SDimitry Andric } else {
203fe6060f1SDimitry Andric o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
204fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
205fe6060f1SDimitry Andric }
206fe6060f1SDimitry Andric }
207fe6060f1SDimitry Andric }
208fe6060f1SDimitry Andric return const_cast<char *>(ret);
209fe6060f1SDimitry Andric }
210fe6060f1SDimitry Andric
__dfsw_strsep(char ** s,const char * delim,dfsan_label s_label,dfsan_label delim_label,dfsan_label * ret_label)21106c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim,
21206c3fb27SDimitry Andric dfsan_label s_label,
21306c3fb27SDimitry Andric dfsan_label delim_label,
21406c3fb27SDimitry Andric dfsan_label *ret_label) {
21506c3fb27SDimitry Andric dfsan_label base_label = dfsan_read_label(s, sizeof(*s));
21606c3fb27SDimitry Andric char *base = *s;
21706c3fb27SDimitry Andric char *res = strsep(s, delim);
21806c3fb27SDimitry Andric if (res != *s) {
21906c3fb27SDimitry Andric char *token_start = res;
22006c3fb27SDimitry Andric int token_length = strlen(res);
22106c3fb27SDimitry Andric // the delimiter byte has been set to NULL
22206c3fb27SDimitry Andric dfsan_set_label(0, token_start + token_length, 1);
22306c3fb27SDimitry Andric }
22406c3fb27SDimitry Andric
22506c3fb27SDimitry Andric if (flags().strict_data_dependencies) {
22606c3fb27SDimitry Andric *ret_label = res ? base_label : 0;
22706c3fb27SDimitry Andric } else {
22806c3fb27SDimitry Andric size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;
22906c3fb27SDimitry Andric *ret_label = dfsan_union(
23006c3fb27SDimitry Andric dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))),
23106c3fb27SDimitry Andric dfsan_union(dfsan_read_label(delim, strlen(delim) + 1),
23206c3fb27SDimitry Andric dfsan_union(s_label, delim_label)));
23306c3fb27SDimitry Andric }
23406c3fb27SDimitry Andric
23506c3fb27SDimitry Andric return res;
23606c3fb27SDimitry Andric }
23706c3fb27SDimitry Andric
__dfso_strsep(char ** s,const char * delim,dfsan_label s_label,dfsan_label delim_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin delim_origin,dfsan_origin * ret_origin)23806c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep(
23906c3fb27SDimitry Andric char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label,
24006c3fb27SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin,
24106c3fb27SDimitry Andric dfsan_origin *ret_origin) {
24206c3fb27SDimitry Andric dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s));
24306c3fb27SDimitry Andric char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label);
24406c3fb27SDimitry Andric if (flags().strict_data_dependencies) {
24506c3fb27SDimitry Andric if (res)
24606c3fb27SDimitry Andric *ret_origin = base_origin;
24706c3fb27SDimitry Andric } else {
24806c3fb27SDimitry Andric if (*ret_label) {
24906c3fb27SDimitry Andric if (base_origin) {
25006c3fb27SDimitry Andric *ret_origin = base_origin;
25106c3fb27SDimitry Andric } else {
25206c3fb27SDimitry Andric dfsan_origin o =
25306c3fb27SDimitry Andric dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1);
25406c3fb27SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : delim_origin);
25506c3fb27SDimitry Andric }
25606c3fb27SDimitry Andric }
25706c3fb27SDimitry Andric }
25806c3fb27SDimitry Andric
25906c3fb27SDimitry Andric return res;
26006c3fb27SDimitry Andric }
26106c3fb27SDimitry Andric
dfsan_memcmp_bcmp(const void * s1,const void * s2,size_t n,size_t * bytes_read)262e8d8bef9SDimitry Andric static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
263fe6060f1SDimitry Andric size_t *bytes_read) {
26468d75effSDimitry Andric const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
26568d75effSDimitry Andric for (size_t i = 0; i != n; ++i) {
26668d75effSDimitry Andric if (cs1[i] != cs2[i]) {
267fe6060f1SDimitry Andric *bytes_read = i + 1;
26868d75effSDimitry Andric return cs1[i] - cs2[i];
26968d75effSDimitry Andric }
27068d75effSDimitry Andric }
271fe6060f1SDimitry Andric *bytes_read = n;
27268d75effSDimitry Andric return 0;
27368d75effSDimitry Andric }
27468d75effSDimitry Andric
dfsan_get_memcmp_label(const void * s1,const void * s2,size_t pos)275fe6060f1SDimitry Andric static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
276fe6060f1SDimitry Andric size_t pos) {
277fe6060f1SDimitry Andric if (flags().strict_data_dependencies)
278fe6060f1SDimitry Andric return 0;
279fe6060f1SDimitry Andric return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
280fe6060f1SDimitry Andric }
281fe6060f1SDimitry Andric
dfsan_get_memcmp_origin(const void * s1,const void * s2,size_t pos,dfsan_label * ret_label,dfsan_origin * ret_origin)282fe6060f1SDimitry Andric static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
283fe6060f1SDimitry Andric dfsan_label *ret_label,
284fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
285fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
286fe6060f1SDimitry Andric if (*ret_label == 0)
287fe6060f1SDimitry Andric return;
288fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
289fe6060f1SDimitry Andric *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
290fe6060f1SDimitry Andric }
291fe6060f1SDimitry Andric
dfsan_memcmp_bcmp_label(const void * s1,const void * s2,size_t n,dfsan_label * ret_label)292fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
293fe6060f1SDimitry Andric dfsan_label *ret_label) {
294fe6060f1SDimitry Andric size_t bytes_read;
295fe6060f1SDimitry Andric int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
296fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
297fe6060f1SDimitry Andric return r;
298fe6060f1SDimitry Andric }
299fe6060f1SDimitry Andric
dfsan_memcmp_bcmp_origin(const void * s1,const void * s2,size_t n,dfsan_label * ret_label,dfsan_origin * ret_origin)300fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
301fe6060f1SDimitry Andric dfsan_label *ret_label,
302fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
303fe6060f1SDimitry Andric size_t bytes_read;
304fe6060f1SDimitry Andric int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
305fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
306fe6060f1SDimitry Andric return r;
307fe6060f1SDimitry Andric }
308fe6060f1SDimitry Andric
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)309e8d8bef9SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
310e8d8bef9SDimitry Andric const void *s1, const void *s2, size_t n,
311e8d8bef9SDimitry Andric dfsan_label s1_label, dfsan_label s2_label,
312e8d8bef9SDimitry Andric dfsan_label n_label)
313e8d8bef9SDimitry Andric
314fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
315fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n,
316fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label,
317fe6060f1SDimitry Andric dfsan_label n_label, dfsan_origin s1_origin,
318fe6060f1SDimitry Andric dfsan_origin s2_origin, dfsan_origin n_origin)
319fe6060f1SDimitry Andric
320e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
321e8d8bef9SDimitry Andric size_t n, dfsan_label s1_label,
322e8d8bef9SDimitry Andric dfsan_label s2_label,
323e8d8bef9SDimitry Andric dfsan_label n_label,
324e8d8bef9SDimitry Andric dfsan_label *ret_label) {
325e8d8bef9SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
326e8d8bef9SDimitry Andric s1_label, s2_label, n_label);
327fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
328fe6060f1SDimitry Andric }
329fe6060f1SDimitry Andric
__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)330fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
331fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n, dfsan_label s1_label,
332fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
333fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
334fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
335fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
336fe6060f1SDimitry Andric s2, n, s1_label, s2_label, n_label, s1_origin,
337fe6060f1SDimitry Andric s2_origin, n_origin);
338fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
339e8d8bef9SDimitry Andric }
340e8d8bef9SDimitry Andric
__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)341e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
342e8d8bef9SDimitry Andric size_t n, dfsan_label s1_label,
343e8d8bef9SDimitry Andric dfsan_label s2_label,
344e8d8bef9SDimitry Andric dfsan_label n_label,
345e8d8bef9SDimitry Andric dfsan_label *ret_label) {
346fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
347fe6060f1SDimitry Andric }
348fe6060f1SDimitry Andric
__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)349fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
350fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n, dfsan_label s1_label,
351fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
352fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
353fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
354fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
355fe6060f1SDimitry Andric }
356fe6060f1SDimitry Andric
357fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit.
358fe6060f1SDimitry Andric // 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)359fe6060f1SDimitry Andric static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
360fe6060f1SDimitry Andric size_t *bytes_read) {
361fe6060f1SDimitry Andric for (size_t i = 0;; ++i) {
362fe6060f1SDimitry Andric if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
363fe6060f1SDimitry Andric *bytes_read = i + 1;
364fe6060f1SDimitry Andric return s1[i] - s2[i];
365fe6060f1SDimitry Andric }
366fe6060f1SDimitry Andric }
367e8d8bef9SDimitry Andric }
368e8d8bef9SDimitry Andric
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)36968d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
37068d75effSDimitry Andric const char *s1, const char *s2,
37168d75effSDimitry Andric dfsan_label s1_label, dfsan_label s2_label)
37268d75effSDimitry Andric
373fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
374fe6060f1SDimitry Andric const char *s1, const char *s2,
375fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label,
376fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin)
377fe6060f1SDimitry Andric
37868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
37968d75effSDimitry Andric dfsan_label s1_label,
38068d75effSDimitry Andric dfsan_label s2_label,
38168d75effSDimitry Andric dfsan_label *ret_label) {
38268d75effSDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
38368d75effSDimitry Andric s1_label, s2_label);
384fe6060f1SDimitry Andric size_t bytes_read;
385fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
386fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
387fe6060f1SDimitry Andric return r;
38868d75effSDimitry Andric }
38968d75effSDimitry Andric
__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)390fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
391fe6060f1SDimitry Andric const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
392fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
393fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
394fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
395fe6060f1SDimitry Andric s2, s1_label, s2_label, s1_origin, s2_origin);
396fe6060f1SDimitry Andric size_t bytes_read;
397fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
398fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
399fe6060f1SDimitry Andric return r;
400fe6060f1SDimitry Andric }
401fe6060f1SDimitry Andric
402fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit.
403fe6060f1SDimitry Andric // 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)404fe6060f1SDimitry Andric static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
405fe6060f1SDimitry Andric size_t *bytes_read) {
40668d75effSDimitry Andric for (size_t i = 0;; ++i) {
4075ffd83dbSDimitry Andric char s1_lower = tolower(s1[i]);
4085ffd83dbSDimitry Andric char s2_lower = tolower(s2[i]);
4095ffd83dbSDimitry Andric
410fe6060f1SDimitry Andric if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
411fe6060f1SDimitry Andric (n > 0 && i == n - 1)) {
412fe6060f1SDimitry Andric *bytes_read = i + 1;
4135ffd83dbSDimitry Andric return s1_lower - s2_lower;
41468d75effSDimitry Andric }
41568d75effSDimitry Andric }
416fe6060f1SDimitry Andric }
417fe6060f1SDimitry Andric
__dfsw_strcasecmp(const char * s1,const char * s2,dfsan_label s1_label,dfsan_label s2_label,dfsan_label * ret_label)418fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
419fe6060f1SDimitry Andric const char *s2,
420fe6060f1SDimitry Andric dfsan_label s1_label,
421fe6060f1SDimitry Andric dfsan_label s2_label,
422fe6060f1SDimitry Andric dfsan_label *ret_label) {
423fe6060f1SDimitry Andric size_t bytes_read;
424fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
425fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
426fe6060f1SDimitry Andric return r;
427fe6060f1SDimitry Andric }
428fe6060f1SDimitry Andric
__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)429fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
430fe6060f1SDimitry Andric const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
431fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
432fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
433fe6060f1SDimitry Andric size_t bytes_read;
434fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
435fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
436fe6060f1SDimitry Andric return r;
43768d75effSDimitry Andric }
43868d75effSDimitry Andric
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)43968d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
44068d75effSDimitry Andric const char *s1, const char *s2, size_t n,
44168d75effSDimitry Andric dfsan_label s1_label, dfsan_label s2_label,
44268d75effSDimitry Andric dfsan_label n_label)
44368d75effSDimitry Andric
444fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
445fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n,
446fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label,
447fe6060f1SDimitry Andric dfsan_label n_label, dfsan_origin s1_origin,
448fe6060f1SDimitry Andric dfsan_origin s2_origin, dfsan_origin n_origin)
449fe6060f1SDimitry Andric
45068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
45168d75effSDimitry Andric size_t n, dfsan_label s1_label,
45268d75effSDimitry Andric dfsan_label s2_label,
45368d75effSDimitry Andric dfsan_label n_label,
45468d75effSDimitry Andric dfsan_label *ret_label) {
45568d75effSDimitry Andric if (n == 0) {
45668d75effSDimitry Andric *ret_label = 0;
45768d75effSDimitry Andric return 0;
45868d75effSDimitry Andric }
45968d75effSDimitry Andric
46068d75effSDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
46168d75effSDimitry Andric n, s1_label, s2_label, n_label);
46268d75effSDimitry Andric
463fe6060f1SDimitry Andric size_t bytes_read;
464fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, n, &bytes_read);
465fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
466fe6060f1SDimitry Andric return r;
46768d75effSDimitry Andric }
46868d75effSDimitry Andric
__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)469fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
470fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label,
471fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
472fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
473fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
47468d75effSDimitry Andric if (n == 0) {
47568d75effSDimitry Andric *ret_label = 0;
47668d75effSDimitry Andric return 0;
47768d75effSDimitry Andric }
47868d75effSDimitry Andric
479fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
480fe6060f1SDimitry Andric s1, s2, n, s1_label, s2_label, n_label, s1_origin,
481fe6060f1SDimitry Andric s2_origin, n_origin);
4825ffd83dbSDimitry Andric
483fe6060f1SDimitry Andric size_t bytes_read;
484fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, n, &bytes_read);
485fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
486fe6060f1SDimitry Andric return r;
487fe6060f1SDimitry Andric }
488fe6060f1SDimitry Andric
__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)489fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
490fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label,
491fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
492fe6060f1SDimitry Andric if (n == 0) {
49368d75effSDimitry Andric *ret_label = 0;
49468d75effSDimitry Andric return 0;
49568d75effSDimitry Andric }
49668d75effSDimitry Andric
497fe6060f1SDimitry Andric size_t bytes_read;
498fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
499fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
500fe6060f1SDimitry Andric return r;
50168d75effSDimitry Andric }
50268d75effSDimitry Andric
__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)503fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
504fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label,
505fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
506fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
507fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
508fe6060f1SDimitry Andric if (n == 0) {
509fe6060f1SDimitry Andric *ret_label = 0;
510fe6060f1SDimitry Andric return 0;
511fe6060f1SDimitry Andric }
512fe6060f1SDimitry Andric
513fe6060f1SDimitry Andric size_t bytes_read;
514fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
515fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
516fe6060f1SDimitry Andric return r;
517fe6060f1SDimitry Andric }
518fe6060f1SDimitry Andric
519fe6060f1SDimitry Andric
52068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t
__dfsw_strlen(const char * s,dfsan_label s_label,dfsan_label * ret_label)52168d75effSDimitry Andric __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
52268d75effSDimitry Andric size_t ret = strlen(s);
52368d75effSDimitry Andric if (flags().strict_data_dependencies) {
52468d75effSDimitry Andric *ret_label = 0;
52568d75effSDimitry Andric } else {
52668d75effSDimitry Andric *ret_label = dfsan_read_label(s, ret + 1);
52768d75effSDimitry Andric }
52868d75effSDimitry Andric return ret;
52968d75effSDimitry Andric }
53068d75effSDimitry Andric
__dfso_strlen(const char * s,dfsan_label s_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin * ret_origin)531fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
532fe6060f1SDimitry Andric dfsan_label s_label,
533fe6060f1SDimitry Andric dfsan_label *ret_label,
534fe6060f1SDimitry Andric dfsan_origin s_origin,
535fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
536fe6060f1SDimitry Andric size_t ret = __dfsw_strlen(s, s_label, ret_label);
537fe6060f1SDimitry Andric if (!flags().strict_data_dependencies)
538fe6060f1SDimitry Andric *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
539fe6060f1SDimitry Andric return ret;
540fe6060f1SDimitry Andric }
541fe6060f1SDimitry Andric
__dfsw_strnlen(const char * s,size_t maxlen,dfsan_label s_label,dfsan_label maxlen_label,dfsan_label * ret_label)54206c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s,
54306c3fb27SDimitry Andric size_t maxlen,
54406c3fb27SDimitry Andric dfsan_label s_label,
54506c3fb27SDimitry Andric dfsan_label maxlen_label,
54606c3fb27SDimitry Andric dfsan_label *ret_label) {
54706c3fb27SDimitry Andric size_t ret = strnlen(s, maxlen);
54806c3fb27SDimitry Andric if (flags().strict_data_dependencies) {
54906c3fb27SDimitry Andric *ret_label = 0;
55006c3fb27SDimitry Andric } else {
55106c3fb27SDimitry Andric size_t full_len = strlen(s);
55206c3fb27SDimitry Andric size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;
55306c3fb27SDimitry Andric *ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len));
55406c3fb27SDimitry Andric }
55506c3fb27SDimitry Andric return ret;
55606c3fb27SDimitry Andric }
55706c3fb27SDimitry Andric
__dfso_strnlen(const char * s,size_t maxlen,dfsan_label s_label,dfsan_label maxlen_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin maxlen_origin,dfsan_origin * ret_origin)55806c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen(
55906c3fb27SDimitry Andric const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label,
56006c3fb27SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin,
56106c3fb27SDimitry Andric dfsan_origin *ret_origin) {
56206c3fb27SDimitry Andric size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label);
56306c3fb27SDimitry Andric if (!flags().strict_data_dependencies) {
56406c3fb27SDimitry Andric size_t full_len = strlen(s);
56506c3fb27SDimitry Andric size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;
56606c3fb27SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len);
56706c3fb27SDimitry Andric *ret_origin = o ? o : maxlen_origin;
56806c3fb27SDimitry Andric }
56906c3fb27SDimitry Andric return ret;
57006c3fb27SDimitry Andric }
57106c3fb27SDimitry Andric
dfsan_memmove(void * dest,const void * src,size_t n)572fe6060f1SDimitry Andric static void *dfsan_memmove(void *dest, const void *src, size_t n) {
573fe6060f1SDimitry Andric dfsan_label *sdest = shadow_for(dest);
574fe6060f1SDimitry Andric const dfsan_label *ssrc = shadow_for(src);
575fe6060f1SDimitry Andric internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
576fe6060f1SDimitry Andric return internal_memmove(dest, src, n);
577fe6060f1SDimitry Andric }
578fe6060f1SDimitry Andric
dfsan_memmove_with_origin(void * dest,const void * src,size_t n)579fe6060f1SDimitry Andric static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
580fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, n);
581fe6060f1SDimitry Andric return dfsan_memmove(dest, src, n);
582fe6060f1SDimitry Andric }
58368d75effSDimitry Andric
dfsan_memcpy(void * dest,const void * src,size_t n)58468d75effSDimitry Andric static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
58504eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, n);
58668d75effSDimitry Andric return internal_memcpy(dest, src, n);
58768d75effSDimitry Andric }
58868d75effSDimitry Andric
dfsan_memcpy_with_origin(void * dest,const void * src,size_t n)589fe6060f1SDimitry Andric static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
590fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, n);
591fe6060f1SDimitry Andric return dfsan_memcpy(dest, src, n);
592fe6060f1SDimitry Andric }
593fe6060f1SDimitry Andric
dfsan_memset(void * s,int c,dfsan_label c_label,size_t n)59468d75effSDimitry Andric static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
59568d75effSDimitry Andric internal_memset(s, c, n);
59668d75effSDimitry Andric dfsan_set_label(c_label, s, n);
59768d75effSDimitry Andric }
59868d75effSDimitry Andric
dfsan_memset_with_origin(void * s,int c,dfsan_label c_label,dfsan_origin c_origin,size_t n)599fe6060f1SDimitry Andric static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
600fe6060f1SDimitry Andric dfsan_origin c_origin, size_t n) {
601fe6060f1SDimitry Andric internal_memset(s, c, n);
602fe6060f1SDimitry Andric dfsan_set_label_origin(c_label, c_origin, s, n);
603fe6060f1SDimitry Andric }
604fe6060f1SDimitry Andric
60568d75effSDimitry Andric 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)60668d75effSDimitry Andric void *__dfsw_memcpy(void *dest, const void *src, size_t n,
60768d75effSDimitry Andric dfsan_label dest_label, dfsan_label src_label,
60868d75effSDimitry Andric dfsan_label n_label, dfsan_label *ret_label) {
60968d75effSDimitry Andric *ret_label = dest_label;
61068d75effSDimitry Andric return dfsan_memcpy(dest, src, n);
61168d75effSDimitry Andric }
61268d75effSDimitry Andric
61368d75effSDimitry Andric 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)614fe6060f1SDimitry Andric void *__dfso_memcpy(void *dest, const void *src, size_t n,
615fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label,
616fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label,
617fe6060f1SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin,
618fe6060f1SDimitry Andric dfsan_origin n_origin, dfsan_origin *ret_origin) {
619fe6060f1SDimitry Andric *ret_label = dest_label;
620fe6060f1SDimitry Andric *ret_origin = dest_origin;
621fe6060f1SDimitry Andric return dfsan_memcpy_with_origin(dest, src, n);
622fe6060f1SDimitry Andric }
623fe6060f1SDimitry Andric
624fe6060f1SDimitry Andric 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)625fe6060f1SDimitry Andric void *__dfsw_memmove(void *dest, const void *src, size_t n,
626fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label,
627fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label) {
628fe6060f1SDimitry Andric *ret_label = dest_label;
629fe6060f1SDimitry Andric return dfsan_memmove(dest, src, n);
630fe6060f1SDimitry Andric }
631fe6060f1SDimitry Andric
632fe6060f1SDimitry Andric 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)633fe6060f1SDimitry Andric void *__dfso_memmove(void *dest, const void *src, size_t n,
634fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label,
635fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label,
636fe6060f1SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin,
637fe6060f1SDimitry Andric dfsan_origin n_origin, dfsan_origin *ret_origin) {
638fe6060f1SDimitry Andric *ret_label = dest_label;
639fe6060f1SDimitry Andric *ret_origin = dest_origin;
640fe6060f1SDimitry Andric return dfsan_memmove_with_origin(dest, src, n);
641fe6060f1SDimitry Andric }
642fe6060f1SDimitry Andric
643fe6060f1SDimitry Andric 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)64468d75effSDimitry Andric void *__dfsw_memset(void *s, int c, size_t n,
64568d75effSDimitry Andric dfsan_label s_label, dfsan_label c_label,
64668d75effSDimitry Andric dfsan_label n_label, dfsan_label *ret_label) {
64768d75effSDimitry Andric dfsan_memset(s, c, c_label, n);
64868d75effSDimitry Andric *ret_label = s_label;
64968d75effSDimitry Andric return s;
65068d75effSDimitry Andric }
65168d75effSDimitry Andric
652fe6060f1SDimitry Andric 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)653fe6060f1SDimitry Andric void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
654fe6060f1SDimitry Andric dfsan_label c_label, dfsan_label n_label,
655fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin,
656fe6060f1SDimitry Andric dfsan_origin c_origin, dfsan_origin n_origin,
657fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
658fe6060f1SDimitry Andric dfsan_memset_with_origin(s, c, c_label, c_origin, n);
659fe6060f1SDimitry Andric *ret_label = s_label;
660fe6060f1SDimitry Andric *ret_origin = s_origin;
661fe6060f1SDimitry Andric return s;
662fe6060f1SDimitry Andric }
663fe6060f1SDimitry Andric
__dfsw_strcat(char * dest,const char * src,dfsan_label dest_label,dfsan_label src_label,dfsan_label * ret_label)664fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
665fe6060f1SDimitry Andric dfsan_label dest_label,
666fe6060f1SDimitry Andric dfsan_label src_label,
667fe6060f1SDimitry Andric dfsan_label *ret_label) {
668fe6060f1SDimitry Andric size_t dest_len = strlen(dest);
669349cc55cSDimitry Andric char *ret = strcat(dest, src);
67004eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));
671fe6060f1SDimitry Andric *ret_label = dest_label;
672fe6060f1SDimitry Andric return ret;
673fe6060f1SDimitry Andric }
674fe6060f1SDimitry Andric
__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)675fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
676fe6060f1SDimitry Andric char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
677fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
678fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
679fe6060f1SDimitry Andric size_t dest_len = strlen(dest);
680349cc55cSDimitry Andric char *ret = strcat(dest, src);
681fe6060f1SDimitry Andric size_t src_len = strlen(src);
682fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
68304eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
684fe6060f1SDimitry Andric *ret_label = dest_label;
685fe6060f1SDimitry Andric *ret_origin = dest_origin;
686fe6060f1SDimitry Andric return ret;
687fe6060f1SDimitry Andric }
688fe6060f1SDimitry Andric
__dfsw_strncat(char * dest,const char * src,size_t num,dfsan_label dest_label,dfsan_label src_label,dfsan_label num_label,dfsan_label * ret_label)68906c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat(
69006c3fb27SDimitry Andric char *dest, const char *src, size_t num, dfsan_label dest_label,
69106c3fb27SDimitry Andric dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) {
69206c3fb27SDimitry Andric size_t src_len = strlen(src);
69306c3fb27SDimitry Andric src_len = src_len < num ? src_len : num;
69406c3fb27SDimitry Andric size_t dest_len = strlen(dest);
69506c3fb27SDimitry Andric
69606c3fb27SDimitry Andric char *ret = strncat(dest, src, num);
69706c3fb27SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
69806c3fb27SDimitry Andric *ret_label = dest_label;
69906c3fb27SDimitry Andric return ret;
70006c3fb27SDimitry Andric }
70106c3fb27SDimitry Andric
__dfso_strncat(char * dest,const char * src,size_t num,dfsan_label dest_label,dfsan_label src_label,dfsan_label num_label,dfsan_label * ret_label,dfsan_origin dest_origin,dfsan_origin src_origin,dfsan_origin num_origin,dfsan_origin * ret_origin)70206c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat(
70306c3fb27SDimitry Andric char *dest, const char *src, size_t num, dfsan_label dest_label,
70406c3fb27SDimitry Andric dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label,
70506c3fb27SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin,
70606c3fb27SDimitry Andric dfsan_origin *ret_origin) {
70706c3fb27SDimitry Andric size_t src_len = strlen(src);
70806c3fb27SDimitry Andric src_len = src_len < num ? src_len : num;
70906c3fb27SDimitry Andric size_t dest_len = strlen(dest);
71006c3fb27SDimitry Andric
71106c3fb27SDimitry Andric char *ret = strncat(dest, src, num);
71206c3fb27SDimitry Andric
71306c3fb27SDimitry Andric dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
71406c3fb27SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
71506c3fb27SDimitry Andric *ret_label = dest_label;
71606c3fb27SDimitry Andric *ret_origin = dest_origin;
71706c3fb27SDimitry Andric return ret;
71806c3fb27SDimitry Andric }
71906c3fb27SDimitry Andric
72068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *
__dfsw_strdup(const char * s,dfsan_label s_label,dfsan_label * ret_label)72168d75effSDimitry Andric __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
72268d75effSDimitry Andric size_t len = strlen(s);
72368d75effSDimitry Andric void *p = malloc(len+1);
72468d75effSDimitry Andric dfsan_memcpy(p, s, len+1);
72568d75effSDimitry Andric *ret_label = 0;
72668d75effSDimitry Andric return static_cast<char *>(p);
72768d75effSDimitry Andric }
72868d75effSDimitry Andric
__dfso_strdup(const char * s,dfsan_label s_label,dfsan_label * ret_label,dfsan_origin s_origin,dfsan_origin * ret_origin)729fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
730fe6060f1SDimitry Andric dfsan_label s_label,
731fe6060f1SDimitry Andric dfsan_label *ret_label,
732fe6060f1SDimitry Andric dfsan_origin s_origin,
733fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
734fe6060f1SDimitry Andric size_t len = strlen(s);
735fe6060f1SDimitry Andric void *p = malloc(len + 1);
736fe6060f1SDimitry Andric dfsan_memcpy_with_origin(p, s, len + 1);
737fe6060f1SDimitry Andric *ret_label = 0;
738fe6060f1SDimitry Andric return static_cast<char *>(p);
739fe6060f1SDimitry Andric }
740fe6060f1SDimitry Andric
74168d75effSDimitry Andric 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)74268d75effSDimitry Andric __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
74368d75effSDimitry Andric dfsan_label s2_label, dfsan_label n_label,
74468d75effSDimitry Andric dfsan_label *ret_label) {
74568d75effSDimitry Andric size_t len = strlen(s2);
74668d75effSDimitry Andric if (len < n) {
74768d75effSDimitry Andric dfsan_memcpy(s1, s2, len+1);
74868d75effSDimitry Andric dfsan_memset(s1+len+1, 0, 0, n-len-1);
74968d75effSDimitry Andric } else {
75068d75effSDimitry Andric dfsan_memcpy(s1, s2, n);
75168d75effSDimitry Andric }
75268d75effSDimitry Andric
75368d75effSDimitry Andric *ret_label = s1_label;
75468d75effSDimitry Andric return s1;
75568d75effSDimitry Andric }
75668d75effSDimitry Andric
__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)757fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
758fe6060f1SDimitry Andric char *s1, const char *s2, size_t n, dfsan_label s1_label,
759fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
760fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
761fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
762fe6060f1SDimitry Andric size_t len = strlen(s2);
763fe6060f1SDimitry Andric if (len < n) {
764fe6060f1SDimitry Andric dfsan_memcpy_with_origin(s1, s2, len + 1);
765fe6060f1SDimitry Andric dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
766fe6060f1SDimitry Andric } else {
767fe6060f1SDimitry Andric dfsan_memcpy_with_origin(s1, s2, n);
768fe6060f1SDimitry Andric }
769fe6060f1SDimitry Andric
770fe6060f1SDimitry Andric *ret_label = s1_label;
771fe6060f1SDimitry Andric *ret_origin = s1_origin;
772fe6060f1SDimitry Andric return s1;
773fe6060f1SDimitry Andric }
774fe6060f1SDimitry Andric
77568d75effSDimitry Andric 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)77668d75effSDimitry Andric __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
77768d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label,
77868d75effSDimitry Andric dfsan_label count_label, dfsan_label offset_label,
77968d75effSDimitry Andric dfsan_label *ret_label) {
78068d75effSDimitry Andric ssize_t ret = pread(fd, buf, count, offset);
78168d75effSDimitry Andric if (ret > 0)
78268d75effSDimitry Andric dfsan_set_label(0, buf, ret);
78368d75effSDimitry Andric *ret_label = 0;
78468d75effSDimitry Andric return ret;
78568d75effSDimitry Andric }
78668d75effSDimitry Andric
__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)787fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
788fe6060f1SDimitry Andric int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
789fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
790fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
791fe6060f1SDimitry Andric dfsan_origin count_origin, dfsan_label offset_origin,
792fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
793fe6060f1SDimitry Andric return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
794fe6060f1SDimitry Andric offset_label, ret_label);
795fe6060f1SDimitry Andric }
796fe6060f1SDimitry Andric
79768d75effSDimitry Andric 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)79868d75effSDimitry Andric __dfsw_read(int fd, void *buf, size_t count,
79968d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label,
80068d75effSDimitry Andric dfsan_label count_label,
80168d75effSDimitry Andric dfsan_label *ret_label) {
80268d75effSDimitry Andric ssize_t ret = read(fd, buf, count);
80368d75effSDimitry Andric if (ret > 0)
80468d75effSDimitry Andric dfsan_set_label(0, buf, ret);
80568d75effSDimitry Andric *ret_label = 0;
80668d75effSDimitry Andric return ret;
80768d75effSDimitry Andric }
80868d75effSDimitry Andric
__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)809fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
810fe6060f1SDimitry Andric int fd, void *buf, size_t count, dfsan_label fd_label,
811fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
812fe6060f1SDimitry Andric dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
813fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
814fe6060f1SDimitry Andric return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
815fe6060f1SDimitry Andric ret_label);
816fe6060f1SDimitry Andric }
817fe6060f1SDimitry Andric
__dfsw_clock_gettime(clockid_t clk_id,struct timespec * tp,dfsan_label clk_id_label,dfsan_label tp_label,dfsan_label * ret_label)81868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
81968d75effSDimitry Andric struct timespec *tp,
82068d75effSDimitry Andric dfsan_label clk_id_label,
82168d75effSDimitry Andric dfsan_label tp_label,
82268d75effSDimitry Andric dfsan_label *ret_label) {
82368d75effSDimitry Andric int ret = clock_gettime(clk_id, tp);
82468d75effSDimitry Andric if (ret == 0)
82568d75effSDimitry Andric dfsan_set_label(0, tp, sizeof(struct timespec));
82668d75effSDimitry Andric *ret_label = 0;
82768d75effSDimitry Andric return ret;
82868d75effSDimitry Andric }
82968d75effSDimitry Andric
__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)830fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
831fe6060f1SDimitry Andric clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
832fe6060f1SDimitry Andric dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
833fe6060f1SDimitry Andric dfsan_origin tp_origin, dfsan_origin *ret_origin) {
834fe6060f1SDimitry Andric return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
835fe6060f1SDimitry Andric }
836fe6060f1SDimitry Andric
dfsan_set_zero_label(const void * ptr,uptr size)837fe6060f1SDimitry Andric static void dfsan_set_zero_label(const void *ptr, uptr size) {
83868d75effSDimitry Andric dfsan_set_label(0, const_cast<void *>(ptr), size);
83968d75effSDimitry Andric }
84068d75effSDimitry Andric
84168d75effSDimitry Andric // dlopen() ultimately calls mmap() down inside the loader, which generally
84268d75effSDimitry Andric // doesn't participate in dynamic symbol resolution. Therefore we won't
84368d75effSDimitry Andric // intercept its calls to mmap, and we have to hook it here.
84468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *
__dfsw_dlopen(const char * filename,int flag,dfsan_label filename_label,dfsan_label flag_label,dfsan_label * ret_label)84568d75effSDimitry Andric __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
84668d75effSDimitry Andric dfsan_label flag_label, dfsan_label *ret_label) {
84768d75effSDimitry Andric void *handle = dlopen(filename, flag);
84868d75effSDimitry Andric link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
8497a6dacacSDimitry Andric if (filename && map)
850fe6060f1SDimitry Andric ForEachMappedRegion(map, dfsan_set_zero_label);
85168d75effSDimitry Andric *ret_label = 0;
85268d75effSDimitry Andric return handle;
85368d75effSDimitry Andric }
85468d75effSDimitry Andric
__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)855fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
856fe6060f1SDimitry Andric const char *filename, int flag, dfsan_label filename_label,
857fe6060f1SDimitry Andric dfsan_label flag_label, dfsan_label *ret_label,
858fe6060f1SDimitry Andric dfsan_origin filename_origin, dfsan_origin flag_origin,
859fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
860fe6060f1SDimitry Andric return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
861fe6060f1SDimitry Andric }
86268d75effSDimitry Andric
DFsanThreadStartFunc(void * arg)863fe6060f1SDimitry Andric static void *DFsanThreadStartFunc(void *arg) {
864fe6060f1SDimitry Andric DFsanThread *t = (DFsanThread *)arg;
865fe6060f1SDimitry Andric SetCurrentThread(t);
866349cc55cSDimitry Andric t->Init();
867349cc55cSDimitry Andric SetSigProcMask(&t->starting_sigset_, nullptr);
868fe6060f1SDimitry Andric return t->ThreadStart();
869fe6060f1SDimitry Andric }
870fe6060f1SDimitry Andric
dfsan_pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * start_routine,void * arg,dfsan_label * ret_label,bool track_origins=false)871fe6060f1SDimitry Andric static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
872fe6060f1SDimitry Andric void *start_routine, void *arg,
873fe6060f1SDimitry Andric dfsan_label *ret_label,
874fe6060f1SDimitry Andric bool track_origins = false) {
875fe6060f1SDimitry Andric pthread_attr_t myattr;
876fe6060f1SDimitry Andric if (!attr) {
877fe6060f1SDimitry Andric pthread_attr_init(&myattr);
878fe6060f1SDimitry Andric attr = &myattr;
879fe6060f1SDimitry Andric }
880fe6060f1SDimitry Andric
881fe6060f1SDimitry Andric // Ensure that the thread stack is large enough to hold all TLS data.
882fe6060f1SDimitry Andric AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
883fe6060f1SDimitry Andric
884fe6060f1SDimitry Andric DFsanThread *t =
88581ad6265SDimitry Andric DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
886349cc55cSDimitry Andric ScopedBlockSignals block(&t->starting_sigset_);
887fe6060f1SDimitry Andric int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
888fe6060f1SDimitry Andric
889fe6060f1SDimitry Andric if (attr == &myattr)
890fe6060f1SDimitry Andric pthread_attr_destroy(&myattr);
891fe6060f1SDimitry Andric *ret_label = 0;
892fe6060f1SDimitry Andric return res;
89368d75effSDimitry Andric }
89468d75effSDimitry Andric
__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)89568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
89681ad6265SDimitry Andric pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
89781ad6265SDimitry Andric void *arg, dfsan_label thread_label, dfsan_label attr_label,
89881ad6265SDimitry Andric dfsan_label start_routine_label, dfsan_label arg_label,
89981ad6265SDimitry Andric dfsan_label *ret_label) {
90081ad6265SDimitry Andric return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
901fe6060f1SDimitry Andric }
902fe6060f1SDimitry Andric
__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)903fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
90481ad6265SDimitry Andric pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
90581ad6265SDimitry Andric void *arg, dfsan_label thread_label, dfsan_label attr_label,
90681ad6265SDimitry Andric dfsan_label start_routine_label, dfsan_label arg_label,
90781ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin thread_origin,
908fe6060f1SDimitry Andric dfsan_origin attr_origin, dfsan_origin start_routine_origin,
909fe6060f1SDimitry Andric dfsan_origin arg_origin, dfsan_origin *ret_origin) {
91081ad6265SDimitry Andric return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
91181ad6265SDimitry Andric true);
91268d75effSDimitry Andric }
91368d75effSDimitry Andric
__dfsw_pthread_join(pthread_t thread,void ** retval,dfsan_label thread_label,dfsan_label retval_label,dfsan_label * ret_label)914e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
915e8d8bef9SDimitry Andric void **retval,
916e8d8bef9SDimitry Andric dfsan_label thread_label,
917e8d8bef9SDimitry Andric dfsan_label retval_label,
918e8d8bef9SDimitry Andric dfsan_label *ret_label) {
919e8d8bef9SDimitry Andric int ret = pthread_join(thread, retval);
920e8d8bef9SDimitry Andric if (ret == 0 && retval)
921e8d8bef9SDimitry Andric dfsan_set_label(0, retval, sizeof(*retval));
922e8d8bef9SDimitry Andric *ret_label = 0;
923e8d8bef9SDimitry Andric return ret;
924e8d8bef9SDimitry Andric }
925e8d8bef9SDimitry Andric
__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)926fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
927fe6060f1SDimitry Andric pthread_t thread, void **retval, dfsan_label thread_label,
928fe6060f1SDimitry Andric dfsan_label retval_label, dfsan_label *ret_label,
929fe6060f1SDimitry Andric dfsan_origin thread_origin, dfsan_origin retval_origin,
930fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
931fe6060f1SDimitry Andric return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
932fe6060f1SDimitry Andric ret_label);
933fe6060f1SDimitry Andric }
934fe6060f1SDimitry Andric
93568d75effSDimitry Andric struct dl_iterate_phdr_info {
93681ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
937fe6060f1SDimitry Andric void *data;
938fe6060f1SDimitry Andric };
939fe6060f1SDimitry Andric
dl_iterate_phdr_cb(struct dl_phdr_info * info,size_t size,void * data)94068d75effSDimitry Andric int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
94168d75effSDimitry Andric dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
94268d75effSDimitry Andric dfsan_set_label(0, *info);
94368d75effSDimitry Andric dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
94468d75effSDimitry Andric strlen(info->dlpi_name) + 1);
94568d75effSDimitry Andric dfsan_set_label(
94668d75effSDimitry Andric 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
94768d75effSDimitry Andric sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
94868d75effSDimitry Andric
94981ad6265SDimitry Andric dfsan_clear_thread_local_state();
95081ad6265SDimitry Andric return dipi->callback(info, size, dipi->data);
951fe6060f1SDimitry Andric }
952fe6060f1SDimitry Andric
__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)95368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
95481ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
95581ad6265SDimitry Andric void *data, dfsan_label callback_label, dfsan_label data_label,
95681ad6265SDimitry Andric dfsan_label *ret_label) {
95781ad6265SDimitry Andric dl_iterate_phdr_info dipi = {callback, data};
95868d75effSDimitry Andric *ret_label = 0;
95968d75effSDimitry Andric return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
96068d75effSDimitry Andric }
96168d75effSDimitry Andric
__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)962fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
96381ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
96481ad6265SDimitry Andric void *data, dfsan_label callback_label, dfsan_label data_label,
96581ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin callback_origin,
96681ad6265SDimitry Andric dfsan_origin data_origin, dfsan_origin *ret_origin) {
96781ad6265SDimitry Andric dl_iterate_phdr_info dipi = {callback, data};
968fe6060f1SDimitry Andric *ret_label = 0;
96981ad6265SDimitry Andric return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
970fe6060f1SDimitry Andric }
971fe6060f1SDimitry Andric
972e8d8bef9SDimitry Andric // This function is only available for glibc 2.27 or newer. Mark it weak so
973e8d8bef9SDimitry Andric // linking succeeds with older glibcs.
974e8d8bef9SDimitry Andric SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
975e8d8bef9SDimitry Andric size_t *alignp);
976e8d8bef9SDimitry Andric
__dfsw__dl_get_tls_static_info(size_t * sizep,size_t * alignp,dfsan_label sizep_label,dfsan_label alignp_label)977e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
978e8d8bef9SDimitry Andric size_t *sizep, size_t *alignp, dfsan_label sizep_label,
979e8d8bef9SDimitry Andric dfsan_label alignp_label) {
980e8d8bef9SDimitry Andric assert(_dl_get_tls_static_info);
981e8d8bef9SDimitry Andric _dl_get_tls_static_info(sizep, alignp);
982e8d8bef9SDimitry Andric dfsan_set_label(0, sizep, sizeof(*sizep));
983e8d8bef9SDimitry Andric dfsan_set_label(0, alignp, sizeof(*alignp));
984e8d8bef9SDimitry Andric }
985e8d8bef9SDimitry Andric
__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)986fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
987fe6060f1SDimitry Andric size_t *sizep, size_t *alignp, dfsan_label sizep_label,
988fe6060f1SDimitry Andric dfsan_label alignp_label, dfsan_origin sizep_origin,
989fe6060f1SDimitry Andric dfsan_origin alignp_origin) {
990fe6060f1SDimitry Andric __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
991fe6060f1SDimitry Andric }
992fe6060f1SDimitry Andric
99368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_ctime_r(const time_t * timep,char * buf,dfsan_label timep_label,dfsan_label buf_label,dfsan_label * ret_label)99468d75effSDimitry Andric char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
99568d75effSDimitry Andric dfsan_label buf_label, dfsan_label *ret_label) {
99668d75effSDimitry Andric char *ret = ctime_r(timep, buf);
99768d75effSDimitry Andric if (ret) {
99868d75effSDimitry Andric dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
99968d75effSDimitry Andric strlen(buf) + 1);
100068d75effSDimitry Andric *ret_label = buf_label;
100168d75effSDimitry Andric } else {
100268d75effSDimitry Andric *ret_label = 0;
100368d75effSDimitry Andric }
100468d75effSDimitry Andric return ret;
100568d75effSDimitry Andric }
100668d75effSDimitry Andric
100768d75effSDimitry Andric 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)1008fe6060f1SDimitry Andric char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
1009fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label *ret_label,
1010fe6060f1SDimitry Andric dfsan_origin timep_origin, dfsan_origin buf_origin,
1011fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1012fe6060f1SDimitry Andric char *ret = ctime_r(timep, buf);
1013fe6060f1SDimitry Andric if (ret) {
1014fe6060f1SDimitry Andric dfsan_set_label_origin(
1015fe6060f1SDimitry Andric dfsan_read_label(timep, sizeof(time_t)),
1016fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
1017fe6060f1SDimitry Andric strlen(buf) + 1);
1018fe6060f1SDimitry Andric *ret_label = buf_label;
1019fe6060f1SDimitry Andric *ret_origin = buf_origin;
1020fe6060f1SDimitry Andric } else {
1021fe6060f1SDimitry Andric *ret_label = 0;
1022fe6060f1SDimitry Andric }
1023fe6060f1SDimitry Andric return ret;
1024fe6060f1SDimitry Andric }
1025fe6060f1SDimitry Andric
1026fe6060f1SDimitry Andric 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)102768d75effSDimitry Andric char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
102868d75effSDimitry Andric dfsan_label size_label, dfsan_label stream_label,
102968d75effSDimitry Andric dfsan_label *ret_label) {
103068d75effSDimitry Andric char *ret = fgets(s, size, stream);
103168d75effSDimitry Andric if (ret) {
103268d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1);
103368d75effSDimitry Andric *ret_label = s_label;
103468d75effSDimitry Andric } else {
103568d75effSDimitry Andric *ret_label = 0;
103668d75effSDimitry Andric }
103768d75effSDimitry Andric return ret;
103868d75effSDimitry Andric }
103968d75effSDimitry Andric
104068d75effSDimitry Andric 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)1041fe6060f1SDimitry Andric char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
1042fe6060f1SDimitry Andric dfsan_label size_label, dfsan_label stream_label,
1043fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin,
1044fe6060f1SDimitry Andric dfsan_origin size_origin, dfsan_origin stream_origin,
1045fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1046fe6060f1SDimitry Andric char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
1047fe6060f1SDimitry Andric ret_label);
1048fe6060f1SDimitry Andric if (ret)
1049fe6060f1SDimitry Andric *ret_origin = s_origin;
1050fe6060f1SDimitry Andric return ret;
1051fe6060f1SDimitry Andric }
1052fe6060f1SDimitry Andric
1053fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getcwd(char * buf,size_t size,dfsan_label buf_label,dfsan_label size_label,dfsan_label * ret_label)105468d75effSDimitry Andric char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
105568d75effSDimitry Andric dfsan_label size_label, dfsan_label *ret_label) {
105668d75effSDimitry Andric char *ret = getcwd(buf, size);
105768d75effSDimitry Andric if (ret) {
105868d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1);
105968d75effSDimitry Andric *ret_label = buf_label;
106068d75effSDimitry Andric } else {
106168d75effSDimitry Andric *ret_label = 0;
106268d75effSDimitry Andric }
106368d75effSDimitry Andric return ret;
106468d75effSDimitry Andric }
106568d75effSDimitry Andric
106668d75effSDimitry Andric 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)1067fe6060f1SDimitry Andric char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
1068fe6060f1SDimitry Andric dfsan_label size_label, dfsan_label *ret_label,
1069fe6060f1SDimitry Andric dfsan_origin buf_origin, dfsan_origin size_origin,
1070fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1071fe6060f1SDimitry Andric char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
1072fe6060f1SDimitry Andric if (ret)
1073fe6060f1SDimitry Andric *ret_origin = buf_origin;
1074fe6060f1SDimitry Andric return ret;
1075fe6060f1SDimitry Andric }
1076fe6060f1SDimitry Andric
1077fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_get_current_dir_name(dfsan_label * ret_label)107868d75effSDimitry Andric char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
107968d75effSDimitry Andric char *ret = get_current_dir_name();
1080fe6060f1SDimitry Andric if (ret)
108168d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1);
108268d75effSDimitry Andric *ret_label = 0;
108368d75effSDimitry Andric return ret;
108468d75effSDimitry Andric }
108568d75effSDimitry Andric
108668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfso_get_current_dir_name(dfsan_label * ret_label,dfsan_origin * ret_origin)1087fe6060f1SDimitry Andric char *__dfso_get_current_dir_name(dfsan_label *ret_label,
1088fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1089fe6060f1SDimitry Andric return __dfsw_get_current_dir_name(ret_label);
1090fe6060f1SDimitry Andric }
1091fe6060f1SDimitry Andric
1092349cc55cSDimitry Andric // This function is only available for glibc 2.25 or newer. Mark it weak so
1093349cc55cSDimitry Andric // linking succeeds with older glibcs.
1094349cc55cSDimitry Andric SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);
1095349cc55cSDimitry Andric
__dfsw_getentropy(void * buffer,size_t length,dfsan_label buffer_label,dfsan_label length_label,dfsan_label * ret_label)1096349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,
1097349cc55cSDimitry Andric dfsan_label buffer_label,
1098349cc55cSDimitry Andric dfsan_label length_label,
1099349cc55cSDimitry Andric dfsan_label *ret_label) {
1100349cc55cSDimitry Andric int ret = getentropy(buffer, length);
1101349cc55cSDimitry Andric if (ret == 0) {
1102349cc55cSDimitry Andric dfsan_set_label(0, buffer, length);
1103349cc55cSDimitry Andric }
1104349cc55cSDimitry Andric *ret_label = 0;
1105349cc55cSDimitry Andric return ret;
1106349cc55cSDimitry Andric }
1107349cc55cSDimitry Andric
__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)1108349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,
1109349cc55cSDimitry Andric dfsan_label buffer_label,
1110349cc55cSDimitry Andric dfsan_label length_label,
1111349cc55cSDimitry Andric dfsan_label *ret_label,
1112349cc55cSDimitry Andric dfsan_origin buffer_origin,
1113349cc55cSDimitry Andric dfsan_origin length_origin,
1114349cc55cSDimitry Andric dfsan_origin *ret_origin) {
1115349cc55cSDimitry Andric return __dfsw_getentropy(buffer, length, buffer_label, length_label,
1116349cc55cSDimitry Andric ret_label);
1117349cc55cSDimitry Andric }
1118349cc55cSDimitry Andric
1119fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_gethostname(char * name,size_t len,dfsan_label name_label,dfsan_label len_label,dfsan_label * ret_label)112068d75effSDimitry Andric int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
112168d75effSDimitry Andric dfsan_label len_label, dfsan_label *ret_label) {
112268d75effSDimitry Andric int ret = gethostname(name, len);
112368d75effSDimitry Andric if (ret == 0) {
112468d75effSDimitry Andric dfsan_set_label(0, name, strlen(name) + 1);
112568d75effSDimitry Andric }
112668d75effSDimitry Andric *ret_label = 0;
112768d75effSDimitry Andric return ret;
112868d75effSDimitry Andric }
112968d75effSDimitry Andric
113068d75effSDimitry Andric 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)1131fe6060f1SDimitry Andric int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
1132fe6060f1SDimitry Andric dfsan_label len_label, dfsan_label *ret_label,
1133fe6060f1SDimitry Andric dfsan_origin name_origin, dfsan_origin len_origin,
1134fe6060f1SDimitry Andric dfsan_label *ret_origin) {
1135fe6060f1SDimitry Andric return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
1136fe6060f1SDimitry Andric }
1137fe6060f1SDimitry Andric
1138fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getrlimit(int resource,struct rlimit * rlim,dfsan_label resource_label,dfsan_label rlim_label,dfsan_label * ret_label)113968d75effSDimitry Andric int __dfsw_getrlimit(int resource, struct rlimit *rlim,
114068d75effSDimitry Andric dfsan_label resource_label, dfsan_label rlim_label,
114168d75effSDimitry Andric dfsan_label *ret_label) {
114268d75effSDimitry Andric int ret = getrlimit(resource, rlim);
114368d75effSDimitry Andric if (ret == 0) {
114468d75effSDimitry Andric dfsan_set_label(0, rlim, sizeof(struct rlimit));
114568d75effSDimitry Andric }
114668d75effSDimitry Andric *ret_label = 0;
114768d75effSDimitry Andric return ret;
114868d75effSDimitry Andric }
114968d75effSDimitry Andric
115068d75effSDimitry Andric 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)1151fe6060f1SDimitry Andric int __dfso_getrlimit(int resource, struct rlimit *rlim,
1152fe6060f1SDimitry Andric dfsan_label resource_label, dfsan_label rlim_label,
1153fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin resource_origin,
1154fe6060f1SDimitry Andric dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
1155fe6060f1SDimitry Andric return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
1156fe6060f1SDimitry Andric ret_label);
1157fe6060f1SDimitry Andric }
1158fe6060f1SDimitry Andric
1159fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_getrusage(int who,struct rusage * usage,dfsan_label who_label,dfsan_label usage_label,dfsan_label * ret_label)116068d75effSDimitry Andric int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
116168d75effSDimitry Andric dfsan_label usage_label, dfsan_label *ret_label) {
116268d75effSDimitry Andric int ret = getrusage(who, usage);
116368d75effSDimitry Andric if (ret == 0) {
116468d75effSDimitry Andric dfsan_set_label(0, usage, sizeof(struct rusage));
116568d75effSDimitry Andric }
116668d75effSDimitry Andric *ret_label = 0;
116768d75effSDimitry Andric return ret;
116868d75effSDimitry Andric }
116968d75effSDimitry Andric
117068d75effSDimitry Andric 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)1171fe6060f1SDimitry Andric int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1172fe6060f1SDimitry Andric dfsan_label usage_label, dfsan_label *ret_label,
1173fe6060f1SDimitry Andric dfsan_origin who_origin, dfsan_origin usage_origin,
1174fe6060f1SDimitry Andric dfsan_label *ret_origin) {
1175fe6060f1SDimitry Andric return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
1176fe6060f1SDimitry Andric }
1177fe6060f1SDimitry Andric
1178fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strcpy(char * dest,const char * src,dfsan_label dst_label,dfsan_label src_label,dfsan_label * ret_label)117968d75effSDimitry Andric char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
118068d75effSDimitry Andric dfsan_label src_label, dfsan_label *ret_label) {
1181349cc55cSDimitry Andric char *ret = strcpy(dest, src);
118268d75effSDimitry Andric if (ret) {
118304eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);
118468d75effSDimitry Andric }
118568d75effSDimitry Andric *ret_label = dst_label;
118668d75effSDimitry Andric return ret;
118768d75effSDimitry Andric }
118868d75effSDimitry Andric
118968d75effSDimitry Andric 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)1190fe6060f1SDimitry Andric char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
1191fe6060f1SDimitry Andric dfsan_label src_label, dfsan_label *ret_label,
1192fe6060f1SDimitry Andric dfsan_origin dst_origin, dfsan_origin src_origin,
1193fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1194349cc55cSDimitry Andric char *ret = strcpy(dest, src);
1195fe6060f1SDimitry Andric if (ret) {
1196fe6060f1SDimitry Andric size_t str_len = strlen(src) + 1;
1197fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, str_len);
119804eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, str_len);
119968d75effSDimitry Andric }
1200fe6060f1SDimitry Andric *ret_label = dst_label;
1201fe6060f1SDimitry Andric *ret_origin = dst_origin;
1202fe6060f1SDimitry Andric return ret;
1203fe6060f1SDimitry Andric }
120474626c16SDimitry Andric }
1205fe6060f1SDimitry Andric
120674626c16SDimitry Andric template <typename Fn>
dfsan_strtol_impl(Fn real,const char * nptr,char ** endptr,int base,char ** tmp_endptr)120774626c16SDimitry Andric static ALWAYS_INLINE auto dfsan_strtol_impl(
120874626c16SDimitry Andric Fn real, const char *nptr, char **endptr, int base,
120974626c16SDimitry Andric char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) {
1210fe6060f1SDimitry Andric assert(tmp_endptr);
121174626c16SDimitry Andric auto ret = real(nptr, tmp_endptr, base);
1212fe6060f1SDimitry Andric if (endptr)
1213fe6060f1SDimitry Andric *endptr = *tmp_endptr;
1214fe6060f1SDimitry Andric return ret;
1215fe6060f1SDimitry Andric }
1216fe6060f1SDimitry Andric
121774626c16SDimitry Andric extern "C" {
dfsan_strtolong_label(const char * nptr,const char * tmp_endptr,dfsan_label base_label,dfsan_label * ret_label)1218fe6060f1SDimitry Andric static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
1219fe6060f1SDimitry Andric dfsan_label base_label,
1220fe6060f1SDimitry Andric dfsan_label *ret_label) {
122168d75effSDimitry Andric if (tmp_endptr > nptr) {
122268d75effSDimitry Andric // If *tmp_endptr is '\0' include its label as well.
122368d75effSDimitry Andric *ret_label = dfsan_union(
122468d75effSDimitry Andric base_label,
122568d75effSDimitry Andric dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
122668d75effSDimitry Andric } else {
122768d75effSDimitry Andric *ret_label = 0;
122868d75effSDimitry Andric }
1229fe6060f1SDimitry Andric }
1230fe6060f1SDimitry Andric
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)1231fe6060f1SDimitry Andric static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
1232fe6060f1SDimitry Andric dfsan_label base_label,
1233fe6060f1SDimitry Andric dfsan_label *ret_label,
1234fe6060f1SDimitry Andric dfsan_origin base_origin,
1235fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1236fe6060f1SDimitry Andric if (tmp_endptr > nptr) {
1237fe6060f1SDimitry Andric // When multiple inputs are tainted, we propagate one of its origins.
1238fe6060f1SDimitry Andric // Because checking if base_label is tainted does not need additional
1239fe6060f1SDimitry Andric // computation, we prefer to propagating base_origin.
1240fe6060f1SDimitry Andric *ret_origin = base_label
1241fe6060f1SDimitry Andric ? base_origin
1242fe6060f1SDimitry Andric : dfsan_read_origin_of_first_taint(
1243fe6060f1SDimitry Andric nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1244fe6060f1SDimitry Andric }
1245fe6060f1SDimitry Andric }
1246fe6060f1SDimitry Andric
dfsan_strtod(const char * nptr,char ** endptr,char ** tmp_endptr)1247fe6060f1SDimitry Andric static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
1248fe6060f1SDimitry Andric assert(tmp_endptr);
1249fe6060f1SDimitry Andric double ret = strtod(nptr, tmp_endptr);
1250fe6060f1SDimitry Andric if (endptr)
1251fe6060f1SDimitry Andric *endptr = *tmp_endptr;
1252fe6060f1SDimitry Andric return ret;
1253fe6060f1SDimitry Andric }
1254fe6060f1SDimitry Andric
dfsan_strtod_label(const char * nptr,const char * tmp_endptr,dfsan_label * ret_label)1255fe6060f1SDimitry Andric static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
1256fe6060f1SDimitry Andric dfsan_label *ret_label) {
125768d75effSDimitry Andric if (tmp_endptr > nptr) {
125868d75effSDimitry Andric // If *tmp_endptr is '\0' include its label as well.
125968d75effSDimitry Andric *ret_label = dfsan_read_label(
126068d75effSDimitry Andric nptr,
126168d75effSDimitry Andric tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
126268d75effSDimitry Andric } else {
126368d75effSDimitry Andric *ret_label = 0;
126468d75effSDimitry Andric }
1265fe6060f1SDimitry Andric }
1266fe6060f1SDimitry Andric
1267fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_strtod(const char * nptr,char ** endptr,dfsan_label nptr_label,dfsan_label endptr_label,dfsan_label * ret_label)1268fe6060f1SDimitry Andric double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1269fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label *ret_label) {
1270fe6060f1SDimitry Andric char *tmp_endptr;
1271fe6060f1SDimitry Andric double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1272fe6060f1SDimitry Andric dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1273fe6060f1SDimitry Andric return ret;
1274fe6060f1SDimitry Andric }
1275fe6060f1SDimitry Andric
1276fe6060f1SDimitry Andric 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)1277fe6060f1SDimitry Andric double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1278fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label *ret_label,
1279fe6060f1SDimitry Andric dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1280fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1281fe6060f1SDimitry Andric char *tmp_endptr;
1282fe6060f1SDimitry Andric double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1283fe6060f1SDimitry Andric dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1284fe6060f1SDimitry Andric if (tmp_endptr > nptr) {
1285fe6060f1SDimitry Andric // If *tmp_endptr is '\0' include its label as well.
1286fe6060f1SDimitry Andric *ret_origin = dfsan_read_origin_of_first_taint(
1287fe6060f1SDimitry Andric nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1288fe6060f1SDimitry Andric } else {
1289fe6060f1SDimitry Andric *ret_origin = 0;
1290fe6060f1SDimitry Andric }
1291fe6060f1SDimitry Andric return ret;
1292fe6060f1SDimitry Andric }
1293fe6060f1SDimitry Andric
WRAPPER_ALIAS(__isoc23_strtod,strtod)129474626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_strtod, strtod)
129574626c16SDimitry Andric
129674626c16SDimitry Andric #define WRAPPER_STRTO(ret_type, fun) \
129774626c16SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \
129874626c16SDimitry Andric const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
129974626c16SDimitry Andric dfsan_label endptr_label, dfsan_label base_label, \
130074626c16SDimitry Andric dfsan_label *ret_label) { \
130174626c16SDimitry Andric char *tmp_endptr; \
130274626c16SDimitry Andric auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
130374626c16SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
130474626c16SDimitry Andric return ret; \
130574626c16SDimitry Andric } \
130674626c16SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \
130774626c16SDimitry Andric const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
130874626c16SDimitry Andric dfsan_label endptr_label, dfsan_label base_label, \
130974626c16SDimitry Andric dfsan_label *ret_label, dfsan_origin nptr_origin, \
131074626c16SDimitry Andric dfsan_origin endptr_origin, dfsan_origin base_origin, \
131174626c16SDimitry Andric dfsan_origin *ret_origin) { \
131274626c16SDimitry Andric char *tmp_endptr; \
131374626c16SDimitry Andric auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
131474626c16SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
131574626c16SDimitry Andric dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \
131674626c16SDimitry Andric base_origin, ret_origin); \
131774626c16SDimitry Andric return ret; \
131868d75effSDimitry Andric }
131968d75effSDimitry Andric
132074626c16SDimitry Andric WRAPPER_STRTO(long, strtol)
132174626c16SDimitry Andric WRAPPER_STRTO(long long, strtoll)
132274626c16SDimitry Andric WRAPPER_STRTO(unsigned long, strtoul)
132374626c16SDimitry Andric WRAPPER_STRTO(unsigned long long, strtoull)
132474626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_strtol, strtol)
132574626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_strtoll, strtoll)
132674626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_strtoul, strtoul)
132774626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_strtoull, strtoull)
132868d75effSDimitry Andric
132968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
133068d75effSDimitry Andric time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
133168d75effSDimitry Andric time_t ret = time(t);
133268d75effSDimitry Andric if (ret != (time_t) -1 && t) {
133368d75effSDimitry Andric dfsan_set_label(0, t, sizeof(time_t));
133468d75effSDimitry Andric }
133568d75effSDimitry Andric *ret_label = 0;
133668d75effSDimitry Andric return ret;
133768d75effSDimitry Andric }
133868d75effSDimitry Andric
133968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfso_time(time_t * t,dfsan_label t_label,dfsan_label * ret_label,dfsan_origin t_origin,dfsan_origin * ret_origin)1340fe6060f1SDimitry Andric time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
1341fe6060f1SDimitry Andric dfsan_origin t_origin, dfsan_origin *ret_origin) {
1342fe6060f1SDimitry Andric return __dfsw_time(t, t_label, ret_label);
1343fe6060f1SDimitry Andric }
1344fe6060f1SDimitry Andric
1345fe6060f1SDimitry Andric 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)134668d75effSDimitry Andric int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
134768d75effSDimitry Andric dfsan_label src_label, dfsan_label dst_label,
134868d75effSDimitry Andric dfsan_label *ret_label) {
134968d75effSDimitry Andric int ret = inet_pton(af, src, dst);
135068d75effSDimitry Andric if (ret == 1) {
135168d75effSDimitry Andric dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
135268d75effSDimitry Andric af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
135368d75effSDimitry Andric }
135468d75effSDimitry Andric *ret_label = 0;
135568d75effSDimitry Andric return ret;
135668d75effSDimitry Andric }
135768d75effSDimitry Andric
135868d75effSDimitry Andric 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)1359fe6060f1SDimitry Andric int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1360fe6060f1SDimitry Andric dfsan_label src_label, dfsan_label dst_label,
1361fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin af_origin,
1362fe6060f1SDimitry Andric dfsan_origin src_origin, dfsan_origin dst_origin,
1363fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1364fe6060f1SDimitry Andric int ret = inet_pton(af, src, dst);
1365fe6060f1SDimitry Andric if (ret == 1) {
1366fe6060f1SDimitry Andric int src_len = strlen(src) + 1;
1367fe6060f1SDimitry Andric dfsan_set_label_origin(
1368fe6060f1SDimitry Andric dfsan_read_label(src, src_len),
1369fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(src, src_len), dst,
1370fe6060f1SDimitry Andric af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1371fe6060f1SDimitry Andric }
1372fe6060f1SDimitry Andric *ret_label = 0;
1373fe6060f1SDimitry Andric return ret;
1374fe6060f1SDimitry Andric }
1375fe6060f1SDimitry Andric
1376fe6060f1SDimitry Andric 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)137768d75effSDimitry Andric struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
137868d75effSDimitry Andric dfsan_label timep_label, dfsan_label result_label,
137968d75effSDimitry Andric dfsan_label *ret_label) {
138068d75effSDimitry Andric struct tm *ret = localtime_r(timep, result);
138168d75effSDimitry Andric if (ret) {
138268d75effSDimitry Andric dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
138368d75effSDimitry Andric sizeof(struct tm));
138468d75effSDimitry Andric *ret_label = result_label;
138568d75effSDimitry Andric } else {
138668d75effSDimitry Andric *ret_label = 0;
138768d75effSDimitry Andric }
138868d75effSDimitry Andric return ret;
138968d75effSDimitry Andric }
139068d75effSDimitry Andric
139168d75effSDimitry Andric 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)1392fe6060f1SDimitry Andric struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
1393fe6060f1SDimitry Andric dfsan_label timep_label, dfsan_label result_label,
1394fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin timep_origin,
1395fe6060f1SDimitry Andric dfsan_origin result_origin,
1396fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1397fe6060f1SDimitry Andric struct tm *ret = localtime_r(timep, result);
1398fe6060f1SDimitry Andric if (ret) {
1399fe6060f1SDimitry Andric dfsan_set_label_origin(
1400fe6060f1SDimitry Andric dfsan_read_label(timep, sizeof(time_t)),
1401fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
1402fe6060f1SDimitry Andric sizeof(struct tm));
1403fe6060f1SDimitry Andric *ret_label = result_label;
1404fe6060f1SDimitry Andric *ret_origin = result_origin;
1405fe6060f1SDimitry Andric } else {
1406fe6060f1SDimitry Andric *ret_label = 0;
1407fe6060f1SDimitry Andric }
1408fe6060f1SDimitry Andric return ret;
1409fe6060f1SDimitry Andric }
1410fe6060f1SDimitry Andric
1411fe6060f1SDimitry Andric 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)141268d75effSDimitry Andric int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
141368d75effSDimitry Andric char *buf, size_t buflen, struct passwd **result,
141468d75effSDimitry Andric dfsan_label uid_label, dfsan_label pwd_label,
141568d75effSDimitry Andric dfsan_label buf_label, dfsan_label buflen_label,
141668d75effSDimitry Andric dfsan_label result_label, dfsan_label *ret_label) {
141768d75effSDimitry Andric // Store the data in pwd, the strings referenced from pwd in buf, and the
141868d75effSDimitry Andric // address of pwd in *result. On failure, NULL is stored in *result.
141968d75effSDimitry Andric int ret = getpwuid_r(uid, pwd, buf, buflen, result);
142068d75effSDimitry Andric if (ret == 0) {
142168d75effSDimitry Andric dfsan_set_label(0, pwd, sizeof(struct passwd));
142268d75effSDimitry Andric dfsan_set_label(0, buf, strlen(buf) + 1);
142368d75effSDimitry Andric }
142468d75effSDimitry Andric *ret_label = 0;
142568d75effSDimitry Andric dfsan_set_label(0, result, sizeof(struct passwd*));
142668d75effSDimitry Andric return ret;
142768d75effSDimitry Andric }
142868d75effSDimitry Andric
142968d75effSDimitry Andric 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)1430fe6060f1SDimitry Andric int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
1431fe6060f1SDimitry Andric struct passwd **result, dfsan_label uid_label,
1432fe6060f1SDimitry Andric dfsan_label pwd_label, dfsan_label buf_label,
1433fe6060f1SDimitry Andric dfsan_label buflen_label, dfsan_label result_label,
1434fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin uid_origin,
1435fe6060f1SDimitry Andric dfsan_origin pwd_origin, dfsan_origin buf_origin,
1436fe6060f1SDimitry Andric dfsan_origin buflen_origin, dfsan_origin result_origin,
1437fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1438fe6060f1SDimitry Andric return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
1439fe6060f1SDimitry Andric buf_label, buflen_label, result_label, ret_label);
1440fe6060f1SDimitry Andric }
1441fe6060f1SDimitry Andric
1442fe6060f1SDimitry Andric 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)1443e8d8bef9SDimitry Andric int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1444e8d8bef9SDimitry Andric int timeout, dfsan_label epfd_label,
1445e8d8bef9SDimitry Andric dfsan_label events_label, dfsan_label maxevents_label,
1446e8d8bef9SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) {
1447e8d8bef9SDimitry Andric int ret = epoll_wait(epfd, events, maxevents, timeout);
1448e8d8bef9SDimitry Andric if (ret > 0)
1449e8d8bef9SDimitry Andric dfsan_set_label(0, events, ret * sizeof(*events));
1450e8d8bef9SDimitry Andric *ret_label = 0;
1451e8d8bef9SDimitry Andric return ret;
1452e8d8bef9SDimitry Andric }
1453e8d8bef9SDimitry Andric
1454e8d8bef9SDimitry Andric 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)1455fe6060f1SDimitry Andric int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1456fe6060f1SDimitry Andric int timeout, dfsan_label epfd_label,
1457fe6060f1SDimitry Andric dfsan_label events_label, dfsan_label maxevents_label,
1458fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label,
1459fe6060f1SDimitry Andric dfsan_origin epfd_origin, dfsan_origin events_origin,
1460fe6060f1SDimitry Andric dfsan_origin maxevents_origin,
1461fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1462fe6060f1SDimitry Andric return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
1463fe6060f1SDimitry Andric events_label, maxevents_label, timeout_label,
1464fe6060f1SDimitry Andric ret_label);
1465fe6060f1SDimitry Andric }
1466fe6060f1SDimitry Andric
1467fe6060f1SDimitry Andric 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)146868d75effSDimitry Andric int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
146968d75effSDimitry Andric dfsan_label dfs_label, dfsan_label nfds_label,
147068d75effSDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) {
147168d75effSDimitry Andric int ret = poll(fds, nfds, timeout);
147268d75effSDimitry Andric if (ret >= 0) {
147368d75effSDimitry Andric for (; nfds > 0; --nfds) {
147468d75effSDimitry Andric dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
147568d75effSDimitry Andric }
147668d75effSDimitry Andric }
147768d75effSDimitry Andric *ret_label = 0;
147868d75effSDimitry Andric return ret;
147968d75effSDimitry Andric }
148068d75effSDimitry Andric
148168d75effSDimitry Andric 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)1482fe6060f1SDimitry Andric int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1483fe6060f1SDimitry Andric dfsan_label dfs_label, dfsan_label nfds_label,
1484fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label,
1485fe6060f1SDimitry Andric dfsan_origin dfs_origin, dfsan_origin nfds_origin,
1486fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1487fe6060f1SDimitry Andric return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
1488fe6060f1SDimitry Andric ret_label);
1489fe6060f1SDimitry Andric }
1490fe6060f1SDimitry Andric
1491fe6060f1SDimitry Andric 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)149268d75effSDimitry Andric int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
149368d75effSDimitry Andric fd_set *exceptfds, struct timeval *timeout,
149468d75effSDimitry Andric dfsan_label nfds_label, dfsan_label readfds_label,
149568d75effSDimitry Andric dfsan_label writefds_label, dfsan_label exceptfds_label,
149668d75effSDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) {
149768d75effSDimitry Andric int ret = select(nfds, readfds, writefds, exceptfds, timeout);
149868d75effSDimitry Andric // Clear everything (also on error) since their content is either set or
149968d75effSDimitry Andric // undefined.
150068d75effSDimitry Andric if (readfds) {
150168d75effSDimitry Andric dfsan_set_label(0, readfds, sizeof(fd_set));
150268d75effSDimitry Andric }
150368d75effSDimitry Andric if (writefds) {
150468d75effSDimitry Andric dfsan_set_label(0, writefds, sizeof(fd_set));
150568d75effSDimitry Andric }
150668d75effSDimitry Andric if (exceptfds) {
150768d75effSDimitry Andric dfsan_set_label(0, exceptfds, sizeof(fd_set));
150868d75effSDimitry Andric }
150968d75effSDimitry Andric dfsan_set_label(0, timeout, sizeof(struct timeval));
151068d75effSDimitry Andric *ret_label = 0;
151168d75effSDimitry Andric return ret;
151268d75effSDimitry Andric }
151368d75effSDimitry Andric
151468d75effSDimitry Andric 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)1515fe6060f1SDimitry Andric int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
1516fe6060f1SDimitry Andric fd_set *exceptfds, struct timeval *timeout,
1517fe6060f1SDimitry Andric dfsan_label nfds_label, dfsan_label readfds_label,
1518fe6060f1SDimitry Andric dfsan_label writefds_label, dfsan_label exceptfds_label,
1519fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label,
1520fe6060f1SDimitry Andric dfsan_origin nfds_origin, dfsan_origin readfds_origin,
1521fe6060f1SDimitry Andric dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
1522fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1523fe6060f1SDimitry Andric return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
1524fe6060f1SDimitry Andric readfds_label, writefds_label, exceptfds_label,
1525fe6060f1SDimitry Andric timeout_label, ret_label);
1526fe6060f1SDimitry Andric }
1527fe6060f1SDimitry Andric
1528fe6060f1SDimitry Andric 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)152968d75effSDimitry Andric int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
153068d75effSDimitry Andric dfsan_label pid_label,
153168d75effSDimitry Andric dfsan_label cpusetsize_label,
153268d75effSDimitry Andric dfsan_label mask_label, dfsan_label *ret_label) {
153368d75effSDimitry Andric int ret = sched_getaffinity(pid, cpusetsize, mask);
153468d75effSDimitry Andric if (ret == 0) {
153568d75effSDimitry Andric dfsan_set_label(0, mask, cpusetsize);
153668d75effSDimitry Andric }
153768d75effSDimitry Andric *ret_label = 0;
153868d75effSDimitry Andric return ret;
153968d75effSDimitry Andric }
154068d75effSDimitry Andric
154168d75effSDimitry Andric 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)1542fe6060f1SDimitry Andric int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1543fe6060f1SDimitry Andric dfsan_label pid_label,
1544fe6060f1SDimitry Andric dfsan_label cpusetsize_label,
1545fe6060f1SDimitry Andric dfsan_label mask_label, dfsan_label *ret_label,
1546fe6060f1SDimitry Andric dfsan_origin pid_origin,
1547fe6060f1SDimitry Andric dfsan_origin cpusetsize_origin,
1548fe6060f1SDimitry Andric dfsan_origin mask_origin,
1549fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1550fe6060f1SDimitry Andric return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
1551fe6060f1SDimitry Andric cpusetsize_label, mask_label, ret_label);
1552fe6060f1SDimitry Andric }
1553fe6060f1SDimitry Andric
1554fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sigemptyset(sigset_t * set,dfsan_label set_label,dfsan_label * ret_label)155568d75effSDimitry Andric int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
155668d75effSDimitry Andric dfsan_label *ret_label) {
155768d75effSDimitry Andric int ret = sigemptyset(set);
155868d75effSDimitry Andric dfsan_set_label(0, set, sizeof(sigset_t));
1559fe6060f1SDimitry Andric *ret_label = 0;
156068d75effSDimitry Andric return ret;
156168d75effSDimitry Andric }
156268d75effSDimitry Andric
156368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sigemptyset(sigset_t * set,dfsan_label set_label,dfsan_label * ret_label,dfsan_origin set_origin,dfsan_origin * ret_origin)1564fe6060f1SDimitry Andric int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
1565fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin set_origin,
1566fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1567fe6060f1SDimitry Andric return __dfsw_sigemptyset(set, set_label, ret_label);
1568fe6060f1SDimitry Andric }
1569fe6060f1SDimitry Andric
1570fe6060f1SDimitry Andric class SignalHandlerScope {
1571fe6060f1SDimitry Andric public:
SignalHandlerScope()1572fe6060f1SDimitry Andric SignalHandlerScope() {
1573fe6060f1SDimitry Andric if (DFsanThread *t = GetCurrentThread())
1574fe6060f1SDimitry Andric t->EnterSignalHandler();
1575fe6060f1SDimitry Andric }
~SignalHandlerScope()1576fe6060f1SDimitry Andric ~SignalHandlerScope() {
1577fe6060f1SDimitry Andric if (DFsanThread *t = GetCurrentThread())
1578fe6060f1SDimitry Andric t->LeaveSignalHandler();
1579fe6060f1SDimitry Andric }
1580fe6060f1SDimitry Andric };
1581fe6060f1SDimitry Andric
1582fe6060f1SDimitry Andric // Clear DFSan runtime TLS state at the end of a scope.
1583fe6060f1SDimitry Andric //
1584fe6060f1SDimitry Andric // Implementation must be async-signal-safe and use small data size, because
1585fe6060f1SDimitry Andric // instances of this class may live on the signal handler stack.
1586fe6060f1SDimitry Andric //
1587fe6060f1SDimitry Andric // DFSan uses TLS to pass metadata of arguments and return values. When an
1588fe6060f1SDimitry Andric // instrumented function accesses the TLS, if a signal callback happens, and the
1589fe6060f1SDimitry Andric // callback calls other instrumented functions with updating the same TLS, the
1590fe6060f1SDimitry Andric // TLS is in an inconsistent state after the callback ends. This may cause
1591fe6060f1SDimitry Andric // either under-tainting or over-tainting.
1592fe6060f1SDimitry Andric //
1593fe6060f1SDimitry Andric // The current implementation simply resets TLS at restore. This prevents from
1594fe6060f1SDimitry Andric // over-tainting. Although under-tainting may still happen, a taint flow can be
1595fe6060f1SDimitry Andric // found eventually if we run a DFSan-instrumented program multiple times. The
1596fe6060f1SDimitry Andric // alternative option is saving the entire TLS. However the TLS storage takes
1597fe6060f1SDimitry Andric // 2k bytes, and signal calls could be nested. So it does not seem worth.
1598fe6060f1SDimitry Andric class ScopedClearThreadLocalState {
1599fe6060f1SDimitry Andric public:
ScopedClearThreadLocalState()1600fe6060f1SDimitry Andric ScopedClearThreadLocalState() {}
~ScopedClearThreadLocalState()1601fe6060f1SDimitry Andric ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1602fe6060f1SDimitry Andric };
1603fe6060f1SDimitry Andric
1604fe6060f1SDimitry Andric // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1605fe6060f1SDimitry Andric const int kMaxSignals = 1024;
1606fe6060f1SDimitry Andric static atomic_uintptr_t sigactions[kMaxSignals];
1607fe6060f1SDimitry Andric
SignalHandler(int signo)1608fe6060f1SDimitry Andric static void SignalHandler(int signo) {
1609fe6060f1SDimitry Andric SignalHandlerScope signal_handler_scope;
1610fe6060f1SDimitry Andric ScopedClearThreadLocalState scoped_clear_tls;
1611fe6060f1SDimitry Andric
161281ad6265SDimitry Andric // Clear shadows for all inputs provided by system.
1613fe6060f1SDimitry Andric dfsan_clear_arg_tls(0, sizeof(dfsan_label));
1614fe6060f1SDimitry Andric
1615fe6060f1SDimitry Andric typedef void (*signal_cb)(int x);
1616fe6060f1SDimitry Andric signal_cb cb =
1617fe6060f1SDimitry Andric (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1618fe6060f1SDimitry Andric cb(signo);
1619fe6060f1SDimitry Andric }
1620fe6060f1SDimitry Andric
SignalAction(int signo,siginfo_t * si,void * uc)1621fe6060f1SDimitry Andric static void SignalAction(int signo, siginfo_t *si, void *uc) {
1622fe6060f1SDimitry Andric SignalHandlerScope signal_handler_scope;
1623fe6060f1SDimitry Andric ScopedClearThreadLocalState scoped_clear_tls;
1624fe6060f1SDimitry Andric
1625fe6060f1SDimitry Andric // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1626fe6060f1SDimitry Andric dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
1627fe6060f1SDimitry Andric dfsan_set_label(0, si, sizeof(*si));
1628fe6060f1SDimitry Andric dfsan_set_label(0, uc, sizeof(ucontext_t));
1629fe6060f1SDimitry Andric
1630fe6060f1SDimitry Andric typedef void (*sigaction_cb)(int, siginfo_t *, void *);
1631fe6060f1SDimitry Andric sigaction_cb cb =
1632fe6060f1SDimitry Andric (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1633fe6060f1SDimitry Andric cb(signo, si, uc);
1634fe6060f1SDimitry Andric }
1635fe6060f1SDimitry Andric
1636fe6060f1SDimitry Andric 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)163768d75effSDimitry Andric int __dfsw_sigaction(int signum, const struct sigaction *act,
163868d75effSDimitry Andric struct sigaction *oldact, dfsan_label signum_label,
163968d75effSDimitry Andric dfsan_label act_label, dfsan_label oldact_label,
164068d75effSDimitry Andric dfsan_label *ret_label) {
1641fe6060f1SDimitry Andric CHECK_LT(signum, kMaxSignals);
1642fe6060f1SDimitry Andric SignalSpinLocker lock;
1643fe6060f1SDimitry Andric uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1644fe6060f1SDimitry Andric struct sigaction new_act;
1645fe6060f1SDimitry Andric struct sigaction *pnew_act = act ? &new_act : nullptr;
1646fe6060f1SDimitry Andric if (act) {
1647fe6060f1SDimitry Andric internal_memcpy(pnew_act, act, sizeof(struct sigaction));
1648fe6060f1SDimitry Andric if (pnew_act->sa_flags & SA_SIGINFO) {
1649fe6060f1SDimitry Andric uptr cb = (uptr)(pnew_act->sa_sigaction);
1650fe6060f1SDimitry Andric if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1651fe6060f1SDimitry Andric atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1652fe6060f1SDimitry Andric pnew_act->sa_sigaction = SignalAction;
1653fe6060f1SDimitry Andric }
1654fe6060f1SDimitry Andric } else {
1655fe6060f1SDimitry Andric uptr cb = (uptr)(pnew_act->sa_handler);
1656fe6060f1SDimitry Andric if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1657fe6060f1SDimitry Andric atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1658fe6060f1SDimitry Andric pnew_act->sa_handler = SignalHandler;
1659fe6060f1SDimitry Andric }
1660fe6060f1SDimitry Andric }
1661fe6060f1SDimitry Andric }
1662fe6060f1SDimitry Andric
1663fe6060f1SDimitry Andric int ret = sigaction(signum, pnew_act, oldact);
1664fe6060f1SDimitry Andric
1665fe6060f1SDimitry Andric if (ret == 0 && oldact) {
1666fe6060f1SDimitry Andric if (oldact->sa_flags & SA_SIGINFO) {
1667fe6060f1SDimitry Andric if (oldact->sa_sigaction == SignalAction)
1668fe6060f1SDimitry Andric oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
1669fe6060f1SDimitry Andric } else {
1670fe6060f1SDimitry Andric if (oldact->sa_handler == SignalHandler)
1671fe6060f1SDimitry Andric oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
1672fe6060f1SDimitry Andric }
1673fe6060f1SDimitry Andric }
1674fe6060f1SDimitry Andric
167568d75effSDimitry Andric if (oldact) {
167668d75effSDimitry Andric dfsan_set_label(0, oldact, sizeof(struct sigaction));
167768d75effSDimitry Andric }
167868d75effSDimitry Andric *ret_label = 0;
167968d75effSDimitry Andric return ret;
168068d75effSDimitry Andric }
168168d75effSDimitry Andric
168268d75effSDimitry Andric 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)1683fe6060f1SDimitry Andric int __dfso_sigaction(int signum, const struct sigaction *act,
1684fe6060f1SDimitry Andric struct sigaction *oldact, dfsan_label signum_label,
1685fe6060f1SDimitry Andric dfsan_label act_label, dfsan_label oldact_label,
1686fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin signum_origin,
1687fe6060f1SDimitry Andric dfsan_origin act_origin, dfsan_origin oldact_origin,
1688fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1689fe6060f1SDimitry Andric return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
1690fe6060f1SDimitry Andric oldact_label, ret_label);
1691fe6060f1SDimitry Andric }
1692fe6060f1SDimitry Andric
dfsan_signal(int signum,sighandler_t handler,dfsan_label * ret_label)1693fe6060f1SDimitry Andric static sighandler_t dfsan_signal(int signum, sighandler_t handler,
1694fe6060f1SDimitry Andric dfsan_label *ret_label) {
1695fe6060f1SDimitry Andric CHECK_LT(signum, kMaxSignals);
1696fe6060f1SDimitry Andric SignalSpinLocker lock;
1697fe6060f1SDimitry Andric uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1698fe6060f1SDimitry Andric if (handler != SIG_IGN && handler != SIG_DFL) {
1699fe6060f1SDimitry Andric atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
1700fe6060f1SDimitry Andric handler = &SignalHandler;
1701fe6060f1SDimitry Andric }
1702fe6060f1SDimitry Andric
1703fe6060f1SDimitry Andric sighandler_t ret = signal(signum, handler);
1704fe6060f1SDimitry Andric
1705fe6060f1SDimitry Andric if (ret == SignalHandler)
1706fe6060f1SDimitry Andric ret = (sighandler_t)old_cb;
1707fe6060f1SDimitry Andric
1708fe6060f1SDimitry Andric *ret_label = 0;
1709fe6060f1SDimitry Andric return ret;
1710fe6060f1SDimitry Andric }
1711fe6060f1SDimitry Andric
1712fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_signal(int signum,sighandler_t handler,dfsan_label signum_label,dfsan_label handler_label,dfsan_label * ret_label)171381ad6265SDimitry Andric sighandler_t __dfsw_signal(int signum, sighandler_t handler,
171481ad6265SDimitry Andric dfsan_label signum_label, dfsan_label handler_label,
171581ad6265SDimitry Andric dfsan_label *ret_label) {
1716fe6060f1SDimitry Andric return dfsan_signal(signum, handler, ret_label);
1717fe6060f1SDimitry Andric }
1718fe6060f1SDimitry Andric
1719fe6060f1SDimitry Andric 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)172081ad6265SDimitry Andric sighandler_t __dfso_signal(int signum, sighandler_t handler,
172181ad6265SDimitry Andric dfsan_label signum_label, dfsan_label handler_label,
1722fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin signum_origin,
172381ad6265SDimitry Andric dfsan_origin handler_origin,
172481ad6265SDimitry Andric dfsan_origin *ret_origin) {
1725fe6060f1SDimitry Andric return dfsan_signal(signum, handler, ret_label);
1726fe6060f1SDimitry Andric }
1727fe6060f1SDimitry Andric
1728fe6060f1SDimitry Andric 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)1729e8d8bef9SDimitry Andric int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1730e8d8bef9SDimitry Andric dfsan_label old_ss_label, dfsan_label *ret_label) {
1731e8d8bef9SDimitry Andric int ret = sigaltstack(ss, old_ss);
1732e8d8bef9SDimitry Andric if (ret != -1 && old_ss)
1733e8d8bef9SDimitry Andric dfsan_set_label(0, old_ss, sizeof(*old_ss));
1734e8d8bef9SDimitry Andric *ret_label = 0;
1735e8d8bef9SDimitry Andric return ret;
1736e8d8bef9SDimitry Andric }
1737e8d8bef9SDimitry Andric
1738e8d8bef9SDimitry Andric 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)1739fe6060f1SDimitry Andric int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1740fe6060f1SDimitry Andric dfsan_label old_ss_label, dfsan_label *ret_label,
1741fe6060f1SDimitry Andric dfsan_origin ss_origin, dfsan_origin old_ss_origin,
1742fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1743fe6060f1SDimitry Andric return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
1744fe6060f1SDimitry Andric }
1745fe6060f1SDimitry Andric
1746fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_gettimeofday(struct timeval * tv,struct timezone * tz,dfsan_label tv_label,dfsan_label tz_label,dfsan_label * ret_label)174768d75effSDimitry Andric int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
174868d75effSDimitry Andric dfsan_label tv_label, dfsan_label tz_label,
174968d75effSDimitry Andric dfsan_label *ret_label) {
175068d75effSDimitry Andric int ret = gettimeofday(tv, tz);
175168d75effSDimitry Andric if (tv) {
175268d75effSDimitry Andric dfsan_set_label(0, tv, sizeof(struct timeval));
175368d75effSDimitry Andric }
175468d75effSDimitry Andric if (tz) {
175568d75effSDimitry Andric dfsan_set_label(0, tz, sizeof(struct timezone));
175668d75effSDimitry Andric }
175768d75effSDimitry Andric *ret_label = 0;
175868d75effSDimitry Andric return ret;
175968d75effSDimitry Andric }
176068d75effSDimitry Andric
1761fe6060f1SDimitry Andric 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)1762fe6060f1SDimitry Andric int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
1763fe6060f1SDimitry Andric dfsan_label tv_label, dfsan_label tz_label,
1764fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin tv_origin,
1765fe6060f1SDimitry Andric dfsan_origin tz_origin, dfsan_origin *ret_origin) {
1766fe6060f1SDimitry Andric return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
1767fe6060f1SDimitry Andric }
1768fe6060f1SDimitry Andric
__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)176968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
177068d75effSDimitry Andric dfsan_label s_label,
177168d75effSDimitry Andric dfsan_label c_label,
177268d75effSDimitry Andric dfsan_label n_label,
177368d75effSDimitry Andric dfsan_label *ret_label) {
177468d75effSDimitry Andric void *ret = memchr(s, c, n);
177568d75effSDimitry Andric if (flags().strict_data_dependencies) {
177668d75effSDimitry Andric *ret_label = ret ? s_label : 0;
177768d75effSDimitry Andric } else {
177868d75effSDimitry Andric size_t len =
177968d75effSDimitry Andric ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
178068d75effSDimitry Andric : n;
178168d75effSDimitry Andric *ret_label =
178268d75effSDimitry Andric dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
178368d75effSDimitry Andric }
178468d75effSDimitry Andric return ret;
178568d75effSDimitry Andric }
178668d75effSDimitry Andric
__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)1787fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
1788fe6060f1SDimitry Andric void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
1789fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
1790fe6060f1SDimitry Andric dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
1791fe6060f1SDimitry Andric void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
1792fe6060f1SDimitry Andric if (flags().strict_data_dependencies) {
1793fe6060f1SDimitry Andric if (ret)
1794fe6060f1SDimitry Andric *ret_origin = s_origin;
1795fe6060f1SDimitry Andric } else {
1796fe6060f1SDimitry Andric size_t len =
1797fe6060f1SDimitry Andric ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1798fe6060f1SDimitry Andric : n;
1799fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
1800fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1801fe6060f1SDimitry Andric }
1802fe6060f1SDimitry Andric return ret;
1803fe6060f1SDimitry Andric }
1804fe6060f1SDimitry Andric
__dfsw_strrchr(char * s,int c,dfsan_label s_label,dfsan_label c_label,dfsan_label * ret_label)180568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
180668d75effSDimitry Andric dfsan_label s_label,
180768d75effSDimitry Andric dfsan_label c_label,
180868d75effSDimitry Andric dfsan_label *ret_label) {
180968d75effSDimitry Andric char *ret = strrchr(s, c);
181068d75effSDimitry Andric if (flags().strict_data_dependencies) {
181168d75effSDimitry Andric *ret_label = ret ? s_label : 0;
181268d75effSDimitry Andric } else {
181368d75effSDimitry Andric *ret_label =
181468d75effSDimitry Andric dfsan_union(dfsan_read_label(s, strlen(s) + 1),
181568d75effSDimitry Andric dfsan_union(s_label, c_label));
181668d75effSDimitry Andric }
181768d75effSDimitry Andric
181868d75effSDimitry Andric return ret;
181968d75effSDimitry Andric }
182068d75effSDimitry Andric
__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)1821fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
1822fe6060f1SDimitry Andric char *s, int c, dfsan_label s_label, dfsan_label c_label,
1823fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
1824fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1825fe6060f1SDimitry Andric char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
1826fe6060f1SDimitry Andric if (flags().strict_data_dependencies) {
1827fe6060f1SDimitry Andric if (ret)
1828fe6060f1SDimitry Andric *ret_origin = s_origin;
1829fe6060f1SDimitry Andric } else {
1830fe6060f1SDimitry Andric size_t s_len = strlen(s) + 1;
1831fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
1832fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1833fe6060f1SDimitry Andric }
1834fe6060f1SDimitry Andric
1835fe6060f1SDimitry Andric return ret;
1836fe6060f1SDimitry Andric }
1837fe6060f1SDimitry Andric
__dfsw_strstr(char * haystack,char * needle,dfsan_label haystack_label,dfsan_label needle_label,dfsan_label * ret_label)183868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
183968d75effSDimitry Andric dfsan_label haystack_label,
184068d75effSDimitry Andric dfsan_label needle_label,
184168d75effSDimitry Andric dfsan_label *ret_label) {
184268d75effSDimitry Andric char *ret = strstr(haystack, needle);
184368d75effSDimitry Andric if (flags().strict_data_dependencies) {
184468d75effSDimitry Andric *ret_label = ret ? haystack_label : 0;
184568d75effSDimitry Andric } else {
184668d75effSDimitry Andric size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
184768d75effSDimitry Andric *ret_label =
184868d75effSDimitry Andric dfsan_union(dfsan_read_label(haystack, len),
184968d75effSDimitry Andric dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
185068d75effSDimitry Andric dfsan_union(haystack_label, needle_label)));
185168d75effSDimitry Andric }
185268d75effSDimitry Andric
185368d75effSDimitry Andric return ret;
185468d75effSDimitry Andric }
185568d75effSDimitry Andric
__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)1856fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
1857fe6060f1SDimitry Andric dfsan_label haystack_label,
1858fe6060f1SDimitry Andric dfsan_label needle_label,
1859fe6060f1SDimitry Andric dfsan_label *ret_label,
1860fe6060f1SDimitry Andric dfsan_origin haystack_origin,
1861fe6060f1SDimitry Andric dfsan_origin needle_origin,
1862fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
1863fe6060f1SDimitry Andric char *ret =
1864fe6060f1SDimitry Andric __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
1865fe6060f1SDimitry Andric if (flags().strict_data_dependencies) {
1866fe6060f1SDimitry Andric if (ret)
1867fe6060f1SDimitry Andric *ret_origin = haystack_origin;
1868fe6060f1SDimitry Andric } else {
1869fe6060f1SDimitry Andric size_t needle_len = strlen(needle);
1870fe6060f1SDimitry Andric size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
1871fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
1872fe6060f1SDimitry Andric if (o) {
1873fe6060f1SDimitry Andric *ret_origin = o;
1874fe6060f1SDimitry Andric } else {
1875fe6060f1SDimitry Andric o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
1876fe6060f1SDimitry Andric *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
1877fe6060f1SDimitry Andric }
1878fe6060f1SDimitry Andric }
1879fe6060f1SDimitry Andric
1880fe6060f1SDimitry Andric return ret;
1881fe6060f1SDimitry Andric }
1882fe6060f1SDimitry Andric
__dfsw_nanosleep(const struct timespec * req,struct timespec * rem,dfsan_label req_label,dfsan_label rem_label,dfsan_label * ret_label)188368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
188468d75effSDimitry Andric struct timespec *rem,
188568d75effSDimitry Andric dfsan_label req_label,
188668d75effSDimitry Andric dfsan_label rem_label,
188768d75effSDimitry Andric dfsan_label *ret_label) {
188868d75effSDimitry Andric int ret = nanosleep(req, rem);
188968d75effSDimitry Andric *ret_label = 0;
189068d75effSDimitry Andric if (ret == -1) {
189168d75effSDimitry Andric // Interrupted by a signal, rem is filled with the remaining time.
189268d75effSDimitry Andric dfsan_set_label(0, rem, sizeof(struct timespec));
189368d75effSDimitry Andric }
189468d75effSDimitry Andric return ret;
189568d75effSDimitry Andric }
189668d75effSDimitry Andric
__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)1897fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
1898fe6060f1SDimitry Andric const struct timespec *req, struct timespec *rem, dfsan_label req_label,
1899fe6060f1SDimitry Andric dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
1900fe6060f1SDimitry Andric dfsan_origin rem_origin, dfsan_origin *ret_origin) {
1901fe6060f1SDimitry Andric return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
1902fe6060f1SDimitry Andric }
1903fe6060f1SDimitry Andric
clear_msghdr_labels(size_t bytes_written,struct msghdr * msg,int flags)1904*0fca6ea1SDimitry Andric static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg,
1905*0fca6ea1SDimitry Andric int flags) {
1906e8d8bef9SDimitry Andric dfsan_set_label(0, msg, sizeof(*msg));
1907e8d8bef9SDimitry Andric dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
1908e8d8bef9SDimitry Andric dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
1909*0fca6ea1SDimitry Andric for (size_t i = 0; i < msg->msg_iovlen; ++i) {
1910e8d8bef9SDimitry Andric struct iovec *iov = &msg->msg_iov[i];
1911*0fca6ea1SDimitry Andric size_t iov_written = iov->iov_len;
1912*0fca6ea1SDimitry Andric
1913*0fca6ea1SDimitry Andric // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that
1914*0fca6ea1SDimitry Andric // may not have changed, using bytes_written to bound the 0 label write.
1915*0fca6ea1SDimitry Andric // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer,
1916*0fca6ea1SDimitry Andric // and should not be used as a bound.
1917*0fca6ea1SDimitry Andric if (!(MSG_TRUNC & flags)) {
1918*0fca6ea1SDimitry Andric if (bytes_written < iov->iov_len) {
1919*0fca6ea1SDimitry Andric iov_written = bytes_written;
1920*0fca6ea1SDimitry Andric }
1921e8d8bef9SDimitry Andric bytes_written -= iov_written;
1922e8d8bef9SDimitry Andric }
1923*0fca6ea1SDimitry Andric
1924*0fca6ea1SDimitry Andric dfsan_set_label(0, iov->iov_base, iov_written);
1925*0fca6ea1SDimitry Andric }
1926e8d8bef9SDimitry Andric }
1927e8d8bef9SDimitry Andric
__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)1928e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
1929e8d8bef9SDimitry Andric int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1930e8d8bef9SDimitry Andric struct timespec *timeout, dfsan_label sockfd_label,
1931e8d8bef9SDimitry Andric dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1932e8d8bef9SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) {
1933e8d8bef9SDimitry Andric int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
1934e8d8bef9SDimitry Andric for (int i = 0; i < ret; ++i) {
1935e8d8bef9SDimitry Andric dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
1936*0fca6ea1SDimitry Andric clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags);
1937e8d8bef9SDimitry Andric }
1938e8d8bef9SDimitry Andric *ret_label = 0;
1939e8d8bef9SDimitry Andric return ret;
1940e8d8bef9SDimitry Andric }
1941e8d8bef9SDimitry Andric
__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)1942fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
1943fe6060f1SDimitry Andric int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1944fe6060f1SDimitry Andric struct timespec *timeout, dfsan_label sockfd_label,
1945fe6060f1SDimitry Andric dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1946fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label,
1947fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
1948fe6060f1SDimitry Andric dfsan_origin vlen_origin, dfsan_origin flags_origin,
1949fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1950fe6060f1SDimitry Andric return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
1951fe6060f1SDimitry Andric msgvec_label, vlen_label, flags_label, timeout_label,
1952fe6060f1SDimitry Andric ret_label);
1953fe6060f1SDimitry Andric }
1954fe6060f1SDimitry Andric
__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)1955e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
1956e8d8bef9SDimitry Andric int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1957e8d8bef9SDimitry Andric dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
1958e8d8bef9SDimitry Andric ssize_t ret = recvmsg(sockfd, msg, flags);
1959e8d8bef9SDimitry Andric if (ret >= 0)
1960*0fca6ea1SDimitry Andric clear_msghdr_labels(ret, msg, flags);
1961e8d8bef9SDimitry Andric *ret_label = 0;
1962e8d8bef9SDimitry Andric return ret;
1963e8d8bef9SDimitry Andric }
1964e8d8bef9SDimitry Andric
__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)1965fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
1966fe6060f1SDimitry Andric int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1967fe6060f1SDimitry Andric dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
1968fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin msg_origin,
1969fe6060f1SDimitry Andric dfsan_origin flags_origin, dfsan_origin *ret_origin) {
1970fe6060f1SDimitry Andric return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
1971fe6060f1SDimitry Andric flags_label, ret_label);
1972fe6060f1SDimitry Andric }
1973fe6060f1SDimitry Andric
197468d75effSDimitry Andric 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)197568d75effSDimitry Andric __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
197668d75effSDimitry Andric dfsan_label domain_label, dfsan_label type_label,
197768d75effSDimitry Andric dfsan_label protocol_label, dfsan_label sv_label,
197868d75effSDimitry Andric dfsan_label *ret_label) {
197968d75effSDimitry Andric int ret = socketpair(domain, type, protocol, sv);
198068d75effSDimitry Andric *ret_label = 0;
198168d75effSDimitry Andric if (ret == 0) {
198268d75effSDimitry Andric dfsan_set_label(0, sv, sizeof(*sv) * 2);
198368d75effSDimitry Andric }
198468d75effSDimitry Andric return ret;
198568d75effSDimitry Andric }
198668d75effSDimitry Andric
__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)1987fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
1988fe6060f1SDimitry Andric int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
1989fe6060f1SDimitry Andric dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
1990fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin domain_origin,
1991fe6060f1SDimitry Andric dfsan_origin type_origin, dfsan_origin protocol_origin,
1992fe6060f1SDimitry Andric dfsan_origin sv_origin, dfsan_origin *ret_origin) {
1993fe6060f1SDimitry Andric return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
1994fe6060f1SDimitry Andric protocol_label, sv_label, ret_label);
1995fe6060f1SDimitry Andric }
1996fe6060f1SDimitry Andric
__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)1997e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
1998e8d8bef9SDimitry Andric int sockfd, int level, int optname, void *optval, socklen_t *optlen,
1999e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label level_label,
2000e8d8bef9SDimitry Andric dfsan_label optname_label, dfsan_label optval_label,
2001e8d8bef9SDimitry Andric dfsan_label optlen_label, dfsan_label *ret_label) {
2002e8d8bef9SDimitry Andric int ret = getsockopt(sockfd, level, optname, optval, optlen);
2003e8d8bef9SDimitry Andric if (ret != -1 && optval && optlen) {
2004e8d8bef9SDimitry Andric dfsan_set_label(0, optlen, sizeof(*optlen));
2005e8d8bef9SDimitry Andric dfsan_set_label(0, optval, *optlen);
2006e8d8bef9SDimitry Andric }
2007e8d8bef9SDimitry Andric *ret_label = 0;
2008e8d8bef9SDimitry Andric return ret;
2009e8d8bef9SDimitry Andric }
2010e8d8bef9SDimitry Andric
__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)2011fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
2012fe6060f1SDimitry Andric int sockfd, int level, int optname, void *optval, socklen_t *optlen,
2013fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label level_label,
2014fe6060f1SDimitry Andric dfsan_label optname_label, dfsan_label optval_label,
2015fe6060f1SDimitry Andric dfsan_label optlen_label, dfsan_label *ret_label,
2016fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin level_origin,
2017fe6060f1SDimitry Andric dfsan_origin optname_origin, dfsan_origin optval_origin,
2018fe6060f1SDimitry Andric dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
2019fe6060f1SDimitry Andric return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
2020fe6060f1SDimitry Andric level_label, optname_label, optval_label,
2021fe6060f1SDimitry Andric optlen_label, ret_label);
2022fe6060f1SDimitry Andric }
2023fe6060f1SDimitry Andric
__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)2024e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
2025e8d8bef9SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2026e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2027e8d8bef9SDimitry Andric dfsan_label *ret_label) {
2028e8d8bef9SDimitry Andric socklen_t origlen = addrlen ? *addrlen : 0;
2029e8d8bef9SDimitry Andric int ret = getsockname(sockfd, addr, addrlen);
2030e8d8bef9SDimitry Andric if (ret != -1 && addr && addrlen) {
2031e8d8bef9SDimitry Andric socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2032e8d8bef9SDimitry Andric dfsan_set_label(0, addrlen, sizeof(*addrlen));
2033e8d8bef9SDimitry Andric dfsan_set_label(0, addr, written_bytes);
2034e8d8bef9SDimitry Andric }
2035e8d8bef9SDimitry Andric *ret_label = 0;
2036e8d8bef9SDimitry Andric return ret;
2037e8d8bef9SDimitry Andric }
2038e8d8bef9SDimitry Andric
__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)2039fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
2040fe6060f1SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2041fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2042fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin sockfd_origin,
2043fe6060f1SDimitry Andric dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2044fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
2045fe6060f1SDimitry Andric return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
2046fe6060f1SDimitry Andric addrlen_label, ret_label);
2047fe6060f1SDimitry Andric }
2048fe6060f1SDimitry Andric
__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)2049e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
2050e8d8bef9SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2051e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2052e8d8bef9SDimitry Andric dfsan_label *ret_label) {
2053e8d8bef9SDimitry Andric socklen_t origlen = addrlen ? *addrlen : 0;
2054e8d8bef9SDimitry Andric int ret = getpeername(sockfd, addr, addrlen);
2055e8d8bef9SDimitry Andric if (ret != -1 && addr && addrlen) {
2056e8d8bef9SDimitry Andric socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2057e8d8bef9SDimitry Andric dfsan_set_label(0, addrlen, sizeof(*addrlen));
2058e8d8bef9SDimitry Andric dfsan_set_label(0, addr, written_bytes);
2059e8d8bef9SDimitry Andric }
2060e8d8bef9SDimitry Andric *ret_label = 0;
2061e8d8bef9SDimitry Andric return ret;
2062e8d8bef9SDimitry Andric }
2063e8d8bef9SDimitry Andric
__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)2064fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
2065fe6060f1SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2066fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2067fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin sockfd_origin,
2068fe6060f1SDimitry Andric dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2069fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
2070fe6060f1SDimitry Andric return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
2071fe6060f1SDimitry Andric addrlen_label, ret_label);
2072fe6060f1SDimitry Andric }
2073fe6060f1SDimitry Andric
207481ad6265SDimitry Andric // Type of the function passed to dfsan_set_write_callback.
207581ad6265SDimitry Andric typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
2076fe6060f1SDimitry Andric
207768d75effSDimitry Andric // Calls to dfsan_set_write_callback() set the values in this struct.
207868d75effSDimitry Andric // Calls to the custom version of write() read (and invoke) them.
207968d75effSDimitry Andric static struct {
208081ad6265SDimitry Andric write_dfsan_callback_t write_callback = nullptr;
208168d75effSDimitry Andric } write_callback_info;
208268d75effSDimitry Andric
__dfsw_dfsan_set_write_callback(write_dfsan_callback_t write_callback,dfsan_label write_callback_label,dfsan_label * ret_label)208381ad6265SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
208481ad6265SDimitry Andric write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
208568d75effSDimitry Andric dfsan_label *ret_label) {
208668d75effSDimitry Andric write_callback_info.write_callback = write_callback;
208768d75effSDimitry Andric }
208868d75effSDimitry Andric
__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)2089fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
209081ad6265SDimitry Andric write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
209181ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin write_callback_origin,
209281ad6265SDimitry Andric dfsan_origin *ret_origin) {
209381ad6265SDimitry Andric write_callback_info.write_callback = write_callback;
209481ad6265SDimitry Andric }
209581ad6265SDimitry Andric
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)209681ad6265SDimitry Andric static inline void setup_tls_args_for_write_callback(
209781ad6265SDimitry Andric dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
209881ad6265SDimitry Andric bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
209981ad6265SDimitry Andric dfsan_origin count_origin) {
210081ad6265SDimitry Andric // The callback code will expect argument shadow labels in the args TLS,
210181ad6265SDimitry Andric // and origin labels in the origin args TLS.
210281ad6265SDimitry Andric // Previously this was done by a trampoline, but we want to remove this:
210381ad6265SDimitry Andric // https://github.com/llvm/llvm-project/issues/54172
210481ad6265SDimitry Andric //
210581ad6265SDimitry Andric // Instead, this code is manually setting up the args TLS data.
210681ad6265SDimitry Andric //
210781ad6265SDimitry Andric // The offsets used need to correspond with the instrumentation code,
210881ad6265SDimitry Andric // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
210981ad6265SDimitry Andric // DFSanFunction::getShadowForTLSArgument.
211081ad6265SDimitry Andric // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
211181ad6265SDimitry Andric // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
211281ad6265SDimitry Andric //
211381ad6265SDimitry Andric // Here the arguments are all primitives, but it can be more complex
211481ad6265SDimitry Andric // to compute offsets for array/aggregate type arguments.
211581ad6265SDimitry Andric //
211681ad6265SDimitry Andric // TODO(browneee): Consider a builtin to improve maintainabliity.
211781ad6265SDimitry Andric // With a builtin, we would provide the argument labels via builtin,
211881ad6265SDimitry Andric // and the builtin would reuse parts of the instrumentation code to ensure
211981ad6265SDimitry Andric // that this code and the instrumentation can never be out of sync.
212081ad6265SDimitry Andric // Note: Currently DFSan instrumentation does not run on this code, so
212181ad6265SDimitry Andric // the builtin may need to be handled outside DFSan instrumentation.
212281ad6265SDimitry Andric dfsan_set_arg_tls(0, fd_label);
212381ad6265SDimitry Andric dfsan_set_arg_tls(1, buf_label);
212481ad6265SDimitry Andric dfsan_set_arg_tls(2, count_label);
212581ad6265SDimitry Andric if (origins) {
212681ad6265SDimitry Andric dfsan_set_arg_origin_tls(0, fd_origin);
212781ad6265SDimitry Andric dfsan_set_arg_origin_tls(1, buf_origin);
212881ad6265SDimitry Andric dfsan_set_arg_origin_tls(2, count_origin);
212981ad6265SDimitry Andric }
2130fe6060f1SDimitry Andric }
2131fe6060f1SDimitry Andric
213268d75effSDimitry Andric 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)213368d75effSDimitry Andric __dfsw_write(int fd, const void *buf, size_t count,
213468d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label,
213568d75effSDimitry Andric dfsan_label count_label, dfsan_label *ret_label) {
213668d75effSDimitry Andric if (write_callback_info.write_callback) {
213781ad6265SDimitry Andric setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
213881ad6265SDimitry Andric 0, 0, 0);
213981ad6265SDimitry Andric write_callback_info.write_callback(fd, buf, count);
214068d75effSDimitry Andric }
214168d75effSDimitry Andric
214268d75effSDimitry Andric *ret_label = 0;
214368d75effSDimitry Andric return write(fd, buf, count);
214468d75effSDimitry Andric }
2145fe6060f1SDimitry Andric
__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)2146fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
2147fe6060f1SDimitry Andric int fd, const void *buf, size_t count, dfsan_label fd_label,
2148fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
2149fe6060f1SDimitry Andric dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
2150fe6060f1SDimitry Andric dfsan_origin *ret_origin) {
215181ad6265SDimitry Andric if (write_callback_info.write_callback) {
215281ad6265SDimitry Andric setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
215381ad6265SDimitry Andric fd_origin, buf_origin, count_origin);
215481ad6265SDimitry Andric write_callback_info.write_callback(fd, buf, count);
2155fe6060f1SDimitry Andric }
2156fe6060f1SDimitry Andric
2157fe6060f1SDimitry Andric *ret_label = 0;
2158fe6060f1SDimitry Andric return write(fd, buf, count);
2159fe6060f1SDimitry Andric }
216068d75effSDimitry Andric } // namespace __dfsan
216168d75effSDimitry Andric
216268d75effSDimitry Andric // Type used to extract a dfsan_label with va_arg()
216368d75effSDimitry Andric typedef int dfsan_label_va;
216468d75effSDimitry Andric
216568d75effSDimitry Andric // Formats a chunk either a constant string or a single format directive (e.g.,
216668d75effSDimitry Andric // '%.3f').
216768d75effSDimitry Andric struct Formatter {
FormatterFormatter216868d75effSDimitry Andric Formatter(char *str_, const char *fmt_, size_t size_)
21695f757f3fSDimitry Andric : str(str_),
21705f757f3fSDimitry Andric str_off(0),
21715f757f3fSDimitry Andric size(size_),
21725f757f3fSDimitry Andric fmt_start(fmt_),
21735f757f3fSDimitry Andric fmt_cur(fmt_),
21745f757f3fSDimitry Andric width(-1),
21755f757f3fSDimitry Andric num_scanned(-1),
21765f757f3fSDimitry Andric skip(false) {}
217768d75effSDimitry Andric
formatFormatter217868d75effSDimitry Andric int format() {
217968d75effSDimitry Andric char *tmp_fmt = build_format_string();
218068d75effSDimitry Andric int retval =
218168d75effSDimitry Andric snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
218268d75effSDimitry Andric 0 /* used only to avoid warnings */);
218368d75effSDimitry Andric free(tmp_fmt);
218468d75effSDimitry Andric return retval;
218568d75effSDimitry Andric }
218668d75effSDimitry Andric
formatFormatter218768d75effSDimitry Andric template <typename T> int format(T arg) {
218868d75effSDimitry Andric char *tmp_fmt = build_format_string();
218968d75effSDimitry Andric int retval;
219068d75effSDimitry Andric if (width >= 0) {
219168d75effSDimitry Andric retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
219268d75effSDimitry Andric tmp_fmt, width, arg);
219368d75effSDimitry Andric } else {
219468d75effSDimitry Andric retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
219568d75effSDimitry Andric tmp_fmt, arg);
219668d75effSDimitry Andric }
219768d75effSDimitry Andric free(tmp_fmt);
219868d75effSDimitry Andric return retval;
219968d75effSDimitry Andric }
220068d75effSDimitry Andric
build_format_stringFormatter2201*0fca6ea1SDimitry Andric char *build_format_string() {
220268d75effSDimitry Andric size_t fmt_size = fmt_cur - fmt_start + 1;
2203*0fca6ea1SDimitry Andric char *new_fmt = (char *)malloc(fmt_size + 1);
220468d75effSDimitry Andric assert(new_fmt);
220568d75effSDimitry Andric internal_memcpy(new_fmt, fmt_start, fmt_size);
220668d75effSDimitry Andric new_fmt[fmt_size] = '\0';
220768d75effSDimitry Andric return new_fmt;
220868d75effSDimitry Andric }
220968d75effSDimitry Andric
str_curFormatter221068d75effSDimitry Andric char *str_cur() { return str + str_off; }
221168d75effSDimitry Andric
num_written_bytesFormatter221268d75effSDimitry Andric size_t num_written_bytes(int retval) {
221368d75effSDimitry Andric if (retval < 0) {
221468d75effSDimitry Andric return 0;
221568d75effSDimitry Andric }
221668d75effSDimitry Andric
221768d75effSDimitry Andric size_t num_avail = str_off < size ? size - str_off : 0;
221868d75effSDimitry Andric if (num_avail == 0) {
221968d75effSDimitry Andric return 0;
222068d75effSDimitry Andric }
222168d75effSDimitry Andric
222268d75effSDimitry Andric size_t num_written = retval;
222368d75effSDimitry Andric // A return value of {v,}snprintf of size or more means that the output was
222468d75effSDimitry Andric // truncated.
222568d75effSDimitry Andric if (num_written >= num_avail) {
222668d75effSDimitry Andric num_written -= num_avail;
222768d75effSDimitry Andric }
222868d75effSDimitry Andric
222968d75effSDimitry Andric return num_written;
223068d75effSDimitry Andric }
223168d75effSDimitry Andric
223268d75effSDimitry Andric char *str;
223368d75effSDimitry Andric size_t str_off;
223468d75effSDimitry Andric size_t size;
223568d75effSDimitry Andric const char *fmt_start;
223668d75effSDimitry Andric const char *fmt_cur;
223768d75effSDimitry Andric int width;
22385f757f3fSDimitry Andric int num_scanned;
22395f757f3fSDimitry Andric bool skip;
224068d75effSDimitry Andric };
224168d75effSDimitry Andric
224268d75effSDimitry Andric // Formats the input and propagates the input labels to the output. The output
224368d75effSDimitry Andric // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
224468d75effSDimitry Andric // 'ap' are the format string and the list of arguments for formatting. Returns
224568d75effSDimitry Andric // the return value vsnprintf would return.
224668d75effSDimitry Andric //
224768d75effSDimitry Andric // The function tokenizes the format string in chunks representing either a
224868d75effSDimitry Andric // constant string or a single format directive (e.g., '%.3f') and formats each
224968d75effSDimitry Andric // chunk independently into the output string. This approach allows to figure
225068d75effSDimitry Andric // out which bytes of the output string depends on which argument and thus to
225168d75effSDimitry Andric // propagate labels more precisely.
225268d75effSDimitry Andric //
225368d75effSDimitry Andric // WARNING: This implementation does not support conversion specifiers with
225468d75effSDimitry Andric // 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)225568d75effSDimitry Andric static int format_buffer(char *str, size_t size, const char *fmt,
225668d75effSDimitry Andric dfsan_label *va_labels, dfsan_label *ret_label,
2257fe6060f1SDimitry Andric dfsan_origin *va_origins, dfsan_origin *ret_origin,
225868d75effSDimitry Andric va_list ap) {
225968d75effSDimitry Andric Formatter formatter(str, fmt, size);
226068d75effSDimitry Andric
226168d75effSDimitry Andric while (*formatter.fmt_cur) {
226268d75effSDimitry Andric formatter.fmt_start = formatter.fmt_cur;
226368d75effSDimitry Andric formatter.width = -1;
226468d75effSDimitry Andric int retval = 0;
226568d75effSDimitry Andric
226668d75effSDimitry Andric if (*formatter.fmt_cur != '%') {
226768d75effSDimitry Andric // Ordinary character. Consume all the characters until a '%' or the end
226868d75effSDimitry Andric // of the string.
226968d75effSDimitry Andric for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
227068d75effSDimitry Andric ++formatter.fmt_cur) {}
227168d75effSDimitry Andric retval = formatter.format();
227268d75effSDimitry Andric dfsan_set_label(0, formatter.str_cur(),
227368d75effSDimitry Andric formatter.num_written_bytes(retval));
227468d75effSDimitry Andric } else {
227568d75effSDimitry Andric // Conversion directive. Consume all the characters until a conversion
227668d75effSDimitry Andric // specifier or the end of the string.
227768d75effSDimitry Andric bool end_fmt = false;
227868d75effSDimitry Andric for (; *formatter.fmt_cur && !end_fmt; ) {
227968d75effSDimitry Andric switch (*++formatter.fmt_cur) {
228068d75effSDimitry Andric case 'd':
228168d75effSDimitry Andric case 'i':
228268d75effSDimitry Andric case 'o':
228368d75effSDimitry Andric case 'u':
228468d75effSDimitry Andric case 'x':
228568d75effSDimitry Andric case 'X':
228668d75effSDimitry Andric switch (*(formatter.fmt_cur - 1)) {
228768d75effSDimitry Andric case 'h':
228868d75effSDimitry Andric // Also covers the 'hh' case (since the size of the arg is still
228968d75effSDimitry Andric // an int).
229068d75effSDimitry Andric retval = formatter.format(va_arg(ap, int));
229168d75effSDimitry Andric break;
229268d75effSDimitry Andric case 'l':
229368d75effSDimitry Andric if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
229468d75effSDimitry Andric *(formatter.fmt_cur - 2) == 'l') {
229568d75effSDimitry Andric retval = formatter.format(va_arg(ap, long long int));
229668d75effSDimitry Andric } else {
229768d75effSDimitry Andric retval = formatter.format(va_arg(ap, long int));
229868d75effSDimitry Andric }
229968d75effSDimitry Andric break;
230068d75effSDimitry Andric case 'q':
230168d75effSDimitry Andric retval = formatter.format(va_arg(ap, long long int));
230268d75effSDimitry Andric break;
230368d75effSDimitry Andric case 'j':
230468d75effSDimitry Andric retval = formatter.format(va_arg(ap, intmax_t));
230568d75effSDimitry Andric break;
230668d75effSDimitry Andric case 'z':
230768d75effSDimitry Andric case 't':
230868d75effSDimitry Andric retval = formatter.format(va_arg(ap, size_t));
230968d75effSDimitry Andric break;
231068d75effSDimitry Andric default:
231168d75effSDimitry Andric retval = formatter.format(va_arg(ap, int));
231268d75effSDimitry Andric }
2313fe6060f1SDimitry Andric if (va_origins == nullptr)
231468d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(),
231568d75effSDimitry Andric formatter.num_written_bytes(retval));
2316fe6060f1SDimitry Andric else
2317fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++,
2318fe6060f1SDimitry Andric formatter.str_cur(),
2319fe6060f1SDimitry Andric formatter.num_written_bytes(retval));
232068d75effSDimitry Andric end_fmt = true;
232168d75effSDimitry Andric break;
232268d75effSDimitry Andric
232368d75effSDimitry Andric case 'a':
232468d75effSDimitry Andric case 'A':
232568d75effSDimitry Andric case 'e':
232668d75effSDimitry Andric case 'E':
232768d75effSDimitry Andric case 'f':
232868d75effSDimitry Andric case 'F':
232968d75effSDimitry Andric case 'g':
233068d75effSDimitry Andric case 'G':
233168d75effSDimitry Andric if (*(formatter.fmt_cur - 1) == 'L') {
233268d75effSDimitry Andric retval = formatter.format(va_arg(ap, long double));
233368d75effSDimitry Andric } else {
233468d75effSDimitry Andric retval = formatter.format(va_arg(ap, double));
233568d75effSDimitry Andric }
2336fe6060f1SDimitry Andric if (va_origins == nullptr)
233768d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(),
233868d75effSDimitry Andric formatter.num_written_bytes(retval));
2339fe6060f1SDimitry Andric else
2340fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++,
2341fe6060f1SDimitry Andric formatter.str_cur(),
2342fe6060f1SDimitry Andric formatter.num_written_bytes(retval));
234368d75effSDimitry Andric end_fmt = true;
234468d75effSDimitry Andric break;
234568d75effSDimitry Andric
234668d75effSDimitry Andric case 'c':
234768d75effSDimitry Andric retval = formatter.format(va_arg(ap, int));
2348fe6060f1SDimitry Andric if (va_origins == nullptr)
234968d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(),
235068d75effSDimitry Andric formatter.num_written_bytes(retval));
2351fe6060f1SDimitry Andric else
2352fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++,
2353fe6060f1SDimitry Andric formatter.str_cur(),
2354fe6060f1SDimitry Andric formatter.num_written_bytes(retval));
235568d75effSDimitry Andric end_fmt = true;
235668d75effSDimitry Andric break;
235768d75effSDimitry Andric
235868d75effSDimitry Andric case 's': {
235968d75effSDimitry Andric char *arg = va_arg(ap, char *);
236068d75effSDimitry Andric retval = formatter.format(arg);
2361fe6060f1SDimitry Andric if (va_origins) {
2362fe6060f1SDimitry Andric va_origins++;
2363fe6060f1SDimitry Andric dfsan_mem_origin_transfer(formatter.str_cur(), arg,
2364fe6060f1SDimitry Andric formatter.num_written_bytes(retval));
2365fe6060f1SDimitry Andric }
236668d75effSDimitry Andric va_labels++;
236704eeddc0SDimitry Andric dfsan_mem_shadow_transfer(formatter.str_cur(), arg,
236868d75effSDimitry Andric formatter.num_written_bytes(retval));
236968d75effSDimitry Andric end_fmt = true;
237068d75effSDimitry Andric break;
237168d75effSDimitry Andric }
237268d75effSDimitry Andric
237368d75effSDimitry Andric case 'p':
237468d75effSDimitry Andric retval = formatter.format(va_arg(ap, void *));
2375fe6060f1SDimitry Andric if (va_origins == nullptr)
237668d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(),
237768d75effSDimitry Andric formatter.num_written_bytes(retval));
2378fe6060f1SDimitry Andric else
2379fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++,
2380fe6060f1SDimitry Andric formatter.str_cur(),
2381fe6060f1SDimitry Andric formatter.num_written_bytes(retval));
238268d75effSDimitry Andric end_fmt = true;
238368d75effSDimitry Andric break;
238468d75effSDimitry Andric
238568d75effSDimitry Andric case 'n': {
238668d75effSDimitry Andric int *ptr = va_arg(ap, int *);
238768d75effSDimitry Andric *ptr = (int)formatter.str_off;
238868d75effSDimitry Andric va_labels++;
2389fe6060f1SDimitry Andric if (va_origins)
2390fe6060f1SDimitry Andric va_origins++;
239168d75effSDimitry Andric dfsan_set_label(0, ptr, sizeof(ptr));
239268d75effSDimitry Andric end_fmt = true;
239368d75effSDimitry Andric break;
239468d75effSDimitry Andric }
239568d75effSDimitry Andric
239668d75effSDimitry Andric case '%':
239768d75effSDimitry Andric retval = formatter.format();
239868d75effSDimitry Andric dfsan_set_label(0, formatter.str_cur(),
239968d75effSDimitry Andric formatter.num_written_bytes(retval));
240068d75effSDimitry Andric end_fmt = true;
240168d75effSDimitry Andric break;
240268d75effSDimitry Andric
240368d75effSDimitry Andric case '*':
240468d75effSDimitry Andric formatter.width = va_arg(ap, int);
240568d75effSDimitry Andric va_labels++;
2406fe6060f1SDimitry Andric if (va_origins)
2407fe6060f1SDimitry Andric va_origins++;
240868d75effSDimitry Andric break;
240968d75effSDimitry Andric
241068d75effSDimitry Andric default:
241168d75effSDimitry Andric break;
241268d75effSDimitry Andric }
241368d75effSDimitry Andric }
241468d75effSDimitry Andric }
241568d75effSDimitry Andric
241668d75effSDimitry Andric if (retval < 0) {
241768d75effSDimitry Andric return retval;
241868d75effSDimitry Andric }
241968d75effSDimitry Andric
242068d75effSDimitry Andric formatter.fmt_cur++;
242168d75effSDimitry Andric formatter.str_off += retval;
242268d75effSDimitry Andric }
242368d75effSDimitry Andric
242468d75effSDimitry Andric *ret_label = 0;
2425fe6060f1SDimitry Andric if (ret_origin)
2426fe6060f1SDimitry Andric *ret_origin = 0;
242768d75effSDimitry Andric
242868d75effSDimitry Andric // Number of bytes written in total.
242968d75effSDimitry Andric return formatter.str_off;
243068d75effSDimitry Andric }
243168d75effSDimitry Andric
2432*0fca6ea1SDimitry Andric // Scans a chunk either a constant string or a single format directive (e.g.,
2433*0fca6ea1SDimitry Andric // '%.3f').
2434*0fca6ea1SDimitry Andric struct Scanner {
ScannerScanner2435*0fca6ea1SDimitry Andric Scanner(char *str_, const char *fmt_, size_t size_)
2436*0fca6ea1SDimitry Andric : str(str_),
2437*0fca6ea1SDimitry Andric str_off(0),
2438*0fca6ea1SDimitry Andric size(size_),
2439*0fca6ea1SDimitry Andric fmt_start(fmt_),
2440*0fca6ea1SDimitry Andric fmt_cur(fmt_),
2441*0fca6ea1SDimitry Andric width(-1),
2442*0fca6ea1SDimitry Andric num_scanned(0),
2443*0fca6ea1SDimitry Andric skip(false) {}
2444*0fca6ea1SDimitry Andric
2445*0fca6ea1SDimitry Andric // Consumes a chunk of ordinary characters.
2446*0fca6ea1SDimitry Andric // Returns number of matching ordinary characters.
2447*0fca6ea1SDimitry Andric // Returns -1 if the match failed.
2448*0fca6ea1SDimitry Andric // In format strings, a space will match multiple spaces.
check_match_ordinaryScanner2449*0fca6ea1SDimitry Andric int check_match_ordinary() {
2450*0fca6ea1SDimitry Andric char *tmp_fmt = build_format_string_with_n();
2451*0fca6ea1SDimitry Andric int read_count = -1;
2452*0fca6ea1SDimitry Andric sscanf(str + str_off, tmp_fmt, &read_count);
2453*0fca6ea1SDimitry Andric free(tmp_fmt);
2454*0fca6ea1SDimitry Andric if (read_count > 0) {
2455*0fca6ea1SDimitry Andric str_off += read_count;
2456*0fca6ea1SDimitry Andric }
2457*0fca6ea1SDimitry Andric return read_count;
2458*0fca6ea1SDimitry Andric }
2459*0fca6ea1SDimitry Andric
scanScanner2460*0fca6ea1SDimitry Andric int scan() {
2461*0fca6ea1SDimitry Andric char *tmp_fmt = build_format_string_with_n();
2462*0fca6ea1SDimitry Andric int read_count = 0;
2463*0fca6ea1SDimitry Andric int retval = sscanf(str + str_off, tmp_fmt, &read_count);
2464*0fca6ea1SDimitry Andric free(tmp_fmt);
2465*0fca6ea1SDimitry Andric if (retval > 0) {
2466*0fca6ea1SDimitry Andric num_scanned += retval;
2467*0fca6ea1SDimitry Andric }
2468*0fca6ea1SDimitry Andric return read_count;
2469*0fca6ea1SDimitry Andric }
2470*0fca6ea1SDimitry Andric
2471*0fca6ea1SDimitry Andric template <typename T>
scanScanner2472*0fca6ea1SDimitry Andric int scan(T arg) {
2473*0fca6ea1SDimitry Andric char *tmp_fmt = build_format_string_with_n();
2474*0fca6ea1SDimitry Andric int read_count = 0;
2475*0fca6ea1SDimitry Andric int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count);
2476*0fca6ea1SDimitry Andric free(tmp_fmt);
2477*0fca6ea1SDimitry Andric if (retval > 0) {
2478*0fca6ea1SDimitry Andric num_scanned += retval;
2479*0fca6ea1SDimitry Andric }
2480*0fca6ea1SDimitry Andric return read_count;
2481*0fca6ea1SDimitry Andric }
2482*0fca6ea1SDimitry Andric
2483*0fca6ea1SDimitry Andric // Adds %n onto current format string to measure length.
build_format_string_with_nScanner2484*0fca6ea1SDimitry Andric char *build_format_string_with_n() {
2485*0fca6ea1SDimitry Andric size_t fmt_size = fmt_cur - fmt_start + 1;
2486*0fca6ea1SDimitry Andric // +2 for %n, +1 for \0
2487*0fca6ea1SDimitry Andric char *new_fmt = (char *)malloc(fmt_size + 2 + 1);
2488*0fca6ea1SDimitry Andric assert(new_fmt);
2489*0fca6ea1SDimitry Andric internal_memcpy(new_fmt, fmt_start, fmt_size);
2490*0fca6ea1SDimitry Andric new_fmt[fmt_size] = '%';
2491*0fca6ea1SDimitry Andric new_fmt[fmt_size + 1] = 'n';
2492*0fca6ea1SDimitry Andric new_fmt[fmt_size + 2] = '\0';
2493*0fca6ea1SDimitry Andric return new_fmt;
2494*0fca6ea1SDimitry Andric }
2495*0fca6ea1SDimitry Andric
str_curScanner2496*0fca6ea1SDimitry Andric char *str_cur() { return str + str_off; }
2497*0fca6ea1SDimitry Andric
num_written_bytesScanner2498*0fca6ea1SDimitry Andric size_t num_written_bytes(int retval) {
2499*0fca6ea1SDimitry Andric if (retval < 0) {
2500*0fca6ea1SDimitry Andric return 0;
2501*0fca6ea1SDimitry Andric }
2502*0fca6ea1SDimitry Andric
2503*0fca6ea1SDimitry Andric size_t num_avail = str_off < size ? size - str_off : 0;
2504*0fca6ea1SDimitry Andric if (num_avail == 0) {
2505*0fca6ea1SDimitry Andric return 0;
2506*0fca6ea1SDimitry Andric }
2507*0fca6ea1SDimitry Andric
2508*0fca6ea1SDimitry Andric size_t num_written = retval;
2509*0fca6ea1SDimitry Andric // A return value of {v,}snprintf of size or more means that the output was
2510*0fca6ea1SDimitry Andric // truncated.
2511*0fca6ea1SDimitry Andric if (num_written >= num_avail) {
2512*0fca6ea1SDimitry Andric num_written -= num_avail;
2513*0fca6ea1SDimitry Andric }
2514*0fca6ea1SDimitry Andric
2515*0fca6ea1SDimitry Andric return num_written;
2516*0fca6ea1SDimitry Andric }
2517*0fca6ea1SDimitry Andric
2518*0fca6ea1SDimitry Andric char *str;
2519*0fca6ea1SDimitry Andric size_t str_off;
2520*0fca6ea1SDimitry Andric size_t size;
2521*0fca6ea1SDimitry Andric const char *fmt_start;
2522*0fca6ea1SDimitry Andric const char *fmt_cur;
2523*0fca6ea1SDimitry Andric int width;
2524*0fca6ea1SDimitry Andric int num_scanned;
2525*0fca6ea1SDimitry Andric bool skip;
2526*0fca6ea1SDimitry Andric };
2527*0fca6ea1SDimitry Andric
25285f757f3fSDimitry Andric // This function is an inverse of format_buffer: we take the input buffer,
25295f757f3fSDimitry Andric // scan it in search for format strings and store the results in the varargs.
25305f757f3fSDimitry Andric // The labels are propagated from the input buffer to the varargs.
scan_buffer(char * str,size_t size,const char * fmt,dfsan_label * va_labels,dfsan_label * ret_label,dfsan_origin * str_origin,dfsan_origin * ret_origin,va_list ap)25315f757f3fSDimitry Andric static int scan_buffer(char *str, size_t size, const char *fmt,
25325f757f3fSDimitry Andric dfsan_label *va_labels, dfsan_label *ret_label,
25335f757f3fSDimitry Andric dfsan_origin *str_origin, dfsan_origin *ret_origin,
25345f757f3fSDimitry Andric va_list ap) {
2535*0fca6ea1SDimitry Andric Scanner scanner(str, fmt, size);
2536*0fca6ea1SDimitry Andric while (*scanner.fmt_cur) {
2537*0fca6ea1SDimitry Andric scanner.fmt_start = scanner.fmt_cur;
2538*0fca6ea1SDimitry Andric scanner.width = -1;
2539*0fca6ea1SDimitry Andric scanner.skip = false;
25405f757f3fSDimitry Andric int read_count = 0;
25415f757f3fSDimitry Andric void *dst_ptr = 0;
25425f757f3fSDimitry Andric size_t write_size = 0;
2543*0fca6ea1SDimitry Andric if (*scanner.fmt_cur != '%') {
2544*0fca6ea1SDimitry Andric // Ordinary character and spaces.
2545*0fca6ea1SDimitry Andric // Consume all the characters until a '%' or the end of the string.
2546*0fca6ea1SDimitry Andric for (; *(scanner.fmt_cur + 1) && *(scanner.fmt_cur + 1) != '%';
2547*0fca6ea1SDimitry Andric ++scanner.fmt_cur) {
25485f757f3fSDimitry Andric }
2549*0fca6ea1SDimitry Andric if (scanner.check_match_ordinary() < 0) {
2550*0fca6ea1SDimitry Andric // The ordinary characters did not match.
2551*0fca6ea1SDimitry Andric break;
2552*0fca6ea1SDimitry Andric }
25535f757f3fSDimitry Andric } else {
25545f757f3fSDimitry Andric // Conversion directive. Consume all the characters until a conversion
25555f757f3fSDimitry Andric // specifier or the end of the string.
25565f757f3fSDimitry Andric bool end_fmt = false;
2557*0fca6ea1SDimitry Andric for (; *scanner.fmt_cur && !end_fmt;) {
2558*0fca6ea1SDimitry Andric switch (*++scanner.fmt_cur) {
25595f757f3fSDimitry Andric case 'd':
25605f757f3fSDimitry Andric case 'i':
25615f757f3fSDimitry Andric case 'o':
25625f757f3fSDimitry Andric case 'u':
25635f757f3fSDimitry Andric case 'x':
25645f757f3fSDimitry Andric case 'X':
2565*0fca6ea1SDimitry Andric if (scanner.skip) {
2566*0fca6ea1SDimitry Andric read_count = scanner.scan();
25675f757f3fSDimitry Andric } else {
2568*0fca6ea1SDimitry Andric switch (*(scanner.fmt_cur - 1)) {
25695f757f3fSDimitry Andric case 'h':
2570*0fca6ea1SDimitry Andric // Also covers the 'hh' case (since the size of the arg is
2571*0fca6ea1SDimitry Andric // still an int).
25725f757f3fSDimitry Andric dst_ptr = va_arg(ap, int *);
2573*0fca6ea1SDimitry Andric read_count = scanner.scan((int *)dst_ptr);
25745f757f3fSDimitry Andric write_size = sizeof(int);
25755f757f3fSDimitry Andric break;
25765f757f3fSDimitry Andric case 'l':
2577*0fca6ea1SDimitry Andric if (scanner.fmt_cur - scanner.fmt_start >= 2 &&
2578*0fca6ea1SDimitry Andric *(scanner.fmt_cur - 2) == 'l') {
25795f757f3fSDimitry Andric dst_ptr = va_arg(ap, long long int *);
2580*0fca6ea1SDimitry Andric read_count = scanner.scan((long long int *)dst_ptr);
25815f757f3fSDimitry Andric write_size = sizeof(long long int);
25825f757f3fSDimitry Andric } else {
25835f757f3fSDimitry Andric dst_ptr = va_arg(ap, long int *);
2584*0fca6ea1SDimitry Andric read_count = scanner.scan((long int *)dst_ptr);
25855f757f3fSDimitry Andric write_size = sizeof(long int);
25865f757f3fSDimitry Andric }
25875f757f3fSDimitry Andric break;
25885f757f3fSDimitry Andric case 'q':
25895f757f3fSDimitry Andric dst_ptr = va_arg(ap, long long int *);
2590*0fca6ea1SDimitry Andric read_count = scanner.scan((long long int *)dst_ptr);
25915f757f3fSDimitry Andric write_size = sizeof(long long int);
25925f757f3fSDimitry Andric break;
25935f757f3fSDimitry Andric case 'j':
25945f757f3fSDimitry Andric dst_ptr = va_arg(ap, intmax_t *);
2595*0fca6ea1SDimitry Andric read_count = scanner.scan((intmax_t *)dst_ptr);
25965f757f3fSDimitry Andric write_size = sizeof(intmax_t);
25975f757f3fSDimitry Andric break;
25985f757f3fSDimitry Andric case 'z':
25995f757f3fSDimitry Andric case 't':
26005f757f3fSDimitry Andric dst_ptr = va_arg(ap, size_t *);
2601*0fca6ea1SDimitry Andric read_count = scanner.scan((size_t *)dst_ptr);
26025f757f3fSDimitry Andric write_size = sizeof(size_t);
26035f757f3fSDimitry Andric break;
26045f757f3fSDimitry Andric default:
26055f757f3fSDimitry Andric dst_ptr = va_arg(ap, int *);
2606*0fca6ea1SDimitry Andric read_count = scanner.scan((int *)dst_ptr);
26075f757f3fSDimitry Andric write_size = sizeof(int);
26085f757f3fSDimitry Andric }
26095f757f3fSDimitry Andric // get the label associated with the string at the corresponding
26105f757f3fSDimitry Andric // place
26115f757f3fSDimitry Andric dfsan_label l = dfsan_read_label(
2612*0fca6ea1SDimitry Andric scanner.str_cur(), scanner.num_written_bytes(read_count));
26135f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
26145f757f3fSDimitry Andric if (str_origin != nullptr) {
26155f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
2616*0fca6ea1SDimitry Andric size_t scan_count = scanner.num_written_bytes(read_count);
26175f757f3fSDimitry Andric size_t size = scan_count > write_size ? write_size : scan_count;
2618*0fca6ea1SDimitry Andric dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
26195f757f3fSDimitry Andric }
26205f757f3fSDimitry Andric }
26215f757f3fSDimitry Andric end_fmt = true;
26225f757f3fSDimitry Andric
26235f757f3fSDimitry Andric break;
26245f757f3fSDimitry Andric
26255f757f3fSDimitry Andric case 'a':
26265f757f3fSDimitry Andric case 'A':
26275f757f3fSDimitry Andric case 'e':
26285f757f3fSDimitry Andric case 'E':
26295f757f3fSDimitry Andric case 'f':
26305f757f3fSDimitry Andric case 'F':
26315f757f3fSDimitry Andric case 'g':
26325f757f3fSDimitry Andric case 'G':
2633*0fca6ea1SDimitry Andric if (scanner.skip) {
2634*0fca6ea1SDimitry Andric read_count = scanner.scan();
26355f757f3fSDimitry Andric } else {
2636*0fca6ea1SDimitry Andric if (*(scanner.fmt_cur - 1) == 'L') {
26375f757f3fSDimitry Andric dst_ptr = va_arg(ap, long double *);
2638*0fca6ea1SDimitry Andric read_count = scanner.scan((long double *)dst_ptr);
26395f757f3fSDimitry Andric write_size = sizeof(long double);
2640*0fca6ea1SDimitry Andric } else if (*(scanner.fmt_cur - 1) == 'l') {
26415f757f3fSDimitry Andric dst_ptr = va_arg(ap, double *);
2642*0fca6ea1SDimitry Andric read_count = scanner.scan((double *)dst_ptr);
26435f757f3fSDimitry Andric write_size = sizeof(double);
26445f757f3fSDimitry Andric } else {
26455f757f3fSDimitry Andric dst_ptr = va_arg(ap, float *);
2646*0fca6ea1SDimitry Andric read_count = scanner.scan((float *)dst_ptr);
26475f757f3fSDimitry Andric write_size = sizeof(float);
26485f757f3fSDimitry Andric }
26495f757f3fSDimitry Andric dfsan_label l = dfsan_read_label(
2650*0fca6ea1SDimitry Andric scanner.str_cur(), scanner.num_written_bytes(read_count));
26515f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
26525f757f3fSDimitry Andric if (str_origin != nullptr) {
26535f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
2654*0fca6ea1SDimitry Andric size_t scan_count = scanner.num_written_bytes(read_count);
26555f757f3fSDimitry Andric size_t size = scan_count > write_size ? write_size : scan_count;
2656*0fca6ea1SDimitry Andric dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
26575f757f3fSDimitry Andric }
26585f757f3fSDimitry Andric }
26595f757f3fSDimitry Andric end_fmt = true;
26605f757f3fSDimitry Andric break;
26615f757f3fSDimitry Andric
26625f757f3fSDimitry Andric case 'c':
2663*0fca6ea1SDimitry Andric if (scanner.skip) {
2664*0fca6ea1SDimitry Andric read_count = scanner.scan();
26655f757f3fSDimitry Andric } else {
26665f757f3fSDimitry Andric dst_ptr = va_arg(ap, char *);
2667*0fca6ea1SDimitry Andric read_count = scanner.scan((char *)dst_ptr);
26685f757f3fSDimitry Andric write_size = sizeof(char);
26695f757f3fSDimitry Andric dfsan_label l = dfsan_read_label(
2670*0fca6ea1SDimitry Andric scanner.str_cur(), scanner.num_written_bytes(read_count));
26715f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
26725f757f3fSDimitry Andric if (str_origin != nullptr) {
2673*0fca6ea1SDimitry Andric size_t scan_count = scanner.num_written_bytes(read_count);
26745f757f3fSDimitry Andric size_t size = scan_count > write_size ? write_size : scan_count;
2675*0fca6ea1SDimitry Andric dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
26765f757f3fSDimitry Andric }
26775f757f3fSDimitry Andric }
26785f757f3fSDimitry Andric end_fmt = true;
26795f757f3fSDimitry Andric break;
26805f757f3fSDimitry Andric
26815f757f3fSDimitry Andric case 's': {
2682*0fca6ea1SDimitry Andric if (scanner.skip) {
2683*0fca6ea1SDimitry Andric read_count = scanner.scan();
26845f757f3fSDimitry Andric } else {
26855f757f3fSDimitry Andric dst_ptr = va_arg(ap, char *);
2686*0fca6ea1SDimitry Andric read_count = scanner.scan((char *)dst_ptr);
26875f757f3fSDimitry Andric if (1 == read_count) {
26885f757f3fSDimitry Andric // special case: we have parsed a single string and we need to
26895f757f3fSDimitry Andric // update read_count with the string size
26905f757f3fSDimitry Andric read_count = strlen((char *)dst_ptr);
26915f757f3fSDimitry Andric }
26925f757f3fSDimitry Andric if (str_origin)
2693*0fca6ea1SDimitry Andric dfsan_mem_origin_transfer(
2694*0fca6ea1SDimitry Andric dst_ptr, scanner.str_cur(),
2695*0fca6ea1SDimitry Andric scanner.num_written_bytes(read_count));
26965f757f3fSDimitry Andric va_labels++;
2697*0fca6ea1SDimitry Andric dfsan_mem_shadow_transfer(dst_ptr, scanner.str_cur(),
2698*0fca6ea1SDimitry Andric scanner.num_written_bytes(read_count));
26995f757f3fSDimitry Andric }
27005f757f3fSDimitry Andric end_fmt = true;
27015f757f3fSDimitry Andric break;
27025f757f3fSDimitry Andric }
27035f757f3fSDimitry Andric
27045f757f3fSDimitry Andric case 'p':
2705*0fca6ea1SDimitry Andric if (scanner.skip) {
2706*0fca6ea1SDimitry Andric read_count = scanner.scan();
27075f757f3fSDimitry Andric } else {
27085f757f3fSDimitry Andric dst_ptr = va_arg(ap, void *);
27095f757f3fSDimitry Andric read_count =
2710*0fca6ea1SDimitry Andric scanner.scan((int *)dst_ptr); // note: changing void* to int*
27115f757f3fSDimitry Andric // since we need to call sizeof
27125f757f3fSDimitry Andric write_size = sizeof(int);
27135f757f3fSDimitry Andric
27145f757f3fSDimitry Andric dfsan_label l = dfsan_read_label(
2715*0fca6ea1SDimitry Andric scanner.str_cur(), scanner.num_written_bytes(read_count));
27165f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
27175f757f3fSDimitry Andric if (str_origin != nullptr) {
27185f757f3fSDimitry Andric dfsan_set_label(l, dst_ptr, write_size);
2719*0fca6ea1SDimitry Andric size_t scan_count = scanner.num_written_bytes(read_count);
27205f757f3fSDimitry Andric size_t size = scan_count > write_size ? write_size : scan_count;
2721*0fca6ea1SDimitry Andric dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);
27225f757f3fSDimitry Andric }
27235f757f3fSDimitry Andric }
27245f757f3fSDimitry Andric end_fmt = true;
27255f757f3fSDimitry Andric break;
27265f757f3fSDimitry Andric
27275f757f3fSDimitry Andric case 'n': {
2728*0fca6ea1SDimitry Andric if (!scanner.skip) {
27295f757f3fSDimitry Andric int *ptr = va_arg(ap, int *);
2730*0fca6ea1SDimitry Andric *ptr = (int)scanner.str_off;
27315f757f3fSDimitry Andric *va_labels++ = 0;
27325f757f3fSDimitry Andric dfsan_set_label(0, ptr, sizeof(*ptr));
27335f757f3fSDimitry Andric if (str_origin != nullptr)
27345f757f3fSDimitry Andric *str_origin++ = 0;
27355f757f3fSDimitry Andric }
27365f757f3fSDimitry Andric end_fmt = true;
27375f757f3fSDimitry Andric break;
27385f757f3fSDimitry Andric }
27395f757f3fSDimitry Andric
27405f757f3fSDimitry Andric case '%':
2741*0fca6ea1SDimitry Andric read_count = scanner.scan();
27425f757f3fSDimitry Andric end_fmt = true;
27435f757f3fSDimitry Andric break;
27445f757f3fSDimitry Andric
27455f757f3fSDimitry Andric case '*':
2746*0fca6ea1SDimitry Andric scanner.skip = true;
27475f757f3fSDimitry Andric break;
27485f757f3fSDimitry Andric
27495f757f3fSDimitry Andric default:
27505f757f3fSDimitry Andric break;
27515f757f3fSDimitry Andric }
27525f757f3fSDimitry Andric }
27535f757f3fSDimitry Andric }
27545f757f3fSDimitry Andric
27555f757f3fSDimitry Andric if (read_count < 0) {
27565f757f3fSDimitry Andric // There was an error.
27575f757f3fSDimitry Andric return read_count;
27585f757f3fSDimitry Andric }
27595f757f3fSDimitry Andric
2760*0fca6ea1SDimitry Andric scanner.fmt_cur++;
2761*0fca6ea1SDimitry Andric scanner.str_off += read_count;
27625f757f3fSDimitry Andric }
27635f757f3fSDimitry Andric
27645f757f3fSDimitry Andric (void)va_labels; // Silence unused-but-set-parameter warning
27655f757f3fSDimitry Andric *ret_label = 0;
27665f757f3fSDimitry Andric if (ret_origin)
27675f757f3fSDimitry Andric *ret_origin = 0;
27685f757f3fSDimitry Andric
27695f757f3fSDimitry Andric // Number of items scanned in total.
2770*0fca6ea1SDimitry Andric return scanner.num_scanned;
27715f757f3fSDimitry Andric }
27725f757f3fSDimitry Andric
277368d75effSDimitry Andric extern "C" {
277468d75effSDimitry Andric 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,...)277568d75effSDimitry Andric int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
277668d75effSDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
277768d75effSDimitry Andric dfsan_label *ret_label, ...) {
277868d75effSDimitry Andric va_list ap;
277968d75effSDimitry Andric va_start(ap, ret_label);
27805f757f3fSDimitry Andric
27817a6dacacSDimitry Andric int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, nullptr,
2782fe6060f1SDimitry Andric nullptr, ap);
2783fe6060f1SDimitry Andric va_end(ap);
2784fe6060f1SDimitry Andric return ret;
2785fe6060f1SDimitry Andric }
2786fe6060f1SDimitry Andric
2787fe6060f1SDimitry Andric 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,...)2788fe6060f1SDimitry Andric int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
2789fe6060f1SDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
2790fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin str_origin,
2791fe6060f1SDimitry Andric dfsan_origin format_origin, dfsan_origin *va_origins,
2792fe6060f1SDimitry Andric dfsan_origin *ret_origin, ...) {
2793fe6060f1SDimitry Andric va_list ap;
2794fe6060f1SDimitry Andric va_start(ap, ret_origin);
27957a6dacacSDimitry Andric int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label,
27967a6dacacSDimitry Andric va_origins, ret_origin, ap);
279768d75effSDimitry Andric va_end(ap);
279868d75effSDimitry Andric return ret;
279968d75effSDimitry Andric }
280068d75effSDimitry Andric
280168d75effSDimitry Andric 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,...)280268d75effSDimitry Andric int __dfsw_snprintf(char *str, size_t size, const char *format,
280368d75effSDimitry Andric dfsan_label str_label, dfsan_label size_label,
280468d75effSDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
280568d75effSDimitry Andric dfsan_label *ret_label, ...) {
280668d75effSDimitry Andric va_list ap;
280768d75effSDimitry Andric va_start(ap, ret_label);
2808fe6060f1SDimitry Andric int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
2809fe6060f1SDimitry Andric nullptr, ap);
281068d75effSDimitry Andric va_end(ap);
281168d75effSDimitry Andric return ret;
281268d75effSDimitry Andric }
281368d75effSDimitry Andric
2814fe6060f1SDimitry Andric 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,...)2815fe6060f1SDimitry Andric int __dfso_snprintf(char *str, size_t size, const char *format,
2816fe6060f1SDimitry Andric dfsan_label str_label, dfsan_label size_label,
2817fe6060f1SDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
2818fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin str_origin,
2819fe6060f1SDimitry Andric dfsan_origin size_origin, dfsan_origin format_origin,
2820fe6060f1SDimitry Andric dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
2821fe6060f1SDimitry Andric va_list ap;
2822fe6060f1SDimitry Andric va_start(ap, ret_origin);
2823fe6060f1SDimitry Andric int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
2824fe6060f1SDimitry Andric ret_origin, ap);
2825fe6060f1SDimitry Andric va_end(ap);
2826fe6060f1SDimitry Andric return ret;
2827fe6060f1SDimitry Andric }
2828fe6060f1SDimitry Andric
28295f757f3fSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_sscanf(char * str,const char * format,dfsan_label str_label,dfsan_label format_label,dfsan_label * va_labels,dfsan_label * ret_label,...)28305f757f3fSDimitry Andric int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label,
28315f757f3fSDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
28325f757f3fSDimitry Andric dfsan_label *ret_label, ...) {
28335f757f3fSDimitry Andric va_list ap;
28345f757f3fSDimitry Andric va_start(ap, ret_label);
28355f757f3fSDimitry Andric int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
28365f757f3fSDimitry Andric nullptr, ap);
28375f757f3fSDimitry Andric va_end(ap);
28385f757f3fSDimitry Andric return ret;
28395f757f3fSDimitry Andric }
28405f757f3fSDimitry Andric
28415f757f3fSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfso_sscanf(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,...)28425f757f3fSDimitry Andric int __dfso_sscanf(char *str, const char *format, dfsan_label str_label,
28435f757f3fSDimitry Andric dfsan_label format_label, dfsan_label *va_labels,
28445f757f3fSDimitry Andric dfsan_label *ret_label, dfsan_origin str_origin,
28455f757f3fSDimitry Andric dfsan_origin format_origin, dfsan_origin *va_origins,
28465f757f3fSDimitry Andric dfsan_origin *ret_origin, ...) {
28475f757f3fSDimitry Andric va_list ap;
28485f757f3fSDimitry Andric va_start(ap, ret_origin);
28495f757f3fSDimitry Andric int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,
28505f757f3fSDimitry Andric ret_origin, ap);
28515f757f3fSDimitry Andric va_end(ap);
28525f757f3fSDimitry Andric return ret;
28535f757f3fSDimitry Andric }
28545f757f3fSDimitry Andric
WRAPPER_ALIAS(__isoc99_sscanf,sscanf)285574626c16SDimitry Andric WRAPPER_ALIAS(__isoc99_sscanf, sscanf)
285674626c16SDimitry Andric WRAPPER_ALIAS(__isoc23_sscanf, sscanf)
28575f757f3fSDimitry Andric
2858fe6060f1SDimitry Andric static void BeforeFork() {
2859cb14a3feSDimitry Andric StackDepotLockBeforeFork();
2860cb14a3feSDimitry Andric ChainedOriginDepotLockBeforeFork();
2861fe6060f1SDimitry Andric }
2862fe6060f1SDimitry Andric
AfterFork(bool fork_child)2863cb14a3feSDimitry Andric static void AfterFork(bool fork_child) {
2864cb14a3feSDimitry Andric ChainedOriginDepotUnlockAfterFork(fork_child);
2865cb14a3feSDimitry Andric StackDepotUnlockAfterFork(fork_child);
2866fe6060f1SDimitry Andric }
2867fe6060f1SDimitry Andric
2868fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfsw_fork(dfsan_label * ret_label)2869fe6060f1SDimitry Andric pid_t __dfsw_fork(dfsan_label *ret_label) {
2870fe6060f1SDimitry Andric pid_t pid = fork();
2871fe6060f1SDimitry Andric *ret_label = 0;
2872fe6060f1SDimitry Andric return pid;
2873fe6060f1SDimitry Andric }
2874fe6060f1SDimitry Andric
2875fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
__dfso_fork(dfsan_label * ret_label,dfsan_origin * ret_origin)2876fe6060f1SDimitry Andric pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
2877fe6060f1SDimitry Andric BeforeFork();
2878fe6060f1SDimitry Andric pid_t pid = __dfsw_fork(ret_label);
2879cb14a3feSDimitry Andric AfterFork(/* fork_child= */ pid == 0);
2880fe6060f1SDimitry Andric return pid;
2881fe6060f1SDimitry Andric }
2882fe6060f1SDimitry Andric
288368d75effSDimitry Andric // Default empty implementations (weak). Users should redefine them.
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_guard,u32 *)288468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_guard_init,u32 *,u32 *)288568d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
288668d75effSDimitry Andric u32 *) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_pcs_init,const uptr * beg,const uptr * end)2887349cc55cSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,
2888349cc55cSDimitry Andric const uptr *end) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_cov_trace_pc_indir,void)288968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
289068d75effSDimitry Andric
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp,void)289168d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp1,void)289268d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp2,void)289368d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp4,void)289468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_cmp8,void)289568d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp1,void)289668d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
289768d75effSDimitry Andric void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp2,void)289868d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
289968d75effSDimitry Andric void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp4,void)290068d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
290168d75effSDimitry Andric void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_const_cmp8,void)290268d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
290368d75effSDimitry Andric void) {}
SANITIZER_INTERFACE_WEAK_DEF(void,__dfsw___sanitizer_cov_trace_switch,void)290468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
290568d75effSDimitry Andric } // extern "C"
2906