xref: /freebsd/contrib/llvm-project/compiler-rt/lib/dfsan/dfsan_custom.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1*fe6060f1SDimitry 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"
40*fe6060f1SDimitry Andric #include "dfsan/dfsan_chained_origin_depot.h"
41*fe6060f1SDimitry Andric #include "dfsan/dfsan_flags.h"
42*fe6060f1SDimitry 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"
46*fe6060f1SDimitry 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 
58*fe6060f1SDimitry Andric // Async-safe, non-reentrant spin lock.
59*fe6060f1SDimitry Andric class SignalSpinLocker {
60*fe6060f1SDimitry Andric  public:
61*fe6060f1SDimitry Andric   SignalSpinLocker() {
62*fe6060f1SDimitry Andric     sigset_t all_set;
63*fe6060f1SDimitry Andric     sigfillset(&all_set);
64*fe6060f1SDimitry Andric     pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
65*fe6060f1SDimitry Andric     sigactions_mu.Lock();
66*fe6060f1SDimitry Andric   }
67*fe6060f1SDimitry Andric   ~SignalSpinLocker() {
68*fe6060f1SDimitry Andric     sigactions_mu.Unlock();
69*fe6060f1SDimitry Andric     pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
70*fe6060f1SDimitry Andric   }
71*fe6060f1SDimitry Andric 
72*fe6060f1SDimitry Andric  private:
73*fe6060f1SDimitry Andric   static StaticSpinMutex sigactions_mu;
74*fe6060f1SDimitry Andric   sigset_t saved_thread_mask_;
75*fe6060f1SDimitry Andric 
76*fe6060f1SDimitry Andric   SignalSpinLocker(const SignalSpinLocker &) = delete;
77*fe6060f1SDimitry Andric   SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
78*fe6060f1SDimitry Andric };
79*fe6060f1SDimitry Andric 
80*fe6060f1SDimitry Andric StaticSpinMutex SignalSpinLocker::sigactions_mu;
81*fe6060f1SDimitry Andric 
8268d75effSDimitry Andric extern "C" {
8368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int
8468d75effSDimitry Andric __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
8568d75effSDimitry Andric             dfsan_label buf_label, dfsan_label *ret_label) {
8668d75effSDimitry Andric   int ret = stat(path, buf);
8768d75effSDimitry Andric   if (ret == 0)
8868d75effSDimitry Andric     dfsan_set_label(0, buf, sizeof(struct stat));
8968d75effSDimitry Andric   *ret_label = 0;
9068d75effSDimitry Andric   return ret;
9168d75effSDimitry Andric }
9268d75effSDimitry Andric 
93*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
94*fe6060f1SDimitry Andric     const char *path, struct stat *buf, dfsan_label path_label,
95*fe6060f1SDimitry Andric     dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
96*fe6060f1SDimitry Andric     dfsan_origin buf_origin, dfsan_origin *ret_origin) {
97*fe6060f1SDimitry Andric   int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
98*fe6060f1SDimitry Andric   return ret;
99*fe6060f1SDimitry Andric }
100*fe6060f1SDimitry Andric 
10168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
10268d75effSDimitry Andric                                                dfsan_label fd_label,
10368d75effSDimitry Andric                                                dfsan_label buf_label,
10468d75effSDimitry Andric                                                dfsan_label *ret_label) {
10568d75effSDimitry Andric   int ret = fstat(fd, buf);
10668d75effSDimitry Andric   if (ret == 0)
10768d75effSDimitry Andric     dfsan_set_label(0, buf, sizeof(struct stat));
10868d75effSDimitry Andric   *ret_label = 0;
10968d75effSDimitry Andric   return ret;
11068d75effSDimitry Andric }
11168d75effSDimitry Andric 
112*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
113*fe6060f1SDimitry Andric     int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
114*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
115*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
116*fe6060f1SDimitry Andric   int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
117*fe6060f1SDimitry Andric   return ret;
118*fe6060f1SDimitry Andric }
119*fe6060f1SDimitry Andric 
120*fe6060f1SDimitry Andric static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
121*fe6060f1SDimitry Andric                                      dfsan_label s_label, dfsan_label c_label,
122*fe6060f1SDimitry Andric                                      dfsan_label *ret_label) {
123*fe6060f1SDimitry Andric   char *match_pos = nullptr;
124*fe6060f1SDimitry Andric   for (size_t i = 0;; ++i) {
125*fe6060f1SDimitry Andric     if (s[i] == c || s[i] == 0) {
126*fe6060f1SDimitry Andric       // If s[i] is the \0 at the end of the string, and \0 is not the
127*fe6060f1SDimitry Andric       // character we are searching for, then return null.
128*fe6060f1SDimitry Andric       *bytes_read = i + 1;
129*fe6060f1SDimitry Andric       match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
130*fe6060f1SDimitry Andric       break;
131*fe6060f1SDimitry Andric     }
132*fe6060f1SDimitry Andric   }
133*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies)
134*fe6060f1SDimitry Andric     *ret_label = s_label;
135*fe6060f1SDimitry Andric   else
136*fe6060f1SDimitry Andric     *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
137*fe6060f1SDimitry Andric                              dfsan_union(s_label, c_label));
138*fe6060f1SDimitry Andric   return match_pos;
139*fe6060f1SDimitry Andric }
140*fe6060f1SDimitry Andric 
14168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
14268d75effSDimitry Andric                                                   dfsan_label s_label,
14368d75effSDimitry Andric                                                   dfsan_label c_label,
14468d75effSDimitry Andric                                                   dfsan_label *ret_label) {
145*fe6060f1SDimitry Andric   size_t bytes_read;
146*fe6060f1SDimitry Andric   return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
147*fe6060f1SDimitry Andric                                  ret_label);
14868d75effSDimitry Andric }
1495ffd83dbSDimitry Andric 
150*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
151*fe6060f1SDimitry Andric     const char *s, int c, dfsan_label s_label, dfsan_label c_label,
152*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
153*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
154*fe6060f1SDimitry Andric   size_t bytes_read;
155*fe6060f1SDimitry Andric   char *r =
156*fe6060f1SDimitry Andric       dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
157*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies) {
158*fe6060f1SDimitry Andric     *ret_origin = s_origin;
159*fe6060f1SDimitry Andric   } else if (*ret_label) {
160*fe6060f1SDimitry Andric     dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
161*fe6060f1SDimitry Andric     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1625ffd83dbSDimitry Andric   }
163*fe6060f1SDimitry Andric   return r;
16468d75effSDimitry Andric }
16568d75effSDimitry Andric 
166e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
167e8d8bef9SDimitry Andric                                                    const char *accept,
168e8d8bef9SDimitry Andric                                                    dfsan_label s_label,
169e8d8bef9SDimitry Andric                                                    dfsan_label accept_label,
17068d75effSDimitry Andric                                                    dfsan_label *ret_label) {
171e8d8bef9SDimitry Andric   const char *ret = strpbrk(s, accept);
172e8d8bef9SDimitry Andric   if (flags().strict_data_dependencies) {
173e8d8bef9SDimitry Andric     *ret_label = ret ? s_label : 0;
174e8d8bef9SDimitry Andric   } else {
175e8d8bef9SDimitry Andric     size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
176e8d8bef9SDimitry Andric     *ret_label =
177e8d8bef9SDimitry Andric         dfsan_union(dfsan_read_label(s, s_bytes_read),
178e8d8bef9SDimitry Andric                     dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
179e8d8bef9SDimitry Andric                                 dfsan_union(s_label, accept_label)));
180e8d8bef9SDimitry Andric   }
181e8d8bef9SDimitry Andric   return const_cast<char *>(ret);
182e8d8bef9SDimitry Andric }
183e8d8bef9SDimitry Andric 
184*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
185*fe6060f1SDimitry Andric     const char *s, const char *accept, dfsan_label s_label,
186*fe6060f1SDimitry Andric     dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
187*fe6060f1SDimitry Andric     dfsan_origin accept_origin, dfsan_origin *ret_origin) {
188*fe6060f1SDimitry Andric   const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
189*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies) {
190*fe6060f1SDimitry Andric     if (ret)
191*fe6060f1SDimitry Andric       *ret_origin = s_origin;
192*fe6060f1SDimitry Andric   } else {
193*fe6060f1SDimitry Andric     if (*ret_label) {
194*fe6060f1SDimitry Andric       size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
195*fe6060f1SDimitry Andric       dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
196*fe6060f1SDimitry Andric       if (o) {
197*fe6060f1SDimitry Andric         *ret_origin = o;
198*fe6060f1SDimitry Andric       } else {
199*fe6060f1SDimitry Andric         o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
200*fe6060f1SDimitry Andric         *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
201*fe6060f1SDimitry Andric       }
202*fe6060f1SDimitry Andric     }
203*fe6060f1SDimitry Andric   }
204*fe6060f1SDimitry Andric   return const_cast<char *>(ret);
205*fe6060f1SDimitry Andric }
206*fe6060f1SDimitry Andric 
207e8d8bef9SDimitry Andric static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
208*fe6060f1SDimitry Andric                              size_t *bytes_read) {
20968d75effSDimitry Andric   const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
21068d75effSDimitry Andric   for (size_t i = 0; i != n; ++i) {
21168d75effSDimitry Andric     if (cs1[i] != cs2[i]) {
212*fe6060f1SDimitry Andric       *bytes_read = i + 1;
21368d75effSDimitry Andric       return cs1[i] - cs2[i];
21468d75effSDimitry Andric     }
21568d75effSDimitry Andric   }
216*fe6060f1SDimitry Andric   *bytes_read = n;
21768d75effSDimitry Andric   return 0;
21868d75effSDimitry Andric }
21968d75effSDimitry Andric 
220*fe6060f1SDimitry Andric static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
221*fe6060f1SDimitry Andric                                           size_t pos) {
222*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies)
223*fe6060f1SDimitry Andric     return 0;
224*fe6060f1SDimitry Andric   return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
225*fe6060f1SDimitry Andric }
226*fe6060f1SDimitry Andric 
227*fe6060f1SDimitry Andric static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
228*fe6060f1SDimitry Andric                                     dfsan_label *ret_label,
229*fe6060f1SDimitry Andric                                     dfsan_origin *ret_origin) {
230*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
231*fe6060f1SDimitry Andric   if (*ret_label == 0)
232*fe6060f1SDimitry Andric     return;
233*fe6060f1SDimitry Andric   dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
234*fe6060f1SDimitry Andric   *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
235*fe6060f1SDimitry Andric }
236*fe6060f1SDimitry Andric 
237*fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
238*fe6060f1SDimitry Andric                                    dfsan_label *ret_label) {
239*fe6060f1SDimitry Andric   size_t bytes_read;
240*fe6060f1SDimitry Andric   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
241*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
242*fe6060f1SDimitry Andric   return r;
243*fe6060f1SDimitry Andric }
244*fe6060f1SDimitry Andric 
245*fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
246*fe6060f1SDimitry Andric                                     dfsan_label *ret_label,
247*fe6060f1SDimitry Andric                                     dfsan_origin *ret_origin) {
248*fe6060f1SDimitry Andric   size_t bytes_read;
249*fe6060f1SDimitry Andric   int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
250*fe6060f1SDimitry Andric   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
251*fe6060f1SDimitry Andric   return r;
252*fe6060f1SDimitry Andric }
253*fe6060f1SDimitry Andric 
254e8d8bef9SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
255e8d8bef9SDimitry Andric                               const void *s1, const void *s2, size_t n,
256e8d8bef9SDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label,
257e8d8bef9SDimitry Andric                               dfsan_label n_label)
258e8d8bef9SDimitry Andric 
259*fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
260*fe6060f1SDimitry Andric                               const void *s1, const void *s2, size_t n,
261*fe6060f1SDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label,
262*fe6060f1SDimitry Andric                               dfsan_label n_label, dfsan_origin s1_origin,
263*fe6060f1SDimitry Andric                               dfsan_origin s2_origin, dfsan_origin n_origin)
264*fe6060f1SDimitry Andric 
265e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
266e8d8bef9SDimitry Andric                                                 size_t n, dfsan_label s1_label,
267e8d8bef9SDimitry Andric                                                 dfsan_label s2_label,
268e8d8bef9SDimitry Andric                                                 dfsan_label n_label,
269e8d8bef9SDimitry Andric                                                 dfsan_label *ret_label) {
270e8d8bef9SDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
271e8d8bef9SDimitry Andric                              s1_label, s2_label, n_label);
272*fe6060f1SDimitry Andric   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
273*fe6060f1SDimitry Andric }
274*fe6060f1SDimitry Andric 
275*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
276*fe6060f1SDimitry Andric     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
277*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
278*fe6060f1SDimitry Andric     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
279*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
280*fe6060f1SDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
281*fe6060f1SDimitry Andric                              s2, n, s1_label, s2_label, n_label, s1_origin,
282*fe6060f1SDimitry Andric                              s2_origin, n_origin);
283*fe6060f1SDimitry Andric   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
284e8d8bef9SDimitry Andric }
285e8d8bef9SDimitry Andric 
286e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
287e8d8bef9SDimitry Andric                                               size_t n, dfsan_label s1_label,
288e8d8bef9SDimitry Andric                                               dfsan_label s2_label,
289e8d8bef9SDimitry Andric                                               dfsan_label n_label,
290e8d8bef9SDimitry Andric                                               dfsan_label *ret_label) {
291*fe6060f1SDimitry Andric   return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
292*fe6060f1SDimitry Andric }
293*fe6060f1SDimitry Andric 
294*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
295*fe6060f1SDimitry Andric     const void *s1, const void *s2, size_t n, dfsan_label s1_label,
296*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
297*fe6060f1SDimitry Andric     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
298*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
299*fe6060f1SDimitry Andric   return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
300*fe6060f1SDimitry Andric }
301*fe6060f1SDimitry Andric 
302*fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit.
303*fe6060f1SDimitry Andric // When n > 0, compare the first (at most) n bytes of s1 and s2.
304*fe6060f1SDimitry Andric static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
305*fe6060f1SDimitry Andric                          size_t *bytes_read) {
306*fe6060f1SDimitry Andric   for (size_t i = 0;; ++i) {
307*fe6060f1SDimitry Andric     if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
308*fe6060f1SDimitry Andric       *bytes_read = i + 1;
309*fe6060f1SDimitry Andric       return s1[i] - s2[i];
310*fe6060f1SDimitry Andric     }
311*fe6060f1SDimitry Andric   }
312e8d8bef9SDimitry Andric }
313e8d8bef9SDimitry Andric 
31468d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
31568d75effSDimitry Andric                               const char *s1, const char *s2,
31668d75effSDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label)
31768d75effSDimitry Andric 
318*fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
319*fe6060f1SDimitry Andric                               const char *s1, const char *s2,
320*fe6060f1SDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label,
321*fe6060f1SDimitry Andric                               dfsan_origin s1_origin, dfsan_origin s2_origin)
322*fe6060f1SDimitry Andric 
32368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
32468d75effSDimitry Andric                                                 dfsan_label s1_label,
32568d75effSDimitry Andric                                                 dfsan_label s2_label,
32668d75effSDimitry Andric                                                 dfsan_label *ret_label) {
32768d75effSDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
32868d75effSDimitry Andric                              s1_label, s2_label);
329*fe6060f1SDimitry Andric   size_t bytes_read;
330*fe6060f1SDimitry Andric   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
331*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
332*fe6060f1SDimitry Andric   return r;
33368d75effSDimitry Andric }
33468d75effSDimitry Andric 
335*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
336*fe6060f1SDimitry Andric     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
337*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
338*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
339*fe6060f1SDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
340*fe6060f1SDimitry Andric                              s2, s1_label, s2_label, s1_origin, s2_origin);
341*fe6060f1SDimitry Andric   size_t bytes_read;
342*fe6060f1SDimitry Andric   int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
343*fe6060f1SDimitry Andric   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
344*fe6060f1SDimitry Andric   return r;
345*fe6060f1SDimitry Andric }
346*fe6060f1SDimitry Andric 
347*fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit.
348*fe6060f1SDimitry Andric // When n > 0, compare the first (at most) n bytes of s1 and s2.
349*fe6060f1SDimitry Andric static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
350*fe6060f1SDimitry Andric                              size_t *bytes_read) {
35168d75effSDimitry Andric   for (size_t i = 0;; ++i) {
3525ffd83dbSDimitry Andric     char s1_lower = tolower(s1[i]);
3535ffd83dbSDimitry Andric     char s2_lower = tolower(s2[i]);
3545ffd83dbSDimitry Andric 
355*fe6060f1SDimitry Andric     if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
356*fe6060f1SDimitry Andric         (n > 0 && i == n - 1)) {
357*fe6060f1SDimitry Andric       *bytes_read = i + 1;
3585ffd83dbSDimitry Andric       return s1_lower - s2_lower;
35968d75effSDimitry Andric     }
36068d75effSDimitry Andric   }
361*fe6060f1SDimitry Andric }
362*fe6060f1SDimitry Andric 
363*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
364*fe6060f1SDimitry Andric                                                     const char *s2,
365*fe6060f1SDimitry Andric                                                     dfsan_label s1_label,
366*fe6060f1SDimitry Andric                                                     dfsan_label s2_label,
367*fe6060f1SDimitry Andric                                                     dfsan_label *ret_label) {
368*fe6060f1SDimitry Andric   size_t bytes_read;
369*fe6060f1SDimitry Andric   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
370*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
371*fe6060f1SDimitry Andric   return r;
372*fe6060f1SDimitry Andric }
373*fe6060f1SDimitry Andric 
374*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
375*fe6060f1SDimitry Andric     const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
376*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
377*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
378*fe6060f1SDimitry Andric   size_t bytes_read;
379*fe6060f1SDimitry Andric   int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
380*fe6060f1SDimitry Andric   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
381*fe6060f1SDimitry Andric   return r;
38268d75effSDimitry Andric }
38368d75effSDimitry Andric 
38468d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
38568d75effSDimitry Andric                               const char *s1, const char *s2, size_t n,
38668d75effSDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label,
38768d75effSDimitry Andric                               dfsan_label n_label)
38868d75effSDimitry Andric 
389*fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
390*fe6060f1SDimitry Andric                               const char *s1, const char *s2, size_t n,
391*fe6060f1SDimitry Andric                               dfsan_label s1_label, dfsan_label s2_label,
392*fe6060f1SDimitry Andric                               dfsan_label n_label, dfsan_origin s1_origin,
393*fe6060f1SDimitry Andric                               dfsan_origin s2_origin, dfsan_origin n_origin)
394*fe6060f1SDimitry Andric 
39568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
39668d75effSDimitry Andric                                                  size_t n, dfsan_label s1_label,
39768d75effSDimitry Andric                                                  dfsan_label s2_label,
39868d75effSDimitry Andric                                                  dfsan_label n_label,
39968d75effSDimitry Andric                                                  dfsan_label *ret_label) {
40068d75effSDimitry Andric   if (n == 0) {
40168d75effSDimitry Andric     *ret_label = 0;
40268d75effSDimitry Andric     return 0;
40368d75effSDimitry Andric   }
40468d75effSDimitry Andric 
40568d75effSDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
40668d75effSDimitry Andric                              n, s1_label, s2_label, n_label);
40768d75effSDimitry Andric 
408*fe6060f1SDimitry Andric   size_t bytes_read;
409*fe6060f1SDimitry Andric   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
410*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
411*fe6060f1SDimitry Andric   return r;
41268d75effSDimitry Andric }
41368d75effSDimitry Andric 
414*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
415*fe6060f1SDimitry Andric     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
416*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
417*fe6060f1SDimitry Andric     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
418*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
41968d75effSDimitry Andric   if (n == 0) {
42068d75effSDimitry Andric     *ret_label = 0;
42168d75effSDimitry Andric     return 0;
42268d75effSDimitry Andric   }
42368d75effSDimitry Andric 
424*fe6060f1SDimitry Andric   CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
425*fe6060f1SDimitry Andric                              s1, s2, n, s1_label, s2_label, n_label, s1_origin,
426*fe6060f1SDimitry Andric                              s2_origin, n_origin);
4275ffd83dbSDimitry Andric 
428*fe6060f1SDimitry Andric   size_t bytes_read;
429*fe6060f1SDimitry Andric   int r = dfsan_strncmp(s1, s2, n, &bytes_read);
430*fe6060f1SDimitry Andric   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
431*fe6060f1SDimitry Andric   return r;
432*fe6060f1SDimitry Andric }
433*fe6060f1SDimitry Andric 
434*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
435*fe6060f1SDimitry Andric     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
436*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
437*fe6060f1SDimitry Andric   if (n == 0) {
43868d75effSDimitry Andric     *ret_label = 0;
43968d75effSDimitry Andric     return 0;
44068d75effSDimitry Andric   }
44168d75effSDimitry Andric 
442*fe6060f1SDimitry Andric   size_t bytes_read;
443*fe6060f1SDimitry Andric   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
444*fe6060f1SDimitry Andric   *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
445*fe6060f1SDimitry Andric   return r;
44668d75effSDimitry Andric }
44768d75effSDimitry Andric 
448*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
449*fe6060f1SDimitry Andric     const char *s1, const char *s2, size_t n, dfsan_label s1_label,
450*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
451*fe6060f1SDimitry Andric     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
452*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
453*fe6060f1SDimitry Andric   if (n == 0) {
454*fe6060f1SDimitry Andric     *ret_label = 0;
455*fe6060f1SDimitry Andric     return 0;
456*fe6060f1SDimitry Andric   }
457*fe6060f1SDimitry Andric 
458*fe6060f1SDimitry Andric   size_t bytes_read;
459*fe6060f1SDimitry Andric   int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
460*fe6060f1SDimitry Andric   dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
461*fe6060f1SDimitry Andric   return r;
462*fe6060f1SDimitry Andric }
463*fe6060f1SDimitry Andric 
464*fe6060f1SDimitry Andric 
46568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t
46668d75effSDimitry Andric __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
46768d75effSDimitry Andric   size_t ret = strlen(s);
46868d75effSDimitry Andric   if (flags().strict_data_dependencies) {
46968d75effSDimitry Andric     *ret_label = 0;
47068d75effSDimitry Andric   } else {
47168d75effSDimitry Andric     *ret_label = dfsan_read_label(s, ret + 1);
47268d75effSDimitry Andric   }
47368d75effSDimitry Andric   return ret;
47468d75effSDimitry Andric }
47568d75effSDimitry Andric 
476*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
477*fe6060f1SDimitry Andric                                                    dfsan_label s_label,
478*fe6060f1SDimitry Andric                                                    dfsan_label *ret_label,
479*fe6060f1SDimitry Andric                                                    dfsan_origin s_origin,
480*fe6060f1SDimitry Andric                                                    dfsan_origin *ret_origin) {
481*fe6060f1SDimitry Andric   size_t ret = __dfsw_strlen(s, s_label, ret_label);
482*fe6060f1SDimitry Andric   if (!flags().strict_data_dependencies)
483*fe6060f1SDimitry Andric     *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
484*fe6060f1SDimitry Andric   return ret;
485*fe6060f1SDimitry Andric }
486*fe6060f1SDimitry Andric 
487*fe6060f1SDimitry Andric static void *dfsan_memmove(void *dest, const void *src, size_t n) {
488*fe6060f1SDimitry Andric   dfsan_label *sdest = shadow_for(dest);
489*fe6060f1SDimitry Andric   const dfsan_label *ssrc = shadow_for(src);
490*fe6060f1SDimitry Andric   internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
491*fe6060f1SDimitry Andric   return internal_memmove(dest, src, n);
492*fe6060f1SDimitry Andric }
493*fe6060f1SDimitry Andric 
494*fe6060f1SDimitry Andric static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
495*fe6060f1SDimitry Andric   dfsan_mem_origin_transfer(dest, src, n);
496*fe6060f1SDimitry Andric   return dfsan_memmove(dest, src, n);
497*fe6060f1SDimitry Andric }
49868d75effSDimitry Andric 
49968d75effSDimitry Andric static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
50068d75effSDimitry Andric   dfsan_label *sdest = shadow_for(dest);
50168d75effSDimitry Andric   const dfsan_label *ssrc = shadow_for(src);
50268d75effSDimitry Andric   internal_memcpy((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
50368d75effSDimitry Andric   return internal_memcpy(dest, src, n);
50468d75effSDimitry Andric }
50568d75effSDimitry Andric 
506*fe6060f1SDimitry Andric static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
507*fe6060f1SDimitry Andric   dfsan_mem_origin_transfer(dest, src, n);
508*fe6060f1SDimitry Andric   return dfsan_memcpy(dest, src, n);
509*fe6060f1SDimitry Andric }
510*fe6060f1SDimitry Andric 
51168d75effSDimitry Andric static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
51268d75effSDimitry Andric   internal_memset(s, c, n);
51368d75effSDimitry Andric   dfsan_set_label(c_label, s, n);
51468d75effSDimitry Andric }
51568d75effSDimitry Andric 
516*fe6060f1SDimitry Andric static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
517*fe6060f1SDimitry Andric                                      dfsan_origin c_origin, size_t n) {
518*fe6060f1SDimitry Andric   internal_memset(s, c, n);
519*fe6060f1SDimitry Andric   dfsan_set_label_origin(c_label, c_origin, s, n);
520*fe6060f1SDimitry Andric }
521*fe6060f1SDimitry Andric 
52268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
52368d75effSDimitry Andric void *__dfsw_memcpy(void *dest, const void *src, size_t n,
52468d75effSDimitry Andric                     dfsan_label dest_label, dfsan_label src_label,
52568d75effSDimitry Andric                     dfsan_label n_label, dfsan_label *ret_label) {
52668d75effSDimitry Andric   *ret_label = dest_label;
52768d75effSDimitry Andric   return dfsan_memcpy(dest, src, n);
52868d75effSDimitry Andric }
52968d75effSDimitry Andric 
53068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
531*fe6060f1SDimitry Andric void *__dfso_memcpy(void *dest, const void *src, size_t n,
532*fe6060f1SDimitry Andric                     dfsan_label dest_label, dfsan_label src_label,
533*fe6060f1SDimitry Andric                     dfsan_label n_label, dfsan_label *ret_label,
534*fe6060f1SDimitry Andric                     dfsan_origin dest_origin, dfsan_origin src_origin,
535*fe6060f1SDimitry Andric                     dfsan_origin n_origin, dfsan_origin *ret_origin) {
536*fe6060f1SDimitry Andric   *ret_label = dest_label;
537*fe6060f1SDimitry Andric   *ret_origin = dest_origin;
538*fe6060f1SDimitry Andric   return dfsan_memcpy_with_origin(dest, src, n);
539*fe6060f1SDimitry Andric }
540*fe6060f1SDimitry Andric 
541*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
542*fe6060f1SDimitry Andric void *__dfsw_memmove(void *dest, const void *src, size_t n,
543*fe6060f1SDimitry Andric                      dfsan_label dest_label, dfsan_label src_label,
544*fe6060f1SDimitry Andric                      dfsan_label n_label, dfsan_label *ret_label) {
545*fe6060f1SDimitry Andric   *ret_label = dest_label;
546*fe6060f1SDimitry Andric   return dfsan_memmove(dest, src, n);
547*fe6060f1SDimitry Andric }
548*fe6060f1SDimitry Andric 
549*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
550*fe6060f1SDimitry Andric void *__dfso_memmove(void *dest, const void *src, size_t n,
551*fe6060f1SDimitry Andric                      dfsan_label dest_label, dfsan_label src_label,
552*fe6060f1SDimitry Andric                      dfsan_label n_label, dfsan_label *ret_label,
553*fe6060f1SDimitry Andric                      dfsan_origin dest_origin, dfsan_origin src_origin,
554*fe6060f1SDimitry Andric                      dfsan_origin n_origin, dfsan_origin *ret_origin) {
555*fe6060f1SDimitry Andric   *ret_label = dest_label;
556*fe6060f1SDimitry Andric   *ret_origin = dest_origin;
557*fe6060f1SDimitry Andric   return dfsan_memmove_with_origin(dest, src, n);
558*fe6060f1SDimitry Andric }
559*fe6060f1SDimitry Andric 
560*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
56168d75effSDimitry Andric void *__dfsw_memset(void *s, int c, size_t n,
56268d75effSDimitry Andric                     dfsan_label s_label, dfsan_label c_label,
56368d75effSDimitry Andric                     dfsan_label n_label, dfsan_label *ret_label) {
56468d75effSDimitry Andric   dfsan_memset(s, c, c_label, n);
56568d75effSDimitry Andric   *ret_label = s_label;
56668d75effSDimitry Andric   return s;
56768d75effSDimitry Andric }
56868d75effSDimitry Andric 
569*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
570*fe6060f1SDimitry Andric void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
571*fe6060f1SDimitry Andric                     dfsan_label c_label, dfsan_label n_label,
572*fe6060f1SDimitry Andric                     dfsan_label *ret_label, dfsan_origin s_origin,
573*fe6060f1SDimitry Andric                     dfsan_origin c_origin, dfsan_origin n_origin,
574*fe6060f1SDimitry Andric                     dfsan_origin *ret_origin) {
575*fe6060f1SDimitry Andric   dfsan_memset_with_origin(s, c, c_label, c_origin, n);
576*fe6060f1SDimitry Andric   *ret_label = s_label;
577*fe6060f1SDimitry Andric   *ret_origin = s_origin;
578*fe6060f1SDimitry Andric   return s;
579*fe6060f1SDimitry Andric }
580*fe6060f1SDimitry Andric 
581*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
582*fe6060f1SDimitry Andric                                                   dfsan_label dest_label,
583*fe6060f1SDimitry Andric                                                   dfsan_label src_label,
584*fe6060f1SDimitry Andric                                                   dfsan_label *ret_label) {
585*fe6060f1SDimitry Andric   size_t dest_len = strlen(dest);
586*fe6060f1SDimitry Andric   char *ret = strcat(dest, src);  // NOLINT
587*fe6060f1SDimitry Andric   dfsan_label *sdest = shadow_for(dest + dest_len);
588*fe6060f1SDimitry Andric   const dfsan_label *ssrc = shadow_for(src);
589*fe6060f1SDimitry Andric   internal_memcpy((void *)sdest, (const void *)ssrc,
590*fe6060f1SDimitry Andric                   strlen(src) * sizeof(dfsan_label));
591*fe6060f1SDimitry Andric   *ret_label = dest_label;
592*fe6060f1SDimitry Andric   return ret;
593*fe6060f1SDimitry Andric }
594*fe6060f1SDimitry Andric 
595*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
596*fe6060f1SDimitry Andric     char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
597*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
598*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
599*fe6060f1SDimitry Andric   size_t dest_len = strlen(dest);
600*fe6060f1SDimitry Andric   char *ret = strcat(dest, src);  // NOLINT
601*fe6060f1SDimitry Andric   dfsan_label *sdest = shadow_for(dest + dest_len);
602*fe6060f1SDimitry Andric   const dfsan_label *ssrc = shadow_for(src);
603*fe6060f1SDimitry Andric   size_t src_len = strlen(src);
604*fe6060f1SDimitry Andric   dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
605*fe6060f1SDimitry Andric   internal_memcpy((void *)sdest, (const void *)ssrc,
606*fe6060f1SDimitry Andric                   src_len * sizeof(dfsan_label));
607*fe6060f1SDimitry Andric   *ret_label = dest_label;
608*fe6060f1SDimitry Andric   *ret_origin = dest_origin;
609*fe6060f1SDimitry Andric   return ret;
610*fe6060f1SDimitry Andric }
611*fe6060f1SDimitry Andric 
61268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *
61368d75effSDimitry Andric __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
61468d75effSDimitry Andric   size_t len = strlen(s);
61568d75effSDimitry Andric   void *p = malloc(len+1);
61668d75effSDimitry Andric   dfsan_memcpy(p, s, len+1);
61768d75effSDimitry Andric   *ret_label = 0;
61868d75effSDimitry Andric   return static_cast<char *>(p);
61968d75effSDimitry Andric }
62068d75effSDimitry Andric 
621*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
622*fe6060f1SDimitry Andric                                                   dfsan_label s_label,
623*fe6060f1SDimitry Andric                                                   dfsan_label *ret_label,
624*fe6060f1SDimitry Andric                                                   dfsan_origin s_origin,
625*fe6060f1SDimitry Andric                                                   dfsan_origin *ret_origin) {
626*fe6060f1SDimitry Andric   size_t len = strlen(s);
627*fe6060f1SDimitry Andric   void *p = malloc(len + 1);
628*fe6060f1SDimitry Andric   dfsan_memcpy_with_origin(p, s, len + 1);
629*fe6060f1SDimitry Andric   *ret_label = 0;
630*fe6060f1SDimitry Andric   return static_cast<char *>(p);
631*fe6060f1SDimitry Andric }
632*fe6060f1SDimitry Andric 
63368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *
63468d75effSDimitry Andric __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
63568d75effSDimitry Andric                dfsan_label s2_label, dfsan_label n_label,
63668d75effSDimitry Andric                dfsan_label *ret_label) {
63768d75effSDimitry Andric   size_t len = strlen(s2);
63868d75effSDimitry Andric   if (len < n) {
63968d75effSDimitry Andric     dfsan_memcpy(s1, s2, len+1);
64068d75effSDimitry Andric     dfsan_memset(s1+len+1, 0, 0, n-len-1);
64168d75effSDimitry Andric   } else {
64268d75effSDimitry Andric     dfsan_memcpy(s1, s2, n);
64368d75effSDimitry Andric   }
64468d75effSDimitry Andric 
64568d75effSDimitry Andric   *ret_label = s1_label;
64668d75effSDimitry Andric   return s1;
64768d75effSDimitry Andric }
64868d75effSDimitry Andric 
649*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
650*fe6060f1SDimitry Andric     char *s1, const char *s2, size_t n, dfsan_label s1_label,
651*fe6060f1SDimitry Andric     dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
652*fe6060f1SDimitry Andric     dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
653*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
654*fe6060f1SDimitry Andric   size_t len = strlen(s2);
655*fe6060f1SDimitry Andric   if (len < n) {
656*fe6060f1SDimitry Andric     dfsan_memcpy_with_origin(s1, s2, len + 1);
657*fe6060f1SDimitry Andric     dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
658*fe6060f1SDimitry Andric   } else {
659*fe6060f1SDimitry Andric     dfsan_memcpy_with_origin(s1, s2, n);
660*fe6060f1SDimitry Andric   }
661*fe6060f1SDimitry Andric 
662*fe6060f1SDimitry Andric   *ret_label = s1_label;
663*fe6060f1SDimitry Andric   *ret_origin = s1_origin;
664*fe6060f1SDimitry Andric   return s1;
665*fe6060f1SDimitry Andric }
666*fe6060f1SDimitry Andric 
66768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t
66868d75effSDimitry Andric __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
66968d75effSDimitry Andric              dfsan_label fd_label, dfsan_label buf_label,
67068d75effSDimitry Andric              dfsan_label count_label, dfsan_label offset_label,
67168d75effSDimitry Andric              dfsan_label *ret_label) {
67268d75effSDimitry Andric   ssize_t ret = pread(fd, buf, count, offset);
67368d75effSDimitry Andric   if (ret > 0)
67468d75effSDimitry Andric     dfsan_set_label(0, buf, ret);
67568d75effSDimitry Andric   *ret_label = 0;
67668d75effSDimitry Andric   return ret;
67768d75effSDimitry Andric }
67868d75effSDimitry Andric 
679*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
680*fe6060f1SDimitry Andric     int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
681*fe6060f1SDimitry Andric     dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
682*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
683*fe6060f1SDimitry Andric     dfsan_origin count_origin, dfsan_label offset_origin,
684*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
685*fe6060f1SDimitry Andric   return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
686*fe6060f1SDimitry Andric                       offset_label, ret_label);
687*fe6060f1SDimitry Andric }
688*fe6060f1SDimitry Andric 
68968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t
69068d75effSDimitry Andric __dfsw_read(int fd, void *buf, size_t count,
69168d75effSDimitry Andric              dfsan_label fd_label, dfsan_label buf_label,
69268d75effSDimitry Andric              dfsan_label count_label,
69368d75effSDimitry Andric              dfsan_label *ret_label) {
69468d75effSDimitry Andric   ssize_t ret = read(fd, buf, count);
69568d75effSDimitry Andric   if (ret > 0)
69668d75effSDimitry Andric     dfsan_set_label(0, buf, ret);
69768d75effSDimitry Andric   *ret_label = 0;
69868d75effSDimitry Andric   return ret;
69968d75effSDimitry Andric }
70068d75effSDimitry Andric 
701*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
702*fe6060f1SDimitry Andric     int fd, void *buf, size_t count, dfsan_label fd_label,
703*fe6060f1SDimitry Andric     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
704*fe6060f1SDimitry Andric     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
705*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
706*fe6060f1SDimitry Andric   return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
707*fe6060f1SDimitry Andric                      ret_label);
708*fe6060f1SDimitry Andric }
709*fe6060f1SDimitry Andric 
71068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
71168d75effSDimitry Andric                                                        struct timespec *tp,
71268d75effSDimitry Andric                                                        dfsan_label clk_id_label,
71368d75effSDimitry Andric                                                        dfsan_label tp_label,
71468d75effSDimitry Andric                                                        dfsan_label *ret_label) {
71568d75effSDimitry Andric   int ret = clock_gettime(clk_id, tp);
71668d75effSDimitry Andric   if (ret == 0)
71768d75effSDimitry Andric     dfsan_set_label(0, tp, sizeof(struct timespec));
71868d75effSDimitry Andric   *ret_label = 0;
71968d75effSDimitry Andric   return ret;
72068d75effSDimitry Andric }
72168d75effSDimitry Andric 
722*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
723*fe6060f1SDimitry Andric     clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
724*fe6060f1SDimitry Andric     dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
725*fe6060f1SDimitry Andric     dfsan_origin tp_origin, dfsan_origin *ret_origin) {
726*fe6060f1SDimitry Andric   return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
727*fe6060f1SDimitry Andric }
728*fe6060f1SDimitry Andric 
729*fe6060f1SDimitry Andric static void dfsan_set_zero_label(const void *ptr, uptr size) {
73068d75effSDimitry Andric   dfsan_set_label(0, const_cast<void *>(ptr), size);
73168d75effSDimitry Andric }
73268d75effSDimitry Andric 
73368d75effSDimitry Andric // dlopen() ultimately calls mmap() down inside the loader, which generally
73468d75effSDimitry Andric // doesn't participate in dynamic symbol resolution.  Therefore we won't
73568d75effSDimitry Andric // intercept its calls to mmap, and we have to hook it here.
73668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *
73768d75effSDimitry Andric __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
73868d75effSDimitry Andric               dfsan_label flag_label, dfsan_label *ret_label) {
73968d75effSDimitry Andric   void *handle = dlopen(filename, flag);
74068d75effSDimitry Andric   link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
74168d75effSDimitry Andric   if (map)
742*fe6060f1SDimitry Andric     ForEachMappedRegion(map, dfsan_set_zero_label);
74368d75effSDimitry Andric   *ret_label = 0;
74468d75effSDimitry Andric   return handle;
74568d75effSDimitry Andric }
74668d75effSDimitry Andric 
747*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
748*fe6060f1SDimitry Andric     const char *filename, int flag, dfsan_label filename_label,
749*fe6060f1SDimitry Andric     dfsan_label flag_label, dfsan_label *ret_label,
750*fe6060f1SDimitry Andric     dfsan_origin filename_origin, dfsan_origin flag_origin,
751*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
752*fe6060f1SDimitry Andric   return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
753*fe6060f1SDimitry Andric }
75468d75effSDimitry Andric 
755*fe6060f1SDimitry Andric static void *DFsanThreadStartFunc(void *arg) {
756*fe6060f1SDimitry Andric   DFsanThread *t = (DFsanThread *)arg;
757*fe6060f1SDimitry Andric   SetCurrentThread(t);
758*fe6060f1SDimitry Andric   return t->ThreadStart();
759*fe6060f1SDimitry Andric }
760*fe6060f1SDimitry Andric 
761*fe6060f1SDimitry Andric static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
762*fe6060f1SDimitry Andric                                 void *start_routine_trampoline,
763*fe6060f1SDimitry Andric                                 void *start_routine, void *arg,
764*fe6060f1SDimitry Andric                                 dfsan_label *ret_label,
765*fe6060f1SDimitry Andric                                 bool track_origins = false) {
766*fe6060f1SDimitry Andric   pthread_attr_t myattr;
767*fe6060f1SDimitry Andric   if (!attr) {
768*fe6060f1SDimitry Andric     pthread_attr_init(&myattr);
769*fe6060f1SDimitry Andric     attr = &myattr;
770*fe6060f1SDimitry Andric   }
771*fe6060f1SDimitry Andric 
772*fe6060f1SDimitry Andric   // Ensure that the thread stack is large enough to hold all TLS data.
773*fe6060f1SDimitry Andric   AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
774*fe6060f1SDimitry Andric 
775*fe6060f1SDimitry Andric   DFsanThread *t =
776*fe6060f1SDimitry Andric       DFsanThread::Create(start_routine_trampoline,
777*fe6060f1SDimitry Andric                           (thread_callback_t)start_routine, arg, track_origins);
778*fe6060f1SDimitry Andric   int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
779*fe6060f1SDimitry Andric 
780*fe6060f1SDimitry Andric   if (attr == &myattr)
781*fe6060f1SDimitry Andric     pthread_attr_destroy(&myattr);
782*fe6060f1SDimitry Andric   *ret_label = 0;
783*fe6060f1SDimitry Andric   return res;
78468d75effSDimitry Andric }
78568d75effSDimitry Andric 
78668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
78768d75effSDimitry Andric     pthread_t *thread, const pthread_attr_t *attr,
78868d75effSDimitry Andric     void *(*start_routine_trampoline)(void *, void *, dfsan_label,
78968d75effSDimitry Andric                                       dfsan_label *),
79068d75effSDimitry Andric     void *start_routine, void *arg, dfsan_label thread_label,
79168d75effSDimitry Andric     dfsan_label attr_label, dfsan_label start_routine_label,
79268d75effSDimitry Andric     dfsan_label arg_label, dfsan_label *ret_label) {
793*fe6060f1SDimitry Andric   return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
794*fe6060f1SDimitry Andric                               start_routine, arg, ret_label);
795*fe6060f1SDimitry Andric }
796*fe6060f1SDimitry Andric 
797*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
798*fe6060f1SDimitry Andric     pthread_t *thread, const pthread_attr_t *attr,
799*fe6060f1SDimitry Andric     void *(*start_routine_trampoline)(void *, void *, dfsan_label,
800*fe6060f1SDimitry Andric                                       dfsan_label *, dfsan_origin,
801*fe6060f1SDimitry Andric                                       dfsan_origin *),
802*fe6060f1SDimitry Andric     void *start_routine, void *arg, dfsan_label thread_label,
803*fe6060f1SDimitry Andric     dfsan_label attr_label, dfsan_label start_routine_label,
804*fe6060f1SDimitry Andric     dfsan_label arg_label, dfsan_label *ret_label, dfsan_origin thread_origin,
805*fe6060f1SDimitry Andric     dfsan_origin attr_origin, dfsan_origin start_routine_origin,
806*fe6060f1SDimitry Andric     dfsan_origin arg_origin, dfsan_origin *ret_origin) {
807*fe6060f1SDimitry Andric   return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
808*fe6060f1SDimitry Andric                               start_routine, arg, ret_label, true);
80968d75effSDimitry Andric }
81068d75effSDimitry Andric 
811e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
812e8d8bef9SDimitry Andric                                                       void **retval,
813e8d8bef9SDimitry Andric                                                       dfsan_label thread_label,
814e8d8bef9SDimitry Andric                                                       dfsan_label retval_label,
815e8d8bef9SDimitry Andric                                                       dfsan_label *ret_label) {
816e8d8bef9SDimitry Andric   int ret = pthread_join(thread, retval);
817e8d8bef9SDimitry Andric   if (ret == 0 && retval)
818e8d8bef9SDimitry Andric     dfsan_set_label(0, retval, sizeof(*retval));
819e8d8bef9SDimitry Andric   *ret_label = 0;
820e8d8bef9SDimitry Andric   return ret;
821e8d8bef9SDimitry Andric }
822e8d8bef9SDimitry Andric 
823*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
824*fe6060f1SDimitry Andric     pthread_t thread, void **retval, dfsan_label thread_label,
825*fe6060f1SDimitry Andric     dfsan_label retval_label, dfsan_label *ret_label,
826*fe6060f1SDimitry Andric     dfsan_origin thread_origin, dfsan_origin retval_origin,
827*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
828*fe6060f1SDimitry Andric   return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
829*fe6060f1SDimitry Andric                              ret_label);
830*fe6060f1SDimitry Andric }
831*fe6060f1SDimitry Andric 
83268d75effSDimitry Andric struct dl_iterate_phdr_info {
83368d75effSDimitry Andric   int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
83468d75effSDimitry Andric                              size_t size, void *data, dfsan_label info_label,
83568d75effSDimitry Andric                              dfsan_label size_label, dfsan_label data_label,
83668d75effSDimitry Andric                              dfsan_label *ret_label);
83768d75effSDimitry Andric   void *callback;
83868d75effSDimitry Andric   void *data;
83968d75effSDimitry Andric };
84068d75effSDimitry Andric 
841*fe6060f1SDimitry Andric struct dl_iterate_phdr_origin_info {
842*fe6060f1SDimitry Andric   int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
843*fe6060f1SDimitry Andric                              size_t size, void *data, dfsan_label info_label,
844*fe6060f1SDimitry Andric                              dfsan_label size_label, dfsan_label data_label,
845*fe6060f1SDimitry Andric                              dfsan_label *ret_label, dfsan_origin info_origin,
846*fe6060f1SDimitry Andric                              dfsan_origin size_origin, dfsan_origin data_origin,
847*fe6060f1SDimitry Andric                              dfsan_origin *ret_origin);
848*fe6060f1SDimitry Andric   void *callback;
849*fe6060f1SDimitry Andric   void *data;
850*fe6060f1SDimitry Andric };
851*fe6060f1SDimitry Andric 
85268d75effSDimitry Andric int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
85368d75effSDimitry Andric   dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
85468d75effSDimitry Andric   dfsan_set_label(0, *info);
85568d75effSDimitry Andric   dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
85668d75effSDimitry Andric                   strlen(info->dlpi_name) + 1);
85768d75effSDimitry Andric   dfsan_set_label(
85868d75effSDimitry Andric       0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
85968d75effSDimitry Andric       sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
86068d75effSDimitry Andric   dfsan_label ret_label;
86168d75effSDimitry Andric   return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
86268d75effSDimitry Andric                                    0, &ret_label);
86368d75effSDimitry Andric }
86468d75effSDimitry Andric 
865*fe6060f1SDimitry Andric int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size,
866*fe6060f1SDimitry Andric                               void *data) {
867*fe6060f1SDimitry Andric   dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data;
868*fe6060f1SDimitry Andric   dfsan_set_label(0, *info);
869*fe6060f1SDimitry Andric   dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
870*fe6060f1SDimitry Andric                   strlen(info->dlpi_name) + 1);
871*fe6060f1SDimitry Andric   dfsan_set_label(
872*fe6060f1SDimitry Andric       0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
873*fe6060f1SDimitry Andric       sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
874*fe6060f1SDimitry Andric   dfsan_label ret_label;
875*fe6060f1SDimitry Andric   dfsan_origin ret_origin;
876*fe6060f1SDimitry Andric   return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
877*fe6060f1SDimitry Andric                                    0, &ret_label, 0, 0, 0, &ret_origin);
878*fe6060f1SDimitry Andric }
879*fe6060f1SDimitry Andric 
88068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
88168d75effSDimitry Andric     int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
88268d75effSDimitry Andric                                size_t size, void *data, dfsan_label info_label,
88368d75effSDimitry Andric                                dfsan_label size_label, dfsan_label data_label,
88468d75effSDimitry Andric                                dfsan_label *ret_label),
88568d75effSDimitry Andric     void *callback, void *data, dfsan_label callback_label,
88668d75effSDimitry Andric     dfsan_label data_label, dfsan_label *ret_label) {
88768d75effSDimitry Andric   dl_iterate_phdr_info dipi = { callback_trampoline, callback, data };
88868d75effSDimitry Andric   *ret_label = 0;
88968d75effSDimitry Andric   return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
89068d75effSDimitry Andric }
89168d75effSDimitry Andric 
892*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
893*fe6060f1SDimitry Andric     int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
894*fe6060f1SDimitry Andric                                size_t size, void *data, dfsan_label info_label,
895*fe6060f1SDimitry Andric                                dfsan_label size_label, dfsan_label data_label,
896*fe6060f1SDimitry Andric                                dfsan_label *ret_label, dfsan_origin info_origin,
897*fe6060f1SDimitry Andric                                dfsan_origin size_origin,
898*fe6060f1SDimitry Andric                                dfsan_origin data_origin,
899*fe6060f1SDimitry Andric                                dfsan_origin *ret_origin),
900*fe6060f1SDimitry Andric     void *callback, void *data, dfsan_label callback_label,
901*fe6060f1SDimitry Andric     dfsan_label data_label, dfsan_label *ret_label,
902*fe6060f1SDimitry Andric     dfsan_origin callback_origin, dfsan_origin data_origin,
903*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
904*fe6060f1SDimitry Andric   dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data};
905*fe6060f1SDimitry Andric   *ret_label = 0;
906*fe6060f1SDimitry Andric   return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi);
907*fe6060f1SDimitry Andric }
908*fe6060f1SDimitry Andric 
909e8d8bef9SDimitry Andric // This function is only available for glibc 2.27 or newer.  Mark it weak so
910e8d8bef9SDimitry Andric // linking succeeds with older glibcs.
911e8d8bef9SDimitry Andric SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
912e8d8bef9SDimitry Andric                                                       size_t *alignp);
913e8d8bef9SDimitry Andric 
914e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
915e8d8bef9SDimitry Andric     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
916e8d8bef9SDimitry Andric     dfsan_label alignp_label) {
917e8d8bef9SDimitry Andric   assert(_dl_get_tls_static_info);
918e8d8bef9SDimitry Andric   _dl_get_tls_static_info(sizep, alignp);
919e8d8bef9SDimitry Andric   dfsan_set_label(0, sizep, sizeof(*sizep));
920e8d8bef9SDimitry Andric   dfsan_set_label(0, alignp, sizeof(*alignp));
921e8d8bef9SDimitry Andric }
922e8d8bef9SDimitry Andric 
923*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
924*fe6060f1SDimitry Andric     size_t *sizep, size_t *alignp, dfsan_label sizep_label,
925*fe6060f1SDimitry Andric     dfsan_label alignp_label, dfsan_origin sizep_origin,
926*fe6060f1SDimitry Andric     dfsan_origin alignp_origin) {
927*fe6060f1SDimitry Andric   __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
928*fe6060f1SDimitry Andric }
929*fe6060f1SDimitry Andric 
93068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
93168d75effSDimitry Andric char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
93268d75effSDimitry Andric                      dfsan_label buf_label, dfsan_label *ret_label) {
93368d75effSDimitry Andric   char *ret = ctime_r(timep, buf);
93468d75effSDimitry Andric   if (ret) {
93568d75effSDimitry Andric     dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
93668d75effSDimitry Andric                     strlen(buf) + 1);
93768d75effSDimitry Andric     *ret_label = buf_label;
93868d75effSDimitry Andric   } else {
93968d75effSDimitry Andric     *ret_label = 0;
94068d75effSDimitry Andric   }
94168d75effSDimitry Andric   return ret;
94268d75effSDimitry Andric }
94368d75effSDimitry Andric 
94468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
945*fe6060f1SDimitry Andric char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
946*fe6060f1SDimitry Andric                      dfsan_label buf_label, dfsan_label *ret_label,
947*fe6060f1SDimitry Andric                      dfsan_origin timep_origin, dfsan_origin buf_origin,
948*fe6060f1SDimitry Andric                      dfsan_origin *ret_origin) {
949*fe6060f1SDimitry Andric   char *ret = ctime_r(timep, buf);
950*fe6060f1SDimitry Andric   if (ret) {
951*fe6060f1SDimitry Andric     dfsan_set_label_origin(
952*fe6060f1SDimitry Andric         dfsan_read_label(timep, sizeof(time_t)),
953*fe6060f1SDimitry Andric         dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
954*fe6060f1SDimitry Andric         strlen(buf) + 1);
955*fe6060f1SDimitry Andric     *ret_label = buf_label;
956*fe6060f1SDimitry Andric     *ret_origin = buf_origin;
957*fe6060f1SDimitry Andric   } else {
958*fe6060f1SDimitry Andric     *ret_label = 0;
959*fe6060f1SDimitry Andric   }
960*fe6060f1SDimitry Andric   return ret;
961*fe6060f1SDimitry Andric }
962*fe6060f1SDimitry Andric 
963*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
96468d75effSDimitry Andric char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
96568d75effSDimitry Andric                    dfsan_label size_label, dfsan_label stream_label,
96668d75effSDimitry Andric                    dfsan_label *ret_label) {
96768d75effSDimitry Andric   char *ret = fgets(s, size, stream);
96868d75effSDimitry Andric   if (ret) {
96968d75effSDimitry Andric     dfsan_set_label(0, ret, strlen(ret) + 1);
97068d75effSDimitry Andric     *ret_label = s_label;
97168d75effSDimitry Andric   } else {
97268d75effSDimitry Andric     *ret_label = 0;
97368d75effSDimitry Andric   }
97468d75effSDimitry Andric   return ret;
97568d75effSDimitry Andric }
97668d75effSDimitry Andric 
97768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
978*fe6060f1SDimitry Andric char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
979*fe6060f1SDimitry Andric                    dfsan_label size_label, dfsan_label stream_label,
980*fe6060f1SDimitry Andric                    dfsan_label *ret_label, dfsan_origin s_origin,
981*fe6060f1SDimitry Andric                    dfsan_origin size_origin, dfsan_origin stream_origin,
982*fe6060f1SDimitry Andric                    dfsan_origin *ret_origin) {
983*fe6060f1SDimitry Andric   char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
984*fe6060f1SDimitry Andric                            ret_label);
985*fe6060f1SDimitry Andric   if (ret)
986*fe6060f1SDimitry Andric     *ret_origin = s_origin;
987*fe6060f1SDimitry Andric   return ret;
988*fe6060f1SDimitry Andric }
989*fe6060f1SDimitry Andric 
990*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
99168d75effSDimitry Andric char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
99268d75effSDimitry Andric                     dfsan_label size_label, dfsan_label *ret_label) {
99368d75effSDimitry Andric   char *ret = getcwd(buf, size);
99468d75effSDimitry Andric   if (ret) {
99568d75effSDimitry Andric     dfsan_set_label(0, ret, strlen(ret) + 1);
99668d75effSDimitry Andric     *ret_label = buf_label;
99768d75effSDimitry Andric   } else {
99868d75effSDimitry Andric     *ret_label = 0;
99968d75effSDimitry Andric   }
100068d75effSDimitry Andric   return ret;
100168d75effSDimitry Andric }
100268d75effSDimitry Andric 
100368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1004*fe6060f1SDimitry Andric char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
1005*fe6060f1SDimitry Andric                     dfsan_label size_label, dfsan_label *ret_label,
1006*fe6060f1SDimitry Andric                     dfsan_origin buf_origin, dfsan_origin size_origin,
1007*fe6060f1SDimitry Andric                     dfsan_origin *ret_origin) {
1008*fe6060f1SDimitry Andric   char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
1009*fe6060f1SDimitry Andric   if (ret)
1010*fe6060f1SDimitry Andric     *ret_origin = buf_origin;
1011*fe6060f1SDimitry Andric   return ret;
1012*fe6060f1SDimitry Andric }
1013*fe6060f1SDimitry Andric 
1014*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
101568d75effSDimitry Andric char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
101668d75effSDimitry Andric   char *ret = get_current_dir_name();
1017*fe6060f1SDimitry Andric   if (ret)
101868d75effSDimitry Andric     dfsan_set_label(0, ret, strlen(ret) + 1);
101968d75effSDimitry Andric   *ret_label = 0;
102068d75effSDimitry Andric   return ret;
102168d75effSDimitry Andric }
102268d75effSDimitry Andric 
102368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1024*fe6060f1SDimitry Andric char *__dfso_get_current_dir_name(dfsan_label *ret_label,
1025*fe6060f1SDimitry Andric                                   dfsan_origin *ret_origin) {
1026*fe6060f1SDimitry Andric   return __dfsw_get_current_dir_name(ret_label);
1027*fe6060f1SDimitry Andric }
1028*fe6060f1SDimitry Andric 
1029*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
103068d75effSDimitry Andric int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
103168d75effSDimitry Andric                        dfsan_label len_label, dfsan_label *ret_label) {
103268d75effSDimitry Andric   int ret = gethostname(name, len);
103368d75effSDimitry Andric   if (ret == 0) {
103468d75effSDimitry Andric     dfsan_set_label(0, name, strlen(name) + 1);
103568d75effSDimitry Andric   }
103668d75effSDimitry Andric   *ret_label = 0;
103768d75effSDimitry Andric   return ret;
103868d75effSDimitry Andric }
103968d75effSDimitry Andric 
104068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1041*fe6060f1SDimitry Andric int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
1042*fe6060f1SDimitry Andric                        dfsan_label len_label, dfsan_label *ret_label,
1043*fe6060f1SDimitry Andric                        dfsan_origin name_origin, dfsan_origin len_origin,
1044*fe6060f1SDimitry Andric                        dfsan_label *ret_origin) {
1045*fe6060f1SDimitry Andric   return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
1046*fe6060f1SDimitry Andric }
1047*fe6060f1SDimitry Andric 
1048*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
104968d75effSDimitry Andric int __dfsw_getrlimit(int resource, struct rlimit *rlim,
105068d75effSDimitry Andric                      dfsan_label resource_label, dfsan_label rlim_label,
105168d75effSDimitry Andric                      dfsan_label *ret_label) {
105268d75effSDimitry Andric   int ret = getrlimit(resource, rlim);
105368d75effSDimitry Andric   if (ret == 0) {
105468d75effSDimitry Andric     dfsan_set_label(0, rlim, sizeof(struct rlimit));
105568d75effSDimitry Andric   }
105668d75effSDimitry Andric   *ret_label = 0;
105768d75effSDimitry Andric   return ret;
105868d75effSDimitry Andric }
105968d75effSDimitry Andric 
106068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1061*fe6060f1SDimitry Andric int __dfso_getrlimit(int resource, struct rlimit *rlim,
1062*fe6060f1SDimitry Andric                      dfsan_label resource_label, dfsan_label rlim_label,
1063*fe6060f1SDimitry Andric                      dfsan_label *ret_label, dfsan_origin resource_origin,
1064*fe6060f1SDimitry Andric                      dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
1065*fe6060f1SDimitry Andric   return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
1066*fe6060f1SDimitry Andric                           ret_label);
1067*fe6060f1SDimitry Andric }
1068*fe6060f1SDimitry Andric 
1069*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
107068d75effSDimitry Andric int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
107168d75effSDimitry Andric                      dfsan_label usage_label, dfsan_label *ret_label) {
107268d75effSDimitry Andric   int ret = getrusage(who, usage);
107368d75effSDimitry Andric   if (ret == 0) {
107468d75effSDimitry Andric     dfsan_set_label(0, usage, sizeof(struct rusage));
107568d75effSDimitry Andric   }
107668d75effSDimitry Andric   *ret_label = 0;
107768d75effSDimitry Andric   return ret;
107868d75effSDimitry Andric }
107968d75effSDimitry Andric 
108068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1081*fe6060f1SDimitry Andric int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
1082*fe6060f1SDimitry Andric                      dfsan_label usage_label, dfsan_label *ret_label,
1083*fe6060f1SDimitry Andric                      dfsan_origin who_origin, dfsan_origin usage_origin,
1084*fe6060f1SDimitry Andric                      dfsan_label *ret_origin) {
1085*fe6060f1SDimitry Andric   return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
1086*fe6060f1SDimitry Andric }
1087*fe6060f1SDimitry Andric 
1088*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
108968d75effSDimitry Andric char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
109068d75effSDimitry Andric                     dfsan_label src_label, dfsan_label *ret_label) {
109168d75effSDimitry Andric   char *ret = strcpy(dest, src);  // NOLINT
109268d75effSDimitry Andric   if (ret) {
109368d75effSDimitry Andric     internal_memcpy(shadow_for(dest), shadow_for(src),
109468d75effSDimitry Andric                     sizeof(dfsan_label) * (strlen(src) + 1));
109568d75effSDimitry Andric   }
109668d75effSDimitry Andric   *ret_label = dst_label;
109768d75effSDimitry Andric   return ret;
109868d75effSDimitry Andric }
109968d75effSDimitry Andric 
110068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1101*fe6060f1SDimitry Andric char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
1102*fe6060f1SDimitry Andric                     dfsan_label src_label, dfsan_label *ret_label,
1103*fe6060f1SDimitry Andric                     dfsan_origin dst_origin, dfsan_origin src_origin,
1104*fe6060f1SDimitry Andric                     dfsan_origin *ret_origin) {
1105*fe6060f1SDimitry Andric   char *ret = strcpy(dest, src);  // NOLINT
1106*fe6060f1SDimitry Andric   if (ret) {
1107*fe6060f1SDimitry Andric     size_t str_len = strlen(src) + 1;
1108*fe6060f1SDimitry Andric     dfsan_mem_origin_transfer(dest, src, str_len);
1109*fe6060f1SDimitry Andric     internal_memcpy(shadow_for(dest), shadow_for(src),
1110*fe6060f1SDimitry Andric                     sizeof(dfsan_label) * str_len);
111168d75effSDimitry Andric   }
1112*fe6060f1SDimitry Andric   *ret_label = dst_label;
1113*fe6060f1SDimitry Andric   *ret_origin = dst_origin;
1114*fe6060f1SDimitry Andric   return ret;
1115*fe6060f1SDimitry Andric }
1116*fe6060f1SDimitry Andric 
1117*fe6060f1SDimitry Andric static long int dfsan_strtol(const char *nptr, char **endptr, int base,
1118*fe6060f1SDimitry Andric                              char **tmp_endptr) {
1119*fe6060f1SDimitry Andric   assert(tmp_endptr);
1120*fe6060f1SDimitry Andric   long int ret = strtol(nptr, tmp_endptr, base);
1121*fe6060f1SDimitry Andric   if (endptr)
1122*fe6060f1SDimitry Andric     *endptr = *tmp_endptr;
1123*fe6060f1SDimitry Andric   return ret;
1124*fe6060f1SDimitry Andric }
1125*fe6060f1SDimitry Andric 
1126*fe6060f1SDimitry Andric static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
1127*fe6060f1SDimitry Andric                                   dfsan_label base_label,
1128*fe6060f1SDimitry Andric                                   dfsan_label *ret_label) {
112968d75effSDimitry Andric   if (tmp_endptr > nptr) {
113068d75effSDimitry Andric     // If *tmp_endptr is '\0' include its label as well.
113168d75effSDimitry Andric     *ret_label = dfsan_union(
113268d75effSDimitry Andric         base_label,
113368d75effSDimitry Andric         dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
113468d75effSDimitry Andric   } else {
113568d75effSDimitry Andric     *ret_label = 0;
113668d75effSDimitry Andric   }
1137*fe6060f1SDimitry Andric }
1138*fe6060f1SDimitry Andric 
1139*fe6060f1SDimitry Andric static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
1140*fe6060f1SDimitry Andric                                    dfsan_label base_label,
1141*fe6060f1SDimitry Andric                                    dfsan_label *ret_label,
1142*fe6060f1SDimitry Andric                                    dfsan_origin base_origin,
1143*fe6060f1SDimitry Andric                                    dfsan_origin *ret_origin) {
1144*fe6060f1SDimitry Andric   if (tmp_endptr > nptr) {
1145*fe6060f1SDimitry Andric     // When multiple inputs are tainted, we propagate one of its origins.
1146*fe6060f1SDimitry Andric     // Because checking if base_label is tainted does not need additional
1147*fe6060f1SDimitry Andric     // computation, we prefer to propagating base_origin.
1148*fe6060f1SDimitry Andric     *ret_origin = base_label
1149*fe6060f1SDimitry Andric                       ? base_origin
1150*fe6060f1SDimitry Andric                       : dfsan_read_origin_of_first_taint(
1151*fe6060f1SDimitry Andric                             nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1152*fe6060f1SDimitry Andric   }
1153*fe6060f1SDimitry Andric }
1154*fe6060f1SDimitry Andric 
1155*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1156*fe6060f1SDimitry Andric long int __dfsw_strtol(const char *nptr, char **endptr, int base,
1157*fe6060f1SDimitry Andric                        dfsan_label nptr_label, dfsan_label endptr_label,
1158*fe6060f1SDimitry Andric                        dfsan_label base_label, dfsan_label *ret_label) {
1159*fe6060f1SDimitry Andric   char *tmp_endptr;
1160*fe6060f1SDimitry Andric   long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1161*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
116268d75effSDimitry Andric   return ret;
116368d75effSDimitry Andric }
116468d75effSDimitry Andric 
116568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1166*fe6060f1SDimitry Andric long int __dfso_strtol(const char *nptr, char **endptr, int base,
116768d75effSDimitry Andric                        dfsan_label nptr_label, dfsan_label endptr_label,
1168*fe6060f1SDimitry Andric                        dfsan_label base_label, dfsan_label *ret_label,
1169*fe6060f1SDimitry Andric                        dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1170*fe6060f1SDimitry Andric                        dfsan_origin base_origin, dfsan_origin *ret_origin) {
117168d75effSDimitry Andric   char *tmp_endptr;
1172*fe6060f1SDimitry Andric   long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1173*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1174*fe6060f1SDimitry Andric   dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1175*fe6060f1SDimitry Andric                          ret_origin);
1176*fe6060f1SDimitry Andric   return ret;
117768d75effSDimitry Andric }
1178*fe6060f1SDimitry Andric 
1179*fe6060f1SDimitry Andric static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
1180*fe6060f1SDimitry Andric   assert(tmp_endptr);
1181*fe6060f1SDimitry Andric   double ret = strtod(nptr, tmp_endptr);
1182*fe6060f1SDimitry Andric   if (endptr)
1183*fe6060f1SDimitry Andric     *endptr = *tmp_endptr;
1184*fe6060f1SDimitry Andric   return ret;
1185*fe6060f1SDimitry Andric }
1186*fe6060f1SDimitry Andric 
1187*fe6060f1SDimitry Andric static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
1188*fe6060f1SDimitry Andric                                dfsan_label *ret_label) {
118968d75effSDimitry Andric   if (tmp_endptr > nptr) {
119068d75effSDimitry Andric     // If *tmp_endptr is '\0' include its label as well.
119168d75effSDimitry Andric     *ret_label = dfsan_read_label(
119268d75effSDimitry Andric         nptr,
119368d75effSDimitry Andric         tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
119468d75effSDimitry Andric   } else {
119568d75effSDimitry Andric     *ret_label = 0;
119668d75effSDimitry Andric   }
1197*fe6060f1SDimitry Andric }
1198*fe6060f1SDimitry Andric 
1199*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1200*fe6060f1SDimitry Andric double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1201*fe6060f1SDimitry Andric                      dfsan_label endptr_label, dfsan_label *ret_label) {
1202*fe6060f1SDimitry Andric   char *tmp_endptr;
1203*fe6060f1SDimitry Andric   double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1204*fe6060f1SDimitry Andric   dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1205*fe6060f1SDimitry Andric   return ret;
1206*fe6060f1SDimitry Andric }
1207*fe6060f1SDimitry Andric 
1208*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1209*fe6060f1SDimitry Andric double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
1210*fe6060f1SDimitry Andric                      dfsan_label endptr_label, dfsan_label *ret_label,
1211*fe6060f1SDimitry Andric                      dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1212*fe6060f1SDimitry Andric                      dfsan_origin *ret_origin) {
1213*fe6060f1SDimitry Andric   char *tmp_endptr;
1214*fe6060f1SDimitry Andric   double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
1215*fe6060f1SDimitry Andric   dfsan_strtod_label(nptr, tmp_endptr, ret_label);
1216*fe6060f1SDimitry Andric   if (tmp_endptr > nptr) {
1217*fe6060f1SDimitry Andric     // If *tmp_endptr is '\0' include its label as well.
1218*fe6060f1SDimitry Andric     *ret_origin = dfsan_read_origin_of_first_taint(
1219*fe6060f1SDimitry Andric         nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
1220*fe6060f1SDimitry Andric   } else {
1221*fe6060f1SDimitry Andric     *ret_origin = 0;
1222*fe6060f1SDimitry Andric   }
1223*fe6060f1SDimitry Andric   return ret;
1224*fe6060f1SDimitry Andric }
1225*fe6060f1SDimitry Andric 
1226*fe6060f1SDimitry Andric static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
1227*fe6060f1SDimitry Andric                                    char **tmp_endptr) {
1228*fe6060f1SDimitry Andric   assert(tmp_endptr);
1229*fe6060f1SDimitry Andric   long long int ret = strtoll(nptr, tmp_endptr, base);
1230*fe6060f1SDimitry Andric   if (endptr)
1231*fe6060f1SDimitry Andric     *endptr = *tmp_endptr;
123268d75effSDimitry Andric   return ret;
123368d75effSDimitry Andric }
123468d75effSDimitry Andric 
123568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
123668d75effSDimitry Andric long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
123768d75effSDimitry Andric                              dfsan_label nptr_label, dfsan_label endptr_label,
123868d75effSDimitry Andric                              dfsan_label base_label, dfsan_label *ret_label) {
123968d75effSDimitry Andric   char *tmp_endptr;
1240*fe6060f1SDimitry Andric   long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1241*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1242*fe6060f1SDimitry Andric   return ret;
124368d75effSDimitry Andric }
1244*fe6060f1SDimitry Andric 
1245*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1246*fe6060f1SDimitry Andric long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
1247*fe6060f1SDimitry Andric                              dfsan_label nptr_label, dfsan_label endptr_label,
1248*fe6060f1SDimitry Andric                              dfsan_label base_label, dfsan_label *ret_label,
1249*fe6060f1SDimitry Andric                              dfsan_origin nptr_origin,
1250*fe6060f1SDimitry Andric                              dfsan_origin endptr_origin,
1251*fe6060f1SDimitry Andric                              dfsan_origin base_origin,
1252*fe6060f1SDimitry Andric                              dfsan_origin *ret_origin) {
1253*fe6060f1SDimitry Andric   char *tmp_endptr;
1254*fe6060f1SDimitry Andric   long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1255*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1256*fe6060f1SDimitry Andric   dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1257*fe6060f1SDimitry Andric                          ret_origin);
1258*fe6060f1SDimitry Andric   return ret;
125968d75effSDimitry Andric }
1260*fe6060f1SDimitry Andric 
1261*fe6060f1SDimitry Andric static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
1262*fe6060f1SDimitry Andric                                        int base, char **tmp_endptr) {
1263*fe6060f1SDimitry Andric   assert(tmp_endptr);
1264*fe6060f1SDimitry Andric   unsigned long int ret = strtoul(nptr, tmp_endptr, base);
1265*fe6060f1SDimitry Andric   if (endptr)
1266*fe6060f1SDimitry Andric     *endptr = *tmp_endptr;
126768d75effSDimitry Andric   return ret;
126868d75effSDimitry Andric }
126968d75effSDimitry Andric 
127068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
127168d75effSDimitry Andric unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
127268d75effSDimitry Andric                        dfsan_label nptr_label, dfsan_label endptr_label,
127368d75effSDimitry Andric                        dfsan_label base_label, dfsan_label *ret_label) {
127468d75effSDimitry Andric   char *tmp_endptr;
1275*fe6060f1SDimitry Andric   unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1276*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1277*fe6060f1SDimitry Andric   return ret;
127868d75effSDimitry Andric }
1279*fe6060f1SDimitry Andric 
1280*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1281*fe6060f1SDimitry Andric unsigned long int __dfso_strtoul(
1282*fe6060f1SDimitry Andric     const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1283*fe6060f1SDimitry Andric     dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1284*fe6060f1SDimitry Andric     dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1285*fe6060f1SDimitry Andric     dfsan_origin base_origin, dfsan_origin *ret_origin) {
1286*fe6060f1SDimitry Andric   char *tmp_endptr;
1287*fe6060f1SDimitry Andric   unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1288*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1289*fe6060f1SDimitry Andric   dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1290*fe6060f1SDimitry Andric                          ret_origin);
1291*fe6060f1SDimitry Andric   return ret;
129268d75effSDimitry Andric }
1293*fe6060f1SDimitry Andric 
1294*fe6060f1SDimitry Andric static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
1295*fe6060f1SDimitry Andric                                              int base, char **tmp_endptr) {
1296*fe6060f1SDimitry Andric   assert(tmp_endptr);
1297*fe6060f1SDimitry Andric   long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
1298*fe6060f1SDimitry Andric   if (endptr)
1299*fe6060f1SDimitry Andric     *endptr = *tmp_endptr;
130068d75effSDimitry Andric   return ret;
130168d75effSDimitry Andric }
130268d75effSDimitry Andric 
130368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
130468d75effSDimitry Andric long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
1305e8d8bef9SDimitry Andric                                        int base, dfsan_label nptr_label,
1306e8d8bef9SDimitry Andric                                        dfsan_label endptr_label,
130768d75effSDimitry Andric                                        dfsan_label base_label,
130868d75effSDimitry Andric                                        dfsan_label *ret_label) {
130968d75effSDimitry Andric   char *tmp_endptr;
1310*fe6060f1SDimitry Andric   long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1311*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1312*fe6060f1SDimitry Andric   return ret;
131368d75effSDimitry Andric }
1314*fe6060f1SDimitry Andric 
1315*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1316*fe6060f1SDimitry Andric long long unsigned int __dfso_strtoull(
1317*fe6060f1SDimitry Andric     const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1318*fe6060f1SDimitry Andric     dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1319*fe6060f1SDimitry Andric     dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1320*fe6060f1SDimitry Andric     dfsan_origin base_origin, dfsan_origin *ret_origin) {
1321*fe6060f1SDimitry Andric   char *tmp_endptr;
1322*fe6060f1SDimitry Andric   long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1323*fe6060f1SDimitry Andric   dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1324*fe6060f1SDimitry Andric   dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1325*fe6060f1SDimitry Andric                          ret_origin);
132668d75effSDimitry Andric   return ret;
132768d75effSDimitry Andric }
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
1340*fe6060f1SDimitry Andric time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
1341*fe6060f1SDimitry Andric                    dfsan_origin t_origin, dfsan_origin *ret_origin) {
1342*fe6060f1SDimitry Andric   return __dfsw_time(t, t_label, ret_label);
1343*fe6060f1SDimitry Andric }
1344*fe6060f1SDimitry Andric 
1345*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1359*fe6060f1SDimitry Andric int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
1360*fe6060f1SDimitry Andric                      dfsan_label src_label, dfsan_label dst_label,
1361*fe6060f1SDimitry Andric                      dfsan_label *ret_label, dfsan_origin af_origin,
1362*fe6060f1SDimitry Andric                      dfsan_origin src_origin, dfsan_origin dst_origin,
1363*fe6060f1SDimitry Andric                      dfsan_origin *ret_origin) {
1364*fe6060f1SDimitry Andric   int ret = inet_pton(af, src, dst);
1365*fe6060f1SDimitry Andric   if (ret == 1) {
1366*fe6060f1SDimitry Andric     int src_len = strlen(src) + 1;
1367*fe6060f1SDimitry Andric     dfsan_set_label_origin(
1368*fe6060f1SDimitry Andric         dfsan_read_label(src, src_len),
1369*fe6060f1SDimitry Andric         dfsan_read_origin_of_first_taint(src, src_len), dst,
1370*fe6060f1SDimitry Andric         af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
1371*fe6060f1SDimitry Andric   }
1372*fe6060f1SDimitry Andric   *ret_label = 0;
1373*fe6060f1SDimitry Andric   return ret;
1374*fe6060f1SDimitry Andric }
1375*fe6060f1SDimitry Andric 
1376*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1392*fe6060f1SDimitry Andric struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
1393*fe6060f1SDimitry Andric                               dfsan_label timep_label, dfsan_label result_label,
1394*fe6060f1SDimitry Andric                               dfsan_label *ret_label, dfsan_origin timep_origin,
1395*fe6060f1SDimitry Andric                               dfsan_origin result_origin,
1396*fe6060f1SDimitry Andric                               dfsan_origin *ret_origin) {
1397*fe6060f1SDimitry Andric   struct tm *ret = localtime_r(timep, result);
1398*fe6060f1SDimitry Andric   if (ret) {
1399*fe6060f1SDimitry Andric     dfsan_set_label_origin(
1400*fe6060f1SDimitry Andric         dfsan_read_label(timep, sizeof(time_t)),
1401*fe6060f1SDimitry Andric         dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
1402*fe6060f1SDimitry Andric         sizeof(struct tm));
1403*fe6060f1SDimitry Andric     *ret_label = result_label;
1404*fe6060f1SDimitry Andric     *ret_origin = result_origin;
1405*fe6060f1SDimitry Andric   } else {
1406*fe6060f1SDimitry Andric     *ret_label = 0;
1407*fe6060f1SDimitry Andric   }
1408*fe6060f1SDimitry Andric   return ret;
1409*fe6060f1SDimitry Andric }
1410*fe6060f1SDimitry Andric 
1411*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1430*fe6060f1SDimitry Andric int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
1431*fe6060f1SDimitry Andric                       struct passwd **result, dfsan_label uid_label,
1432*fe6060f1SDimitry Andric                       dfsan_label pwd_label, dfsan_label buf_label,
1433*fe6060f1SDimitry Andric                       dfsan_label buflen_label, dfsan_label result_label,
1434*fe6060f1SDimitry Andric                       dfsan_label *ret_label, dfsan_origin uid_origin,
1435*fe6060f1SDimitry Andric                       dfsan_origin pwd_origin, dfsan_origin buf_origin,
1436*fe6060f1SDimitry Andric                       dfsan_origin buflen_origin, dfsan_origin result_origin,
1437*fe6060f1SDimitry Andric                       dfsan_origin *ret_origin) {
1438*fe6060f1SDimitry Andric   return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
1439*fe6060f1SDimitry Andric                            buf_label, buflen_label, result_label, ret_label);
1440*fe6060f1SDimitry Andric }
1441*fe6060f1SDimitry Andric 
1442*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1455*fe6060f1SDimitry Andric int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
1456*fe6060f1SDimitry Andric                       int timeout, dfsan_label epfd_label,
1457*fe6060f1SDimitry Andric                       dfsan_label events_label, dfsan_label maxevents_label,
1458*fe6060f1SDimitry Andric                       dfsan_label timeout_label, dfsan_label *ret_label,
1459*fe6060f1SDimitry Andric                       dfsan_origin epfd_origin, dfsan_origin events_origin,
1460*fe6060f1SDimitry Andric                       dfsan_origin maxevents_origin,
1461*fe6060f1SDimitry Andric                       dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1462*fe6060f1SDimitry Andric   return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
1463*fe6060f1SDimitry Andric                            events_label, maxevents_label, timeout_label,
1464*fe6060f1SDimitry Andric                            ret_label);
1465*fe6060f1SDimitry Andric }
1466*fe6060f1SDimitry Andric 
1467*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1482*fe6060f1SDimitry Andric int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
1483*fe6060f1SDimitry Andric                 dfsan_label dfs_label, dfsan_label nfds_label,
1484*fe6060f1SDimitry Andric                 dfsan_label timeout_label, dfsan_label *ret_label,
1485*fe6060f1SDimitry Andric                 dfsan_origin dfs_origin, dfsan_origin nfds_origin,
1486*fe6060f1SDimitry Andric                 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1487*fe6060f1SDimitry Andric   return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
1488*fe6060f1SDimitry Andric                      ret_label);
1489*fe6060f1SDimitry Andric }
1490*fe6060f1SDimitry Andric 
1491*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1515*fe6060f1SDimitry Andric int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
1516*fe6060f1SDimitry Andric                   fd_set *exceptfds, struct timeval *timeout,
1517*fe6060f1SDimitry Andric                   dfsan_label nfds_label, dfsan_label readfds_label,
1518*fe6060f1SDimitry Andric                   dfsan_label writefds_label, dfsan_label exceptfds_label,
1519*fe6060f1SDimitry Andric                   dfsan_label timeout_label, dfsan_label *ret_label,
1520*fe6060f1SDimitry Andric                   dfsan_origin nfds_origin, dfsan_origin readfds_origin,
1521*fe6060f1SDimitry Andric                   dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
1522*fe6060f1SDimitry Andric                   dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1523*fe6060f1SDimitry Andric   return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
1524*fe6060f1SDimitry Andric                        readfds_label, writefds_label, exceptfds_label,
1525*fe6060f1SDimitry Andric                        timeout_label, ret_label);
1526*fe6060f1SDimitry Andric }
1527*fe6060f1SDimitry Andric 
1528*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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
1542*fe6060f1SDimitry Andric int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
1543*fe6060f1SDimitry Andric                              dfsan_label pid_label,
1544*fe6060f1SDimitry Andric                              dfsan_label cpusetsize_label,
1545*fe6060f1SDimitry Andric                              dfsan_label mask_label, dfsan_label *ret_label,
1546*fe6060f1SDimitry Andric                              dfsan_origin pid_origin,
1547*fe6060f1SDimitry Andric                              dfsan_origin cpusetsize_origin,
1548*fe6060f1SDimitry Andric                              dfsan_origin mask_origin,
1549*fe6060f1SDimitry Andric                              dfsan_origin *ret_origin) {
1550*fe6060f1SDimitry Andric   return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
1551*fe6060f1SDimitry Andric                                   cpusetsize_label, mask_label, ret_label);
1552*fe6060f1SDimitry Andric }
1553*fe6060f1SDimitry Andric 
1554*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
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));
1559*fe6060f1SDimitry Andric   *ret_label = 0;
156068d75effSDimitry Andric   return ret;
156168d75effSDimitry Andric }
156268d75effSDimitry Andric 
156368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1564*fe6060f1SDimitry Andric int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
1565*fe6060f1SDimitry Andric                        dfsan_label *ret_label, dfsan_origin set_origin,
1566*fe6060f1SDimitry Andric                        dfsan_origin *ret_origin) {
1567*fe6060f1SDimitry Andric   return __dfsw_sigemptyset(set, set_label, ret_label);
1568*fe6060f1SDimitry Andric }
1569*fe6060f1SDimitry Andric 
1570*fe6060f1SDimitry Andric class SignalHandlerScope {
1571*fe6060f1SDimitry Andric  public:
1572*fe6060f1SDimitry Andric   SignalHandlerScope() {
1573*fe6060f1SDimitry Andric     if (DFsanThread *t = GetCurrentThread())
1574*fe6060f1SDimitry Andric       t->EnterSignalHandler();
1575*fe6060f1SDimitry Andric   }
1576*fe6060f1SDimitry Andric   ~SignalHandlerScope() {
1577*fe6060f1SDimitry Andric     if (DFsanThread *t = GetCurrentThread())
1578*fe6060f1SDimitry Andric       t->LeaveSignalHandler();
1579*fe6060f1SDimitry Andric   }
1580*fe6060f1SDimitry Andric };
1581*fe6060f1SDimitry Andric 
1582*fe6060f1SDimitry Andric // Clear DFSan runtime TLS state at the end of a scope.
1583*fe6060f1SDimitry Andric //
1584*fe6060f1SDimitry Andric // Implementation must be async-signal-safe and use small data size, because
1585*fe6060f1SDimitry Andric // instances of this class may live on the signal handler stack.
1586*fe6060f1SDimitry Andric //
1587*fe6060f1SDimitry Andric // DFSan uses TLS to pass metadata of arguments and return values. When an
1588*fe6060f1SDimitry Andric // instrumented function accesses the TLS, if a signal callback happens, and the
1589*fe6060f1SDimitry Andric // callback calls other instrumented functions with updating the same TLS, the
1590*fe6060f1SDimitry Andric // TLS is in an inconsistent state after the callback ends. This may cause
1591*fe6060f1SDimitry Andric // either under-tainting or over-tainting.
1592*fe6060f1SDimitry Andric //
1593*fe6060f1SDimitry Andric // The current implementation simply resets TLS at restore. This prevents from
1594*fe6060f1SDimitry Andric // over-tainting. Although under-tainting may still happen, a taint flow can be
1595*fe6060f1SDimitry Andric // found eventually if we run a DFSan-instrumented program multiple times. The
1596*fe6060f1SDimitry Andric // alternative option is saving the entire TLS. However the TLS storage takes
1597*fe6060f1SDimitry Andric // 2k bytes, and signal calls could be nested. So it does not seem worth.
1598*fe6060f1SDimitry Andric class ScopedClearThreadLocalState {
1599*fe6060f1SDimitry Andric  public:
1600*fe6060f1SDimitry Andric   ScopedClearThreadLocalState() {}
1601*fe6060f1SDimitry Andric   ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
1602*fe6060f1SDimitry Andric };
1603*fe6060f1SDimitry Andric 
1604*fe6060f1SDimitry Andric // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
1605*fe6060f1SDimitry Andric const int kMaxSignals = 1024;
1606*fe6060f1SDimitry Andric static atomic_uintptr_t sigactions[kMaxSignals];
1607*fe6060f1SDimitry Andric 
1608*fe6060f1SDimitry Andric static void SignalHandler(int signo) {
1609*fe6060f1SDimitry Andric   SignalHandlerScope signal_handler_scope;
1610*fe6060f1SDimitry Andric   ScopedClearThreadLocalState scoped_clear_tls;
1611*fe6060f1SDimitry Andric 
1612*fe6060f1SDimitry Andric   // Clear shadows for all inputs provided by system. This is why DFSan
1613*fe6060f1SDimitry Andric   // instrumentation generates a trampoline function to each function pointer,
1614*fe6060f1SDimitry Andric   // and uses the trampoline to clear shadows. However sigaction does not use
1615*fe6060f1SDimitry Andric   // a function pointer directly, so we have to do this manually.
1616*fe6060f1SDimitry Andric   dfsan_clear_arg_tls(0, sizeof(dfsan_label));
1617*fe6060f1SDimitry Andric 
1618*fe6060f1SDimitry Andric   typedef void (*signal_cb)(int x);
1619*fe6060f1SDimitry Andric   signal_cb cb =
1620*fe6060f1SDimitry Andric       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1621*fe6060f1SDimitry Andric   cb(signo);
1622*fe6060f1SDimitry Andric }
1623*fe6060f1SDimitry Andric 
1624*fe6060f1SDimitry Andric static void SignalAction(int signo, siginfo_t *si, void *uc) {
1625*fe6060f1SDimitry Andric   SignalHandlerScope signal_handler_scope;
1626*fe6060f1SDimitry Andric   ScopedClearThreadLocalState scoped_clear_tls;
1627*fe6060f1SDimitry Andric 
1628*fe6060f1SDimitry Andric   // Clear shadows for all inputs provided by system. Similar to SignalHandler.
1629*fe6060f1SDimitry Andric   dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
1630*fe6060f1SDimitry Andric   dfsan_set_label(0, si, sizeof(*si));
1631*fe6060f1SDimitry Andric   dfsan_set_label(0, uc, sizeof(ucontext_t));
1632*fe6060f1SDimitry Andric 
1633*fe6060f1SDimitry Andric   typedef void (*sigaction_cb)(int, siginfo_t *, void *);
1634*fe6060f1SDimitry Andric   sigaction_cb cb =
1635*fe6060f1SDimitry Andric       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1636*fe6060f1SDimitry Andric   cb(signo, si, uc);
1637*fe6060f1SDimitry Andric }
1638*fe6060f1SDimitry Andric 
1639*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
164068d75effSDimitry Andric int __dfsw_sigaction(int signum, const struct sigaction *act,
164168d75effSDimitry Andric                      struct sigaction *oldact, dfsan_label signum_label,
164268d75effSDimitry Andric                      dfsan_label act_label, dfsan_label oldact_label,
164368d75effSDimitry Andric                      dfsan_label *ret_label) {
1644*fe6060f1SDimitry Andric   CHECK_LT(signum, kMaxSignals);
1645*fe6060f1SDimitry Andric   SignalSpinLocker lock;
1646*fe6060f1SDimitry Andric   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1647*fe6060f1SDimitry Andric   struct sigaction new_act;
1648*fe6060f1SDimitry Andric   struct sigaction *pnew_act = act ? &new_act : nullptr;
1649*fe6060f1SDimitry Andric   if (act) {
1650*fe6060f1SDimitry Andric     internal_memcpy(pnew_act, act, sizeof(struct sigaction));
1651*fe6060f1SDimitry Andric     if (pnew_act->sa_flags & SA_SIGINFO) {
1652*fe6060f1SDimitry Andric       uptr cb = (uptr)(pnew_act->sa_sigaction);
1653*fe6060f1SDimitry Andric       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1654*fe6060f1SDimitry Andric         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1655*fe6060f1SDimitry Andric         pnew_act->sa_sigaction = SignalAction;
1656*fe6060f1SDimitry Andric       }
1657*fe6060f1SDimitry Andric     } else {
1658*fe6060f1SDimitry Andric       uptr cb = (uptr)(pnew_act->sa_handler);
1659*fe6060f1SDimitry Andric       if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
1660*fe6060f1SDimitry Andric         atomic_store(&sigactions[signum], cb, memory_order_relaxed);
1661*fe6060f1SDimitry Andric         pnew_act->sa_handler = SignalHandler;
1662*fe6060f1SDimitry Andric       }
1663*fe6060f1SDimitry Andric     }
1664*fe6060f1SDimitry Andric   }
1665*fe6060f1SDimitry Andric 
1666*fe6060f1SDimitry Andric   int ret = sigaction(signum, pnew_act, oldact);
1667*fe6060f1SDimitry Andric 
1668*fe6060f1SDimitry Andric   if (ret == 0 && oldact) {
1669*fe6060f1SDimitry Andric     if (oldact->sa_flags & SA_SIGINFO) {
1670*fe6060f1SDimitry Andric       if (oldact->sa_sigaction == SignalAction)
1671*fe6060f1SDimitry Andric         oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
1672*fe6060f1SDimitry Andric     } else {
1673*fe6060f1SDimitry Andric       if (oldact->sa_handler == SignalHandler)
1674*fe6060f1SDimitry Andric         oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
1675*fe6060f1SDimitry Andric     }
1676*fe6060f1SDimitry Andric   }
1677*fe6060f1SDimitry Andric 
167868d75effSDimitry Andric   if (oldact) {
167968d75effSDimitry Andric     dfsan_set_label(0, oldact, sizeof(struct sigaction));
168068d75effSDimitry Andric   }
168168d75effSDimitry Andric   *ret_label = 0;
168268d75effSDimitry Andric   return ret;
168368d75effSDimitry Andric }
168468d75effSDimitry Andric 
168568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1686*fe6060f1SDimitry Andric int __dfso_sigaction(int signum, const struct sigaction *act,
1687*fe6060f1SDimitry Andric                      struct sigaction *oldact, dfsan_label signum_label,
1688*fe6060f1SDimitry Andric                      dfsan_label act_label, dfsan_label oldact_label,
1689*fe6060f1SDimitry Andric                      dfsan_label *ret_label, dfsan_origin signum_origin,
1690*fe6060f1SDimitry Andric                      dfsan_origin act_origin, dfsan_origin oldact_origin,
1691*fe6060f1SDimitry Andric                      dfsan_origin *ret_origin) {
1692*fe6060f1SDimitry Andric   return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
1693*fe6060f1SDimitry Andric                           oldact_label, ret_label);
1694*fe6060f1SDimitry Andric }
1695*fe6060f1SDimitry Andric 
1696*fe6060f1SDimitry Andric static sighandler_t dfsan_signal(int signum, sighandler_t handler,
1697*fe6060f1SDimitry Andric                                  dfsan_label *ret_label) {
1698*fe6060f1SDimitry Andric   CHECK_LT(signum, kMaxSignals);
1699*fe6060f1SDimitry Andric   SignalSpinLocker lock;
1700*fe6060f1SDimitry Andric   uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
1701*fe6060f1SDimitry Andric   if (handler != SIG_IGN && handler != SIG_DFL) {
1702*fe6060f1SDimitry Andric     atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
1703*fe6060f1SDimitry Andric     handler = &SignalHandler;
1704*fe6060f1SDimitry Andric   }
1705*fe6060f1SDimitry Andric 
1706*fe6060f1SDimitry Andric   sighandler_t ret = signal(signum, handler);
1707*fe6060f1SDimitry Andric 
1708*fe6060f1SDimitry Andric   if (ret == SignalHandler)
1709*fe6060f1SDimitry Andric     ret = (sighandler_t)old_cb;
1710*fe6060f1SDimitry Andric 
1711*fe6060f1SDimitry Andric   *ret_label = 0;
1712*fe6060f1SDimitry Andric   return ret;
1713*fe6060f1SDimitry Andric }
1714*fe6060f1SDimitry Andric 
1715*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1716*fe6060f1SDimitry Andric sighandler_t __dfsw_signal(int signum,
1717*fe6060f1SDimitry Andric                            void *(*handler_trampoline)(void *, int, dfsan_label,
1718*fe6060f1SDimitry Andric                                                        dfsan_label *),
1719*fe6060f1SDimitry Andric                            sighandler_t handler, dfsan_label signum_label,
1720*fe6060f1SDimitry Andric                            dfsan_label handler_label, dfsan_label *ret_label) {
1721*fe6060f1SDimitry Andric   return dfsan_signal(signum, handler, ret_label);
1722*fe6060f1SDimitry Andric }
1723*fe6060f1SDimitry Andric 
1724*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1725*fe6060f1SDimitry Andric sighandler_t __dfso_signal(
1726*fe6060f1SDimitry Andric     int signum,
1727*fe6060f1SDimitry Andric     void *(*handler_trampoline)(void *, int, dfsan_label, dfsan_label *,
1728*fe6060f1SDimitry Andric                                 dfsan_origin, dfsan_origin *),
1729*fe6060f1SDimitry Andric     sighandler_t handler, dfsan_label signum_label, dfsan_label handler_label,
1730*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin signum_origin,
1731*fe6060f1SDimitry Andric     dfsan_origin handler_origin, dfsan_origin *ret_origin) {
1732*fe6060f1SDimitry Andric   return dfsan_signal(signum, handler, ret_label);
1733*fe6060f1SDimitry Andric }
1734*fe6060f1SDimitry Andric 
1735*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1736e8d8bef9SDimitry Andric int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1737e8d8bef9SDimitry Andric                        dfsan_label old_ss_label, dfsan_label *ret_label) {
1738e8d8bef9SDimitry Andric   int ret = sigaltstack(ss, old_ss);
1739e8d8bef9SDimitry Andric   if (ret != -1 && old_ss)
1740e8d8bef9SDimitry Andric     dfsan_set_label(0, old_ss, sizeof(*old_ss));
1741e8d8bef9SDimitry Andric   *ret_label = 0;
1742e8d8bef9SDimitry Andric   return ret;
1743e8d8bef9SDimitry Andric }
1744e8d8bef9SDimitry Andric 
1745e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1746*fe6060f1SDimitry Andric int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
1747*fe6060f1SDimitry Andric                        dfsan_label old_ss_label, dfsan_label *ret_label,
1748*fe6060f1SDimitry Andric                        dfsan_origin ss_origin, dfsan_origin old_ss_origin,
1749*fe6060f1SDimitry Andric                        dfsan_origin *ret_origin) {
1750*fe6060f1SDimitry Andric   return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
1751*fe6060f1SDimitry Andric }
1752*fe6060f1SDimitry Andric 
1753*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
175468d75effSDimitry Andric int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
175568d75effSDimitry Andric                         dfsan_label tv_label, dfsan_label tz_label,
175668d75effSDimitry Andric                         dfsan_label *ret_label) {
175768d75effSDimitry Andric   int ret = gettimeofday(tv, tz);
175868d75effSDimitry Andric   if (tv) {
175968d75effSDimitry Andric     dfsan_set_label(0, tv, sizeof(struct timeval));
176068d75effSDimitry Andric   }
176168d75effSDimitry Andric   if (tz) {
176268d75effSDimitry Andric     dfsan_set_label(0, tz, sizeof(struct timezone));
176368d75effSDimitry Andric   }
176468d75effSDimitry Andric   *ret_label = 0;
176568d75effSDimitry Andric   return ret;
176668d75effSDimitry Andric }
176768d75effSDimitry Andric 
1768*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
1769*fe6060f1SDimitry Andric int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
1770*fe6060f1SDimitry Andric                         dfsan_label tv_label, dfsan_label tz_label,
1771*fe6060f1SDimitry Andric                         dfsan_label *ret_label, dfsan_origin tv_origin,
1772*fe6060f1SDimitry Andric                         dfsan_origin tz_origin, dfsan_origin *ret_origin) {
1773*fe6060f1SDimitry Andric   return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
1774*fe6060f1SDimitry Andric }
1775*fe6060f1SDimitry Andric 
177668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
177768d75effSDimitry Andric                                                   dfsan_label s_label,
177868d75effSDimitry Andric                                                   dfsan_label c_label,
177968d75effSDimitry Andric                                                   dfsan_label n_label,
178068d75effSDimitry Andric                                                   dfsan_label *ret_label) {
178168d75effSDimitry Andric   void *ret = memchr(s, c, n);
178268d75effSDimitry Andric   if (flags().strict_data_dependencies) {
178368d75effSDimitry Andric     *ret_label = ret ? s_label : 0;
178468d75effSDimitry Andric   } else {
178568d75effSDimitry Andric     size_t len =
178668d75effSDimitry Andric         ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
178768d75effSDimitry Andric             : n;
178868d75effSDimitry Andric     *ret_label =
178968d75effSDimitry Andric         dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
179068d75effSDimitry Andric   }
179168d75effSDimitry Andric   return ret;
179268d75effSDimitry Andric }
179368d75effSDimitry Andric 
1794*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
1795*fe6060f1SDimitry Andric     void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
1796*fe6060f1SDimitry Andric     dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
1797*fe6060f1SDimitry Andric     dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
1798*fe6060f1SDimitry Andric   void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
1799*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies) {
1800*fe6060f1SDimitry Andric     if (ret)
1801*fe6060f1SDimitry Andric       *ret_origin = s_origin;
1802*fe6060f1SDimitry Andric   } else {
1803*fe6060f1SDimitry Andric     size_t len =
1804*fe6060f1SDimitry Andric         ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
1805*fe6060f1SDimitry Andric             : n;
1806*fe6060f1SDimitry Andric     dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
1807*fe6060f1SDimitry Andric     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1808*fe6060f1SDimitry Andric   }
1809*fe6060f1SDimitry Andric   return ret;
1810*fe6060f1SDimitry Andric }
1811*fe6060f1SDimitry Andric 
181268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
181368d75effSDimitry Andric                                                    dfsan_label s_label,
181468d75effSDimitry Andric                                                    dfsan_label c_label,
181568d75effSDimitry Andric                                                    dfsan_label *ret_label) {
181668d75effSDimitry Andric   char *ret = strrchr(s, c);
181768d75effSDimitry Andric   if (flags().strict_data_dependencies) {
181868d75effSDimitry Andric     *ret_label = ret ? s_label : 0;
181968d75effSDimitry Andric   } else {
182068d75effSDimitry Andric     *ret_label =
182168d75effSDimitry Andric         dfsan_union(dfsan_read_label(s, strlen(s) + 1),
182268d75effSDimitry Andric                     dfsan_union(s_label, c_label));
182368d75effSDimitry Andric   }
182468d75effSDimitry Andric 
182568d75effSDimitry Andric   return ret;
182668d75effSDimitry Andric }
182768d75effSDimitry Andric 
1828*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
1829*fe6060f1SDimitry Andric     char *s, int c, dfsan_label s_label, dfsan_label c_label,
1830*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
1831*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
1832*fe6060f1SDimitry Andric   char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
1833*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies) {
1834*fe6060f1SDimitry Andric     if (ret)
1835*fe6060f1SDimitry Andric       *ret_origin = s_origin;
1836*fe6060f1SDimitry Andric   } else {
1837*fe6060f1SDimitry Andric     size_t s_len = strlen(s) + 1;
1838*fe6060f1SDimitry Andric     dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
1839*fe6060f1SDimitry Andric     *ret_origin = o ? o : (s_label ? s_origin : c_origin);
1840*fe6060f1SDimitry Andric   }
1841*fe6060f1SDimitry Andric 
1842*fe6060f1SDimitry Andric   return ret;
1843*fe6060f1SDimitry Andric }
1844*fe6060f1SDimitry Andric 
184568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
184668d75effSDimitry Andric                                                   dfsan_label haystack_label,
184768d75effSDimitry Andric                                                   dfsan_label needle_label,
184868d75effSDimitry Andric                                                   dfsan_label *ret_label) {
184968d75effSDimitry Andric   char *ret = strstr(haystack, needle);
185068d75effSDimitry Andric   if (flags().strict_data_dependencies) {
185168d75effSDimitry Andric     *ret_label = ret ? haystack_label : 0;
185268d75effSDimitry Andric   } else {
185368d75effSDimitry Andric     size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
185468d75effSDimitry Andric     *ret_label =
185568d75effSDimitry Andric         dfsan_union(dfsan_read_label(haystack, len),
185668d75effSDimitry Andric                     dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
185768d75effSDimitry Andric                                 dfsan_union(haystack_label, needle_label)));
185868d75effSDimitry Andric   }
185968d75effSDimitry Andric 
186068d75effSDimitry Andric   return ret;
186168d75effSDimitry Andric }
186268d75effSDimitry Andric 
1863*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
1864*fe6060f1SDimitry Andric                                                   dfsan_label haystack_label,
1865*fe6060f1SDimitry Andric                                                   dfsan_label needle_label,
1866*fe6060f1SDimitry Andric                                                   dfsan_label *ret_label,
1867*fe6060f1SDimitry Andric                                                   dfsan_origin haystack_origin,
1868*fe6060f1SDimitry Andric                                                   dfsan_origin needle_origin,
1869*fe6060f1SDimitry Andric                                                   dfsan_origin *ret_origin) {
1870*fe6060f1SDimitry Andric   char *ret =
1871*fe6060f1SDimitry Andric       __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
1872*fe6060f1SDimitry Andric   if (flags().strict_data_dependencies) {
1873*fe6060f1SDimitry Andric     if (ret)
1874*fe6060f1SDimitry Andric       *ret_origin = haystack_origin;
1875*fe6060f1SDimitry Andric   } else {
1876*fe6060f1SDimitry Andric     size_t needle_len = strlen(needle);
1877*fe6060f1SDimitry Andric     size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
1878*fe6060f1SDimitry Andric     dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
1879*fe6060f1SDimitry Andric     if (o) {
1880*fe6060f1SDimitry Andric       *ret_origin = o;
1881*fe6060f1SDimitry Andric     } else {
1882*fe6060f1SDimitry Andric       o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
1883*fe6060f1SDimitry Andric       *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
1884*fe6060f1SDimitry Andric     }
1885*fe6060f1SDimitry Andric   }
1886*fe6060f1SDimitry Andric 
1887*fe6060f1SDimitry Andric   return ret;
1888*fe6060f1SDimitry Andric }
1889*fe6060f1SDimitry Andric 
189068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
189168d75effSDimitry Andric                                                    struct timespec *rem,
189268d75effSDimitry Andric                                                    dfsan_label req_label,
189368d75effSDimitry Andric                                                    dfsan_label rem_label,
189468d75effSDimitry Andric                                                    dfsan_label *ret_label) {
189568d75effSDimitry Andric   int ret = nanosleep(req, rem);
189668d75effSDimitry Andric   *ret_label = 0;
189768d75effSDimitry Andric   if (ret == -1) {
189868d75effSDimitry Andric     // Interrupted by a signal, rem is filled with the remaining time.
189968d75effSDimitry Andric     dfsan_set_label(0, rem, sizeof(struct timespec));
190068d75effSDimitry Andric   }
190168d75effSDimitry Andric   return ret;
190268d75effSDimitry Andric }
190368d75effSDimitry Andric 
1904*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
1905*fe6060f1SDimitry Andric     const struct timespec *req, struct timespec *rem, dfsan_label req_label,
1906*fe6060f1SDimitry Andric     dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
1907*fe6060f1SDimitry Andric     dfsan_origin rem_origin, dfsan_origin *ret_origin) {
1908*fe6060f1SDimitry Andric   return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
1909*fe6060f1SDimitry Andric }
1910*fe6060f1SDimitry Andric 
1911e8d8bef9SDimitry Andric static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
1912e8d8bef9SDimitry Andric   dfsan_set_label(0, msg, sizeof(*msg));
1913e8d8bef9SDimitry Andric   dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
1914e8d8bef9SDimitry Andric   dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
1915e8d8bef9SDimitry Andric   for (size_t i = 0; bytes_written > 0; ++i) {
1916e8d8bef9SDimitry Andric     assert(i < msg->msg_iovlen);
1917e8d8bef9SDimitry Andric     struct iovec *iov = &msg->msg_iov[i];
1918e8d8bef9SDimitry Andric     size_t iov_written =
1919e8d8bef9SDimitry Andric         bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
1920e8d8bef9SDimitry Andric     dfsan_set_label(0, iov->iov_base, iov_written);
1921e8d8bef9SDimitry Andric     bytes_written -= iov_written;
1922e8d8bef9SDimitry Andric   }
1923e8d8bef9SDimitry Andric }
1924e8d8bef9SDimitry Andric 
1925e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
1926e8d8bef9SDimitry Andric     int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1927e8d8bef9SDimitry Andric     struct timespec *timeout, dfsan_label sockfd_label,
1928e8d8bef9SDimitry Andric     dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1929e8d8bef9SDimitry Andric     dfsan_label timeout_label, dfsan_label *ret_label) {
1930e8d8bef9SDimitry Andric   int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
1931e8d8bef9SDimitry Andric   for (int i = 0; i < ret; ++i) {
1932e8d8bef9SDimitry Andric     dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
1933e8d8bef9SDimitry Andric     clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
1934e8d8bef9SDimitry Andric   }
1935e8d8bef9SDimitry Andric   *ret_label = 0;
1936e8d8bef9SDimitry Andric   return ret;
1937e8d8bef9SDimitry Andric }
1938e8d8bef9SDimitry Andric 
1939*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
1940*fe6060f1SDimitry Andric     int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
1941*fe6060f1SDimitry Andric     struct timespec *timeout, dfsan_label sockfd_label,
1942*fe6060f1SDimitry Andric     dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
1943*fe6060f1SDimitry Andric     dfsan_label timeout_label, dfsan_label *ret_label,
1944*fe6060f1SDimitry Andric     dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
1945*fe6060f1SDimitry Andric     dfsan_origin vlen_origin, dfsan_origin flags_origin,
1946*fe6060f1SDimitry Andric     dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
1947*fe6060f1SDimitry Andric   return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
1948*fe6060f1SDimitry Andric                          msgvec_label, vlen_label, flags_label, timeout_label,
1949*fe6060f1SDimitry Andric                          ret_label);
1950*fe6060f1SDimitry Andric }
1951*fe6060f1SDimitry Andric 
1952e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
1953e8d8bef9SDimitry Andric     int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1954e8d8bef9SDimitry Andric     dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
1955e8d8bef9SDimitry Andric   ssize_t ret = recvmsg(sockfd, msg, flags);
1956e8d8bef9SDimitry Andric   if (ret >= 0)
1957e8d8bef9SDimitry Andric     clear_msghdr_labels(ret, msg);
1958e8d8bef9SDimitry Andric   *ret_label = 0;
1959e8d8bef9SDimitry Andric   return ret;
1960e8d8bef9SDimitry Andric }
1961e8d8bef9SDimitry Andric 
1962*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
1963*fe6060f1SDimitry Andric     int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
1964*fe6060f1SDimitry Andric     dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
1965*fe6060f1SDimitry Andric     dfsan_origin sockfd_origin, dfsan_origin msg_origin,
1966*fe6060f1SDimitry Andric     dfsan_origin flags_origin, dfsan_origin *ret_origin) {
1967*fe6060f1SDimitry Andric   return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
1968*fe6060f1SDimitry Andric                         flags_label, ret_label);
1969*fe6060f1SDimitry Andric }
1970*fe6060f1SDimitry Andric 
197168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int
197268d75effSDimitry Andric __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
197368d75effSDimitry Andric                   dfsan_label domain_label, dfsan_label type_label,
197468d75effSDimitry Andric                   dfsan_label protocol_label, dfsan_label sv_label,
197568d75effSDimitry Andric                   dfsan_label *ret_label) {
197668d75effSDimitry Andric   int ret = socketpair(domain, type, protocol, sv);
197768d75effSDimitry Andric   *ret_label = 0;
197868d75effSDimitry Andric   if (ret == 0) {
197968d75effSDimitry Andric     dfsan_set_label(0, sv, sizeof(*sv) * 2);
198068d75effSDimitry Andric   }
198168d75effSDimitry Andric   return ret;
198268d75effSDimitry Andric }
198368d75effSDimitry Andric 
1984*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
1985*fe6060f1SDimitry Andric     int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
1986*fe6060f1SDimitry Andric     dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
1987*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin domain_origin,
1988*fe6060f1SDimitry Andric     dfsan_origin type_origin, dfsan_origin protocol_origin,
1989*fe6060f1SDimitry Andric     dfsan_origin sv_origin, dfsan_origin *ret_origin) {
1990*fe6060f1SDimitry Andric   return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
1991*fe6060f1SDimitry Andric                            protocol_label, sv_label, ret_label);
1992*fe6060f1SDimitry Andric }
1993*fe6060f1SDimitry Andric 
1994e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
1995e8d8bef9SDimitry Andric     int sockfd, int level, int optname, void *optval, socklen_t *optlen,
1996e8d8bef9SDimitry Andric     dfsan_label sockfd_label, dfsan_label level_label,
1997e8d8bef9SDimitry Andric     dfsan_label optname_label, dfsan_label optval_label,
1998e8d8bef9SDimitry Andric     dfsan_label optlen_label, dfsan_label *ret_label) {
1999e8d8bef9SDimitry Andric   int ret = getsockopt(sockfd, level, optname, optval, optlen);
2000e8d8bef9SDimitry Andric   if (ret != -1 && optval && optlen) {
2001e8d8bef9SDimitry Andric     dfsan_set_label(0, optlen, sizeof(*optlen));
2002e8d8bef9SDimitry Andric     dfsan_set_label(0, optval, *optlen);
2003e8d8bef9SDimitry Andric   }
2004e8d8bef9SDimitry Andric   *ret_label = 0;
2005e8d8bef9SDimitry Andric   return ret;
2006e8d8bef9SDimitry Andric }
2007e8d8bef9SDimitry Andric 
2008*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
2009*fe6060f1SDimitry Andric     int sockfd, int level, int optname, void *optval, socklen_t *optlen,
2010*fe6060f1SDimitry Andric     dfsan_label sockfd_label, dfsan_label level_label,
2011*fe6060f1SDimitry Andric     dfsan_label optname_label, dfsan_label optval_label,
2012*fe6060f1SDimitry Andric     dfsan_label optlen_label, dfsan_label *ret_label,
2013*fe6060f1SDimitry Andric     dfsan_origin sockfd_origin, dfsan_origin level_origin,
2014*fe6060f1SDimitry Andric     dfsan_origin optname_origin, dfsan_origin optval_origin,
2015*fe6060f1SDimitry Andric     dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
2016*fe6060f1SDimitry Andric   return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
2017*fe6060f1SDimitry Andric                            level_label, optname_label, optval_label,
2018*fe6060f1SDimitry Andric                            optlen_label, ret_label);
2019*fe6060f1SDimitry Andric }
2020*fe6060f1SDimitry Andric 
2021e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
2022e8d8bef9SDimitry Andric     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2023e8d8bef9SDimitry Andric     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2024e8d8bef9SDimitry Andric     dfsan_label *ret_label) {
2025e8d8bef9SDimitry Andric   socklen_t origlen = addrlen ? *addrlen : 0;
2026e8d8bef9SDimitry Andric   int ret = getsockname(sockfd, addr, addrlen);
2027e8d8bef9SDimitry Andric   if (ret != -1 && addr && addrlen) {
2028e8d8bef9SDimitry Andric     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2029e8d8bef9SDimitry Andric     dfsan_set_label(0, addrlen, sizeof(*addrlen));
2030e8d8bef9SDimitry Andric     dfsan_set_label(0, addr, written_bytes);
2031e8d8bef9SDimitry Andric   }
2032e8d8bef9SDimitry Andric   *ret_label = 0;
2033e8d8bef9SDimitry Andric   return ret;
2034e8d8bef9SDimitry Andric }
2035e8d8bef9SDimitry Andric 
2036*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
2037*fe6060f1SDimitry Andric     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2038*fe6060f1SDimitry Andric     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2039*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin sockfd_origin,
2040*fe6060f1SDimitry Andric     dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2041*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
2042*fe6060f1SDimitry Andric   return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
2043*fe6060f1SDimitry Andric                             addrlen_label, ret_label);
2044*fe6060f1SDimitry Andric }
2045*fe6060f1SDimitry Andric 
2046e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
2047e8d8bef9SDimitry Andric     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2048e8d8bef9SDimitry Andric     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2049e8d8bef9SDimitry Andric     dfsan_label *ret_label) {
2050e8d8bef9SDimitry Andric   socklen_t origlen = addrlen ? *addrlen : 0;
2051e8d8bef9SDimitry Andric   int ret = getpeername(sockfd, addr, addrlen);
2052e8d8bef9SDimitry Andric   if (ret != -1 && addr && addrlen) {
2053e8d8bef9SDimitry Andric     socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
2054e8d8bef9SDimitry Andric     dfsan_set_label(0, addrlen, sizeof(*addrlen));
2055e8d8bef9SDimitry Andric     dfsan_set_label(0, addr, written_bytes);
2056e8d8bef9SDimitry Andric   }
2057e8d8bef9SDimitry Andric   *ret_label = 0;
2058e8d8bef9SDimitry Andric   return ret;
2059e8d8bef9SDimitry Andric }
2060e8d8bef9SDimitry Andric 
2061*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
2062*fe6060f1SDimitry Andric     int sockfd, struct sockaddr *addr, socklen_t *addrlen,
2063*fe6060f1SDimitry Andric     dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
2064*fe6060f1SDimitry Andric     dfsan_label *ret_label, dfsan_origin sockfd_origin,
2065*fe6060f1SDimitry Andric     dfsan_origin addr_origin, dfsan_origin addrlen_origin,
2066*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
2067*fe6060f1SDimitry Andric   return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
2068*fe6060f1SDimitry Andric                             addrlen_label, ret_label);
2069*fe6060f1SDimitry Andric }
2070*fe6060f1SDimitry Andric 
207168d75effSDimitry Andric // Type of the trampoline function passed to the custom version of
207268d75effSDimitry Andric // dfsan_set_write_callback.
207368d75effSDimitry Andric typedef void (*write_trampoline_t)(
207468d75effSDimitry Andric     void *callback,
207568d75effSDimitry Andric     int fd, const void *buf, ssize_t count,
207668d75effSDimitry Andric     dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label);
207768d75effSDimitry Andric 
2078*fe6060f1SDimitry Andric typedef void (*write_origin_trampoline_t)(
2079*fe6060f1SDimitry Andric     void *callback, int fd, const void *buf, ssize_t count,
2080*fe6060f1SDimitry Andric     dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
2081*fe6060f1SDimitry Andric     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin);
2082*fe6060f1SDimitry Andric 
208368d75effSDimitry Andric // Calls to dfsan_set_write_callback() set the values in this struct.
208468d75effSDimitry Andric // Calls to the custom version of write() read (and invoke) them.
208568d75effSDimitry Andric static struct {
208668d75effSDimitry Andric   write_trampoline_t write_callback_trampoline = nullptr;
208768d75effSDimitry Andric   void *write_callback = nullptr;
208868d75effSDimitry Andric } write_callback_info;
208968d75effSDimitry Andric 
2090*fe6060f1SDimitry Andric static struct {
2091*fe6060f1SDimitry Andric   write_origin_trampoline_t write_callback_trampoline = nullptr;
2092*fe6060f1SDimitry Andric   void *write_callback = nullptr;
2093*fe6060f1SDimitry Andric } write_origin_callback_info;
2094*fe6060f1SDimitry Andric 
209568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void
209668d75effSDimitry Andric __dfsw_dfsan_set_write_callback(
209768d75effSDimitry Andric     write_trampoline_t write_callback_trampoline,
209868d75effSDimitry Andric     void *write_callback,
209968d75effSDimitry Andric     dfsan_label write_callback_label,
210068d75effSDimitry Andric     dfsan_label *ret_label) {
210168d75effSDimitry Andric   write_callback_info.write_callback_trampoline = write_callback_trampoline;
210268d75effSDimitry Andric   write_callback_info.write_callback = write_callback;
210368d75effSDimitry Andric }
210468d75effSDimitry Andric 
2105*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
2106*fe6060f1SDimitry Andric     write_origin_trampoline_t write_callback_trampoline, void *write_callback,
2107*fe6060f1SDimitry Andric     dfsan_label write_callback_label, dfsan_label *ret_label,
2108*fe6060f1SDimitry Andric     dfsan_origin write_callback_origin, dfsan_origin *ret_origin) {
2109*fe6060f1SDimitry Andric   write_origin_callback_info.write_callback_trampoline =
2110*fe6060f1SDimitry Andric       write_callback_trampoline;
2111*fe6060f1SDimitry Andric   write_origin_callback_info.write_callback = write_callback;
2112*fe6060f1SDimitry Andric }
2113*fe6060f1SDimitry Andric 
211468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int
211568d75effSDimitry Andric __dfsw_write(int fd, const void *buf, size_t count,
211668d75effSDimitry Andric              dfsan_label fd_label, dfsan_label buf_label,
211768d75effSDimitry Andric              dfsan_label count_label, dfsan_label *ret_label) {
211868d75effSDimitry Andric   if (write_callback_info.write_callback) {
211968d75effSDimitry Andric     write_callback_info.write_callback_trampoline(
212068d75effSDimitry Andric         write_callback_info.write_callback,
212168d75effSDimitry Andric         fd, buf, count,
212268d75effSDimitry Andric         fd_label, buf_label, count_label);
212368d75effSDimitry Andric   }
212468d75effSDimitry Andric 
212568d75effSDimitry Andric   *ret_label = 0;
212668d75effSDimitry Andric   return write(fd, buf, count);
212768d75effSDimitry Andric }
2128*fe6060f1SDimitry Andric 
2129*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
2130*fe6060f1SDimitry Andric     int fd, const void *buf, size_t count, dfsan_label fd_label,
2131*fe6060f1SDimitry Andric     dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
2132*fe6060f1SDimitry Andric     dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
2133*fe6060f1SDimitry Andric     dfsan_origin *ret_origin) {
2134*fe6060f1SDimitry Andric   if (write_origin_callback_info.write_callback) {
2135*fe6060f1SDimitry Andric     write_origin_callback_info.write_callback_trampoline(
2136*fe6060f1SDimitry Andric         write_origin_callback_info.write_callback, fd, buf, count, fd_label,
2137*fe6060f1SDimitry Andric         buf_label, count_label, fd_origin, buf_origin, count_origin);
2138*fe6060f1SDimitry Andric   }
2139*fe6060f1SDimitry Andric 
2140*fe6060f1SDimitry Andric   *ret_label = 0;
2141*fe6060f1SDimitry Andric   return write(fd, buf, count);
2142*fe6060f1SDimitry Andric }
214368d75effSDimitry Andric } // namespace __dfsan
214468d75effSDimitry Andric 
214568d75effSDimitry Andric // Type used to extract a dfsan_label with va_arg()
214668d75effSDimitry Andric typedef int dfsan_label_va;
214768d75effSDimitry Andric 
214868d75effSDimitry Andric // Formats a chunk either a constant string or a single format directive (e.g.,
214968d75effSDimitry Andric // '%.3f').
215068d75effSDimitry Andric struct Formatter {
215168d75effSDimitry Andric   Formatter(char *str_, const char *fmt_, size_t size_)
215268d75effSDimitry Andric       : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
215368d75effSDimitry Andric         width(-1) {}
215468d75effSDimitry Andric 
215568d75effSDimitry Andric   int format() {
215668d75effSDimitry Andric     char *tmp_fmt = build_format_string();
215768d75effSDimitry Andric     int retval =
215868d75effSDimitry Andric         snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
215968d75effSDimitry Andric                  0 /* used only to avoid warnings */);
216068d75effSDimitry Andric     free(tmp_fmt);
216168d75effSDimitry Andric     return retval;
216268d75effSDimitry Andric   }
216368d75effSDimitry Andric 
216468d75effSDimitry Andric   template <typename T> int format(T arg) {
216568d75effSDimitry Andric     char *tmp_fmt = build_format_string();
216668d75effSDimitry Andric     int retval;
216768d75effSDimitry Andric     if (width >= 0) {
216868d75effSDimitry Andric       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
216968d75effSDimitry Andric                         tmp_fmt, width, arg);
217068d75effSDimitry Andric     } else {
217168d75effSDimitry Andric       retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
217268d75effSDimitry Andric                         tmp_fmt, arg);
217368d75effSDimitry Andric     }
217468d75effSDimitry Andric     free(tmp_fmt);
217568d75effSDimitry Andric     return retval;
217668d75effSDimitry Andric   }
217768d75effSDimitry Andric 
217868d75effSDimitry Andric   char *build_format_string() {
217968d75effSDimitry Andric     size_t fmt_size = fmt_cur - fmt_start + 1;
218068d75effSDimitry Andric     char *new_fmt = (char *)malloc(fmt_size + 1);
218168d75effSDimitry Andric     assert(new_fmt);
218268d75effSDimitry Andric     internal_memcpy(new_fmt, fmt_start, fmt_size);
218368d75effSDimitry Andric     new_fmt[fmt_size] = '\0';
218468d75effSDimitry Andric     return new_fmt;
218568d75effSDimitry Andric   }
218668d75effSDimitry Andric 
218768d75effSDimitry Andric   char *str_cur() { return str + str_off; }
218868d75effSDimitry Andric 
218968d75effSDimitry Andric   size_t num_written_bytes(int retval) {
219068d75effSDimitry Andric     if (retval < 0) {
219168d75effSDimitry Andric       return 0;
219268d75effSDimitry Andric     }
219368d75effSDimitry Andric 
219468d75effSDimitry Andric     size_t num_avail = str_off < size ? size - str_off : 0;
219568d75effSDimitry Andric     if (num_avail == 0) {
219668d75effSDimitry Andric       return 0;
219768d75effSDimitry Andric     }
219868d75effSDimitry Andric 
219968d75effSDimitry Andric     size_t num_written = retval;
220068d75effSDimitry Andric     // A return value of {v,}snprintf of size or more means that the output was
220168d75effSDimitry Andric     // truncated.
220268d75effSDimitry Andric     if (num_written >= num_avail) {
220368d75effSDimitry Andric       num_written -= num_avail;
220468d75effSDimitry Andric     }
220568d75effSDimitry Andric 
220668d75effSDimitry Andric     return num_written;
220768d75effSDimitry Andric   }
220868d75effSDimitry Andric 
220968d75effSDimitry Andric   char *str;
221068d75effSDimitry Andric   size_t str_off;
221168d75effSDimitry Andric   size_t size;
221268d75effSDimitry Andric   const char *fmt_start;
221368d75effSDimitry Andric   const char *fmt_cur;
221468d75effSDimitry Andric   int width;
221568d75effSDimitry Andric };
221668d75effSDimitry Andric 
221768d75effSDimitry Andric // Formats the input and propagates the input labels to the output. The output
221868d75effSDimitry Andric // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
221968d75effSDimitry Andric // 'ap' are the format string and the list of arguments for formatting. Returns
222068d75effSDimitry Andric // the return value vsnprintf would return.
222168d75effSDimitry Andric //
222268d75effSDimitry Andric // The function tokenizes the format string in chunks representing either a
222368d75effSDimitry Andric // constant string or a single format directive (e.g., '%.3f') and formats each
222468d75effSDimitry Andric // chunk independently into the output string. This approach allows to figure
222568d75effSDimitry Andric // out which bytes of the output string depends on which argument and thus to
222668d75effSDimitry Andric // propagate labels more precisely.
222768d75effSDimitry Andric //
222868d75effSDimitry Andric // WARNING: This implementation does not support conversion specifiers with
222968d75effSDimitry Andric // positional arguments.
223068d75effSDimitry Andric static int format_buffer(char *str, size_t size, const char *fmt,
223168d75effSDimitry Andric                          dfsan_label *va_labels, dfsan_label *ret_label,
2232*fe6060f1SDimitry Andric                          dfsan_origin *va_origins, dfsan_origin *ret_origin,
223368d75effSDimitry Andric                          va_list ap) {
223468d75effSDimitry Andric   Formatter formatter(str, fmt, size);
223568d75effSDimitry Andric 
223668d75effSDimitry Andric   while (*formatter.fmt_cur) {
223768d75effSDimitry Andric     formatter.fmt_start = formatter.fmt_cur;
223868d75effSDimitry Andric     formatter.width = -1;
223968d75effSDimitry Andric     int retval = 0;
224068d75effSDimitry Andric 
224168d75effSDimitry Andric     if (*formatter.fmt_cur != '%') {
224268d75effSDimitry Andric       // Ordinary character. Consume all the characters until a '%' or the end
224368d75effSDimitry Andric       // of the string.
224468d75effSDimitry Andric       for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
224568d75effSDimitry Andric            ++formatter.fmt_cur) {}
224668d75effSDimitry Andric       retval = formatter.format();
224768d75effSDimitry Andric       dfsan_set_label(0, formatter.str_cur(),
224868d75effSDimitry Andric                       formatter.num_written_bytes(retval));
224968d75effSDimitry Andric     } else {
225068d75effSDimitry Andric       // Conversion directive. Consume all the characters until a conversion
225168d75effSDimitry Andric       // specifier or the end of the string.
225268d75effSDimitry Andric       bool end_fmt = false;
225368d75effSDimitry Andric       for (; *formatter.fmt_cur && !end_fmt; ) {
225468d75effSDimitry Andric         switch (*++formatter.fmt_cur) {
225568d75effSDimitry Andric         case 'd':
225668d75effSDimitry Andric         case 'i':
225768d75effSDimitry Andric         case 'o':
225868d75effSDimitry Andric         case 'u':
225968d75effSDimitry Andric         case 'x':
226068d75effSDimitry Andric         case 'X':
226168d75effSDimitry Andric           switch (*(formatter.fmt_cur - 1)) {
226268d75effSDimitry Andric           case 'h':
226368d75effSDimitry Andric             // Also covers the 'hh' case (since the size of the arg is still
226468d75effSDimitry Andric             // an int).
226568d75effSDimitry Andric             retval = formatter.format(va_arg(ap, int));
226668d75effSDimitry Andric             break;
226768d75effSDimitry Andric           case 'l':
226868d75effSDimitry Andric             if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
226968d75effSDimitry Andric                 *(formatter.fmt_cur - 2) == 'l') {
227068d75effSDimitry Andric               retval = formatter.format(va_arg(ap, long long int));
227168d75effSDimitry Andric             } else {
227268d75effSDimitry Andric               retval = formatter.format(va_arg(ap, long int));
227368d75effSDimitry Andric             }
227468d75effSDimitry Andric             break;
227568d75effSDimitry Andric           case 'q':
227668d75effSDimitry Andric             retval = formatter.format(va_arg(ap, long long int));
227768d75effSDimitry Andric             break;
227868d75effSDimitry Andric           case 'j':
227968d75effSDimitry Andric             retval = formatter.format(va_arg(ap, intmax_t));
228068d75effSDimitry Andric             break;
228168d75effSDimitry Andric           case 'z':
228268d75effSDimitry Andric           case 't':
228368d75effSDimitry Andric             retval = formatter.format(va_arg(ap, size_t));
228468d75effSDimitry Andric             break;
228568d75effSDimitry Andric           default:
228668d75effSDimitry Andric             retval = formatter.format(va_arg(ap, int));
228768d75effSDimitry Andric           }
2288*fe6060f1SDimitry Andric           if (va_origins == nullptr)
228968d75effSDimitry Andric             dfsan_set_label(*va_labels++, formatter.str_cur(),
229068d75effSDimitry Andric                             formatter.num_written_bytes(retval));
2291*fe6060f1SDimitry Andric           else
2292*fe6060f1SDimitry Andric             dfsan_set_label_origin(*va_labels++, *va_origins++,
2293*fe6060f1SDimitry Andric                                    formatter.str_cur(),
2294*fe6060f1SDimitry Andric                                    formatter.num_written_bytes(retval));
229568d75effSDimitry Andric           end_fmt = true;
229668d75effSDimitry Andric           break;
229768d75effSDimitry Andric 
229868d75effSDimitry Andric         case 'a':
229968d75effSDimitry Andric         case 'A':
230068d75effSDimitry Andric         case 'e':
230168d75effSDimitry Andric         case 'E':
230268d75effSDimitry Andric         case 'f':
230368d75effSDimitry Andric         case 'F':
230468d75effSDimitry Andric         case 'g':
230568d75effSDimitry Andric         case 'G':
230668d75effSDimitry Andric           if (*(formatter.fmt_cur - 1) == 'L') {
230768d75effSDimitry Andric             retval = formatter.format(va_arg(ap, long double));
230868d75effSDimitry Andric           } else {
230968d75effSDimitry Andric             retval = formatter.format(va_arg(ap, double));
231068d75effSDimitry Andric           }
2311*fe6060f1SDimitry Andric           if (va_origins == nullptr)
231268d75effSDimitry Andric             dfsan_set_label(*va_labels++, formatter.str_cur(),
231368d75effSDimitry Andric                             formatter.num_written_bytes(retval));
2314*fe6060f1SDimitry Andric           else
2315*fe6060f1SDimitry Andric             dfsan_set_label_origin(*va_labels++, *va_origins++,
2316*fe6060f1SDimitry Andric                                    formatter.str_cur(),
2317*fe6060f1SDimitry Andric                                    formatter.num_written_bytes(retval));
231868d75effSDimitry Andric           end_fmt = true;
231968d75effSDimitry Andric           break;
232068d75effSDimitry Andric 
232168d75effSDimitry Andric         case 'c':
232268d75effSDimitry Andric           retval = formatter.format(va_arg(ap, int));
2323*fe6060f1SDimitry Andric           if (va_origins == nullptr)
232468d75effSDimitry Andric             dfsan_set_label(*va_labels++, formatter.str_cur(),
232568d75effSDimitry Andric                             formatter.num_written_bytes(retval));
2326*fe6060f1SDimitry Andric           else
2327*fe6060f1SDimitry Andric             dfsan_set_label_origin(*va_labels++, *va_origins++,
2328*fe6060f1SDimitry Andric                                    formatter.str_cur(),
2329*fe6060f1SDimitry Andric                                    formatter.num_written_bytes(retval));
233068d75effSDimitry Andric           end_fmt = true;
233168d75effSDimitry Andric           break;
233268d75effSDimitry Andric 
233368d75effSDimitry Andric         case 's': {
233468d75effSDimitry Andric           char *arg = va_arg(ap, char *);
233568d75effSDimitry Andric           retval = formatter.format(arg);
2336*fe6060f1SDimitry Andric           if (va_origins) {
2337*fe6060f1SDimitry Andric             va_origins++;
2338*fe6060f1SDimitry Andric             dfsan_mem_origin_transfer(formatter.str_cur(), arg,
2339*fe6060f1SDimitry Andric                                       formatter.num_written_bytes(retval));
2340*fe6060f1SDimitry Andric           }
234168d75effSDimitry Andric           va_labels++;
234268d75effSDimitry Andric           internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg),
234368d75effSDimitry Andric                           sizeof(dfsan_label) *
234468d75effSDimitry Andric                               formatter.num_written_bytes(retval));
234568d75effSDimitry Andric           end_fmt = true;
234668d75effSDimitry Andric           break;
234768d75effSDimitry Andric         }
234868d75effSDimitry Andric 
234968d75effSDimitry Andric         case 'p':
235068d75effSDimitry Andric           retval = formatter.format(va_arg(ap, void *));
2351*fe6060f1SDimitry Andric           if (va_origins == nullptr)
235268d75effSDimitry Andric             dfsan_set_label(*va_labels++, formatter.str_cur(),
235368d75effSDimitry Andric                             formatter.num_written_bytes(retval));
2354*fe6060f1SDimitry Andric           else
2355*fe6060f1SDimitry Andric             dfsan_set_label_origin(*va_labels++, *va_origins++,
2356*fe6060f1SDimitry Andric                                    formatter.str_cur(),
2357*fe6060f1SDimitry Andric                                    formatter.num_written_bytes(retval));
235868d75effSDimitry Andric           end_fmt = true;
235968d75effSDimitry Andric           break;
236068d75effSDimitry Andric 
236168d75effSDimitry Andric         case 'n': {
236268d75effSDimitry Andric           int *ptr = va_arg(ap, int *);
236368d75effSDimitry Andric           *ptr = (int)formatter.str_off;
236468d75effSDimitry Andric           va_labels++;
2365*fe6060f1SDimitry Andric           if (va_origins)
2366*fe6060f1SDimitry Andric             va_origins++;
236768d75effSDimitry Andric           dfsan_set_label(0, ptr, sizeof(ptr));
236868d75effSDimitry Andric           end_fmt = true;
236968d75effSDimitry Andric           break;
237068d75effSDimitry Andric         }
237168d75effSDimitry Andric 
237268d75effSDimitry Andric         case '%':
237368d75effSDimitry Andric           retval = formatter.format();
237468d75effSDimitry Andric           dfsan_set_label(0, formatter.str_cur(),
237568d75effSDimitry Andric                           formatter.num_written_bytes(retval));
237668d75effSDimitry Andric           end_fmt = true;
237768d75effSDimitry Andric           break;
237868d75effSDimitry Andric 
237968d75effSDimitry Andric         case '*':
238068d75effSDimitry Andric           formatter.width = va_arg(ap, int);
238168d75effSDimitry Andric           va_labels++;
2382*fe6060f1SDimitry Andric           if (va_origins)
2383*fe6060f1SDimitry Andric             va_origins++;
238468d75effSDimitry Andric           break;
238568d75effSDimitry Andric 
238668d75effSDimitry Andric         default:
238768d75effSDimitry Andric           break;
238868d75effSDimitry Andric         }
238968d75effSDimitry Andric       }
239068d75effSDimitry Andric     }
239168d75effSDimitry Andric 
239268d75effSDimitry Andric     if (retval < 0) {
239368d75effSDimitry Andric       return retval;
239468d75effSDimitry Andric     }
239568d75effSDimitry Andric 
239668d75effSDimitry Andric     formatter.fmt_cur++;
239768d75effSDimitry Andric     formatter.str_off += retval;
239868d75effSDimitry Andric   }
239968d75effSDimitry Andric 
240068d75effSDimitry Andric   *ret_label = 0;
2401*fe6060f1SDimitry Andric   if (ret_origin)
2402*fe6060f1SDimitry Andric     *ret_origin = 0;
240368d75effSDimitry Andric 
240468d75effSDimitry Andric   // Number of bytes written in total.
240568d75effSDimitry Andric   return formatter.str_off;
240668d75effSDimitry Andric }
240768d75effSDimitry Andric 
240868d75effSDimitry Andric extern "C" {
240968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
241068d75effSDimitry Andric int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
241168d75effSDimitry Andric                    dfsan_label format_label, dfsan_label *va_labels,
241268d75effSDimitry Andric                    dfsan_label *ret_label, ...) {
241368d75effSDimitry Andric   va_list ap;
241468d75effSDimitry Andric   va_start(ap, ret_label);
2415*fe6060f1SDimitry Andric   int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
2416*fe6060f1SDimitry Andric                           nullptr, ap);
2417*fe6060f1SDimitry Andric   va_end(ap);
2418*fe6060f1SDimitry Andric   return ret;
2419*fe6060f1SDimitry Andric }
2420*fe6060f1SDimitry Andric 
2421*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
2422*fe6060f1SDimitry Andric int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
2423*fe6060f1SDimitry Andric                    dfsan_label format_label, dfsan_label *va_labels,
2424*fe6060f1SDimitry Andric                    dfsan_label *ret_label, dfsan_origin str_origin,
2425*fe6060f1SDimitry Andric                    dfsan_origin format_origin, dfsan_origin *va_origins,
2426*fe6060f1SDimitry Andric                    dfsan_origin *ret_origin, ...) {
2427*fe6060f1SDimitry Andric   va_list ap;
2428*fe6060f1SDimitry Andric   va_start(ap, ret_origin);
2429*fe6060f1SDimitry Andric   int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins,
2430*fe6060f1SDimitry Andric                           ret_origin, ap);
243168d75effSDimitry Andric   va_end(ap);
243268d75effSDimitry Andric   return ret;
243368d75effSDimitry Andric }
243468d75effSDimitry Andric 
243568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
243668d75effSDimitry Andric int __dfsw_snprintf(char *str, size_t size, const char *format,
243768d75effSDimitry Andric                     dfsan_label str_label, dfsan_label size_label,
243868d75effSDimitry Andric                     dfsan_label format_label, dfsan_label *va_labels,
243968d75effSDimitry Andric                     dfsan_label *ret_label, ...) {
244068d75effSDimitry Andric   va_list ap;
244168d75effSDimitry Andric   va_start(ap, ret_label);
2442*fe6060f1SDimitry Andric   int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
2443*fe6060f1SDimitry Andric                           nullptr, ap);
244468d75effSDimitry Andric   va_end(ap);
244568d75effSDimitry Andric   return ret;
244668d75effSDimitry Andric }
244768d75effSDimitry Andric 
2448*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
2449*fe6060f1SDimitry Andric int __dfso_snprintf(char *str, size_t size, const char *format,
2450*fe6060f1SDimitry Andric                     dfsan_label str_label, dfsan_label size_label,
2451*fe6060f1SDimitry Andric                     dfsan_label format_label, dfsan_label *va_labels,
2452*fe6060f1SDimitry Andric                     dfsan_label *ret_label, dfsan_origin str_origin,
2453*fe6060f1SDimitry Andric                     dfsan_origin size_origin, dfsan_origin format_origin,
2454*fe6060f1SDimitry Andric                     dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
2455*fe6060f1SDimitry Andric   va_list ap;
2456*fe6060f1SDimitry Andric   va_start(ap, ret_origin);
2457*fe6060f1SDimitry Andric   int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
2458*fe6060f1SDimitry Andric                           ret_origin, ap);
2459*fe6060f1SDimitry Andric   va_end(ap);
2460*fe6060f1SDimitry Andric   return ret;
2461*fe6060f1SDimitry Andric }
2462*fe6060f1SDimitry Andric 
2463*fe6060f1SDimitry Andric static void BeforeFork() {
2464*fe6060f1SDimitry Andric   StackDepotLockAll();
2465*fe6060f1SDimitry Andric   GetChainedOriginDepot()->LockAll();
2466*fe6060f1SDimitry Andric }
2467*fe6060f1SDimitry Andric 
2468*fe6060f1SDimitry Andric static void AfterFork() {
2469*fe6060f1SDimitry Andric   GetChainedOriginDepot()->UnlockAll();
2470*fe6060f1SDimitry Andric   StackDepotUnlockAll();
2471*fe6060f1SDimitry Andric }
2472*fe6060f1SDimitry Andric 
2473*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
2474*fe6060f1SDimitry Andric pid_t __dfsw_fork(dfsan_label *ret_label) {
2475*fe6060f1SDimitry Andric   pid_t pid = fork();
2476*fe6060f1SDimitry Andric   *ret_label = 0;
2477*fe6060f1SDimitry Andric   return pid;
2478*fe6060f1SDimitry Andric }
2479*fe6060f1SDimitry Andric 
2480*fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE
2481*fe6060f1SDimitry Andric pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
2482*fe6060f1SDimitry Andric   BeforeFork();
2483*fe6060f1SDimitry Andric   pid_t pid = __dfsw_fork(ret_label);
2484*fe6060f1SDimitry Andric   AfterFork();
2485*fe6060f1SDimitry Andric   return pid;
2486*fe6060f1SDimitry Andric }
2487*fe6060f1SDimitry Andric 
248868d75effSDimitry Andric // Default empty implementations (weak). Users should redefine them.
248968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
249068d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
249168d75effSDimitry Andric                              u32 *) {}
249268d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {}
249368d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
249468d75effSDimitry Andric 
249568d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
249668d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
249768d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
249868d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
249968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
250068d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
250168d75effSDimitry Andric                              void) {}
250268d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
250368d75effSDimitry Andric                              void) {}
250468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
250568d75effSDimitry Andric                              void) {}
250668d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
250768d75effSDimitry Andric                              void) {}
250868d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
250968d75effSDimitry Andric }  // extern "C"
2510