2911 lines · cpp
1//===-- dfsan_custom.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of DataFlowSanitizer.10//11// This file defines the custom functions listed in done_abilist.txt.12//===----------------------------------------------------------------------===//13 14#include <arpa/inet.h>15#include <assert.h>16#include <ctype.h>17#include <dlfcn.h>18#include <link.h>19#include <poll.h>20#include <pthread.h>21#include <pwd.h>22#include <sched.h>23#include <signal.h>24#include <stdarg.h>25#include <stdint.h>26#include <stdio.h>27#include <stdlib.h>28#include <string.h>29#include <sys/epoll.h>30#include <sys/resource.h>31#include <sys/select.h>32#include <sys/socket.h>33#include <sys/stat.h>34#include <sys/time.h>35#include <sys/types.h>36#include <time.h>37#include <unistd.h>38 39#include "dfsan/dfsan.h"40#include "dfsan/dfsan_chained_origin_depot.h"41#include "dfsan/dfsan_flags.h"42#include "dfsan/dfsan_thread.h"43#include "sanitizer_common/sanitizer_common.h"44#include "sanitizer_common/sanitizer_internal_defs.h"45#include "sanitizer_common/sanitizer_linux.h"46#include "sanitizer_common/sanitizer_stackdepot.h"47 48using namespace __dfsan;49 50#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \51 do { \52 if (f) \53 f(__VA_ARGS__); \54 } while (false)55#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \56SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);57 58#define WRAPPER_ALIAS(fun, real) \59 SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \60 SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);61 62// Async-safe, non-reentrant spin lock.63namespace {64class SignalSpinLocker {65 public:66 SignalSpinLocker() {67 sigset_t all_set;68 sigfillset(&all_set);69 pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);70 sigactions_mu.Lock();71 }72 ~SignalSpinLocker() {73 sigactions_mu.Unlock();74 pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);75 }76 77 private:78 static StaticSpinMutex sigactions_mu;79 sigset_t saved_thread_mask_;80 81 SignalSpinLocker(const SignalSpinLocker &) = delete;82 SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;83};84} // namespace85 86StaticSpinMutex SignalSpinLocker::sigactions_mu;87 88extern "C" {89SANITIZER_INTERFACE_ATTRIBUTE int90__dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,91 dfsan_label buf_label, dfsan_label *ret_label) {92 int ret = stat(path, buf);93 if (ret == 0)94 dfsan_set_label(0, buf, sizeof(struct stat));95 *ret_label = 0;96 return ret;97}98 99SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(100 const char *path, struct stat *buf, dfsan_label path_label,101 dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,102 dfsan_origin buf_origin, dfsan_origin *ret_origin) {103 int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);104 return ret;105}106 107SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,108 dfsan_label fd_label,109 dfsan_label buf_label,110 dfsan_label *ret_label) {111 int ret = fstat(fd, buf);112 if (ret == 0)113 dfsan_set_label(0, buf, sizeof(struct stat));114 *ret_label = 0;115 return ret;116}117 118SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(119 int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,120 dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,121 dfsan_origin *ret_origin) {122 int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);123 return ret;124}125 126static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,127 dfsan_label s_label, dfsan_label c_label,128 dfsan_label *ret_label) {129 char *match_pos = nullptr;130 for (size_t i = 0;; ++i) {131 if (s[i] == c || s[i] == 0) {132 // If s[i] is the \0 at the end of the string, and \0 is not the133 // character we are searching for, then return null.134 *bytes_read = i + 1;135 match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);136 break;137 }138 }139 if (flags().strict_data_dependencies)140 *ret_label = s_label;141 else142 *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),143 dfsan_union(s_label, c_label));144 return match_pos;145}146 147SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,148 dfsan_label s_label,149 dfsan_label c_label,150 dfsan_label *ret_label) {151 size_t bytes_read;152 return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,153 ret_label);154}155 156SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(157 const char *s, int c, dfsan_label s_label, dfsan_label c_label,158 dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,159 dfsan_origin *ret_origin) {160 size_t bytes_read;161 char *r =162 dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);163 if (flags().strict_data_dependencies) {164 *ret_origin = s_origin;165 } else if (*ret_label) {166 dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);167 *ret_origin = o ? o : (s_label ? s_origin : c_origin);168 }169 return r;170}171 172SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,173 const char *accept,174 dfsan_label s_label,175 dfsan_label accept_label,176 dfsan_label *ret_label) {177 const char *ret = strpbrk(s, accept);178 if (flags().strict_data_dependencies) {179 *ret_label = ret ? s_label : 0;180 } else {181 size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;182 *ret_label =183 dfsan_union(dfsan_read_label(s, s_bytes_read),184 dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),185 dfsan_union(s_label, accept_label)));186 }187 return const_cast<char *>(ret);188}189 190SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(191 const char *s, const char *accept, dfsan_label s_label,192 dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,193 dfsan_origin accept_origin, dfsan_origin *ret_origin) {194 const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);195 if (flags().strict_data_dependencies) {196 if (ret)197 *ret_origin = s_origin;198 } else {199 if (*ret_label) {200 size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;201 dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);202 if (o) {203 *ret_origin = o;204 } else {205 o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);206 *ret_origin = o ? o : (s_label ? s_origin : accept_origin);207 }208 }209 }210 return const_cast<char *>(ret);211}212 213SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim,214 dfsan_label s_label,215 dfsan_label delim_label,216 dfsan_label *ret_label) {217 dfsan_label base_label = dfsan_read_label(s, sizeof(*s));218 char *base = *s;219 char *res = strsep(s, delim);220 if (res != *s) {221 char *token_start = res;222 int token_length = strlen(res);223 // the delimiter byte has been set to NULL224 dfsan_set_label(0, token_start + token_length, 1);225 }226 227 if (flags().strict_data_dependencies) {228 *ret_label = res ? base_label : 0;229 } else {230 size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;231 *ret_label = dfsan_union(232 dfsan_union(base_label, dfsan_read_label(base, sizeof(s_bytes_read))),233 dfsan_union(dfsan_read_label(delim, strlen(delim) + 1),234 dfsan_union(s_label, delim_label)));235 }236 237 return res;238}239 240SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep(241 char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label,242 dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin,243 dfsan_origin *ret_origin) {244 dfsan_origin base_origin = dfsan_read_origin_of_first_taint(s, sizeof(*s));245 char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label);246 if (flags().strict_data_dependencies) {247 if (res)248 *ret_origin = base_origin;249 } else {250 if (*ret_label) {251 if (base_origin) {252 *ret_origin = base_origin;253 } else {254 dfsan_origin o =255 dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1);256 *ret_origin = o ? o : (s_label ? s_origin : delim_origin);257 }258 }259 }260 261 return res;262}263 264static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,265 size_t *bytes_read) {266 const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;267 for (size_t i = 0; i != n; ++i) {268 if (cs1[i] != cs2[i]) {269 *bytes_read = i + 1;270 return cs1[i] - cs2[i];271 }272 }273 *bytes_read = n;274 return 0;275}276 277static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,278 size_t pos) {279 if (flags().strict_data_dependencies)280 return 0;281 return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));282}283 284static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,285 dfsan_label *ret_label,286 dfsan_origin *ret_origin) {287 *ret_label = dfsan_get_memcmp_label(s1, s2, pos);288 if (*ret_label == 0)289 return;290 dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);291 *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);292}293 294static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,295 dfsan_label *ret_label) {296 size_t bytes_read;297 int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);298 *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);299 return r;300}301 302static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,303 dfsan_label *ret_label,304 dfsan_origin *ret_origin) {305 size_t bytes_read;306 int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);307 dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);308 return r;309}310 311DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,312 const void *s1, const void *s2, size_t n,313 dfsan_label s1_label, dfsan_label s2_label,314 dfsan_label n_label)315 316DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,317 const void *s1, const void *s2, size_t n,318 dfsan_label s1_label, dfsan_label s2_label,319 dfsan_label n_label, dfsan_origin s1_origin,320 dfsan_origin s2_origin, dfsan_origin n_origin)321 322SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,323 size_t n, dfsan_label s1_label,324 dfsan_label s2_label,325 dfsan_label n_label,326 dfsan_label *ret_label) {327 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,328 s1_label, s2_label, n_label);329 return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);330}331 332SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(333 const void *s1, const void *s2, size_t n, dfsan_label s1_label,334 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,335 dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,336 dfsan_origin *ret_origin) {337 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,338 s2, n, s1_label, s2_label, n_label, s1_origin,339 s2_origin, n_origin);340 return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);341}342 343SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,344 size_t n, dfsan_label s1_label,345 dfsan_label s2_label,346 dfsan_label n_label,347 dfsan_label *ret_label) {348 return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);349}350 351SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(352 const void *s1, const void *s2, size_t n, dfsan_label s1_label,353 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,354 dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,355 dfsan_origin *ret_origin) {356 return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);357}358 359// When n == 0, compare strings without byte limit.360// When n > 0, compare the first (at most) n bytes of s1 and s2.361static int dfsan_strncmp(const char *s1, const char *s2, size_t n,362 size_t *bytes_read) {363 for (size_t i = 0;; ++i) {364 if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {365 *bytes_read = i + 1;366 return s1[i] - s2[i];367 }368 }369}370 371DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,372 const char *s1, const char *s2,373 dfsan_label s1_label, dfsan_label s2_label)374 375DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,376 const char *s1, const char *s2,377 dfsan_label s1_label, dfsan_label s2_label,378 dfsan_origin s1_origin, dfsan_origin s2_origin)379 380SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,381 dfsan_label s1_label,382 dfsan_label s2_label,383 dfsan_label *ret_label) {384 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,385 s1_label, s2_label);386 size_t bytes_read;387 int r = dfsan_strncmp(s1, s2, 0, &bytes_read);388 *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);389 return r;390}391 392SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(393 const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,394 dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,395 dfsan_origin *ret_origin) {396 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,397 s2, s1_label, s2_label, s1_origin, s2_origin);398 size_t bytes_read;399 int r = dfsan_strncmp(s1, s2, 0, &bytes_read);400 dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);401 return r;402}403 404// When n == 0, compare strings without byte limit.405// When n > 0, compare the first (at most) n bytes of s1 and s2.406static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,407 size_t *bytes_read) {408 for (size_t i = 0;; ++i) {409 char s1_lower = tolower(s1[i]);410 char s2_lower = tolower(s2[i]);411 412 if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||413 (n > 0 && i == n - 1)) {414 *bytes_read = i + 1;415 return s1_lower - s2_lower;416 }417 }418}419 420SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,421 const char *s2,422 dfsan_label s1_label,423 dfsan_label s2_label,424 dfsan_label *ret_label) {425 size_t bytes_read;426 int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);427 *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);428 return r;429}430 431SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(432 const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,433 dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,434 dfsan_origin *ret_origin) {435 size_t bytes_read;436 int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);437 dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);438 return r;439}440 441DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,442 const char *s1, const char *s2, size_t n,443 dfsan_label s1_label, dfsan_label s2_label,444 dfsan_label n_label)445 446DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,447 const char *s1, const char *s2, size_t n,448 dfsan_label s1_label, dfsan_label s2_label,449 dfsan_label n_label, dfsan_origin s1_origin,450 dfsan_origin s2_origin, dfsan_origin n_origin)451 452SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,453 size_t n, dfsan_label s1_label,454 dfsan_label s2_label,455 dfsan_label n_label,456 dfsan_label *ret_label) {457 if (n == 0) {458 *ret_label = 0;459 return 0;460 }461 462 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,463 n, s1_label, s2_label, n_label);464 465 size_t bytes_read;466 int r = dfsan_strncmp(s1, s2, n, &bytes_read);467 *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);468 return r;469}470 471SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(472 const char *s1, const char *s2, size_t n, dfsan_label s1_label,473 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,474 dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,475 dfsan_origin *ret_origin) {476 if (n == 0) {477 *ret_label = 0;478 return 0;479 }480 481 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),482 s1, s2, n, s1_label, s2_label, n_label, s1_origin,483 s2_origin, n_origin);484 485 size_t bytes_read;486 int r = dfsan_strncmp(s1, s2, n, &bytes_read);487 dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);488 return r;489}490 491SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(492 const char *s1, const char *s2, size_t n, dfsan_label s1_label,493 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {494 if (n == 0) {495 *ret_label = 0;496 return 0;497 }498 499 size_t bytes_read;500 int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);501 *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);502 return r;503}504 505SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(506 const char *s1, const char *s2, size_t n, dfsan_label s1_label,507 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,508 dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,509 dfsan_origin *ret_origin) {510 if (n == 0) {511 *ret_label = 0;512 return 0;513 }514 515 size_t bytes_read;516 int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);517 dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);518 return r;519}520 521 522SANITIZER_INTERFACE_ATTRIBUTE size_t523__dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {524 size_t ret = strlen(s);525 if (flags().strict_data_dependencies) {526 *ret_label = 0;527 } else {528 *ret_label = dfsan_read_label(s, ret + 1);529 }530 return ret;531}532 533SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,534 dfsan_label s_label,535 dfsan_label *ret_label,536 dfsan_origin s_origin,537 dfsan_origin *ret_origin) {538 size_t ret = __dfsw_strlen(s, s_label, ret_label);539 if (!flags().strict_data_dependencies)540 *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);541 return ret;542}543 544SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s,545 size_t maxlen,546 dfsan_label s_label,547 dfsan_label maxlen_label,548 dfsan_label *ret_label) {549 size_t ret = strnlen(s, maxlen);550 if (flags().strict_data_dependencies) {551 *ret_label = 0;552 } else {553 size_t full_len = strlen(s);554 size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;555 *ret_label = dfsan_union(maxlen_label, dfsan_read_label(s, covered_len));556 }557 return ret;558}559 560SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen(561 const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label,562 dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin,563 dfsan_origin *ret_origin) {564 size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label);565 if (!flags().strict_data_dependencies) {566 size_t full_len = strlen(s);567 size_t covered_len = maxlen > (full_len + 1) ? (full_len + 1) : maxlen;568 dfsan_origin o = dfsan_read_origin_of_first_taint(s, covered_len);569 *ret_origin = o ? o : maxlen_origin;570 }571 return ret;572}573 574static void *dfsan_memmove(void *dest, const void *src, size_t n) {575 dfsan_label *sdest = shadow_for(dest);576 const dfsan_label *ssrc = shadow_for(src);577 internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));578 return internal_memmove(dest, src, n);579}580 581static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {582 dfsan_mem_origin_transfer(dest, src, n);583 return dfsan_memmove(dest, src, n);584}585 586static void *dfsan_memcpy(void *dest, const void *src, size_t n) {587 dfsan_mem_shadow_transfer(dest, src, n);588 return internal_memcpy(dest, src, n);589}590 591static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {592 dfsan_mem_origin_transfer(dest, src, n);593 return dfsan_memcpy(dest, src, n);594}595 596static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {597 internal_memset(s, c, n);598 dfsan_set_label(c_label, s, n);599}600 601static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,602 dfsan_origin c_origin, size_t n) {603 internal_memset(s, c, n);604 dfsan_set_label_origin(c_label, c_origin, s, n);605}606 607SANITIZER_INTERFACE_ATTRIBUTE608void *__dfsw_memcpy(void *dest, const void *src, size_t n,609 dfsan_label dest_label, dfsan_label src_label,610 dfsan_label n_label, dfsan_label *ret_label) {611 *ret_label = dest_label;612 return dfsan_memcpy(dest, src, n);613}614 615SANITIZER_INTERFACE_ATTRIBUTE616void *__dfso_memcpy(void *dest, const void *src, size_t n,617 dfsan_label dest_label, dfsan_label src_label,618 dfsan_label n_label, dfsan_label *ret_label,619 dfsan_origin dest_origin, dfsan_origin src_origin,620 dfsan_origin n_origin, dfsan_origin *ret_origin) {621 *ret_label = dest_label;622 *ret_origin = dest_origin;623 return dfsan_memcpy_with_origin(dest, src, n);624}625 626SANITIZER_INTERFACE_ATTRIBUTE627void *__dfsw_memmove(void *dest, const void *src, size_t n,628 dfsan_label dest_label, dfsan_label src_label,629 dfsan_label n_label, dfsan_label *ret_label) {630 *ret_label = dest_label;631 return dfsan_memmove(dest, src, n);632}633 634SANITIZER_INTERFACE_ATTRIBUTE635void *__dfso_memmove(void *dest, const void *src, size_t n,636 dfsan_label dest_label, dfsan_label src_label,637 dfsan_label n_label, dfsan_label *ret_label,638 dfsan_origin dest_origin, dfsan_origin src_origin,639 dfsan_origin n_origin, dfsan_origin *ret_origin) {640 *ret_label = dest_label;641 *ret_origin = dest_origin;642 return dfsan_memmove_with_origin(dest, src, n);643}644 645SANITIZER_INTERFACE_ATTRIBUTE646void *__dfsw_memset(void *s, int c, size_t n,647 dfsan_label s_label, dfsan_label c_label,648 dfsan_label n_label, dfsan_label *ret_label) {649 dfsan_memset(s, c, c_label, n);650 *ret_label = s_label;651 return s;652}653 654SANITIZER_INTERFACE_ATTRIBUTE655void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,656 dfsan_label c_label, dfsan_label n_label,657 dfsan_label *ret_label, dfsan_origin s_origin,658 dfsan_origin c_origin, dfsan_origin n_origin,659 dfsan_origin *ret_origin) {660 dfsan_memset_with_origin(s, c, c_label, c_origin, n);661 *ret_label = s_label;662 *ret_origin = s_origin;663 return s;664}665 666SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,667 dfsan_label dest_label,668 dfsan_label src_label,669 dfsan_label *ret_label) {670 size_t dest_len = strlen(dest);671 char *ret = strcat(dest, src);672 dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));673 *ret_label = dest_label;674 return ret;675}676 677SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(678 char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,679 dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,680 dfsan_origin *ret_origin) {681 size_t dest_len = strlen(dest);682 char *ret = strcat(dest, src);683 size_t src_len = strlen(src);684 dfsan_mem_origin_transfer(dest + dest_len, src, src_len);685 dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);686 *ret_label = dest_label;687 *ret_origin = dest_origin;688 return ret;689}690 691SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat(692 char *dest, const char *src, size_t num, dfsan_label dest_label,693 dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) {694 size_t src_len = strlen(src);695 src_len = src_len < num ? src_len : num;696 size_t dest_len = strlen(dest);697 698 char *ret = strncat(dest, src, num);699 dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);700 *ret_label = dest_label;701 return ret;702}703 704SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat(705 char *dest, const char *src, size_t num, dfsan_label dest_label,706 dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label,707 dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin,708 dfsan_origin *ret_origin) {709 size_t src_len = strlen(src);710 src_len = src_len < num ? src_len : num;711 size_t dest_len = strlen(dest);712 713 char *ret = strncat(dest, src, num);714 715 dfsan_mem_origin_transfer(dest + dest_len, src, src_len);716 dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);717 *ret_label = dest_label;718 *ret_origin = dest_origin;719 return ret;720}721 722SANITIZER_INTERFACE_ATTRIBUTE char *723__dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {724 size_t len = strlen(s);725 void *p = malloc(len+1);726 dfsan_memcpy(p, s, len+1);727 *ret_label = 0;728 return static_cast<char *>(p);729}730 731SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,732 dfsan_label s_label,733 dfsan_label *ret_label,734 dfsan_origin s_origin,735 dfsan_origin *ret_origin) {736 size_t len = strlen(s);737 void *p = malloc(len + 1);738 dfsan_memcpy_with_origin(p, s, len + 1);739 *ret_label = 0;740 return static_cast<char *>(p);741}742 743SANITIZER_INTERFACE_ATTRIBUTE char *744__dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,745 dfsan_label s2_label, dfsan_label n_label,746 dfsan_label *ret_label) {747 size_t len = strlen(s2);748 if (len < n) {749 dfsan_memcpy(s1, s2, len+1);750 dfsan_memset(s1+len+1, 0, 0, n-len-1);751 } else {752 dfsan_memcpy(s1, s2, n);753 }754 755 *ret_label = s1_label;756 return s1;757}758 759SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(760 char *s1, const char *s2, size_t n, dfsan_label s1_label,761 dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,762 dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,763 dfsan_origin *ret_origin) {764 size_t len = strlen(s2);765 if (len < n) {766 dfsan_memcpy_with_origin(s1, s2, len + 1);767 dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);768 } else {769 dfsan_memcpy_with_origin(s1, s2, n);770 }771 772 *ret_label = s1_label;773 *ret_origin = s1_origin;774 return s1;775}776 777SANITIZER_INTERFACE_ATTRIBUTE ssize_t778__dfsw_pread(int fd, void *buf, size_t count, off_t offset,779 dfsan_label fd_label, dfsan_label buf_label,780 dfsan_label count_label, dfsan_label offset_label,781 dfsan_label *ret_label) {782 ssize_t ret = pread(fd, buf, count, offset);783 if (ret > 0)784 dfsan_set_label(0, buf, ret);785 *ret_label = 0;786 return ret;787}788 789SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(790 int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,791 dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,792 dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,793 dfsan_origin count_origin, dfsan_label offset_origin,794 dfsan_origin *ret_origin) {795 return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,796 offset_label, ret_label);797}798 799SANITIZER_INTERFACE_ATTRIBUTE ssize_t800__dfsw_read(int fd, void *buf, size_t count,801 dfsan_label fd_label, dfsan_label buf_label,802 dfsan_label count_label,803 dfsan_label *ret_label) {804 ssize_t ret = read(fd, buf, count);805 if (ret > 0)806 dfsan_set_label(0, buf, ret);807 *ret_label = 0;808 return ret;809}810 811SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(812 int fd, void *buf, size_t count, dfsan_label fd_label,813 dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,814 dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,815 dfsan_origin *ret_origin) {816 return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,817 ret_label);818}819 820SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,821 struct timespec *tp,822 dfsan_label clk_id_label,823 dfsan_label tp_label,824 dfsan_label *ret_label) {825 int ret = clock_gettime(clk_id, tp);826 if (ret == 0)827 dfsan_set_label(0, tp, sizeof(struct timespec));828 *ret_label = 0;829 return ret;830}831 832SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(833 clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,834 dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,835 dfsan_origin tp_origin, dfsan_origin *ret_origin) {836 return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);837}838 839static void dfsan_set_zero_label(const void *ptr, uptr size) {840 dfsan_set_label(0, const_cast<void *>(ptr), size);841}842 843// dlopen() ultimately calls mmap() down inside the loader, which generally844// doesn't participate in dynamic symbol resolution. Therefore we won't845// intercept its calls to mmap, and we have to hook it here.846SANITIZER_INTERFACE_ATTRIBUTE void *847__dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,848 dfsan_label flag_label, dfsan_label *ret_label) {849 void *handle = dlopen(filename, flag);850 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);851 if (filename && map)852 ForEachMappedRegion(map, dfsan_set_zero_label);853 *ret_label = 0;854 return handle;855}856 857SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(858 const char *filename, int flag, dfsan_label filename_label,859 dfsan_label flag_label, dfsan_label *ret_label,860 dfsan_origin filename_origin, dfsan_origin flag_origin,861 dfsan_origin *ret_origin) {862 return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);863}864 865static void *DFsanThreadStartFunc(void *arg) {866 DFsanThread *t = (DFsanThread *)arg;867 SetCurrentThread(t);868 t->Init();869 SetSigProcMask(&t->starting_sigset_, nullptr);870 return t->ThreadStart();871}872 873static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,874 void *start_routine, void *arg,875 dfsan_label *ret_label,876 bool track_origins = false) {877 pthread_attr_t myattr;878 if (!attr) {879 pthread_attr_init(&myattr);880 attr = &myattr;881 }882 883 // Ensure that the thread stack is large enough to hold all TLS data.884 AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));885 886 DFsanThread *t =887 DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);888 ScopedBlockSignals block(&t->starting_sigset_);889 int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);890 891 if (attr == &myattr)892 pthread_attr_destroy(&myattr);893 *ret_label = 0;894 return res;895}896 897SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(898 pthread_t *thread, const pthread_attr_t *attr, void *start_routine,899 void *arg, dfsan_label thread_label, dfsan_label attr_label,900 dfsan_label start_routine_label, dfsan_label arg_label,901 dfsan_label *ret_label) {902 return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);903}904 905SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(906 pthread_t *thread, const pthread_attr_t *attr, void *start_routine,907 void *arg, dfsan_label thread_label, dfsan_label attr_label,908 dfsan_label start_routine_label, dfsan_label arg_label,909 dfsan_label *ret_label, dfsan_origin thread_origin,910 dfsan_origin attr_origin, dfsan_origin start_routine_origin,911 dfsan_origin arg_origin, dfsan_origin *ret_origin) {912 return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,913 true);914}915 916SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,917 void **retval,918 dfsan_label thread_label,919 dfsan_label retval_label,920 dfsan_label *ret_label) {921 int ret = pthread_join(thread, retval);922 if (ret == 0 && retval)923 dfsan_set_label(0, retval, sizeof(*retval));924 *ret_label = 0;925 return ret;926}927 928SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(929 pthread_t thread, void **retval, dfsan_label thread_label,930 dfsan_label retval_label, dfsan_label *ret_label,931 dfsan_origin thread_origin, dfsan_origin retval_origin,932 dfsan_origin *ret_origin) {933 return __dfsw_pthread_join(thread, retval, thread_label, retval_label,934 ret_label);935}936 937struct dl_iterate_phdr_info {938 int (*callback)(struct dl_phdr_info *info, size_t size, void *data);939 void *data;940};941 942static int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size,943 void *data) {944 dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;945 dfsan_set_label(0, *info);946 dfsan_set_label(0, const_cast<char *>(info->dlpi_name),947 strlen(info->dlpi_name) + 1);948 dfsan_set_label(949 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),950 sizeof(*info->dlpi_phdr) * info->dlpi_phnum);951 952 dfsan_clear_thread_local_state();953 return dipi->callback(info, size, dipi->data);954}955 956SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(957 int (*callback)(struct dl_phdr_info *info, size_t size, void *data),958 void *data, dfsan_label callback_label, dfsan_label data_label,959 dfsan_label *ret_label) {960 dl_iterate_phdr_info dipi = {callback, data};961 *ret_label = 0;962 return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);963}964 965SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(966 int (*callback)(struct dl_phdr_info *info, size_t size, void *data),967 void *data, dfsan_label callback_label, dfsan_label data_label,968 dfsan_label *ret_label, dfsan_origin callback_origin,969 dfsan_origin data_origin, dfsan_origin *ret_origin) {970 dl_iterate_phdr_info dipi = {callback, data};971 *ret_label = 0;972 return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);973}974 975// This function is only available for glibc 2.27 or newer. Mark it weak so976// linking succeeds with older glibcs.977SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,978 size_t *alignp);979 980SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(981 size_t *sizep, size_t *alignp, dfsan_label sizep_label,982 dfsan_label alignp_label) {983 assert(_dl_get_tls_static_info);984 _dl_get_tls_static_info(sizep, alignp);985 dfsan_set_label(0, sizep, sizeof(*sizep));986 dfsan_set_label(0, alignp, sizeof(*alignp));987}988 989SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(990 size_t *sizep, size_t *alignp, dfsan_label sizep_label,991 dfsan_label alignp_label, dfsan_origin sizep_origin,992 dfsan_origin alignp_origin) {993 __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);994}995 996SANITIZER_INTERFACE_ATTRIBUTE997char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,998 dfsan_label buf_label, dfsan_label *ret_label) {999 char *ret = ctime_r(timep, buf);1000 if (ret) {1001 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,1002 strlen(buf) + 1);1003 *ret_label = buf_label;1004 } else {1005 *ret_label = 0;1006 }1007 return ret;1008}1009 1010SANITIZER_INTERFACE_ATTRIBUTE1011char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,1012 dfsan_label buf_label, dfsan_label *ret_label,1013 dfsan_origin timep_origin, dfsan_origin buf_origin,1014 dfsan_origin *ret_origin) {1015 char *ret = ctime_r(timep, buf);1016 if (ret) {1017 dfsan_set_label_origin(1018 dfsan_read_label(timep, sizeof(time_t)),1019 dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,1020 strlen(buf) + 1);1021 *ret_label = buf_label;1022 *ret_origin = buf_origin;1023 } else {1024 *ret_label = 0;1025 }1026 return ret;1027}1028 1029SANITIZER_INTERFACE_ATTRIBUTE1030char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,1031 dfsan_label size_label, dfsan_label stream_label,1032 dfsan_label *ret_label) {1033 char *ret = fgets(s, size, stream);1034 if (ret) {1035 dfsan_set_label(0, ret, strlen(ret) + 1);1036 *ret_label = s_label;1037 } else {1038 *ret_label = 0;1039 }1040 return ret;1041}1042 1043SANITIZER_INTERFACE_ATTRIBUTE1044char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,1045 dfsan_label size_label, dfsan_label stream_label,1046 dfsan_label *ret_label, dfsan_origin s_origin,1047 dfsan_origin size_origin, dfsan_origin stream_origin,1048 dfsan_origin *ret_origin) {1049 char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,1050 ret_label);1051 if (ret)1052 *ret_origin = s_origin;1053 return ret;1054}1055 1056SANITIZER_INTERFACE_ATTRIBUTE1057char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,1058 dfsan_label size_label, dfsan_label *ret_label) {1059 char *ret = getcwd(buf, size);1060 if (ret) {1061 dfsan_set_label(0, ret, strlen(ret) + 1);1062 *ret_label = buf_label;1063 } else {1064 *ret_label = 0;1065 }1066 return ret;1067}1068 1069SANITIZER_INTERFACE_ATTRIBUTE1070char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,1071 dfsan_label size_label, dfsan_label *ret_label,1072 dfsan_origin buf_origin, dfsan_origin size_origin,1073 dfsan_origin *ret_origin) {1074 char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);1075 if (ret)1076 *ret_origin = buf_origin;1077 return ret;1078}1079 1080SANITIZER_INTERFACE_ATTRIBUTE1081char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {1082 char *ret = get_current_dir_name();1083 if (ret)1084 dfsan_set_label(0, ret, strlen(ret) + 1);1085 *ret_label = 0;1086 return ret;1087}1088 1089SANITIZER_INTERFACE_ATTRIBUTE1090char *__dfso_get_current_dir_name(dfsan_label *ret_label,1091 dfsan_origin *ret_origin) {1092 return __dfsw_get_current_dir_name(ret_label);1093}1094 1095// This function is only available for glibc 2.25 or newer. Mark it weak so1096// linking succeeds with older glibcs.1097SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);1098 1099SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,1100 dfsan_label buffer_label,1101 dfsan_label length_label,1102 dfsan_label *ret_label) {1103 int ret = getentropy(buffer, length);1104 if (ret == 0) {1105 dfsan_set_label(0, buffer, length);1106 }1107 *ret_label = 0;1108 return ret;1109}1110 1111SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,1112 dfsan_label buffer_label,1113 dfsan_label length_label,1114 dfsan_label *ret_label,1115 dfsan_origin buffer_origin,1116 dfsan_origin length_origin,1117 dfsan_origin *ret_origin) {1118 return __dfsw_getentropy(buffer, length, buffer_label, length_label,1119 ret_label);1120}1121 1122SANITIZER_INTERFACE_ATTRIBUTE1123int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,1124 dfsan_label len_label, dfsan_label *ret_label) {1125 int ret = gethostname(name, len);1126 if (ret == 0) {1127 dfsan_set_label(0, name, strlen(name) + 1);1128 }1129 *ret_label = 0;1130 return ret;1131}1132 1133SANITIZER_INTERFACE_ATTRIBUTE1134int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,1135 dfsan_label len_label, dfsan_label *ret_label,1136 dfsan_origin name_origin, dfsan_origin len_origin,1137 dfsan_label *ret_origin) {1138 return __dfsw_gethostname(name, len, name_label, len_label, ret_label);1139}1140 1141SANITIZER_INTERFACE_ATTRIBUTE1142int __dfsw_getrlimit(int resource, struct rlimit *rlim,1143 dfsan_label resource_label, dfsan_label rlim_label,1144 dfsan_label *ret_label) {1145 int ret = getrlimit(resource, rlim);1146 if (ret == 0) {1147 dfsan_set_label(0, rlim, sizeof(struct rlimit));1148 }1149 *ret_label = 0;1150 return ret;1151}1152 1153SANITIZER_INTERFACE_ATTRIBUTE1154int __dfso_getrlimit(int resource, struct rlimit *rlim,1155 dfsan_label resource_label, dfsan_label rlim_label,1156 dfsan_label *ret_label, dfsan_origin resource_origin,1157 dfsan_origin rlim_origin, dfsan_origin *ret_origin) {1158 return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,1159 ret_label);1160}1161 1162SANITIZER_INTERFACE_ATTRIBUTE1163int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,1164 dfsan_label usage_label, dfsan_label *ret_label) {1165 int ret = getrusage(who, usage);1166 if (ret == 0) {1167 dfsan_set_label(0, usage, sizeof(struct rusage));1168 }1169 *ret_label = 0;1170 return ret;1171}1172 1173SANITIZER_INTERFACE_ATTRIBUTE1174int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,1175 dfsan_label usage_label, dfsan_label *ret_label,1176 dfsan_origin who_origin, dfsan_origin usage_origin,1177 dfsan_label *ret_origin) {1178 return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);1179}1180 1181SANITIZER_INTERFACE_ATTRIBUTE1182char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,1183 dfsan_label src_label, dfsan_label *ret_label) {1184 char *ret = strcpy(dest, src);1185 if (ret) {1186 dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);1187 }1188 *ret_label = dst_label;1189 return ret;1190}1191 1192SANITIZER_INTERFACE_ATTRIBUTE1193char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,1194 dfsan_label src_label, dfsan_label *ret_label,1195 dfsan_origin dst_origin, dfsan_origin src_origin,1196 dfsan_origin *ret_origin) {1197 char *ret = strcpy(dest, src);1198 if (ret) {1199 size_t str_len = strlen(src) + 1;1200 dfsan_mem_origin_transfer(dest, src, str_len);1201 dfsan_mem_shadow_transfer(dest, src, str_len);1202 }1203 *ret_label = dst_label;1204 *ret_origin = dst_origin;1205 return ret;1206}1207}1208 1209template <typename Fn>1210static ALWAYS_INLINE auto dfsan_strtol_impl(1211 Fn real, const char *nptr, char **endptr, int base,1212 char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) {1213 assert(tmp_endptr);1214 auto ret = real(nptr, tmp_endptr, base);1215 if (endptr)1216 *endptr = *tmp_endptr;1217 return ret;1218}1219 1220extern "C" {1221static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,1222 dfsan_label base_label,1223 dfsan_label *ret_label) {1224 if (tmp_endptr > nptr) {1225 // If *tmp_endptr is '\0' include its label as well.1226 *ret_label = dfsan_union(1227 base_label,1228 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));1229 } else {1230 *ret_label = 0;1231 }1232}1233 1234static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,1235 dfsan_label base_label,1236 dfsan_label *ret_label,1237 dfsan_origin base_origin,1238 dfsan_origin *ret_origin) {1239 if (tmp_endptr > nptr) {1240 // When multiple inputs are tainted, we propagate one of its origins.1241 // Because checking if base_label is tainted does not need additional1242 // computation, we prefer to propagating base_origin.1243 *ret_origin = base_label1244 ? base_origin1245 : dfsan_read_origin_of_first_taint(1246 nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1247 }1248}1249 1250static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {1251 assert(tmp_endptr);1252 double ret = strtod(nptr, tmp_endptr);1253 if (endptr)1254 *endptr = *tmp_endptr;1255 return ret;1256}1257 1258static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,1259 dfsan_label *ret_label) {1260 if (tmp_endptr > nptr) {1261 // If *tmp_endptr is '\0' include its label as well.1262 *ret_label = dfsan_read_label(1263 nptr,1264 tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1265 } else {1266 *ret_label = 0;1267 }1268}1269 1270SANITIZER_INTERFACE_ATTRIBUTE1271double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,1272 dfsan_label endptr_label, dfsan_label *ret_label) {1273 char *tmp_endptr;1274 double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);1275 dfsan_strtod_label(nptr, tmp_endptr, ret_label);1276 return ret;1277}1278 1279SANITIZER_INTERFACE_ATTRIBUTE1280double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,1281 dfsan_label endptr_label, dfsan_label *ret_label,1282 dfsan_origin nptr_origin, dfsan_origin endptr_origin,1283 dfsan_origin *ret_origin) {1284 char *tmp_endptr;1285 double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);1286 dfsan_strtod_label(nptr, tmp_endptr, ret_label);1287 if (tmp_endptr > nptr) {1288 // If *tmp_endptr is '\0' include its label as well.1289 *ret_origin = dfsan_read_origin_of_first_taint(1290 nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));1291 } else {1292 *ret_origin = 0;1293 }1294 return ret;1295}1296 1297WRAPPER_ALIAS(__isoc23_strtod, strtod)1298 1299#define WRAPPER_STRTO(ret_type, fun) \1300 SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \1301 const char *nptr, char **endptr, int base, dfsan_label nptr_label, \1302 dfsan_label endptr_label, dfsan_label base_label, \1303 dfsan_label *ret_label) { \1304 char *tmp_endptr; \1305 auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \1306 dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \1307 return ret; \1308 } \1309 SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \1310 const char *nptr, char **endptr, int base, dfsan_label nptr_label, \1311 dfsan_label endptr_label, dfsan_label base_label, \1312 dfsan_label *ret_label, dfsan_origin nptr_origin, \1313 dfsan_origin endptr_origin, dfsan_origin base_origin, \1314 dfsan_origin *ret_origin) { \1315 char *tmp_endptr; \1316 auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \1317 dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \1318 dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \1319 base_origin, ret_origin); \1320 return ret; \1321 }1322 1323WRAPPER_STRTO(long, strtol)1324WRAPPER_STRTO(long long, strtoll)1325WRAPPER_STRTO(unsigned long, strtoul)1326WRAPPER_STRTO(unsigned long long, strtoull)1327WRAPPER_ALIAS(__isoc23_strtol, strtol)1328WRAPPER_ALIAS(__isoc23_strtoll, strtoll)1329WRAPPER_ALIAS(__isoc23_strtoul, strtoul)1330WRAPPER_ALIAS(__isoc23_strtoull, strtoull)1331 1332SANITIZER_INTERFACE_ATTRIBUTE1333time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {1334 time_t ret = time(t);1335 if (ret != (time_t) -1 && t) {1336 dfsan_set_label(0, t, sizeof(time_t));1337 }1338 *ret_label = 0;1339 return ret;1340}1341 1342SANITIZER_INTERFACE_ATTRIBUTE1343time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,1344 dfsan_origin t_origin, dfsan_origin *ret_origin) {1345 return __dfsw_time(t, t_label, ret_label);1346}1347 1348SANITIZER_INTERFACE_ATTRIBUTE1349int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,1350 dfsan_label src_label, dfsan_label dst_label,1351 dfsan_label *ret_label) {1352 int ret = inet_pton(af, src, dst);1353 if (ret == 1) {1354 dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,1355 af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));1356 }1357 *ret_label = 0;1358 return ret;1359}1360 1361SANITIZER_INTERFACE_ATTRIBUTE1362int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,1363 dfsan_label src_label, dfsan_label dst_label,1364 dfsan_label *ret_label, dfsan_origin af_origin,1365 dfsan_origin src_origin, dfsan_origin dst_origin,1366 dfsan_origin *ret_origin) {1367 int ret = inet_pton(af, src, dst);1368 if (ret == 1) {1369 int src_len = strlen(src) + 1;1370 dfsan_set_label_origin(1371 dfsan_read_label(src, src_len),1372 dfsan_read_origin_of_first_taint(src, src_len), dst,1373 af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));1374 }1375 *ret_label = 0;1376 return ret;1377}1378 1379SANITIZER_INTERFACE_ATTRIBUTE1380struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,1381 dfsan_label timep_label, dfsan_label result_label,1382 dfsan_label *ret_label) {1383 struct tm *ret = localtime_r(timep, result);1384 if (ret) {1385 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,1386 sizeof(struct tm));1387 *ret_label = result_label;1388 } else {1389 *ret_label = 0;1390 }1391 return ret;1392}1393 1394SANITIZER_INTERFACE_ATTRIBUTE1395struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,1396 dfsan_label timep_label, dfsan_label result_label,1397 dfsan_label *ret_label, dfsan_origin timep_origin,1398 dfsan_origin result_origin,1399 dfsan_origin *ret_origin) {1400 struct tm *ret = localtime_r(timep, result);1401 if (ret) {1402 dfsan_set_label_origin(1403 dfsan_read_label(timep, sizeof(time_t)),1404 dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,1405 sizeof(struct tm));1406 *ret_label = result_label;1407 *ret_origin = result_origin;1408 } else {1409 *ret_label = 0;1410 }1411 return ret;1412}1413 1414SANITIZER_INTERFACE_ATTRIBUTE1415int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,1416 char *buf, size_t buflen, struct passwd **result,1417 dfsan_label uid_label, dfsan_label pwd_label,1418 dfsan_label buf_label, dfsan_label buflen_label,1419 dfsan_label result_label, dfsan_label *ret_label) {1420 // Store the data in pwd, the strings referenced from pwd in buf, and the1421 // address of pwd in *result. On failure, NULL is stored in *result.1422 int ret = getpwuid_r(uid, pwd, buf, buflen, result);1423 if (ret == 0) {1424 dfsan_set_label(0, pwd, sizeof(struct passwd));1425 dfsan_set_label(0, buf, strlen(buf) + 1);1426 }1427 *ret_label = 0;1428 dfsan_set_label(0, result, sizeof(struct passwd*));1429 return ret;1430}1431 1432SANITIZER_INTERFACE_ATTRIBUTE1433int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,1434 struct passwd **result, dfsan_label uid_label,1435 dfsan_label pwd_label, dfsan_label buf_label,1436 dfsan_label buflen_label, dfsan_label result_label,1437 dfsan_label *ret_label, dfsan_origin uid_origin,1438 dfsan_origin pwd_origin, dfsan_origin buf_origin,1439 dfsan_origin buflen_origin, dfsan_origin result_origin,1440 dfsan_origin *ret_origin) {1441 return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,1442 buf_label, buflen_label, result_label, ret_label);1443}1444 1445SANITIZER_INTERFACE_ATTRIBUTE1446int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,1447 int timeout, dfsan_label epfd_label,1448 dfsan_label events_label, dfsan_label maxevents_label,1449 dfsan_label timeout_label, dfsan_label *ret_label) {1450 int ret = epoll_wait(epfd, events, maxevents, timeout);1451 if (ret > 0)1452 dfsan_set_label(0, events, ret * sizeof(*events));1453 *ret_label = 0;1454 return ret;1455}1456 1457SANITIZER_INTERFACE_ATTRIBUTE1458int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,1459 int timeout, dfsan_label epfd_label,1460 dfsan_label events_label, dfsan_label maxevents_label,1461 dfsan_label timeout_label, dfsan_label *ret_label,1462 dfsan_origin epfd_origin, dfsan_origin events_origin,1463 dfsan_origin maxevents_origin,1464 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1465 return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,1466 events_label, maxevents_label, timeout_label,1467 ret_label);1468}1469 1470SANITIZER_INTERFACE_ATTRIBUTE1471int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,1472 dfsan_label dfs_label, dfsan_label nfds_label,1473 dfsan_label timeout_label, dfsan_label *ret_label) {1474 int ret = poll(fds, nfds, timeout);1475 if (ret >= 0) {1476 for (; nfds > 0; --nfds) {1477 dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));1478 }1479 }1480 *ret_label = 0;1481 return ret;1482}1483 1484SANITIZER_INTERFACE_ATTRIBUTE1485int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,1486 dfsan_label dfs_label, dfsan_label nfds_label,1487 dfsan_label timeout_label, dfsan_label *ret_label,1488 dfsan_origin dfs_origin, dfsan_origin nfds_origin,1489 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1490 return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,1491 ret_label);1492}1493 1494SANITIZER_INTERFACE_ATTRIBUTE1495int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,1496 fd_set *exceptfds, struct timeval *timeout,1497 dfsan_label nfds_label, dfsan_label readfds_label,1498 dfsan_label writefds_label, dfsan_label exceptfds_label,1499 dfsan_label timeout_label, dfsan_label *ret_label) {1500 int ret = select(nfds, readfds, writefds, exceptfds, timeout);1501 // Clear everything (also on error) since their content is either set or1502 // undefined.1503 if (readfds) {1504 dfsan_set_label(0, readfds, sizeof(fd_set));1505 }1506 if (writefds) {1507 dfsan_set_label(0, writefds, sizeof(fd_set));1508 }1509 if (exceptfds) {1510 dfsan_set_label(0, exceptfds, sizeof(fd_set));1511 }1512 dfsan_set_label(0, timeout, sizeof(struct timeval));1513 *ret_label = 0;1514 return ret;1515}1516 1517SANITIZER_INTERFACE_ATTRIBUTE1518int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,1519 fd_set *exceptfds, struct timeval *timeout,1520 dfsan_label nfds_label, dfsan_label readfds_label,1521 dfsan_label writefds_label, dfsan_label exceptfds_label,1522 dfsan_label timeout_label, dfsan_label *ret_label,1523 dfsan_origin nfds_origin, dfsan_origin readfds_origin,1524 dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,1525 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1526 return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,1527 readfds_label, writefds_label, exceptfds_label,1528 timeout_label, ret_label);1529}1530 1531SANITIZER_INTERFACE_ATTRIBUTE1532int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,1533 dfsan_label pid_label,1534 dfsan_label cpusetsize_label,1535 dfsan_label mask_label, dfsan_label *ret_label) {1536 int ret = sched_getaffinity(pid, cpusetsize, mask);1537 if (ret == 0) {1538 dfsan_set_label(0, mask, cpusetsize);1539 }1540 *ret_label = 0;1541 return ret;1542}1543 1544SANITIZER_INTERFACE_ATTRIBUTE1545int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,1546 dfsan_label pid_label,1547 dfsan_label cpusetsize_label,1548 dfsan_label mask_label, dfsan_label *ret_label,1549 dfsan_origin pid_origin,1550 dfsan_origin cpusetsize_origin,1551 dfsan_origin mask_origin,1552 dfsan_origin *ret_origin) {1553 return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,1554 cpusetsize_label, mask_label, ret_label);1555}1556 1557SANITIZER_INTERFACE_ATTRIBUTE1558int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,1559 dfsan_label *ret_label) {1560 int ret = sigemptyset(set);1561 dfsan_set_label(0, set, sizeof(sigset_t));1562 *ret_label = 0;1563 return ret;1564}1565 1566SANITIZER_INTERFACE_ATTRIBUTE1567int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,1568 dfsan_label *ret_label, dfsan_origin set_origin,1569 dfsan_origin *ret_origin) {1570 return __dfsw_sigemptyset(set, set_label, ret_label);1571}1572 1573class SignalHandlerScope {1574 public:1575 SignalHandlerScope() {1576 if (DFsanThread *t = GetCurrentThread())1577 t->EnterSignalHandler();1578 }1579 ~SignalHandlerScope() {1580 if (DFsanThread *t = GetCurrentThread())1581 t->LeaveSignalHandler();1582 }1583};1584 1585// Clear DFSan runtime TLS state at the end of a scope.1586//1587// Implementation must be async-signal-safe and use small data size, because1588// instances of this class may live on the signal handler stack.1589//1590// DFSan uses TLS to pass metadata of arguments and return values. When an1591// instrumented function accesses the TLS, if a signal callback happens, and the1592// callback calls other instrumented functions with updating the same TLS, the1593// TLS is in an inconsistent state after the callback ends. This may cause1594// either under-tainting or over-tainting.1595//1596// The current implementation simply resets TLS at restore. This prevents from1597// over-tainting. Although under-tainting may still happen, a taint flow can be1598// found eventually if we run a DFSan-instrumented program multiple times. The1599// alternative option is saving the entire TLS. However the TLS storage takes1600// 2k bytes, and signal calls could be nested. So it does not seem worth.1601class ScopedClearThreadLocalState {1602 public:1603 ScopedClearThreadLocalState() {}1604 ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }1605};1606 1607// SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.1608const int kMaxSignals = 1024;1609static atomic_uintptr_t sigactions[kMaxSignals];1610 1611static void SignalHandler(int signo) {1612 SignalHandlerScope signal_handler_scope;1613 ScopedClearThreadLocalState scoped_clear_tls;1614 1615 // Clear shadows for all inputs provided by system.1616 dfsan_clear_arg_tls(0, sizeof(dfsan_label));1617 1618 typedef void (*signal_cb)(int x);1619 signal_cb cb =1620 (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);1621 cb(signo);1622}1623 1624static void SignalAction(int signo, siginfo_t *si, void *uc) {1625 SignalHandlerScope signal_handler_scope;1626 ScopedClearThreadLocalState scoped_clear_tls;1627 1628 // Clear shadows for all inputs provided by system. Similar to SignalHandler.1629 dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));1630 dfsan_set_label(0, si, sizeof(*si));1631 dfsan_set_label(0, uc, sizeof(ucontext_t));1632 1633 typedef void (*sigaction_cb)(int, siginfo_t *, void *);1634 sigaction_cb cb =1635 (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);1636 cb(signo, si, uc);1637}1638 1639SANITIZER_INTERFACE_ATTRIBUTE1640int __dfsw_sigaction(int signum, const struct sigaction *act,1641 struct sigaction *oldact, dfsan_label signum_label,1642 dfsan_label act_label, dfsan_label oldact_label,1643 dfsan_label *ret_label) {1644 CHECK_LT(signum, kMaxSignals);1645 SignalSpinLocker lock;1646 uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);1647 struct sigaction new_act;1648 struct sigaction *pnew_act = act ? &new_act : nullptr;1649 if (act) {1650 internal_memcpy(pnew_act, act, sizeof(struct sigaction));1651 if (pnew_act->sa_flags & SA_SIGINFO) {1652 uptr cb = (uptr)(pnew_act->sa_sigaction);1653 if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {1654 atomic_store(&sigactions[signum], cb, memory_order_relaxed);1655 pnew_act->sa_sigaction = SignalAction;1656 }1657 } else {1658 uptr cb = (uptr)(pnew_act->sa_handler);1659 if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {1660 atomic_store(&sigactions[signum], cb, memory_order_relaxed);1661 pnew_act->sa_handler = SignalHandler;1662 }1663 }1664 }1665 1666 int ret = sigaction(signum, pnew_act, oldact);1667 1668 if (ret == 0 && oldact) {1669 if (oldact->sa_flags & SA_SIGINFO) {1670 if (oldact->sa_sigaction == SignalAction)1671 oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;1672 } else {1673 if (oldact->sa_handler == SignalHandler)1674 oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;1675 }1676 }1677 1678 if (oldact) {1679 dfsan_set_label(0, oldact, sizeof(struct sigaction));1680 }1681 *ret_label = 0;1682 return ret;1683}1684 1685SANITIZER_INTERFACE_ATTRIBUTE1686int __dfso_sigaction(int signum, const struct sigaction *act,1687 struct sigaction *oldact, dfsan_label signum_label,1688 dfsan_label act_label, dfsan_label oldact_label,1689 dfsan_label *ret_label, dfsan_origin signum_origin,1690 dfsan_origin act_origin, dfsan_origin oldact_origin,1691 dfsan_origin *ret_origin) {1692 return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,1693 oldact_label, ret_label);1694}1695 1696static sighandler_t dfsan_signal(int signum, sighandler_t handler,1697 dfsan_label *ret_label) {1698 CHECK_LT(signum, kMaxSignals);1699 SignalSpinLocker lock;1700 uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);1701 if (handler != SIG_IGN && handler != SIG_DFL) {1702 atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);1703 handler = &SignalHandler;1704 }1705 1706 sighandler_t ret = signal(signum, handler);1707 1708 if (ret == SignalHandler)1709 ret = (sighandler_t)old_cb;1710 1711 *ret_label = 0;1712 return ret;1713}1714 1715SANITIZER_INTERFACE_ATTRIBUTE1716sighandler_t __dfsw_signal(int signum, sighandler_t handler,1717 dfsan_label signum_label, dfsan_label handler_label,1718 dfsan_label *ret_label) {1719 return dfsan_signal(signum, handler, ret_label);1720}1721 1722SANITIZER_INTERFACE_ATTRIBUTE1723sighandler_t __dfso_signal(int signum, sighandler_t handler,1724 dfsan_label signum_label, dfsan_label handler_label,1725 dfsan_label *ret_label, dfsan_origin signum_origin,1726 dfsan_origin handler_origin,1727 dfsan_origin *ret_origin) {1728 return dfsan_signal(signum, handler, ret_label);1729}1730 1731SANITIZER_INTERFACE_ATTRIBUTE1732int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,1733 dfsan_label old_ss_label, dfsan_label *ret_label) {1734 int ret = sigaltstack(ss, old_ss);1735 if (ret != -1 && old_ss)1736 dfsan_set_label(0, old_ss, sizeof(*old_ss));1737 *ret_label = 0;1738 return ret;1739}1740 1741SANITIZER_INTERFACE_ATTRIBUTE1742int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,1743 dfsan_label old_ss_label, dfsan_label *ret_label,1744 dfsan_origin ss_origin, dfsan_origin old_ss_origin,1745 dfsan_origin *ret_origin) {1746 return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);1747}1748 1749SANITIZER_INTERFACE_ATTRIBUTE1750int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,1751 dfsan_label tv_label, dfsan_label tz_label,1752 dfsan_label *ret_label) {1753 int ret = gettimeofday(tv, tz);1754 if (tv) {1755 dfsan_set_label(0, tv, sizeof(struct timeval));1756 }1757 if (tz) {1758 dfsan_set_label(0, tz, sizeof(struct timezone));1759 }1760 *ret_label = 0;1761 return ret;1762}1763 1764SANITIZER_INTERFACE_ATTRIBUTE1765int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,1766 dfsan_label tv_label, dfsan_label tz_label,1767 dfsan_label *ret_label, dfsan_origin tv_origin,1768 dfsan_origin tz_origin, dfsan_origin *ret_origin) {1769 return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);1770}1771 1772SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,1773 dfsan_label s_label,1774 dfsan_label c_label,1775 dfsan_label n_label,1776 dfsan_label *ret_label) {1777 void *ret = memchr(s, c, n);1778 if (flags().strict_data_dependencies) {1779 *ret_label = ret ? s_label : 0;1780 } else {1781 size_t len =1782 ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 11783 : n;1784 *ret_label =1785 dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));1786 }1787 return ret;1788}1789 1790SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(1791 void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,1792 dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,1793 dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {1794 void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);1795 if (flags().strict_data_dependencies) {1796 if (ret)1797 *ret_origin = s_origin;1798 } else {1799 size_t len =1800 ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 11801 : n;1802 dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);1803 *ret_origin = o ? o : (s_label ? s_origin : c_origin);1804 }1805 return ret;1806}1807 1808SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,1809 dfsan_label s_label,1810 dfsan_label c_label,1811 dfsan_label *ret_label) {1812 char *ret = strrchr(s, c);1813 if (flags().strict_data_dependencies) {1814 *ret_label = ret ? s_label : 0;1815 } else {1816 *ret_label =1817 dfsan_union(dfsan_read_label(s, strlen(s) + 1),1818 dfsan_union(s_label, c_label));1819 }1820 1821 return ret;1822}1823 1824SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(1825 char *s, int c, dfsan_label s_label, dfsan_label c_label,1826 dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,1827 dfsan_origin *ret_origin) {1828 char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);1829 if (flags().strict_data_dependencies) {1830 if (ret)1831 *ret_origin = s_origin;1832 } else {1833 size_t s_len = strlen(s) + 1;1834 dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);1835 *ret_origin = o ? o : (s_label ? s_origin : c_origin);1836 }1837 1838 return ret;1839}1840 1841SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,1842 dfsan_label haystack_label,1843 dfsan_label needle_label,1844 dfsan_label *ret_label) {1845 char *ret = strstr(haystack, needle);1846 if (flags().strict_data_dependencies) {1847 *ret_label = ret ? haystack_label : 0;1848 } else {1849 size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;1850 *ret_label =1851 dfsan_union(dfsan_read_label(haystack, len),1852 dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),1853 dfsan_union(haystack_label, needle_label)));1854 }1855 1856 return ret;1857}1858 1859SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,1860 dfsan_label haystack_label,1861 dfsan_label needle_label,1862 dfsan_label *ret_label,1863 dfsan_origin haystack_origin,1864 dfsan_origin needle_origin,1865 dfsan_origin *ret_origin) {1866 char *ret =1867 __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);1868 if (flags().strict_data_dependencies) {1869 if (ret)1870 *ret_origin = haystack_origin;1871 } else {1872 size_t needle_len = strlen(needle);1873 size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;1874 dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);1875 if (o) {1876 *ret_origin = o;1877 } else {1878 o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);1879 *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);1880 }1881 }1882 1883 return ret;1884}1885 1886SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,1887 struct timespec *rem,1888 dfsan_label req_label,1889 dfsan_label rem_label,1890 dfsan_label *ret_label) {1891 int ret = nanosleep(req, rem);1892 *ret_label = 0;1893 if (ret == -1) {1894 // Interrupted by a signal, rem is filled with the remaining time.1895 dfsan_set_label(0, rem, sizeof(struct timespec));1896 }1897 return ret;1898}1899 1900SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(1901 const struct timespec *req, struct timespec *rem, dfsan_label req_label,1902 dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,1903 dfsan_origin rem_origin, dfsan_origin *ret_origin) {1904 return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);1905}1906 1907static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg,1908 int flags) {1909 dfsan_set_label(0, msg, sizeof(*msg));1910 dfsan_set_label(0, msg->msg_name, msg->msg_namelen);1911 dfsan_set_label(0, msg->msg_control, msg->msg_controllen);1912 for (size_t i = 0; i < msg->msg_iovlen; ++i) {1913 struct iovec *iov = &msg->msg_iov[i];1914 size_t iov_written = iov->iov_len;1915 1916 // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that1917 // may not have changed, using bytes_written to bound the 0 label write.1918 // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer,1919 // and should not be used as a bound.1920 if (!(MSG_TRUNC & flags)) {1921 if (bytes_written < iov->iov_len) {1922 iov_written = bytes_written;1923 }1924 bytes_written -= iov_written;1925 }1926 1927 dfsan_set_label(0, iov->iov_base, iov_written);1928 }1929}1930 1931SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(1932 int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,1933 struct timespec *timeout, dfsan_label sockfd_label,1934 dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,1935 dfsan_label timeout_label, dfsan_label *ret_label) {1936 int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);1937 for (int i = 0; i < ret; ++i) {1938 dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));1939 clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags);1940 }1941 *ret_label = 0;1942 return ret;1943}1944 1945SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(1946 int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,1947 struct timespec *timeout, dfsan_label sockfd_label,1948 dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,1949 dfsan_label timeout_label, dfsan_label *ret_label,1950 dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,1951 dfsan_origin vlen_origin, dfsan_origin flags_origin,1952 dfsan_origin timeout_origin, dfsan_origin *ret_origin) {1953 return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,1954 msgvec_label, vlen_label, flags_label, timeout_label,1955 ret_label);1956}1957 1958SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(1959 int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,1960 dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {1961 ssize_t ret = recvmsg(sockfd, msg, flags);1962 if (ret >= 0)1963 clear_msghdr_labels(ret, msg, flags);1964 *ret_label = 0;1965 return ret;1966}1967 1968SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(1969 int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,1970 dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,1971 dfsan_origin sockfd_origin, dfsan_origin msg_origin,1972 dfsan_origin flags_origin, dfsan_origin *ret_origin) {1973 return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,1974 flags_label, ret_label);1975}1976 1977SANITIZER_INTERFACE_ATTRIBUTE int1978__dfsw_socketpair(int domain, int type, int protocol, int sv[2],1979 dfsan_label domain_label, dfsan_label type_label,1980 dfsan_label protocol_label, dfsan_label sv_label,1981 dfsan_label *ret_label) {1982 int ret = socketpair(domain, type, protocol, sv);1983 *ret_label = 0;1984 if (ret == 0) {1985 dfsan_set_label(0, sv, sizeof(*sv) * 2);1986 }1987 return ret;1988}1989 1990SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(1991 int domain, int type, int protocol, int sv[2], dfsan_label domain_label,1992 dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,1993 dfsan_label *ret_label, dfsan_origin domain_origin,1994 dfsan_origin type_origin, dfsan_origin protocol_origin,1995 dfsan_origin sv_origin, dfsan_origin *ret_origin) {1996 return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,1997 protocol_label, sv_label, ret_label);1998}1999 2000SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(2001 int sockfd, int level, int optname, void *optval, socklen_t *optlen,2002 dfsan_label sockfd_label, dfsan_label level_label,2003 dfsan_label optname_label, dfsan_label optval_label,2004 dfsan_label optlen_label, dfsan_label *ret_label) {2005 int ret = getsockopt(sockfd, level, optname, optval, optlen);2006 if (ret != -1 && optval && optlen) {2007 dfsan_set_label(0, optlen, sizeof(*optlen));2008 dfsan_set_label(0, optval, *optlen);2009 }2010 *ret_label = 0;2011 return ret;2012}2013 2014SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(2015 int sockfd, int level, int optname, void *optval, socklen_t *optlen,2016 dfsan_label sockfd_label, dfsan_label level_label,2017 dfsan_label optname_label, dfsan_label optval_label,2018 dfsan_label optlen_label, dfsan_label *ret_label,2019 dfsan_origin sockfd_origin, dfsan_origin level_origin,2020 dfsan_origin optname_origin, dfsan_origin optval_origin,2021 dfsan_origin optlen_origin, dfsan_origin *ret_origin) {2022 return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,2023 level_label, optname_label, optval_label,2024 optlen_label, ret_label);2025}2026 2027SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(2028 int sockfd, struct sockaddr *addr, socklen_t *addrlen,2029 dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2030 dfsan_label *ret_label) {2031 socklen_t origlen = addrlen ? *addrlen : 0;2032 int ret = getsockname(sockfd, addr, addrlen);2033 if (ret != -1 && addr && addrlen) {2034 socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;2035 dfsan_set_label(0, addrlen, sizeof(*addrlen));2036 dfsan_set_label(0, addr, written_bytes);2037 }2038 *ret_label = 0;2039 return ret;2040}2041 2042SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(2043 int sockfd, struct sockaddr *addr, socklen_t *addrlen,2044 dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2045 dfsan_label *ret_label, dfsan_origin sockfd_origin,2046 dfsan_origin addr_origin, dfsan_origin addrlen_origin,2047 dfsan_origin *ret_origin) {2048 return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,2049 addrlen_label, ret_label);2050}2051 2052SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(2053 int sockfd, struct sockaddr *addr, socklen_t *addrlen,2054 dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2055 dfsan_label *ret_label) {2056 socklen_t origlen = addrlen ? *addrlen : 0;2057 int ret = getpeername(sockfd, addr, addrlen);2058 if (ret != -1 && addr && addrlen) {2059 socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;2060 dfsan_set_label(0, addrlen, sizeof(*addrlen));2061 dfsan_set_label(0, addr, written_bytes);2062 }2063 *ret_label = 0;2064 return ret;2065}2066 2067SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(2068 int sockfd, struct sockaddr *addr, socklen_t *addrlen,2069 dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,2070 dfsan_label *ret_label, dfsan_origin sockfd_origin,2071 dfsan_origin addr_origin, dfsan_origin addrlen_origin,2072 dfsan_origin *ret_origin) {2073 return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,2074 addrlen_label, ret_label);2075}2076 2077// Type of the function passed to dfsan_set_write_callback.2078typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);2079 2080// Calls to dfsan_set_write_callback() set the values in this struct.2081// Calls to the custom version of write() read (and invoke) them.2082static struct {2083 write_dfsan_callback_t write_callback = nullptr;2084} write_callback_info;2085 2086SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(2087 write_dfsan_callback_t write_callback, dfsan_label write_callback_label,2088 dfsan_label *ret_label) {2089 write_callback_info.write_callback = write_callback;2090}2091 2092SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(2093 write_dfsan_callback_t write_callback, dfsan_label write_callback_label,2094 dfsan_label *ret_label, dfsan_origin write_callback_origin,2095 dfsan_origin *ret_origin) {2096 write_callback_info.write_callback = write_callback;2097}2098 2099static inline void setup_tls_args_for_write_callback(2100 dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,2101 bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,2102 dfsan_origin count_origin) {2103 // The callback code will expect argument shadow labels in the args TLS,2104 // and origin labels in the origin args TLS.2105 // Previously this was done by a trampoline, but we want to remove this:2106 // https://github.com/llvm/llvm-project/issues/541722107 //2108 // Instead, this code is manually setting up the args TLS data.2109 //2110 // The offsets used need to correspond with the instrumentation code,2111 // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp2112 // DFSanFunction::getShadowForTLSArgument.2113 // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L16842114 // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1252115 //2116 // Here the arguments are all primitives, but it can be more complex2117 // to compute offsets for array/aggregate type arguments.2118 //2119 // TODO(browneee): Consider a builtin to improve maintainabliity.2120 // With a builtin, we would provide the argument labels via builtin,2121 // and the builtin would reuse parts of the instrumentation code to ensure2122 // that this code and the instrumentation can never be out of sync.2123 // Note: Currently DFSan instrumentation does not run on this code, so2124 // the builtin may need to be handled outside DFSan instrumentation.2125 dfsan_set_arg_tls(0, fd_label);2126 dfsan_set_arg_tls(1, buf_label);2127 dfsan_set_arg_tls(2, count_label);2128 if (origins) {2129 dfsan_set_arg_origin_tls(0, fd_origin);2130 dfsan_set_arg_origin_tls(1, buf_origin);2131 dfsan_set_arg_origin_tls(2, count_origin);2132 }2133}2134 2135SANITIZER_INTERFACE_ATTRIBUTE int2136__dfsw_write(int fd, const void *buf, size_t count,2137 dfsan_label fd_label, dfsan_label buf_label,2138 dfsan_label count_label, dfsan_label *ret_label) {2139 if (write_callback_info.write_callback) {2140 setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,2141 0, 0, 0);2142 write_callback_info.write_callback(fd, buf, count);2143 }2144 2145 *ret_label = 0;2146 return write(fd, buf, count);2147}2148 2149SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(2150 int fd, const void *buf, size_t count, dfsan_label fd_label,2151 dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,2152 dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,2153 dfsan_origin *ret_origin) {2154 if (write_callback_info.write_callback) {2155 setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,2156 fd_origin, buf_origin, count_origin);2157 write_callback_info.write_callback(fd, buf, count);2158 }2159 2160 *ret_label = 0;2161 return write(fd, buf, count);2162}2163} // namespace __dfsan2164 2165// Type used to extract a dfsan_label with va_arg()2166typedef int dfsan_label_va;2167 2168// Formats a chunk either a constant string or a single format directive (e.g.,2169// '%.3f').2170struct Formatter {2171 Formatter(char *str_, const char *fmt_, size_t size_)2172 : str(str_),2173 str_off(0),2174 size(size_),2175 fmt_start(fmt_),2176 fmt_cur(fmt_),2177 width(-1),2178 num_scanned(-1),2179 skip(false) {}2180 2181 int format() {2182 char *tmp_fmt = build_format_string();2183 int retval =2184 snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,2185 0 /* used only to avoid warnings */);2186 free(tmp_fmt);2187 return retval;2188 }2189 2190 template <typename T> int format(T arg) {2191 char *tmp_fmt = build_format_string();2192 int retval;2193 if (width >= 0) {2194 retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,2195 tmp_fmt, width, arg);2196 } else {2197 retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,2198 tmp_fmt, arg);2199 }2200 free(tmp_fmt);2201 return retval;2202 }2203 2204 char *build_format_string() {2205 size_t fmt_size = fmt_cur - fmt_start + 1;2206 char *new_fmt = (char *)malloc(fmt_size + 1);2207 assert(new_fmt);2208 internal_memcpy(new_fmt, fmt_start, fmt_size);2209 new_fmt[fmt_size] = '\0';2210 return new_fmt;2211 }2212 2213 char *str_cur() { return str + str_off; }2214 2215 size_t num_written_bytes(int retval) {2216 if (retval < 0) {2217 return 0;2218 }2219 2220 size_t num_avail = str_off < size ? size - str_off : 0;2221 if (num_avail == 0) {2222 return 0;2223 }2224 2225 size_t num_written = retval;2226 // A return value of {v,}snprintf of size or more means that the output was2227 // truncated.2228 if (num_written >= num_avail) {2229 num_written -= num_avail;2230 }2231 2232 return num_written;2233 }2234 2235 char *str;2236 size_t str_off;2237 size_t size;2238 const char *fmt_start;2239 const char *fmt_cur;2240 int width;2241 int num_scanned;2242 bool skip;2243};2244 2245// Formats the input and propagates the input labels to the output. The output2246// is stored in 'str'. 'size' bounds the number of output bytes. 'format' and2247// 'ap' are the format string and the list of arguments for formatting. Returns2248// the return value vsnprintf would return.2249//2250// The function tokenizes the format string in chunks representing either a2251// constant string or a single format directive (e.g., '%.3f') and formats each2252// chunk independently into the output string. This approach allows to figure2253// out which bytes of the output string depends on which argument and thus to2254// propagate labels more precisely.2255//2256// WARNING: This implementation does not support conversion specifiers with2257// positional arguments.2258static int format_buffer(char *str, size_t size, const char *fmt,2259 dfsan_label *va_labels, dfsan_label *ret_label,2260 dfsan_origin *va_origins, dfsan_origin *ret_origin,2261 va_list ap) {2262 Formatter formatter(str, fmt, size);2263 2264 while (*formatter.fmt_cur) {2265 formatter.fmt_start = formatter.fmt_cur;2266 formatter.width = -1;2267 int retval = 0;2268 2269 if (*formatter.fmt_cur != '%') {2270 // Ordinary character. Consume all the characters until a '%' or the end2271 // of the string.2272 for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';2273 ++formatter.fmt_cur) {}2274 retval = formatter.format();2275 dfsan_set_label(0, formatter.str_cur(),2276 formatter.num_written_bytes(retval));2277 } else {2278 // Conversion directive. Consume all the characters until a conversion2279 // specifier or the end of the string.2280 bool end_fmt = false;2281 for (; *formatter.fmt_cur && !end_fmt; ) {2282 switch (*++formatter.fmt_cur) {2283 case 'd':2284 case 'i':2285 case 'o':2286 case 'u':2287 case 'x':2288 case 'X':2289 switch (*(formatter.fmt_cur - 1)) {2290 case 'h':2291 // Also covers the 'hh' case (since the size of the arg is still2292 // an int).2293 retval = formatter.format(va_arg(ap, int));2294 break;2295 case 'l':2296 if (formatter.fmt_cur - formatter.fmt_start >= 2 &&2297 *(formatter.fmt_cur - 2) == 'l') {2298 retval = formatter.format(va_arg(ap, long long int));2299 } else {2300 retval = formatter.format(va_arg(ap, long int));2301 }2302 break;2303 case 'q':2304 retval = formatter.format(va_arg(ap, long long int));2305 break;2306 case 'j':2307 retval = formatter.format(va_arg(ap, intmax_t));2308 break;2309 case 'z':2310 case 't':2311 retval = formatter.format(va_arg(ap, size_t));2312 break;2313 default:2314 retval = formatter.format(va_arg(ap, int));2315 }2316 if (va_origins == nullptr)2317 dfsan_set_label(*va_labels++, formatter.str_cur(),2318 formatter.num_written_bytes(retval));2319 else2320 dfsan_set_label_origin(*va_labels++, *va_origins++,2321 formatter.str_cur(),2322 formatter.num_written_bytes(retval));2323 end_fmt = true;2324 break;2325 2326 case 'a':2327 case 'A':2328 case 'e':2329 case 'E':2330 case 'f':2331 case 'F':2332 case 'g':2333 case 'G':2334 if (*(formatter.fmt_cur - 1) == 'L') {2335 retval = formatter.format(va_arg(ap, long double));2336 } else {2337 retval = formatter.format(va_arg(ap, double));2338 }2339 if (va_origins == nullptr)2340 dfsan_set_label(*va_labels++, formatter.str_cur(),2341 formatter.num_written_bytes(retval));2342 else2343 dfsan_set_label_origin(*va_labels++, *va_origins++,2344 formatter.str_cur(),2345 formatter.num_written_bytes(retval));2346 end_fmt = true;2347 break;2348 2349 case 'c':2350 retval = formatter.format(va_arg(ap, int));2351 if (va_origins == nullptr)2352 dfsan_set_label(*va_labels++, formatter.str_cur(),2353 formatter.num_written_bytes(retval));2354 else2355 dfsan_set_label_origin(*va_labels++, *va_origins++,2356 formatter.str_cur(),2357 formatter.num_written_bytes(retval));2358 end_fmt = true;2359 break;2360 2361 case 's': {2362 char *arg = va_arg(ap, char *);2363 retval = formatter.format(arg);2364 if (va_origins) {2365 va_origins++;2366 dfsan_mem_origin_transfer(formatter.str_cur(), arg,2367 formatter.num_written_bytes(retval));2368 }2369 va_labels++;2370 dfsan_mem_shadow_transfer(formatter.str_cur(), arg,2371 formatter.num_written_bytes(retval));2372 end_fmt = true;2373 break;2374 }2375 2376 case 'p':2377 retval = formatter.format(va_arg(ap, void *));2378 if (va_origins == nullptr)2379 dfsan_set_label(*va_labels++, formatter.str_cur(),2380 formatter.num_written_bytes(retval));2381 else2382 dfsan_set_label_origin(*va_labels++, *va_origins++,2383 formatter.str_cur(),2384 formatter.num_written_bytes(retval));2385 end_fmt = true;2386 break;2387 2388 case 'n': {2389 int *ptr = va_arg(ap, int *);2390 *ptr = (int)formatter.str_off;2391 va_labels++;2392 if (va_origins)2393 va_origins++;2394 dfsan_set_label(0, ptr, sizeof(ptr));2395 end_fmt = true;2396 break;2397 }2398 2399 case '%':2400 retval = formatter.format();2401 dfsan_set_label(0, formatter.str_cur(),2402 formatter.num_written_bytes(retval));2403 end_fmt = true;2404 break;2405 2406 case '*':2407 formatter.width = va_arg(ap, int);2408 va_labels++;2409 if (va_origins)2410 va_origins++;2411 break;2412 2413 default:2414 break;2415 }2416 }2417 }2418 2419 if (retval < 0) {2420 return retval;2421 }2422 2423 formatter.fmt_cur++;2424 formatter.str_off += retval;2425 }2426 2427 *ret_label = 0;2428 if (ret_origin)2429 *ret_origin = 0;2430 2431 // Number of bytes written in total.2432 return formatter.str_off;2433}2434 2435// Scans a chunk either a constant string or a single format directive (e.g.,2436// '%.3f').2437struct Scanner {2438 Scanner(char *str_, const char *fmt_, size_t size_)2439 : str(str_),2440 str_off(0),2441 size(size_),2442 fmt_start(fmt_),2443 fmt_cur(fmt_),2444 width(-1),2445 num_scanned(0),2446 skip(false) {}2447 2448 // Consumes a chunk of ordinary characters.2449 // Returns number of matching ordinary characters.2450 // Returns -1 if the match failed.2451 // In format strings, a space will match multiple spaces.2452 int check_match_ordinary() {2453 char *tmp_fmt = build_format_string_with_n();2454 int read_count = -1;2455 sscanf(str + str_off, tmp_fmt, &read_count);2456 free(tmp_fmt);2457 if (read_count > 0) {2458 str_off += read_count;2459 }2460 return read_count;2461 }2462 2463 int scan() {2464 char *tmp_fmt = build_format_string_with_n();2465 int read_count = 0;2466 int retval = sscanf(str + str_off, tmp_fmt, &read_count);2467 free(tmp_fmt);2468 if (retval > 0) {2469 num_scanned += retval;2470 }2471 return read_count;2472 }2473 2474 template <typename T>2475 int scan(T arg) {2476 char *tmp_fmt = build_format_string_with_n();2477 int read_count = 0;2478 int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count);2479 free(tmp_fmt);2480 if (retval > 0) {2481 num_scanned += retval;2482 }2483 return read_count;2484 }2485 2486 // Adds %n onto current format string to measure length.2487 char *build_format_string_with_n() {2488 size_t fmt_size = fmt_cur - fmt_start + 1;2489 // +2 for %n, +1 for \02490 char *new_fmt = (char *)malloc(fmt_size + 2 + 1);2491 assert(new_fmt);2492 internal_memcpy(new_fmt, fmt_start, fmt_size);2493 new_fmt[fmt_size] = '%';2494 new_fmt[fmt_size + 1] = 'n';2495 new_fmt[fmt_size + 2] = '\0';2496 return new_fmt;2497 }2498 2499 char *str_cur() { return str + str_off; }2500 2501 size_t num_written_bytes(int retval) {2502 if (retval < 0) {2503 return 0;2504 }2505 2506 size_t num_avail = str_off < size ? size - str_off : 0;2507 if (num_avail == 0) {2508 return 0;2509 }2510 2511 size_t num_written = retval;2512 // A return value of {v,}snprintf of size or more means that the output was2513 // truncated.2514 if (num_written >= num_avail) {2515 num_written -= num_avail;2516 }2517 2518 return num_written;2519 }2520 2521 char *str;2522 size_t str_off;2523 size_t size;2524 const char *fmt_start;2525 const char *fmt_cur;2526 int width;2527 int num_scanned;2528 bool skip;2529};2530 2531// This function is an inverse of format_buffer: we take the input buffer,2532// scan it in search for format strings and store the results in the varargs.2533// The labels are propagated from the input buffer to the varargs.2534static int scan_buffer(char *str, size_t size, const char *fmt,2535 dfsan_label *va_labels, dfsan_label *ret_label,2536 dfsan_origin *str_origin, dfsan_origin *ret_origin,2537 va_list ap) {2538 Scanner scanner(str, fmt, size);2539 while (*scanner.fmt_cur) {2540 scanner.fmt_start = scanner.fmt_cur;2541 scanner.width = -1;2542 scanner.skip = false;2543 int read_count = 0;2544 void *dst_ptr = 0;2545 size_t write_size = 0;2546 if (*scanner.fmt_cur != '%') {2547 // Ordinary character and spaces.2548 // Consume all the characters until a '%' or the end of the string.2549 for (; *(scanner.fmt_cur + 1) && *(scanner.fmt_cur + 1) != '%';2550 ++scanner.fmt_cur) {2551 }2552 if (scanner.check_match_ordinary() < 0) {2553 // The ordinary characters did not match.2554 break;2555 }2556 } else {2557 // Conversion directive. Consume all the characters until a conversion2558 // specifier or the end of the string.2559 bool end_fmt = false;2560 for (; *scanner.fmt_cur && !end_fmt;) {2561 switch (*++scanner.fmt_cur) {2562 case 'd':2563 case 'i':2564 case 'o':2565 case 'u':2566 case 'x':2567 case 'X':2568 if (scanner.skip) {2569 read_count = scanner.scan();2570 } else {2571 switch (*(scanner.fmt_cur - 1)) {2572 case 'h':2573 // Also covers the 'hh' case (since the size of the arg is2574 // still an int).2575 dst_ptr = va_arg(ap, int *);2576 read_count = scanner.scan((int *)dst_ptr);2577 write_size = sizeof(int);2578 break;2579 case 'l':2580 if (scanner.fmt_cur - scanner.fmt_start >= 2 &&2581 *(scanner.fmt_cur - 2) == 'l') {2582 dst_ptr = va_arg(ap, long long int *);2583 read_count = scanner.scan((long long int *)dst_ptr);2584 write_size = sizeof(long long int);2585 } else {2586 dst_ptr = va_arg(ap, long int *);2587 read_count = scanner.scan((long int *)dst_ptr);2588 write_size = sizeof(long int);2589 }2590 break;2591 case 'q':2592 dst_ptr = va_arg(ap, long long int *);2593 read_count = scanner.scan((long long int *)dst_ptr);2594 write_size = sizeof(long long int);2595 break;2596 case 'j':2597 dst_ptr = va_arg(ap, intmax_t *);2598 read_count = scanner.scan((intmax_t *)dst_ptr);2599 write_size = sizeof(intmax_t);2600 break;2601 case 'z':2602 case 't':2603 dst_ptr = va_arg(ap, size_t *);2604 read_count = scanner.scan((size_t *)dst_ptr);2605 write_size = sizeof(size_t);2606 break;2607 default:2608 dst_ptr = va_arg(ap, int *);2609 read_count = scanner.scan((int *)dst_ptr);2610 write_size = sizeof(int);2611 }2612 // get the label associated with the string at the corresponding2613 // place2614 dfsan_label l = dfsan_read_label(2615 scanner.str_cur(), scanner.num_written_bytes(read_count));2616 dfsan_set_label(l, dst_ptr, write_size);2617 if (str_origin != nullptr) {2618 dfsan_set_label(l, dst_ptr, write_size);2619 size_t scan_count = scanner.num_written_bytes(read_count);2620 size_t size = scan_count > write_size ? write_size : scan_count;2621 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2622 }2623 }2624 end_fmt = true;2625 2626 break;2627 2628 case 'a':2629 case 'A':2630 case 'e':2631 case 'E':2632 case 'f':2633 case 'F':2634 case 'g':2635 case 'G':2636 if (scanner.skip) {2637 read_count = scanner.scan();2638 } else {2639 if (*(scanner.fmt_cur - 1) == 'L') {2640 dst_ptr = va_arg(ap, long double *);2641 read_count = scanner.scan((long double *)dst_ptr);2642 write_size = sizeof(long double);2643 } else if (*(scanner.fmt_cur - 1) == 'l') {2644 dst_ptr = va_arg(ap, double *);2645 read_count = scanner.scan((double *)dst_ptr);2646 write_size = sizeof(double);2647 } else {2648 dst_ptr = va_arg(ap, float *);2649 read_count = scanner.scan((float *)dst_ptr);2650 write_size = sizeof(float);2651 }2652 dfsan_label l = dfsan_read_label(2653 scanner.str_cur(), scanner.num_written_bytes(read_count));2654 dfsan_set_label(l, dst_ptr, write_size);2655 if (str_origin != nullptr) {2656 dfsan_set_label(l, dst_ptr, write_size);2657 size_t scan_count = scanner.num_written_bytes(read_count);2658 size_t size = scan_count > write_size ? write_size : scan_count;2659 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2660 }2661 }2662 end_fmt = true;2663 break;2664 2665 case 'c':2666 if (scanner.skip) {2667 read_count = scanner.scan();2668 } else {2669 dst_ptr = va_arg(ap, char *);2670 read_count = scanner.scan((char *)dst_ptr);2671 write_size = sizeof(char);2672 dfsan_label l = dfsan_read_label(2673 scanner.str_cur(), scanner.num_written_bytes(read_count));2674 dfsan_set_label(l, dst_ptr, write_size);2675 if (str_origin != nullptr) {2676 size_t scan_count = scanner.num_written_bytes(read_count);2677 size_t size = scan_count > write_size ? write_size : scan_count;2678 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2679 }2680 }2681 end_fmt = true;2682 break;2683 2684 case 's': {2685 if (scanner.skip) {2686 read_count = scanner.scan();2687 } else {2688 dst_ptr = va_arg(ap, char *);2689 read_count = scanner.scan((char *)dst_ptr);2690 if (1 == read_count) {2691 // special case: we have parsed a single string and we need to2692 // update read_count with the string size2693 read_count = strlen((char *)dst_ptr);2694 }2695 if (str_origin)2696 dfsan_mem_origin_transfer(2697 dst_ptr, scanner.str_cur(),2698 scanner.num_written_bytes(read_count));2699 va_labels++;2700 dfsan_mem_shadow_transfer(dst_ptr, scanner.str_cur(),2701 scanner.num_written_bytes(read_count));2702 }2703 end_fmt = true;2704 break;2705 }2706 2707 case 'p':2708 if (scanner.skip) {2709 read_count = scanner.scan();2710 } else {2711 dst_ptr = va_arg(ap, void *);2712 read_count =2713 scanner.scan((int *)dst_ptr); // note: changing void* to int*2714 // since we need to call sizeof2715 write_size = sizeof(int);2716 2717 dfsan_label l = dfsan_read_label(2718 scanner.str_cur(), scanner.num_written_bytes(read_count));2719 dfsan_set_label(l, dst_ptr, write_size);2720 if (str_origin != nullptr) {2721 dfsan_set_label(l, dst_ptr, write_size);2722 size_t scan_count = scanner.num_written_bytes(read_count);2723 size_t size = scan_count > write_size ? write_size : scan_count;2724 dfsan_mem_origin_transfer(dst_ptr, scanner.str_cur(), size);2725 }2726 }2727 end_fmt = true;2728 break;2729 2730 case 'n': {2731 if (!scanner.skip) {2732 int *ptr = va_arg(ap, int *);2733 *ptr = (int)scanner.str_off;2734 *va_labels++ = 0;2735 dfsan_set_label(0, ptr, sizeof(*ptr));2736 if (str_origin != nullptr)2737 *str_origin++ = 0;2738 }2739 end_fmt = true;2740 break;2741 }2742 2743 case '%':2744 read_count = scanner.scan();2745 end_fmt = true;2746 break;2747 2748 case '*':2749 scanner.skip = true;2750 break;2751 2752 default:2753 break;2754 }2755 }2756 }2757 2758 if (read_count < 0) {2759 // There was an error.2760 return read_count;2761 }2762 2763 scanner.fmt_cur++;2764 scanner.str_off += read_count;2765 }2766 2767 (void)va_labels; // Silence unused-but-set-parameter warning2768 *ret_label = 0;2769 if (ret_origin)2770 *ret_origin = 0;2771 2772 // Number of items scanned in total.2773 return scanner.num_scanned;2774}2775 2776extern "C" {2777SANITIZER_INTERFACE_ATTRIBUTE2778int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,2779 dfsan_label format_label, dfsan_label *va_labels,2780 dfsan_label *ret_label, ...) {2781 va_list ap;2782 va_start(ap, ret_label);2783 2784 int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label, nullptr,2785 nullptr, ap);2786 va_end(ap);2787 return ret;2788}2789 2790SANITIZER_INTERFACE_ATTRIBUTE2791int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,2792 dfsan_label format_label, dfsan_label *va_labels,2793 dfsan_label *ret_label, dfsan_origin str_origin,2794 dfsan_origin format_origin, dfsan_origin *va_origins,2795 dfsan_origin *ret_origin, ...) {2796 va_list ap;2797 va_start(ap, ret_origin);2798 int ret = format_buffer(str, INT32_MAX, format, va_labels, ret_label,2799 va_origins, ret_origin, ap);2800 va_end(ap);2801 return ret;2802}2803 2804SANITIZER_INTERFACE_ATTRIBUTE2805int __dfsw_snprintf(char *str, size_t size, const char *format,2806 dfsan_label str_label, dfsan_label size_label,2807 dfsan_label format_label, dfsan_label *va_labels,2808 dfsan_label *ret_label, ...) {2809 va_list ap;2810 va_start(ap, ret_label);2811 int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,2812 nullptr, ap);2813 va_end(ap);2814 return ret;2815}2816 2817SANITIZER_INTERFACE_ATTRIBUTE2818int __dfso_snprintf(char *str, size_t size, const char *format,2819 dfsan_label str_label, dfsan_label size_label,2820 dfsan_label format_label, dfsan_label *va_labels,2821 dfsan_label *ret_label, dfsan_origin str_origin,2822 dfsan_origin size_origin, dfsan_origin format_origin,2823 dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {2824 va_list ap;2825 va_start(ap, ret_origin);2826 int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,2827 ret_origin, ap);2828 va_end(ap);2829 return ret;2830}2831 2832SANITIZER_INTERFACE_ATTRIBUTE2833int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label,2834 dfsan_label format_label, dfsan_label *va_labels,2835 dfsan_label *ret_label, ...) {2836 va_list ap;2837 va_start(ap, ret_label);2838 int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,2839 nullptr, ap);2840 va_end(ap);2841 return ret;2842}2843 2844SANITIZER_INTERFACE_ATTRIBUTE2845int __dfso_sscanf(char *str, const char *format, dfsan_label str_label,2846 dfsan_label format_label, dfsan_label *va_labels,2847 dfsan_label *ret_label, dfsan_origin str_origin,2848 dfsan_origin format_origin, dfsan_origin *va_origins,2849 dfsan_origin *ret_origin, ...) {2850 va_list ap;2851 va_start(ap, ret_origin);2852 int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,2853 ret_origin, ap);2854 va_end(ap);2855 return ret;2856}2857 2858WRAPPER_ALIAS(__isoc99_sscanf, sscanf)2859WRAPPER_ALIAS(__isoc23_sscanf, sscanf)2860 2861static void BeforeFork() {2862 VReport(2, "BeforeFork tid: %llu\n", GetTid());2863 StackDepotLockBeforeFork();2864 ChainedOriginDepotLockBeforeFork();2865}2866 2867static void AfterFork(bool fork_child) {2868 ChainedOriginDepotUnlockAfterFork(fork_child);2869 StackDepotUnlockAfterFork(fork_child);2870 VReport(2, "AfterFork tid: %llu\n", GetTid());2871}2872 2873SANITIZER_INTERFACE_ATTRIBUTE2874pid_t __dfsw_fork(dfsan_label *ret_label) {2875 pid_t pid = fork();2876 *ret_label = 0;2877 return pid;2878}2879 2880SANITIZER_INTERFACE_ATTRIBUTE2881pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {2882 BeforeFork();2883 pid_t pid = __dfsw_fork(ret_label);2884 AfterFork(/* fork_child= */ pid == 0);2885 return pid;2886}2887 2888// Default empty implementations (weak). Users should redefine them.2889SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}2890SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,2891 u32 *) {}2892SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,2893 const uptr *end) {}2894SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}2895 2896SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}2897SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}2898SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}2899SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}2900SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}2901SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,2902 void) {}2903SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,2904 void) {}2905SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,2906 void) {}2907SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,2908 void) {}2909SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}2910} // extern "C"2911