1fe6060f1SDimitry Andric //===-- dfsan_custom.cpp --------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of DataFlowSanitizer. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // This file defines the custom functions listed in done_abilist.txt. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include <arpa/inet.h> 1568d75effSDimitry Andric #include <assert.h> 1668d75effSDimitry Andric #include <ctype.h> 1768d75effSDimitry Andric #include <dlfcn.h> 1868d75effSDimitry Andric #include <link.h> 1968d75effSDimitry Andric #include <poll.h> 2068d75effSDimitry Andric #include <pthread.h> 2168d75effSDimitry Andric #include <pwd.h> 2268d75effSDimitry Andric #include <sched.h> 2368d75effSDimitry Andric #include <signal.h> 2468d75effSDimitry Andric #include <stdarg.h> 2568d75effSDimitry Andric #include <stdint.h> 2668d75effSDimitry Andric #include <stdio.h> 2768d75effSDimitry Andric #include <stdlib.h> 2868d75effSDimitry Andric #include <string.h> 29e8d8bef9SDimitry Andric #include <sys/epoll.h> 3068d75effSDimitry Andric #include <sys/resource.h> 3168d75effSDimitry Andric #include <sys/select.h> 32e8d8bef9SDimitry Andric #include <sys/socket.h> 3368d75effSDimitry Andric #include <sys/stat.h> 3468d75effSDimitry Andric #include <sys/time.h> 3568d75effSDimitry Andric #include <sys/types.h> 3668d75effSDimitry Andric #include <time.h> 3768d75effSDimitry Andric #include <unistd.h> 3868d75effSDimitry Andric 39e8d8bef9SDimitry Andric #include "dfsan/dfsan.h" 40fe6060f1SDimitry Andric #include "dfsan/dfsan_chained_origin_depot.h" 41fe6060f1SDimitry Andric #include "dfsan/dfsan_flags.h" 42fe6060f1SDimitry Andric #include "dfsan/dfsan_thread.h" 43e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_common.h" 44e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h" 45e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_linux.h" 46fe6060f1SDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 47e8d8bef9SDimitry Andric 4868d75effSDimitry Andric using namespace __dfsan; 4968d75effSDimitry Andric 5068d75effSDimitry Andric #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \ 5168d75effSDimitry Andric do { \ 5268d75effSDimitry Andric if (f) \ 5368d75effSDimitry Andric f(__VA_ARGS__); \ 5468d75effSDimitry Andric } while (false) 5568d75effSDimitry Andric #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \ 5668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__); 5768d75effSDimitry Andric 58fe6060f1SDimitry Andric // Async-safe, non-reentrant spin lock. 59fe6060f1SDimitry Andric class SignalSpinLocker { 60fe6060f1SDimitry Andric public: 61fe6060f1SDimitry Andric SignalSpinLocker() { 62fe6060f1SDimitry Andric sigset_t all_set; 63fe6060f1SDimitry Andric sigfillset(&all_set); 64fe6060f1SDimitry Andric pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_); 65fe6060f1SDimitry Andric sigactions_mu.Lock(); 66fe6060f1SDimitry Andric } 67fe6060f1SDimitry Andric ~SignalSpinLocker() { 68fe6060f1SDimitry Andric sigactions_mu.Unlock(); 69fe6060f1SDimitry Andric pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr); 70fe6060f1SDimitry Andric } 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric private: 73fe6060f1SDimitry Andric static StaticSpinMutex sigactions_mu; 74fe6060f1SDimitry Andric sigset_t saved_thread_mask_; 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric SignalSpinLocker(const SignalSpinLocker &) = delete; 77fe6060f1SDimitry Andric SignalSpinLocker &operator=(const SignalSpinLocker &) = delete; 78fe6060f1SDimitry Andric }; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric StaticSpinMutex SignalSpinLocker::sigactions_mu; 81fe6060f1SDimitry 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 93fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat( 94fe6060f1SDimitry Andric const char *path, struct stat *buf, dfsan_label path_label, 95fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin, 96fe6060f1SDimitry Andric dfsan_origin buf_origin, dfsan_origin *ret_origin) { 97fe6060f1SDimitry Andric int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label); 98fe6060f1SDimitry Andric return ret; 99fe6060f1SDimitry Andric } 100fe6060f1SDimitry 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 112fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat( 113fe6060f1SDimitry Andric int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label, 114fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, 115fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 116fe6060f1SDimitry Andric int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label); 117fe6060f1SDimitry Andric return ret; 118fe6060f1SDimitry Andric } 119fe6060f1SDimitry Andric 120fe6060f1SDimitry Andric static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read, 121fe6060f1SDimitry Andric dfsan_label s_label, dfsan_label c_label, 122fe6060f1SDimitry Andric dfsan_label *ret_label) { 123fe6060f1SDimitry Andric char *match_pos = nullptr; 124fe6060f1SDimitry Andric for (size_t i = 0;; ++i) { 125fe6060f1SDimitry Andric if (s[i] == c || s[i] == 0) { 126fe6060f1SDimitry Andric // If s[i] is the \0 at the end of the string, and \0 is not the 127fe6060f1SDimitry Andric // character we are searching for, then return null. 128fe6060f1SDimitry Andric *bytes_read = i + 1; 129fe6060f1SDimitry Andric match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i); 130fe6060f1SDimitry Andric break; 131fe6060f1SDimitry Andric } 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric if (flags().strict_data_dependencies) 134fe6060f1SDimitry Andric *ret_label = s_label; 135fe6060f1SDimitry Andric else 136fe6060f1SDimitry Andric *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read), 137fe6060f1SDimitry Andric dfsan_union(s_label, c_label)); 138fe6060f1SDimitry Andric return match_pos; 139fe6060f1SDimitry Andric } 140fe6060f1SDimitry 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) { 145fe6060f1SDimitry Andric size_t bytes_read; 146fe6060f1SDimitry Andric return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, 147fe6060f1SDimitry Andric ret_label); 14868d75effSDimitry Andric } 1495ffd83dbSDimitry Andric 150fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr( 151fe6060f1SDimitry Andric const char *s, int c, dfsan_label s_label, dfsan_label c_label, 152fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin, 153fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 154fe6060f1SDimitry Andric size_t bytes_read; 155fe6060f1SDimitry Andric char *r = 156fe6060f1SDimitry Andric dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label); 157fe6060f1SDimitry Andric if (flags().strict_data_dependencies) { 158fe6060f1SDimitry Andric *ret_origin = s_origin; 159fe6060f1SDimitry Andric } else if (*ret_label) { 160fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read); 161fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin); 1625ffd83dbSDimitry Andric } 163fe6060f1SDimitry 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 184fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk( 185fe6060f1SDimitry Andric const char *s, const char *accept, dfsan_label s_label, 186fe6060f1SDimitry Andric dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin, 187fe6060f1SDimitry Andric dfsan_origin accept_origin, dfsan_origin *ret_origin) { 188fe6060f1SDimitry Andric const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label); 189fe6060f1SDimitry Andric if (flags().strict_data_dependencies) { 190fe6060f1SDimitry Andric if (ret) 191fe6060f1SDimitry Andric *ret_origin = s_origin; 192fe6060f1SDimitry Andric } else { 193fe6060f1SDimitry Andric if (*ret_label) { 194fe6060f1SDimitry Andric size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1; 195fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read); 196fe6060f1SDimitry Andric if (o) { 197fe6060f1SDimitry Andric *ret_origin = o; 198fe6060f1SDimitry Andric } else { 199fe6060f1SDimitry Andric o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1); 200fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : accept_origin); 201fe6060f1SDimitry Andric } 202fe6060f1SDimitry Andric } 203fe6060f1SDimitry Andric } 204fe6060f1SDimitry Andric return const_cast<char *>(ret); 205fe6060f1SDimitry Andric } 206fe6060f1SDimitry Andric 207*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim, 208*06c3fb27SDimitry Andric dfsan_label s_label, 209*06c3fb27SDimitry Andric dfsan_label delim_label, 210*06c3fb27SDimitry Andric dfsan_label *ret_label) { 211*06c3fb27SDimitry Andric dfsan_label base_label = dfsan_read_label(s, sizeof(*s)); 212*06c3fb27SDimitry Andric char *base = *s; 213*06c3fb27SDimitry Andric char *res = strsep(s, delim); 214*06c3fb27SDimitry Andric if (res != *s) { 215*06c3fb27SDimitry Andric char *token_start = res; 216*06c3fb27SDimitry Andric int token_length = strlen(res); 217*06c3fb27SDimitry Andric // the delimiter byte has been set to NULL 218*06c3fb27SDimitry Andric dfsan_set_label(0, token_start + token_length, 1); 219*06c3fb27SDimitry Andric } 220*06c3fb27SDimitry Andric 221*06c3fb27SDimitry Andric if (flags().strict_data_dependencies) { 222*06c3fb27SDimitry Andric *ret_label = res ? base_label : 0; 223*06c3fb27SDimitry Andric } else { 224*06c3fb27SDimitry Andric size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1; 225*06c3fb27SDimitry Andric *ret_label = dfsan_union( 226*06c3fb27SDimitry Andric dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))), 227*06c3fb27SDimitry Andric dfsan_union(dfsan_read_label(delim, strlen(delim) + 1), 228*06c3fb27SDimitry Andric dfsan_union(s_label, delim_label))); 229*06c3fb27SDimitry Andric } 230*06c3fb27SDimitry Andric 231*06c3fb27SDimitry Andric return res; 232*06c3fb27SDimitry Andric } 233*06c3fb27SDimitry Andric 234*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep( 235*06c3fb27SDimitry Andric char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label, 236*06c3fb27SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin, 237*06c3fb27SDimitry Andric dfsan_origin *ret_origin) { 238*06c3fb27SDimitry Andric dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s)); 239*06c3fb27SDimitry Andric char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label); 240*06c3fb27SDimitry Andric if (flags().strict_data_dependencies) { 241*06c3fb27SDimitry Andric if (res) 242*06c3fb27SDimitry Andric *ret_origin = base_origin; 243*06c3fb27SDimitry Andric } else { 244*06c3fb27SDimitry Andric if (*ret_label) { 245*06c3fb27SDimitry Andric if (base_origin) { 246*06c3fb27SDimitry Andric *ret_origin = base_origin; 247*06c3fb27SDimitry Andric } else { 248*06c3fb27SDimitry Andric dfsan_origin o = 249*06c3fb27SDimitry Andric dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1); 250*06c3fb27SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : delim_origin); 251*06c3fb27SDimitry Andric } 252*06c3fb27SDimitry Andric } 253*06c3fb27SDimitry Andric } 254*06c3fb27SDimitry Andric 255*06c3fb27SDimitry Andric return res; 256*06c3fb27SDimitry Andric } 257*06c3fb27SDimitry Andric 258e8d8bef9SDimitry Andric static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n, 259fe6060f1SDimitry Andric size_t *bytes_read) { 26068d75effSDimitry Andric const char *cs1 = (const char *) s1, *cs2 = (const char *) s2; 26168d75effSDimitry Andric for (size_t i = 0; i != n; ++i) { 26268d75effSDimitry Andric if (cs1[i] != cs2[i]) { 263fe6060f1SDimitry Andric *bytes_read = i + 1; 26468d75effSDimitry Andric return cs1[i] - cs2[i]; 26568d75effSDimitry Andric } 26668d75effSDimitry Andric } 267fe6060f1SDimitry Andric *bytes_read = n; 26868d75effSDimitry Andric return 0; 26968d75effSDimitry Andric } 27068d75effSDimitry Andric 271fe6060f1SDimitry Andric static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2, 272fe6060f1SDimitry Andric size_t pos) { 273fe6060f1SDimitry Andric if (flags().strict_data_dependencies) 274fe6060f1SDimitry Andric return 0; 275fe6060f1SDimitry Andric return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos)); 276fe6060f1SDimitry Andric } 277fe6060f1SDimitry Andric 278fe6060f1SDimitry Andric static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos, 279fe6060f1SDimitry Andric dfsan_label *ret_label, 280fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 281fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, pos); 282fe6060f1SDimitry Andric if (*ret_label == 0) 283fe6060f1SDimitry Andric return; 284fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos); 285fe6060f1SDimitry Andric *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos); 286fe6060f1SDimitry Andric } 287fe6060f1SDimitry Andric 288fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n, 289fe6060f1SDimitry Andric dfsan_label *ret_label) { 290fe6060f1SDimitry Andric size_t bytes_read; 291fe6060f1SDimitry Andric int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read); 292fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 293fe6060f1SDimitry Andric return r; 294fe6060f1SDimitry Andric } 295fe6060f1SDimitry Andric 296fe6060f1SDimitry Andric static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n, 297fe6060f1SDimitry Andric dfsan_label *ret_label, 298fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 299fe6060f1SDimitry Andric size_t bytes_read; 300fe6060f1SDimitry Andric int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read); 301fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 302fe6060f1SDimitry Andric return r; 303fe6060f1SDimitry Andric } 304fe6060f1SDimitry Andric 305e8d8bef9SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc, 306e8d8bef9SDimitry Andric const void *s1, const void *s2, size_t n, 307e8d8bef9SDimitry Andric dfsan_label s1_label, dfsan_label s2_label, 308e8d8bef9SDimitry Andric dfsan_label n_label) 309e8d8bef9SDimitry Andric 310fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc, 311fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n, 312fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label, 313fe6060f1SDimitry Andric dfsan_label n_label, dfsan_origin s1_origin, 314fe6060f1SDimitry Andric dfsan_origin s2_origin, dfsan_origin n_origin) 315fe6060f1SDimitry Andric 316e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2, 317e8d8bef9SDimitry Andric size_t n, dfsan_label s1_label, 318e8d8bef9SDimitry Andric dfsan_label s2_label, 319e8d8bef9SDimitry Andric dfsan_label n_label, 320e8d8bef9SDimitry Andric dfsan_label *ret_label) { 321e8d8bef9SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n, 322e8d8bef9SDimitry Andric s1_label, s2_label, n_label); 323fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label); 324fe6060f1SDimitry Andric } 325fe6060f1SDimitry Andric 326fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp( 327fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n, dfsan_label s1_label, 328fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 329fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 330fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 331fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1, 332fe6060f1SDimitry Andric s2, n, s1_label, s2_label, n_label, s1_origin, 333fe6060f1SDimitry Andric s2_origin, n_origin); 334fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin); 335e8d8bef9SDimitry Andric } 336e8d8bef9SDimitry Andric 337e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2, 338e8d8bef9SDimitry Andric size_t n, dfsan_label s1_label, 339e8d8bef9SDimitry Andric dfsan_label s2_label, 340e8d8bef9SDimitry Andric dfsan_label n_label, 341e8d8bef9SDimitry Andric dfsan_label *ret_label) { 342fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label); 343fe6060f1SDimitry Andric } 344fe6060f1SDimitry Andric 345fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp( 346fe6060f1SDimitry Andric const void *s1, const void *s2, size_t n, dfsan_label s1_label, 347fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 348fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 349fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 350fe6060f1SDimitry Andric return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin); 351fe6060f1SDimitry Andric } 352fe6060f1SDimitry Andric 353fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit. 354fe6060f1SDimitry Andric // When n > 0, compare the first (at most) n bytes of s1 and s2. 355fe6060f1SDimitry Andric static int dfsan_strncmp(const char *s1, const char *s2, size_t n, 356fe6060f1SDimitry Andric size_t *bytes_read) { 357fe6060f1SDimitry Andric for (size_t i = 0;; ++i) { 358fe6060f1SDimitry Andric if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) { 359fe6060f1SDimitry Andric *bytes_read = i + 1; 360fe6060f1SDimitry Andric return s1[i] - s2[i]; 361fe6060f1SDimitry Andric } 362fe6060f1SDimitry Andric } 363e8d8bef9SDimitry Andric } 364e8d8bef9SDimitry Andric 36568d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc, 36668d75effSDimitry Andric const char *s1, const char *s2, 36768d75effSDimitry Andric dfsan_label s1_label, dfsan_label s2_label) 36868d75effSDimitry Andric 369fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc, 370fe6060f1SDimitry Andric const char *s1, const char *s2, 371fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label, 372fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin) 373fe6060f1SDimitry Andric 37468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2, 37568d75effSDimitry Andric dfsan_label s1_label, 37668d75effSDimitry Andric dfsan_label s2_label, 37768d75effSDimitry Andric dfsan_label *ret_label) { 37868d75effSDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2, 37968d75effSDimitry Andric s1_label, s2_label); 380fe6060f1SDimitry Andric size_t bytes_read; 381fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, 0, &bytes_read); 382fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 383fe6060f1SDimitry Andric return r; 38468d75effSDimitry Andric } 38568d75effSDimitry Andric 386fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp( 387fe6060f1SDimitry Andric const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label, 388fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin, 389fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 390fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1, 391fe6060f1SDimitry Andric s2, s1_label, s2_label, s1_origin, s2_origin); 392fe6060f1SDimitry Andric size_t bytes_read; 393fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, 0, &bytes_read); 394fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 395fe6060f1SDimitry Andric return r; 396fe6060f1SDimitry Andric } 397fe6060f1SDimitry Andric 398fe6060f1SDimitry Andric // When n == 0, compare strings without byte limit. 399fe6060f1SDimitry Andric // When n > 0, compare the first (at most) n bytes of s1 and s2. 400fe6060f1SDimitry Andric static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n, 401fe6060f1SDimitry Andric size_t *bytes_read) { 40268d75effSDimitry Andric for (size_t i = 0;; ++i) { 4035ffd83dbSDimitry Andric char s1_lower = tolower(s1[i]); 4045ffd83dbSDimitry Andric char s2_lower = tolower(s2[i]); 4055ffd83dbSDimitry Andric 406fe6060f1SDimitry Andric if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 || 407fe6060f1SDimitry Andric (n > 0 && i == n - 1)) { 408fe6060f1SDimitry Andric *bytes_read = i + 1; 4095ffd83dbSDimitry Andric return s1_lower - s2_lower; 41068d75effSDimitry Andric } 41168d75effSDimitry Andric } 412fe6060f1SDimitry Andric } 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1, 415fe6060f1SDimitry Andric const char *s2, 416fe6060f1SDimitry Andric dfsan_label s1_label, 417fe6060f1SDimitry Andric dfsan_label s2_label, 418fe6060f1SDimitry Andric dfsan_label *ret_label) { 419fe6060f1SDimitry Andric size_t bytes_read; 420fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read); 421fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 422fe6060f1SDimitry Andric return r; 423fe6060f1SDimitry Andric } 424fe6060f1SDimitry Andric 425fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp( 426fe6060f1SDimitry Andric const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label, 427fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin, 428fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 429fe6060f1SDimitry Andric size_t bytes_read; 430fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read); 431fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 432fe6060f1SDimitry Andric return r; 43368d75effSDimitry Andric } 43468d75effSDimitry Andric 43568d75effSDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc, 43668d75effSDimitry Andric const char *s1, const char *s2, size_t n, 43768d75effSDimitry Andric dfsan_label s1_label, dfsan_label s2_label, 43868d75effSDimitry Andric dfsan_label n_label) 43968d75effSDimitry Andric 440fe6060f1SDimitry Andric DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc, 441fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, 442fe6060f1SDimitry Andric dfsan_label s1_label, dfsan_label s2_label, 443fe6060f1SDimitry Andric dfsan_label n_label, dfsan_origin s1_origin, 444fe6060f1SDimitry Andric dfsan_origin s2_origin, dfsan_origin n_origin) 445fe6060f1SDimitry Andric 44668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2, 44768d75effSDimitry Andric size_t n, dfsan_label s1_label, 44868d75effSDimitry Andric dfsan_label s2_label, 44968d75effSDimitry Andric dfsan_label n_label, 45068d75effSDimitry Andric dfsan_label *ret_label) { 45168d75effSDimitry Andric if (n == 0) { 45268d75effSDimitry Andric *ret_label = 0; 45368d75effSDimitry Andric return 0; 45468d75effSDimitry Andric } 45568d75effSDimitry Andric 45668d75effSDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2, 45768d75effSDimitry Andric n, s1_label, s2_label, n_label); 45868d75effSDimitry Andric 459fe6060f1SDimitry Andric size_t bytes_read; 460fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, n, &bytes_read); 461fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 462fe6060f1SDimitry Andric return r; 46368d75effSDimitry Andric } 46468d75effSDimitry Andric 465fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp( 466fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label, 467fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 468fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 469fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 47068d75effSDimitry Andric if (n == 0) { 47168d75effSDimitry Andric *ret_label = 0; 47268d75effSDimitry Andric return 0; 47368d75effSDimitry Andric } 47468d75effSDimitry Andric 475fe6060f1SDimitry Andric CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(), 476fe6060f1SDimitry Andric s1, s2, n, s1_label, s2_label, n_label, s1_origin, 477fe6060f1SDimitry Andric s2_origin, n_origin); 4785ffd83dbSDimitry Andric 479fe6060f1SDimitry Andric size_t bytes_read; 480fe6060f1SDimitry Andric int r = dfsan_strncmp(s1, s2, n, &bytes_read); 481fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 482fe6060f1SDimitry Andric return r; 483fe6060f1SDimitry Andric } 484fe6060f1SDimitry Andric 485fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp( 486fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label, 487fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) { 488fe6060f1SDimitry Andric if (n == 0) { 48968d75effSDimitry Andric *ret_label = 0; 49068d75effSDimitry Andric return 0; 49168d75effSDimitry Andric } 49268d75effSDimitry Andric 493fe6060f1SDimitry Andric size_t bytes_read; 494fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, n, &bytes_read); 495fe6060f1SDimitry Andric *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 496fe6060f1SDimitry Andric return r; 49768d75effSDimitry Andric } 49868d75effSDimitry Andric 499fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp( 500fe6060f1SDimitry Andric const char *s1, const char *s2, size_t n, dfsan_label s1_label, 501fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 502fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 503fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 504fe6060f1SDimitry Andric if (n == 0) { 505fe6060f1SDimitry Andric *ret_label = 0; 506fe6060f1SDimitry Andric return 0; 507fe6060f1SDimitry Andric } 508fe6060f1SDimitry Andric 509fe6060f1SDimitry Andric size_t bytes_read; 510fe6060f1SDimitry Andric int r = dfsan_strncasecmp(s1, s2, n, &bytes_read); 511fe6060f1SDimitry Andric dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 512fe6060f1SDimitry Andric return r; 513fe6060f1SDimitry Andric } 514fe6060f1SDimitry Andric 515fe6060f1SDimitry Andric 51668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t 51768d75effSDimitry Andric __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 51868d75effSDimitry Andric size_t ret = strlen(s); 51968d75effSDimitry Andric if (flags().strict_data_dependencies) { 52068d75effSDimitry Andric *ret_label = 0; 52168d75effSDimitry Andric } else { 52268d75effSDimitry Andric *ret_label = dfsan_read_label(s, ret + 1); 52368d75effSDimitry Andric } 52468d75effSDimitry Andric return ret; 52568d75effSDimitry Andric } 52668d75effSDimitry Andric 527fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s, 528fe6060f1SDimitry Andric dfsan_label s_label, 529fe6060f1SDimitry Andric dfsan_label *ret_label, 530fe6060f1SDimitry Andric dfsan_origin s_origin, 531fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 532fe6060f1SDimitry Andric size_t ret = __dfsw_strlen(s, s_label, ret_label); 533fe6060f1SDimitry Andric if (!flags().strict_data_dependencies) 534fe6060f1SDimitry Andric *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1); 535fe6060f1SDimitry Andric return ret; 536fe6060f1SDimitry Andric } 537fe6060f1SDimitry Andric 538*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s, 539*06c3fb27SDimitry Andric size_t maxlen, 540*06c3fb27SDimitry Andric dfsan_label s_label, 541*06c3fb27SDimitry Andric dfsan_label maxlen_label, 542*06c3fb27SDimitry Andric dfsan_label *ret_label) { 543*06c3fb27SDimitry Andric size_t ret = strnlen(s, maxlen); 544*06c3fb27SDimitry Andric if (flags().strict_data_dependencies) { 545*06c3fb27SDimitry Andric *ret_label = 0; 546*06c3fb27SDimitry Andric } else { 547*06c3fb27SDimitry Andric size_t full_len = strlen(s); 548*06c3fb27SDimitry Andric size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen; 549*06c3fb27SDimitry Andric *ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len)); 550*06c3fb27SDimitry Andric } 551*06c3fb27SDimitry Andric return ret; 552*06c3fb27SDimitry Andric } 553*06c3fb27SDimitry Andric 554*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen( 555*06c3fb27SDimitry Andric const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label, 556*06c3fb27SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin, 557*06c3fb27SDimitry Andric dfsan_origin *ret_origin) { 558*06c3fb27SDimitry Andric size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label); 559*06c3fb27SDimitry Andric if (!flags().strict_data_dependencies) { 560*06c3fb27SDimitry Andric size_t full_len = strlen(s); 561*06c3fb27SDimitry Andric size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen; 562*06c3fb27SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len); 563*06c3fb27SDimitry Andric *ret_origin = o ? o : maxlen_origin; 564*06c3fb27SDimitry Andric } 565*06c3fb27SDimitry Andric return ret; 566*06c3fb27SDimitry Andric } 567*06c3fb27SDimitry Andric 568fe6060f1SDimitry Andric static void *dfsan_memmove(void *dest, const void *src, size_t n) { 569fe6060f1SDimitry Andric dfsan_label *sdest = shadow_for(dest); 570fe6060f1SDimitry Andric const dfsan_label *ssrc = shadow_for(src); 571fe6060f1SDimitry Andric internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label)); 572fe6060f1SDimitry Andric return internal_memmove(dest, src, n); 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 575fe6060f1SDimitry Andric static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) { 576fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, n); 577fe6060f1SDimitry Andric return dfsan_memmove(dest, src, n); 578fe6060f1SDimitry Andric } 57968d75effSDimitry Andric 58068d75effSDimitry Andric static void *dfsan_memcpy(void *dest, const void *src, size_t n) { 58104eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, n); 58268d75effSDimitry Andric return internal_memcpy(dest, src, n); 58368d75effSDimitry Andric } 58468d75effSDimitry Andric 585fe6060f1SDimitry Andric static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) { 586fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, n); 587fe6060f1SDimitry Andric return dfsan_memcpy(dest, src, n); 588fe6060f1SDimitry Andric } 589fe6060f1SDimitry Andric 59068d75effSDimitry Andric static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) { 59168d75effSDimitry Andric internal_memset(s, c, n); 59268d75effSDimitry Andric dfsan_set_label(c_label, s, n); 59368d75effSDimitry Andric } 59468d75effSDimitry Andric 595fe6060f1SDimitry Andric static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label, 596fe6060f1SDimitry Andric dfsan_origin c_origin, size_t n) { 597fe6060f1SDimitry Andric internal_memset(s, c, n); 598fe6060f1SDimitry Andric dfsan_set_label_origin(c_label, c_origin, s, n); 599fe6060f1SDimitry Andric } 600fe6060f1SDimitry Andric 60168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 60268d75effSDimitry Andric void *__dfsw_memcpy(void *dest, const void *src, size_t n, 60368d75effSDimitry Andric dfsan_label dest_label, dfsan_label src_label, 60468d75effSDimitry Andric dfsan_label n_label, dfsan_label *ret_label) { 60568d75effSDimitry Andric *ret_label = dest_label; 60668d75effSDimitry Andric return dfsan_memcpy(dest, src, n); 60768d75effSDimitry Andric } 60868d75effSDimitry Andric 60968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 610fe6060f1SDimitry Andric void *__dfso_memcpy(void *dest, const void *src, size_t n, 611fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label, 612fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label, 613fe6060f1SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin, 614fe6060f1SDimitry Andric dfsan_origin n_origin, dfsan_origin *ret_origin) { 615fe6060f1SDimitry Andric *ret_label = dest_label; 616fe6060f1SDimitry Andric *ret_origin = dest_origin; 617fe6060f1SDimitry Andric return dfsan_memcpy_with_origin(dest, src, n); 618fe6060f1SDimitry Andric } 619fe6060f1SDimitry Andric 620fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 621fe6060f1SDimitry Andric void *__dfsw_memmove(void *dest, const void *src, size_t n, 622fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label, 623fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label) { 624fe6060f1SDimitry Andric *ret_label = dest_label; 625fe6060f1SDimitry Andric return dfsan_memmove(dest, src, n); 626fe6060f1SDimitry Andric } 627fe6060f1SDimitry Andric 628fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 629fe6060f1SDimitry Andric void *__dfso_memmove(void *dest, const void *src, size_t n, 630fe6060f1SDimitry Andric dfsan_label dest_label, dfsan_label src_label, 631fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label, 632fe6060f1SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin, 633fe6060f1SDimitry Andric dfsan_origin n_origin, dfsan_origin *ret_origin) { 634fe6060f1SDimitry Andric *ret_label = dest_label; 635fe6060f1SDimitry Andric *ret_origin = dest_origin; 636fe6060f1SDimitry Andric return dfsan_memmove_with_origin(dest, src, n); 637fe6060f1SDimitry Andric } 638fe6060f1SDimitry Andric 639fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 64068d75effSDimitry Andric void *__dfsw_memset(void *s, int c, size_t n, 64168d75effSDimitry Andric dfsan_label s_label, dfsan_label c_label, 64268d75effSDimitry Andric dfsan_label n_label, dfsan_label *ret_label) { 64368d75effSDimitry Andric dfsan_memset(s, c, c_label, n); 64468d75effSDimitry Andric *ret_label = s_label; 64568d75effSDimitry Andric return s; 64668d75effSDimitry Andric } 64768d75effSDimitry Andric 648fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 649fe6060f1SDimitry Andric void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label, 650fe6060f1SDimitry Andric dfsan_label c_label, dfsan_label n_label, 651fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, 652fe6060f1SDimitry Andric dfsan_origin c_origin, dfsan_origin n_origin, 653fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 654fe6060f1SDimitry Andric dfsan_memset_with_origin(s, c, c_label, c_origin, n); 655fe6060f1SDimitry Andric *ret_label = s_label; 656fe6060f1SDimitry Andric *ret_origin = s_origin; 657fe6060f1SDimitry Andric return s; 658fe6060f1SDimitry Andric } 659fe6060f1SDimitry Andric 660fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src, 661fe6060f1SDimitry Andric dfsan_label dest_label, 662fe6060f1SDimitry Andric dfsan_label src_label, 663fe6060f1SDimitry Andric dfsan_label *ret_label) { 664fe6060f1SDimitry Andric size_t dest_len = strlen(dest); 665349cc55cSDimitry Andric char *ret = strcat(dest, src); 66604eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src)); 667fe6060f1SDimitry Andric *ret_label = dest_label; 668fe6060f1SDimitry Andric return ret; 669fe6060f1SDimitry Andric } 670fe6060f1SDimitry Andric 671fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat( 672fe6060f1SDimitry Andric char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label, 673fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin, 674fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 675fe6060f1SDimitry Andric size_t dest_len = strlen(dest); 676349cc55cSDimitry Andric char *ret = strcat(dest, src); 677fe6060f1SDimitry Andric size_t src_len = strlen(src); 678fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest + dest_len, src, src_len); 67904eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 680fe6060f1SDimitry Andric *ret_label = dest_label; 681fe6060f1SDimitry Andric *ret_origin = dest_origin; 682fe6060f1SDimitry Andric return ret; 683fe6060f1SDimitry Andric } 684fe6060f1SDimitry Andric 685*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat( 686*06c3fb27SDimitry Andric char *dest, const char *src, size_t num, dfsan_label dest_label, 687*06c3fb27SDimitry Andric dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) { 688*06c3fb27SDimitry Andric size_t src_len = strlen(src); 689*06c3fb27SDimitry Andric src_len = src_len < num ? src_len : num; 690*06c3fb27SDimitry Andric size_t dest_len = strlen(dest); 691*06c3fb27SDimitry Andric 692*06c3fb27SDimitry Andric char *ret = strncat(dest, src, num); 693*06c3fb27SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 694*06c3fb27SDimitry Andric *ret_label = dest_label; 695*06c3fb27SDimitry Andric return ret; 696*06c3fb27SDimitry Andric } 697*06c3fb27SDimitry Andric 698*06c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat( 699*06c3fb27SDimitry Andric char *dest, const char *src, size_t num, dfsan_label dest_label, 700*06c3fb27SDimitry Andric dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label, 701*06c3fb27SDimitry Andric dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin, 702*06c3fb27SDimitry Andric dfsan_origin *ret_origin) { 703*06c3fb27SDimitry Andric size_t src_len = strlen(src); 704*06c3fb27SDimitry Andric src_len = src_len < num ? src_len : num; 705*06c3fb27SDimitry Andric size_t dest_len = strlen(dest); 706*06c3fb27SDimitry Andric 707*06c3fb27SDimitry Andric char *ret = strncat(dest, src, num); 708*06c3fb27SDimitry Andric 709*06c3fb27SDimitry Andric dfsan_mem_origin_transfer(dest + dest_len, src, src_len); 710*06c3fb27SDimitry Andric dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 711*06c3fb27SDimitry Andric *ret_label = dest_label; 712*06c3fb27SDimitry Andric *ret_origin = dest_origin; 713*06c3fb27SDimitry Andric return ret; 714*06c3fb27SDimitry Andric } 715*06c3fb27SDimitry Andric 71668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char * 71768d75effSDimitry Andric __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 71868d75effSDimitry Andric size_t len = strlen(s); 71968d75effSDimitry Andric void *p = malloc(len+1); 72068d75effSDimitry Andric dfsan_memcpy(p, s, len+1); 72168d75effSDimitry Andric *ret_label = 0; 72268d75effSDimitry Andric return static_cast<char *>(p); 72368d75effSDimitry Andric } 72468d75effSDimitry Andric 725fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s, 726fe6060f1SDimitry Andric dfsan_label s_label, 727fe6060f1SDimitry Andric dfsan_label *ret_label, 728fe6060f1SDimitry Andric dfsan_origin s_origin, 729fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 730fe6060f1SDimitry Andric size_t len = strlen(s); 731fe6060f1SDimitry Andric void *p = malloc(len + 1); 732fe6060f1SDimitry Andric dfsan_memcpy_with_origin(p, s, len + 1); 733fe6060f1SDimitry Andric *ret_label = 0; 734fe6060f1SDimitry Andric return static_cast<char *>(p); 735fe6060f1SDimitry Andric } 736fe6060f1SDimitry Andric 73768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char * 73868d75effSDimitry Andric __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label, 73968d75effSDimitry Andric dfsan_label s2_label, dfsan_label n_label, 74068d75effSDimitry Andric dfsan_label *ret_label) { 74168d75effSDimitry Andric size_t len = strlen(s2); 74268d75effSDimitry Andric if (len < n) { 74368d75effSDimitry Andric dfsan_memcpy(s1, s2, len+1); 74468d75effSDimitry Andric dfsan_memset(s1+len+1, 0, 0, n-len-1); 74568d75effSDimitry Andric } else { 74668d75effSDimitry Andric dfsan_memcpy(s1, s2, n); 74768d75effSDimitry Andric } 74868d75effSDimitry Andric 74968d75effSDimitry Andric *ret_label = s1_label; 75068d75effSDimitry Andric return s1; 75168d75effSDimitry Andric } 75268d75effSDimitry Andric 753fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy( 754fe6060f1SDimitry Andric char *s1, const char *s2, size_t n, dfsan_label s1_label, 755fe6060f1SDimitry Andric dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 756fe6060f1SDimitry Andric dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 757fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 758fe6060f1SDimitry Andric size_t len = strlen(s2); 759fe6060f1SDimitry Andric if (len < n) { 760fe6060f1SDimitry Andric dfsan_memcpy_with_origin(s1, s2, len + 1); 761fe6060f1SDimitry Andric dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1); 762fe6060f1SDimitry Andric } else { 763fe6060f1SDimitry Andric dfsan_memcpy_with_origin(s1, s2, n); 764fe6060f1SDimitry Andric } 765fe6060f1SDimitry Andric 766fe6060f1SDimitry Andric *ret_label = s1_label; 767fe6060f1SDimitry Andric *ret_origin = s1_origin; 768fe6060f1SDimitry Andric return s1; 769fe6060f1SDimitry Andric } 770fe6060f1SDimitry Andric 77168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t 77268d75effSDimitry Andric __dfsw_pread(int fd, void *buf, size_t count, off_t offset, 77368d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label, 77468d75effSDimitry Andric dfsan_label count_label, dfsan_label offset_label, 77568d75effSDimitry Andric dfsan_label *ret_label) { 77668d75effSDimitry Andric ssize_t ret = pread(fd, buf, count, offset); 77768d75effSDimitry Andric if (ret > 0) 77868d75effSDimitry Andric dfsan_set_label(0, buf, ret); 77968d75effSDimitry Andric *ret_label = 0; 78068d75effSDimitry Andric return ret; 78168d75effSDimitry Andric } 78268d75effSDimitry Andric 783fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread( 784fe6060f1SDimitry Andric int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label, 785fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label, 786fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, 787fe6060f1SDimitry Andric dfsan_origin count_origin, dfsan_label offset_origin, 788fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 789fe6060f1SDimitry Andric return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label, 790fe6060f1SDimitry Andric offset_label, ret_label); 791fe6060f1SDimitry Andric } 792fe6060f1SDimitry Andric 79368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t 79468d75effSDimitry Andric __dfsw_read(int fd, void *buf, size_t count, 79568d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label, 79668d75effSDimitry Andric dfsan_label count_label, 79768d75effSDimitry Andric dfsan_label *ret_label) { 79868d75effSDimitry Andric ssize_t ret = read(fd, buf, count); 79968d75effSDimitry Andric if (ret > 0) 80068d75effSDimitry Andric dfsan_set_label(0, buf, ret); 80168d75effSDimitry Andric *ret_label = 0; 80268d75effSDimitry Andric return ret; 80368d75effSDimitry Andric } 80468d75effSDimitry Andric 805fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read( 806fe6060f1SDimitry Andric int fd, void *buf, size_t count, dfsan_label fd_label, 807fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, 808fe6060f1SDimitry Andric dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, 809fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 810fe6060f1SDimitry Andric return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label, 811fe6060f1SDimitry Andric ret_label); 812fe6060f1SDimitry Andric } 813fe6060f1SDimitry Andric 81468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id, 81568d75effSDimitry Andric struct timespec *tp, 81668d75effSDimitry Andric dfsan_label clk_id_label, 81768d75effSDimitry Andric dfsan_label tp_label, 81868d75effSDimitry Andric dfsan_label *ret_label) { 81968d75effSDimitry Andric int ret = clock_gettime(clk_id, tp); 82068d75effSDimitry Andric if (ret == 0) 82168d75effSDimitry Andric dfsan_set_label(0, tp, sizeof(struct timespec)); 82268d75effSDimitry Andric *ret_label = 0; 82368d75effSDimitry Andric return ret; 82468d75effSDimitry Andric } 82568d75effSDimitry Andric 826fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime( 827fe6060f1SDimitry Andric clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label, 828fe6060f1SDimitry Andric dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin, 829fe6060f1SDimitry Andric dfsan_origin tp_origin, dfsan_origin *ret_origin) { 830fe6060f1SDimitry Andric return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label); 831fe6060f1SDimitry Andric } 832fe6060f1SDimitry Andric 833fe6060f1SDimitry Andric static void dfsan_set_zero_label(const void *ptr, uptr size) { 83468d75effSDimitry Andric dfsan_set_label(0, const_cast<void *>(ptr), size); 83568d75effSDimitry Andric } 83668d75effSDimitry Andric 83768d75effSDimitry Andric // dlopen() ultimately calls mmap() down inside the loader, which generally 83868d75effSDimitry Andric // doesn't participate in dynamic symbol resolution. Therefore we won't 83968d75effSDimitry Andric // intercept its calls to mmap, and we have to hook it here. 84068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void * 84168d75effSDimitry Andric __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label, 84268d75effSDimitry Andric dfsan_label flag_label, dfsan_label *ret_label) { 84368d75effSDimitry Andric void *handle = dlopen(filename, flag); 84468d75effSDimitry Andric link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle); 84568d75effSDimitry Andric if (map) 846fe6060f1SDimitry Andric ForEachMappedRegion(map, dfsan_set_zero_label); 84768d75effSDimitry Andric *ret_label = 0; 84868d75effSDimitry Andric return handle; 84968d75effSDimitry Andric } 85068d75effSDimitry Andric 851fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen( 852fe6060f1SDimitry Andric const char *filename, int flag, dfsan_label filename_label, 853fe6060f1SDimitry Andric dfsan_label flag_label, dfsan_label *ret_label, 854fe6060f1SDimitry Andric dfsan_origin filename_origin, dfsan_origin flag_origin, 855fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 856fe6060f1SDimitry Andric return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label); 857fe6060f1SDimitry Andric } 85868d75effSDimitry Andric 859fe6060f1SDimitry Andric static void *DFsanThreadStartFunc(void *arg) { 860fe6060f1SDimitry Andric DFsanThread *t = (DFsanThread *)arg; 861fe6060f1SDimitry Andric SetCurrentThread(t); 862349cc55cSDimitry Andric t->Init(); 863349cc55cSDimitry Andric SetSigProcMask(&t->starting_sigset_, nullptr); 864fe6060f1SDimitry Andric return t->ThreadStart(); 865fe6060f1SDimitry Andric } 866fe6060f1SDimitry Andric 867fe6060f1SDimitry Andric static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, 868fe6060f1SDimitry Andric void *start_routine, void *arg, 869fe6060f1SDimitry Andric dfsan_label *ret_label, 870fe6060f1SDimitry Andric bool track_origins = false) { 871fe6060f1SDimitry Andric pthread_attr_t myattr; 872fe6060f1SDimitry Andric if (!attr) { 873fe6060f1SDimitry Andric pthread_attr_init(&myattr); 874fe6060f1SDimitry Andric attr = &myattr; 875fe6060f1SDimitry Andric } 876fe6060f1SDimitry Andric 877fe6060f1SDimitry Andric // Ensure that the thread stack is large enough to hold all TLS data. 878fe6060f1SDimitry Andric AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr))); 879fe6060f1SDimitry Andric 880fe6060f1SDimitry Andric DFsanThread *t = 88181ad6265SDimitry Andric DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins); 882349cc55cSDimitry Andric ScopedBlockSignals block(&t->starting_sigset_); 883fe6060f1SDimitry Andric int res = pthread_create(thread, attr, DFsanThreadStartFunc, t); 884fe6060f1SDimitry Andric 885fe6060f1SDimitry Andric if (attr == &myattr) 886fe6060f1SDimitry Andric pthread_attr_destroy(&myattr); 887fe6060f1SDimitry Andric *ret_label = 0; 888fe6060f1SDimitry Andric return res; 88968d75effSDimitry Andric } 89068d75effSDimitry Andric 89168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create( 89281ad6265SDimitry Andric pthread_t *thread, const pthread_attr_t *attr, void *start_routine, 89381ad6265SDimitry Andric void *arg, dfsan_label thread_label, dfsan_label attr_label, 89481ad6265SDimitry Andric dfsan_label start_routine_label, dfsan_label arg_label, 89581ad6265SDimitry Andric dfsan_label *ret_label) { 89681ad6265SDimitry Andric return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label); 897fe6060f1SDimitry Andric } 898fe6060f1SDimitry Andric 899fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create( 90081ad6265SDimitry Andric pthread_t *thread, const pthread_attr_t *attr, void *start_routine, 90181ad6265SDimitry Andric void *arg, dfsan_label thread_label, dfsan_label attr_label, 90281ad6265SDimitry Andric dfsan_label start_routine_label, dfsan_label arg_label, 90381ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin thread_origin, 904fe6060f1SDimitry Andric dfsan_origin attr_origin, dfsan_origin start_routine_origin, 905fe6060f1SDimitry Andric dfsan_origin arg_origin, dfsan_origin *ret_origin) { 90681ad6265SDimitry Andric return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label, 90781ad6265SDimitry Andric true); 90868d75effSDimitry Andric } 90968d75effSDimitry Andric 910e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread, 911e8d8bef9SDimitry Andric void **retval, 912e8d8bef9SDimitry Andric dfsan_label thread_label, 913e8d8bef9SDimitry Andric dfsan_label retval_label, 914e8d8bef9SDimitry Andric dfsan_label *ret_label) { 915e8d8bef9SDimitry Andric int ret = pthread_join(thread, retval); 916e8d8bef9SDimitry Andric if (ret == 0 && retval) 917e8d8bef9SDimitry Andric dfsan_set_label(0, retval, sizeof(*retval)); 918e8d8bef9SDimitry Andric *ret_label = 0; 919e8d8bef9SDimitry Andric return ret; 920e8d8bef9SDimitry Andric } 921e8d8bef9SDimitry Andric 922fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join( 923fe6060f1SDimitry Andric pthread_t thread, void **retval, dfsan_label thread_label, 924fe6060f1SDimitry Andric dfsan_label retval_label, dfsan_label *ret_label, 925fe6060f1SDimitry Andric dfsan_origin thread_origin, dfsan_origin retval_origin, 926fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 927fe6060f1SDimitry Andric return __dfsw_pthread_join(thread, retval, thread_label, retval_label, 928fe6060f1SDimitry Andric ret_label); 929fe6060f1SDimitry Andric } 930fe6060f1SDimitry Andric 93168d75effSDimitry Andric struct dl_iterate_phdr_info { 93281ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data); 933fe6060f1SDimitry Andric void *data; 934fe6060f1SDimitry Andric }; 935fe6060f1SDimitry Andric 93668d75effSDimitry Andric int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) { 93768d75effSDimitry Andric dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data; 93868d75effSDimitry Andric dfsan_set_label(0, *info); 93968d75effSDimitry Andric dfsan_set_label(0, const_cast<char *>(info->dlpi_name), 94068d75effSDimitry Andric strlen(info->dlpi_name) + 1); 94168d75effSDimitry Andric dfsan_set_label( 94268d75effSDimitry Andric 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)), 94368d75effSDimitry Andric sizeof(*info->dlpi_phdr) * info->dlpi_phnum); 94468d75effSDimitry Andric 94581ad6265SDimitry Andric dfsan_clear_thread_local_state(); 94681ad6265SDimitry Andric return dipi->callback(info, size, dipi->data); 947fe6060f1SDimitry Andric } 948fe6060f1SDimitry Andric 94968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( 95081ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data), 95181ad6265SDimitry Andric void *data, dfsan_label callback_label, dfsan_label data_label, 95281ad6265SDimitry Andric dfsan_label *ret_label) { 95381ad6265SDimitry Andric dl_iterate_phdr_info dipi = {callback, data}; 95468d75effSDimitry Andric *ret_label = 0; 95568d75effSDimitry Andric return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); 95668d75effSDimitry Andric } 95768d75effSDimitry Andric 958fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr( 95981ad6265SDimitry Andric int (*callback)(struct dl_phdr_info *info, size_t size, void *data), 96081ad6265SDimitry Andric void *data, dfsan_label callback_label, dfsan_label data_label, 96181ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin callback_origin, 96281ad6265SDimitry Andric dfsan_origin data_origin, dfsan_origin *ret_origin) { 96381ad6265SDimitry Andric dl_iterate_phdr_info dipi = {callback, data}; 964fe6060f1SDimitry Andric *ret_label = 0; 96581ad6265SDimitry Andric return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); 966fe6060f1SDimitry Andric } 967fe6060f1SDimitry Andric 968e8d8bef9SDimitry Andric // This function is only available for glibc 2.27 or newer. Mark it weak so 969e8d8bef9SDimitry Andric // linking succeeds with older glibcs. 970e8d8bef9SDimitry Andric SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep, 971e8d8bef9SDimitry Andric size_t *alignp); 972e8d8bef9SDimitry Andric 973e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info( 974e8d8bef9SDimitry Andric size_t *sizep, size_t *alignp, dfsan_label sizep_label, 975e8d8bef9SDimitry Andric dfsan_label alignp_label) { 976e8d8bef9SDimitry Andric assert(_dl_get_tls_static_info); 977e8d8bef9SDimitry Andric _dl_get_tls_static_info(sizep, alignp); 978e8d8bef9SDimitry Andric dfsan_set_label(0, sizep, sizeof(*sizep)); 979e8d8bef9SDimitry Andric dfsan_set_label(0, alignp, sizeof(*alignp)); 980e8d8bef9SDimitry Andric } 981e8d8bef9SDimitry Andric 982fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info( 983fe6060f1SDimitry Andric size_t *sizep, size_t *alignp, dfsan_label sizep_label, 984fe6060f1SDimitry Andric dfsan_label alignp_label, dfsan_origin sizep_origin, 985fe6060f1SDimitry Andric dfsan_origin alignp_origin) { 986fe6060f1SDimitry Andric __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label); 987fe6060f1SDimitry Andric } 988fe6060f1SDimitry Andric 98968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 99068d75effSDimitry Andric char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, 99168d75effSDimitry Andric dfsan_label buf_label, dfsan_label *ret_label) { 99268d75effSDimitry Andric char *ret = ctime_r(timep, buf); 99368d75effSDimitry Andric if (ret) { 99468d75effSDimitry Andric dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf, 99568d75effSDimitry Andric strlen(buf) + 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 1004fe6060f1SDimitry Andric char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, 1005fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label *ret_label, 1006fe6060f1SDimitry Andric dfsan_origin timep_origin, dfsan_origin buf_origin, 1007fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1008fe6060f1SDimitry Andric char *ret = ctime_r(timep, buf); 1009fe6060f1SDimitry Andric if (ret) { 1010fe6060f1SDimitry Andric dfsan_set_label_origin( 1011fe6060f1SDimitry Andric dfsan_read_label(timep, sizeof(time_t)), 1012fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf, 1013fe6060f1SDimitry Andric strlen(buf) + 1); 1014fe6060f1SDimitry Andric *ret_label = buf_label; 1015fe6060f1SDimitry Andric *ret_origin = buf_origin; 1016fe6060f1SDimitry Andric } else { 1017fe6060f1SDimitry Andric *ret_label = 0; 1018fe6060f1SDimitry Andric } 1019fe6060f1SDimitry Andric return ret; 1020fe6060f1SDimitry Andric } 1021fe6060f1SDimitry Andric 1022fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 102368d75effSDimitry Andric char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label, 102468d75effSDimitry Andric dfsan_label size_label, dfsan_label stream_label, 102568d75effSDimitry Andric dfsan_label *ret_label) { 102668d75effSDimitry Andric char *ret = fgets(s, size, stream); 102768d75effSDimitry Andric if (ret) { 102868d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1); 102968d75effSDimitry Andric *ret_label = s_label; 103068d75effSDimitry Andric } else { 103168d75effSDimitry Andric *ret_label = 0; 103268d75effSDimitry Andric } 103368d75effSDimitry Andric return ret; 103468d75effSDimitry Andric } 103568d75effSDimitry Andric 103668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1037fe6060f1SDimitry Andric char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label, 1038fe6060f1SDimitry Andric dfsan_label size_label, dfsan_label stream_label, 1039fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, 1040fe6060f1SDimitry Andric dfsan_origin size_origin, dfsan_origin stream_origin, 1041fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1042fe6060f1SDimitry Andric char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label, 1043fe6060f1SDimitry Andric ret_label); 1044fe6060f1SDimitry Andric if (ret) 1045fe6060f1SDimitry Andric *ret_origin = s_origin; 1046fe6060f1SDimitry Andric return ret; 1047fe6060f1SDimitry Andric } 1048fe6060f1SDimitry Andric 1049fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 105068d75effSDimitry Andric char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label, 105168d75effSDimitry Andric dfsan_label size_label, dfsan_label *ret_label) { 105268d75effSDimitry Andric char *ret = getcwd(buf, size); 105368d75effSDimitry Andric if (ret) { 105468d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1); 105568d75effSDimitry Andric *ret_label = buf_label; 105668d75effSDimitry Andric } else { 105768d75effSDimitry Andric *ret_label = 0; 105868d75effSDimitry Andric } 105968d75effSDimitry Andric return ret; 106068d75effSDimitry Andric } 106168d75effSDimitry Andric 106268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1063fe6060f1SDimitry Andric char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label, 1064fe6060f1SDimitry Andric dfsan_label size_label, dfsan_label *ret_label, 1065fe6060f1SDimitry Andric dfsan_origin buf_origin, dfsan_origin size_origin, 1066fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1067fe6060f1SDimitry Andric char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label); 1068fe6060f1SDimitry Andric if (ret) 1069fe6060f1SDimitry Andric *ret_origin = buf_origin; 1070fe6060f1SDimitry Andric return ret; 1071fe6060f1SDimitry Andric } 1072fe6060f1SDimitry Andric 1073fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 107468d75effSDimitry Andric char *__dfsw_get_current_dir_name(dfsan_label *ret_label) { 107568d75effSDimitry Andric char *ret = get_current_dir_name(); 1076fe6060f1SDimitry Andric if (ret) 107768d75effSDimitry Andric dfsan_set_label(0, ret, strlen(ret) + 1); 107868d75effSDimitry Andric *ret_label = 0; 107968d75effSDimitry Andric return ret; 108068d75effSDimitry Andric } 108168d75effSDimitry Andric 108268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1083fe6060f1SDimitry Andric char *__dfso_get_current_dir_name(dfsan_label *ret_label, 1084fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1085fe6060f1SDimitry Andric return __dfsw_get_current_dir_name(ret_label); 1086fe6060f1SDimitry Andric } 1087fe6060f1SDimitry Andric 1088349cc55cSDimitry Andric // This function is only available for glibc 2.25 or newer. Mark it weak so 1089349cc55cSDimitry Andric // linking succeeds with older glibcs. 1090349cc55cSDimitry Andric SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length); 1091349cc55cSDimitry Andric 1092349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length, 1093349cc55cSDimitry Andric dfsan_label buffer_label, 1094349cc55cSDimitry Andric dfsan_label length_label, 1095349cc55cSDimitry Andric dfsan_label *ret_label) { 1096349cc55cSDimitry Andric int ret = getentropy(buffer, length); 1097349cc55cSDimitry Andric if (ret == 0) { 1098349cc55cSDimitry Andric dfsan_set_label(0, buffer, length); 1099349cc55cSDimitry Andric } 1100349cc55cSDimitry Andric *ret_label = 0; 1101349cc55cSDimitry Andric return ret; 1102349cc55cSDimitry Andric } 1103349cc55cSDimitry Andric 1104349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length, 1105349cc55cSDimitry Andric dfsan_label buffer_label, 1106349cc55cSDimitry Andric dfsan_label length_label, 1107349cc55cSDimitry Andric dfsan_label *ret_label, 1108349cc55cSDimitry Andric dfsan_origin buffer_origin, 1109349cc55cSDimitry Andric dfsan_origin length_origin, 1110349cc55cSDimitry Andric dfsan_origin *ret_origin) { 1111349cc55cSDimitry Andric return __dfsw_getentropy(buffer, length, buffer_label, length_label, 1112349cc55cSDimitry Andric ret_label); 1113349cc55cSDimitry Andric } 1114349cc55cSDimitry Andric 1115fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 111668d75effSDimitry Andric int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label, 111768d75effSDimitry Andric dfsan_label len_label, dfsan_label *ret_label) { 111868d75effSDimitry Andric int ret = gethostname(name, len); 111968d75effSDimitry Andric if (ret == 0) { 112068d75effSDimitry Andric dfsan_set_label(0, name, strlen(name) + 1); 112168d75effSDimitry Andric } 112268d75effSDimitry Andric *ret_label = 0; 112368d75effSDimitry Andric return ret; 112468d75effSDimitry Andric } 112568d75effSDimitry Andric 112668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1127fe6060f1SDimitry Andric int __dfso_gethostname(char *name, size_t len, dfsan_label name_label, 1128fe6060f1SDimitry Andric dfsan_label len_label, dfsan_label *ret_label, 1129fe6060f1SDimitry Andric dfsan_origin name_origin, dfsan_origin len_origin, 1130fe6060f1SDimitry Andric dfsan_label *ret_origin) { 1131fe6060f1SDimitry Andric return __dfsw_gethostname(name, len, name_label, len_label, ret_label); 1132fe6060f1SDimitry Andric } 1133fe6060f1SDimitry Andric 1134fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 113568d75effSDimitry Andric int __dfsw_getrlimit(int resource, struct rlimit *rlim, 113668d75effSDimitry Andric dfsan_label resource_label, dfsan_label rlim_label, 113768d75effSDimitry Andric dfsan_label *ret_label) { 113868d75effSDimitry Andric int ret = getrlimit(resource, rlim); 113968d75effSDimitry Andric if (ret == 0) { 114068d75effSDimitry Andric dfsan_set_label(0, rlim, sizeof(struct rlimit)); 114168d75effSDimitry Andric } 114268d75effSDimitry Andric *ret_label = 0; 114368d75effSDimitry Andric return ret; 114468d75effSDimitry Andric } 114568d75effSDimitry Andric 114668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1147fe6060f1SDimitry Andric int __dfso_getrlimit(int resource, struct rlimit *rlim, 1148fe6060f1SDimitry Andric dfsan_label resource_label, dfsan_label rlim_label, 1149fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin resource_origin, 1150fe6060f1SDimitry Andric dfsan_origin rlim_origin, dfsan_origin *ret_origin) { 1151fe6060f1SDimitry Andric return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label, 1152fe6060f1SDimitry Andric ret_label); 1153fe6060f1SDimitry Andric } 1154fe6060f1SDimitry Andric 1155fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 115668d75effSDimitry Andric int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label, 115768d75effSDimitry Andric dfsan_label usage_label, dfsan_label *ret_label) { 115868d75effSDimitry Andric int ret = getrusage(who, usage); 115968d75effSDimitry Andric if (ret == 0) { 116068d75effSDimitry Andric dfsan_set_label(0, usage, sizeof(struct rusage)); 116168d75effSDimitry Andric } 116268d75effSDimitry Andric *ret_label = 0; 116368d75effSDimitry Andric return ret; 116468d75effSDimitry Andric } 116568d75effSDimitry Andric 116668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1167fe6060f1SDimitry Andric int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label, 1168fe6060f1SDimitry Andric dfsan_label usage_label, dfsan_label *ret_label, 1169fe6060f1SDimitry Andric dfsan_origin who_origin, dfsan_origin usage_origin, 1170fe6060f1SDimitry Andric dfsan_label *ret_origin) { 1171fe6060f1SDimitry Andric return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label); 1172fe6060f1SDimitry Andric } 1173fe6060f1SDimitry Andric 1174fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 117568d75effSDimitry Andric char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label, 117668d75effSDimitry Andric dfsan_label src_label, dfsan_label *ret_label) { 1177349cc55cSDimitry Andric char *ret = strcpy(dest, src); 117868d75effSDimitry Andric if (ret) { 117904eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1); 118068d75effSDimitry Andric } 118168d75effSDimitry Andric *ret_label = dst_label; 118268d75effSDimitry Andric return ret; 118368d75effSDimitry Andric } 118468d75effSDimitry Andric 118568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1186fe6060f1SDimitry Andric char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label, 1187fe6060f1SDimitry Andric dfsan_label src_label, dfsan_label *ret_label, 1188fe6060f1SDimitry Andric dfsan_origin dst_origin, dfsan_origin src_origin, 1189fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1190349cc55cSDimitry Andric char *ret = strcpy(dest, src); 1191fe6060f1SDimitry Andric if (ret) { 1192fe6060f1SDimitry Andric size_t str_len = strlen(src) + 1; 1193fe6060f1SDimitry Andric dfsan_mem_origin_transfer(dest, src, str_len); 119404eeddc0SDimitry Andric dfsan_mem_shadow_transfer(dest, src, str_len); 119568d75effSDimitry Andric } 1196fe6060f1SDimitry Andric *ret_label = dst_label; 1197fe6060f1SDimitry Andric *ret_origin = dst_origin; 1198fe6060f1SDimitry Andric return ret; 1199fe6060f1SDimitry Andric } 1200fe6060f1SDimitry Andric 1201fe6060f1SDimitry Andric static long int dfsan_strtol(const char *nptr, char **endptr, int base, 1202fe6060f1SDimitry Andric char **tmp_endptr) { 1203fe6060f1SDimitry Andric assert(tmp_endptr); 1204fe6060f1SDimitry Andric long int ret = strtol(nptr, tmp_endptr, base); 1205fe6060f1SDimitry Andric if (endptr) 1206fe6060f1SDimitry Andric *endptr = *tmp_endptr; 1207fe6060f1SDimitry Andric return ret; 1208fe6060f1SDimitry Andric } 1209fe6060f1SDimitry Andric 1210fe6060f1SDimitry Andric static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr, 1211fe6060f1SDimitry Andric dfsan_label base_label, 1212fe6060f1SDimitry Andric dfsan_label *ret_label) { 121368d75effSDimitry Andric if (tmp_endptr > nptr) { 121468d75effSDimitry Andric // If *tmp_endptr is '\0' include its label as well. 121568d75effSDimitry Andric *ret_label = dfsan_union( 121668d75effSDimitry Andric base_label, 121768d75effSDimitry Andric dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 121868d75effSDimitry Andric } else { 121968d75effSDimitry Andric *ret_label = 0; 122068d75effSDimitry Andric } 1221fe6060f1SDimitry Andric } 1222fe6060f1SDimitry Andric 1223fe6060f1SDimitry Andric static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr, 1224fe6060f1SDimitry Andric dfsan_label base_label, 1225fe6060f1SDimitry Andric dfsan_label *ret_label, 1226fe6060f1SDimitry Andric dfsan_origin base_origin, 1227fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1228fe6060f1SDimitry Andric if (tmp_endptr > nptr) { 1229fe6060f1SDimitry Andric // When multiple inputs are tainted, we propagate one of its origins. 1230fe6060f1SDimitry Andric // Because checking if base_label is tainted does not need additional 1231fe6060f1SDimitry Andric // computation, we prefer to propagating base_origin. 1232fe6060f1SDimitry Andric *ret_origin = base_label 1233fe6060f1SDimitry Andric ? base_origin 1234fe6060f1SDimitry Andric : dfsan_read_origin_of_first_taint( 1235fe6060f1SDimitry Andric nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 1236fe6060f1SDimitry Andric } 1237fe6060f1SDimitry Andric } 1238fe6060f1SDimitry Andric 1239fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1240fe6060f1SDimitry Andric long int __dfsw_strtol(const char *nptr, char **endptr, int base, 1241fe6060f1SDimitry Andric dfsan_label nptr_label, dfsan_label endptr_label, 1242fe6060f1SDimitry Andric dfsan_label base_label, dfsan_label *ret_label) { 1243fe6060f1SDimitry Andric char *tmp_endptr; 1244fe6060f1SDimitry Andric long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr); 1245fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 124668d75effSDimitry Andric return ret; 124768d75effSDimitry Andric } 124868d75effSDimitry Andric 124968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1250fe6060f1SDimitry Andric long int __dfso_strtol(const char *nptr, char **endptr, int base, 125168d75effSDimitry Andric dfsan_label nptr_label, dfsan_label endptr_label, 1252fe6060f1SDimitry Andric dfsan_label base_label, dfsan_label *ret_label, 1253fe6060f1SDimitry Andric dfsan_origin nptr_origin, dfsan_origin endptr_origin, 1254fe6060f1SDimitry Andric dfsan_origin base_origin, dfsan_origin *ret_origin) { 125568d75effSDimitry Andric char *tmp_endptr; 1256fe6060f1SDimitry Andric long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr); 1257fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1258fe6060f1SDimitry Andric dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, 1259fe6060f1SDimitry Andric ret_origin); 1260fe6060f1SDimitry Andric return ret; 126168d75effSDimitry Andric } 1262fe6060f1SDimitry Andric 1263fe6060f1SDimitry Andric static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) { 1264fe6060f1SDimitry Andric assert(tmp_endptr); 1265fe6060f1SDimitry Andric double ret = strtod(nptr, tmp_endptr); 1266fe6060f1SDimitry Andric if (endptr) 1267fe6060f1SDimitry Andric *endptr = *tmp_endptr; 1268fe6060f1SDimitry Andric return ret; 1269fe6060f1SDimitry Andric } 1270fe6060f1SDimitry Andric 1271fe6060f1SDimitry Andric static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr, 1272fe6060f1SDimitry Andric dfsan_label *ret_label) { 127368d75effSDimitry Andric if (tmp_endptr > nptr) { 127468d75effSDimitry Andric // If *tmp_endptr is '\0' include its label as well. 127568d75effSDimitry Andric *ret_label = dfsan_read_label( 127668d75effSDimitry Andric nptr, 127768d75effSDimitry Andric tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 127868d75effSDimitry Andric } else { 127968d75effSDimitry Andric *ret_label = 0; 128068d75effSDimitry Andric } 1281fe6060f1SDimitry Andric } 1282fe6060f1SDimitry Andric 1283fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1284fe6060f1SDimitry Andric double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, 1285fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label *ret_label) { 1286fe6060f1SDimitry Andric char *tmp_endptr; 1287fe6060f1SDimitry Andric double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); 1288fe6060f1SDimitry Andric dfsan_strtod_label(nptr, tmp_endptr, ret_label); 1289fe6060f1SDimitry Andric return ret; 1290fe6060f1SDimitry Andric } 1291fe6060f1SDimitry Andric 1292fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1293fe6060f1SDimitry Andric double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, 1294fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label *ret_label, 1295fe6060f1SDimitry Andric dfsan_origin nptr_origin, dfsan_origin endptr_origin, 1296fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1297fe6060f1SDimitry Andric char *tmp_endptr; 1298fe6060f1SDimitry Andric double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); 1299fe6060f1SDimitry Andric dfsan_strtod_label(nptr, tmp_endptr, ret_label); 1300fe6060f1SDimitry Andric if (tmp_endptr > nptr) { 1301fe6060f1SDimitry Andric // If *tmp_endptr is '\0' include its label as well. 1302fe6060f1SDimitry Andric *ret_origin = dfsan_read_origin_of_first_taint( 1303fe6060f1SDimitry Andric nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 1304fe6060f1SDimitry Andric } else { 1305fe6060f1SDimitry Andric *ret_origin = 0; 1306fe6060f1SDimitry Andric } 1307fe6060f1SDimitry Andric return ret; 1308fe6060f1SDimitry Andric } 1309fe6060f1SDimitry Andric 1310fe6060f1SDimitry Andric static long long int dfsan_strtoll(const char *nptr, char **endptr, int base, 1311fe6060f1SDimitry Andric char **tmp_endptr) { 1312fe6060f1SDimitry Andric assert(tmp_endptr); 1313fe6060f1SDimitry Andric long long int ret = strtoll(nptr, tmp_endptr, base); 1314fe6060f1SDimitry Andric if (endptr) 1315fe6060f1SDimitry Andric *endptr = *tmp_endptr; 131668d75effSDimitry Andric return ret; 131768d75effSDimitry Andric } 131868d75effSDimitry Andric 131968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 132068d75effSDimitry Andric long long int __dfsw_strtoll(const char *nptr, char **endptr, int base, 132168d75effSDimitry Andric dfsan_label nptr_label, dfsan_label endptr_label, 132268d75effSDimitry Andric dfsan_label base_label, dfsan_label *ret_label) { 132368d75effSDimitry Andric char *tmp_endptr; 1324fe6060f1SDimitry Andric long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr); 1325fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1326fe6060f1SDimitry Andric return ret; 132768d75effSDimitry Andric } 1328fe6060f1SDimitry Andric 1329fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1330fe6060f1SDimitry Andric long long int __dfso_strtoll(const char *nptr, char **endptr, int base, 1331fe6060f1SDimitry Andric dfsan_label nptr_label, dfsan_label endptr_label, 1332fe6060f1SDimitry Andric dfsan_label base_label, dfsan_label *ret_label, 1333fe6060f1SDimitry Andric dfsan_origin nptr_origin, 1334fe6060f1SDimitry Andric dfsan_origin endptr_origin, 1335fe6060f1SDimitry Andric dfsan_origin base_origin, 1336fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1337fe6060f1SDimitry Andric char *tmp_endptr; 1338fe6060f1SDimitry Andric long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr); 1339fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1340fe6060f1SDimitry Andric dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, 1341fe6060f1SDimitry Andric ret_origin); 1342fe6060f1SDimitry Andric return ret; 134368d75effSDimitry Andric } 1344fe6060f1SDimitry Andric 1345fe6060f1SDimitry Andric static unsigned long int dfsan_strtoul(const char *nptr, char **endptr, 1346fe6060f1SDimitry Andric int base, char **tmp_endptr) { 1347fe6060f1SDimitry Andric assert(tmp_endptr); 1348fe6060f1SDimitry Andric unsigned long int ret = strtoul(nptr, tmp_endptr, base); 1349fe6060f1SDimitry Andric if (endptr) 1350fe6060f1SDimitry Andric *endptr = *tmp_endptr; 135168d75effSDimitry Andric return ret; 135268d75effSDimitry Andric } 135368d75effSDimitry Andric 135468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 135568d75effSDimitry Andric unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base, 135668d75effSDimitry Andric dfsan_label nptr_label, dfsan_label endptr_label, 135768d75effSDimitry Andric dfsan_label base_label, dfsan_label *ret_label) { 135868d75effSDimitry Andric char *tmp_endptr; 1359fe6060f1SDimitry Andric unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr); 1360fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1361fe6060f1SDimitry Andric return ret; 136268d75effSDimitry Andric } 1363fe6060f1SDimitry Andric 1364fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1365fe6060f1SDimitry Andric unsigned long int __dfso_strtoul( 1366fe6060f1SDimitry Andric const char *nptr, char **endptr, int base, dfsan_label nptr_label, 1367fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label, 1368fe6060f1SDimitry Andric dfsan_origin nptr_origin, dfsan_origin endptr_origin, 1369fe6060f1SDimitry Andric dfsan_origin base_origin, dfsan_origin *ret_origin) { 1370fe6060f1SDimitry Andric char *tmp_endptr; 1371fe6060f1SDimitry Andric unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr); 1372fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1373fe6060f1SDimitry Andric dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, 1374fe6060f1SDimitry Andric ret_origin); 1375fe6060f1SDimitry Andric return ret; 137668d75effSDimitry Andric } 1377fe6060f1SDimitry Andric 1378fe6060f1SDimitry Andric static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr, 1379fe6060f1SDimitry Andric int base, char **tmp_endptr) { 1380fe6060f1SDimitry Andric assert(tmp_endptr); 1381fe6060f1SDimitry Andric long long unsigned int ret = strtoull(nptr, tmp_endptr, base); 1382fe6060f1SDimitry Andric if (endptr) 1383fe6060f1SDimitry Andric *endptr = *tmp_endptr; 138468d75effSDimitry Andric return ret; 138568d75effSDimitry Andric } 138668d75effSDimitry Andric 138768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 138868d75effSDimitry Andric long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr, 1389e8d8bef9SDimitry Andric int base, dfsan_label nptr_label, 1390e8d8bef9SDimitry Andric dfsan_label endptr_label, 139168d75effSDimitry Andric dfsan_label base_label, 139268d75effSDimitry Andric dfsan_label *ret_label) { 139368d75effSDimitry Andric char *tmp_endptr; 1394fe6060f1SDimitry Andric long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr); 1395fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1396fe6060f1SDimitry Andric return ret; 139768d75effSDimitry Andric } 1398fe6060f1SDimitry Andric 1399fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1400fe6060f1SDimitry Andric long long unsigned int __dfso_strtoull( 1401fe6060f1SDimitry Andric const char *nptr, char **endptr, int base, dfsan_label nptr_label, 1402fe6060f1SDimitry Andric dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label, 1403fe6060f1SDimitry Andric dfsan_origin nptr_origin, dfsan_origin endptr_origin, 1404fe6060f1SDimitry Andric dfsan_origin base_origin, dfsan_origin *ret_origin) { 1405fe6060f1SDimitry Andric char *tmp_endptr; 1406fe6060f1SDimitry Andric long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr); 1407fe6060f1SDimitry Andric dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); 1408fe6060f1SDimitry Andric dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, 1409fe6060f1SDimitry Andric ret_origin); 141068d75effSDimitry Andric return ret; 141168d75effSDimitry Andric } 141268d75effSDimitry Andric 141368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 141468d75effSDimitry Andric time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) { 141568d75effSDimitry Andric time_t ret = time(t); 141668d75effSDimitry Andric if (ret != (time_t) -1 && t) { 141768d75effSDimitry Andric dfsan_set_label(0, t, sizeof(time_t)); 141868d75effSDimitry Andric } 141968d75effSDimitry Andric *ret_label = 0; 142068d75effSDimitry Andric return ret; 142168d75effSDimitry Andric } 142268d75effSDimitry Andric 142368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1424fe6060f1SDimitry Andric time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label, 1425fe6060f1SDimitry Andric dfsan_origin t_origin, dfsan_origin *ret_origin) { 1426fe6060f1SDimitry Andric return __dfsw_time(t, t_label, ret_label); 1427fe6060f1SDimitry Andric } 1428fe6060f1SDimitry Andric 1429fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 143068d75effSDimitry Andric int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label, 143168d75effSDimitry Andric dfsan_label src_label, dfsan_label dst_label, 143268d75effSDimitry Andric dfsan_label *ret_label) { 143368d75effSDimitry Andric int ret = inet_pton(af, src, dst); 143468d75effSDimitry Andric if (ret == 1) { 143568d75effSDimitry Andric dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst, 143668d75effSDimitry Andric af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr)); 143768d75effSDimitry Andric } 143868d75effSDimitry Andric *ret_label = 0; 143968d75effSDimitry Andric return ret; 144068d75effSDimitry Andric } 144168d75effSDimitry Andric 144268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1443fe6060f1SDimitry Andric int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label, 1444fe6060f1SDimitry Andric dfsan_label src_label, dfsan_label dst_label, 1445fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin af_origin, 1446fe6060f1SDimitry Andric dfsan_origin src_origin, dfsan_origin dst_origin, 1447fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1448fe6060f1SDimitry Andric int ret = inet_pton(af, src, dst); 1449fe6060f1SDimitry Andric if (ret == 1) { 1450fe6060f1SDimitry Andric int src_len = strlen(src) + 1; 1451fe6060f1SDimitry Andric dfsan_set_label_origin( 1452fe6060f1SDimitry Andric dfsan_read_label(src, src_len), 1453fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(src, src_len), dst, 1454fe6060f1SDimitry Andric af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr)); 1455fe6060f1SDimitry Andric } 1456fe6060f1SDimitry Andric *ret_label = 0; 1457fe6060f1SDimitry Andric return ret; 1458fe6060f1SDimitry Andric } 1459fe6060f1SDimitry Andric 1460fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 146168d75effSDimitry Andric struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result, 146268d75effSDimitry Andric dfsan_label timep_label, dfsan_label result_label, 146368d75effSDimitry Andric dfsan_label *ret_label) { 146468d75effSDimitry Andric struct tm *ret = localtime_r(timep, result); 146568d75effSDimitry Andric if (ret) { 146668d75effSDimitry Andric dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result, 146768d75effSDimitry Andric sizeof(struct tm)); 146868d75effSDimitry Andric *ret_label = result_label; 146968d75effSDimitry Andric } else { 147068d75effSDimitry Andric *ret_label = 0; 147168d75effSDimitry Andric } 147268d75effSDimitry Andric return ret; 147368d75effSDimitry Andric } 147468d75effSDimitry Andric 147568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1476fe6060f1SDimitry Andric struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result, 1477fe6060f1SDimitry Andric dfsan_label timep_label, dfsan_label result_label, 1478fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin timep_origin, 1479fe6060f1SDimitry Andric dfsan_origin result_origin, 1480fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1481fe6060f1SDimitry Andric struct tm *ret = localtime_r(timep, result); 1482fe6060f1SDimitry Andric if (ret) { 1483fe6060f1SDimitry Andric dfsan_set_label_origin( 1484fe6060f1SDimitry Andric dfsan_read_label(timep, sizeof(time_t)), 1485fe6060f1SDimitry Andric dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result, 1486fe6060f1SDimitry Andric sizeof(struct tm)); 1487fe6060f1SDimitry Andric *ret_label = result_label; 1488fe6060f1SDimitry Andric *ret_origin = result_origin; 1489fe6060f1SDimitry Andric } else { 1490fe6060f1SDimitry Andric *ret_label = 0; 1491fe6060f1SDimitry Andric } 1492fe6060f1SDimitry Andric return ret; 1493fe6060f1SDimitry Andric } 1494fe6060f1SDimitry Andric 1495fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 149668d75effSDimitry Andric int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd, 149768d75effSDimitry Andric char *buf, size_t buflen, struct passwd **result, 149868d75effSDimitry Andric dfsan_label uid_label, dfsan_label pwd_label, 149968d75effSDimitry Andric dfsan_label buf_label, dfsan_label buflen_label, 150068d75effSDimitry Andric dfsan_label result_label, dfsan_label *ret_label) { 150168d75effSDimitry Andric // Store the data in pwd, the strings referenced from pwd in buf, and the 150268d75effSDimitry Andric // address of pwd in *result. On failure, NULL is stored in *result. 150368d75effSDimitry Andric int ret = getpwuid_r(uid, pwd, buf, buflen, result); 150468d75effSDimitry Andric if (ret == 0) { 150568d75effSDimitry Andric dfsan_set_label(0, pwd, sizeof(struct passwd)); 150668d75effSDimitry Andric dfsan_set_label(0, buf, strlen(buf) + 1); 150768d75effSDimitry Andric } 150868d75effSDimitry Andric *ret_label = 0; 150968d75effSDimitry Andric dfsan_set_label(0, result, sizeof(struct passwd*)); 151068d75effSDimitry Andric return ret; 151168d75effSDimitry Andric } 151268d75effSDimitry Andric 151368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1514fe6060f1SDimitry Andric int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen, 1515fe6060f1SDimitry Andric struct passwd **result, dfsan_label uid_label, 1516fe6060f1SDimitry Andric dfsan_label pwd_label, dfsan_label buf_label, 1517fe6060f1SDimitry Andric dfsan_label buflen_label, dfsan_label result_label, 1518fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin uid_origin, 1519fe6060f1SDimitry Andric dfsan_origin pwd_origin, dfsan_origin buf_origin, 1520fe6060f1SDimitry Andric dfsan_origin buflen_origin, dfsan_origin result_origin, 1521fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1522fe6060f1SDimitry Andric return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label, 1523fe6060f1SDimitry Andric buf_label, buflen_label, result_label, ret_label); 1524fe6060f1SDimitry Andric } 1525fe6060f1SDimitry Andric 1526fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1527e8d8bef9SDimitry Andric int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents, 1528e8d8bef9SDimitry Andric int timeout, dfsan_label epfd_label, 1529e8d8bef9SDimitry Andric dfsan_label events_label, dfsan_label maxevents_label, 1530e8d8bef9SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) { 1531e8d8bef9SDimitry Andric int ret = epoll_wait(epfd, events, maxevents, timeout); 1532e8d8bef9SDimitry Andric if (ret > 0) 1533e8d8bef9SDimitry Andric dfsan_set_label(0, events, ret * sizeof(*events)); 1534e8d8bef9SDimitry Andric *ret_label = 0; 1535e8d8bef9SDimitry Andric return ret; 1536e8d8bef9SDimitry Andric } 1537e8d8bef9SDimitry Andric 1538e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1539fe6060f1SDimitry Andric int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents, 1540fe6060f1SDimitry Andric int timeout, dfsan_label epfd_label, 1541fe6060f1SDimitry Andric dfsan_label events_label, dfsan_label maxevents_label, 1542fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label, 1543fe6060f1SDimitry Andric dfsan_origin epfd_origin, dfsan_origin events_origin, 1544fe6060f1SDimitry Andric dfsan_origin maxevents_origin, 1545fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 1546fe6060f1SDimitry Andric return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label, 1547fe6060f1SDimitry Andric events_label, maxevents_label, timeout_label, 1548fe6060f1SDimitry Andric ret_label); 1549fe6060f1SDimitry Andric } 1550fe6060f1SDimitry Andric 1551fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 155268d75effSDimitry Andric int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout, 155368d75effSDimitry Andric dfsan_label dfs_label, dfsan_label nfds_label, 155468d75effSDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) { 155568d75effSDimitry Andric int ret = poll(fds, nfds, timeout); 155668d75effSDimitry Andric if (ret >= 0) { 155768d75effSDimitry Andric for (; nfds > 0; --nfds) { 155868d75effSDimitry Andric dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents)); 155968d75effSDimitry Andric } 156068d75effSDimitry Andric } 156168d75effSDimitry Andric *ret_label = 0; 156268d75effSDimitry Andric return ret; 156368d75effSDimitry Andric } 156468d75effSDimitry Andric 156568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1566fe6060f1SDimitry Andric int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout, 1567fe6060f1SDimitry Andric dfsan_label dfs_label, dfsan_label nfds_label, 1568fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label, 1569fe6060f1SDimitry Andric dfsan_origin dfs_origin, dfsan_origin nfds_origin, 1570fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 1571fe6060f1SDimitry Andric return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label, 1572fe6060f1SDimitry Andric ret_label); 1573fe6060f1SDimitry Andric } 1574fe6060f1SDimitry Andric 1575fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 157668d75effSDimitry Andric int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds, 157768d75effSDimitry Andric fd_set *exceptfds, struct timeval *timeout, 157868d75effSDimitry Andric dfsan_label nfds_label, dfsan_label readfds_label, 157968d75effSDimitry Andric dfsan_label writefds_label, dfsan_label exceptfds_label, 158068d75effSDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) { 158168d75effSDimitry Andric int ret = select(nfds, readfds, writefds, exceptfds, timeout); 158268d75effSDimitry Andric // Clear everything (also on error) since their content is either set or 158368d75effSDimitry Andric // undefined. 158468d75effSDimitry Andric if (readfds) { 158568d75effSDimitry Andric dfsan_set_label(0, readfds, sizeof(fd_set)); 158668d75effSDimitry Andric } 158768d75effSDimitry Andric if (writefds) { 158868d75effSDimitry Andric dfsan_set_label(0, writefds, sizeof(fd_set)); 158968d75effSDimitry Andric } 159068d75effSDimitry Andric if (exceptfds) { 159168d75effSDimitry Andric dfsan_set_label(0, exceptfds, sizeof(fd_set)); 159268d75effSDimitry Andric } 159368d75effSDimitry Andric dfsan_set_label(0, timeout, sizeof(struct timeval)); 159468d75effSDimitry Andric *ret_label = 0; 159568d75effSDimitry Andric return ret; 159668d75effSDimitry Andric } 159768d75effSDimitry Andric 159868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1599fe6060f1SDimitry Andric int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds, 1600fe6060f1SDimitry Andric fd_set *exceptfds, struct timeval *timeout, 1601fe6060f1SDimitry Andric dfsan_label nfds_label, dfsan_label readfds_label, 1602fe6060f1SDimitry Andric dfsan_label writefds_label, dfsan_label exceptfds_label, 1603fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label, 1604fe6060f1SDimitry Andric dfsan_origin nfds_origin, dfsan_origin readfds_origin, 1605fe6060f1SDimitry Andric dfsan_origin writefds_origin, dfsan_origin exceptfds_origin, 1606fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 1607fe6060f1SDimitry Andric return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label, 1608fe6060f1SDimitry Andric readfds_label, writefds_label, exceptfds_label, 1609fe6060f1SDimitry Andric timeout_label, ret_label); 1610fe6060f1SDimitry Andric } 1611fe6060f1SDimitry Andric 1612fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 161368d75effSDimitry Andric int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask, 161468d75effSDimitry Andric dfsan_label pid_label, 161568d75effSDimitry Andric dfsan_label cpusetsize_label, 161668d75effSDimitry Andric dfsan_label mask_label, dfsan_label *ret_label) { 161768d75effSDimitry Andric int ret = sched_getaffinity(pid, cpusetsize, mask); 161868d75effSDimitry Andric if (ret == 0) { 161968d75effSDimitry Andric dfsan_set_label(0, mask, cpusetsize); 162068d75effSDimitry Andric } 162168d75effSDimitry Andric *ret_label = 0; 162268d75effSDimitry Andric return ret; 162368d75effSDimitry Andric } 162468d75effSDimitry Andric 162568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1626fe6060f1SDimitry Andric int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask, 1627fe6060f1SDimitry Andric dfsan_label pid_label, 1628fe6060f1SDimitry Andric dfsan_label cpusetsize_label, 1629fe6060f1SDimitry Andric dfsan_label mask_label, dfsan_label *ret_label, 1630fe6060f1SDimitry Andric dfsan_origin pid_origin, 1631fe6060f1SDimitry Andric dfsan_origin cpusetsize_origin, 1632fe6060f1SDimitry Andric dfsan_origin mask_origin, 1633fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1634fe6060f1SDimitry Andric return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label, 1635fe6060f1SDimitry Andric cpusetsize_label, mask_label, ret_label); 1636fe6060f1SDimitry Andric } 1637fe6060f1SDimitry Andric 1638fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 163968d75effSDimitry Andric int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label, 164068d75effSDimitry Andric dfsan_label *ret_label) { 164168d75effSDimitry Andric int ret = sigemptyset(set); 164268d75effSDimitry Andric dfsan_set_label(0, set, sizeof(sigset_t)); 1643fe6060f1SDimitry Andric *ret_label = 0; 164468d75effSDimitry Andric return ret; 164568d75effSDimitry Andric } 164668d75effSDimitry Andric 164768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1648fe6060f1SDimitry Andric int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label, 1649fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin set_origin, 1650fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1651fe6060f1SDimitry Andric return __dfsw_sigemptyset(set, set_label, ret_label); 1652fe6060f1SDimitry Andric } 1653fe6060f1SDimitry Andric 1654fe6060f1SDimitry Andric class SignalHandlerScope { 1655fe6060f1SDimitry Andric public: 1656fe6060f1SDimitry Andric SignalHandlerScope() { 1657fe6060f1SDimitry Andric if (DFsanThread *t = GetCurrentThread()) 1658fe6060f1SDimitry Andric t->EnterSignalHandler(); 1659fe6060f1SDimitry Andric } 1660fe6060f1SDimitry Andric ~SignalHandlerScope() { 1661fe6060f1SDimitry Andric if (DFsanThread *t = GetCurrentThread()) 1662fe6060f1SDimitry Andric t->LeaveSignalHandler(); 1663fe6060f1SDimitry Andric } 1664fe6060f1SDimitry Andric }; 1665fe6060f1SDimitry Andric 1666fe6060f1SDimitry Andric // Clear DFSan runtime TLS state at the end of a scope. 1667fe6060f1SDimitry Andric // 1668fe6060f1SDimitry Andric // Implementation must be async-signal-safe and use small data size, because 1669fe6060f1SDimitry Andric // instances of this class may live on the signal handler stack. 1670fe6060f1SDimitry Andric // 1671fe6060f1SDimitry Andric // DFSan uses TLS to pass metadata of arguments and return values. When an 1672fe6060f1SDimitry Andric // instrumented function accesses the TLS, if a signal callback happens, and the 1673fe6060f1SDimitry Andric // callback calls other instrumented functions with updating the same TLS, the 1674fe6060f1SDimitry Andric // TLS is in an inconsistent state after the callback ends. This may cause 1675fe6060f1SDimitry Andric // either under-tainting or over-tainting. 1676fe6060f1SDimitry Andric // 1677fe6060f1SDimitry Andric // The current implementation simply resets TLS at restore. This prevents from 1678fe6060f1SDimitry Andric // over-tainting. Although under-tainting may still happen, a taint flow can be 1679fe6060f1SDimitry Andric // found eventually if we run a DFSan-instrumented program multiple times. The 1680fe6060f1SDimitry Andric // alternative option is saving the entire TLS. However the TLS storage takes 1681fe6060f1SDimitry Andric // 2k bytes, and signal calls could be nested. So it does not seem worth. 1682fe6060f1SDimitry Andric class ScopedClearThreadLocalState { 1683fe6060f1SDimitry Andric public: 1684fe6060f1SDimitry Andric ScopedClearThreadLocalState() {} 1685fe6060f1SDimitry Andric ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); } 1686fe6060f1SDimitry Andric }; 1687fe6060f1SDimitry Andric 1688fe6060f1SDimitry Andric // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls. 1689fe6060f1SDimitry Andric const int kMaxSignals = 1024; 1690fe6060f1SDimitry Andric static atomic_uintptr_t sigactions[kMaxSignals]; 1691fe6060f1SDimitry Andric 1692fe6060f1SDimitry Andric static void SignalHandler(int signo) { 1693fe6060f1SDimitry Andric SignalHandlerScope signal_handler_scope; 1694fe6060f1SDimitry Andric ScopedClearThreadLocalState scoped_clear_tls; 1695fe6060f1SDimitry Andric 169681ad6265SDimitry Andric // Clear shadows for all inputs provided by system. 1697fe6060f1SDimitry Andric dfsan_clear_arg_tls(0, sizeof(dfsan_label)); 1698fe6060f1SDimitry Andric 1699fe6060f1SDimitry Andric typedef void (*signal_cb)(int x); 1700fe6060f1SDimitry Andric signal_cb cb = 1701fe6060f1SDimitry Andric (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1702fe6060f1SDimitry Andric cb(signo); 1703fe6060f1SDimitry Andric } 1704fe6060f1SDimitry Andric 1705fe6060f1SDimitry Andric static void SignalAction(int signo, siginfo_t *si, void *uc) { 1706fe6060f1SDimitry Andric SignalHandlerScope signal_handler_scope; 1707fe6060f1SDimitry Andric ScopedClearThreadLocalState scoped_clear_tls; 1708fe6060f1SDimitry Andric 1709fe6060f1SDimitry Andric // Clear shadows for all inputs provided by system. Similar to SignalHandler. 1710fe6060f1SDimitry Andric dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label)); 1711fe6060f1SDimitry Andric dfsan_set_label(0, si, sizeof(*si)); 1712fe6060f1SDimitry Andric dfsan_set_label(0, uc, sizeof(ucontext_t)); 1713fe6060f1SDimitry Andric 1714fe6060f1SDimitry Andric typedef void (*sigaction_cb)(int, siginfo_t *, void *); 1715fe6060f1SDimitry Andric sigaction_cb cb = 1716fe6060f1SDimitry Andric (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1717fe6060f1SDimitry Andric cb(signo, si, uc); 1718fe6060f1SDimitry Andric } 1719fe6060f1SDimitry Andric 1720fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 172168d75effSDimitry Andric int __dfsw_sigaction(int signum, const struct sigaction *act, 172268d75effSDimitry Andric struct sigaction *oldact, dfsan_label signum_label, 172368d75effSDimitry Andric dfsan_label act_label, dfsan_label oldact_label, 172468d75effSDimitry Andric dfsan_label *ret_label) { 1725fe6060f1SDimitry Andric CHECK_LT(signum, kMaxSignals); 1726fe6060f1SDimitry Andric SignalSpinLocker lock; 1727fe6060f1SDimitry Andric uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed); 1728fe6060f1SDimitry Andric struct sigaction new_act; 1729fe6060f1SDimitry Andric struct sigaction *pnew_act = act ? &new_act : nullptr; 1730fe6060f1SDimitry Andric if (act) { 1731fe6060f1SDimitry Andric internal_memcpy(pnew_act, act, sizeof(struct sigaction)); 1732fe6060f1SDimitry Andric if (pnew_act->sa_flags & SA_SIGINFO) { 1733fe6060f1SDimitry Andric uptr cb = (uptr)(pnew_act->sa_sigaction); 1734fe6060f1SDimitry Andric if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) { 1735fe6060f1SDimitry Andric atomic_store(&sigactions[signum], cb, memory_order_relaxed); 1736fe6060f1SDimitry Andric pnew_act->sa_sigaction = SignalAction; 1737fe6060f1SDimitry Andric } 1738fe6060f1SDimitry Andric } else { 1739fe6060f1SDimitry Andric uptr cb = (uptr)(pnew_act->sa_handler); 1740fe6060f1SDimitry Andric if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) { 1741fe6060f1SDimitry Andric atomic_store(&sigactions[signum], cb, memory_order_relaxed); 1742fe6060f1SDimitry Andric pnew_act->sa_handler = SignalHandler; 1743fe6060f1SDimitry Andric } 1744fe6060f1SDimitry Andric } 1745fe6060f1SDimitry Andric } 1746fe6060f1SDimitry Andric 1747fe6060f1SDimitry Andric int ret = sigaction(signum, pnew_act, oldact); 1748fe6060f1SDimitry Andric 1749fe6060f1SDimitry Andric if (ret == 0 && oldact) { 1750fe6060f1SDimitry Andric if (oldact->sa_flags & SA_SIGINFO) { 1751fe6060f1SDimitry Andric if (oldact->sa_sigaction == SignalAction) 1752fe6060f1SDimitry Andric oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb; 1753fe6060f1SDimitry Andric } else { 1754fe6060f1SDimitry Andric if (oldact->sa_handler == SignalHandler) 1755fe6060f1SDimitry Andric oldact->sa_handler = (decltype(oldact->sa_handler))old_cb; 1756fe6060f1SDimitry Andric } 1757fe6060f1SDimitry Andric } 1758fe6060f1SDimitry Andric 175968d75effSDimitry Andric if (oldact) { 176068d75effSDimitry Andric dfsan_set_label(0, oldact, sizeof(struct sigaction)); 176168d75effSDimitry Andric } 176268d75effSDimitry Andric *ret_label = 0; 176368d75effSDimitry Andric return ret; 176468d75effSDimitry Andric } 176568d75effSDimitry Andric 176668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1767fe6060f1SDimitry Andric int __dfso_sigaction(int signum, const struct sigaction *act, 1768fe6060f1SDimitry Andric struct sigaction *oldact, dfsan_label signum_label, 1769fe6060f1SDimitry Andric dfsan_label act_label, dfsan_label oldact_label, 1770fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin signum_origin, 1771fe6060f1SDimitry Andric dfsan_origin act_origin, dfsan_origin oldact_origin, 1772fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1773fe6060f1SDimitry Andric return __dfsw_sigaction(signum, act, oldact, signum_label, act_label, 1774fe6060f1SDimitry Andric oldact_label, ret_label); 1775fe6060f1SDimitry Andric } 1776fe6060f1SDimitry Andric 1777fe6060f1SDimitry Andric static sighandler_t dfsan_signal(int signum, sighandler_t handler, 1778fe6060f1SDimitry Andric dfsan_label *ret_label) { 1779fe6060f1SDimitry Andric CHECK_LT(signum, kMaxSignals); 1780fe6060f1SDimitry Andric SignalSpinLocker lock; 1781fe6060f1SDimitry Andric uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed); 1782fe6060f1SDimitry Andric if (handler != SIG_IGN && handler != SIG_DFL) { 1783fe6060f1SDimitry Andric atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed); 1784fe6060f1SDimitry Andric handler = &SignalHandler; 1785fe6060f1SDimitry Andric } 1786fe6060f1SDimitry Andric 1787fe6060f1SDimitry Andric sighandler_t ret = signal(signum, handler); 1788fe6060f1SDimitry Andric 1789fe6060f1SDimitry Andric if (ret == SignalHandler) 1790fe6060f1SDimitry Andric ret = (sighandler_t)old_cb; 1791fe6060f1SDimitry Andric 1792fe6060f1SDimitry Andric *ret_label = 0; 1793fe6060f1SDimitry Andric return ret; 1794fe6060f1SDimitry Andric } 1795fe6060f1SDimitry Andric 1796fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 179781ad6265SDimitry Andric sighandler_t __dfsw_signal(int signum, sighandler_t handler, 179881ad6265SDimitry Andric dfsan_label signum_label, dfsan_label handler_label, 179981ad6265SDimitry Andric dfsan_label *ret_label) { 1800fe6060f1SDimitry Andric return dfsan_signal(signum, handler, ret_label); 1801fe6060f1SDimitry Andric } 1802fe6060f1SDimitry Andric 1803fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 180481ad6265SDimitry Andric sighandler_t __dfso_signal(int signum, sighandler_t handler, 180581ad6265SDimitry Andric dfsan_label signum_label, dfsan_label handler_label, 1806fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin signum_origin, 180781ad6265SDimitry Andric dfsan_origin handler_origin, 180881ad6265SDimitry Andric dfsan_origin *ret_origin) { 1809fe6060f1SDimitry Andric return dfsan_signal(signum, handler, ret_label); 1810fe6060f1SDimitry Andric } 1811fe6060f1SDimitry Andric 1812fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1813e8d8bef9SDimitry Andric int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label, 1814e8d8bef9SDimitry Andric dfsan_label old_ss_label, dfsan_label *ret_label) { 1815e8d8bef9SDimitry Andric int ret = sigaltstack(ss, old_ss); 1816e8d8bef9SDimitry Andric if (ret != -1 && old_ss) 1817e8d8bef9SDimitry Andric dfsan_set_label(0, old_ss, sizeof(*old_ss)); 1818e8d8bef9SDimitry Andric *ret_label = 0; 1819e8d8bef9SDimitry Andric return ret; 1820e8d8bef9SDimitry Andric } 1821e8d8bef9SDimitry Andric 1822e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1823fe6060f1SDimitry Andric int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label, 1824fe6060f1SDimitry Andric dfsan_label old_ss_label, dfsan_label *ret_label, 1825fe6060f1SDimitry Andric dfsan_origin ss_origin, dfsan_origin old_ss_origin, 1826fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1827fe6060f1SDimitry Andric return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label); 1828fe6060f1SDimitry Andric } 1829fe6060f1SDimitry Andric 1830fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 183168d75effSDimitry Andric int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz, 183268d75effSDimitry Andric dfsan_label tv_label, dfsan_label tz_label, 183368d75effSDimitry Andric dfsan_label *ret_label) { 183468d75effSDimitry Andric int ret = gettimeofday(tv, tz); 183568d75effSDimitry Andric if (tv) { 183668d75effSDimitry Andric dfsan_set_label(0, tv, sizeof(struct timeval)); 183768d75effSDimitry Andric } 183868d75effSDimitry Andric if (tz) { 183968d75effSDimitry Andric dfsan_set_label(0, tz, sizeof(struct timezone)); 184068d75effSDimitry Andric } 184168d75effSDimitry Andric *ret_label = 0; 184268d75effSDimitry Andric return ret; 184368d75effSDimitry Andric } 184468d75effSDimitry Andric 1845fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 1846fe6060f1SDimitry Andric int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz, 1847fe6060f1SDimitry Andric dfsan_label tv_label, dfsan_label tz_label, 1848fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin tv_origin, 1849fe6060f1SDimitry Andric dfsan_origin tz_origin, dfsan_origin *ret_origin) { 1850fe6060f1SDimitry Andric return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label); 1851fe6060f1SDimitry Andric } 1852fe6060f1SDimitry Andric 185368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n, 185468d75effSDimitry Andric dfsan_label s_label, 185568d75effSDimitry Andric dfsan_label c_label, 185668d75effSDimitry Andric dfsan_label n_label, 185768d75effSDimitry Andric dfsan_label *ret_label) { 185868d75effSDimitry Andric void *ret = memchr(s, c, n); 185968d75effSDimitry Andric if (flags().strict_data_dependencies) { 186068d75effSDimitry Andric *ret_label = ret ? s_label : 0; 186168d75effSDimitry Andric } else { 186268d75effSDimitry Andric size_t len = 186368d75effSDimitry Andric ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1 186468d75effSDimitry Andric : n; 186568d75effSDimitry Andric *ret_label = 186668d75effSDimitry Andric dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label)); 186768d75effSDimitry Andric } 186868d75effSDimitry Andric return ret; 186968d75effSDimitry Andric } 187068d75effSDimitry Andric 1871fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr( 1872fe6060f1SDimitry Andric void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label, 1873fe6060f1SDimitry Andric dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin, 1874fe6060f1SDimitry Andric dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) { 1875fe6060f1SDimitry Andric void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label); 1876fe6060f1SDimitry Andric if (flags().strict_data_dependencies) { 1877fe6060f1SDimitry Andric if (ret) 1878fe6060f1SDimitry Andric *ret_origin = s_origin; 1879fe6060f1SDimitry Andric } else { 1880fe6060f1SDimitry Andric size_t len = 1881fe6060f1SDimitry Andric ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1 1882fe6060f1SDimitry Andric : n; 1883fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, len); 1884fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin); 1885fe6060f1SDimitry Andric } 1886fe6060f1SDimitry Andric return ret; 1887fe6060f1SDimitry Andric } 1888fe6060f1SDimitry Andric 188968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c, 189068d75effSDimitry Andric dfsan_label s_label, 189168d75effSDimitry Andric dfsan_label c_label, 189268d75effSDimitry Andric dfsan_label *ret_label) { 189368d75effSDimitry Andric char *ret = strrchr(s, c); 189468d75effSDimitry Andric if (flags().strict_data_dependencies) { 189568d75effSDimitry Andric *ret_label = ret ? s_label : 0; 189668d75effSDimitry Andric } else { 189768d75effSDimitry Andric *ret_label = 189868d75effSDimitry Andric dfsan_union(dfsan_read_label(s, strlen(s) + 1), 189968d75effSDimitry Andric dfsan_union(s_label, c_label)); 190068d75effSDimitry Andric } 190168d75effSDimitry Andric 190268d75effSDimitry Andric return ret; 190368d75effSDimitry Andric } 190468d75effSDimitry Andric 1905fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr( 1906fe6060f1SDimitry Andric char *s, int c, dfsan_label s_label, dfsan_label c_label, 1907fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin, 1908fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1909fe6060f1SDimitry Andric char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label); 1910fe6060f1SDimitry Andric if (flags().strict_data_dependencies) { 1911fe6060f1SDimitry Andric if (ret) 1912fe6060f1SDimitry Andric *ret_origin = s_origin; 1913fe6060f1SDimitry Andric } else { 1914fe6060f1SDimitry Andric size_t s_len = strlen(s) + 1; 1915fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len); 1916fe6060f1SDimitry Andric *ret_origin = o ? o : (s_label ? s_origin : c_origin); 1917fe6060f1SDimitry Andric } 1918fe6060f1SDimitry Andric 1919fe6060f1SDimitry Andric return ret; 1920fe6060f1SDimitry Andric } 1921fe6060f1SDimitry Andric 192268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle, 192368d75effSDimitry Andric dfsan_label haystack_label, 192468d75effSDimitry Andric dfsan_label needle_label, 192568d75effSDimitry Andric dfsan_label *ret_label) { 192668d75effSDimitry Andric char *ret = strstr(haystack, needle); 192768d75effSDimitry Andric if (flags().strict_data_dependencies) { 192868d75effSDimitry Andric *ret_label = ret ? haystack_label : 0; 192968d75effSDimitry Andric } else { 193068d75effSDimitry Andric size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1; 193168d75effSDimitry Andric *ret_label = 193268d75effSDimitry Andric dfsan_union(dfsan_read_label(haystack, len), 193368d75effSDimitry Andric dfsan_union(dfsan_read_label(needle, strlen(needle) + 1), 193468d75effSDimitry Andric dfsan_union(haystack_label, needle_label))); 193568d75effSDimitry Andric } 193668d75effSDimitry Andric 193768d75effSDimitry Andric return ret; 193868d75effSDimitry Andric } 193968d75effSDimitry Andric 1940fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle, 1941fe6060f1SDimitry Andric dfsan_label haystack_label, 1942fe6060f1SDimitry Andric dfsan_label needle_label, 1943fe6060f1SDimitry Andric dfsan_label *ret_label, 1944fe6060f1SDimitry Andric dfsan_origin haystack_origin, 1945fe6060f1SDimitry Andric dfsan_origin needle_origin, 1946fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 1947fe6060f1SDimitry Andric char *ret = 1948fe6060f1SDimitry Andric __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label); 1949fe6060f1SDimitry Andric if (flags().strict_data_dependencies) { 1950fe6060f1SDimitry Andric if (ret) 1951fe6060f1SDimitry Andric *ret_origin = haystack_origin; 1952fe6060f1SDimitry Andric } else { 1953fe6060f1SDimitry Andric size_t needle_len = strlen(needle); 1954fe6060f1SDimitry Andric size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1; 1955fe6060f1SDimitry Andric dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len); 1956fe6060f1SDimitry Andric if (o) { 1957fe6060f1SDimitry Andric *ret_origin = o; 1958fe6060f1SDimitry Andric } else { 1959fe6060f1SDimitry Andric o = dfsan_read_origin_of_first_taint(needle, needle_len + 1); 1960fe6060f1SDimitry Andric *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin); 1961fe6060f1SDimitry Andric } 1962fe6060f1SDimitry Andric } 1963fe6060f1SDimitry Andric 1964fe6060f1SDimitry Andric return ret; 1965fe6060f1SDimitry Andric } 1966fe6060f1SDimitry Andric 196768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req, 196868d75effSDimitry Andric struct timespec *rem, 196968d75effSDimitry Andric dfsan_label req_label, 197068d75effSDimitry Andric dfsan_label rem_label, 197168d75effSDimitry Andric dfsan_label *ret_label) { 197268d75effSDimitry Andric int ret = nanosleep(req, rem); 197368d75effSDimitry Andric *ret_label = 0; 197468d75effSDimitry Andric if (ret == -1) { 197568d75effSDimitry Andric // Interrupted by a signal, rem is filled with the remaining time. 197668d75effSDimitry Andric dfsan_set_label(0, rem, sizeof(struct timespec)); 197768d75effSDimitry Andric } 197868d75effSDimitry Andric return ret; 197968d75effSDimitry Andric } 198068d75effSDimitry Andric 1981fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep( 1982fe6060f1SDimitry Andric const struct timespec *req, struct timespec *rem, dfsan_label req_label, 1983fe6060f1SDimitry Andric dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin, 1984fe6060f1SDimitry Andric dfsan_origin rem_origin, dfsan_origin *ret_origin) { 1985fe6060f1SDimitry Andric return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label); 1986fe6060f1SDimitry Andric } 1987fe6060f1SDimitry Andric 1988e8d8bef9SDimitry Andric static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) { 1989e8d8bef9SDimitry Andric dfsan_set_label(0, msg, sizeof(*msg)); 1990e8d8bef9SDimitry Andric dfsan_set_label(0, msg->msg_name, msg->msg_namelen); 1991e8d8bef9SDimitry Andric dfsan_set_label(0, msg->msg_control, msg->msg_controllen); 1992e8d8bef9SDimitry Andric for (size_t i = 0; bytes_written > 0; ++i) { 1993e8d8bef9SDimitry Andric assert(i < msg->msg_iovlen); 1994e8d8bef9SDimitry Andric struct iovec *iov = &msg->msg_iov[i]; 1995e8d8bef9SDimitry Andric size_t iov_written = 1996e8d8bef9SDimitry Andric bytes_written < iov->iov_len ? bytes_written : iov->iov_len; 1997e8d8bef9SDimitry Andric dfsan_set_label(0, iov->iov_base, iov_written); 1998e8d8bef9SDimitry Andric bytes_written -= iov_written; 1999e8d8bef9SDimitry Andric } 2000e8d8bef9SDimitry Andric } 2001e8d8bef9SDimitry Andric 2002e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg( 2003e8d8bef9SDimitry Andric int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, 2004e8d8bef9SDimitry Andric struct timespec *timeout, dfsan_label sockfd_label, 2005e8d8bef9SDimitry Andric dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label, 2006e8d8bef9SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label) { 2007e8d8bef9SDimitry Andric int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout); 2008e8d8bef9SDimitry Andric for (int i = 0; i < ret; ++i) { 2009e8d8bef9SDimitry Andric dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len)); 2010e8d8bef9SDimitry Andric clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr); 2011e8d8bef9SDimitry Andric } 2012e8d8bef9SDimitry Andric *ret_label = 0; 2013e8d8bef9SDimitry Andric return ret; 2014e8d8bef9SDimitry Andric } 2015e8d8bef9SDimitry Andric 2016fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg( 2017fe6060f1SDimitry Andric int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, 2018fe6060f1SDimitry Andric struct timespec *timeout, dfsan_label sockfd_label, 2019fe6060f1SDimitry Andric dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label, 2020fe6060f1SDimitry Andric dfsan_label timeout_label, dfsan_label *ret_label, 2021fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin msgvec_origin, 2022fe6060f1SDimitry Andric dfsan_origin vlen_origin, dfsan_origin flags_origin, 2023fe6060f1SDimitry Andric dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 2024fe6060f1SDimitry Andric return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label, 2025fe6060f1SDimitry Andric msgvec_label, vlen_label, flags_label, timeout_label, 2026fe6060f1SDimitry Andric ret_label); 2027fe6060f1SDimitry Andric } 2028fe6060f1SDimitry Andric 2029e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg( 2030e8d8bef9SDimitry Andric int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, 2031e8d8bef9SDimitry Andric dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) { 2032e8d8bef9SDimitry Andric ssize_t ret = recvmsg(sockfd, msg, flags); 2033e8d8bef9SDimitry Andric if (ret >= 0) 2034e8d8bef9SDimitry Andric clear_msghdr_labels(ret, msg); 2035e8d8bef9SDimitry Andric *ret_label = 0; 2036e8d8bef9SDimitry Andric return ret; 2037e8d8bef9SDimitry Andric } 2038e8d8bef9SDimitry Andric 2039fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg( 2040fe6060f1SDimitry Andric int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, 2041fe6060f1SDimitry Andric dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label, 2042fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin msg_origin, 2043fe6060f1SDimitry Andric dfsan_origin flags_origin, dfsan_origin *ret_origin) { 2044fe6060f1SDimitry Andric return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label, 2045fe6060f1SDimitry Andric flags_label, ret_label); 2046fe6060f1SDimitry Andric } 2047fe6060f1SDimitry Andric 204868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int 204968d75effSDimitry Andric __dfsw_socketpair(int domain, int type, int protocol, int sv[2], 205068d75effSDimitry Andric dfsan_label domain_label, dfsan_label type_label, 205168d75effSDimitry Andric dfsan_label protocol_label, dfsan_label sv_label, 205268d75effSDimitry Andric dfsan_label *ret_label) { 205368d75effSDimitry Andric int ret = socketpair(domain, type, protocol, sv); 205468d75effSDimitry Andric *ret_label = 0; 205568d75effSDimitry Andric if (ret == 0) { 205668d75effSDimitry Andric dfsan_set_label(0, sv, sizeof(*sv) * 2); 205768d75effSDimitry Andric } 205868d75effSDimitry Andric return ret; 205968d75effSDimitry Andric } 206068d75effSDimitry Andric 2061fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair( 2062fe6060f1SDimitry Andric int domain, int type, int protocol, int sv[2], dfsan_label domain_label, 2063fe6060f1SDimitry Andric dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label, 2064fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin domain_origin, 2065fe6060f1SDimitry Andric dfsan_origin type_origin, dfsan_origin protocol_origin, 2066fe6060f1SDimitry Andric dfsan_origin sv_origin, dfsan_origin *ret_origin) { 2067fe6060f1SDimitry Andric return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label, 2068fe6060f1SDimitry Andric protocol_label, sv_label, ret_label); 2069fe6060f1SDimitry Andric } 2070fe6060f1SDimitry Andric 2071e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt( 2072e8d8bef9SDimitry Andric int sockfd, int level, int optname, void *optval, socklen_t *optlen, 2073e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label level_label, 2074e8d8bef9SDimitry Andric dfsan_label optname_label, dfsan_label optval_label, 2075e8d8bef9SDimitry Andric dfsan_label optlen_label, dfsan_label *ret_label) { 2076e8d8bef9SDimitry Andric int ret = getsockopt(sockfd, level, optname, optval, optlen); 2077e8d8bef9SDimitry Andric if (ret != -1 && optval && optlen) { 2078e8d8bef9SDimitry Andric dfsan_set_label(0, optlen, sizeof(*optlen)); 2079e8d8bef9SDimitry Andric dfsan_set_label(0, optval, *optlen); 2080e8d8bef9SDimitry Andric } 2081e8d8bef9SDimitry Andric *ret_label = 0; 2082e8d8bef9SDimitry Andric return ret; 2083e8d8bef9SDimitry Andric } 2084e8d8bef9SDimitry Andric 2085fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt( 2086fe6060f1SDimitry Andric int sockfd, int level, int optname, void *optval, socklen_t *optlen, 2087fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label level_label, 2088fe6060f1SDimitry Andric dfsan_label optname_label, dfsan_label optval_label, 2089fe6060f1SDimitry Andric dfsan_label optlen_label, dfsan_label *ret_label, 2090fe6060f1SDimitry Andric dfsan_origin sockfd_origin, dfsan_origin level_origin, 2091fe6060f1SDimitry Andric dfsan_origin optname_origin, dfsan_origin optval_origin, 2092fe6060f1SDimitry Andric dfsan_origin optlen_origin, dfsan_origin *ret_origin) { 2093fe6060f1SDimitry Andric return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label, 2094fe6060f1SDimitry Andric level_label, optname_label, optval_label, 2095fe6060f1SDimitry Andric optlen_label, ret_label); 2096fe6060f1SDimitry Andric } 2097fe6060f1SDimitry Andric 2098e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname( 2099e8d8bef9SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen, 2100e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 2101e8d8bef9SDimitry Andric dfsan_label *ret_label) { 2102e8d8bef9SDimitry Andric socklen_t origlen = addrlen ? *addrlen : 0; 2103e8d8bef9SDimitry Andric int ret = getsockname(sockfd, addr, addrlen); 2104e8d8bef9SDimitry Andric if (ret != -1 && addr && addrlen) { 2105e8d8bef9SDimitry Andric socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen; 2106e8d8bef9SDimitry Andric dfsan_set_label(0, addrlen, sizeof(*addrlen)); 2107e8d8bef9SDimitry Andric dfsan_set_label(0, addr, written_bytes); 2108e8d8bef9SDimitry Andric } 2109e8d8bef9SDimitry Andric *ret_label = 0; 2110e8d8bef9SDimitry Andric return ret; 2111e8d8bef9SDimitry Andric } 2112e8d8bef9SDimitry Andric 2113fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname( 2114fe6060f1SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen, 2115fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 2116fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin sockfd_origin, 2117fe6060f1SDimitry Andric dfsan_origin addr_origin, dfsan_origin addrlen_origin, 2118fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 2119fe6060f1SDimitry Andric return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label, 2120fe6060f1SDimitry Andric addrlen_label, ret_label); 2121fe6060f1SDimitry Andric } 2122fe6060f1SDimitry Andric 2123e8d8bef9SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername( 2124e8d8bef9SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen, 2125e8d8bef9SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 2126e8d8bef9SDimitry Andric dfsan_label *ret_label) { 2127e8d8bef9SDimitry Andric socklen_t origlen = addrlen ? *addrlen : 0; 2128e8d8bef9SDimitry Andric int ret = getpeername(sockfd, addr, addrlen); 2129e8d8bef9SDimitry Andric if (ret != -1 && addr && addrlen) { 2130e8d8bef9SDimitry Andric socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen; 2131e8d8bef9SDimitry Andric dfsan_set_label(0, addrlen, sizeof(*addrlen)); 2132e8d8bef9SDimitry Andric dfsan_set_label(0, addr, written_bytes); 2133e8d8bef9SDimitry Andric } 2134e8d8bef9SDimitry Andric *ret_label = 0; 2135e8d8bef9SDimitry Andric return ret; 2136e8d8bef9SDimitry Andric } 2137e8d8bef9SDimitry Andric 2138fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername( 2139fe6060f1SDimitry Andric int sockfd, struct sockaddr *addr, socklen_t *addrlen, 2140fe6060f1SDimitry Andric dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 2141fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin sockfd_origin, 2142fe6060f1SDimitry Andric dfsan_origin addr_origin, dfsan_origin addrlen_origin, 2143fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 2144fe6060f1SDimitry Andric return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label, 2145fe6060f1SDimitry Andric addrlen_label, ret_label); 2146fe6060f1SDimitry Andric } 2147fe6060f1SDimitry Andric 214881ad6265SDimitry Andric // Type of the function passed to dfsan_set_write_callback. 214981ad6265SDimitry Andric typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count); 2150fe6060f1SDimitry Andric 215168d75effSDimitry Andric // Calls to dfsan_set_write_callback() set the values in this struct. 215268d75effSDimitry Andric // Calls to the custom version of write() read (and invoke) them. 215368d75effSDimitry Andric static struct { 215481ad6265SDimitry Andric write_dfsan_callback_t write_callback = nullptr; 215568d75effSDimitry Andric } write_callback_info; 215668d75effSDimitry Andric 215781ad6265SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback( 215881ad6265SDimitry Andric write_dfsan_callback_t write_callback, dfsan_label write_callback_label, 215968d75effSDimitry Andric dfsan_label *ret_label) { 216068d75effSDimitry Andric write_callback_info.write_callback = write_callback; 216168d75effSDimitry Andric } 216268d75effSDimitry Andric 2163fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback( 216481ad6265SDimitry Andric write_dfsan_callback_t write_callback, dfsan_label write_callback_label, 216581ad6265SDimitry Andric dfsan_label *ret_label, dfsan_origin write_callback_origin, 216681ad6265SDimitry Andric dfsan_origin *ret_origin) { 216781ad6265SDimitry Andric write_callback_info.write_callback = write_callback; 216881ad6265SDimitry Andric } 216981ad6265SDimitry Andric 217081ad6265SDimitry Andric static inline void setup_tls_args_for_write_callback( 217181ad6265SDimitry Andric dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, 217281ad6265SDimitry Andric bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin, 217381ad6265SDimitry Andric dfsan_origin count_origin) { 217481ad6265SDimitry Andric // The callback code will expect argument shadow labels in the args TLS, 217581ad6265SDimitry Andric // and origin labels in the origin args TLS. 217681ad6265SDimitry Andric // Previously this was done by a trampoline, but we want to remove this: 217781ad6265SDimitry Andric // https://github.com/llvm/llvm-project/issues/54172 217881ad6265SDimitry Andric // 217981ad6265SDimitry Andric // Instead, this code is manually setting up the args TLS data. 218081ad6265SDimitry Andric // 218181ad6265SDimitry Andric // The offsets used need to correspond with the instrumentation code, 218281ad6265SDimitry Andric // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp 218381ad6265SDimitry Andric // DFSanFunction::getShadowForTLSArgument. 218481ad6265SDimitry Andric // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684 218581ad6265SDimitry Andric // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125 218681ad6265SDimitry Andric // 218781ad6265SDimitry Andric // Here the arguments are all primitives, but it can be more complex 218881ad6265SDimitry Andric // to compute offsets for array/aggregate type arguments. 218981ad6265SDimitry Andric // 219081ad6265SDimitry Andric // TODO(browneee): Consider a builtin to improve maintainabliity. 219181ad6265SDimitry Andric // With a builtin, we would provide the argument labels via builtin, 219281ad6265SDimitry Andric // and the builtin would reuse parts of the instrumentation code to ensure 219381ad6265SDimitry Andric // that this code and the instrumentation can never be out of sync. 219481ad6265SDimitry Andric // Note: Currently DFSan instrumentation does not run on this code, so 219581ad6265SDimitry Andric // the builtin may need to be handled outside DFSan instrumentation. 219681ad6265SDimitry Andric dfsan_set_arg_tls(0, fd_label); 219781ad6265SDimitry Andric dfsan_set_arg_tls(1, buf_label); 219881ad6265SDimitry Andric dfsan_set_arg_tls(2, count_label); 219981ad6265SDimitry Andric if (origins) { 220081ad6265SDimitry Andric dfsan_set_arg_origin_tls(0, fd_origin); 220181ad6265SDimitry Andric dfsan_set_arg_origin_tls(1, buf_origin); 220281ad6265SDimitry Andric dfsan_set_arg_origin_tls(2, count_origin); 220381ad6265SDimitry Andric } 2204fe6060f1SDimitry Andric } 2205fe6060f1SDimitry Andric 220668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int 220768d75effSDimitry Andric __dfsw_write(int fd, const void *buf, size_t count, 220868d75effSDimitry Andric dfsan_label fd_label, dfsan_label buf_label, 220968d75effSDimitry Andric dfsan_label count_label, dfsan_label *ret_label) { 221068d75effSDimitry Andric if (write_callback_info.write_callback) { 221181ad6265SDimitry Andric setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false, 221281ad6265SDimitry Andric 0, 0, 0); 221381ad6265SDimitry Andric write_callback_info.write_callback(fd, buf, count); 221468d75effSDimitry Andric } 221568d75effSDimitry Andric 221668d75effSDimitry Andric *ret_label = 0; 221768d75effSDimitry Andric return write(fd, buf, count); 221868d75effSDimitry Andric } 2219fe6060f1SDimitry Andric 2220fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write( 2221fe6060f1SDimitry Andric int fd, const void *buf, size_t count, dfsan_label fd_label, 2222fe6060f1SDimitry Andric dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, 2223fe6060f1SDimitry Andric dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, 2224fe6060f1SDimitry Andric dfsan_origin *ret_origin) { 222581ad6265SDimitry Andric if (write_callback_info.write_callback) { 222681ad6265SDimitry Andric setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true, 222781ad6265SDimitry Andric fd_origin, buf_origin, count_origin); 222881ad6265SDimitry Andric write_callback_info.write_callback(fd, buf, count); 2229fe6060f1SDimitry Andric } 2230fe6060f1SDimitry Andric 2231fe6060f1SDimitry Andric *ret_label = 0; 2232fe6060f1SDimitry Andric return write(fd, buf, count); 2233fe6060f1SDimitry Andric } 223468d75effSDimitry Andric } // namespace __dfsan 223568d75effSDimitry Andric 223668d75effSDimitry Andric // Type used to extract a dfsan_label with va_arg() 223768d75effSDimitry Andric typedef int dfsan_label_va; 223868d75effSDimitry Andric 223968d75effSDimitry Andric // Formats a chunk either a constant string or a single format directive (e.g., 224068d75effSDimitry Andric // '%.3f'). 224168d75effSDimitry Andric struct Formatter { 224268d75effSDimitry Andric Formatter(char *str_, const char *fmt_, size_t size_) 224368d75effSDimitry Andric : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_), 224468d75effSDimitry Andric width(-1) {} 224568d75effSDimitry Andric 224668d75effSDimitry Andric int format() { 224768d75effSDimitry Andric char *tmp_fmt = build_format_string(); 224868d75effSDimitry Andric int retval = 224968d75effSDimitry Andric snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt, 225068d75effSDimitry Andric 0 /* used only to avoid warnings */); 225168d75effSDimitry Andric free(tmp_fmt); 225268d75effSDimitry Andric return retval; 225368d75effSDimitry Andric } 225468d75effSDimitry Andric 225568d75effSDimitry Andric template <typename T> int format(T arg) { 225668d75effSDimitry Andric char *tmp_fmt = build_format_string(); 225768d75effSDimitry Andric int retval; 225868d75effSDimitry Andric if (width >= 0) { 225968d75effSDimitry Andric retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 226068d75effSDimitry Andric tmp_fmt, width, arg); 226168d75effSDimitry Andric } else { 226268d75effSDimitry Andric retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 226368d75effSDimitry Andric tmp_fmt, arg); 226468d75effSDimitry Andric } 226568d75effSDimitry Andric free(tmp_fmt); 226668d75effSDimitry Andric return retval; 226768d75effSDimitry Andric } 226868d75effSDimitry Andric 226968d75effSDimitry Andric char *build_format_string() { 227068d75effSDimitry Andric size_t fmt_size = fmt_cur - fmt_start + 1; 227168d75effSDimitry Andric char *new_fmt = (char *)malloc(fmt_size + 1); 227268d75effSDimitry Andric assert(new_fmt); 227368d75effSDimitry Andric internal_memcpy(new_fmt, fmt_start, fmt_size); 227468d75effSDimitry Andric new_fmt[fmt_size] = '\0'; 227568d75effSDimitry Andric return new_fmt; 227668d75effSDimitry Andric } 227768d75effSDimitry Andric 227868d75effSDimitry Andric char *str_cur() { return str + str_off; } 227968d75effSDimitry Andric 228068d75effSDimitry Andric size_t num_written_bytes(int retval) { 228168d75effSDimitry Andric if (retval < 0) { 228268d75effSDimitry Andric return 0; 228368d75effSDimitry Andric } 228468d75effSDimitry Andric 228568d75effSDimitry Andric size_t num_avail = str_off < size ? size - str_off : 0; 228668d75effSDimitry Andric if (num_avail == 0) { 228768d75effSDimitry Andric return 0; 228868d75effSDimitry Andric } 228968d75effSDimitry Andric 229068d75effSDimitry Andric size_t num_written = retval; 229168d75effSDimitry Andric // A return value of {v,}snprintf of size or more means that the output was 229268d75effSDimitry Andric // truncated. 229368d75effSDimitry Andric if (num_written >= num_avail) { 229468d75effSDimitry Andric num_written -= num_avail; 229568d75effSDimitry Andric } 229668d75effSDimitry Andric 229768d75effSDimitry Andric return num_written; 229868d75effSDimitry Andric } 229968d75effSDimitry Andric 230068d75effSDimitry Andric char *str; 230168d75effSDimitry Andric size_t str_off; 230268d75effSDimitry Andric size_t size; 230368d75effSDimitry Andric const char *fmt_start; 230468d75effSDimitry Andric const char *fmt_cur; 230568d75effSDimitry Andric int width; 230668d75effSDimitry Andric }; 230768d75effSDimitry Andric 230868d75effSDimitry Andric // Formats the input and propagates the input labels to the output. The output 230968d75effSDimitry Andric // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and 231068d75effSDimitry Andric // 'ap' are the format string and the list of arguments for formatting. Returns 231168d75effSDimitry Andric // the return value vsnprintf would return. 231268d75effSDimitry Andric // 231368d75effSDimitry Andric // The function tokenizes the format string in chunks representing either a 231468d75effSDimitry Andric // constant string or a single format directive (e.g., '%.3f') and formats each 231568d75effSDimitry Andric // chunk independently into the output string. This approach allows to figure 231668d75effSDimitry Andric // out which bytes of the output string depends on which argument and thus to 231768d75effSDimitry Andric // propagate labels more precisely. 231868d75effSDimitry Andric // 231968d75effSDimitry Andric // WARNING: This implementation does not support conversion specifiers with 232068d75effSDimitry Andric // positional arguments. 232168d75effSDimitry Andric static int format_buffer(char *str, size_t size, const char *fmt, 232268d75effSDimitry Andric dfsan_label *va_labels, dfsan_label *ret_label, 2323fe6060f1SDimitry Andric dfsan_origin *va_origins, dfsan_origin *ret_origin, 232468d75effSDimitry Andric va_list ap) { 232568d75effSDimitry Andric Formatter formatter(str, fmt, size); 232668d75effSDimitry Andric 232768d75effSDimitry Andric while (*formatter.fmt_cur) { 232868d75effSDimitry Andric formatter.fmt_start = formatter.fmt_cur; 232968d75effSDimitry Andric formatter.width = -1; 233068d75effSDimitry Andric int retval = 0; 233168d75effSDimitry Andric 233268d75effSDimitry Andric if (*formatter.fmt_cur != '%') { 233368d75effSDimitry Andric // Ordinary character. Consume all the characters until a '%' or the end 233468d75effSDimitry Andric // of the string. 233568d75effSDimitry Andric for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%'; 233668d75effSDimitry Andric ++formatter.fmt_cur) {} 233768d75effSDimitry Andric retval = formatter.format(); 233868d75effSDimitry Andric dfsan_set_label(0, formatter.str_cur(), 233968d75effSDimitry Andric formatter.num_written_bytes(retval)); 234068d75effSDimitry Andric } else { 234168d75effSDimitry Andric // Conversion directive. Consume all the characters until a conversion 234268d75effSDimitry Andric // specifier or the end of the string. 234368d75effSDimitry Andric bool end_fmt = false; 234468d75effSDimitry Andric for (; *formatter.fmt_cur && !end_fmt; ) { 234568d75effSDimitry Andric switch (*++formatter.fmt_cur) { 234668d75effSDimitry Andric case 'd': 234768d75effSDimitry Andric case 'i': 234868d75effSDimitry Andric case 'o': 234968d75effSDimitry Andric case 'u': 235068d75effSDimitry Andric case 'x': 235168d75effSDimitry Andric case 'X': 235268d75effSDimitry Andric switch (*(formatter.fmt_cur - 1)) { 235368d75effSDimitry Andric case 'h': 235468d75effSDimitry Andric // Also covers the 'hh' case (since the size of the arg is still 235568d75effSDimitry Andric // an int). 235668d75effSDimitry Andric retval = formatter.format(va_arg(ap, int)); 235768d75effSDimitry Andric break; 235868d75effSDimitry Andric case 'l': 235968d75effSDimitry Andric if (formatter.fmt_cur - formatter.fmt_start >= 2 && 236068d75effSDimitry Andric *(formatter.fmt_cur - 2) == 'l') { 236168d75effSDimitry Andric retval = formatter.format(va_arg(ap, long long int)); 236268d75effSDimitry Andric } else { 236368d75effSDimitry Andric retval = formatter.format(va_arg(ap, long int)); 236468d75effSDimitry Andric } 236568d75effSDimitry Andric break; 236668d75effSDimitry Andric case 'q': 236768d75effSDimitry Andric retval = formatter.format(va_arg(ap, long long int)); 236868d75effSDimitry Andric break; 236968d75effSDimitry Andric case 'j': 237068d75effSDimitry Andric retval = formatter.format(va_arg(ap, intmax_t)); 237168d75effSDimitry Andric break; 237268d75effSDimitry Andric case 'z': 237368d75effSDimitry Andric case 't': 237468d75effSDimitry Andric retval = formatter.format(va_arg(ap, size_t)); 237568d75effSDimitry Andric break; 237668d75effSDimitry Andric default: 237768d75effSDimitry Andric retval = formatter.format(va_arg(ap, int)); 237868d75effSDimitry Andric } 2379fe6060f1SDimitry Andric if (va_origins == nullptr) 238068d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(), 238168d75effSDimitry Andric formatter.num_written_bytes(retval)); 2382fe6060f1SDimitry Andric else 2383fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++, 2384fe6060f1SDimitry Andric formatter.str_cur(), 2385fe6060f1SDimitry Andric formatter.num_written_bytes(retval)); 238668d75effSDimitry Andric end_fmt = true; 238768d75effSDimitry Andric break; 238868d75effSDimitry Andric 238968d75effSDimitry Andric case 'a': 239068d75effSDimitry Andric case 'A': 239168d75effSDimitry Andric case 'e': 239268d75effSDimitry Andric case 'E': 239368d75effSDimitry Andric case 'f': 239468d75effSDimitry Andric case 'F': 239568d75effSDimitry Andric case 'g': 239668d75effSDimitry Andric case 'G': 239768d75effSDimitry Andric if (*(formatter.fmt_cur - 1) == 'L') { 239868d75effSDimitry Andric retval = formatter.format(va_arg(ap, long double)); 239968d75effSDimitry Andric } else { 240068d75effSDimitry Andric retval = formatter.format(va_arg(ap, double)); 240168d75effSDimitry Andric } 2402fe6060f1SDimitry Andric if (va_origins == nullptr) 240368d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(), 240468d75effSDimitry Andric formatter.num_written_bytes(retval)); 2405fe6060f1SDimitry Andric else 2406fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++, 2407fe6060f1SDimitry Andric formatter.str_cur(), 2408fe6060f1SDimitry Andric formatter.num_written_bytes(retval)); 240968d75effSDimitry Andric end_fmt = true; 241068d75effSDimitry Andric break; 241168d75effSDimitry Andric 241268d75effSDimitry Andric case 'c': 241368d75effSDimitry Andric retval = formatter.format(va_arg(ap, int)); 2414fe6060f1SDimitry Andric if (va_origins == nullptr) 241568d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(), 241668d75effSDimitry Andric formatter.num_written_bytes(retval)); 2417fe6060f1SDimitry Andric else 2418fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++, 2419fe6060f1SDimitry Andric formatter.str_cur(), 2420fe6060f1SDimitry Andric formatter.num_written_bytes(retval)); 242168d75effSDimitry Andric end_fmt = true; 242268d75effSDimitry Andric break; 242368d75effSDimitry Andric 242468d75effSDimitry Andric case 's': { 242568d75effSDimitry Andric char *arg = va_arg(ap, char *); 242668d75effSDimitry Andric retval = formatter.format(arg); 2427fe6060f1SDimitry Andric if (va_origins) { 2428fe6060f1SDimitry Andric va_origins++; 2429fe6060f1SDimitry Andric dfsan_mem_origin_transfer(formatter.str_cur(), arg, 2430fe6060f1SDimitry Andric formatter.num_written_bytes(retval)); 2431fe6060f1SDimitry Andric } 243268d75effSDimitry Andric va_labels++; 243304eeddc0SDimitry Andric dfsan_mem_shadow_transfer(formatter.str_cur(), arg, 243468d75effSDimitry Andric formatter.num_written_bytes(retval)); 243568d75effSDimitry Andric end_fmt = true; 243668d75effSDimitry Andric break; 243768d75effSDimitry Andric } 243868d75effSDimitry Andric 243968d75effSDimitry Andric case 'p': 244068d75effSDimitry Andric retval = formatter.format(va_arg(ap, void *)); 2441fe6060f1SDimitry Andric if (va_origins == nullptr) 244268d75effSDimitry Andric dfsan_set_label(*va_labels++, formatter.str_cur(), 244368d75effSDimitry Andric formatter.num_written_bytes(retval)); 2444fe6060f1SDimitry Andric else 2445fe6060f1SDimitry Andric dfsan_set_label_origin(*va_labels++, *va_origins++, 2446fe6060f1SDimitry Andric formatter.str_cur(), 2447fe6060f1SDimitry Andric formatter.num_written_bytes(retval)); 244868d75effSDimitry Andric end_fmt = true; 244968d75effSDimitry Andric break; 245068d75effSDimitry Andric 245168d75effSDimitry Andric case 'n': { 245268d75effSDimitry Andric int *ptr = va_arg(ap, int *); 245368d75effSDimitry Andric *ptr = (int)formatter.str_off; 245468d75effSDimitry Andric va_labels++; 2455fe6060f1SDimitry Andric if (va_origins) 2456fe6060f1SDimitry Andric va_origins++; 245768d75effSDimitry Andric dfsan_set_label(0, ptr, sizeof(ptr)); 245868d75effSDimitry Andric end_fmt = true; 245968d75effSDimitry Andric break; 246068d75effSDimitry Andric } 246168d75effSDimitry Andric 246268d75effSDimitry Andric case '%': 246368d75effSDimitry Andric retval = formatter.format(); 246468d75effSDimitry Andric dfsan_set_label(0, formatter.str_cur(), 246568d75effSDimitry Andric formatter.num_written_bytes(retval)); 246668d75effSDimitry Andric end_fmt = true; 246768d75effSDimitry Andric break; 246868d75effSDimitry Andric 246968d75effSDimitry Andric case '*': 247068d75effSDimitry Andric formatter.width = va_arg(ap, int); 247168d75effSDimitry Andric va_labels++; 2472fe6060f1SDimitry Andric if (va_origins) 2473fe6060f1SDimitry Andric va_origins++; 247468d75effSDimitry Andric break; 247568d75effSDimitry Andric 247668d75effSDimitry Andric default: 247768d75effSDimitry Andric break; 247868d75effSDimitry Andric } 247968d75effSDimitry Andric } 248068d75effSDimitry Andric } 248168d75effSDimitry Andric 248268d75effSDimitry Andric if (retval < 0) { 248368d75effSDimitry Andric return retval; 248468d75effSDimitry Andric } 248568d75effSDimitry Andric 248668d75effSDimitry Andric formatter.fmt_cur++; 248768d75effSDimitry Andric formatter.str_off += retval; 248868d75effSDimitry Andric } 248968d75effSDimitry Andric 249068d75effSDimitry Andric *ret_label = 0; 2491fe6060f1SDimitry Andric if (ret_origin) 2492fe6060f1SDimitry Andric *ret_origin = 0; 249368d75effSDimitry Andric 249468d75effSDimitry Andric // Number of bytes written in total. 249568d75effSDimitry Andric return formatter.str_off; 249668d75effSDimitry Andric } 249768d75effSDimitry Andric 249868d75effSDimitry Andric extern "C" { 249968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 250068d75effSDimitry Andric int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label, 250168d75effSDimitry Andric dfsan_label format_label, dfsan_label *va_labels, 250268d75effSDimitry Andric dfsan_label *ret_label, ...) { 250368d75effSDimitry Andric va_list ap; 250468d75effSDimitry Andric va_start(ap, ret_label); 2505fe6060f1SDimitry Andric int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr, 2506fe6060f1SDimitry Andric nullptr, ap); 2507fe6060f1SDimitry Andric va_end(ap); 2508fe6060f1SDimitry Andric return ret; 2509fe6060f1SDimitry Andric } 2510fe6060f1SDimitry Andric 2511fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 2512fe6060f1SDimitry Andric int __dfso_sprintf(char *str, const char *format, dfsan_label str_label, 2513fe6060f1SDimitry Andric dfsan_label format_label, dfsan_label *va_labels, 2514fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin str_origin, 2515fe6060f1SDimitry Andric dfsan_origin format_origin, dfsan_origin *va_origins, 2516fe6060f1SDimitry Andric dfsan_origin *ret_origin, ...) { 2517fe6060f1SDimitry Andric va_list ap; 2518fe6060f1SDimitry Andric va_start(ap, ret_origin); 2519fe6060f1SDimitry Andric int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins, 2520fe6060f1SDimitry Andric ret_origin, ap); 252168d75effSDimitry Andric va_end(ap); 252268d75effSDimitry Andric return ret; 252368d75effSDimitry Andric } 252468d75effSDimitry Andric 252568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 252668d75effSDimitry Andric int __dfsw_snprintf(char *str, size_t size, const char *format, 252768d75effSDimitry Andric dfsan_label str_label, dfsan_label size_label, 252868d75effSDimitry Andric dfsan_label format_label, dfsan_label *va_labels, 252968d75effSDimitry Andric dfsan_label *ret_label, ...) { 253068d75effSDimitry Andric va_list ap; 253168d75effSDimitry Andric va_start(ap, ret_label); 2532fe6060f1SDimitry Andric int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr, 2533fe6060f1SDimitry Andric nullptr, ap); 253468d75effSDimitry Andric va_end(ap); 253568d75effSDimitry Andric return ret; 253668d75effSDimitry Andric } 253768d75effSDimitry Andric 2538fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 2539fe6060f1SDimitry Andric int __dfso_snprintf(char *str, size_t size, const char *format, 2540fe6060f1SDimitry Andric dfsan_label str_label, dfsan_label size_label, 2541fe6060f1SDimitry Andric dfsan_label format_label, dfsan_label *va_labels, 2542fe6060f1SDimitry Andric dfsan_label *ret_label, dfsan_origin str_origin, 2543fe6060f1SDimitry Andric dfsan_origin size_origin, dfsan_origin format_origin, 2544fe6060f1SDimitry Andric dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) { 2545fe6060f1SDimitry Andric va_list ap; 2546fe6060f1SDimitry Andric va_start(ap, ret_origin); 2547fe6060f1SDimitry Andric int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins, 2548fe6060f1SDimitry Andric ret_origin, ap); 2549fe6060f1SDimitry Andric va_end(ap); 2550fe6060f1SDimitry Andric return ret; 2551fe6060f1SDimitry Andric } 2552fe6060f1SDimitry Andric 2553fe6060f1SDimitry Andric static void BeforeFork() { 2554fe6060f1SDimitry Andric StackDepotLockAll(); 2555fe6060f1SDimitry Andric GetChainedOriginDepot()->LockAll(); 2556fe6060f1SDimitry Andric } 2557fe6060f1SDimitry Andric 2558fe6060f1SDimitry Andric static void AfterFork() { 2559fe6060f1SDimitry Andric GetChainedOriginDepot()->UnlockAll(); 2560fe6060f1SDimitry Andric StackDepotUnlockAll(); 2561fe6060f1SDimitry Andric } 2562fe6060f1SDimitry Andric 2563fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 2564fe6060f1SDimitry Andric pid_t __dfsw_fork(dfsan_label *ret_label) { 2565fe6060f1SDimitry Andric pid_t pid = fork(); 2566fe6060f1SDimitry Andric *ret_label = 0; 2567fe6060f1SDimitry Andric return pid; 2568fe6060f1SDimitry Andric } 2569fe6060f1SDimitry Andric 2570fe6060f1SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 2571fe6060f1SDimitry Andric pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) { 2572fe6060f1SDimitry Andric BeforeFork(); 2573fe6060f1SDimitry Andric pid_t pid = __dfsw_fork(ret_label); 2574fe6060f1SDimitry Andric AfterFork(); 2575fe6060f1SDimitry Andric return pid; 2576fe6060f1SDimitry Andric } 2577fe6060f1SDimitry Andric 257868d75effSDimitry Andric // Default empty implementations (weak). Users should redefine them. 257968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {} 258068d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *, 258168d75effSDimitry Andric u32 *) {} 2582349cc55cSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg, 2583349cc55cSDimitry Andric const uptr *end) {} 258468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} 258568d75effSDimitry Andric 258668d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {} 258768d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {} 258868d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {} 258968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {} 259068d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {} 259168d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1, 259268d75effSDimitry Andric void) {} 259368d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2, 259468d75effSDimitry Andric void) {} 259568d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4, 259668d75effSDimitry Andric void) {} 259768d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8, 259868d75effSDimitry Andric void) {} 259968d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {} 260068d75effSDimitry Andric } // extern "C" 2601