1ec5ed66cSJianzhou Zhao //===-- dfsan_custom.cpp --------------------------------------------------===// 2a9aa8137SNico Weber // 3a9aa8137SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a9aa8137SNico Weber // See https://llvm.org/LICENSE.txt for license information. 5a9aa8137SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a9aa8137SNico Weber // 7a9aa8137SNico Weber //===----------------------------------------------------------------------===// 8a9aa8137SNico Weber // 9a9aa8137SNico Weber // This file is a part of DataFlowSanitizer. 10a9aa8137SNico Weber // 11a9aa8137SNico Weber // This file defines the custom functions listed in done_abilist.txt. 12a9aa8137SNico Weber //===----------------------------------------------------------------------===// 13a9aa8137SNico Weber 14a9aa8137SNico Weber #include <arpa/inet.h> 15a9aa8137SNico Weber #include <assert.h> 16a9aa8137SNico Weber #include <ctype.h> 17a9aa8137SNico Weber #include <dlfcn.h> 18a9aa8137SNico Weber #include <link.h> 19a9aa8137SNico Weber #include <poll.h> 20a9aa8137SNico Weber #include <pthread.h> 21a9aa8137SNico Weber #include <pwd.h> 22a9aa8137SNico Weber #include <sched.h> 23a9aa8137SNico Weber #include <signal.h> 24a9aa8137SNico Weber #include <stdarg.h> 25a9aa8137SNico Weber #include <stdint.h> 26a9aa8137SNico Weber #include <stdio.h> 27a9aa8137SNico Weber #include <stdlib.h> 28a9aa8137SNico Weber #include <string.h> 296f13445fSMatt Morehouse #include <sys/epoll.h> 30a9aa8137SNico Weber #include <sys/resource.h> 31a9aa8137SNico Weber #include <sys/select.h> 32a3eb2fb2SMatt Morehouse #include <sys/socket.h> 33a9aa8137SNico Weber #include <sys/stat.h> 34a9aa8137SNico Weber #include <sys/time.h> 35a9aa8137SNico Weber #include <sys/types.h> 36a9aa8137SNico Weber #include <time.h> 37a9aa8137SNico Weber #include <unistd.h> 38a9aa8137SNico Weber 396f13445fSMatt Morehouse #include "dfsan/dfsan.h" 404e67ae7bSJianzhou Zhao #include "dfsan/dfsan_chained_origin_depot.h" 4136cec26bSJianzhou Zhao #include "dfsan/dfsan_flags.h" 420f3fd3b2SJianzhou Zhao #include "dfsan/dfsan_thread.h" 436f13445fSMatt Morehouse #include "sanitizer_common/sanitizer_common.h" 446f13445fSMatt Morehouse #include "sanitizer_common/sanitizer_internal_defs.h" 456f13445fSMatt Morehouse #include "sanitizer_common/sanitizer_linux.h" 464e67ae7bSJianzhou Zhao #include "sanitizer_common/sanitizer_stackdepot.h" 476f13445fSMatt Morehouse 48a9aa8137SNico Weber using namespace __dfsan; 49a9aa8137SNico Weber 50a9aa8137SNico Weber #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \ 51a9aa8137SNico Weber do { \ 52a9aa8137SNico Weber if (f) \ 53a9aa8137SNico Weber f(__VA_ARGS__); \ 54a9aa8137SNico Weber } while (false) 55a9aa8137SNico Weber #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \ 56a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__); 57a9aa8137SNico Weber 5864856006SFangrui Song #define WRAPPER_ALIAS(fun, real) \ 5964856006SFangrui Song SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \ 6064856006SFangrui Song SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real); 6164856006SFangrui Song 62e1a4322fSJianzhou Zhao // Async-safe, non-reentrant spin lock. 6380eea015SFangrui Song namespace { 64e1a4322fSJianzhou Zhao class SignalSpinLocker { 65e1a4322fSJianzhou Zhao public: 66e1a4322fSJianzhou Zhao SignalSpinLocker() { 67e1a4322fSJianzhou Zhao sigset_t all_set; 68e1a4322fSJianzhou Zhao sigfillset(&all_set); 69e1a4322fSJianzhou Zhao pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_); 70e1a4322fSJianzhou Zhao sigactions_mu.Lock(); 71e1a4322fSJianzhou Zhao } 72e1a4322fSJianzhou Zhao ~SignalSpinLocker() { 73e1a4322fSJianzhou Zhao sigactions_mu.Unlock(); 74e1a4322fSJianzhou Zhao pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr); 75e1a4322fSJianzhou Zhao } 76e1a4322fSJianzhou Zhao 77e1a4322fSJianzhou Zhao private: 78e1a4322fSJianzhou Zhao static StaticSpinMutex sigactions_mu; 79e1a4322fSJianzhou Zhao sigset_t saved_thread_mask_; 80e1a4322fSJianzhou Zhao 81e1a4322fSJianzhou Zhao SignalSpinLocker(const SignalSpinLocker &) = delete; 82e1a4322fSJianzhou Zhao SignalSpinLocker &operator=(const SignalSpinLocker &) = delete; 83e1a4322fSJianzhou Zhao }; 8480eea015SFangrui Song } // namespace 85e1a4322fSJianzhou Zhao 86e1a4322fSJianzhou Zhao StaticSpinMutex SignalSpinLocker::sigactions_mu; 87e1a4322fSJianzhou Zhao 88a9aa8137SNico Weber extern "C" { 89a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int 90a9aa8137SNico Weber __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label, 91a9aa8137SNico Weber dfsan_label buf_label, dfsan_label *ret_label) { 92a9aa8137SNico Weber int ret = stat(path, buf); 93a9aa8137SNico Weber if (ret == 0) 94a9aa8137SNico Weber dfsan_set_label(0, buf, sizeof(struct stat)); 95a9aa8137SNico Weber *ret_label = 0; 96a9aa8137SNico Weber return ret; 97a9aa8137SNico Weber } 98a9aa8137SNico Weber 99ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat( 100ec5ed66cSJianzhou Zhao const char *path, struct stat *buf, dfsan_label path_label, 101ec5ed66cSJianzhou Zhao dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin, 102ec5ed66cSJianzhou Zhao dfsan_origin buf_origin, dfsan_origin *ret_origin) { 103ec5ed66cSJianzhou Zhao int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label); 104ec5ed66cSJianzhou Zhao return ret; 105ec5ed66cSJianzhou Zhao } 106ec5ed66cSJianzhou Zhao 107a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf, 108a9aa8137SNico Weber dfsan_label fd_label, 109a9aa8137SNico Weber dfsan_label buf_label, 110a9aa8137SNico Weber dfsan_label *ret_label) { 111a9aa8137SNico Weber int ret = fstat(fd, buf); 112a9aa8137SNico Weber if (ret == 0) 113a9aa8137SNico Weber dfsan_set_label(0, buf, sizeof(struct stat)); 114a9aa8137SNico Weber *ret_label = 0; 115a9aa8137SNico Weber return ret; 116a9aa8137SNico Weber } 117a9aa8137SNico Weber 118ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat( 119ec5ed66cSJianzhou Zhao int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label, 120ec5ed66cSJianzhou Zhao dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, 121ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 122ec5ed66cSJianzhou Zhao int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label); 123ec5ed66cSJianzhou Zhao return ret; 124ec5ed66cSJianzhou Zhao } 125ec5ed66cSJianzhou Zhao 126ec5ed66cSJianzhou Zhao static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read, 127ec5ed66cSJianzhou Zhao dfsan_label s_label, dfsan_label c_label, 128ec5ed66cSJianzhou Zhao dfsan_label *ret_label) { 129ec5ed66cSJianzhou Zhao char *match_pos = nullptr; 130ec5ed66cSJianzhou Zhao for (size_t i = 0;; ++i) { 131ec5ed66cSJianzhou Zhao if (s[i] == c || s[i] == 0) { 132ec5ed66cSJianzhou Zhao // If s[i] is the \0 at the end of the string, and \0 is not the 133ec5ed66cSJianzhou Zhao // character we are searching for, then return null. 134ec5ed66cSJianzhou Zhao *bytes_read = i + 1; 135ec5ed66cSJianzhou Zhao match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i); 136ec5ed66cSJianzhou Zhao break; 137ec5ed66cSJianzhou Zhao } 138ec5ed66cSJianzhou Zhao } 139ec5ed66cSJianzhou Zhao if (flags().strict_data_dependencies) 140ec5ed66cSJianzhou Zhao *ret_label = s_label; 141ec5ed66cSJianzhou Zhao else 142ec5ed66cSJianzhou Zhao *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read), 143ec5ed66cSJianzhou Zhao dfsan_union(s_label, c_label)); 144ec5ed66cSJianzhou Zhao return match_pos; 145ec5ed66cSJianzhou Zhao } 146ec5ed66cSJianzhou Zhao 147a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c, 148a9aa8137SNico Weber dfsan_label s_label, 149a9aa8137SNico Weber dfsan_label c_label, 150a9aa8137SNico Weber dfsan_label *ret_label) { 151ec5ed66cSJianzhou Zhao size_t bytes_read; 152ec5ed66cSJianzhou Zhao return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, 153ec5ed66cSJianzhou Zhao ret_label); 154a9aa8137SNico Weber } 15510070e31SSam Kerner 156ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr( 157ec5ed66cSJianzhou Zhao const char *s, int c, dfsan_label s_label, dfsan_label c_label, 158ec5ed66cSJianzhou Zhao dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin, 159ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 160ec5ed66cSJianzhou Zhao size_t bytes_read; 161ec5ed66cSJianzhou Zhao char *r = 162ec5ed66cSJianzhou Zhao dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label); 163ec5ed66cSJianzhou Zhao if (flags().strict_data_dependencies) { 164ec5ed66cSJianzhou Zhao *ret_origin = s_origin; 165ec5ed66cSJianzhou Zhao } else if (*ret_label) { 166ec5ed66cSJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read); 167ec5ed66cSJianzhou Zhao *ret_origin = o ? o : (s_label ? s_origin : c_origin); 16810070e31SSam Kerner } 169ec5ed66cSJianzhou Zhao return r; 170a9aa8137SNico Weber } 171a9aa8137SNico Weber 17223bab1ebSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s, 17323bab1ebSMatt Morehouse const char *accept, 17423bab1ebSMatt Morehouse dfsan_label s_label, 17523bab1ebSMatt Morehouse dfsan_label accept_label, 17623bab1ebSMatt Morehouse dfsan_label *ret_label) { 17723bab1ebSMatt Morehouse const char *ret = strpbrk(s, accept); 17823bab1ebSMatt Morehouse if (flags().strict_data_dependencies) { 17923bab1ebSMatt Morehouse *ret_label = ret ? s_label : 0; 18023bab1ebSMatt Morehouse } else { 18123bab1ebSMatt Morehouse size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1; 18223bab1ebSMatt Morehouse *ret_label = 18323bab1ebSMatt Morehouse dfsan_union(dfsan_read_label(s, s_bytes_read), 18423bab1ebSMatt Morehouse dfsan_union(dfsan_read_label(accept, strlen(accept) + 1), 18523bab1ebSMatt Morehouse dfsan_union(s_label, accept_label))); 18623bab1ebSMatt Morehouse } 18723bab1ebSMatt Morehouse return const_cast<char *>(ret); 18823bab1ebSMatt Morehouse } 18923bab1ebSMatt Morehouse 190ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk( 191ec5ed66cSJianzhou Zhao const char *s, const char *accept, dfsan_label s_label, 192ec5ed66cSJianzhou Zhao dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin, 193ec5ed66cSJianzhou Zhao dfsan_origin accept_origin, dfsan_origin *ret_origin) { 194ec5ed66cSJianzhou Zhao const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label); 195ec5ed66cSJianzhou Zhao if (flags().strict_data_dependencies) { 196ec5ed66cSJianzhou Zhao if (ret) 197ec5ed66cSJianzhou Zhao *ret_origin = s_origin; 198ec5ed66cSJianzhou Zhao } else { 199ec5ed66cSJianzhou Zhao if (*ret_label) { 200ec5ed66cSJianzhou Zhao size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1; 201ec5ed66cSJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read); 202ec5ed66cSJianzhou Zhao if (o) { 203ec5ed66cSJianzhou Zhao *ret_origin = o; 204ec5ed66cSJianzhou Zhao } else { 205ec5ed66cSJianzhou Zhao o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1); 206ec5ed66cSJianzhou Zhao *ret_origin = o ? o : (s_label ? s_origin : accept_origin); 207ec5ed66cSJianzhou Zhao } 208ec5ed66cSJianzhou Zhao } 209ec5ed66cSJianzhou Zhao } 210ec5ed66cSJianzhou Zhao return const_cast<char *>(ret); 211ec5ed66cSJianzhou Zhao } 212ec5ed66cSJianzhou Zhao 21374f00516STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim, 21474f00516STomasz Kuchta dfsan_label s_label, 21574f00516STomasz Kuchta dfsan_label delim_label, 21674f00516STomasz Kuchta dfsan_label *ret_label) { 21774f00516STomasz Kuchta dfsan_label base_label = dfsan_read_label(s, sizeof(*s)); 21874f00516STomasz Kuchta char *base = *s; 21974f00516STomasz Kuchta char *res = strsep(s, delim); 22074f00516STomasz Kuchta if (res != *s) { 22174f00516STomasz Kuchta char *token_start = res; 22274f00516STomasz Kuchta int token_length = strlen(res); 22374f00516STomasz Kuchta // the delimiter byte has been set to NULL 22474f00516STomasz Kuchta dfsan_set_label(0, token_start + token_length, 1); 22574f00516STomasz Kuchta } 22674f00516STomasz Kuchta 22774f00516STomasz Kuchta if (flags().strict_data_dependencies) { 22874f00516STomasz Kuchta *ret_label = res ? base_label : 0; 22974f00516STomasz Kuchta } else { 23074f00516STomasz Kuchta size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1; 23174f00516STomasz Kuchta *ret_label = dfsan_union( 23274f00516STomasz Kuchta dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))), 23374f00516STomasz Kuchta dfsan_union(dfsan_read_label(delim, strlen(delim) + 1), 23474f00516STomasz Kuchta dfsan_union(s_label, delim_label))); 23574f00516STomasz Kuchta } 23674f00516STomasz Kuchta 23774f00516STomasz Kuchta return res; 23874f00516STomasz Kuchta } 23974f00516STomasz Kuchta 24074f00516STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep( 24174f00516STomasz Kuchta char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label, 24274f00516STomasz Kuchta dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin, 24374f00516STomasz Kuchta dfsan_origin *ret_origin) { 24474f00516STomasz Kuchta dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s)); 24574f00516STomasz Kuchta char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label); 24674f00516STomasz Kuchta if (flags().strict_data_dependencies) { 24774f00516STomasz Kuchta if (res) 24874f00516STomasz Kuchta *ret_origin = base_origin; 24974f00516STomasz Kuchta } else { 25074f00516STomasz Kuchta if (*ret_label) { 25174f00516STomasz Kuchta if (base_origin) { 25274f00516STomasz Kuchta *ret_origin = base_origin; 25374f00516STomasz Kuchta } else { 25474f00516STomasz Kuchta dfsan_origin o = 25574f00516STomasz Kuchta dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1); 25674f00516STomasz Kuchta *ret_origin = o ? o : (s_label ? s_origin : delim_origin); 25774f00516STomasz Kuchta } 25874f00516STomasz Kuchta } 25974f00516STomasz Kuchta } 26074f00516STomasz Kuchta 26174f00516STomasz Kuchta return res; 26274f00516STomasz Kuchta } 26374f00516STomasz Kuchta 26450dd545bSMatt Morehouse static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n, 265ec5ed66cSJianzhou Zhao size_t *bytes_read) { 266a9aa8137SNico Weber const char *cs1 = (const char *) s1, *cs2 = (const char *) s2; 267a9aa8137SNico Weber for (size_t i = 0; i != n; ++i) { 268a9aa8137SNico Weber if (cs1[i] != cs2[i]) { 269ec5ed66cSJianzhou Zhao *bytes_read = i + 1; 270a9aa8137SNico Weber return cs1[i] - cs2[i]; 271a9aa8137SNico Weber } 272a9aa8137SNico Weber } 273ec5ed66cSJianzhou Zhao *bytes_read = n; 274a9aa8137SNico Weber return 0; 275a9aa8137SNico Weber } 276a9aa8137SNico Weber 277ec5ed66cSJianzhou Zhao static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2, 278ec5ed66cSJianzhou Zhao size_t pos) { 279ec5ed66cSJianzhou Zhao if (flags().strict_data_dependencies) 280ec5ed66cSJianzhou Zhao return 0; 281ec5ed66cSJianzhou Zhao return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos)); 282ec5ed66cSJianzhou Zhao } 283ec5ed66cSJianzhou Zhao 284ec5ed66cSJianzhou Zhao static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos, 285ec5ed66cSJianzhou Zhao dfsan_label *ret_label, 286ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 287ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, pos); 288ec5ed66cSJianzhou Zhao if (*ret_label == 0) 289ec5ed66cSJianzhou Zhao return; 290ec5ed66cSJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos); 291ec5ed66cSJianzhou Zhao *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos); 292ec5ed66cSJianzhou Zhao } 293ec5ed66cSJianzhou Zhao 294ec5ed66cSJianzhou Zhao static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n, 295ec5ed66cSJianzhou Zhao dfsan_label *ret_label) { 296ec5ed66cSJianzhou Zhao size_t bytes_read; 297ec5ed66cSJianzhou Zhao int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read); 298ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 299ec5ed66cSJianzhou Zhao return r; 300ec5ed66cSJianzhou Zhao } 301ec5ed66cSJianzhou Zhao 302ec5ed66cSJianzhou Zhao static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n, 303ec5ed66cSJianzhou Zhao dfsan_label *ret_label, 304ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 305ec5ed66cSJianzhou Zhao size_t bytes_read; 306ec5ed66cSJianzhou Zhao int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read); 307ec5ed66cSJianzhou Zhao dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 308ec5ed66cSJianzhou Zhao return r; 309ec5ed66cSJianzhou Zhao } 310ec5ed66cSJianzhou Zhao 31150dd545bSMatt Morehouse DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc, 31250dd545bSMatt Morehouse const void *s1, const void *s2, size_t n, 31350dd545bSMatt Morehouse dfsan_label s1_label, dfsan_label s2_label, 31450dd545bSMatt Morehouse dfsan_label n_label) 31550dd545bSMatt Morehouse 316ec5ed66cSJianzhou Zhao DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc, 317ec5ed66cSJianzhou Zhao const void *s1, const void *s2, size_t n, 318ec5ed66cSJianzhou Zhao dfsan_label s1_label, dfsan_label s2_label, 319ec5ed66cSJianzhou Zhao dfsan_label n_label, dfsan_origin s1_origin, 320ec5ed66cSJianzhou Zhao dfsan_origin s2_origin, dfsan_origin n_origin) 321ec5ed66cSJianzhou Zhao 32250dd545bSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2, 32350dd545bSMatt Morehouse size_t n, dfsan_label s1_label, 32450dd545bSMatt Morehouse dfsan_label s2_label, 32550dd545bSMatt Morehouse dfsan_label n_label, 32650dd545bSMatt Morehouse dfsan_label *ret_label) { 32750dd545bSMatt Morehouse CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n, 32850dd545bSMatt Morehouse s1_label, s2_label, n_label); 329ec5ed66cSJianzhou Zhao return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label); 330ec5ed66cSJianzhou Zhao } 331ec5ed66cSJianzhou Zhao 332ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp( 333ec5ed66cSJianzhou Zhao const void *s1, const void *s2, size_t n, dfsan_label s1_label, 334ec5ed66cSJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 335ec5ed66cSJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 336ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 337ec5ed66cSJianzhou Zhao CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1, 338ec5ed66cSJianzhou Zhao s2, n, s1_label, s2_label, n_label, s1_origin, 339ec5ed66cSJianzhou Zhao s2_origin, n_origin); 340ec5ed66cSJianzhou Zhao return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin); 34150dd545bSMatt Morehouse } 34250dd545bSMatt Morehouse 34350dd545bSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2, 34450dd545bSMatt Morehouse size_t n, dfsan_label s1_label, 34550dd545bSMatt Morehouse dfsan_label s2_label, 34650dd545bSMatt Morehouse dfsan_label n_label, 34750dd545bSMatt Morehouse dfsan_label *ret_label) { 348ec5ed66cSJianzhou Zhao return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label); 349ec5ed66cSJianzhou Zhao } 350ec5ed66cSJianzhou Zhao 351ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp( 352ec5ed66cSJianzhou Zhao const void *s1, const void *s2, size_t n, dfsan_label s1_label, 353ec5ed66cSJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 354ec5ed66cSJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 355ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 356ec5ed66cSJianzhou Zhao return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin); 357ec5ed66cSJianzhou Zhao } 358ec5ed66cSJianzhou Zhao 359ec5ed66cSJianzhou Zhao // When n == 0, compare strings without byte limit. 360ec5ed66cSJianzhou Zhao // When n > 0, compare the first (at most) n bytes of s1 and s2. 361ec5ed66cSJianzhou Zhao static int dfsan_strncmp(const char *s1, const char *s2, size_t n, 362ec5ed66cSJianzhou Zhao size_t *bytes_read) { 363ec5ed66cSJianzhou Zhao for (size_t i = 0;; ++i) { 364ec5ed66cSJianzhou Zhao if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) { 365ec5ed66cSJianzhou Zhao *bytes_read = i + 1; 366ec5ed66cSJianzhou Zhao return s1[i] - s2[i]; 367ec5ed66cSJianzhou Zhao } 368ec5ed66cSJianzhou Zhao } 36950dd545bSMatt Morehouse } 37050dd545bSMatt Morehouse 371a9aa8137SNico Weber DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc, 372a9aa8137SNico Weber const char *s1, const char *s2, 373a9aa8137SNico Weber dfsan_label s1_label, dfsan_label s2_label) 374a9aa8137SNico Weber 375ec5ed66cSJianzhou Zhao DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc, 376ec5ed66cSJianzhou Zhao const char *s1, const char *s2, 377ec5ed66cSJianzhou Zhao dfsan_label s1_label, dfsan_label s2_label, 378ec5ed66cSJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin) 379ec5ed66cSJianzhou Zhao 380a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2, 381a9aa8137SNico Weber dfsan_label s1_label, 382a9aa8137SNico Weber dfsan_label s2_label, 383a9aa8137SNico Weber dfsan_label *ret_label) { 384a9aa8137SNico Weber CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2, 385a9aa8137SNico Weber s1_label, s2_label); 386ec5ed66cSJianzhou Zhao size_t bytes_read; 387ec5ed66cSJianzhou Zhao int r = dfsan_strncmp(s1, s2, 0, &bytes_read); 388ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 389ec5ed66cSJianzhou Zhao return r; 390a9aa8137SNico Weber } 391a9aa8137SNico Weber 392ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp( 393ec5ed66cSJianzhou Zhao const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label, 394ec5ed66cSJianzhou Zhao dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin, 395ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 396ec5ed66cSJianzhou Zhao CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1, 397ec5ed66cSJianzhou Zhao s2, s1_label, s2_label, s1_origin, s2_origin); 398ec5ed66cSJianzhou Zhao size_t bytes_read; 399ec5ed66cSJianzhou Zhao int r = dfsan_strncmp(s1, s2, 0, &bytes_read); 400ec5ed66cSJianzhou Zhao dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 401ec5ed66cSJianzhou Zhao return r; 402ec5ed66cSJianzhou Zhao } 403ec5ed66cSJianzhou Zhao 404ec5ed66cSJianzhou Zhao // When n == 0, compare strings without byte limit. 405ec5ed66cSJianzhou Zhao // When n > 0, compare the first (at most) n bytes of s1 and s2. 406ec5ed66cSJianzhou Zhao static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n, 407ec5ed66cSJianzhou Zhao size_t *bytes_read) { 408a9aa8137SNico Weber for (size_t i = 0;; ++i) { 409e5ce95c6SSam Kerner char s1_lower = tolower(s1[i]); 410e5ce95c6SSam Kerner char s2_lower = tolower(s2[i]); 411e5ce95c6SSam Kerner 412ec5ed66cSJianzhou Zhao if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 || 413ec5ed66cSJianzhou Zhao (n > 0 && i == n - 1)) { 414ec5ed66cSJianzhou Zhao *bytes_read = i + 1; 415e5ce95c6SSam Kerner return s1_lower - s2_lower; 416a9aa8137SNico Weber } 417a9aa8137SNico Weber } 418ec5ed66cSJianzhou Zhao } 419ec5ed66cSJianzhou Zhao 420ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1, 421ec5ed66cSJianzhou Zhao const char *s2, 422ec5ed66cSJianzhou Zhao dfsan_label s1_label, 423ec5ed66cSJianzhou Zhao dfsan_label s2_label, 424ec5ed66cSJianzhou Zhao dfsan_label *ret_label) { 425ec5ed66cSJianzhou Zhao size_t bytes_read; 426ec5ed66cSJianzhou Zhao int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read); 427ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 428ec5ed66cSJianzhou Zhao return r; 429ec5ed66cSJianzhou Zhao } 430ec5ed66cSJianzhou Zhao 431ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp( 432ec5ed66cSJianzhou Zhao const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label, 433ec5ed66cSJianzhou Zhao dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin, 434ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 435ec5ed66cSJianzhou Zhao size_t bytes_read; 436ec5ed66cSJianzhou Zhao int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read); 437ec5ed66cSJianzhou Zhao dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 438ec5ed66cSJianzhou Zhao return r; 439a9aa8137SNico Weber } 440a9aa8137SNico Weber 441a9aa8137SNico Weber DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc, 442a9aa8137SNico Weber const char *s1, const char *s2, size_t n, 443a9aa8137SNico Weber dfsan_label s1_label, dfsan_label s2_label, 444a9aa8137SNico Weber dfsan_label n_label) 445a9aa8137SNico Weber 446ec5ed66cSJianzhou Zhao DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc, 447ec5ed66cSJianzhou Zhao const char *s1, const char *s2, size_t n, 448ec5ed66cSJianzhou Zhao dfsan_label s1_label, dfsan_label s2_label, 449ec5ed66cSJianzhou Zhao dfsan_label n_label, dfsan_origin s1_origin, 450ec5ed66cSJianzhou Zhao dfsan_origin s2_origin, dfsan_origin n_origin) 451ec5ed66cSJianzhou Zhao 452a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2, 453a9aa8137SNico Weber size_t n, dfsan_label s1_label, 454a9aa8137SNico Weber dfsan_label s2_label, 455a9aa8137SNico Weber dfsan_label n_label, 456a9aa8137SNico Weber dfsan_label *ret_label) { 457a9aa8137SNico Weber if (n == 0) { 458a9aa8137SNico Weber *ret_label = 0; 459a9aa8137SNico Weber return 0; 460a9aa8137SNico Weber } 461a9aa8137SNico Weber 462a9aa8137SNico Weber CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2, 463a9aa8137SNico Weber n, s1_label, s2_label, n_label); 464a9aa8137SNico Weber 465ec5ed66cSJianzhou Zhao size_t bytes_read; 466ec5ed66cSJianzhou Zhao int r = dfsan_strncmp(s1, s2, n, &bytes_read); 467ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 468ec5ed66cSJianzhou Zhao return r; 469a9aa8137SNico Weber } 470a9aa8137SNico Weber 471ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp( 472ec5ed66cSJianzhou Zhao const char *s1, const char *s2, size_t n, dfsan_label s1_label, 473ec5ed66cSJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 474ec5ed66cSJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 475ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 476a9aa8137SNico Weber if (n == 0) { 477a9aa8137SNico Weber *ret_label = 0; 478a9aa8137SNico Weber return 0; 479a9aa8137SNico Weber } 480a9aa8137SNico Weber 481ec5ed66cSJianzhou Zhao CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(), 482ec5ed66cSJianzhou Zhao s1, s2, n, s1_label, s2_label, n_label, s1_origin, 483ec5ed66cSJianzhou Zhao s2_origin, n_origin); 484e5ce95c6SSam Kerner 485ec5ed66cSJianzhou Zhao size_t bytes_read; 486ec5ed66cSJianzhou Zhao int r = dfsan_strncmp(s1, s2, n, &bytes_read); 487ec5ed66cSJianzhou Zhao dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 488ec5ed66cSJianzhou Zhao return r; 489ec5ed66cSJianzhou Zhao } 490ec5ed66cSJianzhou Zhao 491ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp( 492ec5ed66cSJianzhou Zhao const char *s1, const char *s2, size_t n, dfsan_label s1_label, 493ec5ed66cSJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) { 494ec5ed66cSJianzhou Zhao if (n == 0) { 495a9aa8137SNico Weber *ret_label = 0; 496a9aa8137SNico Weber return 0; 497a9aa8137SNico Weber } 498a9aa8137SNico Weber 499ec5ed66cSJianzhou Zhao size_t bytes_read; 500ec5ed66cSJianzhou Zhao int r = dfsan_strncasecmp(s1, s2, n, &bytes_read); 501ec5ed66cSJianzhou Zhao *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read); 502ec5ed66cSJianzhou Zhao return r; 503ec5ed66cSJianzhou Zhao } 504ec5ed66cSJianzhou Zhao 505ec5ed66cSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp( 506ec5ed66cSJianzhou Zhao const char *s1, const char *s2, size_t n, dfsan_label s1_label, 507ec5ed66cSJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 508ec5ed66cSJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 509ec5ed66cSJianzhou Zhao dfsan_origin *ret_origin) { 510ec5ed66cSJianzhou Zhao if (n == 0) { 511ec5ed66cSJianzhou Zhao *ret_label = 0; 512ec5ed66cSJianzhou Zhao return 0; 513ec5ed66cSJianzhou Zhao } 514ec5ed66cSJianzhou Zhao 515ec5ed66cSJianzhou Zhao size_t bytes_read; 516ec5ed66cSJianzhou Zhao int r = dfsan_strncasecmp(s1, s2, n, &bytes_read); 517ec5ed66cSJianzhou Zhao dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin); 518ec5ed66cSJianzhou Zhao return r; 519ec5ed66cSJianzhou Zhao } 520ec5ed66cSJianzhou Zhao 5211fe04204SJianzhou Zhao 522a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE size_t 523a9aa8137SNico Weber __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 524a9aa8137SNico Weber size_t ret = strlen(s); 525a9aa8137SNico Weber if (flags().strict_data_dependencies) { 526a9aa8137SNico Weber *ret_label = 0; 527a9aa8137SNico Weber } else { 528a9aa8137SNico Weber *ret_label = dfsan_read_label(s, ret + 1); 529a9aa8137SNico Weber } 530a9aa8137SNico Weber return ret; 531a9aa8137SNico Weber } 532a9aa8137SNico Weber 5334e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s, 5344e67ae7bSJianzhou Zhao dfsan_label s_label, 5354e67ae7bSJianzhou Zhao dfsan_label *ret_label, 5364e67ae7bSJianzhou Zhao dfsan_origin s_origin, 5374e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 5384e67ae7bSJianzhou Zhao size_t ret = __dfsw_strlen(s, s_label, ret_label); 5394e67ae7bSJianzhou Zhao if (!flags().strict_data_dependencies) 5404e67ae7bSJianzhou Zhao *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1); 5414e67ae7bSJianzhou Zhao return ret; 5424e67ae7bSJianzhou Zhao } 5434e67ae7bSJianzhou Zhao 5445becf548STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s, 5455becf548STomasz Kuchta size_t maxlen, 5465becf548STomasz Kuchta dfsan_label s_label, 5475becf548STomasz Kuchta dfsan_label maxlen_label, 5485becf548STomasz Kuchta dfsan_label *ret_label) { 5495becf548STomasz Kuchta size_t ret = strnlen(s, maxlen); 5505becf548STomasz Kuchta if (flags().strict_data_dependencies) { 5515becf548STomasz Kuchta *ret_label = 0; 5525becf548STomasz Kuchta } else { 5535becf548STomasz Kuchta size_t full_len = strlen(s); 5545becf548STomasz Kuchta size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen; 5555becf548STomasz Kuchta *ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len)); 5565becf548STomasz Kuchta } 5575becf548STomasz Kuchta return ret; 5585becf548STomasz Kuchta } 5595becf548STomasz Kuchta 5605becf548STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen( 5615becf548STomasz Kuchta const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label, 5625becf548STomasz Kuchta dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin, 5635becf548STomasz Kuchta dfsan_origin *ret_origin) { 5645becf548STomasz Kuchta size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label); 5655becf548STomasz Kuchta if (!flags().strict_data_dependencies) { 5665becf548STomasz Kuchta size_t full_len = strlen(s); 5675becf548STomasz Kuchta size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen; 5685becf548STomasz Kuchta dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len); 5695becf548STomasz Kuchta *ret_origin = o ? o : maxlen_origin; 5705becf548STomasz Kuchta } 5715becf548STomasz Kuchta return ret; 5725becf548STomasz Kuchta } 5735becf548STomasz Kuchta 5743f568e1fSJianzhou Zhao static void *dfsan_memmove(void *dest, const void *src, size_t n) { 5753f568e1fSJianzhou Zhao dfsan_label *sdest = shadow_for(dest); 5763f568e1fSJianzhou Zhao const dfsan_label *ssrc = shadow_for(src); 5773f568e1fSJianzhou Zhao internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label)); 5783f568e1fSJianzhou Zhao return internal_memmove(dest, src, n); 5793f568e1fSJianzhou Zhao } 580a9aa8137SNico Weber 5811fe04204SJianzhou Zhao static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) { 5821fe04204SJianzhou Zhao dfsan_mem_origin_transfer(dest, src, n); 5831fe04204SJianzhou Zhao return dfsan_memmove(dest, src, n); 5841fe04204SJianzhou Zhao } 5851fe04204SJianzhou Zhao 586a9aa8137SNico Weber static void *dfsan_memcpy(void *dest, const void *src, size_t n) { 58732167bfeSAndrew Browne dfsan_mem_shadow_transfer(dest, src, n); 588a9aa8137SNico Weber return internal_memcpy(dest, src, n); 589a9aa8137SNico Weber } 590a9aa8137SNico Weber 5911fe04204SJianzhou Zhao static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) { 5921fe04204SJianzhou Zhao dfsan_mem_origin_transfer(dest, src, n); 5931fe04204SJianzhou Zhao return dfsan_memcpy(dest, src, n); 5941fe04204SJianzhou Zhao } 5951fe04204SJianzhou Zhao 596a9aa8137SNico Weber static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) { 597a9aa8137SNico Weber internal_memset(s, c, n); 598a9aa8137SNico Weber dfsan_set_label(c_label, s, n); 599a9aa8137SNico Weber } 600a9aa8137SNico Weber 6011fe04204SJianzhou Zhao static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label, 6021fe04204SJianzhou Zhao dfsan_origin c_origin, size_t n) { 6031fe04204SJianzhou Zhao internal_memset(s, c, n); 6041fe04204SJianzhou Zhao dfsan_set_label_origin(c_label, c_origin, s, n); 6051fe04204SJianzhou Zhao } 6061fe04204SJianzhou Zhao 607a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 608a9aa8137SNico Weber void *__dfsw_memcpy(void *dest, const void *src, size_t n, 609a9aa8137SNico Weber dfsan_label dest_label, dfsan_label src_label, 610a9aa8137SNico Weber dfsan_label n_label, dfsan_label *ret_label) { 611a9aa8137SNico Weber *ret_label = dest_label; 612a9aa8137SNico Weber return dfsan_memcpy(dest, src, n); 613a9aa8137SNico Weber } 614a9aa8137SNico Weber 615a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 6161fe04204SJianzhou Zhao void *__dfso_memcpy(void *dest, const void *src, size_t n, 6171fe04204SJianzhou Zhao dfsan_label dest_label, dfsan_label src_label, 6181fe04204SJianzhou Zhao dfsan_label n_label, dfsan_label *ret_label, 6191fe04204SJianzhou Zhao dfsan_origin dest_origin, dfsan_origin src_origin, 6201fe04204SJianzhou Zhao dfsan_origin n_origin, dfsan_origin *ret_origin) { 6211fe04204SJianzhou Zhao *ret_label = dest_label; 6221fe04204SJianzhou Zhao *ret_origin = dest_origin; 6231fe04204SJianzhou Zhao return dfsan_memcpy_with_origin(dest, src, n); 6241fe04204SJianzhou Zhao } 6251fe04204SJianzhou Zhao 6261fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 6273f568e1fSJianzhou Zhao void *__dfsw_memmove(void *dest, const void *src, size_t n, 6283f568e1fSJianzhou Zhao dfsan_label dest_label, dfsan_label src_label, 6293f568e1fSJianzhou Zhao dfsan_label n_label, dfsan_label *ret_label) { 6303f568e1fSJianzhou Zhao *ret_label = dest_label; 6313f568e1fSJianzhou Zhao return dfsan_memmove(dest, src, n); 6323f568e1fSJianzhou Zhao } 6333f568e1fSJianzhou Zhao 6343f568e1fSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 6351fe04204SJianzhou Zhao void *__dfso_memmove(void *dest, const void *src, size_t n, 6361fe04204SJianzhou Zhao dfsan_label dest_label, dfsan_label src_label, 6371fe04204SJianzhou Zhao dfsan_label n_label, dfsan_label *ret_label, 6381fe04204SJianzhou Zhao dfsan_origin dest_origin, dfsan_origin src_origin, 6391fe04204SJianzhou Zhao dfsan_origin n_origin, dfsan_origin *ret_origin) { 6401fe04204SJianzhou Zhao *ret_label = dest_label; 6411fe04204SJianzhou Zhao *ret_origin = dest_origin; 6421fe04204SJianzhou Zhao return dfsan_memmove_with_origin(dest, src, n); 6431fe04204SJianzhou Zhao } 6441fe04204SJianzhou Zhao 6451fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 646a9aa8137SNico Weber void *__dfsw_memset(void *s, int c, size_t n, 647a9aa8137SNico Weber dfsan_label s_label, dfsan_label c_label, 648a9aa8137SNico Weber dfsan_label n_label, dfsan_label *ret_label) { 649a9aa8137SNico Weber dfsan_memset(s, c, c_label, n); 650a9aa8137SNico Weber *ret_label = s_label; 651a9aa8137SNico Weber return s; 652a9aa8137SNico Weber } 653a9aa8137SNico Weber 6541fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 6551fe04204SJianzhou Zhao void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label, 6561fe04204SJianzhou Zhao dfsan_label c_label, dfsan_label n_label, 6571fe04204SJianzhou Zhao dfsan_label *ret_label, dfsan_origin s_origin, 6581fe04204SJianzhou Zhao dfsan_origin c_origin, dfsan_origin n_origin, 6591fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 6601fe04204SJianzhou Zhao dfsan_memset_with_origin(s, c, c_label, c_origin, n); 6611fe04204SJianzhou Zhao *ret_label = s_label; 6621fe04204SJianzhou Zhao *ret_origin = s_origin; 6631fe04204SJianzhou Zhao return s; 6641fe04204SJianzhou Zhao } 6651fe04204SJianzhou Zhao 66615f26c5fSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src, 66715f26c5fSJianzhou Zhao dfsan_label dest_label, 66815f26c5fSJianzhou Zhao dfsan_label src_label, 66915f26c5fSJianzhou Zhao dfsan_label *ret_label) { 67015f26c5fSJianzhou Zhao size_t dest_len = strlen(dest); 67144c83eccSVitaly Buka char *ret = strcat(dest, src); 67232167bfeSAndrew Browne dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src)); 67315f26c5fSJianzhou Zhao *ret_label = dest_label; 67415f26c5fSJianzhou Zhao return ret; 67515f26c5fSJianzhou Zhao } 67615f26c5fSJianzhou Zhao 6771fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat( 6781fe04204SJianzhou Zhao char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label, 6791fe04204SJianzhou Zhao dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin, 6801fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 6811fe04204SJianzhou Zhao size_t dest_len = strlen(dest); 68244c83eccSVitaly Buka char *ret = strcat(dest, src); 6831fe04204SJianzhou Zhao size_t src_len = strlen(src); 6841fe04204SJianzhou Zhao dfsan_mem_origin_transfer(dest + dest_len, src, src_len); 68532167bfeSAndrew Browne dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 6861fe04204SJianzhou Zhao *ret_label = dest_label; 6871fe04204SJianzhou Zhao *ret_origin = dest_origin; 6881fe04204SJianzhou Zhao return ret; 6891fe04204SJianzhou Zhao } 6901fe04204SJianzhou Zhao 691d9b36911STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat( 692d9b36911STomasz Kuchta char *dest, const char *src, size_t num, dfsan_label dest_label, 693d9b36911STomasz Kuchta dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) { 694d9b36911STomasz Kuchta size_t src_len = strlen(src); 695d9b36911STomasz Kuchta src_len = src_len < num ? src_len : num; 696d9b36911STomasz Kuchta size_t dest_len = strlen(dest); 697d9b36911STomasz Kuchta 698d9b36911STomasz Kuchta char *ret = strncat(dest, src, num); 699d9b36911STomasz Kuchta dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 700d9b36911STomasz Kuchta *ret_label = dest_label; 701d9b36911STomasz Kuchta return ret; 702d9b36911STomasz Kuchta } 703d9b36911STomasz Kuchta 704d9b36911STomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat( 705d9b36911STomasz Kuchta char *dest, const char *src, size_t num, dfsan_label dest_label, 706d9b36911STomasz Kuchta dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label, 707d9b36911STomasz Kuchta dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin, 708d9b36911STomasz Kuchta dfsan_origin *ret_origin) { 709d9b36911STomasz Kuchta size_t src_len = strlen(src); 710d9b36911STomasz Kuchta src_len = src_len < num ? src_len : num; 711d9b36911STomasz Kuchta size_t dest_len = strlen(dest); 712d9b36911STomasz Kuchta 713d9b36911STomasz Kuchta char *ret = strncat(dest, src, num); 714d9b36911STomasz Kuchta 715d9b36911STomasz Kuchta dfsan_mem_origin_transfer(dest + dest_len, src, src_len); 716d9b36911STomasz Kuchta dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); 717d9b36911STomasz Kuchta *ret_label = dest_label; 718d9b36911STomasz Kuchta *ret_origin = dest_origin; 719d9b36911STomasz Kuchta return ret; 720d9b36911STomasz Kuchta } 721d9b36911STomasz Kuchta 722a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE char * 723a9aa8137SNico Weber __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 724a9aa8137SNico Weber size_t len = strlen(s); 725a9aa8137SNico Weber void *p = malloc(len+1); 726a9aa8137SNico Weber dfsan_memcpy(p, s, len+1); 727a9aa8137SNico Weber *ret_label = 0; 728a9aa8137SNico Weber return static_cast<char *>(p); 729a9aa8137SNico Weber } 730a9aa8137SNico Weber 7311fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s, 7321fe04204SJianzhou Zhao dfsan_label s_label, 7331fe04204SJianzhou Zhao dfsan_label *ret_label, 7341fe04204SJianzhou Zhao dfsan_origin s_origin, 7351fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 7361fe04204SJianzhou Zhao size_t len = strlen(s); 7371fe04204SJianzhou Zhao void *p = malloc(len + 1); 7381fe04204SJianzhou Zhao dfsan_memcpy_with_origin(p, s, len + 1); 7391fe04204SJianzhou Zhao *ret_label = 0; 7401fe04204SJianzhou Zhao return static_cast<char *>(p); 7411fe04204SJianzhou Zhao } 7421fe04204SJianzhou Zhao 743a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE char * 744a9aa8137SNico Weber __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label, 745a9aa8137SNico Weber dfsan_label s2_label, dfsan_label n_label, 746a9aa8137SNico Weber dfsan_label *ret_label) { 747a9aa8137SNico Weber size_t len = strlen(s2); 748a9aa8137SNico Weber if (len < n) { 749a9aa8137SNico Weber dfsan_memcpy(s1, s2, len+1); 750a9aa8137SNico Weber dfsan_memset(s1+len+1, 0, 0, n-len-1); 751a9aa8137SNico Weber } else { 752a9aa8137SNico Weber dfsan_memcpy(s1, s2, n); 753a9aa8137SNico Weber } 754a9aa8137SNico Weber 755a9aa8137SNico Weber *ret_label = s1_label; 756a9aa8137SNico Weber return s1; 757a9aa8137SNico Weber } 758a9aa8137SNico Weber 7591fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy( 7601fe04204SJianzhou Zhao char *s1, const char *s2, size_t n, dfsan_label s1_label, 7611fe04204SJianzhou Zhao dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, 7621fe04204SJianzhou Zhao dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, 7631fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 7641fe04204SJianzhou Zhao size_t len = strlen(s2); 7651fe04204SJianzhou Zhao if (len < n) { 7661fe04204SJianzhou Zhao dfsan_memcpy_with_origin(s1, s2, len + 1); 7671fe04204SJianzhou Zhao dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1); 7681fe04204SJianzhou Zhao } else { 7691fe04204SJianzhou Zhao dfsan_memcpy_with_origin(s1, s2, n); 7701fe04204SJianzhou Zhao } 7711fe04204SJianzhou Zhao 7721fe04204SJianzhou Zhao *ret_label = s1_label; 7731fe04204SJianzhou Zhao *ret_origin = s1_origin; 7741fe04204SJianzhou Zhao return s1; 7751fe04204SJianzhou Zhao } 7761fe04204SJianzhou Zhao 777a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE ssize_t 778a9aa8137SNico Weber __dfsw_pread(int fd, void *buf, size_t count, off_t offset, 779a9aa8137SNico Weber dfsan_label fd_label, dfsan_label buf_label, 780a9aa8137SNico Weber dfsan_label count_label, dfsan_label offset_label, 781a9aa8137SNico Weber dfsan_label *ret_label) { 782a9aa8137SNico Weber ssize_t ret = pread(fd, buf, count, offset); 783a9aa8137SNico Weber if (ret > 0) 784a9aa8137SNico Weber dfsan_set_label(0, buf, ret); 785a9aa8137SNico Weber *ret_label = 0; 786a9aa8137SNico Weber return ret; 787a9aa8137SNico Weber } 788a9aa8137SNico Weber 7891fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread( 7901fe04204SJianzhou Zhao int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label, 7911fe04204SJianzhou Zhao dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label, 7921fe04204SJianzhou Zhao dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, 7931fe04204SJianzhou Zhao dfsan_origin count_origin, dfsan_label offset_origin, 7941fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 7954950695eSJianzhou Zhao return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label, 7964950695eSJianzhou Zhao offset_label, ret_label); 7971fe04204SJianzhou Zhao } 7981fe04204SJianzhou Zhao 799a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE ssize_t 800a9aa8137SNico Weber __dfsw_read(int fd, void *buf, size_t count, 801a9aa8137SNico Weber dfsan_label fd_label, dfsan_label buf_label, 802a9aa8137SNico Weber dfsan_label count_label, 803a9aa8137SNico Weber dfsan_label *ret_label) { 804a9aa8137SNico Weber ssize_t ret = read(fd, buf, count); 805a9aa8137SNico Weber if (ret > 0) 806a9aa8137SNico Weber dfsan_set_label(0, buf, ret); 807a9aa8137SNico Weber *ret_label = 0; 808a9aa8137SNico Weber return ret; 809a9aa8137SNico Weber } 810a9aa8137SNico Weber 8111fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read( 8121fe04204SJianzhou Zhao int fd, void *buf, size_t count, dfsan_label fd_label, 8131fe04204SJianzhou Zhao dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, 8141fe04204SJianzhou Zhao dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, 8151fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 8164950695eSJianzhou Zhao return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label, 8174950695eSJianzhou Zhao ret_label); 8181fe04204SJianzhou Zhao } 8191fe04204SJianzhou Zhao 820a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id, 821a9aa8137SNico Weber struct timespec *tp, 822a9aa8137SNico Weber dfsan_label clk_id_label, 823a9aa8137SNico Weber dfsan_label tp_label, 824a9aa8137SNico Weber dfsan_label *ret_label) { 825a9aa8137SNico Weber int ret = clock_gettime(clk_id, tp); 826a9aa8137SNico Weber if (ret == 0) 827a9aa8137SNico Weber dfsan_set_label(0, tp, sizeof(struct timespec)); 828a9aa8137SNico Weber *ret_label = 0; 829a9aa8137SNico Weber return ret; 830a9aa8137SNico Weber } 831a9aa8137SNico Weber 8321fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime( 8331fe04204SJianzhou Zhao clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label, 8341fe04204SJianzhou Zhao dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin, 8351fe04204SJianzhou Zhao dfsan_origin tp_origin, dfsan_origin *ret_origin) { 8364950695eSJianzhou Zhao return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label); 8371fe04204SJianzhou Zhao } 8381fe04204SJianzhou Zhao 8391fe04204SJianzhou Zhao static void dfsan_set_zero_label(const void *ptr, uptr size) { 840a9aa8137SNico Weber dfsan_set_label(0, const_cast<void *>(ptr), size); 841a9aa8137SNico Weber } 842a9aa8137SNico Weber 843a9aa8137SNico Weber // dlopen() ultimately calls mmap() down inside the loader, which generally 844a9aa8137SNico Weber // doesn't participate in dynamic symbol resolution. Therefore we won't 845a9aa8137SNico Weber // intercept its calls to mmap, and we have to hook it here. 846a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE void * 847a9aa8137SNico Weber __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label, 848a9aa8137SNico Weber dfsan_label flag_label, dfsan_label *ret_label) { 849a9aa8137SNico Weber void *handle = dlopen(filename, flag); 850a9aa8137SNico Weber link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle); 8518434e5d0SFangrui Song if (filename && map) 8521fe04204SJianzhou Zhao ForEachMappedRegion(map, dfsan_set_zero_label); 853a9aa8137SNico Weber *ret_label = 0; 854a9aa8137SNico Weber return handle; 855a9aa8137SNico Weber } 856a9aa8137SNico Weber 8571fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen( 8581fe04204SJianzhou Zhao const char *filename, int flag, dfsan_label filename_label, 8591fe04204SJianzhou Zhao dfsan_label flag_label, dfsan_label *ret_label, 8601fe04204SJianzhou Zhao dfsan_origin filename_origin, dfsan_origin flag_origin, 8611fe04204SJianzhou Zhao dfsan_origin *ret_origin) { 8624950695eSJianzhou Zhao return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label); 8631fe04204SJianzhou Zhao } 8641fe04204SJianzhou Zhao 8650f3fd3b2SJianzhou Zhao static void *DFsanThreadStartFunc(void *arg) { 8660f3fd3b2SJianzhou Zhao DFsanThread *t = (DFsanThread *)arg; 8670f3fd3b2SJianzhou Zhao SetCurrentThread(t); 86863886c21SVitaly Buka t->Init(); 869ffd9c123SVitaly Buka SetSigProcMask(&t->starting_sigset_, nullptr); 8700f3fd3b2SJianzhou Zhao return t->ThreadStart(); 8710f3fd3b2SJianzhou Zhao } 872a9aa8137SNico Weber 8730f3fd3b2SJianzhou Zhao static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, 8740f3fd3b2SJianzhou Zhao void *start_routine, void *arg, 8754e67ae7bSJianzhou Zhao dfsan_label *ret_label, 8764e67ae7bSJianzhou Zhao bool track_origins = false) { 8770f3fd3b2SJianzhou Zhao pthread_attr_t myattr; 8780f3fd3b2SJianzhou Zhao if (!attr) { 8790f3fd3b2SJianzhou Zhao pthread_attr_init(&myattr); 8800f3fd3b2SJianzhou Zhao attr = &myattr; 8810f3fd3b2SJianzhou Zhao } 8820f3fd3b2SJianzhou Zhao 8830f3fd3b2SJianzhou Zhao // Ensure that the thread stack is large enough to hold all TLS data. 8840f3fd3b2SJianzhou Zhao AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr))); 8850f3fd3b2SJianzhou Zhao 8864e67ae7bSJianzhou Zhao DFsanThread *t = 887dbf8c00bSAndrew Browne DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins); 888ffd9c123SVitaly Buka ScopedBlockSignals block(&t->starting_sigset_); 8890f3fd3b2SJianzhou Zhao int res = pthread_create(thread, attr, DFsanThreadStartFunc, t); 8900f3fd3b2SJianzhou Zhao 8910f3fd3b2SJianzhou Zhao if (attr == &myattr) 8920f3fd3b2SJianzhou Zhao pthread_attr_destroy(&myattr); 8930f3fd3b2SJianzhou Zhao *ret_label = 0; 8940f3fd3b2SJianzhou Zhao return res; 895a9aa8137SNico Weber } 896a9aa8137SNico Weber 897a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create( 898dbf8c00bSAndrew Browne pthread_t *thread, const pthread_attr_t *attr, void *start_routine, 899dbf8c00bSAndrew Browne void *arg, dfsan_label thread_label, dfsan_label attr_label, 900dbf8c00bSAndrew Browne dfsan_label start_routine_label, dfsan_label arg_label, 901dbf8c00bSAndrew Browne dfsan_label *ret_label) { 902dbf8c00bSAndrew Browne return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label); 903a9aa8137SNico Weber } 904a9aa8137SNico Weber 9054e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create( 906dbf8c00bSAndrew Browne pthread_t *thread, const pthread_attr_t *attr, void *start_routine, 907dbf8c00bSAndrew Browne void *arg, dfsan_label thread_label, dfsan_label attr_label, 908dbf8c00bSAndrew Browne dfsan_label start_routine_label, dfsan_label arg_label, 909dbf8c00bSAndrew Browne dfsan_label *ret_label, dfsan_origin thread_origin, 9104e67ae7bSJianzhou Zhao dfsan_origin attr_origin, dfsan_origin start_routine_origin, 9114e67ae7bSJianzhou Zhao dfsan_origin arg_origin, dfsan_origin *ret_origin) { 912dbf8c00bSAndrew Browne return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label, 913dbf8c00bSAndrew Browne true); 9144e67ae7bSJianzhou Zhao } 9154e67ae7bSJianzhou Zhao 91600993164SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread, 91700993164SMatt Morehouse void **retval, 91800993164SMatt Morehouse dfsan_label thread_label, 91900993164SMatt Morehouse dfsan_label retval_label, 92000993164SMatt Morehouse dfsan_label *ret_label) { 92100993164SMatt Morehouse int ret = pthread_join(thread, retval); 92200993164SMatt Morehouse if (ret == 0 && retval) 92300993164SMatt Morehouse dfsan_set_label(0, retval, sizeof(*retval)); 92400993164SMatt Morehouse *ret_label = 0; 92500993164SMatt Morehouse return ret; 92600993164SMatt Morehouse } 92700993164SMatt Morehouse 9284e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join( 9294e67ae7bSJianzhou Zhao pthread_t thread, void **retval, dfsan_label thread_label, 9304e67ae7bSJianzhou Zhao dfsan_label retval_label, dfsan_label *ret_label, 9314e67ae7bSJianzhou Zhao dfsan_origin thread_origin, dfsan_origin retval_origin, 9324e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 9334e67ae7bSJianzhou Zhao return __dfsw_pthread_join(thread, retval, thread_label, retval_label, 9344e67ae7bSJianzhou Zhao ret_label); 9354e67ae7bSJianzhou Zhao } 9364e67ae7bSJianzhou Zhao 937a9aa8137SNico Weber struct dl_iterate_phdr_info { 938dbf8c00bSAndrew Browne int (*callback)(struct dl_phdr_info *info, size_t size, void *data); 9391fe04204SJianzhou Zhao void *data; 9401fe04204SJianzhou Zhao }; 9411fe04204SJianzhou Zhao 942fe31363aSFangrui Song static int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, 943fe31363aSFangrui Song void *data) { 944a9aa8137SNico Weber dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data; 945a9aa8137SNico Weber dfsan_set_label(0, *info); 946a9aa8137SNico Weber dfsan_set_label(0, const_cast<char *>(info->dlpi_name), 947a9aa8137SNico Weber strlen(info->dlpi_name) + 1); 948a9aa8137SNico Weber dfsan_set_label( 949a9aa8137SNico Weber 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)), 950a9aa8137SNico Weber sizeof(*info->dlpi_phdr) * info->dlpi_phnum); 951a9aa8137SNico Weber 952dbf8c00bSAndrew Browne dfsan_clear_thread_local_state(); 953dbf8c00bSAndrew Browne return dipi->callback(info, size, dipi->data); 9541fe04204SJianzhou Zhao } 9551fe04204SJianzhou Zhao 956a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( 957dbf8c00bSAndrew Browne int (*callback)(struct dl_phdr_info *info, size_t size, void *data), 958dbf8c00bSAndrew Browne void *data, dfsan_label callback_label, dfsan_label data_label, 959dbf8c00bSAndrew Browne dfsan_label *ret_label) { 960dbf8c00bSAndrew Browne dl_iterate_phdr_info dipi = {callback, data}; 961a9aa8137SNico Weber *ret_label = 0; 962a9aa8137SNico Weber return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); 963a9aa8137SNico Weber } 964a9aa8137SNico Weber 9651fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr( 966dbf8c00bSAndrew Browne int (*callback)(struct dl_phdr_info *info, size_t size, void *data), 967dbf8c00bSAndrew Browne void *data, dfsan_label callback_label, dfsan_label data_label, 968dbf8c00bSAndrew Browne dfsan_label *ret_label, dfsan_origin callback_origin, 969dbf8c00bSAndrew Browne dfsan_origin data_origin, dfsan_origin *ret_origin) { 970dbf8c00bSAndrew Browne dl_iterate_phdr_info dipi = {callback, data}; 9711fe04204SJianzhou Zhao *ret_label = 0; 972dbf8c00bSAndrew Browne return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); 9731fe04204SJianzhou Zhao } 9741fe04204SJianzhou Zhao 97572fd47b9SMatt Morehouse // This function is only available for glibc 2.27 or newer. Mark it weak so 97672fd47b9SMatt Morehouse // linking succeeds with older glibcs. 97772fd47b9SMatt Morehouse SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep, 97872fd47b9SMatt Morehouse size_t *alignp); 97972fd47b9SMatt Morehouse 98072fd47b9SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info( 98172fd47b9SMatt Morehouse size_t *sizep, size_t *alignp, dfsan_label sizep_label, 98272fd47b9SMatt Morehouse dfsan_label alignp_label) { 98372fd47b9SMatt Morehouse assert(_dl_get_tls_static_info); 98472fd47b9SMatt Morehouse _dl_get_tls_static_info(sizep, alignp); 98572fd47b9SMatt Morehouse dfsan_set_label(0, sizep, sizeof(*sizep)); 98672fd47b9SMatt Morehouse dfsan_set_label(0, alignp, sizeof(*alignp)); 98772fd47b9SMatt Morehouse } 98872fd47b9SMatt Morehouse 9891fe04204SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info( 9901fe04204SJianzhou Zhao size_t *sizep, size_t *alignp, dfsan_label sizep_label, 9911fe04204SJianzhou Zhao dfsan_label alignp_label, dfsan_origin sizep_origin, 9921fe04204SJianzhou Zhao dfsan_origin alignp_origin) { 9931fe04204SJianzhou Zhao __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label); 9941fe04204SJianzhou Zhao } 9951fe04204SJianzhou Zhao 996a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 997a9aa8137SNico Weber char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, 998a9aa8137SNico Weber dfsan_label buf_label, dfsan_label *ret_label) { 999a9aa8137SNico Weber char *ret = ctime_r(timep, buf); 1000a9aa8137SNico Weber if (ret) { 1001a9aa8137SNico Weber dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf, 1002a9aa8137SNico Weber strlen(buf) + 1); 1003a9aa8137SNico Weber *ret_label = buf_label; 1004a9aa8137SNico Weber } else { 1005a9aa8137SNico Weber *ret_label = 0; 1006a9aa8137SNico Weber } 1007a9aa8137SNico Weber return ret; 1008a9aa8137SNico Weber } 1009a9aa8137SNico Weber 1010a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 10114950695eSJianzhou Zhao char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, 10124950695eSJianzhou Zhao dfsan_label buf_label, dfsan_label *ret_label, 10134950695eSJianzhou Zhao dfsan_origin timep_origin, dfsan_origin buf_origin, 10144950695eSJianzhou Zhao dfsan_origin *ret_origin) { 10154950695eSJianzhou Zhao char *ret = ctime_r(timep, buf); 10164950695eSJianzhou Zhao if (ret) { 10174950695eSJianzhou Zhao dfsan_set_label_origin( 10184950695eSJianzhou Zhao dfsan_read_label(timep, sizeof(time_t)), 10194950695eSJianzhou Zhao dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf, 10204950695eSJianzhou Zhao strlen(buf) + 1); 10214950695eSJianzhou Zhao *ret_label = buf_label; 10224950695eSJianzhou Zhao *ret_origin = buf_origin; 10234950695eSJianzhou Zhao } else { 10244950695eSJianzhou Zhao *ret_label = 0; 10254950695eSJianzhou Zhao } 10264950695eSJianzhou Zhao return ret; 10274950695eSJianzhou Zhao } 10284950695eSJianzhou Zhao 10294950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1030a9aa8137SNico Weber char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label, 1031a9aa8137SNico Weber dfsan_label size_label, dfsan_label stream_label, 1032a9aa8137SNico Weber dfsan_label *ret_label) { 1033a9aa8137SNico Weber char *ret = fgets(s, size, stream); 1034a9aa8137SNico Weber if (ret) { 1035a9aa8137SNico Weber dfsan_set_label(0, ret, strlen(ret) + 1); 1036a9aa8137SNico Weber *ret_label = s_label; 1037a9aa8137SNico Weber } else { 1038a9aa8137SNico Weber *ret_label = 0; 1039a9aa8137SNico Weber } 1040a9aa8137SNico Weber return ret; 1041a9aa8137SNico Weber } 1042a9aa8137SNico Weber 1043a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 10444950695eSJianzhou Zhao char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label, 10454950695eSJianzhou Zhao dfsan_label size_label, dfsan_label stream_label, 10464950695eSJianzhou Zhao dfsan_label *ret_label, dfsan_origin s_origin, 10474950695eSJianzhou Zhao dfsan_origin size_origin, dfsan_origin stream_origin, 10484950695eSJianzhou Zhao dfsan_origin *ret_origin) { 10494950695eSJianzhou Zhao char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label, 10504950695eSJianzhou Zhao ret_label); 10514950695eSJianzhou Zhao if (ret) 10524950695eSJianzhou Zhao *ret_origin = s_origin; 10534950695eSJianzhou Zhao return ret; 10544950695eSJianzhou Zhao } 10554950695eSJianzhou Zhao 10564950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1057a9aa8137SNico Weber char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label, 1058a9aa8137SNico Weber dfsan_label size_label, dfsan_label *ret_label) { 1059a9aa8137SNico Weber char *ret = getcwd(buf, size); 1060a9aa8137SNico Weber if (ret) { 1061a9aa8137SNico Weber dfsan_set_label(0, ret, strlen(ret) + 1); 1062a9aa8137SNico Weber *ret_label = buf_label; 1063a9aa8137SNico Weber } else { 1064a9aa8137SNico Weber *ret_label = 0; 1065a9aa8137SNico Weber } 1066a9aa8137SNico Weber return ret; 1067a9aa8137SNico Weber } 1068a9aa8137SNico Weber 1069a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 10704950695eSJianzhou Zhao char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label, 10714950695eSJianzhou Zhao dfsan_label size_label, dfsan_label *ret_label, 10724950695eSJianzhou Zhao dfsan_origin buf_origin, dfsan_origin size_origin, 10734950695eSJianzhou Zhao dfsan_origin *ret_origin) { 10744950695eSJianzhou Zhao char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label); 10754950695eSJianzhou Zhao if (ret) 10764950695eSJianzhou Zhao *ret_origin = buf_origin; 10774950695eSJianzhou Zhao return ret; 10784950695eSJianzhou Zhao } 10794950695eSJianzhou Zhao 10804950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1081a9aa8137SNico Weber char *__dfsw_get_current_dir_name(dfsan_label *ret_label) { 1082a9aa8137SNico Weber char *ret = get_current_dir_name(); 10834950695eSJianzhou Zhao if (ret) 1084a9aa8137SNico Weber dfsan_set_label(0, ret, strlen(ret) + 1); 1085a9aa8137SNico Weber *ret_label = 0; 1086a9aa8137SNico Weber return ret; 1087a9aa8137SNico Weber } 1088a9aa8137SNico Weber 1089a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 10904950695eSJianzhou Zhao char *__dfso_get_current_dir_name(dfsan_label *ret_label, 10914950695eSJianzhou Zhao dfsan_origin *ret_origin) { 10924950695eSJianzhou Zhao return __dfsw_get_current_dir_name(ret_label); 10934950695eSJianzhou Zhao } 10944950695eSJianzhou Zhao 109576777b21SAndrew Browne // This function is only available for glibc 2.25 or newer. Mark it weak so 109676777b21SAndrew Browne // linking succeeds with older glibcs. 109776777b21SAndrew Browne SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length); 109876777b21SAndrew Browne 109976777b21SAndrew Browne SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length, 110076777b21SAndrew Browne dfsan_label buffer_label, 110176777b21SAndrew Browne dfsan_label length_label, 110276777b21SAndrew Browne dfsan_label *ret_label) { 110376777b21SAndrew Browne int ret = getentropy(buffer, length); 110476777b21SAndrew Browne if (ret == 0) { 110576777b21SAndrew Browne dfsan_set_label(0, buffer, length); 110676777b21SAndrew Browne } 110776777b21SAndrew Browne *ret_label = 0; 110876777b21SAndrew Browne return ret; 110976777b21SAndrew Browne } 111076777b21SAndrew Browne 111176777b21SAndrew Browne SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length, 111276777b21SAndrew Browne dfsan_label buffer_label, 111376777b21SAndrew Browne dfsan_label length_label, 111476777b21SAndrew Browne dfsan_label *ret_label, 111576777b21SAndrew Browne dfsan_origin buffer_origin, 111676777b21SAndrew Browne dfsan_origin length_origin, 111776777b21SAndrew Browne dfsan_origin *ret_origin) { 111876777b21SAndrew Browne return __dfsw_getentropy(buffer, length, buffer_label, length_label, 111976777b21SAndrew Browne ret_label); 112076777b21SAndrew Browne } 112176777b21SAndrew Browne 11224950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1123a9aa8137SNico Weber int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label, 1124a9aa8137SNico Weber dfsan_label len_label, dfsan_label *ret_label) { 1125a9aa8137SNico Weber int ret = gethostname(name, len); 1126a9aa8137SNico Weber if (ret == 0) { 1127a9aa8137SNico Weber dfsan_set_label(0, name, strlen(name) + 1); 1128a9aa8137SNico Weber } 1129a9aa8137SNico Weber *ret_label = 0; 1130a9aa8137SNico Weber return ret; 1131a9aa8137SNico Weber } 1132a9aa8137SNico Weber 1133a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 11344950695eSJianzhou Zhao int __dfso_gethostname(char *name, size_t len, dfsan_label name_label, 11354950695eSJianzhou Zhao dfsan_label len_label, dfsan_label *ret_label, 11364950695eSJianzhou Zhao dfsan_origin name_origin, dfsan_origin len_origin, 11374950695eSJianzhou Zhao dfsan_label *ret_origin) { 11384950695eSJianzhou Zhao return __dfsw_gethostname(name, len, name_label, len_label, ret_label); 11394950695eSJianzhou Zhao } 11404950695eSJianzhou Zhao 11414950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1142a9aa8137SNico Weber int __dfsw_getrlimit(int resource, struct rlimit *rlim, 1143a9aa8137SNico Weber dfsan_label resource_label, dfsan_label rlim_label, 1144a9aa8137SNico Weber dfsan_label *ret_label) { 1145a9aa8137SNico Weber int ret = getrlimit(resource, rlim); 1146a9aa8137SNico Weber if (ret == 0) { 1147a9aa8137SNico Weber dfsan_set_label(0, rlim, sizeof(struct rlimit)); 1148a9aa8137SNico Weber } 1149a9aa8137SNico Weber *ret_label = 0; 1150a9aa8137SNico Weber return ret; 1151a9aa8137SNico Weber } 1152a9aa8137SNico Weber 1153a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 11544950695eSJianzhou Zhao int __dfso_getrlimit(int resource, struct rlimit *rlim, 11554950695eSJianzhou Zhao dfsan_label resource_label, dfsan_label rlim_label, 11564950695eSJianzhou Zhao dfsan_label *ret_label, dfsan_origin resource_origin, 11574950695eSJianzhou Zhao dfsan_origin rlim_origin, dfsan_origin *ret_origin) { 11584950695eSJianzhou Zhao return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label, 11594950695eSJianzhou Zhao ret_label); 11604950695eSJianzhou Zhao } 11614950695eSJianzhou Zhao 11624950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1163a9aa8137SNico Weber int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label, 1164a9aa8137SNico Weber dfsan_label usage_label, dfsan_label *ret_label) { 1165a9aa8137SNico Weber int ret = getrusage(who, usage); 1166a9aa8137SNico Weber if (ret == 0) { 1167a9aa8137SNico Weber dfsan_set_label(0, usage, sizeof(struct rusage)); 1168a9aa8137SNico Weber } 1169a9aa8137SNico Weber *ret_label = 0; 1170a9aa8137SNico Weber return ret; 1171a9aa8137SNico Weber } 1172a9aa8137SNico Weber 1173a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 11744950695eSJianzhou Zhao int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label, 11754950695eSJianzhou Zhao dfsan_label usage_label, dfsan_label *ret_label, 11764950695eSJianzhou Zhao dfsan_origin who_origin, dfsan_origin usage_origin, 11774950695eSJianzhou Zhao dfsan_label *ret_origin) { 11784950695eSJianzhou Zhao return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label); 11794950695eSJianzhou Zhao } 11804950695eSJianzhou Zhao 11814950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1182a9aa8137SNico Weber char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label, 1183a9aa8137SNico Weber dfsan_label src_label, dfsan_label *ret_label) { 118444c83eccSVitaly Buka char *ret = strcpy(dest, src); 1185a9aa8137SNico Weber if (ret) { 118632167bfeSAndrew Browne dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1); 1187a9aa8137SNico Weber } 1188a9aa8137SNico Weber *ret_label = dst_label; 1189a9aa8137SNico Weber return ret; 1190a9aa8137SNico Weber } 1191a9aa8137SNico Weber 1192a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 119391516925SJianzhou Zhao char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label, 119491516925SJianzhou Zhao dfsan_label src_label, dfsan_label *ret_label, 119591516925SJianzhou Zhao dfsan_origin dst_origin, dfsan_origin src_origin, 119691516925SJianzhou Zhao dfsan_origin *ret_origin) { 119744c83eccSVitaly Buka char *ret = strcpy(dest, src); 119891516925SJianzhou Zhao if (ret) { 119991516925SJianzhou Zhao size_t str_len = strlen(src) + 1; 120091516925SJianzhou Zhao dfsan_mem_origin_transfer(dest, src, str_len); 120132167bfeSAndrew Browne dfsan_mem_shadow_transfer(dest, src, str_len); 1202a9aa8137SNico Weber } 120391516925SJianzhou Zhao *ret_label = dst_label; 120491516925SJianzhou Zhao *ret_origin = dst_origin; 120591516925SJianzhou Zhao return ret; 120691516925SJianzhou Zhao } 120764856006SFangrui Song } 120891516925SJianzhou Zhao 120964856006SFangrui Song template <typename Fn> 121064856006SFangrui Song static ALWAYS_INLINE auto dfsan_strtol_impl( 121164856006SFangrui Song Fn real, const char *nptr, char **endptr, int base, 121264856006SFangrui Song char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) { 121391516925SJianzhou Zhao assert(tmp_endptr); 121464856006SFangrui Song auto ret = real(nptr, tmp_endptr, base); 121591516925SJianzhou Zhao if (endptr) 121691516925SJianzhou Zhao *endptr = *tmp_endptr; 121791516925SJianzhou Zhao return ret; 121891516925SJianzhou Zhao } 121991516925SJianzhou Zhao 122064856006SFangrui Song extern "C" { 122191516925SJianzhou Zhao static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr, 122291516925SJianzhou Zhao dfsan_label base_label, 122391516925SJianzhou Zhao dfsan_label *ret_label) { 1224a9aa8137SNico Weber if (tmp_endptr > nptr) { 1225a9aa8137SNico Weber // If *tmp_endptr is '\0' include its label as well. 1226a9aa8137SNico Weber *ret_label = dfsan_union( 1227a9aa8137SNico Weber base_label, 1228a9aa8137SNico Weber dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 1229a9aa8137SNico Weber } else { 1230a9aa8137SNico Weber *ret_label = 0; 1231a9aa8137SNico Weber } 123291516925SJianzhou Zhao } 123391516925SJianzhou Zhao 123491516925SJianzhou Zhao static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr, 123591516925SJianzhou Zhao dfsan_label base_label, 123691516925SJianzhou Zhao dfsan_label *ret_label, 123791516925SJianzhou Zhao dfsan_origin base_origin, 123891516925SJianzhou Zhao dfsan_origin *ret_origin) { 123991516925SJianzhou Zhao if (tmp_endptr > nptr) { 124091516925SJianzhou Zhao // When multiple inputs are tainted, we propagate one of its origins. 124191516925SJianzhou Zhao // Because checking if base_label is tainted does not need additional 124291516925SJianzhou Zhao // computation, we prefer to propagating base_origin. 124391516925SJianzhou Zhao *ret_origin = base_label 124491516925SJianzhou Zhao ? base_origin 124591516925SJianzhou Zhao : dfsan_read_origin_of_first_taint( 124691516925SJianzhou Zhao nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 124791516925SJianzhou Zhao } 124891516925SJianzhou Zhao } 124991516925SJianzhou Zhao 125091516925SJianzhou Zhao static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) { 125191516925SJianzhou Zhao assert(tmp_endptr); 125291516925SJianzhou Zhao double ret = strtod(nptr, tmp_endptr); 125391516925SJianzhou Zhao if (endptr) 125491516925SJianzhou Zhao *endptr = *tmp_endptr; 125591516925SJianzhou Zhao return ret; 125691516925SJianzhou Zhao } 125791516925SJianzhou Zhao 125891516925SJianzhou Zhao static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr, 125991516925SJianzhou Zhao dfsan_label *ret_label) { 1260a9aa8137SNico Weber if (tmp_endptr > nptr) { 1261a9aa8137SNico Weber // If *tmp_endptr is '\0' include its label as well. 1262a9aa8137SNico Weber *ret_label = dfsan_read_label( 1263a9aa8137SNico Weber nptr, 1264a9aa8137SNico Weber tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 1265a9aa8137SNico Weber } else { 1266a9aa8137SNico Weber *ret_label = 0; 1267a9aa8137SNico Weber } 126891516925SJianzhou Zhao } 126991516925SJianzhou Zhao 127091516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 127191516925SJianzhou Zhao double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, 127291516925SJianzhou Zhao dfsan_label endptr_label, dfsan_label *ret_label) { 127391516925SJianzhou Zhao char *tmp_endptr; 127491516925SJianzhou Zhao double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); 127591516925SJianzhou Zhao dfsan_strtod_label(nptr, tmp_endptr, ret_label); 127691516925SJianzhou Zhao return ret; 127791516925SJianzhou Zhao } 127891516925SJianzhou Zhao 127991516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 128091516925SJianzhou Zhao double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, 128191516925SJianzhou Zhao dfsan_label endptr_label, dfsan_label *ret_label, 128291516925SJianzhou Zhao dfsan_origin nptr_origin, dfsan_origin endptr_origin, 128391516925SJianzhou Zhao dfsan_origin *ret_origin) { 128491516925SJianzhou Zhao char *tmp_endptr; 128591516925SJianzhou Zhao double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); 128691516925SJianzhou Zhao dfsan_strtod_label(nptr, tmp_endptr, ret_label); 128791516925SJianzhou Zhao if (tmp_endptr > nptr) { 128891516925SJianzhou Zhao // If *tmp_endptr is '\0' include its label as well. 128991516925SJianzhou Zhao *ret_origin = dfsan_read_origin_of_first_taint( 129091516925SJianzhou Zhao nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 129191516925SJianzhou Zhao } else { 129291516925SJianzhou Zhao *ret_origin = 0; 129391516925SJianzhou Zhao } 129491516925SJianzhou Zhao return ret; 129591516925SJianzhou Zhao } 129691516925SJianzhou Zhao 129764856006SFangrui Song WRAPPER_ALIAS(__isoc23_strtod, strtod) 129864856006SFangrui Song 129964856006SFangrui Song #define WRAPPER_STRTO(ret_type, fun) \ 130064856006SFangrui Song SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \ 130164856006SFangrui Song const char *nptr, char **endptr, int base, dfsan_label nptr_label, \ 130264856006SFangrui Song dfsan_label endptr_label, dfsan_label base_label, \ 130364856006SFangrui Song dfsan_label *ret_label) { \ 130464856006SFangrui Song char *tmp_endptr; \ 130564856006SFangrui Song auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \ 130664856006SFangrui Song dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \ 130764856006SFangrui Song return ret; \ 130864856006SFangrui Song } \ 130964856006SFangrui Song SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \ 131064856006SFangrui Song const char *nptr, char **endptr, int base, dfsan_label nptr_label, \ 131164856006SFangrui Song dfsan_label endptr_label, dfsan_label base_label, \ 131264856006SFangrui Song dfsan_label *ret_label, dfsan_origin nptr_origin, \ 131364856006SFangrui Song dfsan_origin endptr_origin, dfsan_origin base_origin, \ 131464856006SFangrui Song dfsan_origin *ret_origin) { \ 131564856006SFangrui Song char *tmp_endptr; \ 131664856006SFangrui Song auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \ 131764856006SFangrui Song dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \ 131864856006SFangrui Song dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \ 131964856006SFangrui Song base_origin, ret_origin); \ 132064856006SFangrui Song return ret; \ 1321a9aa8137SNico Weber } 1322a9aa8137SNico Weber 132364856006SFangrui Song WRAPPER_STRTO(long, strtol) 132464856006SFangrui Song WRAPPER_STRTO(long long, strtoll) 132564856006SFangrui Song WRAPPER_STRTO(unsigned long, strtoul) 132664856006SFangrui Song WRAPPER_STRTO(unsigned long long, strtoull) 132764856006SFangrui Song WRAPPER_ALIAS(__isoc23_strtol, strtol) 132864856006SFangrui Song WRAPPER_ALIAS(__isoc23_strtoll, strtoll) 132964856006SFangrui Song WRAPPER_ALIAS(__isoc23_strtoul, strtoul) 133064856006SFangrui Song WRAPPER_ALIAS(__isoc23_strtoull, strtoull) 1331a9aa8137SNico Weber 1332a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 1333a9aa8137SNico Weber time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) { 1334a9aa8137SNico Weber time_t ret = time(t); 1335a9aa8137SNico Weber if (ret != (time_t) -1 && t) { 1336a9aa8137SNico Weber dfsan_set_label(0, t, sizeof(time_t)); 1337a9aa8137SNico Weber } 1338a9aa8137SNico Weber *ret_label = 0; 1339a9aa8137SNico Weber return ret; 1340a9aa8137SNico Weber } 1341a9aa8137SNico Weber 1342a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 13434950695eSJianzhou Zhao time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label, 13444950695eSJianzhou Zhao dfsan_origin t_origin, dfsan_origin *ret_origin) { 13454950695eSJianzhou Zhao return __dfsw_time(t, t_label, ret_label); 13464950695eSJianzhou Zhao } 13474950695eSJianzhou Zhao 13484950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1349a9aa8137SNico Weber int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label, 1350a9aa8137SNico Weber dfsan_label src_label, dfsan_label dst_label, 1351a9aa8137SNico Weber dfsan_label *ret_label) { 1352a9aa8137SNico Weber int ret = inet_pton(af, src, dst); 1353a9aa8137SNico Weber if (ret == 1) { 1354a9aa8137SNico Weber dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst, 1355a9aa8137SNico Weber af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr)); 1356a9aa8137SNico Weber } 1357a9aa8137SNico Weber *ret_label = 0; 1358a9aa8137SNico Weber return ret; 1359a9aa8137SNico Weber } 1360a9aa8137SNico Weber 1361a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 13624950695eSJianzhou Zhao int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label, 13634950695eSJianzhou Zhao dfsan_label src_label, dfsan_label dst_label, 13644950695eSJianzhou Zhao dfsan_label *ret_label, dfsan_origin af_origin, 13654950695eSJianzhou Zhao dfsan_origin src_origin, dfsan_origin dst_origin, 13664950695eSJianzhou Zhao dfsan_origin *ret_origin) { 13674950695eSJianzhou Zhao int ret = inet_pton(af, src, dst); 13684950695eSJianzhou Zhao if (ret == 1) { 13694950695eSJianzhou Zhao int src_len = strlen(src) + 1; 13704950695eSJianzhou Zhao dfsan_set_label_origin( 13714950695eSJianzhou Zhao dfsan_read_label(src, src_len), 13724950695eSJianzhou Zhao dfsan_read_origin_of_first_taint(src, src_len), dst, 13734950695eSJianzhou Zhao af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr)); 13744950695eSJianzhou Zhao } 13754950695eSJianzhou Zhao *ret_label = 0; 13764950695eSJianzhou Zhao return ret; 13774950695eSJianzhou Zhao } 13784950695eSJianzhou Zhao 13794950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1380a9aa8137SNico Weber struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result, 1381a9aa8137SNico Weber dfsan_label timep_label, dfsan_label result_label, 1382a9aa8137SNico Weber dfsan_label *ret_label) { 1383a9aa8137SNico Weber struct tm *ret = localtime_r(timep, result); 1384a9aa8137SNico Weber if (ret) { 1385a9aa8137SNico Weber dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result, 1386a9aa8137SNico Weber sizeof(struct tm)); 1387a9aa8137SNico Weber *ret_label = result_label; 1388a9aa8137SNico Weber } else { 1389a9aa8137SNico Weber *ret_label = 0; 1390a9aa8137SNico Weber } 1391a9aa8137SNico Weber return ret; 1392a9aa8137SNico Weber } 1393a9aa8137SNico Weber 1394a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 13954950695eSJianzhou Zhao struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result, 13964950695eSJianzhou Zhao dfsan_label timep_label, dfsan_label result_label, 13974950695eSJianzhou Zhao dfsan_label *ret_label, dfsan_origin timep_origin, 13984950695eSJianzhou Zhao dfsan_origin result_origin, 13994950695eSJianzhou Zhao dfsan_origin *ret_origin) { 14004950695eSJianzhou Zhao struct tm *ret = localtime_r(timep, result); 14014950695eSJianzhou Zhao if (ret) { 14024950695eSJianzhou Zhao dfsan_set_label_origin( 14034950695eSJianzhou Zhao dfsan_read_label(timep, sizeof(time_t)), 14044950695eSJianzhou Zhao dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result, 14054950695eSJianzhou Zhao sizeof(struct tm)); 14064950695eSJianzhou Zhao *ret_label = result_label; 14074950695eSJianzhou Zhao *ret_origin = result_origin; 14084950695eSJianzhou Zhao } else { 14094950695eSJianzhou Zhao *ret_label = 0; 14104950695eSJianzhou Zhao } 14114950695eSJianzhou Zhao return ret; 14124950695eSJianzhou Zhao } 14134950695eSJianzhou Zhao 14144950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1415a9aa8137SNico Weber int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd, 1416a9aa8137SNico Weber char *buf, size_t buflen, struct passwd **result, 1417a9aa8137SNico Weber dfsan_label uid_label, dfsan_label pwd_label, 1418a9aa8137SNico Weber dfsan_label buf_label, dfsan_label buflen_label, 1419a9aa8137SNico Weber dfsan_label result_label, dfsan_label *ret_label) { 1420a9aa8137SNico Weber // Store the data in pwd, the strings referenced from pwd in buf, and the 1421a9aa8137SNico Weber // address of pwd in *result. On failure, NULL is stored in *result. 1422a9aa8137SNico Weber int ret = getpwuid_r(uid, pwd, buf, buflen, result); 1423a9aa8137SNico Weber if (ret == 0) { 1424a9aa8137SNico Weber dfsan_set_label(0, pwd, sizeof(struct passwd)); 1425a9aa8137SNico Weber dfsan_set_label(0, buf, strlen(buf) + 1); 1426a9aa8137SNico Weber } 1427a9aa8137SNico Weber *ret_label = 0; 1428a9aa8137SNico Weber dfsan_set_label(0, result, sizeof(struct passwd*)); 1429a9aa8137SNico Weber return ret; 1430a9aa8137SNico Weber } 1431a9aa8137SNico Weber 1432a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 14334950695eSJianzhou Zhao int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen, 14344950695eSJianzhou Zhao struct passwd **result, dfsan_label uid_label, 14354950695eSJianzhou Zhao dfsan_label pwd_label, dfsan_label buf_label, 14364950695eSJianzhou Zhao dfsan_label buflen_label, dfsan_label result_label, 14374950695eSJianzhou Zhao dfsan_label *ret_label, dfsan_origin uid_origin, 14384950695eSJianzhou Zhao dfsan_origin pwd_origin, dfsan_origin buf_origin, 14394950695eSJianzhou Zhao dfsan_origin buflen_origin, dfsan_origin result_origin, 14404950695eSJianzhou Zhao dfsan_origin *ret_origin) { 14414950695eSJianzhou Zhao return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label, 14424950695eSJianzhou Zhao buf_label, buflen_label, result_label, ret_label); 14434950695eSJianzhou Zhao } 14444950695eSJianzhou Zhao 14454950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 14466f13445fSMatt Morehouse int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents, 14476f13445fSMatt Morehouse int timeout, dfsan_label epfd_label, 14486f13445fSMatt Morehouse dfsan_label events_label, dfsan_label maxevents_label, 14496f13445fSMatt Morehouse dfsan_label timeout_label, dfsan_label *ret_label) { 14506f13445fSMatt Morehouse int ret = epoll_wait(epfd, events, maxevents, timeout); 14516f13445fSMatt Morehouse if (ret > 0) 14526f13445fSMatt Morehouse dfsan_set_label(0, events, ret * sizeof(*events)); 14536f13445fSMatt Morehouse *ret_label = 0; 14546f13445fSMatt Morehouse return ret; 14556f13445fSMatt Morehouse } 14566f13445fSMatt Morehouse 14576f13445fSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE 14584950695eSJianzhou Zhao int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents, 14594950695eSJianzhou Zhao int timeout, dfsan_label epfd_label, 14604950695eSJianzhou Zhao dfsan_label events_label, dfsan_label maxevents_label, 14614950695eSJianzhou Zhao dfsan_label timeout_label, dfsan_label *ret_label, 14624950695eSJianzhou Zhao dfsan_origin epfd_origin, dfsan_origin events_origin, 14634950695eSJianzhou Zhao dfsan_origin maxevents_origin, 14644950695eSJianzhou Zhao dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 14654950695eSJianzhou Zhao return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label, 14664950695eSJianzhou Zhao events_label, maxevents_label, timeout_label, 14674950695eSJianzhou Zhao ret_label); 14684950695eSJianzhou Zhao } 14694950695eSJianzhou Zhao 14704950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1471a9aa8137SNico Weber int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout, 1472a9aa8137SNico Weber dfsan_label dfs_label, dfsan_label nfds_label, 1473a9aa8137SNico Weber dfsan_label timeout_label, dfsan_label *ret_label) { 1474a9aa8137SNico Weber int ret = poll(fds, nfds, timeout); 1475a9aa8137SNico Weber if (ret >= 0) { 1476a9aa8137SNico Weber for (; nfds > 0; --nfds) { 1477a9aa8137SNico Weber dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents)); 1478a9aa8137SNico Weber } 1479a9aa8137SNico Weber } 1480a9aa8137SNico Weber *ret_label = 0; 1481a9aa8137SNico Weber return ret; 1482a9aa8137SNico Weber } 1483a9aa8137SNico Weber 1484a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 14854950695eSJianzhou Zhao int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout, 14864950695eSJianzhou Zhao dfsan_label dfs_label, dfsan_label nfds_label, 14874950695eSJianzhou Zhao dfsan_label timeout_label, dfsan_label *ret_label, 14884950695eSJianzhou Zhao dfsan_origin dfs_origin, dfsan_origin nfds_origin, 14894950695eSJianzhou Zhao dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 14904950695eSJianzhou Zhao return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label, 14914950695eSJianzhou Zhao ret_label); 14924950695eSJianzhou Zhao } 14934950695eSJianzhou Zhao 14944950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1495a9aa8137SNico Weber int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds, 1496a9aa8137SNico Weber fd_set *exceptfds, struct timeval *timeout, 1497a9aa8137SNico Weber dfsan_label nfds_label, dfsan_label readfds_label, 1498a9aa8137SNico Weber dfsan_label writefds_label, dfsan_label exceptfds_label, 1499a9aa8137SNico Weber dfsan_label timeout_label, dfsan_label *ret_label) { 1500a9aa8137SNico Weber int ret = select(nfds, readfds, writefds, exceptfds, timeout); 1501a9aa8137SNico Weber // Clear everything (also on error) since their content is either set or 1502a9aa8137SNico Weber // undefined. 1503a9aa8137SNico Weber if (readfds) { 1504a9aa8137SNico Weber dfsan_set_label(0, readfds, sizeof(fd_set)); 1505a9aa8137SNico Weber } 1506a9aa8137SNico Weber if (writefds) { 1507a9aa8137SNico Weber dfsan_set_label(0, writefds, sizeof(fd_set)); 1508a9aa8137SNico Weber } 1509a9aa8137SNico Weber if (exceptfds) { 1510a9aa8137SNico Weber dfsan_set_label(0, exceptfds, sizeof(fd_set)); 1511a9aa8137SNico Weber } 1512a9aa8137SNico Weber dfsan_set_label(0, timeout, sizeof(struct timeval)); 1513a9aa8137SNico Weber *ret_label = 0; 1514a9aa8137SNico Weber return ret; 1515a9aa8137SNico Weber } 1516a9aa8137SNico Weber 1517a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 15184950695eSJianzhou Zhao int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds, 15194950695eSJianzhou Zhao fd_set *exceptfds, struct timeval *timeout, 15204950695eSJianzhou Zhao dfsan_label nfds_label, dfsan_label readfds_label, 15214950695eSJianzhou Zhao dfsan_label writefds_label, dfsan_label exceptfds_label, 15224950695eSJianzhou Zhao dfsan_label timeout_label, dfsan_label *ret_label, 15234950695eSJianzhou Zhao dfsan_origin nfds_origin, dfsan_origin readfds_origin, 15244950695eSJianzhou Zhao dfsan_origin writefds_origin, dfsan_origin exceptfds_origin, 15254950695eSJianzhou Zhao dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 15264950695eSJianzhou Zhao return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label, 15274950695eSJianzhou Zhao readfds_label, writefds_label, exceptfds_label, 15284950695eSJianzhou Zhao timeout_label, ret_label); 15294950695eSJianzhou Zhao } 15304950695eSJianzhou Zhao 15314950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1532a9aa8137SNico Weber int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask, 1533a9aa8137SNico Weber dfsan_label pid_label, 1534a9aa8137SNico Weber dfsan_label cpusetsize_label, 1535a9aa8137SNico Weber dfsan_label mask_label, dfsan_label *ret_label) { 1536a9aa8137SNico Weber int ret = sched_getaffinity(pid, cpusetsize, mask); 1537a9aa8137SNico Weber if (ret == 0) { 1538a9aa8137SNico Weber dfsan_set_label(0, mask, cpusetsize); 1539a9aa8137SNico Weber } 1540a9aa8137SNico Weber *ret_label = 0; 1541a9aa8137SNico Weber return ret; 1542a9aa8137SNico Weber } 1543a9aa8137SNico Weber 1544a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 15454950695eSJianzhou Zhao int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask, 15464950695eSJianzhou Zhao dfsan_label pid_label, 15474950695eSJianzhou Zhao dfsan_label cpusetsize_label, 15484950695eSJianzhou Zhao dfsan_label mask_label, dfsan_label *ret_label, 15494950695eSJianzhou Zhao dfsan_origin pid_origin, 15504950695eSJianzhou Zhao dfsan_origin cpusetsize_origin, 15514950695eSJianzhou Zhao dfsan_origin mask_origin, 15524950695eSJianzhou Zhao dfsan_origin *ret_origin) { 15534950695eSJianzhou Zhao return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label, 15544950695eSJianzhou Zhao cpusetsize_label, mask_label, ret_label); 15554950695eSJianzhou Zhao } 15564950695eSJianzhou Zhao 15574950695eSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1558a9aa8137SNico Weber int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label, 1559a9aa8137SNico Weber dfsan_label *ret_label) { 1560a9aa8137SNico Weber int ret = sigemptyset(set); 1561a9aa8137SNico Weber dfsan_set_label(0, set, sizeof(sigset_t)); 1562e4701471SJianzhou Zhao *ret_label = 0; 1563a9aa8137SNico Weber return ret; 1564a9aa8137SNico Weber } 1565a9aa8137SNico Weber 15664e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 15674e67ae7bSJianzhou Zhao int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label, 15684e67ae7bSJianzhou Zhao dfsan_label *ret_label, dfsan_origin set_origin, 15694e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 15704e67ae7bSJianzhou Zhao return __dfsw_sigemptyset(set, set_label, ret_label); 15714e67ae7bSJianzhou Zhao } 15724e67ae7bSJianzhou Zhao 15730f3fd3b2SJianzhou Zhao class SignalHandlerScope { 15740f3fd3b2SJianzhou Zhao public: 15750f3fd3b2SJianzhou Zhao SignalHandlerScope() { 15760f3fd3b2SJianzhou Zhao if (DFsanThread *t = GetCurrentThread()) 15770f3fd3b2SJianzhou Zhao t->EnterSignalHandler(); 15780f3fd3b2SJianzhou Zhao } 15790f3fd3b2SJianzhou Zhao ~SignalHandlerScope() { 15800f3fd3b2SJianzhou Zhao if (DFsanThread *t = GetCurrentThread()) 15810f3fd3b2SJianzhou Zhao t->LeaveSignalHandler(); 15820f3fd3b2SJianzhou Zhao } 15830f3fd3b2SJianzhou Zhao }; 15840f3fd3b2SJianzhou Zhao 1585e1a4322fSJianzhou Zhao // Clear DFSan runtime TLS state at the end of a scope. 1586e1a4322fSJianzhou Zhao // 1587e1a4322fSJianzhou Zhao // Implementation must be async-signal-safe and use small data size, because 1588e1a4322fSJianzhou Zhao // instances of this class may live on the signal handler stack. 1589e1a4322fSJianzhou Zhao // 1590e1a4322fSJianzhou Zhao // DFSan uses TLS to pass metadata of arguments and return values. When an 1591e1a4322fSJianzhou Zhao // instrumented function accesses the TLS, if a signal callback happens, and the 1592e1a4322fSJianzhou Zhao // callback calls other instrumented functions with updating the same TLS, the 1593e1a4322fSJianzhou Zhao // TLS is in an inconsistent state after the callback ends. This may cause 1594e1a4322fSJianzhou Zhao // either under-tainting or over-tainting. 1595e1a4322fSJianzhou Zhao // 1596e1a4322fSJianzhou Zhao // The current implementation simply resets TLS at restore. This prevents from 1597e1a4322fSJianzhou Zhao // over-tainting. Although under-tainting may still happen, a taint flow can be 1598e1a4322fSJianzhou Zhao // found eventually if we run a DFSan-instrumented program multiple times. The 1599e1a4322fSJianzhou Zhao // alternative option is saving the entire TLS. However the TLS storage takes 1600e1a4322fSJianzhou Zhao // 2k bytes, and signal calls could be nested. So it does not seem worth. 1601e1a4322fSJianzhou Zhao class ScopedClearThreadLocalState { 1602e1a4322fSJianzhou Zhao public: 1603e1a4322fSJianzhou Zhao ScopedClearThreadLocalState() {} 1604e1a4322fSJianzhou Zhao ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); } 1605e1a4322fSJianzhou Zhao }; 1606e1a4322fSJianzhou Zhao 1607e1a4322fSJianzhou Zhao // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls. 1608e1a4322fSJianzhou Zhao const int kMaxSignals = 1024; 1609e1a4322fSJianzhou Zhao static atomic_uintptr_t sigactions[kMaxSignals]; 1610e1a4322fSJianzhou Zhao 1611e1a4322fSJianzhou Zhao static void SignalHandler(int signo) { 16120f3fd3b2SJianzhou Zhao SignalHandlerScope signal_handler_scope; 16130f3fd3b2SJianzhou Zhao ScopedClearThreadLocalState scoped_clear_tls; 1614e1a4322fSJianzhou Zhao 1615dbf8c00bSAndrew Browne // Clear shadows for all inputs provided by system. 1616e1a4322fSJianzhou Zhao dfsan_clear_arg_tls(0, sizeof(dfsan_label)); 1617e1a4322fSJianzhou Zhao 1618e1a4322fSJianzhou Zhao typedef void (*signal_cb)(int x); 1619e1a4322fSJianzhou Zhao signal_cb cb = 1620e1a4322fSJianzhou Zhao (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1621e1a4322fSJianzhou Zhao cb(signo); 1622e1a4322fSJianzhou Zhao } 1623e1a4322fSJianzhou Zhao 1624e1a4322fSJianzhou Zhao static void SignalAction(int signo, siginfo_t *si, void *uc) { 16250f3fd3b2SJianzhou Zhao SignalHandlerScope signal_handler_scope; 16260f3fd3b2SJianzhou Zhao ScopedClearThreadLocalState scoped_clear_tls; 1627e1a4322fSJianzhou Zhao 1628e1a4322fSJianzhou Zhao // Clear shadows for all inputs provided by system. Similar to SignalHandler. 1629e1a4322fSJianzhou Zhao dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label)); 1630e1a4322fSJianzhou Zhao dfsan_set_label(0, si, sizeof(*si)); 1631e1a4322fSJianzhou Zhao dfsan_set_label(0, uc, sizeof(ucontext_t)); 1632e1a4322fSJianzhou Zhao 1633e1a4322fSJianzhou Zhao typedef void (*sigaction_cb)(int, siginfo_t *, void *); 1634e1a4322fSJianzhou Zhao sigaction_cb cb = 1635e1a4322fSJianzhou Zhao (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1636e1a4322fSJianzhou Zhao cb(signo, si, uc); 1637e1a4322fSJianzhou Zhao } 1638e1a4322fSJianzhou Zhao 1639a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 1640a9aa8137SNico Weber int __dfsw_sigaction(int signum, const struct sigaction *act, 1641a9aa8137SNico Weber struct sigaction *oldact, dfsan_label signum_label, 1642a9aa8137SNico Weber dfsan_label act_label, dfsan_label oldact_label, 1643a9aa8137SNico Weber dfsan_label *ret_label) { 1644e1a4322fSJianzhou Zhao CHECK_LT(signum, kMaxSignals); 1645e1a4322fSJianzhou Zhao SignalSpinLocker lock; 1646e1a4322fSJianzhou Zhao uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed); 1647e1a4322fSJianzhou Zhao struct sigaction new_act; 1648e1a4322fSJianzhou Zhao struct sigaction *pnew_act = act ? &new_act : nullptr; 1649e1a4322fSJianzhou Zhao if (act) { 1650e1a4322fSJianzhou Zhao internal_memcpy(pnew_act, act, sizeof(struct sigaction)); 1651e1a4322fSJianzhou Zhao if (pnew_act->sa_flags & SA_SIGINFO) { 1652e1a4322fSJianzhou Zhao uptr cb = (uptr)(pnew_act->sa_sigaction); 1653e1a4322fSJianzhou Zhao if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) { 1654e1a4322fSJianzhou Zhao atomic_store(&sigactions[signum], cb, memory_order_relaxed); 1655e1a4322fSJianzhou Zhao pnew_act->sa_sigaction = SignalAction; 1656e1a4322fSJianzhou Zhao } 1657e1a4322fSJianzhou Zhao } else { 1658e1a4322fSJianzhou Zhao uptr cb = (uptr)(pnew_act->sa_handler); 1659e1a4322fSJianzhou Zhao if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) { 1660e1a4322fSJianzhou Zhao atomic_store(&sigactions[signum], cb, memory_order_relaxed); 1661e1a4322fSJianzhou Zhao pnew_act->sa_handler = SignalHandler; 1662e1a4322fSJianzhou Zhao } 1663e1a4322fSJianzhou Zhao } 1664e1a4322fSJianzhou Zhao } 1665e1a4322fSJianzhou Zhao 1666e1a4322fSJianzhou Zhao int ret = sigaction(signum, pnew_act, oldact); 1667e1a4322fSJianzhou Zhao 1668e1a4322fSJianzhou Zhao if (ret == 0 && oldact) { 1669e1a4322fSJianzhou Zhao if (oldact->sa_flags & SA_SIGINFO) { 1670e1a4322fSJianzhou Zhao if (oldact->sa_sigaction == SignalAction) 1671e1a4322fSJianzhou Zhao oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb; 1672e1a4322fSJianzhou Zhao } else { 1673e1a4322fSJianzhou Zhao if (oldact->sa_handler == SignalHandler) 1674e1a4322fSJianzhou Zhao oldact->sa_handler = (decltype(oldact->sa_handler))old_cb; 1675e1a4322fSJianzhou Zhao } 1676e1a4322fSJianzhou Zhao } 1677e1a4322fSJianzhou Zhao 1678a9aa8137SNico Weber if (oldact) { 1679a9aa8137SNico Weber dfsan_set_label(0, oldact, sizeof(struct sigaction)); 1680a9aa8137SNico Weber } 1681a9aa8137SNico Weber *ret_label = 0; 1682a9aa8137SNico Weber return ret; 1683a9aa8137SNico Weber } 1684a9aa8137SNico Weber 1685a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 16864e67ae7bSJianzhou Zhao int __dfso_sigaction(int signum, const struct sigaction *act, 16874e67ae7bSJianzhou Zhao struct sigaction *oldact, dfsan_label signum_label, 16884e67ae7bSJianzhou Zhao dfsan_label act_label, dfsan_label oldact_label, 16894e67ae7bSJianzhou Zhao dfsan_label *ret_label, dfsan_origin signum_origin, 16904e67ae7bSJianzhou Zhao dfsan_origin act_origin, dfsan_origin oldact_origin, 16914e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 16924e67ae7bSJianzhou Zhao return __dfsw_sigaction(signum, act, oldact, signum_label, act_label, 16934e67ae7bSJianzhou Zhao oldact_label, ret_label); 16944e67ae7bSJianzhou Zhao } 16954e67ae7bSJianzhou Zhao 16964e67ae7bSJianzhou Zhao static sighandler_t dfsan_signal(int signum, sighandler_t handler, 16974e67ae7bSJianzhou Zhao dfsan_label *ret_label) { 169893afc345SJianzhou Zhao CHECK_LT(signum, kMaxSignals); 169993afc345SJianzhou Zhao SignalSpinLocker lock; 170093afc345SJianzhou Zhao uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed); 170193afc345SJianzhou Zhao if (handler != SIG_IGN && handler != SIG_DFL) { 170293afc345SJianzhou Zhao atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed); 170393afc345SJianzhou Zhao handler = &SignalHandler; 170493afc345SJianzhou Zhao } 170593afc345SJianzhou Zhao 170693afc345SJianzhou Zhao sighandler_t ret = signal(signum, handler); 170793afc345SJianzhou Zhao 170893afc345SJianzhou Zhao if (ret == SignalHandler) 170993afc345SJianzhou Zhao ret = (sighandler_t)old_cb; 171093afc345SJianzhou Zhao 171193afc345SJianzhou Zhao *ret_label = 0; 171293afc345SJianzhou Zhao return ret; 171393afc345SJianzhou Zhao } 171493afc345SJianzhou Zhao 171593afc345SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1716dbf8c00bSAndrew Browne sighandler_t __dfsw_signal(int signum, sighandler_t handler, 1717dbf8c00bSAndrew Browne dfsan_label signum_label, dfsan_label handler_label, 1718dbf8c00bSAndrew Browne dfsan_label *ret_label) { 17194e67ae7bSJianzhou Zhao return dfsan_signal(signum, handler, ret_label); 17204e67ae7bSJianzhou Zhao } 17214e67ae7bSJianzhou Zhao 17224e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1723dbf8c00bSAndrew Browne sighandler_t __dfso_signal(int signum, sighandler_t handler, 1724dbf8c00bSAndrew Browne dfsan_label signum_label, dfsan_label handler_label, 17254e67ae7bSJianzhou Zhao dfsan_label *ret_label, dfsan_origin signum_origin, 1726dbf8c00bSAndrew Browne dfsan_origin handler_origin, 1727dbf8c00bSAndrew Browne dfsan_origin *ret_origin) { 17284e67ae7bSJianzhou Zhao return dfsan_signal(signum, handler, ret_label); 17294e67ae7bSJianzhou Zhao } 17304e67ae7bSJianzhou Zhao 17314e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1732bdaeb82aSMatt Morehouse int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label, 1733bdaeb82aSMatt Morehouse dfsan_label old_ss_label, dfsan_label *ret_label) { 1734bdaeb82aSMatt Morehouse int ret = sigaltstack(ss, old_ss); 1735bdaeb82aSMatt Morehouse if (ret != -1 && old_ss) 1736bdaeb82aSMatt Morehouse dfsan_set_label(0, old_ss, sizeof(*old_ss)); 1737bdaeb82aSMatt Morehouse *ret_label = 0; 1738bdaeb82aSMatt Morehouse return ret; 1739bdaeb82aSMatt Morehouse } 1740bdaeb82aSMatt Morehouse 1741bdaeb82aSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE 17424e67ae7bSJianzhou Zhao int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label, 17434e67ae7bSJianzhou Zhao dfsan_label old_ss_label, dfsan_label *ret_label, 17444e67ae7bSJianzhou Zhao dfsan_origin ss_origin, dfsan_origin old_ss_origin, 17454e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 17464e67ae7bSJianzhou Zhao return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label); 17474e67ae7bSJianzhou Zhao } 17484e67ae7bSJianzhou Zhao 17494e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 1750a9aa8137SNico Weber int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz, 1751a9aa8137SNico Weber dfsan_label tv_label, dfsan_label tz_label, 1752a9aa8137SNico Weber dfsan_label *ret_label) { 1753a9aa8137SNico Weber int ret = gettimeofday(tv, tz); 1754a9aa8137SNico Weber if (tv) { 1755a9aa8137SNico Weber dfsan_set_label(0, tv, sizeof(struct timeval)); 1756a9aa8137SNico Weber } 1757a9aa8137SNico Weber if (tz) { 1758a9aa8137SNico Weber dfsan_set_label(0, tz, sizeof(struct timezone)); 1759a9aa8137SNico Weber } 1760a9aa8137SNico Weber *ret_label = 0; 1761a9aa8137SNico Weber return ret; 1762a9aa8137SNico Weber } 1763a9aa8137SNico Weber 176491516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 176591516925SJianzhou Zhao int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz, 176691516925SJianzhou Zhao dfsan_label tv_label, dfsan_label tz_label, 176791516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin tv_origin, 176891516925SJianzhou Zhao dfsan_origin tz_origin, dfsan_origin *ret_origin) { 176991516925SJianzhou Zhao return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label); 177091516925SJianzhou Zhao } 177191516925SJianzhou Zhao 1772a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n, 1773a9aa8137SNico Weber dfsan_label s_label, 1774a9aa8137SNico Weber dfsan_label c_label, 1775a9aa8137SNico Weber dfsan_label n_label, 1776a9aa8137SNico Weber dfsan_label *ret_label) { 1777a9aa8137SNico Weber void *ret = memchr(s, c, n); 1778a9aa8137SNico Weber if (flags().strict_data_dependencies) { 1779a9aa8137SNico Weber *ret_label = ret ? s_label : 0; 1780a9aa8137SNico Weber } else { 1781a9aa8137SNico Weber size_t len = 1782a9aa8137SNico Weber ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1 1783a9aa8137SNico Weber : n; 1784a9aa8137SNico Weber *ret_label = 1785a9aa8137SNico Weber dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label)); 1786a9aa8137SNico Weber } 1787a9aa8137SNico Weber return ret; 1788a9aa8137SNico Weber } 1789a9aa8137SNico Weber 179091516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr( 179191516925SJianzhou Zhao void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label, 179291516925SJianzhou Zhao dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin, 179391516925SJianzhou Zhao dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) { 179491516925SJianzhou Zhao void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label); 179591516925SJianzhou Zhao if (flags().strict_data_dependencies) { 179691516925SJianzhou Zhao if (ret) 179791516925SJianzhou Zhao *ret_origin = s_origin; 179891516925SJianzhou Zhao } else { 179991516925SJianzhou Zhao size_t len = 180091516925SJianzhou Zhao ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1 180191516925SJianzhou Zhao : n; 180291516925SJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(s, len); 180391516925SJianzhou Zhao *ret_origin = o ? o : (s_label ? s_origin : c_origin); 180491516925SJianzhou Zhao } 180591516925SJianzhou Zhao return ret; 180691516925SJianzhou Zhao } 180791516925SJianzhou Zhao 1808a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c, 1809a9aa8137SNico Weber dfsan_label s_label, 1810a9aa8137SNico Weber dfsan_label c_label, 1811a9aa8137SNico Weber dfsan_label *ret_label) { 1812a9aa8137SNico Weber char *ret = strrchr(s, c); 1813a9aa8137SNico Weber if (flags().strict_data_dependencies) { 1814a9aa8137SNico Weber *ret_label = ret ? s_label : 0; 1815a9aa8137SNico Weber } else { 1816a9aa8137SNico Weber *ret_label = 1817a9aa8137SNico Weber dfsan_union(dfsan_read_label(s, strlen(s) + 1), 1818a9aa8137SNico Weber dfsan_union(s_label, c_label)); 1819a9aa8137SNico Weber } 1820a9aa8137SNico Weber 1821a9aa8137SNico Weber return ret; 1822a9aa8137SNico Weber } 1823a9aa8137SNico Weber 182491516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr( 182591516925SJianzhou Zhao char *s, int c, dfsan_label s_label, dfsan_label c_label, 182691516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin, 182791516925SJianzhou Zhao dfsan_origin *ret_origin) { 182891516925SJianzhou Zhao char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label); 182991516925SJianzhou Zhao if (flags().strict_data_dependencies) { 183091516925SJianzhou Zhao if (ret) 183191516925SJianzhou Zhao *ret_origin = s_origin; 183291516925SJianzhou Zhao } else { 183391516925SJianzhou Zhao size_t s_len = strlen(s) + 1; 183491516925SJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len); 183591516925SJianzhou Zhao *ret_origin = o ? o : (s_label ? s_origin : c_origin); 183691516925SJianzhou Zhao } 183791516925SJianzhou Zhao 183891516925SJianzhou Zhao return ret; 183991516925SJianzhou Zhao } 184091516925SJianzhou Zhao 1841a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle, 1842a9aa8137SNico Weber dfsan_label haystack_label, 1843a9aa8137SNico Weber dfsan_label needle_label, 1844a9aa8137SNico Weber dfsan_label *ret_label) { 1845a9aa8137SNico Weber char *ret = strstr(haystack, needle); 1846a9aa8137SNico Weber if (flags().strict_data_dependencies) { 1847a9aa8137SNico Weber *ret_label = ret ? haystack_label : 0; 1848a9aa8137SNico Weber } else { 1849a9aa8137SNico Weber size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1; 1850a9aa8137SNico Weber *ret_label = 1851a9aa8137SNico Weber dfsan_union(dfsan_read_label(haystack, len), 1852a9aa8137SNico Weber dfsan_union(dfsan_read_label(needle, strlen(needle) + 1), 1853a9aa8137SNico Weber dfsan_union(haystack_label, needle_label))); 1854a9aa8137SNico Weber } 1855a9aa8137SNico Weber 1856a9aa8137SNico Weber return ret; 1857a9aa8137SNico Weber } 1858a9aa8137SNico Weber 185991516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle, 186091516925SJianzhou Zhao dfsan_label haystack_label, 186191516925SJianzhou Zhao dfsan_label needle_label, 186291516925SJianzhou Zhao dfsan_label *ret_label, 186391516925SJianzhou Zhao dfsan_origin haystack_origin, 186491516925SJianzhou Zhao dfsan_origin needle_origin, 186591516925SJianzhou Zhao dfsan_origin *ret_origin) { 186691516925SJianzhou Zhao char *ret = 186791516925SJianzhou Zhao __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label); 186891516925SJianzhou Zhao if (flags().strict_data_dependencies) { 186991516925SJianzhou Zhao if (ret) 187091516925SJianzhou Zhao *ret_origin = haystack_origin; 187191516925SJianzhou Zhao } else { 187291516925SJianzhou Zhao size_t needle_len = strlen(needle); 187391516925SJianzhou Zhao size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1; 187491516925SJianzhou Zhao dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len); 187591516925SJianzhou Zhao if (o) { 187691516925SJianzhou Zhao *ret_origin = o; 187791516925SJianzhou Zhao } else { 187891516925SJianzhou Zhao o = dfsan_read_origin_of_first_taint(needle, needle_len + 1); 187991516925SJianzhou Zhao *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin); 188091516925SJianzhou Zhao } 188191516925SJianzhou Zhao } 188291516925SJianzhou Zhao 188391516925SJianzhou Zhao return ret; 188491516925SJianzhou Zhao } 188591516925SJianzhou Zhao 1886a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req, 1887a9aa8137SNico Weber struct timespec *rem, 1888a9aa8137SNico Weber dfsan_label req_label, 1889a9aa8137SNico Weber dfsan_label rem_label, 1890a9aa8137SNico Weber dfsan_label *ret_label) { 1891a9aa8137SNico Weber int ret = nanosleep(req, rem); 1892a9aa8137SNico Weber *ret_label = 0; 1893a9aa8137SNico Weber if (ret == -1) { 1894a9aa8137SNico Weber // Interrupted by a signal, rem is filled with the remaining time. 1895a9aa8137SNico Weber dfsan_set_label(0, rem, sizeof(struct timespec)); 1896a9aa8137SNico Weber } 1897a9aa8137SNico Weber return ret; 1898a9aa8137SNico Weber } 1899a9aa8137SNico Weber 190091516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep( 190191516925SJianzhou Zhao const struct timespec *req, struct timespec *rem, dfsan_label req_label, 190291516925SJianzhou Zhao dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin, 190391516925SJianzhou Zhao dfsan_origin rem_origin, dfsan_origin *ret_origin) { 190491516925SJianzhou Zhao return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label); 190591516925SJianzhou Zhao } 190691516925SJianzhou Zhao 19073b3d622bSAndrew Browne static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg, 19083b3d622bSAndrew Browne int flags) { 19097bc7501aSMatt Morehouse dfsan_set_label(0, msg, sizeof(*msg)); 19107bc7501aSMatt Morehouse dfsan_set_label(0, msg->msg_name, msg->msg_namelen); 19117bc7501aSMatt Morehouse dfsan_set_label(0, msg->msg_control, msg->msg_controllen); 19123b3d622bSAndrew Browne for (size_t i = 0; i < msg->msg_iovlen; ++i) { 19137bc7501aSMatt Morehouse struct iovec *iov = &msg->msg_iov[i]; 19143b3d622bSAndrew Browne size_t iov_written = iov->iov_len; 19153b3d622bSAndrew Browne 19163b3d622bSAndrew Browne // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that 19173b3d622bSAndrew Browne // may not have changed, using bytes_written to bound the 0 label write. 19183b3d622bSAndrew Browne // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer, 19193b3d622bSAndrew Browne // and should not be used as a bound. 19203b3d622bSAndrew Browne if (!(MSG_TRUNC & flags)) { 19213b3d622bSAndrew Browne if (bytes_written < iov->iov_len) { 19223b3d622bSAndrew Browne iov_written = bytes_written; 19233b3d622bSAndrew Browne } 19247bc7501aSMatt Morehouse bytes_written -= iov_written; 19257bc7501aSMatt Morehouse } 19263b3d622bSAndrew Browne 19273b3d622bSAndrew Browne dfsan_set_label(0, iov->iov_base, iov_written); 19283b3d622bSAndrew Browne } 19297bc7501aSMatt Morehouse } 19307bc7501aSMatt Morehouse 19317bc7501aSMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg( 19327bc7501aSMatt Morehouse int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, 19337bc7501aSMatt Morehouse struct timespec *timeout, dfsan_label sockfd_label, 19347bc7501aSMatt Morehouse dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label, 19357bc7501aSMatt Morehouse dfsan_label timeout_label, dfsan_label *ret_label) { 19367bc7501aSMatt Morehouse int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout); 19377bc7501aSMatt Morehouse for (int i = 0; i < ret; ++i) { 19387bc7501aSMatt Morehouse dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len)); 19393b3d622bSAndrew Browne clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags); 19407bc7501aSMatt Morehouse } 19417bc7501aSMatt Morehouse *ret_label = 0; 19427bc7501aSMatt Morehouse return ret; 19437bc7501aSMatt Morehouse } 19447bc7501aSMatt Morehouse 194591516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg( 194691516925SJianzhou Zhao int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, 194791516925SJianzhou Zhao struct timespec *timeout, dfsan_label sockfd_label, 194891516925SJianzhou Zhao dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label, 194991516925SJianzhou Zhao dfsan_label timeout_label, dfsan_label *ret_label, 195091516925SJianzhou Zhao dfsan_origin sockfd_origin, dfsan_origin msgvec_origin, 195191516925SJianzhou Zhao dfsan_origin vlen_origin, dfsan_origin flags_origin, 195291516925SJianzhou Zhao dfsan_origin timeout_origin, dfsan_origin *ret_origin) { 195391516925SJianzhou Zhao return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label, 195491516925SJianzhou Zhao msgvec_label, vlen_label, flags_label, timeout_label, 195591516925SJianzhou Zhao ret_label); 195691516925SJianzhou Zhao } 195791516925SJianzhou Zhao 1958a3eb2fb2SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg( 1959a3eb2fb2SMatt Morehouse int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, 1960a3eb2fb2SMatt Morehouse dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) { 1961a3eb2fb2SMatt Morehouse ssize_t ret = recvmsg(sockfd, msg, flags); 19627bc7501aSMatt Morehouse if (ret >= 0) 19633b3d622bSAndrew Browne clear_msghdr_labels(ret, msg, flags); 1964a3eb2fb2SMatt Morehouse *ret_label = 0; 1965a3eb2fb2SMatt Morehouse return ret; 1966a3eb2fb2SMatt Morehouse } 1967a3eb2fb2SMatt Morehouse 196891516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg( 196991516925SJianzhou Zhao int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, 197091516925SJianzhou Zhao dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label, 197191516925SJianzhou Zhao dfsan_origin sockfd_origin, dfsan_origin msg_origin, 197291516925SJianzhou Zhao dfsan_origin flags_origin, dfsan_origin *ret_origin) { 197391516925SJianzhou Zhao return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label, 197491516925SJianzhou Zhao flags_label, ret_label); 197591516925SJianzhou Zhao } 197691516925SJianzhou Zhao 1977a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int 1978a9aa8137SNico Weber __dfsw_socketpair(int domain, int type, int protocol, int sv[2], 1979a9aa8137SNico Weber dfsan_label domain_label, dfsan_label type_label, 1980a9aa8137SNico Weber dfsan_label protocol_label, dfsan_label sv_label, 1981a9aa8137SNico Weber dfsan_label *ret_label) { 1982a9aa8137SNico Weber int ret = socketpair(domain, type, protocol, sv); 1983a9aa8137SNico Weber *ret_label = 0; 1984a9aa8137SNico Weber if (ret == 0) { 1985a9aa8137SNico Weber dfsan_set_label(0, sv, sizeof(*sv) * 2); 1986a9aa8137SNico Weber } 1987a9aa8137SNico Weber return ret; 1988a9aa8137SNico Weber } 1989a9aa8137SNico Weber 199091516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair( 199191516925SJianzhou Zhao int domain, int type, int protocol, int sv[2], dfsan_label domain_label, 199291516925SJianzhou Zhao dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label, 199391516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin domain_origin, 199491516925SJianzhou Zhao dfsan_origin type_origin, dfsan_origin protocol_origin, 199591516925SJianzhou Zhao dfsan_origin sv_origin, dfsan_origin *ret_origin) { 199691516925SJianzhou Zhao return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label, 199791516925SJianzhou Zhao protocol_label, sv_label, ret_label); 199891516925SJianzhou Zhao } 199991516925SJianzhou Zhao 20004eedc2e3SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt( 20014eedc2e3SMatt Morehouse int sockfd, int level, int optname, void *optval, socklen_t *optlen, 20024eedc2e3SMatt Morehouse dfsan_label sockfd_label, dfsan_label level_label, 20034eedc2e3SMatt Morehouse dfsan_label optname_label, dfsan_label optval_label, 20044eedc2e3SMatt Morehouse dfsan_label optlen_label, dfsan_label *ret_label) { 20054eedc2e3SMatt Morehouse int ret = getsockopt(sockfd, level, optname, optval, optlen); 20064eedc2e3SMatt Morehouse if (ret != -1 && optval && optlen) { 20074eedc2e3SMatt Morehouse dfsan_set_label(0, optlen, sizeof(*optlen)); 20084eedc2e3SMatt Morehouse dfsan_set_label(0, optval, *optlen); 20094eedc2e3SMatt Morehouse } 20104eedc2e3SMatt Morehouse *ret_label = 0; 20114eedc2e3SMatt Morehouse return ret; 20124eedc2e3SMatt Morehouse } 20134eedc2e3SMatt Morehouse 201491516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt( 201591516925SJianzhou Zhao int sockfd, int level, int optname, void *optval, socklen_t *optlen, 201691516925SJianzhou Zhao dfsan_label sockfd_label, dfsan_label level_label, 201791516925SJianzhou Zhao dfsan_label optname_label, dfsan_label optval_label, 201891516925SJianzhou Zhao dfsan_label optlen_label, dfsan_label *ret_label, 201991516925SJianzhou Zhao dfsan_origin sockfd_origin, dfsan_origin level_origin, 202091516925SJianzhou Zhao dfsan_origin optname_origin, dfsan_origin optval_origin, 202191516925SJianzhou Zhao dfsan_origin optlen_origin, dfsan_origin *ret_origin) { 202291516925SJianzhou Zhao return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label, 202391516925SJianzhou Zhao level_label, optname_label, optval_label, 202491516925SJianzhou Zhao optlen_label, ret_label); 202591516925SJianzhou Zhao } 202691516925SJianzhou Zhao 20278a874a42SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname( 20288a874a42SMatt Morehouse int sockfd, struct sockaddr *addr, socklen_t *addrlen, 20298a874a42SMatt Morehouse dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 20308a874a42SMatt Morehouse dfsan_label *ret_label) { 20318a874a42SMatt Morehouse socklen_t origlen = addrlen ? *addrlen : 0; 20328a874a42SMatt Morehouse int ret = getsockname(sockfd, addr, addrlen); 20338a874a42SMatt Morehouse if (ret != -1 && addr && addrlen) { 20348a874a42SMatt Morehouse socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen; 20358a874a42SMatt Morehouse dfsan_set_label(0, addrlen, sizeof(*addrlen)); 20368a874a42SMatt Morehouse dfsan_set_label(0, addr, written_bytes); 20378a874a42SMatt Morehouse } 20388a874a42SMatt Morehouse *ret_label = 0; 20398a874a42SMatt Morehouse return ret; 20408a874a42SMatt Morehouse } 20418a874a42SMatt Morehouse 204291516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname( 204391516925SJianzhou Zhao int sockfd, struct sockaddr *addr, socklen_t *addrlen, 204491516925SJianzhou Zhao dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 204591516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin sockfd_origin, 204691516925SJianzhou Zhao dfsan_origin addr_origin, dfsan_origin addrlen_origin, 204791516925SJianzhou Zhao dfsan_origin *ret_origin) { 204891516925SJianzhou Zhao return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label, 204991516925SJianzhou Zhao addrlen_label, ret_label); 205091516925SJianzhou Zhao } 205191516925SJianzhou Zhao 2052fa4bd4b3SMatt Morehouse SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername( 2053fa4bd4b3SMatt Morehouse int sockfd, struct sockaddr *addr, socklen_t *addrlen, 2054fa4bd4b3SMatt Morehouse dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 2055fa4bd4b3SMatt Morehouse dfsan_label *ret_label) { 2056fa4bd4b3SMatt Morehouse socklen_t origlen = addrlen ? *addrlen : 0; 2057fa4bd4b3SMatt Morehouse int ret = getpeername(sockfd, addr, addrlen); 2058fa4bd4b3SMatt Morehouse if (ret != -1 && addr && addrlen) { 2059fa4bd4b3SMatt Morehouse socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen; 2060fa4bd4b3SMatt Morehouse dfsan_set_label(0, addrlen, sizeof(*addrlen)); 2061fa4bd4b3SMatt Morehouse dfsan_set_label(0, addr, written_bytes); 2062fa4bd4b3SMatt Morehouse } 2063fa4bd4b3SMatt Morehouse *ret_label = 0; 2064fa4bd4b3SMatt Morehouse return ret; 2065fa4bd4b3SMatt Morehouse } 2066fa4bd4b3SMatt Morehouse 206791516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername( 206891516925SJianzhou Zhao int sockfd, struct sockaddr *addr, socklen_t *addrlen, 206991516925SJianzhou Zhao dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, 207091516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin sockfd_origin, 207191516925SJianzhou Zhao dfsan_origin addr_origin, dfsan_origin addrlen_origin, 207291516925SJianzhou Zhao dfsan_origin *ret_origin) { 207391516925SJianzhou Zhao return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label, 207491516925SJianzhou Zhao addrlen_label, ret_label); 207591516925SJianzhou Zhao } 207691516925SJianzhou Zhao 2077dbf8c00bSAndrew Browne // Type of the function passed to dfsan_set_write_callback. 2078dbf8c00bSAndrew Browne typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count); 20794e67ae7bSJianzhou Zhao 2080a9aa8137SNico Weber // Calls to dfsan_set_write_callback() set the values in this struct. 2081a9aa8137SNico Weber // Calls to the custom version of write() read (and invoke) them. 2082a9aa8137SNico Weber static struct { 2083dbf8c00bSAndrew Browne write_dfsan_callback_t write_callback = nullptr; 2084a9aa8137SNico Weber } write_callback_info; 2085a9aa8137SNico Weber 2086dbf8c00bSAndrew Browne SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback( 2087dbf8c00bSAndrew Browne write_dfsan_callback_t write_callback, dfsan_label write_callback_label, 2088a9aa8137SNico Weber dfsan_label *ret_label) { 2089a9aa8137SNico Weber write_callback_info.write_callback = write_callback; 2090a9aa8137SNico Weber } 2091a9aa8137SNico Weber 20924e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback( 2093dbf8c00bSAndrew Browne write_dfsan_callback_t write_callback, dfsan_label write_callback_label, 2094dbf8c00bSAndrew Browne dfsan_label *ret_label, dfsan_origin write_callback_origin, 2095dbf8c00bSAndrew Browne dfsan_origin *ret_origin) { 2096dbf8c00bSAndrew Browne write_callback_info.write_callback = write_callback; 2097dbf8c00bSAndrew Browne } 2098dbf8c00bSAndrew Browne 2099dbf8c00bSAndrew Browne static inline void setup_tls_args_for_write_callback( 2100dbf8c00bSAndrew Browne dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, 2101dbf8c00bSAndrew Browne bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin, 2102dbf8c00bSAndrew Browne dfsan_origin count_origin) { 2103dbf8c00bSAndrew Browne // The callback code will expect argument shadow labels in the args TLS, 2104dbf8c00bSAndrew Browne // and origin labels in the origin args TLS. 2105dbf8c00bSAndrew Browne // Previously this was done by a trampoline, but we want to remove this: 2106dbf8c00bSAndrew Browne // https://github.com/llvm/llvm-project/issues/54172 2107dbf8c00bSAndrew Browne // 2108dbf8c00bSAndrew Browne // Instead, this code is manually setting up the args TLS data. 2109dbf8c00bSAndrew Browne // 2110dbf8c00bSAndrew Browne // The offsets used need to correspond with the instrumentation code, 2111dbf8c00bSAndrew Browne // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp 2112dbf8c00bSAndrew Browne // DFSanFunction::getShadowForTLSArgument. 2113dbf8c00bSAndrew Browne // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684 2114dbf8c00bSAndrew Browne // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125 2115dbf8c00bSAndrew Browne // 2116dbf8c00bSAndrew Browne // Here the arguments are all primitives, but it can be more complex 2117dbf8c00bSAndrew Browne // to compute offsets for array/aggregate type arguments. 2118dbf8c00bSAndrew Browne // 2119dbf8c00bSAndrew Browne // TODO(browneee): Consider a builtin to improve maintainabliity. 2120dbf8c00bSAndrew Browne // With a builtin, we would provide the argument labels via builtin, 2121dbf8c00bSAndrew Browne // and the builtin would reuse parts of the instrumentation code to ensure 2122dbf8c00bSAndrew Browne // that this code and the instrumentation can never be out of sync. 2123dbf8c00bSAndrew Browne // Note: Currently DFSan instrumentation does not run on this code, so 2124dbf8c00bSAndrew Browne // the builtin may need to be handled outside DFSan instrumentation. 2125dbf8c00bSAndrew Browne dfsan_set_arg_tls(0, fd_label); 2126dbf8c00bSAndrew Browne dfsan_set_arg_tls(1, buf_label); 2127dbf8c00bSAndrew Browne dfsan_set_arg_tls(2, count_label); 2128dbf8c00bSAndrew Browne if (origins) { 2129dbf8c00bSAndrew Browne dfsan_set_arg_origin_tls(0, fd_origin); 2130dbf8c00bSAndrew Browne dfsan_set_arg_origin_tls(1, buf_origin); 2131dbf8c00bSAndrew Browne dfsan_set_arg_origin_tls(2, count_origin); 2132dbf8c00bSAndrew Browne } 21334e67ae7bSJianzhou Zhao } 21344e67ae7bSJianzhou Zhao 2135a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE int 2136a9aa8137SNico Weber __dfsw_write(int fd, const void *buf, size_t count, 2137a9aa8137SNico Weber dfsan_label fd_label, dfsan_label buf_label, 2138a9aa8137SNico Weber dfsan_label count_label, dfsan_label *ret_label) { 2139a9aa8137SNico Weber if (write_callback_info.write_callback) { 2140dbf8c00bSAndrew Browne setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false, 2141dbf8c00bSAndrew Browne 0, 0, 0); 2142dbf8c00bSAndrew Browne write_callback_info.write_callback(fd, buf, count); 2143a9aa8137SNico Weber } 2144a9aa8137SNico Weber 2145a9aa8137SNico Weber *ret_label = 0; 2146a9aa8137SNico Weber return write(fd, buf, count); 2147a9aa8137SNico Weber } 21484e67ae7bSJianzhou Zhao 21494e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write( 21504e67ae7bSJianzhou Zhao int fd, const void *buf, size_t count, dfsan_label fd_label, 21514e67ae7bSJianzhou Zhao dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, 21524e67ae7bSJianzhou Zhao dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, 21534e67ae7bSJianzhou Zhao dfsan_origin *ret_origin) { 2154dbf8c00bSAndrew Browne if (write_callback_info.write_callback) { 2155dbf8c00bSAndrew Browne setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true, 2156dbf8c00bSAndrew Browne fd_origin, buf_origin, count_origin); 2157dbf8c00bSAndrew Browne write_callback_info.write_callback(fd, buf, count); 21584e67ae7bSJianzhou Zhao } 21594e67ae7bSJianzhou Zhao 21604e67ae7bSJianzhou Zhao *ret_label = 0; 21614e67ae7bSJianzhou Zhao return write(fd, buf, count); 21624e67ae7bSJianzhou Zhao } 2163a9aa8137SNico Weber } // namespace __dfsan 2164a9aa8137SNico Weber 2165a9aa8137SNico Weber // Type used to extract a dfsan_label with va_arg() 2166a9aa8137SNico Weber typedef int dfsan_label_va; 2167a9aa8137SNico Weber 2168a9aa8137SNico Weber // Formats a chunk either a constant string or a single format directive (e.g., 2169a9aa8137SNico Weber // '%.3f'). 2170a9aa8137SNico Weber struct Formatter { 2171a9aa8137SNico Weber Formatter(char *str_, const char *fmt_, size_t size_) 21728dbcf8ebSTomasz Kuchta : str(str_), 21738dbcf8ebSTomasz Kuchta str_off(0), 21748dbcf8ebSTomasz Kuchta size(size_), 21758dbcf8ebSTomasz Kuchta fmt_start(fmt_), 21768dbcf8ebSTomasz Kuchta fmt_cur(fmt_), 21778dbcf8ebSTomasz Kuchta width(-1), 2178368d7493SAndrew Browne num_scanned(-1), 2179368d7493SAndrew Browne skip(false) {} 2180a9aa8137SNico Weber 2181a9aa8137SNico Weber int format() { 2182a9aa8137SNico Weber char *tmp_fmt = build_format_string(); 2183a9aa8137SNico Weber int retval = 2184a9aa8137SNico Weber snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt, 2185a9aa8137SNico Weber 0 /* used only to avoid warnings */); 2186a9aa8137SNico Weber free(tmp_fmt); 2187a9aa8137SNico Weber return retval; 2188a9aa8137SNico Weber } 2189a9aa8137SNico Weber 2190a9aa8137SNico Weber template <typename T> int format(T arg) { 2191a9aa8137SNico Weber char *tmp_fmt = build_format_string(); 2192a9aa8137SNico Weber int retval; 2193a9aa8137SNico Weber if (width >= 0) { 2194a9aa8137SNico Weber retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 2195a9aa8137SNico Weber tmp_fmt, width, arg); 2196a9aa8137SNico Weber } else { 2197a9aa8137SNico Weber retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 2198a9aa8137SNico Weber tmp_fmt, arg); 2199a9aa8137SNico Weber } 2200a9aa8137SNico Weber free(tmp_fmt); 2201a9aa8137SNico Weber return retval; 2202a9aa8137SNico Weber } 2203a9aa8137SNico Weber 2204cd94fa7eSAndrew Browne char *build_format_string() { 2205a9aa8137SNico Weber size_t fmt_size = fmt_cur - fmt_start + 1; 2206cd94fa7eSAndrew Browne char *new_fmt = (char *)malloc(fmt_size + 1); 2207a9aa8137SNico Weber assert(new_fmt); 2208a9aa8137SNico Weber internal_memcpy(new_fmt, fmt_start, fmt_size); 2209a9aa8137SNico Weber new_fmt[fmt_size] = '\0'; 2210a9aa8137SNico Weber return new_fmt; 2211a9aa8137SNico Weber } 2212a9aa8137SNico Weber 2213a9aa8137SNico Weber char *str_cur() { return str + str_off; } 2214a9aa8137SNico Weber 2215a9aa8137SNico Weber size_t num_written_bytes(int retval) { 2216a9aa8137SNico Weber if (retval < 0) { 2217a9aa8137SNico Weber return 0; 2218a9aa8137SNico Weber } 2219a9aa8137SNico Weber 2220a9aa8137SNico Weber size_t num_avail = str_off < size ? size - str_off : 0; 2221a9aa8137SNico Weber if (num_avail == 0) { 2222a9aa8137SNico Weber return 0; 2223a9aa8137SNico Weber } 2224a9aa8137SNico Weber 2225a9aa8137SNico Weber size_t num_written = retval; 2226a9aa8137SNico Weber // A return value of {v,}snprintf of size or more means that the output was 2227a9aa8137SNico Weber // truncated. 2228a9aa8137SNico Weber if (num_written >= num_avail) { 2229a9aa8137SNico Weber num_written -= num_avail; 2230a9aa8137SNico Weber } 2231a9aa8137SNico Weber 2232a9aa8137SNico Weber return num_written; 2233a9aa8137SNico Weber } 2234a9aa8137SNico Weber 2235a9aa8137SNico Weber char *str; 2236a9aa8137SNico Weber size_t str_off; 2237a9aa8137SNico Weber size_t size; 2238a9aa8137SNico Weber const char *fmt_start; 2239a9aa8137SNico Weber const char *fmt_cur; 2240a9aa8137SNico Weber int width; 22418dbcf8ebSTomasz Kuchta int num_scanned; 2242368d7493SAndrew Browne bool skip; 2243a9aa8137SNico Weber }; 2244a9aa8137SNico Weber 2245a9aa8137SNico Weber // Formats the input and propagates the input labels to the output. The output 2246a9aa8137SNico Weber // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and 2247a9aa8137SNico Weber // 'ap' are the format string and the list of arguments for formatting. Returns 2248a9aa8137SNico Weber // the return value vsnprintf would return. 2249a9aa8137SNico Weber // 2250a9aa8137SNico Weber // The function tokenizes the format string in chunks representing either a 2251a9aa8137SNico Weber // constant string or a single format directive (e.g., '%.3f') and formats each 2252a9aa8137SNico Weber // chunk independently into the output string. This approach allows to figure 2253a9aa8137SNico Weber // out which bytes of the output string depends on which argument and thus to 2254a9aa8137SNico Weber // propagate labels more precisely. 2255a9aa8137SNico Weber // 2256a9aa8137SNico Weber // WARNING: This implementation does not support conversion specifiers with 2257a9aa8137SNico Weber // positional arguments. 2258a9aa8137SNico Weber static int format_buffer(char *str, size_t size, const char *fmt, 2259a9aa8137SNico Weber dfsan_label *va_labels, dfsan_label *ret_label, 226091516925SJianzhou Zhao dfsan_origin *va_origins, dfsan_origin *ret_origin, 2261a9aa8137SNico Weber va_list ap) { 2262a9aa8137SNico Weber Formatter formatter(str, fmt, size); 2263a9aa8137SNico Weber 2264a9aa8137SNico Weber while (*formatter.fmt_cur) { 2265a9aa8137SNico Weber formatter.fmt_start = formatter.fmt_cur; 2266a9aa8137SNico Weber formatter.width = -1; 2267a9aa8137SNico Weber int retval = 0; 2268a9aa8137SNico Weber 2269a9aa8137SNico Weber if (*formatter.fmt_cur != '%') { 2270a9aa8137SNico Weber // Ordinary character. Consume all the characters until a '%' or the end 2271a9aa8137SNico Weber // of the string. 2272a9aa8137SNico Weber for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%'; 2273a9aa8137SNico Weber ++formatter.fmt_cur) {} 2274a9aa8137SNico Weber retval = formatter.format(); 2275a9aa8137SNico Weber dfsan_set_label(0, formatter.str_cur(), 2276a9aa8137SNico Weber formatter.num_written_bytes(retval)); 2277a9aa8137SNico Weber } else { 2278a9aa8137SNico Weber // Conversion directive. Consume all the characters until a conversion 2279a9aa8137SNico Weber // specifier or the end of the string. 2280a9aa8137SNico Weber bool end_fmt = false; 2281a9aa8137SNico Weber for (; *formatter.fmt_cur && !end_fmt; ) { 2282a9aa8137SNico Weber switch (*++formatter.fmt_cur) { 2283a9aa8137SNico Weber case 'd': 2284a9aa8137SNico Weber case 'i': 2285a9aa8137SNico Weber case 'o': 2286a9aa8137SNico Weber case 'u': 2287a9aa8137SNico Weber case 'x': 2288a9aa8137SNico Weber case 'X': 2289a9aa8137SNico Weber switch (*(formatter.fmt_cur - 1)) { 2290a9aa8137SNico Weber case 'h': 2291a9aa8137SNico Weber // Also covers the 'hh' case (since the size of the arg is still 2292a9aa8137SNico Weber // an int). 2293a9aa8137SNico Weber retval = formatter.format(va_arg(ap, int)); 2294a9aa8137SNico Weber break; 2295a9aa8137SNico Weber case 'l': 2296a9aa8137SNico Weber if (formatter.fmt_cur - formatter.fmt_start >= 2 && 2297a9aa8137SNico Weber *(formatter.fmt_cur - 2) == 'l') { 2298a9aa8137SNico Weber retval = formatter.format(va_arg(ap, long long int)); 2299a9aa8137SNico Weber } else { 2300a9aa8137SNico Weber retval = formatter.format(va_arg(ap, long int)); 2301a9aa8137SNico Weber } 2302a9aa8137SNico Weber break; 2303a9aa8137SNico Weber case 'q': 2304a9aa8137SNico Weber retval = formatter.format(va_arg(ap, long long int)); 2305a9aa8137SNico Weber break; 2306a9aa8137SNico Weber case 'j': 2307a9aa8137SNico Weber retval = formatter.format(va_arg(ap, intmax_t)); 2308a9aa8137SNico Weber break; 2309a9aa8137SNico Weber case 'z': 2310a9aa8137SNico Weber case 't': 2311a9aa8137SNico Weber retval = formatter.format(va_arg(ap, size_t)); 2312a9aa8137SNico Weber break; 2313a9aa8137SNico Weber default: 2314a9aa8137SNico Weber retval = formatter.format(va_arg(ap, int)); 2315a9aa8137SNico Weber } 231691516925SJianzhou Zhao if (va_origins == nullptr) 2317a9aa8137SNico Weber dfsan_set_label(*va_labels++, formatter.str_cur(), 2318a9aa8137SNico Weber formatter.num_written_bytes(retval)); 231991516925SJianzhou Zhao else 232091516925SJianzhou Zhao dfsan_set_label_origin(*va_labels++, *va_origins++, 232191516925SJianzhou Zhao formatter.str_cur(), 232291516925SJianzhou Zhao formatter.num_written_bytes(retval)); 2323a9aa8137SNico Weber end_fmt = true; 2324a9aa8137SNico Weber break; 2325a9aa8137SNico Weber 2326a9aa8137SNico Weber case 'a': 2327a9aa8137SNico Weber case 'A': 2328a9aa8137SNico Weber case 'e': 2329a9aa8137SNico Weber case 'E': 2330a9aa8137SNico Weber case 'f': 2331a9aa8137SNico Weber case 'F': 2332a9aa8137SNico Weber case 'g': 2333a9aa8137SNico Weber case 'G': 2334a9aa8137SNico Weber if (*(formatter.fmt_cur - 1) == 'L') { 2335a9aa8137SNico Weber retval = formatter.format(va_arg(ap, long double)); 2336a9aa8137SNico Weber } else { 2337a9aa8137SNico Weber retval = formatter.format(va_arg(ap, double)); 2338a9aa8137SNico Weber } 233991516925SJianzhou Zhao if (va_origins == nullptr) 2340a9aa8137SNico Weber dfsan_set_label(*va_labels++, formatter.str_cur(), 2341a9aa8137SNico Weber formatter.num_written_bytes(retval)); 234291516925SJianzhou Zhao else 234391516925SJianzhou Zhao dfsan_set_label_origin(*va_labels++, *va_origins++, 234491516925SJianzhou Zhao formatter.str_cur(), 234591516925SJianzhou Zhao formatter.num_written_bytes(retval)); 2346a9aa8137SNico Weber end_fmt = true; 2347a9aa8137SNico Weber break; 2348a9aa8137SNico Weber 2349a9aa8137SNico Weber case 'c': 2350a9aa8137SNico Weber retval = formatter.format(va_arg(ap, int)); 235191516925SJianzhou Zhao if (va_origins == nullptr) 2352a9aa8137SNico Weber dfsan_set_label(*va_labels++, formatter.str_cur(), 2353a9aa8137SNico Weber formatter.num_written_bytes(retval)); 235491516925SJianzhou Zhao else 235591516925SJianzhou Zhao dfsan_set_label_origin(*va_labels++, *va_origins++, 235691516925SJianzhou Zhao formatter.str_cur(), 235791516925SJianzhou Zhao formatter.num_written_bytes(retval)); 2358a9aa8137SNico Weber end_fmt = true; 2359a9aa8137SNico Weber break; 2360a9aa8137SNico Weber 2361a9aa8137SNico Weber case 's': { 2362a9aa8137SNico Weber char *arg = va_arg(ap, char *); 2363a9aa8137SNico Weber retval = formatter.format(arg); 236491516925SJianzhou Zhao if (va_origins) { 236591516925SJianzhou Zhao va_origins++; 236691516925SJianzhou Zhao dfsan_mem_origin_transfer(formatter.str_cur(), arg, 236791516925SJianzhou Zhao formatter.num_written_bytes(retval)); 236891516925SJianzhou Zhao } 2369a9aa8137SNico Weber va_labels++; 237032167bfeSAndrew Browne dfsan_mem_shadow_transfer(formatter.str_cur(), arg, 2371a9aa8137SNico Weber formatter.num_written_bytes(retval)); 2372a9aa8137SNico Weber end_fmt = true; 2373a9aa8137SNico Weber break; 2374a9aa8137SNico Weber } 2375a9aa8137SNico Weber 2376a9aa8137SNico Weber case 'p': 2377a9aa8137SNico Weber retval = formatter.format(va_arg(ap, void *)); 237891516925SJianzhou Zhao if (va_origins == nullptr) 2379a9aa8137SNico Weber dfsan_set_label(*va_labels++, formatter.str_cur(), 2380a9aa8137SNico Weber formatter.num_written_bytes(retval)); 238191516925SJianzhou Zhao else 238291516925SJianzhou Zhao dfsan_set_label_origin(*va_labels++, *va_origins++, 238391516925SJianzhou Zhao formatter.str_cur(), 238491516925SJianzhou Zhao formatter.num_written_bytes(retval)); 2385a9aa8137SNico Weber end_fmt = true; 2386a9aa8137SNico Weber break; 2387a9aa8137SNico Weber 2388a9aa8137SNico Weber case 'n': { 2389a9aa8137SNico Weber int *ptr = va_arg(ap, int *); 2390a9aa8137SNico Weber *ptr = (int)formatter.str_off; 2391a9aa8137SNico Weber va_labels++; 239291516925SJianzhou Zhao if (va_origins) 239391516925SJianzhou Zhao va_origins++; 2394a9aa8137SNico Weber dfsan_set_label(0, ptr, sizeof(ptr)); 2395a9aa8137SNico Weber end_fmt = true; 2396a9aa8137SNico Weber break; 2397a9aa8137SNico Weber } 2398a9aa8137SNico Weber 2399a9aa8137SNico Weber case '%': 2400a9aa8137SNico Weber retval = formatter.format(); 2401a9aa8137SNico Weber dfsan_set_label(0, formatter.str_cur(), 2402a9aa8137SNico Weber formatter.num_written_bytes(retval)); 2403a9aa8137SNico Weber end_fmt = true; 2404a9aa8137SNico Weber break; 2405a9aa8137SNico Weber 2406a9aa8137SNico Weber case '*': 2407a9aa8137SNico Weber formatter.width = va_arg(ap, int); 2408a9aa8137SNico Weber va_labels++; 240991516925SJianzhou Zhao if (va_origins) 241091516925SJianzhou Zhao va_origins++; 2411a9aa8137SNico Weber break; 2412a9aa8137SNico Weber 2413a9aa8137SNico Weber default: 2414a9aa8137SNico Weber break; 2415a9aa8137SNico Weber } 2416a9aa8137SNico Weber } 2417a9aa8137SNico Weber } 2418a9aa8137SNico Weber 2419a9aa8137SNico Weber if (retval < 0) { 2420a9aa8137SNico Weber return retval; 2421a9aa8137SNico Weber } 2422a9aa8137SNico Weber 2423a9aa8137SNico Weber formatter.fmt_cur++; 2424a9aa8137SNico Weber formatter.str_off += retval; 2425a9aa8137SNico Weber } 2426a9aa8137SNico Weber 2427a9aa8137SNico Weber *ret_label = 0; 242891516925SJianzhou Zhao if (ret_origin) 242991516925SJianzhou Zhao *ret_origin = 0; 2430a9aa8137SNico Weber 2431a9aa8137SNico Weber // Number of bytes written in total. 2432a9aa8137SNico Weber return formatter.str_off; 2433a9aa8137SNico Weber } 2434a9aa8137SNico Weber 2435cd94fa7eSAndrew Browne // Scans a chunk either a constant string or a single format directive (e.g., 2436cd94fa7eSAndrew Browne // '%.3f'). 2437cd94fa7eSAndrew Browne struct Scanner { 2438cd94fa7eSAndrew Browne Scanner(char *str_, const char *fmt_, size_t size_) 2439cd94fa7eSAndrew Browne : str(str_), 2440cd94fa7eSAndrew Browne str_off(0), 2441cd94fa7eSAndrew Browne size(size_), 2442cd94fa7eSAndrew Browne fmt_start(fmt_), 2443cd94fa7eSAndrew Browne fmt_cur(fmt_), 2444cd94fa7eSAndrew Browne width(-1), 2445cd94fa7eSAndrew Browne num_scanned(0), 2446cd94fa7eSAndrew Browne skip(false) {} 2447cd94fa7eSAndrew Browne 2448cd94fa7eSAndrew Browne // Consumes a chunk of ordinary characters. 2449cd94fa7eSAndrew Browne // Returns number of matching ordinary characters. 2450cd94fa7eSAndrew Browne // Returns -1 if the match failed. 2451cd94fa7eSAndrew Browne // In format strings, a space will match multiple spaces. 2452cd94fa7eSAndrew Browne int check_match_ordinary() { 2453cd94fa7eSAndrew Browne char *tmp_fmt = build_format_string_with_n(); 2454cd94fa7eSAndrew Browne int read_count = -1; 2455cd94fa7eSAndrew Browne sscanf(str + str_off, tmp_fmt, &read_count); 2456cd94fa7eSAndrew Browne free(tmp_fmt); 2457cd94fa7eSAndrew Browne if (read_count > 0) { 2458cd94fa7eSAndrew Browne str_off += read_count; 2459cd94fa7eSAndrew Browne } 2460cd94fa7eSAndrew Browne return read_count; 2461cd94fa7eSAndrew Browne } 2462cd94fa7eSAndrew Browne 2463cd94fa7eSAndrew Browne int scan() { 2464cd94fa7eSAndrew Browne char *tmp_fmt = build_format_string_with_n(); 2465cd94fa7eSAndrew Browne int read_count = 0; 2466cd94fa7eSAndrew Browne int retval = sscanf(str + str_off, tmp_fmt, &read_count); 2467cd94fa7eSAndrew Browne free(tmp_fmt); 2468cd94fa7eSAndrew Browne if (retval > 0) { 2469cd94fa7eSAndrew Browne num_scanned += retval; 2470cd94fa7eSAndrew Browne } 2471cd94fa7eSAndrew Browne return read_count; 2472cd94fa7eSAndrew Browne } 2473cd94fa7eSAndrew Browne 2474cd94fa7eSAndrew Browne template <typename T> 2475cd94fa7eSAndrew Browne int scan(T arg) { 2476cd94fa7eSAndrew Browne char *tmp_fmt = build_format_string_with_n(); 2477cd94fa7eSAndrew Browne int read_count = 0; 2478cd94fa7eSAndrew Browne int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count); 2479cd94fa7eSAndrew Browne free(tmp_fmt); 2480cd94fa7eSAndrew Browne if (retval > 0) { 2481cd94fa7eSAndrew Browne num_scanned += retval; 2482cd94fa7eSAndrew Browne } 2483cd94fa7eSAndrew Browne return read_count; 2484cd94fa7eSAndrew Browne } 2485cd94fa7eSAndrew Browne 2486cd94fa7eSAndrew Browne // Adds %n onto current format string to measure length. 2487cd94fa7eSAndrew Browne char *build_format_string_with_n() { 2488cd94fa7eSAndrew Browne size_t fmt_size = fmt_cur - fmt_start + 1; 2489cd94fa7eSAndrew Browne // +2 for %n, +1 for \0 2490cd94fa7eSAndrew Browne char *new_fmt = (char *)malloc(fmt_size + 2 + 1); 2491cd94fa7eSAndrew Browne assert(new_fmt); 2492cd94fa7eSAndrew Browne internal_memcpy(new_fmt, fmt_start, fmt_size); 2493cd94fa7eSAndrew Browne new_fmt[fmt_size] = '%'; 2494cd94fa7eSAndrew Browne new_fmt[fmt_size + 1] = 'n'; 2495cd94fa7eSAndrew Browne new_fmt[fmt_size + 2] = '\0'; 2496cd94fa7eSAndrew Browne return new_fmt; 2497cd94fa7eSAndrew Browne } 2498cd94fa7eSAndrew Browne 2499cd94fa7eSAndrew Browne char *str_cur() { return str + str_off; } 2500cd94fa7eSAndrew Browne 2501cd94fa7eSAndrew Browne size_t num_written_bytes(int retval) { 2502cd94fa7eSAndrew Browne if (retval < 0) { 2503cd94fa7eSAndrew Browne return 0; 2504cd94fa7eSAndrew Browne } 2505cd94fa7eSAndrew Browne 2506cd94fa7eSAndrew Browne size_t num_avail = str_off < size ? size - str_off : 0; 2507cd94fa7eSAndrew Browne if (num_avail == 0) { 2508cd94fa7eSAndrew Browne return 0; 2509cd94fa7eSAndrew Browne } 2510cd94fa7eSAndrew Browne 2511cd94fa7eSAndrew Browne size_t num_written = retval; 2512cd94fa7eSAndrew Browne // A return value of {v,}snprintf of size or more means that the output was 2513cd94fa7eSAndrew Browne // truncated. 2514cd94fa7eSAndrew Browne if (num_written >= num_avail) { 2515cd94fa7eSAndrew Browne num_written -= num_avail; 2516cd94fa7eSAndrew Browne } 2517cd94fa7eSAndrew Browne 2518cd94fa7eSAndrew Browne return num_written; 2519cd94fa7eSAndrew Browne } 2520cd94fa7eSAndrew Browne 2521cd94fa7eSAndrew Browne char *str; 2522cd94fa7eSAndrew Browne size_t str_off; 2523cd94fa7eSAndrew Browne size_t size; 2524cd94fa7eSAndrew Browne const char *fmt_start; 2525cd94fa7eSAndrew Browne const char *fmt_cur; 2526cd94fa7eSAndrew Browne int width; 2527cd94fa7eSAndrew Browne int num_scanned; 2528cd94fa7eSAndrew Browne bool skip; 2529cd94fa7eSAndrew Browne }; 2530cd94fa7eSAndrew Browne 25318dbcf8ebSTomasz Kuchta // This function is an inverse of format_buffer: we take the input buffer, 25328dbcf8ebSTomasz Kuchta // scan it in search for format strings and store the results in the varargs. 25338dbcf8ebSTomasz Kuchta // The labels are propagated from the input buffer to the varargs. 25348dbcf8ebSTomasz Kuchta static int scan_buffer(char *str, size_t size, const char *fmt, 25358dbcf8ebSTomasz Kuchta dfsan_label *va_labels, dfsan_label *ret_label, 25368dbcf8ebSTomasz Kuchta dfsan_origin *str_origin, dfsan_origin *ret_origin, 25378dbcf8ebSTomasz Kuchta va_list ap) { 2538cd94fa7eSAndrew Browne Scanner scanner(str, fmt, size); 2539cd94fa7eSAndrew Browne while (*scanner.fmt_cur) { 2540cd94fa7eSAndrew Browne scanner.fmt_start = scanner.fmt_cur; 2541cd94fa7eSAndrew Browne scanner.width = -1; 2542cd94fa7eSAndrew Browne scanner.skip = false; 2543368d7493SAndrew Browne int read_count = 0; 25448dbcf8ebSTomasz Kuchta void *dst_ptr = 0; 25458dbcf8ebSTomasz Kuchta size_t write_size = 0; 2546cd94fa7eSAndrew Browne if (*scanner.fmt_cur != '%') { 2547cd94fa7eSAndrew Browne // Ordinary character and spaces. 2548cd94fa7eSAndrew Browne // Consume all the characters until a '%' or the end of the string. 2549cd94fa7eSAndrew Browne for (; *(scanner.fmt_cur + 1) && *(scanner.fmt_cur + 1) != '%'; 2550cd94fa7eSAndrew Browne ++scanner.fmt_cur) { 25518dbcf8ebSTomasz Kuchta } 2552cd94fa7eSAndrew Browne if (scanner.check_match_ordinary() < 0) { 2553cd94fa7eSAndrew Browne // The ordinary characters did not match. 2554cd94fa7eSAndrew Browne break; 2555cd94fa7eSAndrew Browne } 25568dbcf8ebSTomasz Kuchta } else { 25578dbcf8ebSTomasz Kuchta // Conversion directive. Consume all the characters until a conversion 25588dbcf8ebSTomasz Kuchta // specifier or the end of the string. 25598dbcf8ebSTomasz Kuchta bool end_fmt = false; 2560cd94fa7eSAndrew Browne for (; *scanner.fmt_cur && !end_fmt;) { 2561cd94fa7eSAndrew Browne switch (*++scanner.fmt_cur) { 25628dbcf8ebSTomasz Kuchta case 'd': 25638dbcf8ebSTomasz Kuchta case 'i': 25648dbcf8ebSTomasz Kuchta case 'o': 25658dbcf8ebSTomasz Kuchta case 'u': 25668dbcf8ebSTomasz Kuchta case 'x': 25678dbcf8ebSTomasz Kuchta case 'X': 2568cd94fa7eSAndrew Browne if (scanner.skip) { 2569cd94fa7eSAndrew Browne read_count = scanner.scan(); 2570368d7493SAndrew Browne } else { 2571cd94fa7eSAndrew Browne switch (*(scanner.fmt_cur - 1)) { 25728dbcf8ebSTomasz Kuchta case 'h': 2573cd94fa7eSAndrew Browne // Also covers the 'hh' case (since the size of the arg is 2574cd94fa7eSAndrew Browne // still an int). 25758dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, int *); 2576cd94fa7eSAndrew Browne read_count = scanner.scan((int *)dst_ptr); 25778dbcf8ebSTomasz Kuchta write_size = sizeof(int); 25788dbcf8ebSTomasz Kuchta break; 25798dbcf8ebSTomasz Kuchta case 'l': 2580cd94fa7eSAndrew Browne if (scanner.fmt_cur - scanner.fmt_start >= 2 && 2581cd94fa7eSAndrew Browne *(scanner.fmt_cur - 2) == 'l') { 25828dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, long long int *); 2583cd94fa7eSAndrew Browne read_count = scanner.scan((long long int *)dst_ptr); 25848dbcf8ebSTomasz Kuchta write_size = sizeof(long long int); 25858dbcf8ebSTomasz Kuchta } else { 25868dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, long int *); 2587cd94fa7eSAndrew Browne read_count = scanner.scan((long int *)dst_ptr); 25888dbcf8ebSTomasz Kuchta write_size = sizeof(long int); 25898dbcf8ebSTomasz Kuchta } 25908dbcf8ebSTomasz Kuchta break; 25918dbcf8ebSTomasz Kuchta case 'q': 25928dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, long long int *); 2593cd94fa7eSAndrew Browne read_count = scanner.scan((long long int *)dst_ptr); 25948dbcf8ebSTomasz Kuchta write_size = sizeof(long long int); 25958dbcf8ebSTomasz Kuchta break; 25968dbcf8ebSTomasz Kuchta case 'j': 25978dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, intmax_t *); 2598cd94fa7eSAndrew Browne read_count = scanner.scan((intmax_t *)dst_ptr); 25998dbcf8ebSTomasz Kuchta write_size = sizeof(intmax_t); 26008dbcf8ebSTomasz Kuchta break; 26018dbcf8ebSTomasz Kuchta case 'z': 26028dbcf8ebSTomasz Kuchta case 't': 26038dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, size_t *); 2604cd94fa7eSAndrew Browne read_count = scanner.scan((size_t *)dst_ptr); 26058dbcf8ebSTomasz Kuchta write_size = sizeof(size_t); 26068dbcf8ebSTomasz Kuchta break; 26078dbcf8ebSTomasz Kuchta default: 26088dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, int *); 2609cd94fa7eSAndrew Browne read_count = scanner.scan((int *)dst_ptr); 26108dbcf8ebSTomasz Kuchta write_size = sizeof(int); 26118dbcf8ebSTomasz Kuchta } 26128dbcf8ebSTomasz Kuchta // get the label associated with the string at the corresponding 26138dbcf8ebSTomasz Kuchta // place 2614368d7493SAndrew Browne dfsan_label l = dfsan_read_label( 2615cd94fa7eSAndrew Browne scanner.str_cur(), scanner.num_written_bytes(read_count)); 26168dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2617368d7493SAndrew Browne if (str_origin != nullptr) { 26188dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2619cd94fa7eSAndrew Browne size_t scan_count = scanner.num_written_bytes(read_count); 26208dbcf8ebSTomasz Kuchta size_t size = scan_count > write_size ? write_size : scan_count; 2621cd94fa7eSAndrew Browne dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size); 26228dbcf8ebSTomasz Kuchta } 2623368d7493SAndrew Browne } 26248dbcf8ebSTomasz Kuchta end_fmt = true; 26258dbcf8ebSTomasz Kuchta 26268dbcf8ebSTomasz Kuchta break; 26278dbcf8ebSTomasz Kuchta 26288dbcf8ebSTomasz Kuchta case 'a': 26298dbcf8ebSTomasz Kuchta case 'A': 26308dbcf8ebSTomasz Kuchta case 'e': 26318dbcf8ebSTomasz Kuchta case 'E': 26328dbcf8ebSTomasz Kuchta case 'f': 26338dbcf8ebSTomasz Kuchta case 'F': 26348dbcf8ebSTomasz Kuchta case 'g': 26358dbcf8ebSTomasz Kuchta case 'G': 2636cd94fa7eSAndrew Browne if (scanner.skip) { 2637cd94fa7eSAndrew Browne read_count = scanner.scan(); 2638368d7493SAndrew Browne } else { 2639cd94fa7eSAndrew Browne if (*(scanner.fmt_cur - 1) == 'L') { 26408dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, long double *); 2641cd94fa7eSAndrew Browne read_count = scanner.scan((long double *)dst_ptr); 26428dbcf8ebSTomasz Kuchta write_size = sizeof(long double); 2643cd94fa7eSAndrew Browne } else if (*(scanner.fmt_cur - 1) == 'l') { 26448dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, double *); 2645cd94fa7eSAndrew Browne read_count = scanner.scan((double *)dst_ptr); 26468dbcf8ebSTomasz Kuchta write_size = sizeof(double); 26478dbcf8ebSTomasz Kuchta } else { 26488dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, float *); 2649cd94fa7eSAndrew Browne read_count = scanner.scan((float *)dst_ptr); 26508dbcf8ebSTomasz Kuchta write_size = sizeof(float); 26518dbcf8ebSTomasz Kuchta } 2652368d7493SAndrew Browne dfsan_label l = dfsan_read_label( 2653cd94fa7eSAndrew Browne scanner.str_cur(), scanner.num_written_bytes(read_count)); 26548dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2655368d7493SAndrew Browne if (str_origin != nullptr) { 26568dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2657cd94fa7eSAndrew Browne size_t scan_count = scanner.num_written_bytes(read_count); 26588dbcf8ebSTomasz Kuchta size_t size = scan_count > write_size ? write_size : scan_count; 2659cd94fa7eSAndrew Browne dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size); 26608dbcf8ebSTomasz Kuchta } 2661368d7493SAndrew Browne } 26628dbcf8ebSTomasz Kuchta end_fmt = true; 26638dbcf8ebSTomasz Kuchta break; 26648dbcf8ebSTomasz Kuchta 26658dbcf8ebSTomasz Kuchta case 'c': 2666cd94fa7eSAndrew Browne if (scanner.skip) { 2667cd94fa7eSAndrew Browne read_count = scanner.scan(); 2668368d7493SAndrew Browne } else { 26698dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, char *); 2670cd94fa7eSAndrew Browne read_count = scanner.scan((char *)dst_ptr); 26718dbcf8ebSTomasz Kuchta write_size = sizeof(char); 2672368d7493SAndrew Browne dfsan_label l = dfsan_read_label( 2673cd94fa7eSAndrew Browne scanner.str_cur(), scanner.num_written_bytes(read_count)); 26748dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2675368d7493SAndrew Browne if (str_origin != nullptr) { 2676cd94fa7eSAndrew Browne size_t scan_count = scanner.num_written_bytes(read_count); 26778dbcf8ebSTomasz Kuchta size_t size = scan_count > write_size ? write_size : scan_count; 2678cd94fa7eSAndrew Browne dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size); 26798dbcf8ebSTomasz Kuchta } 2680368d7493SAndrew Browne } 26818dbcf8ebSTomasz Kuchta end_fmt = true; 26828dbcf8ebSTomasz Kuchta break; 26838dbcf8ebSTomasz Kuchta 26848dbcf8ebSTomasz Kuchta case 's': { 2685cd94fa7eSAndrew Browne if (scanner.skip) { 2686cd94fa7eSAndrew Browne read_count = scanner.scan(); 2687368d7493SAndrew Browne } else { 26888dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, char *); 2689cd94fa7eSAndrew Browne read_count = scanner.scan((char *)dst_ptr); 2690368d7493SAndrew Browne if (1 == read_count) { 26918dbcf8ebSTomasz Kuchta // special case: we have parsed a single string and we need to 2692368d7493SAndrew Browne // update read_count with the string size 2693368d7493SAndrew Browne read_count = strlen((char *)dst_ptr); 26948dbcf8ebSTomasz Kuchta } 26958dbcf8ebSTomasz Kuchta if (str_origin) 2696cd94fa7eSAndrew Browne dfsan_mem_origin_transfer( 2697cd94fa7eSAndrew Browne dst_ptr, scanner.str_cur(), 2698cd94fa7eSAndrew Browne scanner.num_written_bytes(read_count)); 26998dbcf8ebSTomasz Kuchta va_labels++; 2700cd94fa7eSAndrew Browne dfsan_mem_shadow_transfer(dst_ptr, scanner.str_cur(), 2701cd94fa7eSAndrew Browne scanner.num_written_bytes(read_count)); 2702368d7493SAndrew Browne } 27038dbcf8ebSTomasz Kuchta end_fmt = true; 27048dbcf8ebSTomasz Kuchta break; 27058dbcf8ebSTomasz Kuchta } 27068dbcf8ebSTomasz Kuchta 27078dbcf8ebSTomasz Kuchta case 'p': 2708cd94fa7eSAndrew Browne if (scanner.skip) { 2709cd94fa7eSAndrew Browne read_count = scanner.scan(); 2710368d7493SAndrew Browne } else { 27118dbcf8ebSTomasz Kuchta dst_ptr = va_arg(ap, void *); 2712368d7493SAndrew Browne read_count = 2713cd94fa7eSAndrew Browne scanner.scan((int *)dst_ptr); // note: changing void* to int* 27148dbcf8ebSTomasz Kuchta // since we need to call sizeof 27158dbcf8ebSTomasz Kuchta write_size = sizeof(int); 27168dbcf8ebSTomasz Kuchta 2717368d7493SAndrew Browne dfsan_label l = dfsan_read_label( 2718cd94fa7eSAndrew Browne scanner.str_cur(), scanner.num_written_bytes(read_count)); 27198dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2720368d7493SAndrew Browne if (str_origin != nullptr) { 27218dbcf8ebSTomasz Kuchta dfsan_set_label(l, dst_ptr, write_size); 2722cd94fa7eSAndrew Browne size_t scan_count = scanner.num_written_bytes(read_count); 27238dbcf8ebSTomasz Kuchta size_t size = scan_count > write_size ? write_size : scan_count; 2724cd94fa7eSAndrew Browne dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size); 27258dbcf8ebSTomasz Kuchta } 2726368d7493SAndrew Browne } 27278dbcf8ebSTomasz Kuchta end_fmt = true; 27288dbcf8ebSTomasz Kuchta break; 27298dbcf8ebSTomasz Kuchta 27308dbcf8ebSTomasz Kuchta case 'n': { 2731cd94fa7eSAndrew Browne if (!scanner.skip) { 27328dbcf8ebSTomasz Kuchta int *ptr = va_arg(ap, int *); 2733cd94fa7eSAndrew Browne *ptr = (int)scanner.str_off; 2734368d7493SAndrew Browne *va_labels++ = 0; 27358dbcf8ebSTomasz Kuchta dfsan_set_label(0, ptr, sizeof(*ptr)); 2736368d7493SAndrew Browne if (str_origin != nullptr) 2737368d7493SAndrew Browne *str_origin++ = 0; 2738368d7493SAndrew Browne } 27398dbcf8ebSTomasz Kuchta end_fmt = true; 27408dbcf8ebSTomasz Kuchta break; 27418dbcf8ebSTomasz Kuchta } 27428dbcf8ebSTomasz Kuchta 27438dbcf8ebSTomasz Kuchta case '%': 2744cd94fa7eSAndrew Browne read_count = scanner.scan(); 27458dbcf8ebSTomasz Kuchta end_fmt = true; 27468dbcf8ebSTomasz Kuchta break; 27478dbcf8ebSTomasz Kuchta 27488dbcf8ebSTomasz Kuchta case '*': 2749cd94fa7eSAndrew Browne scanner.skip = true; 27508dbcf8ebSTomasz Kuchta break; 27518dbcf8ebSTomasz Kuchta 27528dbcf8ebSTomasz Kuchta default: 27538dbcf8ebSTomasz Kuchta break; 27548dbcf8ebSTomasz Kuchta } 27558dbcf8ebSTomasz Kuchta } 27568dbcf8ebSTomasz Kuchta } 27578dbcf8ebSTomasz Kuchta 2758368d7493SAndrew Browne if (read_count < 0) { 2759368d7493SAndrew Browne // There was an error. 2760368d7493SAndrew Browne return read_count; 27618dbcf8ebSTomasz Kuchta } 27628dbcf8ebSTomasz Kuchta 2763cd94fa7eSAndrew Browne scanner.fmt_cur++; 2764cd94fa7eSAndrew Browne scanner.str_off += read_count; 27658dbcf8ebSTomasz Kuchta } 27668dbcf8ebSTomasz Kuchta 27671438544eSJie Fu (void)va_labels; // Silence unused-but-set-parameter warning 27688dbcf8ebSTomasz Kuchta *ret_label = 0; 27698dbcf8ebSTomasz Kuchta if (ret_origin) 27708dbcf8ebSTomasz Kuchta *ret_origin = 0; 27718dbcf8ebSTomasz Kuchta 27728dbcf8ebSTomasz Kuchta // Number of items scanned in total. 2773cd94fa7eSAndrew Browne return scanner.num_scanned; 27748dbcf8ebSTomasz Kuchta } 27758dbcf8ebSTomasz Kuchta 2776a9aa8137SNico Weber extern "C" { 2777a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 2778a9aa8137SNico Weber int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label, 2779a9aa8137SNico Weber dfsan_label format_label, dfsan_label *va_labels, 2780a9aa8137SNico Weber dfsan_label *ret_label, ...) { 2781a9aa8137SNico Weber va_list ap; 2782a9aa8137SNico Weber va_start(ap, ret_label); 27838dbcf8ebSTomasz Kuchta 278467e0f410SFangrui Song int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, nullptr, 278591516925SJianzhou Zhao nullptr, ap); 278691516925SJianzhou Zhao va_end(ap); 278791516925SJianzhou Zhao return ret; 278891516925SJianzhou Zhao } 278991516925SJianzhou Zhao 279091516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 279191516925SJianzhou Zhao int __dfso_sprintf(char *str, const char *format, dfsan_label str_label, 279291516925SJianzhou Zhao dfsan_label format_label, dfsan_label *va_labels, 279391516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin str_origin, 279491516925SJianzhou Zhao dfsan_origin format_origin, dfsan_origin *va_origins, 279591516925SJianzhou Zhao dfsan_origin *ret_origin, ...) { 279691516925SJianzhou Zhao va_list ap; 279791516925SJianzhou Zhao va_start(ap, ret_origin); 279867e0f410SFangrui Song int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, 279967e0f410SFangrui Song va_origins, ret_origin, ap); 2800a9aa8137SNico Weber va_end(ap); 2801a9aa8137SNico Weber return ret; 2802a9aa8137SNico Weber } 2803a9aa8137SNico Weber 2804a9aa8137SNico Weber SANITIZER_INTERFACE_ATTRIBUTE 2805a9aa8137SNico Weber int __dfsw_snprintf(char *str, size_t size, const char *format, 2806a9aa8137SNico Weber dfsan_label str_label, dfsan_label size_label, 2807a9aa8137SNico Weber dfsan_label format_label, dfsan_label *va_labels, 2808a9aa8137SNico Weber dfsan_label *ret_label, ...) { 2809a9aa8137SNico Weber va_list ap; 2810a9aa8137SNico Weber va_start(ap, ret_label); 281191516925SJianzhou Zhao int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr, 281291516925SJianzhou Zhao nullptr, ap); 281391516925SJianzhou Zhao va_end(ap); 281491516925SJianzhou Zhao return ret; 281591516925SJianzhou Zhao } 281691516925SJianzhou Zhao 281791516925SJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 281891516925SJianzhou Zhao int __dfso_snprintf(char *str, size_t size, const char *format, 281991516925SJianzhou Zhao dfsan_label str_label, dfsan_label size_label, 282091516925SJianzhou Zhao dfsan_label format_label, dfsan_label *va_labels, 282191516925SJianzhou Zhao dfsan_label *ret_label, dfsan_origin str_origin, 282291516925SJianzhou Zhao dfsan_origin size_origin, dfsan_origin format_origin, 282391516925SJianzhou Zhao dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) { 282491516925SJianzhou Zhao va_list ap; 282591516925SJianzhou Zhao va_start(ap, ret_origin); 282691516925SJianzhou Zhao int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins, 282791516925SJianzhou Zhao ret_origin, ap); 2828a9aa8137SNico Weber va_end(ap); 2829a9aa8137SNico Weber return ret; 2830a9aa8137SNico Weber } 2831a9aa8137SNico Weber 28328dbcf8ebSTomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE 28338dbcf8ebSTomasz Kuchta int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label, 28348dbcf8ebSTomasz Kuchta dfsan_label format_label, dfsan_label *va_labels, 28358dbcf8ebSTomasz Kuchta dfsan_label *ret_label, ...) { 28368dbcf8ebSTomasz Kuchta va_list ap; 28378dbcf8ebSTomasz Kuchta va_start(ap, ret_label); 28388dbcf8ebSTomasz Kuchta int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr, 28398dbcf8ebSTomasz Kuchta nullptr, ap); 28408dbcf8ebSTomasz Kuchta va_end(ap); 28418dbcf8ebSTomasz Kuchta return ret; 28428dbcf8ebSTomasz Kuchta } 28438dbcf8ebSTomasz Kuchta 28448dbcf8ebSTomasz Kuchta SANITIZER_INTERFACE_ATTRIBUTE 28458dbcf8ebSTomasz Kuchta int __dfso_sscanf(char *str, const char *format, dfsan_label str_label, 28468dbcf8ebSTomasz Kuchta dfsan_label format_label, dfsan_label *va_labels, 28478dbcf8ebSTomasz Kuchta dfsan_label *ret_label, dfsan_origin str_origin, 28488dbcf8ebSTomasz Kuchta dfsan_origin format_origin, dfsan_origin *va_origins, 28498dbcf8ebSTomasz Kuchta dfsan_origin *ret_origin, ...) { 28508dbcf8ebSTomasz Kuchta va_list ap; 28518dbcf8ebSTomasz Kuchta va_start(ap, ret_origin); 28528dbcf8ebSTomasz Kuchta int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin, 28538dbcf8ebSTomasz Kuchta ret_origin, ap); 28548dbcf8ebSTomasz Kuchta va_end(ap); 28558dbcf8ebSTomasz Kuchta return ret; 28568dbcf8ebSTomasz Kuchta } 28578dbcf8ebSTomasz Kuchta 285864856006SFangrui Song WRAPPER_ALIAS(__isoc99_sscanf, sscanf) 285964856006SFangrui Song WRAPPER_ALIAS(__isoc23_sscanf, sscanf) 28608dbcf8ebSTomasz Kuchta 28614e67ae7bSJianzhou Zhao static void BeforeFork() { 2862*36bd9aebSVitaly Buka VReport(2, "BeforeFork tid: %llu\n", GetTid()); 2863f78a742aSVitaly Buka StackDepotLockBeforeFork(); 2864f78a742aSVitaly Buka ChainedOriginDepotLockBeforeFork(); 28654e67ae7bSJianzhou Zhao } 28664e67ae7bSJianzhou Zhao 2867f78a742aSVitaly Buka static void AfterFork(bool fork_child) { 2868f78a742aSVitaly Buka ChainedOriginDepotUnlockAfterFork(fork_child); 2869f78a742aSVitaly Buka StackDepotUnlockAfterFork(fork_child); 2870*36bd9aebSVitaly Buka VReport(2, "AfterFork tid: %llu\n", GetTid()); 28714e67ae7bSJianzhou Zhao } 28724e67ae7bSJianzhou Zhao 28734e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 28744e67ae7bSJianzhou Zhao pid_t __dfsw_fork(dfsan_label *ret_label) { 28754e67ae7bSJianzhou Zhao pid_t pid = fork(); 28764e67ae7bSJianzhou Zhao *ret_label = 0; 28774e67ae7bSJianzhou Zhao return pid; 28784e67ae7bSJianzhou Zhao } 28794e67ae7bSJianzhou Zhao 28804e67ae7bSJianzhou Zhao SANITIZER_INTERFACE_ATTRIBUTE 28814e67ae7bSJianzhou Zhao pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) { 28824e67ae7bSJianzhou Zhao BeforeFork(); 28834e67ae7bSJianzhou Zhao pid_t pid = __dfsw_fork(ret_label); 2884f78a742aSVitaly Buka AfterFork(/* fork_child= */ pid == 0); 28854e67ae7bSJianzhou Zhao return pid; 28864e67ae7bSJianzhou Zhao } 28874e67ae7bSJianzhou Zhao 2888a9aa8137SNico Weber // Default empty implementations (weak). Users should redefine them. 2889a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {} 2890a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *, 2891a9aa8137SNico Weber u32 *) {} 28928103b070SKostya Serebryany SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg, 28938103b070SKostya Serebryany const uptr *end) {} 2894a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} 2895a9aa8137SNico Weber 2896a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {} 2897a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {} 2898a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {} 2899a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {} 2900a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {} 2901a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1, 2902a9aa8137SNico Weber void) {} 2903a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2, 2904a9aa8137SNico Weber void) {} 2905a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4, 2906a9aa8137SNico Weber void) {} 2907a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8, 2908a9aa8137SNico Weber void) {} 2909a9aa8137SNico Weber SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {} 2910a9aa8137SNico Weber } // extern "C" 2911