Path: blob/main/contrib/llvm-project/compiler-rt/lib/dfsan/dfsan_custom.cpp
35233 views
//===-- dfsan_custom.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of DataFlowSanitizer.9//10// This file defines the custom functions listed in done_abilist.txt.11//===----------------------------------------------------------------------===//1213#include <arpa/inet.h>14#include <assert.h>15#include <ctype.h>16#include <dlfcn.h>17#include <link.h>18#include <poll.h>19#include <pthread.h>20#include <pwd.h>21#include <sched.h>22#include <signal.h>23#include <stdarg.h>24#include <stdint.h>25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <sys/epoll.h>29#include <sys/resource.h>30#include <sys/select.h>31#include <sys/socket.h>32#include <sys/stat.h>33#include <sys/time.h>34#include <sys/types.h>35#include <time.h>36#include <unistd.h>3738#include "dfsan/dfsan.h"39#include "dfsan/dfsan_chained_origin_depot.h"40#include "dfsan/dfsan_flags.h"41#include "dfsan/dfsan_thread.h"42#include "sanitizer_common/sanitizer_common.h"43#include "sanitizer_common/sanitizer_internal_defs.h"44#include "sanitizer_common/sanitizer_linux.h"45#include "sanitizer_common/sanitizer_stackdepot.h"4647using namespace __dfsan;4849#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \50do { \51if (f) \52f(__VA_ARGS__); \53} while (false)54#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \55SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);5657#define WRAPPER_ALIAS(fun, real) \58SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \59SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);6061// Async-safe, non-reentrant spin lock.62class SignalSpinLocker {63public:64SignalSpinLocker() {65sigset_t all_set;66sigfillset(&all_set);67pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);68sigactions_mu.Lock();69}70~SignalSpinLocker() {71sigactions_mu.Unlock();72pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);73}7475private:76static StaticSpinMutex sigactions_mu;77sigset_t saved_thread_mask_;7879SignalSpinLocker(const SignalSpinLocker &) = delete;80SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;81};8283StaticSpinMutex SignalSpinLocker::sigactions_mu;8485extern "C" {86SANITIZER_INTERFACE_ATTRIBUTE int87__dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,88dfsan_label buf_label, dfsan_label *ret_label) {89int ret = stat(path, buf);90if (ret == 0)91dfsan_set_label(0, buf, sizeof(struct stat));92*ret_label = 0;93return ret;94}9596SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(97const char *path, struct stat *buf, dfsan_label path_label,98dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,99dfsan_origin buf_origin, dfsan_origin *ret_origin) {100int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);101return ret;102}103104SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,105dfsan_label fd_label,106dfsan_label buf_label,107dfsan_label *ret_label) {108int ret = fstat(fd, buf);109if (ret == 0)110dfsan_set_label(0, buf, sizeof(struct stat));111*ret_label = 0;112return ret;113}114115SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(116int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,117dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,118dfsan_origin *ret_origin) {119int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);120return ret;121}122123static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,124dfsan_label s_label, dfsan_label c_label,125dfsan_label *ret_label) {126char *match_pos = nullptr;127for (size_t i = 0;; ++i) {128if (s[i] == c || s[i] == 0) {129// If s[i] is the \0 at the end of the string, and \0 is not the130// character we are searching for, then return null.131*bytes_read = i + 1;132match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);133break;134}135}136if (flags().strict_data_dependencies)137*ret_label = s_label;138else139*ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),140dfsan_union(s_label, c_label));141return match_pos;142}143144SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,145dfsan_label s_label,146dfsan_label c_label,147dfsan_label *ret_label) {148size_t bytes_read;149return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,150ret_label);151}152153SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(154const char *s, int c, dfsan_label s_label, dfsan_label c_label,155dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,156dfsan_origin *ret_origin) {157size_t bytes_read;158char *r =159dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);160if (flags().strict_data_dependencies) {161*ret_origin = s_origin;162} else if (*ret_label) {163dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);164*ret_origin = o ? o : (s_label ? s_origin : c_origin);165}166return r;167}168169SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,170const char *accept,171dfsan_label s_label,172dfsan_label accept_label,173dfsan_label *ret_label) {174const char *ret = strpbrk(s, accept);175if (flags().strict_data_dependencies) {176*ret_label = ret ? s_label : 0;177} else {178size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;179*ret_label =180dfsan_union(dfsan_read_label(s, s_bytes_read),181dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),182dfsan_union(s_label, accept_label)));183}184return const_cast<char *>(ret);185}186187SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(188const char *s, const char *accept, dfsan_label s_label,189dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,190dfsan_origin accept_origin, dfsan_origin *ret_origin) {191const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);192if (flags().strict_data_dependencies) {193if (ret)194*ret_origin = s_origin;195} else {196if (*ret_label) {197size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;198dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);199if (o) {200*ret_origin = o;201} else {202o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);203*ret_origin = o ? o : (s_label ? s_origin : accept_origin);204}205}206}207return const_cast<char *>(ret);208}209210SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim,211dfsan_label s_label,212dfsan_label delim_label,213dfsan_label *ret_label) {214dfsan_label base_label = dfsan_read_label(s, sizeof(*s));215char *base = *s;216char *res = strsep(s, delim);217if (res != *s) {218char *token_start = res;219int token_length = strlen(res);220// the delimiter byte has been set to NULL221dfsan_set_label(0, token_start + token_length, 1);222}223224if (flags().strict_data_dependencies) {225*ret_label = res ? base_label : 0;226} else {227size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;228*ret_label = dfsan_union(229dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))),230dfsan_union(dfsan_read_label(delim, strlen(delim) + 1),231dfsan_union(s_label, delim_label)));232}233234return res;235}236237SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep(238char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label,239dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin,240dfsan_origin *ret_origin) {241dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s));242char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label);243if (flags().strict_data_dependencies) {244if (res)245*ret_origin = base_origin;246} else {247if (*ret_label) {248if (base_origin) {249*ret_origin = base_origin;250} else {251dfsan_origin o =252dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1);253*ret_origin = o ? o : (s_label ? s_origin : delim_origin);254}255}256}257258return res;259}260261static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,262size_t *bytes_read) {263const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;264for (size_t i = 0; i != n; ++i) {265if (cs1[i] != cs2[i]) {266*bytes_read = i + 1;267return cs1[i] - cs2[i];268}269}270*bytes_read = n;271return 0;272}273274static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,275size_t pos) {276if (flags().strict_data_dependencies)277return 0;278return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));279}280281static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,282dfsan_label *ret_label,283dfsan_origin *ret_origin) {284*ret_label = dfsan_get_memcmp_label(s1, s2, pos);285if (*ret_label == 0)286return;287dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);288*ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);289}290291static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,292dfsan_label *ret_label) {293size_t bytes_read;294int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);295*ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);296return r;297}298299static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,300dfsan_label *ret_label,301dfsan_origin *ret_origin) {302size_t bytes_read;303int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);304dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);305return r;306}307308DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,309const void *s1, const void *s2, size_t n,310dfsan_label s1_label, dfsan_label s2_label,311dfsan_label n_label)312313DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,314const void *s1, const void *s2, size_t n,315dfsan_label s1_label, dfsan_label s2_label,316dfsan_label n_label, dfsan_origin s1_origin,317dfsan_origin s2_origin, dfsan_origin n_origin)318319SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,320size_t n, dfsan_label s1_label,321dfsan_label s2_label,322dfsan_label n_label,323dfsan_label *ret_label) {324CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,325s1_label, s2_label, n_label);326return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);327}328329SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(330const void *s1, const void *s2, size_t n, dfsan_label s1_label,331dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,332dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,333dfsan_origin *ret_origin) {334CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,335s2, n, s1_label, s2_label, n_label, s1_origin,336s2_origin, n_origin);337return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);338}339340SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,341size_t n, dfsan_label s1_label,342dfsan_label s2_label,343dfsan_label n_label,344dfsan_label *ret_label) {345return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);346}347348SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(349const void *s1, const void *s2, size_t n, dfsan_label s1_label,350dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,351dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,352dfsan_origin *ret_origin) {353return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);354}355356// When n == 0, compare strings without byte limit.357// When n > 0, compare the first (at most) n bytes of s1 and s2.358static int dfsan_strncmp(const char *s1, const char *s2, size_t n,359size_t *bytes_read) {360for (size_t i = 0;; ++i) {361if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {362*bytes_read = i + 1;363return s1[i] - s2[i];364}365}366}367368DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,369const char *s1, const char *s2,370dfsan_label s1_label, dfsan_label s2_label)371372DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,373const char *s1, const char *s2,374dfsan_label s1_label, dfsan_label s2_label,375dfsan_origin s1_origin, dfsan_origin s2_origin)376377SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,378dfsan_label s1_label,379dfsan_label s2_label,380dfsan_label *ret_label) {381CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,382s1_label, s2_label);383size_t bytes_read;384int r = dfsan_strncmp(s1, s2, 0, &bytes_read);385*ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);386return r;387}388389SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(390const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,391dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,392dfsan_origin *ret_origin) {393CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,394s2, s1_label, s2_label, s1_origin, s2_origin);395size_t bytes_read;396int r = dfsan_strncmp(s1, s2, 0, &bytes_read);397dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);398return r;399}400401// When n == 0, compare strings without byte limit.402// When n > 0, compare the first (at most) n bytes of s1 and s2.403static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,404size_t *bytes_read) {405for (size_t i = 0;; ++i) {406char s1_lower = tolower(s1[i]);407char s2_lower = tolower(s2[i]);408409if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||410(n > 0 && i == n - 1)) {411*bytes_read = i + 1;412return s1_lower - s2_lower;413}414}415}416417SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,418const char *s2,419dfsan_label s1_label,420dfsan_label s2_label,421dfsan_label *ret_label) {422size_t bytes_read;423int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);424*ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);425return r;426}427428SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(429const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,430dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,431dfsan_origin *ret_origin) {432size_t bytes_read;433int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);434dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);435return r;436}437438DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,439const char *s1, const char *s2, size_t n,440dfsan_label s1_label, dfsan_label s2_label,441dfsan_label n_label)442443DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,444const char *s1, const char *s2, size_t n,445dfsan_label s1_label, dfsan_label s2_label,446dfsan_label n_label, dfsan_origin s1_origin,447dfsan_origin s2_origin, dfsan_origin n_origin)448449SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,450size_t n, dfsan_label s1_label,451dfsan_label s2_label,452dfsan_label n_label,453dfsan_label *ret_label) {454if (n == 0) {455*ret_label = 0;456return 0;457}458459CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,460n, s1_label, s2_label, n_label);461462size_t bytes_read;463int r = dfsan_strncmp(s1, s2, n, &bytes_read);464*ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);465return r;466}467468SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(469const char *s1, const char *s2, size_t n, dfsan_label s1_label,470dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,471dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,472dfsan_origin *ret_origin) {473if (n == 0) {474*ret_label = 0;475return 0;476}477478CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),479s1, s2, n, s1_label, s2_label, n_label, s1_origin,480s2_origin, n_origin);481482size_t bytes_read;483int r = dfsan_strncmp(s1, s2, n, &bytes_read);484dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);485return r;486}487488SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(489const char *s1, const char *s2, size_t n, dfsan_label s1_label,490dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {491if (n == 0) {492*ret_label = 0;493return 0;494}495496size_t bytes_read;497int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);498*ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);499return r;500}501502SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(503const char *s1, const char *s2, size_t n, dfsan_label s1_label,504dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,505dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,506dfsan_origin *ret_origin) {507if (n == 0) {508*ret_label = 0;509return 0;510}511512size_t bytes_read;513int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);514dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);515return r;516}517518519SANITIZER_INTERFACE_ATTRIBUTE size_t520__dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {521size_t ret = strlen(s);522if (flags().strict_data_dependencies) {523*ret_label = 0;524} else {525*ret_label = dfsan_read_label(s, ret + 1);526}527return ret;528}529530SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,531dfsan_label s_label,532dfsan_label *ret_label,533dfsan_origin s_origin,534dfsan_origin *ret_origin) {535size_t ret = __dfsw_strlen(s, s_label, ret_label);536if (!flags().strict_data_dependencies)537*ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);538return ret;539}540541SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s,542size_t maxlen,543dfsan_label s_label,544dfsan_label maxlen_label,545dfsan_label *ret_label) {546size_t ret = strnlen(s, maxlen);547if (flags().strict_data_dependencies) {548*ret_label = 0;549} else {550size_t full_len = strlen(s);551size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;552*ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len));553}554return ret;555}556557SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen(558const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label,559dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin,560dfsan_origin *ret_origin) {561size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label);562if (!flags().strict_data_dependencies) {563size_t full_len = strlen(s);564size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;565dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len);566*ret_origin = o ? o : maxlen_origin;567}568return ret;569}570571static void *dfsan_memmove(void *dest, const void *src, size_t n) {572dfsan_label *sdest = shadow_for(dest);573const dfsan_label *ssrc = shadow_for(src);574internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));575return internal_memmove(dest, src, n);576}577578static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {579dfsan_mem_origin_transfer(dest, src, n);580return dfsan_memmove(dest, src, n);581}582583static void *dfsan_memcpy(void *dest, const void *src, size_t n) {584dfsan_mem_shadow_transfer(dest, src, n);585return internal_memcpy(dest, src, n);586}587588static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {589dfsan_mem_origin_transfer(dest, src, n);590return dfsan_memcpy(dest, src, n);591}592593static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {594internal_memset(s, c, n);595dfsan_set_label(c_label, s, n);596}597598static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,599dfsan_origin c_origin, size_t n) {600internal_memset(s, c, n);601dfsan_set_label_origin(c_label, c_origin, s, n);602}603604SANITIZER_INTERFACE_ATTRIBUTE605void *__dfsw_memcpy(void *dest, const void *src, size_t n,606dfsan_label dest_label, dfsan_label src_label,607dfsan_label n_label, dfsan_label *ret_label) {608*ret_label = dest_label;609return dfsan_memcpy(dest, src, n);610}611612SANITIZER_INTERFACE_ATTRIBUTE613void *__dfso_memcpy(void *dest, const void *src, size_t n,614dfsan_label dest_label, dfsan_label src_label,615dfsan_label n_label, dfsan_label *ret_label,616dfsan_origin dest_origin, dfsan_origin src_origin,617dfsan_origin n_origin, dfsan_origin *ret_origin) {618*ret_label = dest_label;619*ret_origin = dest_origin;620return dfsan_memcpy_with_origin(dest, src, n);621}622623SANITIZER_INTERFACE_ATTRIBUTE624void *__dfsw_memmove(void *dest, const void *src, size_t n,625dfsan_label dest_label, dfsan_label src_label,626dfsan_label n_label, dfsan_label *ret_label) {627*ret_label = dest_label;628return dfsan_memmove(dest, src, n);629}630631SANITIZER_INTERFACE_ATTRIBUTE632void *__dfso_memmove(void *dest, const void *src, size_t n,633dfsan_label dest_label, dfsan_label src_label,634dfsan_label n_label, dfsan_label *ret_label,635dfsan_origin dest_origin, dfsan_origin src_origin,636dfsan_origin n_origin, dfsan_origin *ret_origin) {637*ret_label = dest_label;638*ret_origin = dest_origin;639return dfsan_memmove_with_origin(dest, src, n);640}641642SANITIZER_INTERFACE_ATTRIBUTE643void *__dfsw_memset(void *s, int c, size_t n,644dfsan_label s_label, dfsan_label c_label,645dfsan_label n_label, dfsan_label *ret_label) {646dfsan_memset(s, c, c_label, n);647*ret_label = s_label;648return s;649}650651SANITIZER_INTERFACE_ATTRIBUTE652void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,653dfsan_label c_label, dfsan_label n_label,654dfsan_label *ret_label, dfsan_origin s_origin,655dfsan_origin c_origin, dfsan_origin n_origin,656dfsan_origin *ret_origin) {657dfsan_memset_with_origin(s, c, c_label, c_origin, n);658*ret_label = s_label;659*ret_origin = s_origin;660return s;661}662663SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,664dfsan_label dest_label,665dfsan_label src_label,666dfsan_label *ret_label) {667size_t dest_len = strlen(dest);668char *ret = strcat(dest, src);669dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));670*ret_label = dest_label;671return ret;672}673674SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(675char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,676dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,677dfsan_origin *ret_origin) {678size_t dest_len = strlen(dest);679char *ret = strcat(dest, src);680size_t src_len = strlen(src);681dfsan_mem_origin_transfer(dest + dest_len, src, src_len);682dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);683*ret_label = dest_label;684*ret_origin = dest_origin;685return ret;686}687688SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat(689char *dest, const char *src, size_t num, dfsan_label dest_label,690dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) {691size_t src_len = strlen(src);692src_len = src_len < num ? src_len : num;693size_t dest_len = strlen(dest);694695char *ret = strncat(dest, src, num);696dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);697*ret_label = dest_label;698return ret;699}700701SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat(702char *dest, const char *src, size_t num, dfsan_label dest_label,703dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label,704dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin,705dfsan_origin *ret_origin) {706size_t src_len = strlen(src);707src_len = src_len < num ? src_len : num;708size_t dest_len = strlen(dest);709710char *ret = strncat(dest, src, num);711712dfsan_mem_origin_transfer(dest + dest_len, src, src_len);713dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);714*ret_label = dest_label;715*ret_origin = dest_origin;716return ret;717}718719SANITIZER_INTERFACE_ATTRIBUTE char *720__dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {721size_t len = strlen(s);722void *p = malloc(len+1);723dfsan_memcpy(p, s, len+1);724*ret_label = 0;725return static_cast<char *>(p);726}727728SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,729dfsan_label s_label,730dfsan_label *ret_label,731dfsan_origin s_origin,732dfsan_origin *ret_origin) {733size_t len = strlen(s);734void *p = malloc(len + 1);735dfsan_memcpy_with_origin(p, s, len + 1);736*ret_label = 0;737return static_cast<char *>(p);738}739740SANITIZER_INTERFACE_ATTRIBUTE char *741__dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,742dfsan_label s2_label, dfsan_label n_label,743dfsan_label *ret_label) {744size_t len = strlen(s2);745if (len < n) {746dfsan_memcpy(s1, s2, len+1);747dfsan_memset(s1+len+1, 0, 0, n-len-1);748} else {749dfsan_memcpy(s1, s2, n);750}751752*ret_label = s1_label;753return s1;754}755756SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(757char *s1, const char *s2, size_t n, dfsan_label s1_label,758dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,759dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,760dfsan_origin *ret_origin) {761size_t len = strlen(s2);762if (len < n) {763dfsan_memcpy_with_origin(s1, s2, len + 1);764dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);765} else {766dfsan_memcpy_with_origin(s1, s2, n);767}768769*ret_label = s1_label;770*ret_origin = s1_origin;771return s1;772}773774SANITIZER_INTERFACE_ATTRIBUTE ssize_t775__dfsw_pread(int fd, void *buf, size_t count, off_t offset,776dfsan_label fd_label, dfsan_label buf_label,777dfsan_label count_label, dfsan_label offset_label,778dfsan_label *ret_label) {779ssize_t ret = pread(fd, buf, count, offset);780if (ret > 0)781dfsan_set_label(0, buf, ret);782*ret_label = 0;783return ret;784}785786SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(787int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,788dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,789dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,790dfsan_origin count_origin, dfsan_label offset_origin,791dfsan_origin *ret_origin) {792return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,793offset_label, ret_label);794}795796SANITIZER_INTERFACE_ATTRIBUTE ssize_t797__dfsw_read(int fd, void *buf, size_t count,798dfsan_label fd_label, dfsan_label buf_label,799dfsan_label count_label,800dfsan_label *ret_label) {801ssize_t ret = read(fd, buf, count);802if (ret > 0)803dfsan_set_label(0, buf, ret);804*ret_label = 0;805return ret;806}807808SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(809int fd, void *buf, size_t count, dfsan_label fd_label,810dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,811dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,812dfsan_origin *ret_origin) {813return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,814ret_label);815}816817SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,818struct timespec *tp,819dfsan_label clk_id_label,820dfsan_label tp_label,821dfsan_label *ret_label) {822int ret = clock_gettime(clk_id, tp);823if (ret == 0)824dfsan_set_label(0, tp, sizeof(struct timespec));825*ret_label = 0;826return ret;827}828829SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(830clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,831dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,832dfsan_origin tp_origin, dfsan_origin *ret_origin) {833return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);834}835836static void dfsan_set_zero_label(const void *ptr, uptr size) {837dfsan_set_label(0, const_cast<void *>(ptr), size);838}839840// dlopen() ultimately calls mmap() down inside the loader, which generally841// doesn't participate in dynamic symbol resolution. Therefore we won't842// intercept its calls to mmap, and we have to hook it here.843SANITIZER_INTERFACE_ATTRIBUTE void *844__dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,845dfsan_label flag_label, dfsan_label *ret_label) {846void *handle = dlopen(filename, flag);847link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);848if (filename && map)849ForEachMappedRegion(map, dfsan_set_zero_label);850*ret_label = 0;851return handle;852}853854SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(855const char *filename, int flag, dfsan_label filename_label,856dfsan_label flag_label, dfsan_label *ret_label,857dfsan_origin filename_origin, dfsan_origin flag_origin,858dfsan_origin *ret_origin) {859return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);860}861862static void *DFsanThreadStartFunc(void *arg) {863DFsanThread *t = (DFsanThread *)arg;864SetCurrentThread(t);865t->Init();866SetSigProcMask(&t->starting_sigset_, nullptr);867return t->ThreadStart();868}869870static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,871void *start_routine, void *arg,872dfsan_label *ret_label,873bool track_origins = false) {874pthread_attr_t myattr;875if (!attr) {876pthread_attr_init(&myattr);877attr = &myattr;878}879880// Ensure that the thread stack is large enough to hold all TLS data.881AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));882883DFsanThread *t =884DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);885ScopedBlockSignals block(&t->starting_sigset_);886int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);887888if (attr == &myattr)889pthread_attr_destroy(&myattr);890*ret_label = 0;891return res;892}893894SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(895pthread_t *thread, const pthread_attr_t *attr, void *start_routine,896void *arg, dfsan_label thread_label, dfsan_label attr_label,897dfsan_label start_routine_label, dfsan_label arg_label,898dfsan_label *ret_label) {899return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);900}901902SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(903pthread_t *thread, const pthread_attr_t *attr, void *start_routine,904void *arg, dfsan_label thread_label, dfsan_label attr_label,905dfsan_label start_routine_label, dfsan_label arg_label,906dfsan_label *ret_label, dfsan_origin thread_origin,907dfsan_origin attr_origin, dfsan_origin start_routine_origin,908dfsan_origin arg_origin, dfsan_origin *ret_origin) {909return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,910true);911}912913SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,914void **retval,915dfsan_label thread_label,916dfsan_label retval_label,917dfsan_label *ret_label) {918int ret = pthread_join(thread, retval);919if (ret == 0 && retval)920dfsan_set_label(0, retval, sizeof(*retval));921*ret_label = 0;922return ret;923}924925SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(926pthread_t thread, void **retval, dfsan_label thread_label,927dfsan_label retval_label, dfsan_label *ret_label,928dfsan_origin thread_origin, dfsan_origin retval_origin,929dfsan_origin *ret_origin) {930return __dfsw_pthread_join(thread, retval, thread_label, retval_label,931ret_label);932}933934struct dl_iterate_phdr_info {935int (*callback)(struct dl_phdr_info *info, size_t size, void *data);936void *data;937};938939int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {940dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;941dfsan_set_label(0, *info);942dfsan_set_label(0, const_cast<char *>(info->dlpi_name),943strlen(info->dlpi_name) + 1);944dfsan_set_label(9450, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),946sizeof(*info->dlpi_phdr) * info->dlpi_phnum);947948dfsan_clear_thread_local_state();949return dipi->callback(info, size, dipi->data);950}951952SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(953int (*callback)(struct dl_phdr_info *info, size_t size, void *data),954void *data, dfsan_label callback_label, dfsan_label data_label,955dfsan_label *ret_label) {956dl_iterate_phdr_info dipi = {callback, data};957*ret_label = 0;958return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);959}960961SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(962int (*callback)(struct dl_phdr_info *info, size_t size, void *data),963void *data, dfsan_label callback_label, dfsan_label data_label,964dfsan_label *ret_label, dfsan_origin callback_origin,965dfsan_origin data_origin, dfsan_origin *ret_origin) {966dl_iterate_phdr_info dipi = {callback, data};967*ret_label = 0;968return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);969}970971// This function is only available for glibc 2.27 or newer. Mark it weak so972// linking succeeds with older glibcs.973SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,974size_t *alignp);975976SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(977size_t *sizep, size_t *alignp, dfsan_label sizep_label,978dfsan_label alignp_label) {979assert(_dl_get_tls_static_info);980_dl_get_tls_static_info(sizep, alignp);981dfsan_set_label(0, sizep, sizeof(*sizep));982dfsan_set_label(0, alignp, sizeof(*alignp));983}984985SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(986size_t *sizep, size_t *alignp, dfsan_label sizep_label,987dfsan_label alignp_label, dfsan_origin sizep_origin,988dfsan_origin alignp_origin) {989__dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);990}991992SANITIZER_INTERFACE_ATTRIBUTE993char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,994dfsan_label buf_label, dfsan_label *ret_label) {995char *ret = ctime_r(timep, buf);996if (ret) {997dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,998strlen(buf) + 1);999*ret_label = buf_label;1000} else {1001*ret_label = 0;1002}1003return ret;1004}10051006SANITIZER_INTERFACE_ATTRIBUTE1007char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,1008dfsan_label buf_label, dfsan_label *ret_label,1009dfsan_origin timep_origin, dfsan_origin buf_origin,1010dfsan_origin *ret_origin) {1011char *ret = ctime_r(timep, buf);1012if (ret) {1013dfsan_set_label_origin(1014dfsan_read_label(timep, sizeof(time_t)),1015dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,1016strlen(buf) + 1);1017*ret_label = buf_label;1018*ret_origin = buf_origin;1019} else {1020*ret_label = 0;1021}1022return ret;1023}10241025SANITIZER_INTERFACE_ATTRIBUTE1026char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,1027dfsan_label size_label, dfsan_label stream_label,1028dfsan_label *ret_label) {1029char *ret = fgets(s, size, stream);1030if (ret) {1031dfsan_set_label(0, ret, strlen(ret) + 1);1032*ret_label = s_label;1033} else {1034*ret_label = 0;1035}1036return ret;1037}10381039SANITIZER_INTERFACE_ATTRIBUTE1040char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,1041dfsan_label size_label, dfsan_label stream_label,1042dfsan_label *ret_label, dfsan_origin s_origin,1043dfsan_origin size_origin, dfsan_origin stream_origin,1044dfsan_origin *ret_origin) {1045char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,1046ret_label);1047if (ret)1048*ret_origin = s_origin;1049return ret;1050}10511052SANITIZER_INTERFACE_ATTRIBUTE1053char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,1054dfsan_label size_label, dfsan_label *ret_label) {1055char *ret = getcwd(buf, size);1056if (ret) {1057dfsan_set_label(0, ret, strlen(ret) + 1);1058*ret_label = buf_label;1059} else {1060*ret_label = 0;1061}1062return ret;1063}10641065SANITIZER_INTERFACE_ATTRIBUTE1066char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,1067dfsan_label size_label, dfsan_label *ret_label,1068dfsan_origin buf_origin, dfsan_origin size_origin,1069dfsan_origin *ret_origin) {1070char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);1071if (ret)1072*ret_origin = buf_origin;1073return ret;1074}10751076SANITIZER_INTERFACE_ATTRIBUTE1077char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {1078char *ret = get_current_dir_name();1079if (ret)1080dfsan_set_label(0, ret, strlen(ret) + 1);1081*ret_label = 0;1082return ret;1083}10841085SANITIZER_INTERFACE_ATTRIBUTE1086char *__dfso_get_current_dir_name(dfsan_label *ret_label,1087dfsan_origin *ret_origin) {1088return __dfsw_get_current_dir_name(ret_label);1089}10901091// This function is only available for glibc 2.25 or newer. Mark it weak so1092// linking succeeds with older glibcs.1093SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);10941095SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,1096dfsan_label buffer_label,1097dfsan_label length_label,1098dfsan_label *ret_label) {1099int ret = getentropy(buffer, length);1100if (ret == 0) {1101dfsan_set_label(0, buffer, length);1102}1103*ret_label = 0;1104return ret;1105}11061107SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,1108dfsan_label buffer_label,1109dfsan_label length_label,1110dfsan_label *ret_label,1111dfsan_origin buffer_origin,1112dfsan_origin length_origin,1113dfsan_origin *ret_origin) {1114return __dfsw_getentropy(buffer, length, buffer_label, length_label,1115ret_label);1116}11171118SANITIZER_INTERFACE_ATTRIBUTE1119int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,1120dfsan_label len_label, dfsan_label *ret_label) {1121int ret = gethostname(name, len);1122if (ret == 0) {1123dfsan_set_label(0, name, strlen(name) + 1);1124}1125*ret_label = 0;1126return ret;1127}11281129SANITIZER_INTERFACE_ATTRIBUTE1130int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,1131dfsan_label len_label, dfsan_label *ret_label,1132dfsan_origin name_origin, dfsan_origin len_origin,1133dfsan_label *ret_origin) {1134return __dfsw_gethostname(name, len, name_label, len_label, ret_label);1135}11361137SANITIZER_INTERFACE_ATTRIBUTE1138int __dfsw_getrlimit(int resource, struct rlimit *rlim,1139dfsan_label resource_label, dfsan_label rlim_label,1140dfsan_label *ret_label) {1141int ret = getrlimit(resource, rlim);1142if (ret == 0) {1143dfsan_set_label(0, rlim, sizeof(struct rlimit));1144}1145*ret_label = 0;1146return ret;1147}11481149SANITIZER_INTERFACE_ATTRIBUTE1150int __dfso_getrlimit(int resource, struct rlimit *rlim,1151dfsan_label resource_label, dfsan_label rlim_label,1152dfsan_label *ret_label, dfsan_origin resource_origin,1153dfsan_origin rlim_origin, dfsan_origin *ret_origin) {1154return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,1155ret_label);1156}11571158SANITIZER_INTERFACE_ATTRIBUTE1159int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,1160dfsan_label usage_label, dfsan_label *ret_label) {1161int ret = getrusage(who, usage);1162if (ret == 0) {1163dfsan_set_label(0, usage, sizeof(struct rusage));1164}1165*ret_label = 0;1166return ret;1167}11681169SANITIZER_INTERFACE_ATTRIBUTE1170int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,1171dfsan_label usage_label, dfsan_label *ret_label,1172dfsan_origin who_origin, dfsan_origin usage_origin,1173dfsan_label *ret_origin) {1174return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);1175}11761177SANITIZER_INTERFACE_ATTRIBUTE1178char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,1179dfsan_label src_label, dfsan_label *ret_label) {1180char *ret = strcpy(dest, src);1181if (ret) {1182dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);1183}1184*ret_label = dst_label;1185return ret;1186}11871188SANITIZER_INTERFACE_ATTRIBUTE1189char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,1190dfsan_label src_label, dfsan_label *ret_label,1191dfsan_origin dst_origin, dfsan_origin src_origin,1192dfsan_origin *ret_origin) {1193char *ret = strcpy(dest, src);1194if (ret) {1195size_t str_len = strlen(src) + 1;1196dfsan_mem_origin_transfer(dest, src, str_len);1197dfsan_mem_shadow_transfer(dest, src, str_len);1198}1199*ret_label = dst_label;1200*ret_origin = dst_origin;1201return ret;1202}1203}12041205template <typename Fn>1206static ALWAYS_INLINE auto dfsan_strtol_impl(1207Fn real, const char *nptr, char **endptr, int base,1208char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) {1209assert(tmp_endptr);1210auto ret = real(nptr, tmp_endptr, base);1211if (endptr)1212*endptr = *tmp_endptr;1213return ret;1214}12151216extern "C" {1217static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,1218dfsan_label base_label,1219dfsan_label *ret_label) {1220if (tmp_endptr > nptr) {1221// If *tmp_endptr is '\0' include its label as well.1222*ret_label = dfsan_union(1223base_label,1224dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));1225} else {1226*ret_label = 0;1227}1228}12291230static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,1231dfsan_label base_label,1232dfsan_label *ret_label,1233dfsan_origin base_origin,1234dfsan_origin *ret_origin) {1235if (tmp_endptr > nptr) {1236// When multiple inputs are tainted, we propagate one of its origins.1237// Because checking if base_label is tainted does not need additional1238// computation, we prefer to propagating base_origin.1239*ret_origin = base_label1240? base_origin1241: dfsan_read_origin_of_first_taint(1242nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1243}1244}12451246static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {1247assert(tmp_endptr);1248double ret = strtod(nptr, tmp_endptr);1249if (endptr)1250*endptr = *tmp_endptr;1251return ret;1252}12531254static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,1255dfsan_label *ret_label) {1256if (tmp_endptr > nptr) {1257// If *tmp_endptr is '\0' include its label as well.1258*ret_label = dfsan_read_label(1259nptr,1260tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1261} else {1262*ret_label = 0;1263}1264}12651266SANITIZER_INTERFACE_ATTRIBUTE1267double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,1268dfsan_label endptr_label, dfsan_label *ret_label) {1269char *tmp_endptr;1270double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);1271dfsan_strtod_label(nptr, tmp_endptr, ret_label);1272return ret;1273}12741275SANITIZER_INTERFACE_ATTRIBUTE1276double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,1277dfsan_label endptr_label, dfsan_label *ret_label,1278dfsan_origin nptr_origin, dfsan_origin endptr_origin,1279dfsan_origin *ret_origin) {1280char *tmp_endptr;1281double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);1282dfsan_strtod_label(nptr, tmp_endptr, ret_label);1283if (tmp_endptr > nptr) {1284// If *tmp_endptr is '\0' include its label as well.1285*ret_origin = dfsan_read_origin_of_first_taint(1286nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1287} else {1288*ret_origin = 0;1289}1290return ret;1291}12921293WRAPPER_ALIAS(__isoc23_strtod, strtod)12941295#define WRAPPER_STRTO(ret_type, fun) \1296SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \1297const char *nptr, char **endptr, int base, dfsan_label nptr_label, \1298dfsan_label endptr_label, dfsan_label base_label, \1299dfsan_label *ret_label) { \1300char *tmp_endptr; \1301auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \1302dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \1303return ret; \1304} \1305SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \1306const char *nptr, char **endptr, int base, dfsan_label nptr_label, \1307dfsan_label endptr_label, dfsan_label base_label, \1308dfsan_label *ret_label, dfsan_origin nptr_origin, \1309dfsan_origin endptr_origin, dfsan_origin base_origin, \1310dfsan_origin *ret_origin) { \1311char *tmp_endptr; \1312auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \1313dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \1314dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \1315base_origin, ret_origin); \1316return ret; \1317}13181319WRAPPER_STRTO(long, strtol)1320WRAPPER_STRTO(long long, strtoll)1321WRAPPER_STRTO(unsigned long, strtoul)1322WRAPPER_STRTO(unsigned long long, strtoull)1323WRAPPER_ALIAS(__isoc23_strtol, strtol)1324WRAPPER_ALIAS(__isoc23_strtoll, strtoll)1325WRAPPER_ALIAS(__isoc23_strtoul, strtoul)1326WRAPPER_ALIAS(__isoc23_strtoull, strtoull)13271328SANITIZER_INTERFACE_ATTRIBUTE1329time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {1330time_t ret = time(t);1331if (ret != (time_t) -1 && t) {1332dfsan_set_label(0, t, sizeof(time_t));1333}1334*ret_label = 0;1335return ret;1336}13371338SANITIZER_INTERFACE_ATTRIBUTE1339time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,1340dfsan_origin t_origin, dfsan_origin *ret_origin) {1341return __dfsw_time(t, t_label, ret_label);1342}13431344SANITIZER_INTERFACE_ATTRIBUTE1345int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,1346dfsan_label src_label, dfsan_label dst_label,1347dfsan_label *ret_label) {1348int ret = inet_pton(af, src, dst);1349if (ret == 1) {1350dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,1351af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));1352}1353*ret_label = 0;1354return ret;1355}13561357SANITIZER_INTERFACE_ATTRIBUTE1358int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,1359dfsan_label src_label, dfsan_label dst_label,1360dfsan_label *ret_label, dfsan_origin af_origin,1361dfsan_origin src_origin, dfsan_origin dst_origin,1362dfsan_origin *ret_origin) {1363int ret = inet_pton(af, src, dst);1364if (ret == 1) {1365int src_len = strlen(src) + 1;1366dfsan_set_label_origin(1367dfsan_read_label(src, src_len),1368dfsan_read_origin_of_first_taint(src, src_len), dst,1369af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));1370}1371*ret_label = 0;1372return ret;1373}13741375SANITIZER_INTERFACE_ATTRIBUTE1376struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,1377dfsan_label timep_label, dfsan_label result_label,1378dfsan_label *ret_label) {1379struct tm *ret = localtime_r(timep, result);1380if (ret) {1381dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,1382sizeof(struct tm));1383*ret_label = result_label;1384} else {1385*ret_label = 0;1386}1387return ret;1388}13891390SANITIZER_INTERFACE_ATTRIBUTE1391struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,1392dfsan_label timep_label, dfsan_label result_label,1393dfsan_label *ret_label, dfsan_origin timep_origin,1394dfsan_origin result_origin,1395dfsan_origin *ret_origin) {1396struct tm *ret = localtime_r(timep, result);1397if (ret) {1398dfsan_set_label_origin(1399dfsan_read_label(timep, sizeof(time_t)),1400dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,1401sizeof(struct tm));1402*ret_label = result_label;1403*ret_origin = result_origin;1404} else {1405*ret_label = 0;1406}1407return ret;1408}14091410SANITIZER_INTERFACE_ATTRIBUTE1411int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,1412char *buf, size_t buflen, struct passwd **result,1413dfsan_label uid_label, dfsan_label pwd_label,1414dfsan_label buf_label, dfsan_label buflen_label,1415dfsan_label result_label, dfsan_label *ret_label) {1416// Store the data in pwd, the strings referenced from pwd in buf, and the1417// address of pwd in *result. On failure, NULL is stored in *result.1418int ret = getpwuid_r(uid, pwd, buf, buflen, result);1419if (ret == 0) {1420dfsan_set_label(0, pwd, sizeof(struct passwd));1421dfsan_set_label(0, buf, strlen(buf) + 1);1422}1423*ret_label = 0;1424dfsan_set_label(0, result, sizeof(struct passwd*));1425return ret;1426}14271428SANITIZER_INTERFACE_ATTRIBUTE1429int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,1430struct passwd **result, dfsan_label uid_label,1431dfsan_label pwd_label, dfsan_label buf_label,1432dfsan_label buflen_label, dfsan_label result_label,1433dfsan_label *ret_label, dfsan_origin uid_origin,1434dfsan_origin pwd_origin, dfsan_origin buf_origin,1435dfsan_origin buflen_origin, dfsan_origin result_origin,1436dfsan_origin *ret_origin) {1437return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,1438buf_label, buflen_label, result_label, ret_label);1439}14401441SANITIZER_INTERFACE_ATTRIBUTE1442int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,1443int timeout, dfsan_label epfd_label,1444dfsan_label events_label, dfsan_label maxevents_label,1445dfsan_label timeout_label, dfsan_label *ret_label) {1446int ret = epoll_wait(epfd, events, maxevents, timeout);1447if (ret > 0)1448dfsan_set_label(0, events, ret * sizeof(*events));1449*ret_label = 0;1450return ret;1451}14521453SANITIZER_INTERFACE_ATTRIBUTE1454int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,1455int timeout, dfsan_label epfd_label,1456dfsan_label events_label, dfsan_label maxevents_label,1457dfsan_label timeout_label, dfsan_label *ret_label,1458dfsan_origin epfd_origin, dfsan_origin events_origin,1459dfsan_origin maxevents_origin,1460dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1461return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,1462events_label, maxevents_label, timeout_label,1463ret_label);1464}14651466SANITIZER_INTERFACE_ATTRIBUTE1467int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,1468dfsan_label dfs_label, dfsan_label nfds_label,1469dfsan_label timeout_label, dfsan_label *ret_label) {1470int ret = poll(fds, nfds, timeout);1471if (ret >= 0) {1472for (; nfds > 0; --nfds) {1473dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));1474}1475}1476*ret_label = 0;1477return ret;1478}14791480SANITIZER_INTERFACE_ATTRIBUTE1481int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,1482dfsan_label dfs_label, dfsan_label nfds_label,1483dfsan_label timeout_label, dfsan_label *ret_label,1484dfsan_origin dfs_origin, dfsan_origin nfds_origin,1485dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1486return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,1487ret_label);1488}14891490SANITIZER_INTERFACE_ATTRIBUTE1491int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,1492fd_set *exceptfds, struct timeval *timeout,1493dfsan_label nfds_label, dfsan_label readfds_label,1494dfsan_label writefds_label, dfsan_label exceptfds_label,1495dfsan_label timeout_label, dfsan_label *ret_label) {1496int ret = select(nfds, readfds, writefds, exceptfds, timeout);1497// Clear everything (also on error) since their content is either set or1498// undefined.1499if (readfds) {1500dfsan_set_label(0, readfds, sizeof(fd_set));1501}1502if (writefds) {1503dfsan_set_label(0, writefds, sizeof(fd_set));1504}1505if (exceptfds) {1506dfsan_set_label(0, exceptfds, sizeof(fd_set));1507}1508dfsan_set_label(0, timeout, sizeof(struct timeval));1509*ret_label = 0;1510return ret;1511}15121513SANITIZER_INTERFACE_ATTRIBUTE1514int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,1515fd_set *exceptfds, struct timeval *timeout,1516dfsan_label nfds_label, dfsan_label readfds_label,1517dfsan_label writefds_label, dfsan_label exceptfds_label,1518dfsan_label timeout_label, dfsan_label *ret_label,1519dfsan_origin nfds_origin, dfsan_origin readfds_origin,1520dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,1521dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1522return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,1523readfds_label, writefds_label, exceptfds_label,1524timeout_label, ret_label);1525}15261527SANITIZER_INTERFACE_ATTRIBUTE1528int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,1529dfsan_label pid_label,1530dfsan_label cpusetsize_label,1531dfsan_label mask_label, dfsan_label *ret_label) {1532int ret = sched_getaffinity(pid, cpusetsize, mask);1533if (ret == 0) {1534dfsan_set_label(0, mask, cpusetsize);1535}1536*ret_label = 0;1537return ret;1538}15391540SANITIZER_INTERFACE_ATTRIBUTE1541int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,1542dfsan_label pid_label,1543dfsan_label cpusetsize_label,1544dfsan_label mask_label, dfsan_label *ret_label,1545dfsan_origin pid_origin,1546dfsan_origin cpusetsize_origin,1547dfsan_origin mask_origin,1548dfsan_origin *ret_origin) {1549return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,1550cpusetsize_label, mask_label, ret_label);1551}15521553SANITIZER_INTERFACE_ATTRIBUTE1554int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,1555dfsan_label *ret_label) {1556int ret = sigemptyset(set);1557dfsan_set_label(0, set, sizeof(sigset_t));1558*ret_label = 0;1559return ret;1560}15611562SANITIZER_INTERFACE_ATTRIBUTE1563int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,1564dfsan_label *ret_label, dfsan_origin set_origin,1565dfsan_origin *ret_origin) {1566return __dfsw_sigemptyset(set, set_label, ret_label);1567}15681569class SignalHandlerScope {1570public:1571SignalHandlerScope() {1572if (DFsanThread *t = GetCurrentThread())1573t->EnterSignalHandler();1574}1575~SignalHandlerScope() {1576if (DFsanThread *t = GetCurrentThread())1577t->LeaveSignalHandler();1578}1579};15801581// Clear DFSan runtime TLS state at the end of a scope.1582//1583// Implementation must be async-signal-safe and use small data size, because1584// instances of this class may live on the signal handler stack.1585//1586// DFSan uses TLS to pass metadata of arguments and return values. When an1587// instrumented function accesses the TLS, if a signal callback happens, and the1588// callback calls other instrumented functions with updating the same TLS, the1589// TLS is in an inconsistent state after the callback ends. This may cause1590// either under-tainting or over-tainting.1591//1592// The current implementation simply resets TLS at restore. This prevents from1593// over-tainting. Although under-tainting may still happen, a taint flow can be1594// found eventually if we run a DFSan-instrumented program multiple times. The1595// alternative option is saving the entire TLS. However the TLS storage takes1596// 2k bytes, and signal calls could be nested. So it does not seem worth.1597class ScopedClearThreadLocalState {1598public:1599ScopedClearThreadLocalState() {}1600~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }1601};16021603// SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.1604const int kMaxSignals = 1024;1605static atomic_uintptr_t sigactions[kMaxSignals];16061607static void SignalHandler(int signo) {1608SignalHandlerScope signal_handler_scope;1609ScopedClearThreadLocalState scoped_clear_tls;16101611// Clear shadows for all inputs provided by system.1612dfsan_clear_arg_tls(0, sizeof(dfsan_label));16131614typedef void (*signal_cb)(int x);1615signal_cb cb =1616(signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);1617cb(signo);1618}16191620static void SignalAction(int signo, siginfo_t *si, void *uc) {1621SignalHandlerScope signal_handler_scope;1622ScopedClearThreadLocalState scoped_clear_tls;16231624// Clear shadows for all inputs provided by system. Similar to SignalHandler.1625dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));1626dfsan_set_label(0, si, sizeof(*si));1627dfsan_set_label(0, uc, sizeof(ucontext_t));16281629typedef void (*sigaction_cb)(int, siginfo_t *, void *);1630sigaction_cb cb =1631(sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);1632cb(signo, si, uc);1633}16341635SANITIZER_INTERFACE_ATTRIBUTE1636int __dfsw_sigaction(int signum, const struct sigaction *act,1637struct sigaction *oldact, dfsan_label signum_label,1638dfsan_label act_label, dfsan_label oldact_label,1639dfsan_label *ret_label) {1640CHECK_LT(signum, kMaxSignals);1641SignalSpinLocker lock;1642uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);1643struct sigaction new_act;1644struct sigaction *pnew_act = act ? &new_act : nullptr;1645if (act) {1646internal_memcpy(pnew_act, act, sizeof(struct sigaction));1647if (pnew_act->sa_flags & SA_SIGINFO) {1648uptr cb = (uptr)(pnew_act->sa_sigaction);1649if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {1650atomic_store(&sigactions[signum], cb, memory_order_relaxed);1651pnew_act->sa_sigaction = SignalAction;1652}1653} else {1654uptr cb = (uptr)(pnew_act->sa_handler);1655if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {1656atomic_store(&sigactions[signum], cb, memory_order_relaxed);1657pnew_act->sa_handler = SignalHandler;1658}1659}1660}16611662int ret = sigaction(signum, pnew_act, oldact);16631664if (ret == 0 && oldact) {1665if (oldact->sa_flags & SA_SIGINFO) {1666if (oldact->sa_sigaction == SignalAction)1667oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;1668} else {1669if (oldact->sa_handler == SignalHandler)1670oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;1671}1672}16731674if (oldact) {1675dfsan_set_label(0, oldact, sizeof(struct sigaction));1676}1677*ret_label = 0;1678return ret;1679}16801681SANITIZER_INTERFACE_ATTRIBUTE1682int __dfso_sigaction(int signum, const struct sigaction *act,1683struct sigaction *oldact, dfsan_label signum_label,1684dfsan_label act_label, dfsan_label oldact_label,1685dfsan_label *ret_label, dfsan_origin signum_origin,1686dfsan_origin act_origin, dfsan_origin oldact_origin,1687dfsan_origin *ret_origin) {1688return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,1689oldact_label, ret_label);1690}16911692static sighandler_t dfsan_signal(int signum, sighandler_t handler,1693dfsan_label *ret_label) {1694CHECK_LT(signum, kMaxSignals);1695SignalSpinLocker lock;1696uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);1697if (handler != SIG_IGN && handler != SIG_DFL) {1698atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);1699handler = &SignalHandler;1700}17011702sighandler_t ret = signal(signum, handler);17031704if (ret == SignalHandler)1705ret = (sighandler_t)old_cb;17061707*ret_label = 0;1708return ret;1709}17101711SANITIZER_INTERFACE_ATTRIBUTE1712sighandler_t __dfsw_signal(int signum, sighandler_t handler,1713dfsan_label signum_label, dfsan_label handler_label,1714dfsan_label *ret_label) {1715return dfsan_signal(signum, handler, ret_label);1716}17171718SANITIZER_INTERFACE_ATTRIBUTE1719sighandler_t __dfso_signal(int signum, sighandler_t handler,1720dfsan_label signum_label, dfsan_label handler_label,1721dfsan_label *ret_label, dfsan_origin signum_origin,1722dfsan_origin handler_origin,1723dfsan_origin *ret_origin) {1724return dfsan_signal(signum, handler, ret_label);1725}17261727SANITIZER_INTERFACE_ATTRIBUTE1728int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,1729dfsan_label old_ss_label, dfsan_label *ret_label) {1730int ret = sigaltstack(ss, old_ss);1731if (ret != -1 && old_ss)1732dfsan_set_label(0, old_ss, sizeof(*old_ss));1733*ret_label = 0;1734return ret;1735}17361737SANITIZER_INTERFACE_ATTRIBUTE1738int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,1739dfsan_label old_ss_label, dfsan_label *ret_label,1740dfsan_origin ss_origin, dfsan_origin old_ss_origin,1741dfsan_origin *ret_origin) {1742return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);1743}17441745SANITIZER_INTERFACE_ATTRIBUTE1746int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,1747dfsan_label tv_label, dfsan_label tz_label,1748dfsan_label *ret_label) {1749int ret = gettimeofday(tv, tz);1750if (tv) {1751dfsan_set_label(0, tv, sizeof(struct timeval));1752}1753if (tz) {1754dfsan_set_label(0, tz, sizeof(struct timezone));1755}1756*ret_label = 0;1757return ret;1758}17591760SANITIZER_INTERFACE_ATTRIBUTE1761int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,1762dfsan_label tv_label, dfsan_label tz_label,1763dfsan_label *ret_label, dfsan_origin tv_origin,1764dfsan_origin tz_origin, dfsan_origin *ret_origin) {1765return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);1766}17671768SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,1769dfsan_label s_label,1770dfsan_label c_label,1771dfsan_label n_label,1772dfsan_label *ret_label) {1773void *ret = memchr(s, c, n);1774if (flags().strict_data_dependencies) {1775*ret_label = ret ? s_label : 0;1776} else {1777size_t len =1778ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 11779: n;1780*ret_label =1781dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));1782}1783return ret;1784}17851786SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(1787void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,1788dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,1789dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {1790void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);1791if (flags().strict_data_dependencies) {1792if (ret)1793*ret_origin = s_origin;1794} else {1795size_t len =1796ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 11797: n;1798dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);1799*ret_origin = o ? o : (s_label ? s_origin : c_origin);1800}1801return ret;1802}18031804SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,1805dfsan_label s_label,1806dfsan_label c_label,1807dfsan_label *ret_label) {1808char *ret = strrchr(s, c);1809if (flags().strict_data_dependencies) {1810*ret_label = ret ? s_label : 0;1811} else {1812*ret_label =1813dfsan_union(dfsan_read_label(s, strlen(s) + 1),1814dfsan_union(s_label, c_label));1815}18161817return ret;1818}18191820SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(1821char *s, int c, dfsan_label s_label, dfsan_label c_label,1822dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,1823dfsan_origin *ret_origin) {1824char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);1825if (flags().strict_data_dependencies) {1826if (ret)1827*ret_origin = s_origin;1828} else {1829size_t s_len = strlen(s) + 1;1830dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);1831*ret_origin = o ? o : (s_label ? s_origin : c_origin);1832}18331834return ret;1835}18361837SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,1838dfsan_label haystack_label,1839dfsan_label needle_label,1840dfsan_label *ret_label) {1841char *ret = strstr(haystack, needle);1842if (flags().strict_data_dependencies) {1843*ret_label = ret ? haystack_label : 0;1844} else {1845size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;1846*ret_label =1847dfsan_union(dfsan_read_label(haystack, len),1848dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),1849dfsan_union(haystack_label, needle_label)));1850}18511852return ret;1853}18541855SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,1856dfsan_label haystack_label,1857dfsan_label needle_label,1858dfsan_label *ret_label,1859dfsan_origin haystack_origin,1860dfsan_origin needle_origin,1861dfsan_origin *ret_origin) {1862char *ret =1863__dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);1864if (flags().strict_data_dependencies) {1865if (ret)1866*ret_origin = haystack_origin;1867} else {1868size_t needle_len = strlen(needle);1869size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;1870dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);1871if (o) {1872*ret_origin = o;1873} else {1874o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);1875*ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);1876}1877}18781879return ret;1880}18811882SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,1883struct timespec *rem,1884dfsan_label req_label,1885dfsan_label rem_label,1886dfsan_label *ret_label) {1887int ret = nanosleep(req, rem);1888*ret_label = 0;1889if (ret == -1) {1890// Interrupted by a signal, rem is filled with the remaining time.1891dfsan_set_label(0, rem, sizeof(struct timespec));1892}1893return ret;1894}18951896SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(1897const struct timespec *req, struct timespec *rem, dfsan_label req_label,1898dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,1899dfsan_origin rem_origin, dfsan_origin *ret_origin) {1900return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);1901}19021903static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg,1904int flags) {1905dfsan_set_label(0, msg, sizeof(*msg));1906dfsan_set_label(0, msg->msg_name, msg->msg_namelen);1907dfsan_set_label(0, msg->msg_control, msg->msg_controllen);1908for (size_t i = 0; i < msg->msg_iovlen; ++i) {1909struct iovec *iov = &msg->msg_iov[i];1910size_t iov_written = iov->iov_len;19111912// When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that1913// may not have changed, using bytes_written to bound the 0 label write.1914// When MSG_TRUNC flag is set, bytes_written may be larger than the buffer,1915// and should not be used as a bound.1916if (!(MSG_TRUNC & flags)) {1917if (bytes_written < iov->iov_len) {1918iov_written = bytes_written;1919}1920bytes_written -= iov_written;1921}19221923dfsan_set_label(0, iov->iov_base, iov_written);1924}1925}19261927SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(1928int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,1929struct timespec *timeout, dfsan_label sockfd_label,1930dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,1931dfsan_label timeout_label, dfsan_label *ret_label) {1932int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);1933for (int i = 0; i < ret; ++i) {1934dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));1935clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags);1936}1937*ret_label = 0;1938return ret;1939}19401941SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(1942int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,1943struct timespec *timeout, dfsan_label sockfd_label,1944dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,1945dfsan_label timeout_label, dfsan_label *ret_label,1946dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,1947dfsan_origin vlen_origin, dfsan_origin flags_origin,1948dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1949return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,1950msgvec_label, vlen_label, flags_label, timeout_label,1951ret_label);1952}19531954SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(1955int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,1956dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {1957ssize_t ret = recvmsg(sockfd, msg, flags);1958if (ret >= 0)1959clear_msghdr_labels(ret, msg, flags);1960*ret_label = 0;1961return ret;1962}19631964SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(1965int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,1966dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,1967dfsan_origin sockfd_origin, dfsan_origin msg_origin,1968dfsan_origin flags_origin, dfsan_origin *ret_origin) {1969return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,1970flags_label, ret_label);1971}19721973SANITIZER_INTERFACE_ATTRIBUTE int1974__dfsw_socketpair(int domain, int type, int protocol, int sv[2],1975dfsan_label domain_label, dfsan_label type_label,1976dfsan_label protocol_label, dfsan_label sv_label,1977dfsan_label *ret_label) {1978int ret = socketpair(domain, type, protocol, sv);1979*ret_label = 0;1980if (ret == 0) {1981dfsan_set_label(0, sv, sizeof(*sv) * 2);1982}1983return ret;1984}19851986SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(1987int domain, int type, int protocol, int sv[2], dfsan_label domain_label,1988dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,1989dfsan_label *ret_label, dfsan_origin domain_origin,1990dfsan_origin type_origin, dfsan_origin protocol_origin,1991dfsan_origin sv_origin, dfsan_origin *ret_origin) {1992return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,1993protocol_label, sv_label, ret_label);1994}19951996SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(1997int sockfd, int level, int optname, void *optval, socklen_t *optlen,1998dfsan_label sockfd_label, dfsan_label level_label,1999dfsan_label optname_label, dfsan_label optval_label,2000dfsan_label optlen_label, dfsan_label *ret_label) {2001int ret = getsockopt(sockfd, level, optname, optval, optlen);2002if (ret != -1 && optval && optlen) {2003dfsan_set_label(0, optlen, sizeof(*optlen));2004dfsan_set_label(0, optval, *optlen);2005}2006*ret_label = 0;2007return ret;2008}20092010SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(2011int sockfd, int level, int optname, void *optval, socklen_t *optlen,2012dfsan_label sockfd_label, dfsan_label level_label,2013dfsan_label optname_label, dfsan_label optval_label,2014dfsan_label optlen_label, dfsan_label *ret_label,2015dfsan_origin sockfd_origin, dfsan_origin level_origin,2016dfsan_origin optname_origin, dfsan_origin optval_origin,2017dfsan_origin optlen_origin, dfsan_origin *ret_origin) {2018return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,2019level_label, optname_label, optval_label,2020optlen_label, ret_label);2021}20222023SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(2024int sockfd, struct sockaddr *addr, socklen_t *addrlen,2025dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2026dfsan_label *ret_label) {2027socklen_t origlen = addrlen ? *addrlen : 0;2028int ret = getsockname(sockfd, addr, addrlen);2029if (ret != -1 && addr && addrlen) {2030socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;2031dfsan_set_label(0, addrlen, sizeof(*addrlen));2032dfsan_set_label(0, addr, written_bytes);2033}2034*ret_label = 0;2035return ret;2036}20372038SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(2039int sockfd, struct sockaddr *addr, socklen_t *addrlen,2040dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2041dfsan_label *ret_label, dfsan_origin sockfd_origin,2042dfsan_origin addr_origin, dfsan_origin addrlen_origin,2043dfsan_origin *ret_origin) {2044return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,2045addrlen_label, ret_label);2046}20472048SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(2049int sockfd, struct sockaddr *addr, socklen_t *addrlen,2050dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2051dfsan_label *ret_label) {2052socklen_t origlen = addrlen ? *addrlen : 0;2053int ret = getpeername(sockfd, addr, addrlen);2054if (ret != -1 && addr && addrlen) {2055socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;2056dfsan_set_label(0, addrlen, sizeof(*addrlen));2057dfsan_set_label(0, addr, written_bytes);2058}2059*ret_label = 0;2060return ret;2061}20622063SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(2064int sockfd, struct sockaddr *addr, socklen_t *addrlen,2065dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2066dfsan_label *ret_label, dfsan_origin sockfd_origin,2067dfsan_origin addr_origin, dfsan_origin addrlen_origin,2068dfsan_origin *ret_origin) {2069return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,2070addrlen_label, ret_label);2071}20722073// Type of the function passed to dfsan_set_write_callback.2074typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);20752076// Calls to dfsan_set_write_callback() set the values in this struct.2077// Calls to the custom version of write() read (and invoke) them.2078static struct {2079write_dfsan_callback_t write_callback = nullptr;2080} write_callback_info;20812082SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(2083write_dfsan_callback_t write_callback, dfsan_label write_callback_label,2084dfsan_label *ret_label) {2085write_callback_info.write_callback = write_callback;2086}20872088SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(2089write_dfsan_callback_t write_callback, dfsan_label write_callback_label,2090dfsan_label *ret_label, dfsan_origin write_callback_origin,2091dfsan_origin *ret_origin) {2092write_callback_info.write_callback = write_callback;2093}20942095static inline void setup_tls_args_for_write_callback(2096dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,2097bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,2098dfsan_origin count_origin) {2099// The callback code will expect argument shadow labels in the args TLS,2100// and origin labels in the origin args TLS.2101// Previously this was done by a trampoline, but we want to remove this:2102// https://github.com/llvm/llvm-project/issues/541722103//2104// Instead, this code is manually setting up the args TLS data.2105//2106// The offsets used need to correspond with the instrumentation code,2107// see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp2108// DFSanFunction::getShadowForTLSArgument.2109// https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L16842110// https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1252111//2112// Here the arguments are all primitives, but it can be more complex2113// to compute offsets for array/aggregate type arguments.2114//2115// TODO(browneee): Consider a builtin to improve maintainabliity.2116// With a builtin, we would provide the argument labels via builtin,2117// and the builtin would reuse parts of the instrumentation code to ensure2118// that this code and the instrumentation can never be out of sync.2119// Note: Currently DFSan instrumentation does not run on this code, so2120// the builtin may need to be handled outside DFSan instrumentation.2121dfsan_set_arg_tls(0, fd_label);2122dfsan_set_arg_tls(1, buf_label);2123dfsan_set_arg_tls(2, count_label);2124if (origins) {2125dfsan_set_arg_origin_tls(0, fd_origin);2126dfsan_set_arg_origin_tls(1, buf_origin);2127dfsan_set_arg_origin_tls(2, count_origin);2128}2129}21302131SANITIZER_INTERFACE_ATTRIBUTE int2132__dfsw_write(int fd, const void *buf, size_t count,2133dfsan_label fd_label, dfsan_label buf_label,2134dfsan_label count_label, dfsan_label *ret_label) {2135if (write_callback_info.write_callback) {2136setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,21370, 0, 0);2138write_callback_info.write_callback(fd, buf, count);2139}21402141*ret_label = 0;2142return write(fd, buf, count);2143}21442145SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(2146int fd, const void *buf, size_t count, dfsan_label fd_label,2147dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,2148dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,2149dfsan_origin *ret_origin) {2150if (write_callback_info.write_callback) {2151setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,2152fd_origin, buf_origin, count_origin);2153write_callback_info.write_callback(fd, buf, count);2154}21552156*ret_label = 0;2157return write(fd, buf, count);2158}2159} // namespace __dfsan21602161// Type used to extract a dfsan_label with va_arg()2162typedef int dfsan_label_va;21632164// Formats a chunk either a constant string or a single format directive (e.g.,2165// '%.3f').2166struct Formatter {2167Formatter(char *str_, const char *fmt_, size_t size_)2168: str(str_),2169str_off(0),2170size(size_),2171fmt_start(fmt_),2172fmt_cur(fmt_),2173width(-1),2174num_scanned(-1),2175skip(false) {}21762177int format() {2178char *tmp_fmt = build_format_string();2179int retval =2180snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,21810 /* used only to avoid warnings */);2182free(tmp_fmt);2183return retval;2184}21852186template <typename T> int format(T arg) {2187char *tmp_fmt = build_format_string();2188int retval;2189if (width >= 0) {2190retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,2191tmp_fmt, width, arg);2192} else {2193retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,2194tmp_fmt, arg);2195}2196free(tmp_fmt);2197return retval;2198}21992200char *build_format_string() {2201size_t fmt_size = fmt_cur - fmt_start + 1;2202char *new_fmt = (char *)malloc(fmt_size + 1);2203assert(new_fmt);2204internal_memcpy(new_fmt, fmt_start, fmt_size);2205new_fmt[fmt_size] = '\0';2206return new_fmt;2207}22082209char *str_cur() { return str + str_off; }22102211size_t num_written_bytes(int retval) {2212if (retval < 0) {2213return 0;2214}22152216size_t num_avail = str_off < size ? size - str_off : 0;2217if (num_avail == 0) {2218return 0;2219}22202221size_t num_written = retval;2222// A return value of {v,}snprintf of size or more means that the output was2223// truncated.2224if (num_written >= num_avail) {2225num_written -= num_avail;2226}22272228return num_written;2229}22302231char *str;2232size_t str_off;2233size_t size;2234const char *fmt_start;2235const char *fmt_cur;2236int width;2237int num_scanned;2238bool skip;2239};22402241// Formats the input and propagates the input labels to the output. The output2242// is stored in 'str'. 'size' bounds the number of output bytes. 'format' and2243// 'ap' are the format string and the list of arguments for formatting. Returns2244// the return value vsnprintf would return.2245//2246// The function tokenizes the format string in chunks representing either a2247// constant string or a single format directive (e.g., '%.3f') and formats each2248// chunk independently into the output string. This approach allows to figure2249// out which bytes of the output string depends on which argument and thus to2250// propagate labels more precisely.2251//2252// WARNING: This implementation does not support conversion specifiers with2253// positional arguments.2254static int format_buffer(char *str, size_t size, const char *fmt,2255dfsan_label *va_labels, dfsan_label *ret_label,2256dfsan_origin *va_origins, dfsan_origin *ret_origin,2257va_list ap) {2258Formatter formatter(str, fmt, size);22592260while (*formatter.fmt_cur) {2261formatter.fmt_start = formatter.fmt_cur;2262formatter.width = -1;2263int retval = 0;22642265if (*formatter.fmt_cur != '%') {2266// Ordinary character. Consume all the characters until a '%' or the end2267// of the string.2268for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';2269++formatter.fmt_cur) {}2270retval = formatter.format();2271dfsan_set_label(0, formatter.str_cur(),2272formatter.num_written_bytes(retval));2273} else {2274// Conversion directive. Consume all the characters until a conversion2275// specifier or the end of the string.2276bool end_fmt = false;2277for (; *formatter.fmt_cur && !end_fmt; ) {2278switch (*++formatter.fmt_cur) {2279case 'd':2280case 'i':2281case 'o':2282case 'u':2283case 'x':2284case 'X':2285switch (*(formatter.fmt_cur - 1)) {2286case 'h':2287// Also covers the 'hh' case (since the size of the arg is still2288// an int).2289retval = formatter.format(va_arg(ap, int));2290break;2291case 'l':2292if (formatter.fmt_cur - formatter.fmt_start >= 2 &&2293*(formatter.fmt_cur - 2) == 'l') {2294retval = formatter.format(va_arg(ap, long long int));2295} else {2296retval = formatter.format(va_arg(ap, long int));2297}2298break;2299case 'q':2300retval = formatter.format(va_arg(ap, long long int));2301break;2302case 'j':2303retval = formatter.format(va_arg(ap, intmax_t));2304break;2305case 'z':2306case 't':2307retval = formatter.format(va_arg(ap, size_t));2308break;2309default:2310retval = formatter.format(va_arg(ap, int));2311}2312if (va_origins == nullptr)2313dfsan_set_label(*va_labels++, formatter.str_cur(),2314formatter.num_written_bytes(retval));2315else2316dfsan_set_label_origin(*va_labels++, *va_origins++,2317formatter.str_cur(),2318formatter.num_written_bytes(retval));2319end_fmt = true;2320break;23212322case 'a':2323case 'A':2324case 'e':2325case 'E':2326case 'f':2327case 'F':2328case 'g':2329case 'G':2330if (*(formatter.fmt_cur - 1) == 'L') {2331retval = formatter.format(va_arg(ap, long double));2332} else {2333retval = formatter.format(va_arg(ap, double));2334}2335if (va_origins == nullptr)2336dfsan_set_label(*va_labels++, formatter.str_cur(),2337formatter.num_written_bytes(retval));2338else2339dfsan_set_label_origin(*va_labels++, *va_origins++,2340formatter.str_cur(),2341formatter.num_written_bytes(retval));2342end_fmt = true;2343break;23442345case 'c':2346retval = formatter.format(va_arg(ap, int));2347if (va_origins == nullptr)2348dfsan_set_label(*va_labels++, formatter.str_cur(),2349formatter.num_written_bytes(retval));2350else2351dfsan_set_label_origin(*va_labels++, *va_origins++,2352formatter.str_cur(),2353formatter.num_written_bytes(retval));2354end_fmt = true;2355break;23562357case 's': {2358char *arg = va_arg(ap, char *);2359retval = formatter.format(arg);2360if (va_origins) {2361va_origins++;2362dfsan_mem_origin_transfer(formatter.str_cur(), arg,2363formatter.num_written_bytes(retval));2364}2365va_labels++;2366dfsan_mem_shadow_transfer(formatter.str_cur(), arg,2367formatter.num_written_bytes(retval));2368end_fmt = true;2369break;2370}23712372case 'p':2373retval = formatter.format(va_arg(ap, void *));2374if (va_origins == nullptr)2375dfsan_set_label(*va_labels++, formatter.str_cur(),2376formatter.num_written_bytes(retval));2377else2378dfsan_set_label_origin(*va_labels++, *va_origins++,2379formatter.str_cur(),2380formatter.num_written_bytes(retval));2381end_fmt = true;2382break;23832384case 'n': {2385int *ptr = va_arg(ap, int *);2386*ptr = (int)formatter.str_off;2387va_labels++;2388if (va_origins)2389va_origins++;2390dfsan_set_label(0, ptr, sizeof(ptr));2391end_fmt = true;2392break;2393}23942395case '%':2396retval = formatter.format();2397dfsan_set_label(0, formatter.str_cur(),2398formatter.num_written_bytes(retval));2399end_fmt = true;2400break;24012402case '*':2403formatter.width = va_arg(ap, int);2404va_labels++;2405if (va_origins)2406va_origins++;2407break;24082409default:2410break;2411}2412}2413}24142415if (retval < 0) {2416return retval;2417}24182419formatter.fmt_cur++;2420formatter.str_off += retval;2421}24222423*ret_label = 0;2424if (ret_origin)2425*ret_origin = 0;24262427// Number of bytes written in total.2428return formatter.str_off;2429}24302431// Scans a chunk either a constant string or a single format directive (e.g.,2432// '%.3f').2433struct Scanner {2434Scanner(char *str_, const char *fmt_, size_t size_)2435: str(str_),2436str_off(0),2437size(size_),2438fmt_start(fmt_),2439fmt_cur(fmt_),2440width(-1),2441num_scanned(0),2442skip(false) {}24432444// Consumes a chunk of ordinary characters.2445// Returns number of matching ordinary characters.2446// Returns -1 if the match failed.2447// In format strings, a space will match multiple spaces.2448int check_match_ordinary() {2449char *tmp_fmt = build_format_string_with_n();2450int read_count = -1;2451sscanf(str + str_off, tmp_fmt, &read_count);2452free(tmp_fmt);2453if (read_count > 0) {2454str_off += read_count;2455}2456return read_count;2457}24582459int scan() {2460char *tmp_fmt = build_format_string_with_n();2461int read_count = 0;2462int retval = sscanf(str + str_off, tmp_fmt, &read_count);2463free(tmp_fmt);2464if (retval > 0) {2465num_scanned += retval;2466}2467return read_count;2468}24692470template <typename T>2471int scan(T arg) {2472char *tmp_fmt = build_format_string_with_n();2473int read_count = 0;2474int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count);2475free(tmp_fmt);2476if (retval > 0) {2477num_scanned += retval;2478}2479return read_count;2480}24812482// Adds %n onto current format string to measure length.2483char *build_format_string_with_n() {2484size_t fmt_size = fmt_cur - fmt_start + 1;2485// +2 for %n, +1 for \02486char *new_fmt = (char *)malloc(fmt_size + 2 + 1);2487assert(new_fmt);2488internal_memcpy(new_fmt, fmt_start, fmt_size);2489new_fmt[fmt_size] = '%';2490new_fmt[fmt_size + 1] = 'n';2491new_fmt[fmt_size + 2] = '\0';2492return new_fmt;2493}24942495char *str_cur() { return str + str_off; }24962497size_t num_written_bytes(int retval) {2498if (retval < 0) {2499return 0;2500}25012502size_t num_avail = str_off < size ? size - str_off : 0;2503if (num_avail == 0) {2504return 0;2505}25062507size_t num_written = retval;2508// A return value of {v,}snprintf of size or more means that the output was2509// truncated.2510if (num_written >= num_avail) {2511num_written -= num_avail;2512}25132514return num_written;2515}25162517char *str;2518size_t str_off;2519size_t size;2520const char *fmt_start;2521const char *fmt_cur;2522int width;2523int num_scanned;2524bool skip;2525};25262527// This function is an inverse of format_buffer: we take the input buffer,2528// scan it in search for format strings and store the results in the varargs.2529// The labels are propagated from the input buffer to the varargs.2530static int scan_buffer(char *str, size_t size, const char *fmt,2531dfsan_label *va_labels, dfsan_label *ret_label,2532dfsan_origin *str_origin, dfsan_origin *ret_origin,2533va_list ap) {2534Scanner scanner(str, fmt, size);2535while (*scanner.fmt_cur) {2536scanner.fmt_start = scanner.fmt_cur;2537scanner.width = -1;2538scanner.skip = false;2539int read_count = 0;2540void *dst_ptr = 0;2541size_t write_size = 0;2542if (*scanner.fmt_cur != '%') {2543// Ordinary character and spaces.2544// Consume all the characters until a '%' or the end of the string.2545for (; *(scanner.fmt_cur + 1) && *(scanner.fmt_cur + 1) != '%';2546++scanner.fmt_cur) {2547}2548if (scanner.check_match_ordinary() < 0) {2549// The ordinary characters did not match.2550break;2551}2552} else {2553// Conversion directive. Consume all the characters until a conversion2554// specifier or the end of the string.2555bool end_fmt = false;2556for (; *scanner.fmt_cur && !end_fmt;) {2557switch (*++scanner.fmt_cur) {2558case 'd':2559case 'i':2560case 'o':2561case 'u':2562case 'x':2563case 'X':2564if (scanner.skip) {2565read_count = scanner.scan();2566} else {2567switch (*(scanner.fmt_cur - 1)) {2568case 'h':2569// Also covers the 'hh' case (since the size of the arg is2570// still an int).2571dst_ptr = va_arg(ap, int *);2572read_count = scanner.scan((int *)dst_ptr);2573write_size = sizeof(int);2574break;2575case 'l':2576if (scanner.fmt_cur - scanner.fmt_start >= 2 &&2577*(scanner.fmt_cur - 2) == 'l') {2578dst_ptr = va_arg(ap, long long int *);2579read_count = scanner.scan((long long int *)dst_ptr);2580write_size = sizeof(long long int);2581} else {2582dst_ptr = va_arg(ap, long int *);2583read_count = scanner.scan((long int *)dst_ptr);2584write_size = sizeof(long int);2585}2586break;2587case 'q':2588dst_ptr = va_arg(ap, long long int *);2589read_count = scanner.scan((long long int *)dst_ptr);2590write_size = sizeof(long long int);2591break;2592case 'j':2593dst_ptr = va_arg(ap, intmax_t *);2594read_count = scanner.scan((intmax_t *)dst_ptr);2595write_size = sizeof(intmax_t);2596break;2597case 'z':2598case 't':2599dst_ptr = va_arg(ap, size_t *);2600read_count = scanner.scan((size_t *)dst_ptr);2601write_size = sizeof(size_t);2602break;2603default:2604dst_ptr = va_arg(ap, int *);2605read_count = scanner.scan((int *)dst_ptr);2606write_size = sizeof(int);2607}2608// get the label associated with the string at the corresponding2609// place2610dfsan_label l = dfsan_read_label(2611scanner.str_cur(), scanner.num_written_bytes(read_count));2612dfsan_set_label(l, dst_ptr, write_size);2613if (str_origin != nullptr) {2614dfsan_set_label(l, dst_ptr, write_size);2615size_t scan_count = scanner.num_written_bytes(read_count);2616size_t size = scan_count > write_size ? write_size : scan_count;2617dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2618}2619}2620end_fmt = true;26212622break;26232624case 'a':2625case 'A':2626case 'e':2627case 'E':2628case 'f':2629case 'F':2630case 'g':2631case 'G':2632if (scanner.skip) {2633read_count = scanner.scan();2634} else {2635if (*(scanner.fmt_cur - 1) == 'L') {2636dst_ptr = va_arg(ap, long double *);2637read_count = scanner.scan((long double *)dst_ptr);2638write_size = sizeof(long double);2639} else if (*(scanner.fmt_cur - 1) == 'l') {2640dst_ptr = va_arg(ap, double *);2641read_count = scanner.scan((double *)dst_ptr);2642write_size = sizeof(double);2643} else {2644dst_ptr = va_arg(ap, float *);2645read_count = scanner.scan((float *)dst_ptr);2646write_size = sizeof(float);2647}2648dfsan_label l = dfsan_read_label(2649scanner.str_cur(), scanner.num_written_bytes(read_count));2650dfsan_set_label(l, dst_ptr, write_size);2651if (str_origin != nullptr) {2652dfsan_set_label(l, dst_ptr, write_size);2653size_t scan_count = scanner.num_written_bytes(read_count);2654size_t size = scan_count > write_size ? write_size : scan_count;2655dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2656}2657}2658end_fmt = true;2659break;26602661case 'c':2662if (scanner.skip) {2663read_count = scanner.scan();2664} else {2665dst_ptr = va_arg(ap, char *);2666read_count = scanner.scan((char *)dst_ptr);2667write_size = sizeof(char);2668dfsan_label l = dfsan_read_label(2669scanner.str_cur(), scanner.num_written_bytes(read_count));2670dfsan_set_label(l, dst_ptr, write_size);2671if (str_origin != nullptr) {2672size_t scan_count = scanner.num_written_bytes(read_count);2673size_t size = scan_count > write_size ? write_size : scan_count;2674dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2675}2676}2677end_fmt = true;2678break;26792680case 's': {2681if (scanner.skip) {2682read_count = scanner.scan();2683} else {2684dst_ptr = va_arg(ap, char *);2685read_count = scanner.scan((char *)dst_ptr);2686if (1 == read_count) {2687// special case: we have parsed a single string and we need to2688// update read_count with the string size2689read_count = strlen((char *)dst_ptr);2690}2691if (str_origin)2692dfsan_mem_origin_transfer(2693dst_ptr, scanner.str_cur(),2694scanner.num_written_bytes(read_count));2695va_labels++;2696dfsan_mem_shadow_transfer(dst_ptr, scanner.str_cur(),2697scanner.num_written_bytes(read_count));2698}2699end_fmt = true;2700break;2701}27022703case 'p':2704if (scanner.skip) {2705read_count = scanner.scan();2706} else {2707dst_ptr = va_arg(ap, void *);2708read_count =2709scanner.scan((int *)dst_ptr); // note: changing void* to int*2710// since we need to call sizeof2711write_size = sizeof(int);27122713dfsan_label l = dfsan_read_label(2714scanner.str_cur(), scanner.num_written_bytes(read_count));2715dfsan_set_label(l, dst_ptr, write_size);2716if (str_origin != nullptr) {2717dfsan_set_label(l, dst_ptr, write_size);2718size_t scan_count = scanner.num_written_bytes(read_count);2719size_t size = scan_count > write_size ? write_size : scan_count;2720dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2721}2722}2723end_fmt = true;2724break;27252726case 'n': {2727if (!scanner.skip) {2728int *ptr = va_arg(ap, int *);2729*ptr = (int)scanner.str_off;2730*va_labels++ = 0;2731dfsan_set_label(0, ptr, sizeof(*ptr));2732if (str_origin != nullptr)2733*str_origin++ = 0;2734}2735end_fmt = true;2736break;2737}27382739case '%':2740read_count = scanner.scan();2741end_fmt = true;2742break;27432744case '*':2745scanner.skip = true;2746break;27472748default:2749break;2750}2751}2752}27532754if (read_count < 0) {2755// There was an error.2756return read_count;2757}27582759scanner.fmt_cur++;2760scanner.str_off += read_count;2761}27622763(void)va_labels; // Silence unused-but-set-parameter warning2764*ret_label = 0;2765if (ret_origin)2766*ret_origin = 0;27672768// Number of items scanned in total.2769return scanner.num_scanned;2770}27712772extern "C" {2773SANITIZER_INTERFACE_ATTRIBUTE2774int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,2775dfsan_label format_label, dfsan_label *va_labels,2776dfsan_label *ret_label, ...) {2777va_list ap;2778va_start(ap, ret_label);27792780int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, nullptr,2781nullptr, ap);2782va_end(ap);2783return ret;2784}27852786SANITIZER_INTERFACE_ATTRIBUTE2787int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,2788dfsan_label format_label, dfsan_label *va_labels,2789dfsan_label *ret_label, dfsan_origin str_origin,2790dfsan_origin format_origin, dfsan_origin *va_origins,2791dfsan_origin *ret_origin, ...) {2792va_list ap;2793va_start(ap, ret_origin);2794int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label,2795va_origins, ret_origin, ap);2796va_end(ap);2797return ret;2798}27992800SANITIZER_INTERFACE_ATTRIBUTE2801int __dfsw_snprintf(char *str, size_t size, const char *format,2802dfsan_label str_label, dfsan_label size_label,2803dfsan_label format_label, dfsan_label *va_labels,2804dfsan_label *ret_label, ...) {2805va_list ap;2806va_start(ap, ret_label);2807int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,2808nullptr, ap);2809va_end(ap);2810return ret;2811}28122813SANITIZER_INTERFACE_ATTRIBUTE2814int __dfso_snprintf(char *str, size_t size, const char *format,2815dfsan_label str_label, dfsan_label size_label,2816dfsan_label format_label, dfsan_label *va_labels,2817dfsan_label *ret_label, dfsan_origin str_origin,2818dfsan_origin size_origin, dfsan_origin format_origin,2819dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {2820va_list ap;2821va_start(ap, ret_origin);2822int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,2823ret_origin, ap);2824va_end(ap);2825return ret;2826}28272828SANITIZER_INTERFACE_ATTRIBUTE2829int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label,2830dfsan_label format_label, dfsan_label *va_labels,2831dfsan_label *ret_label, ...) {2832va_list ap;2833va_start(ap, ret_label);2834int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,2835nullptr, ap);2836va_end(ap);2837return ret;2838}28392840SANITIZER_INTERFACE_ATTRIBUTE2841int __dfso_sscanf(char *str, const char *format, dfsan_label str_label,2842dfsan_label format_label, dfsan_label *va_labels,2843dfsan_label *ret_label, dfsan_origin str_origin,2844dfsan_origin format_origin, dfsan_origin *va_origins,2845dfsan_origin *ret_origin, ...) {2846va_list ap;2847va_start(ap, ret_origin);2848int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,2849ret_origin, ap);2850va_end(ap);2851return ret;2852}28532854WRAPPER_ALIAS(__isoc99_sscanf, sscanf)2855WRAPPER_ALIAS(__isoc23_sscanf, sscanf)28562857static void BeforeFork() {2858StackDepotLockBeforeFork();2859ChainedOriginDepotLockBeforeFork();2860}28612862static void AfterFork(bool fork_child) {2863ChainedOriginDepotUnlockAfterFork(fork_child);2864StackDepotUnlockAfterFork(fork_child);2865}28662867SANITIZER_INTERFACE_ATTRIBUTE2868pid_t __dfsw_fork(dfsan_label *ret_label) {2869pid_t pid = fork();2870*ret_label = 0;2871return pid;2872}28732874SANITIZER_INTERFACE_ATTRIBUTE2875pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {2876BeforeFork();2877pid_t pid = __dfsw_fork(ret_label);2878AfterFork(/* fork_child= */ pid == 0);2879return pid;2880}28812882// Default empty implementations (weak). Users should redefine them.2883SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}2884SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,2885u32 *) {}2886SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,2887const uptr *end) {}2888SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}28892890SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}2891SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}2892SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}2893SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}2894SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}2895SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,2896void) {}2897SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,2898void) {}2899SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,2900void) {}2901SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,2902void) {}2903SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}2904} // extern "C"290529062907