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