1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488 |
- //===-- dfsan_custom.cpp --------------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is a part of DataFlowSanitizer.
- //
- // This file defines the custom functions listed in done_abilist.txt.
- //===----------------------------------------------------------------------===//
- #include <arpa/inet.h>
- #include <assert.h>
- #include <ctype.h>
- #include <dlfcn.h>
- #include <link.h>
- #include <poll.h>
- #include <pthread.h>
- #include <pwd.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/epoll.h>
- #include <sys/resource.h>
- #include <sys/select.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <time.h>
- #include <unistd.h>
- #include "dfsan/dfsan.h"
- #include "dfsan/dfsan_chained_origin_depot.h"
- #include "dfsan/dfsan_flags.h"
- #include "dfsan/dfsan_thread.h"
- #include "sanitizer_common/sanitizer_common.h"
- #include "sanitizer_common/sanitizer_internal_defs.h"
- #include "sanitizer_common/sanitizer_linux.h"
- #include "sanitizer_common/sanitizer_stackdepot.h"
- using namespace __dfsan;
- #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \
- do { \
- if (f) \
- f(__VA_ARGS__); \
- } while (false)
- #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
- SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
- // Async-safe, non-reentrant spin lock.
- class SignalSpinLocker {
- public:
- SignalSpinLocker() {
- sigset_t all_set;
- sigfillset(&all_set);
- pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
- sigactions_mu.Lock();
- }
- ~SignalSpinLocker() {
- sigactions_mu.Unlock();
- pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
- }
- private:
- static StaticSpinMutex sigactions_mu;
- sigset_t saved_thread_mask_;
- SignalSpinLocker(const SignalSpinLocker &) = delete;
- SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
- };
- StaticSpinMutex SignalSpinLocker::sigactions_mu;
- extern "C" {
- SANITIZER_INTERFACE_ATTRIBUTE int
- __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
- dfsan_label buf_label, dfsan_label *ret_label) {
- int ret = stat(path, buf);
- if (ret == 0)
- dfsan_set_label(0, buf, sizeof(struct stat));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
- const char *path, struct stat *buf, dfsan_label path_label,
- dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
- dfsan_origin buf_origin, dfsan_origin *ret_origin) {
- int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
- dfsan_label fd_label,
- dfsan_label buf_label,
- dfsan_label *ret_label) {
- int ret = fstat(fd, buf);
- if (ret == 0)
- dfsan_set_label(0, buf, sizeof(struct stat));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
- int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
- dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
- dfsan_origin *ret_origin) {
- int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
- return ret;
- }
- static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
- dfsan_label s_label, dfsan_label c_label,
- dfsan_label *ret_label) {
- char *match_pos = nullptr;
- for (size_t i = 0;; ++i) {
- if (s[i] == c || s[i] == 0) {
- // If s[i] is the \0 at the end of the string, and \0 is not the
- // character we are searching for, then return null.
- *bytes_read = i + 1;
- match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
- break;
- }
- }
- if (flags().strict_data_dependencies)
- *ret_label = s_label;
- else
- *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
- dfsan_union(s_label, c_label));
- return match_pos;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
- dfsan_label s_label,
- dfsan_label c_label,
- dfsan_label *ret_label) {
- size_t bytes_read;
- return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
- const char *s, int c, dfsan_label s_label, dfsan_label c_label,
- dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
- dfsan_origin *ret_origin) {
- size_t bytes_read;
- char *r =
- dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
- if (flags().strict_data_dependencies) {
- *ret_origin = s_origin;
- } else if (*ret_label) {
- dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
- *ret_origin = o ? o : (s_label ? s_origin : c_origin);
- }
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
- const char *accept,
- dfsan_label s_label,
- dfsan_label accept_label,
- dfsan_label *ret_label) {
- const char *ret = strpbrk(s, accept);
- if (flags().strict_data_dependencies) {
- *ret_label = ret ? s_label : 0;
- } else {
- size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
- *ret_label =
- dfsan_union(dfsan_read_label(s, s_bytes_read),
- dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
- dfsan_union(s_label, accept_label)));
- }
- return const_cast<char *>(ret);
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
- const char *s, const char *accept, dfsan_label s_label,
- dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
- dfsan_origin accept_origin, dfsan_origin *ret_origin) {
- const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
- if (flags().strict_data_dependencies) {
- if (ret)
- *ret_origin = s_origin;
- } else {
- if (*ret_label) {
- size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
- dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
- if (o) {
- *ret_origin = o;
- } else {
- o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
- *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
- }
- }
- }
- return const_cast<char *>(ret);
- }
- static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
- size_t *bytes_read) {
- const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
- for (size_t i = 0; i != n; ++i) {
- if (cs1[i] != cs2[i]) {
- *bytes_read = i + 1;
- return cs1[i] - cs2[i];
- }
- }
- *bytes_read = n;
- return 0;
- }
- static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
- size_t pos) {
- if (flags().strict_data_dependencies)
- return 0;
- return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
- }
- static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
- dfsan_label *ret_label,
- dfsan_origin *ret_origin) {
- *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
- if (*ret_label == 0)
- return;
- dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
- *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
- }
- static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
- dfsan_label *ret_label) {
- size_t bytes_read;
- int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
- *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
- return r;
- }
- static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
- dfsan_label *ret_label,
- dfsan_origin *ret_origin) {
- size_t bytes_read;
- int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
- dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
- return r;
- }
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
- const void *s1, const void *s2, size_t n,
- dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label n_label)
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
- const void *s1, const void *s2, size_t n,
- dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label n_label, dfsan_origin s1_origin,
- dfsan_origin s2_origin, dfsan_origin n_origin)
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
- size_t n, dfsan_label s1_label,
- dfsan_label s2_label,
- dfsan_label n_label,
- dfsan_label *ret_label) {
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
- s1_label, s2_label, n_label);
- return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
- const void *s1, const void *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
- s2, n, s1_label, s2_label, n_label, s1_origin,
- s2_origin, n_origin);
- return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
- size_t n, dfsan_label s1_label,
- dfsan_label s2_label,
- dfsan_label n_label,
- dfsan_label *ret_label) {
- return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
- const void *s1, const void *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
- }
- // When n == 0, compare strings without byte limit.
- // When n > 0, compare the first (at most) n bytes of s1 and s2.
- static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
- size_t *bytes_read) {
- for (size_t i = 0;; ++i) {
- if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
- *bytes_read = i + 1;
- return s1[i] - s2[i];
- }
- }
- }
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
- const char *s1, const char *s2,
- dfsan_label s1_label, dfsan_label s2_label)
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
- const char *s1, const char *s2,
- dfsan_label s1_label, dfsan_label s2_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin)
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
- dfsan_label s1_label,
- dfsan_label s2_label,
- dfsan_label *ret_label) {
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
- s1_label, s2_label);
- size_t bytes_read;
- int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
- *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
- const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
- dfsan_origin *ret_origin) {
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
- s2, s1_label, s2_label, s1_origin, s2_origin);
- size_t bytes_read;
- int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
- dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
- return r;
- }
- // When n == 0, compare strings without byte limit.
- // When n > 0, compare the first (at most) n bytes of s1 and s2.
- static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
- size_t *bytes_read) {
- for (size_t i = 0;; ++i) {
- char s1_lower = tolower(s1[i]);
- char s2_lower = tolower(s2[i]);
- if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
- (n > 0 && i == n - 1)) {
- *bytes_read = i + 1;
- return s1_lower - s2_lower;
- }
- }
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
- const char *s2,
- dfsan_label s1_label,
- dfsan_label s2_label,
- dfsan_label *ret_label) {
- size_t bytes_read;
- int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
- *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
- const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
- dfsan_origin *ret_origin) {
- size_t bytes_read;
- int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
- dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
- return r;
- }
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
- const char *s1, const char *s2, size_t n,
- dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label n_label)
- DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
- const char *s1, const char *s2, size_t n,
- dfsan_label s1_label, dfsan_label s2_label,
- dfsan_label n_label, dfsan_origin s1_origin,
- dfsan_origin s2_origin, dfsan_origin n_origin)
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
- size_t n, dfsan_label s1_label,
- dfsan_label s2_label,
- dfsan_label n_label,
- dfsan_label *ret_label) {
- if (n == 0) {
- *ret_label = 0;
- return 0;
- }
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
- n, s1_label, s2_label, n_label);
- size_t bytes_read;
- int r = dfsan_strncmp(s1, s2, n, &bytes_read);
- *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
- const char *s1, const char *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- if (n == 0) {
- *ret_label = 0;
- return 0;
- }
- CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
- s1, s2, n, s1_label, s2_label, n_label, s1_origin,
- s2_origin, n_origin);
- size_t bytes_read;
- int r = dfsan_strncmp(s1, s2, n, &bytes_read);
- dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
- const char *s1, const char *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
- if (n == 0) {
- *ret_label = 0;
- return 0;
- }
- size_t bytes_read;
- int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
- *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
- const char *s1, const char *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- if (n == 0) {
- *ret_label = 0;
- return 0;
- }
- size_t bytes_read;
- int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
- dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
- return r;
- }
- SANITIZER_INTERFACE_ATTRIBUTE size_t
- __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
- size_t ret = strlen(s);
- if (flags().strict_data_dependencies) {
- *ret_label = 0;
- } else {
- *ret_label = dfsan_read_label(s, ret + 1);
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
- dfsan_label s_label,
- dfsan_label *ret_label,
- dfsan_origin s_origin,
- dfsan_origin *ret_origin) {
- size_t ret = __dfsw_strlen(s, s_label, ret_label);
- if (!flags().strict_data_dependencies)
- *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
- return ret;
- }
- static void *dfsan_memmove(void *dest, const void *src, size_t n) {
- dfsan_label *sdest = shadow_for(dest);
- const dfsan_label *ssrc = shadow_for(src);
- internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
- return internal_memmove(dest, src, n);
- }
- static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
- dfsan_mem_origin_transfer(dest, src, n);
- return dfsan_memmove(dest, src, n);
- }
- static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
- dfsan_mem_shadow_transfer(dest, src, n);
- return internal_memcpy(dest, src, n);
- }
- static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
- dfsan_mem_origin_transfer(dest, src, n);
- return dfsan_memcpy(dest, src, n);
- }
- static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
- internal_memset(s, c, n);
- dfsan_set_label(c_label, s, n);
- }
- static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
- dfsan_origin c_origin, size_t n) {
- internal_memset(s, c, n);
- dfsan_set_label_origin(c_label, c_origin, s, n);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfsw_memcpy(void *dest, const void *src, size_t n,
- dfsan_label dest_label, dfsan_label src_label,
- dfsan_label n_label, dfsan_label *ret_label) {
- *ret_label = dest_label;
- return dfsan_memcpy(dest, src, n);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfso_memcpy(void *dest, const void *src, size_t n,
- dfsan_label dest_label, dfsan_label src_label,
- dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin dest_origin, dfsan_origin src_origin,
- dfsan_origin n_origin, dfsan_origin *ret_origin) {
- *ret_label = dest_label;
- *ret_origin = dest_origin;
- return dfsan_memcpy_with_origin(dest, src, n);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfsw_memmove(void *dest, const void *src, size_t n,
- dfsan_label dest_label, dfsan_label src_label,
- dfsan_label n_label, dfsan_label *ret_label) {
- *ret_label = dest_label;
- return dfsan_memmove(dest, src, n);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfso_memmove(void *dest, const void *src, size_t n,
- dfsan_label dest_label, dfsan_label src_label,
- dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin dest_origin, dfsan_origin src_origin,
- dfsan_origin n_origin, dfsan_origin *ret_origin) {
- *ret_label = dest_label;
- *ret_origin = dest_origin;
- return dfsan_memmove_with_origin(dest, src, n);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfsw_memset(void *s, int c, size_t n,
- dfsan_label s_label, dfsan_label c_label,
- dfsan_label n_label, dfsan_label *ret_label) {
- dfsan_memset(s, c, c_label, n);
- *ret_label = s_label;
- return s;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
- dfsan_label c_label, dfsan_label n_label,
- dfsan_label *ret_label, dfsan_origin s_origin,
- dfsan_origin c_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- dfsan_memset_with_origin(s, c, c_label, c_origin, n);
- *ret_label = s_label;
- *ret_origin = s_origin;
- return s;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
- dfsan_label dest_label,
- dfsan_label src_label,
- dfsan_label *ret_label) {
- size_t dest_len = strlen(dest);
- char *ret = strcat(dest, src);
- dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));
- *ret_label = dest_label;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
- char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
- dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
- dfsan_origin *ret_origin) {
- size_t dest_len = strlen(dest);
- char *ret = strcat(dest, src);
- size_t src_len = strlen(src);
- dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
- dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
- *ret_label = dest_label;
- *ret_origin = dest_origin;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *
- __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
- size_t len = strlen(s);
- void *p = malloc(len+1);
- dfsan_memcpy(p, s, len+1);
- *ret_label = 0;
- return static_cast<char *>(p);
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
- dfsan_label s_label,
- dfsan_label *ret_label,
- dfsan_origin s_origin,
- dfsan_origin *ret_origin) {
- size_t len = strlen(s);
- void *p = malloc(len + 1);
- dfsan_memcpy_with_origin(p, s, len + 1);
- *ret_label = 0;
- return static_cast<char *>(p);
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *
- __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label,
- dfsan_label *ret_label) {
- size_t len = strlen(s2);
- if (len < n) {
- dfsan_memcpy(s1, s2, len+1);
- dfsan_memset(s1+len+1, 0, 0, n-len-1);
- } else {
- dfsan_memcpy(s1, s2, n);
- }
- *ret_label = s1_label;
- return s1;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
- char *s1, const char *s2, size_t n, dfsan_label s1_label,
- dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
- dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
- dfsan_origin *ret_origin) {
- size_t len = strlen(s2);
- if (len < n) {
- dfsan_memcpy_with_origin(s1, s2, len + 1);
- dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
- } else {
- dfsan_memcpy_with_origin(s1, s2, n);
- }
- *ret_label = s1_label;
- *ret_origin = s1_origin;
- return s1;
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t
- __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
- dfsan_label fd_label, dfsan_label buf_label,
- dfsan_label count_label, dfsan_label offset_label,
- dfsan_label *ret_label) {
- ssize_t ret = pread(fd, buf, count, offset);
- if (ret > 0)
- dfsan_set_label(0, buf, ret);
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
- int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
- dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
- dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
- dfsan_origin count_origin, dfsan_label offset_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
- offset_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t
- __dfsw_read(int fd, void *buf, size_t count,
- dfsan_label fd_label, dfsan_label buf_label,
- dfsan_label count_label,
- dfsan_label *ret_label) {
- ssize_t ret = read(fd, buf, count);
- if (ret > 0)
- dfsan_set_label(0, buf, ret);
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
- int fd, void *buf, size_t count, dfsan_label fd_label,
- dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
- dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
- struct timespec *tp,
- dfsan_label clk_id_label,
- dfsan_label tp_label,
- dfsan_label *ret_label) {
- int ret = clock_gettime(clk_id, tp);
- if (ret == 0)
- dfsan_set_label(0, tp, sizeof(struct timespec));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
- clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
- dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
- dfsan_origin tp_origin, dfsan_origin *ret_origin) {
- return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
- }
- static void dfsan_set_zero_label(const void *ptr, uptr size) {
- dfsan_set_label(0, const_cast<void *>(ptr), size);
- }
- // dlopen() ultimately calls mmap() down inside the loader, which generally
- // doesn't participate in dynamic symbol resolution. Therefore we won't
- // intercept its calls to mmap, and we have to hook it here.
- SANITIZER_INTERFACE_ATTRIBUTE void *
- __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
- dfsan_label flag_label, dfsan_label *ret_label) {
- void *handle = dlopen(filename, flag);
- link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
- if (map)
- ForEachMappedRegion(map, dfsan_set_zero_label);
- *ret_label = 0;
- return handle;
- }
- SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
- const char *filename, int flag, dfsan_label filename_label,
- dfsan_label flag_label, dfsan_label *ret_label,
- dfsan_origin filename_origin, dfsan_origin flag_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
- }
- static void *DFsanThreadStartFunc(void *arg) {
- DFsanThread *t = (DFsanThread *)arg;
- SetCurrentThread(t);
- t->Init();
- SetSigProcMask(&t->starting_sigset_, nullptr);
- return t->ThreadStart();
- }
- static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
- void *start_routine, void *arg,
- dfsan_label *ret_label,
- bool track_origins = false) {
- pthread_attr_t myattr;
- if (!attr) {
- pthread_attr_init(&myattr);
- attr = &myattr;
- }
- // Ensure that the thread stack is large enough to hold all TLS data.
- AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
- DFsanThread *t =
- DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
- ScopedBlockSignals block(&t->starting_sigset_);
- int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
- if (attr == &myattr)
- pthread_attr_destroy(&myattr);
- *ret_label = 0;
- return res;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
- pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
- void *arg, dfsan_label thread_label, dfsan_label attr_label,
- dfsan_label start_routine_label, dfsan_label arg_label,
- dfsan_label *ret_label) {
- return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
- pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
- void *arg, dfsan_label thread_label, dfsan_label attr_label,
- dfsan_label start_routine_label, dfsan_label arg_label,
- dfsan_label *ret_label, dfsan_origin thread_origin,
- dfsan_origin attr_origin, dfsan_origin start_routine_origin,
- dfsan_origin arg_origin, dfsan_origin *ret_origin) {
- return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
- true);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
- void **retval,
- dfsan_label thread_label,
- dfsan_label retval_label,
- dfsan_label *ret_label) {
- int ret = pthread_join(thread, retval);
- if (ret == 0 && retval)
- dfsan_set_label(0, retval, sizeof(*retval));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
- pthread_t thread, void **retval, dfsan_label thread_label,
- dfsan_label retval_label, dfsan_label *ret_label,
- dfsan_origin thread_origin, dfsan_origin retval_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
- ret_label);
- }
- struct dl_iterate_phdr_info {
- int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
- void *data;
- };
- int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
- dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
- dfsan_set_label(0, *info);
- dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
- strlen(info->dlpi_name) + 1);
- dfsan_set_label(
- 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
- sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
- dfsan_clear_thread_local_state();
- return dipi->callback(info, size, dipi->data);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
- int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
- void *data, dfsan_label callback_label, dfsan_label data_label,
- dfsan_label *ret_label) {
- dl_iterate_phdr_info dipi = {callback, data};
- *ret_label = 0;
- return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
- int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
- void *data, dfsan_label callback_label, dfsan_label data_label,
- dfsan_label *ret_label, dfsan_origin callback_origin,
- dfsan_origin data_origin, dfsan_origin *ret_origin) {
- dl_iterate_phdr_info dipi = {callback, data};
- *ret_label = 0;
- return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
- }
- // This function is only available for glibc 2.27 or newer. Mark it weak so
- // linking succeeds with older glibcs.
- SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
- size_t *alignp);
- SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
- size_t *sizep, size_t *alignp, dfsan_label sizep_label,
- dfsan_label alignp_label) {
- assert(_dl_get_tls_static_info);
- _dl_get_tls_static_info(sizep, alignp);
- dfsan_set_label(0, sizep, sizeof(*sizep));
- dfsan_set_label(0, alignp, sizeof(*alignp));
- }
- SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
- size_t *sizep, size_t *alignp, dfsan_label sizep_label,
- dfsan_label alignp_label, dfsan_origin sizep_origin,
- dfsan_origin alignp_origin) {
- __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
- dfsan_label buf_label, dfsan_label *ret_label) {
- char *ret = ctime_r(timep, buf);
- if (ret) {
- dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
- strlen(buf) + 1);
- *ret_label = buf_label;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
- dfsan_label buf_label, dfsan_label *ret_label,
- dfsan_origin timep_origin, dfsan_origin buf_origin,
- dfsan_origin *ret_origin) {
- char *ret = ctime_r(timep, buf);
- if (ret) {
- dfsan_set_label_origin(
- dfsan_read_label(timep, sizeof(time_t)),
- dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
- strlen(buf) + 1);
- *ret_label = buf_label;
- *ret_origin = buf_origin;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
- dfsan_label size_label, dfsan_label stream_label,
- dfsan_label *ret_label) {
- char *ret = fgets(s, size, stream);
- if (ret) {
- dfsan_set_label(0, ret, strlen(ret) + 1);
- *ret_label = s_label;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
- dfsan_label size_label, dfsan_label stream_label,
- dfsan_label *ret_label, dfsan_origin s_origin,
- dfsan_origin size_origin, dfsan_origin stream_origin,
- dfsan_origin *ret_origin) {
- char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
- ret_label);
- if (ret)
- *ret_origin = s_origin;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
- dfsan_label size_label, dfsan_label *ret_label) {
- char *ret = getcwd(buf, size);
- if (ret) {
- dfsan_set_label(0, ret, strlen(ret) + 1);
- *ret_label = buf_label;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
- dfsan_label size_label, dfsan_label *ret_label,
- dfsan_origin buf_origin, dfsan_origin size_origin,
- dfsan_origin *ret_origin) {
- char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
- if (ret)
- *ret_origin = buf_origin;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
- char *ret = get_current_dir_name();
- if (ret)
- dfsan_set_label(0, ret, strlen(ret) + 1);
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfso_get_current_dir_name(dfsan_label *ret_label,
- dfsan_origin *ret_origin) {
- return __dfsw_get_current_dir_name(ret_label);
- }
- // This function is only available for glibc 2.25 or newer. Mark it weak so
- // linking succeeds with older glibcs.
- SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,
- dfsan_label buffer_label,
- dfsan_label length_label,
- dfsan_label *ret_label) {
- int ret = getentropy(buffer, length);
- if (ret == 0) {
- dfsan_set_label(0, buffer, length);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,
- dfsan_label buffer_label,
- dfsan_label length_label,
- dfsan_label *ret_label,
- dfsan_origin buffer_origin,
- dfsan_origin length_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_getentropy(buffer, length, buffer_label, length_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
- dfsan_label len_label, dfsan_label *ret_label) {
- int ret = gethostname(name, len);
- if (ret == 0) {
- dfsan_set_label(0, name, strlen(name) + 1);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
- dfsan_label len_label, dfsan_label *ret_label,
- dfsan_origin name_origin, dfsan_origin len_origin,
- dfsan_label *ret_origin) {
- return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_getrlimit(int resource, struct rlimit *rlim,
- dfsan_label resource_label, dfsan_label rlim_label,
- dfsan_label *ret_label) {
- int ret = getrlimit(resource, rlim);
- if (ret == 0) {
- dfsan_set_label(0, rlim, sizeof(struct rlimit));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_getrlimit(int resource, struct rlimit *rlim,
- dfsan_label resource_label, dfsan_label rlim_label,
- dfsan_label *ret_label, dfsan_origin resource_origin,
- dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
- return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
- dfsan_label usage_label, dfsan_label *ret_label) {
- int ret = getrusage(who, usage);
- if (ret == 0) {
- dfsan_set_label(0, usage, sizeof(struct rusage));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
- dfsan_label usage_label, dfsan_label *ret_label,
- dfsan_origin who_origin, dfsan_origin usage_origin,
- dfsan_label *ret_origin) {
- return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
- dfsan_label src_label, dfsan_label *ret_label) {
- char *ret = strcpy(dest, src);
- if (ret) {
- dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);
- }
- *ret_label = dst_label;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
- dfsan_label src_label, dfsan_label *ret_label,
- dfsan_origin dst_origin, dfsan_origin src_origin,
- dfsan_origin *ret_origin) {
- char *ret = strcpy(dest, src);
- if (ret) {
- size_t str_len = strlen(src) + 1;
- dfsan_mem_origin_transfer(dest, src, str_len);
- dfsan_mem_shadow_transfer(dest, src, str_len);
- }
- *ret_label = dst_label;
- *ret_origin = dst_origin;
- return ret;
- }
- static long int dfsan_strtol(const char *nptr, char **endptr, int base,
- char **tmp_endptr) {
- assert(tmp_endptr);
- long int ret = strtol(nptr, tmp_endptr, base);
- if (endptr)
- *endptr = *tmp_endptr;
- return ret;
- }
- static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
- dfsan_label base_label,
- dfsan_label *ret_label) {
- if (tmp_endptr > nptr) {
- // If *tmp_endptr is '\0' include its label as well.
- *ret_label = dfsan_union(
- base_label,
- dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
- } else {
- *ret_label = 0;
- }
- }
- static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
- dfsan_label base_label,
- dfsan_label *ret_label,
- dfsan_origin base_origin,
- dfsan_origin *ret_origin) {
- if (tmp_endptr > nptr) {
- // When multiple inputs are tainted, we propagate one of its origins.
- // Because checking if base_label is tainted does not need additional
- // computation, we prefer to propagating base_origin.
- *ret_origin = base_label
- ? base_origin
- : dfsan_read_origin_of_first_taint(
- nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
- }
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long int __dfsw_strtol(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label) {
- char *tmp_endptr;
- long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long int __dfso_strtol(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label,
- dfsan_origin nptr_origin, dfsan_origin endptr_origin,
- dfsan_origin base_origin, dfsan_origin *ret_origin) {
- char *tmp_endptr;
- long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
- ret_origin);
- return ret;
- }
- static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
- assert(tmp_endptr);
- double ret = strtod(nptr, tmp_endptr);
- if (endptr)
- *endptr = *tmp_endptr;
- return ret;
- }
- static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
- dfsan_label *ret_label) {
- if (tmp_endptr > nptr) {
- // If *tmp_endptr is '\0' include its label as well.
- *ret_label = dfsan_read_label(
- nptr,
- tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
- } else {
- *ret_label = 0;
- }
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
- dfsan_label endptr_label, dfsan_label *ret_label) {
- char *tmp_endptr;
- double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
- dfsan_strtod_label(nptr, tmp_endptr, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
- dfsan_label endptr_label, dfsan_label *ret_label,
- dfsan_origin nptr_origin, dfsan_origin endptr_origin,
- dfsan_origin *ret_origin) {
- char *tmp_endptr;
- double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
- dfsan_strtod_label(nptr, tmp_endptr, ret_label);
- if (tmp_endptr > nptr) {
- // If *tmp_endptr is '\0' include its label as well.
- *ret_origin = dfsan_read_origin_of_first_taint(
- nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
- } else {
- *ret_origin = 0;
- }
- return ret;
- }
- static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
- char **tmp_endptr) {
- assert(tmp_endptr);
- long long int ret = strtoll(nptr, tmp_endptr, base);
- if (endptr)
- *endptr = *tmp_endptr;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label) {
- char *tmp_endptr;
- long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label,
- dfsan_origin nptr_origin,
- dfsan_origin endptr_origin,
- dfsan_origin base_origin,
- dfsan_origin *ret_origin) {
- char *tmp_endptr;
- long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
- ret_origin);
- return ret;
- }
- static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
- int base, char **tmp_endptr) {
- assert(tmp_endptr);
- unsigned long int ret = strtoul(nptr, tmp_endptr, base);
- if (endptr)
- *endptr = *tmp_endptr;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label) {
- char *tmp_endptr;
- unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- unsigned long int __dfso_strtoul(
- const char *nptr, char **endptr, int base, dfsan_label nptr_label,
- dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
- dfsan_origin nptr_origin, dfsan_origin endptr_origin,
- dfsan_origin base_origin, dfsan_origin *ret_origin) {
- char *tmp_endptr;
- unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
- ret_origin);
- return ret;
- }
- static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
- int base, char **tmp_endptr) {
- assert(tmp_endptr);
- long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
- if (endptr)
- *endptr = *tmp_endptr;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
- int base, dfsan_label nptr_label,
- dfsan_label endptr_label,
- dfsan_label base_label,
- dfsan_label *ret_label) {
- char *tmp_endptr;
- long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- long long unsigned int __dfso_strtoull(
- const char *nptr, char **endptr, int base, dfsan_label nptr_label,
- dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
- dfsan_origin nptr_origin, dfsan_origin endptr_origin,
- dfsan_origin base_origin, dfsan_origin *ret_origin) {
- char *tmp_endptr;
- long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
- dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
- dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
- ret_origin);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
- time_t ret = time(t);
- if (ret != (time_t) -1 && t) {
- dfsan_set_label(0, t, sizeof(time_t));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
- dfsan_origin t_origin, dfsan_origin *ret_origin) {
- return __dfsw_time(t, t_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
- dfsan_label src_label, dfsan_label dst_label,
- dfsan_label *ret_label) {
- int ret = inet_pton(af, src, dst);
- if (ret == 1) {
- dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
- af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
- dfsan_label src_label, dfsan_label dst_label,
- dfsan_label *ret_label, dfsan_origin af_origin,
- dfsan_origin src_origin, dfsan_origin dst_origin,
- dfsan_origin *ret_origin) {
- int ret = inet_pton(af, src, dst);
- if (ret == 1) {
- int src_len = strlen(src) + 1;
- dfsan_set_label_origin(
- dfsan_read_label(src, src_len),
- dfsan_read_origin_of_first_taint(src, src_len), dst,
- af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
- dfsan_label timep_label, dfsan_label result_label,
- dfsan_label *ret_label) {
- struct tm *ret = localtime_r(timep, result);
- if (ret) {
- dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
- sizeof(struct tm));
- *ret_label = result_label;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
- dfsan_label timep_label, dfsan_label result_label,
- dfsan_label *ret_label, dfsan_origin timep_origin,
- dfsan_origin result_origin,
- dfsan_origin *ret_origin) {
- struct tm *ret = localtime_r(timep, result);
- if (ret) {
- dfsan_set_label_origin(
- dfsan_read_label(timep, sizeof(time_t)),
- dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
- sizeof(struct tm));
- *ret_label = result_label;
- *ret_origin = result_origin;
- } else {
- *ret_label = 0;
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
- char *buf, size_t buflen, struct passwd **result,
- dfsan_label uid_label, dfsan_label pwd_label,
- dfsan_label buf_label, dfsan_label buflen_label,
- dfsan_label result_label, dfsan_label *ret_label) {
- // Store the data in pwd, the strings referenced from pwd in buf, and the
- // address of pwd in *result. On failure, NULL is stored in *result.
- int ret = getpwuid_r(uid, pwd, buf, buflen, result);
- if (ret == 0) {
- dfsan_set_label(0, pwd, sizeof(struct passwd));
- dfsan_set_label(0, buf, strlen(buf) + 1);
- }
- *ret_label = 0;
- dfsan_set_label(0, result, sizeof(struct passwd*));
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
- struct passwd **result, dfsan_label uid_label,
- dfsan_label pwd_label, dfsan_label buf_label,
- dfsan_label buflen_label, dfsan_label result_label,
- dfsan_label *ret_label, dfsan_origin uid_origin,
- dfsan_origin pwd_origin, dfsan_origin buf_origin,
- dfsan_origin buflen_origin, dfsan_origin result_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
- buf_label, buflen_label, result_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
- int timeout, dfsan_label epfd_label,
- dfsan_label events_label, dfsan_label maxevents_label,
- dfsan_label timeout_label, dfsan_label *ret_label) {
- int ret = epoll_wait(epfd, events, maxevents, timeout);
- if (ret > 0)
- dfsan_set_label(0, events, ret * sizeof(*events));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
- int timeout, dfsan_label epfd_label,
- dfsan_label events_label, dfsan_label maxevents_label,
- dfsan_label timeout_label, dfsan_label *ret_label,
- dfsan_origin epfd_origin, dfsan_origin events_origin,
- dfsan_origin maxevents_origin,
- dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
- return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
- events_label, maxevents_label, timeout_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
- dfsan_label dfs_label, dfsan_label nfds_label,
- dfsan_label timeout_label, dfsan_label *ret_label) {
- int ret = poll(fds, nfds, timeout);
- if (ret >= 0) {
- for (; nfds > 0; --nfds) {
- dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
- }
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
- dfsan_label dfs_label, dfsan_label nfds_label,
- dfsan_label timeout_label, dfsan_label *ret_label,
- dfsan_origin dfs_origin, dfsan_origin nfds_origin,
- dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
- return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout,
- dfsan_label nfds_label, dfsan_label readfds_label,
- dfsan_label writefds_label, dfsan_label exceptfds_label,
- dfsan_label timeout_label, dfsan_label *ret_label) {
- int ret = select(nfds, readfds, writefds, exceptfds, timeout);
- // Clear everything (also on error) since their content is either set or
- // undefined.
- if (readfds) {
- dfsan_set_label(0, readfds, sizeof(fd_set));
- }
- if (writefds) {
- dfsan_set_label(0, writefds, sizeof(fd_set));
- }
- if (exceptfds) {
- dfsan_set_label(0, exceptfds, sizeof(fd_set));
- }
- dfsan_set_label(0, timeout, sizeof(struct timeval));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout,
- dfsan_label nfds_label, dfsan_label readfds_label,
- dfsan_label writefds_label, dfsan_label exceptfds_label,
- dfsan_label timeout_label, dfsan_label *ret_label,
- dfsan_origin nfds_origin, dfsan_origin readfds_origin,
- dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
- dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
- return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
- readfds_label, writefds_label, exceptfds_label,
- timeout_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
- dfsan_label pid_label,
- dfsan_label cpusetsize_label,
- dfsan_label mask_label, dfsan_label *ret_label) {
- int ret = sched_getaffinity(pid, cpusetsize, mask);
- if (ret == 0) {
- dfsan_set_label(0, mask, cpusetsize);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
- dfsan_label pid_label,
- dfsan_label cpusetsize_label,
- dfsan_label mask_label, dfsan_label *ret_label,
- dfsan_origin pid_origin,
- dfsan_origin cpusetsize_origin,
- dfsan_origin mask_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
- cpusetsize_label, mask_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
- dfsan_label *ret_label) {
- int ret = sigemptyset(set);
- dfsan_set_label(0, set, sizeof(sigset_t));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
- dfsan_label *ret_label, dfsan_origin set_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_sigemptyset(set, set_label, ret_label);
- }
- class SignalHandlerScope {
- public:
- SignalHandlerScope() {
- if (DFsanThread *t = GetCurrentThread())
- t->EnterSignalHandler();
- }
- ~SignalHandlerScope() {
- if (DFsanThread *t = GetCurrentThread())
- t->LeaveSignalHandler();
- }
- };
- // Clear DFSan runtime TLS state at the end of a scope.
- //
- // Implementation must be async-signal-safe and use small data size, because
- // instances of this class may live on the signal handler stack.
- //
- // DFSan uses TLS to pass metadata of arguments and return values. When an
- // instrumented function accesses the TLS, if a signal callback happens, and the
- // callback calls other instrumented functions with updating the same TLS, the
- // TLS is in an inconsistent state after the callback ends. This may cause
- // either under-tainting or over-tainting.
- //
- // The current implementation simply resets TLS at restore. This prevents from
- // over-tainting. Although under-tainting may still happen, a taint flow can be
- // found eventually if we run a DFSan-instrumented program multiple times. The
- // alternative option is saving the entire TLS. However the TLS storage takes
- // 2k bytes, and signal calls could be nested. So it does not seem worth.
- class ScopedClearThreadLocalState {
- public:
- ScopedClearThreadLocalState() {}
- ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
- };
- // SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
- const int kMaxSignals = 1024;
- static atomic_uintptr_t sigactions[kMaxSignals];
- static void SignalHandler(int signo) {
- SignalHandlerScope signal_handler_scope;
- ScopedClearThreadLocalState scoped_clear_tls;
- // Clear shadows for all inputs provided by system.
- dfsan_clear_arg_tls(0, sizeof(dfsan_label));
- typedef void (*signal_cb)(int x);
- signal_cb cb =
- (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
- cb(signo);
- }
- static void SignalAction(int signo, siginfo_t *si, void *uc) {
- SignalHandlerScope signal_handler_scope;
- ScopedClearThreadLocalState scoped_clear_tls;
- // Clear shadows for all inputs provided by system. Similar to SignalHandler.
- dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
- dfsan_set_label(0, si, sizeof(*si));
- dfsan_set_label(0, uc, sizeof(ucontext_t));
- typedef void (*sigaction_cb)(int, siginfo_t *, void *);
- sigaction_cb cb =
- (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
- cb(signo, si, uc);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_sigaction(int signum, const struct sigaction *act,
- struct sigaction *oldact, dfsan_label signum_label,
- dfsan_label act_label, dfsan_label oldact_label,
- dfsan_label *ret_label) {
- CHECK_LT(signum, kMaxSignals);
- SignalSpinLocker lock;
- uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
- struct sigaction new_act;
- struct sigaction *pnew_act = act ? &new_act : nullptr;
- if (act) {
- internal_memcpy(pnew_act, act, sizeof(struct sigaction));
- if (pnew_act->sa_flags & SA_SIGINFO) {
- uptr cb = (uptr)(pnew_act->sa_sigaction);
- if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
- atomic_store(&sigactions[signum], cb, memory_order_relaxed);
- pnew_act->sa_sigaction = SignalAction;
- }
- } else {
- uptr cb = (uptr)(pnew_act->sa_handler);
- if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
- atomic_store(&sigactions[signum], cb, memory_order_relaxed);
- pnew_act->sa_handler = SignalHandler;
- }
- }
- }
- int ret = sigaction(signum, pnew_act, oldact);
- if (ret == 0 && oldact) {
- if (oldact->sa_flags & SA_SIGINFO) {
- if (oldact->sa_sigaction == SignalAction)
- oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
- } else {
- if (oldact->sa_handler == SignalHandler)
- oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
- }
- }
- if (oldact) {
- dfsan_set_label(0, oldact, sizeof(struct sigaction));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_sigaction(int signum, const struct sigaction *act,
- struct sigaction *oldact, dfsan_label signum_label,
- dfsan_label act_label, dfsan_label oldact_label,
- dfsan_label *ret_label, dfsan_origin signum_origin,
- dfsan_origin act_origin, dfsan_origin oldact_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
- oldact_label, ret_label);
- }
- static sighandler_t dfsan_signal(int signum, sighandler_t handler,
- dfsan_label *ret_label) {
- CHECK_LT(signum, kMaxSignals);
- SignalSpinLocker lock;
- uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
- if (handler != SIG_IGN && handler != SIG_DFL) {
- atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
- handler = &SignalHandler;
- }
- sighandler_t ret = signal(signum, handler);
- if (ret == SignalHandler)
- ret = (sighandler_t)old_cb;
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- sighandler_t __dfsw_signal(int signum, sighandler_t handler,
- dfsan_label signum_label, dfsan_label handler_label,
- dfsan_label *ret_label) {
- return dfsan_signal(signum, handler, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- sighandler_t __dfso_signal(int signum, sighandler_t handler,
- dfsan_label signum_label, dfsan_label handler_label,
- dfsan_label *ret_label, dfsan_origin signum_origin,
- dfsan_origin handler_origin,
- dfsan_origin *ret_origin) {
- return dfsan_signal(signum, handler, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
- dfsan_label old_ss_label, dfsan_label *ret_label) {
- int ret = sigaltstack(ss, old_ss);
- if (ret != -1 && old_ss)
- dfsan_set_label(0, old_ss, sizeof(*old_ss));
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
- dfsan_label old_ss_label, dfsan_label *ret_label,
- dfsan_origin ss_origin, dfsan_origin old_ss_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
- dfsan_label tv_label, dfsan_label tz_label,
- dfsan_label *ret_label) {
- int ret = gettimeofday(tv, tz);
- if (tv) {
- dfsan_set_label(0, tv, sizeof(struct timeval));
- }
- if (tz) {
- dfsan_set_label(0, tz, sizeof(struct timezone));
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
- dfsan_label tv_label, dfsan_label tz_label,
- dfsan_label *ret_label, dfsan_origin tv_origin,
- dfsan_origin tz_origin, dfsan_origin *ret_origin) {
- return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
- dfsan_label s_label,
- dfsan_label c_label,
- dfsan_label n_label,
- dfsan_label *ret_label) {
- void *ret = memchr(s, c, n);
- if (flags().strict_data_dependencies) {
- *ret_label = ret ? s_label : 0;
- } else {
- size_t len =
- ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
- : n;
- *ret_label =
- dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
- void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
- dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
- dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
- void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
- if (flags().strict_data_dependencies) {
- if (ret)
- *ret_origin = s_origin;
- } else {
- size_t len =
- ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
- : n;
- dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
- *ret_origin = o ? o : (s_label ? s_origin : c_origin);
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
- dfsan_label s_label,
- dfsan_label c_label,
- dfsan_label *ret_label) {
- char *ret = strrchr(s, c);
- if (flags().strict_data_dependencies) {
- *ret_label = ret ? s_label : 0;
- } else {
- *ret_label =
- dfsan_union(dfsan_read_label(s, strlen(s) + 1),
- dfsan_union(s_label, c_label));
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
- char *s, int c, dfsan_label s_label, dfsan_label c_label,
- dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
- dfsan_origin *ret_origin) {
- char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
- if (flags().strict_data_dependencies) {
- if (ret)
- *ret_origin = s_origin;
- } else {
- size_t s_len = strlen(s) + 1;
- dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
- *ret_origin = o ? o : (s_label ? s_origin : c_origin);
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
- dfsan_label haystack_label,
- dfsan_label needle_label,
- dfsan_label *ret_label) {
- char *ret = strstr(haystack, needle);
- if (flags().strict_data_dependencies) {
- *ret_label = ret ? haystack_label : 0;
- } else {
- size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
- *ret_label =
- dfsan_union(dfsan_read_label(haystack, len),
- dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
- dfsan_union(haystack_label, needle_label)));
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
- dfsan_label haystack_label,
- dfsan_label needle_label,
- dfsan_label *ret_label,
- dfsan_origin haystack_origin,
- dfsan_origin needle_origin,
- dfsan_origin *ret_origin) {
- char *ret =
- __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
- if (flags().strict_data_dependencies) {
- if (ret)
- *ret_origin = haystack_origin;
- } else {
- size_t needle_len = strlen(needle);
- size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
- dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
- if (o) {
- *ret_origin = o;
- } else {
- o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
- *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
- }
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
- struct timespec *rem,
- dfsan_label req_label,
- dfsan_label rem_label,
- dfsan_label *ret_label) {
- int ret = nanosleep(req, rem);
- *ret_label = 0;
- if (ret == -1) {
- // Interrupted by a signal, rem is filled with the remaining time.
- dfsan_set_label(0, rem, sizeof(struct timespec));
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
- const struct timespec *req, struct timespec *rem, dfsan_label req_label,
- dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
- dfsan_origin rem_origin, dfsan_origin *ret_origin) {
- return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
- }
- static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
- dfsan_set_label(0, msg, sizeof(*msg));
- dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
- dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
- for (size_t i = 0; bytes_written > 0; ++i) {
- assert(i < msg->msg_iovlen);
- struct iovec *iov = &msg->msg_iov[i];
- size_t iov_written =
- bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
- dfsan_set_label(0, iov->iov_base, iov_written);
- bytes_written -= iov_written;
- }
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
- int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
- struct timespec *timeout, dfsan_label sockfd_label,
- dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
- dfsan_label timeout_label, dfsan_label *ret_label) {
- int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
- for (int i = 0; i < ret; ++i) {
- dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
- clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
- int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
- struct timespec *timeout, dfsan_label sockfd_label,
- dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
- dfsan_label timeout_label, dfsan_label *ret_label,
- dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
- dfsan_origin vlen_origin, dfsan_origin flags_origin,
- dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
- return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
- msgvec_label, vlen_label, flags_label, timeout_label,
- ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
- int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
- dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
- ssize_t ret = recvmsg(sockfd, msg, flags);
- if (ret >= 0)
- clear_msghdr_labels(ret, msg);
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
- int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
- dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
- dfsan_origin sockfd_origin, dfsan_origin msg_origin,
- dfsan_origin flags_origin, dfsan_origin *ret_origin) {
- return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
- flags_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int
- __dfsw_socketpair(int domain, int type, int protocol, int sv[2],
- dfsan_label domain_label, dfsan_label type_label,
- dfsan_label protocol_label, dfsan_label sv_label,
- dfsan_label *ret_label) {
- int ret = socketpair(domain, type, protocol, sv);
- *ret_label = 0;
- if (ret == 0) {
- dfsan_set_label(0, sv, sizeof(*sv) * 2);
- }
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
- int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
- dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
- dfsan_label *ret_label, dfsan_origin domain_origin,
- dfsan_origin type_origin, dfsan_origin protocol_origin,
- dfsan_origin sv_origin, dfsan_origin *ret_origin) {
- return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
- protocol_label, sv_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
- int sockfd, int level, int optname, void *optval, socklen_t *optlen,
- dfsan_label sockfd_label, dfsan_label level_label,
- dfsan_label optname_label, dfsan_label optval_label,
- dfsan_label optlen_label, dfsan_label *ret_label) {
- int ret = getsockopt(sockfd, level, optname, optval, optlen);
- if (ret != -1 && optval && optlen) {
- dfsan_set_label(0, optlen, sizeof(*optlen));
- dfsan_set_label(0, optval, *optlen);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
- int sockfd, int level, int optname, void *optval, socklen_t *optlen,
- dfsan_label sockfd_label, dfsan_label level_label,
- dfsan_label optname_label, dfsan_label optval_label,
- dfsan_label optlen_label, dfsan_label *ret_label,
- dfsan_origin sockfd_origin, dfsan_origin level_origin,
- dfsan_origin optname_origin, dfsan_origin optval_origin,
- dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
- return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
- level_label, optname_label, optval_label,
- optlen_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
- int sockfd, struct sockaddr *addr, socklen_t *addrlen,
- dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
- dfsan_label *ret_label) {
- socklen_t origlen = addrlen ? *addrlen : 0;
- int ret = getsockname(sockfd, addr, addrlen);
- if (ret != -1 && addr && addrlen) {
- socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
- dfsan_set_label(0, addrlen, sizeof(*addrlen));
- dfsan_set_label(0, addr, written_bytes);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
- int sockfd, struct sockaddr *addr, socklen_t *addrlen,
- dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
- dfsan_label *ret_label, dfsan_origin sockfd_origin,
- dfsan_origin addr_origin, dfsan_origin addrlen_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
- addrlen_label, ret_label);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
- int sockfd, struct sockaddr *addr, socklen_t *addrlen,
- dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
- dfsan_label *ret_label) {
- socklen_t origlen = addrlen ? *addrlen : 0;
- int ret = getpeername(sockfd, addr, addrlen);
- if (ret != -1 && addr && addrlen) {
- socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
- dfsan_set_label(0, addrlen, sizeof(*addrlen));
- dfsan_set_label(0, addr, written_bytes);
- }
- *ret_label = 0;
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
- int sockfd, struct sockaddr *addr, socklen_t *addrlen,
- dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
- dfsan_label *ret_label, dfsan_origin sockfd_origin,
- dfsan_origin addr_origin, dfsan_origin addrlen_origin,
- dfsan_origin *ret_origin) {
- return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
- addrlen_label, ret_label);
- }
- // Type of the function passed to dfsan_set_write_callback.
- typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
- // Calls to dfsan_set_write_callback() set the values in this struct.
- // Calls to the custom version of write() read (and invoke) them.
- static struct {
- write_dfsan_callback_t write_callback = nullptr;
- } write_callback_info;
- SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
- write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
- dfsan_label *ret_label) {
- write_callback_info.write_callback = write_callback;
- }
- SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
- write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
- dfsan_label *ret_label, dfsan_origin write_callback_origin,
- dfsan_origin *ret_origin) {
- write_callback_info.write_callback = write_callback;
- }
- static inline void setup_tls_args_for_write_callback(
- dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
- bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
- dfsan_origin count_origin) {
- // The callback code will expect argument shadow labels in the args TLS,
- // and origin labels in the origin args TLS.
- // Previously this was done by a trampoline, but we want to remove this:
- // https://github.com/llvm/llvm-project/issues/54172
- //
- // Instead, this code is manually setting up the args TLS data.
- //
- // The offsets used need to correspond with the instrumentation code,
- // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
- // DFSanFunction::getShadowForTLSArgument.
- // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
- // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
- //
- // Here the arguments are all primitives, but it can be more complex
- // to compute offsets for array/aggregate type arguments.
- //
- // TODO(browneee): Consider a builtin to improve maintainabliity.
- // With a builtin, we would provide the argument labels via builtin,
- // and the builtin would reuse parts of the instrumentation code to ensure
- // that this code and the instrumentation can never be out of sync.
- // Note: Currently DFSan instrumentation does not run on this code, so
- // the builtin may need to be handled outside DFSan instrumentation.
- dfsan_set_arg_tls(0, fd_label);
- dfsan_set_arg_tls(1, buf_label);
- dfsan_set_arg_tls(2, count_label);
- if (origins) {
- dfsan_set_arg_origin_tls(0, fd_origin);
- dfsan_set_arg_origin_tls(1, buf_origin);
- dfsan_set_arg_origin_tls(2, count_origin);
- }
- }
- SANITIZER_INTERFACE_ATTRIBUTE int
- __dfsw_write(int fd, const void *buf, size_t count,
- dfsan_label fd_label, dfsan_label buf_label,
- dfsan_label count_label, dfsan_label *ret_label) {
- if (write_callback_info.write_callback) {
- setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
- 0, 0, 0);
- write_callback_info.write_callback(fd, buf, count);
- }
- *ret_label = 0;
- return write(fd, buf, count);
- }
- SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
- int fd, const void *buf, size_t count, dfsan_label fd_label,
- dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
- dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
- dfsan_origin *ret_origin) {
- if (write_callback_info.write_callback) {
- setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
- fd_origin, buf_origin, count_origin);
- write_callback_info.write_callback(fd, buf, count);
- }
- *ret_label = 0;
- return write(fd, buf, count);
- }
- } // namespace __dfsan
- // Type used to extract a dfsan_label with va_arg()
- typedef int dfsan_label_va;
- // Formats a chunk either a constant string or a single format directive (e.g.,
- // '%.3f').
- struct Formatter {
- Formatter(char *str_, const char *fmt_, size_t size_)
- : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
- width(-1) {}
- int format() {
- char *tmp_fmt = build_format_string();
- int retval =
- snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
- 0 /* used only to avoid warnings */);
- free(tmp_fmt);
- return retval;
- }
- template <typename T> int format(T arg) {
- char *tmp_fmt = build_format_string();
- int retval;
- if (width >= 0) {
- retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
- tmp_fmt, width, arg);
- } else {
- retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
- tmp_fmt, arg);
- }
- free(tmp_fmt);
- return retval;
- }
- char *build_format_string() {
- size_t fmt_size = fmt_cur - fmt_start + 1;
- char *new_fmt = (char *)malloc(fmt_size + 1);
- assert(new_fmt);
- internal_memcpy(new_fmt, fmt_start, fmt_size);
- new_fmt[fmt_size] = '\0';
- return new_fmt;
- }
- char *str_cur() { return str + str_off; }
- size_t num_written_bytes(int retval) {
- if (retval < 0) {
- return 0;
- }
- size_t num_avail = str_off < size ? size - str_off : 0;
- if (num_avail == 0) {
- return 0;
- }
- size_t num_written = retval;
- // A return value of {v,}snprintf of size or more means that the output was
- // truncated.
- if (num_written >= num_avail) {
- num_written -= num_avail;
- }
- return num_written;
- }
- char *str;
- size_t str_off;
- size_t size;
- const char *fmt_start;
- const char *fmt_cur;
- int width;
- };
- // Formats the input and propagates the input labels to the output. The output
- // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
- // 'ap' are the format string and the list of arguments for formatting. Returns
- // the return value vsnprintf would return.
- //
- // The function tokenizes the format string in chunks representing either a
- // constant string or a single format directive (e.g., '%.3f') and formats each
- // chunk independently into the output string. This approach allows to figure
- // out which bytes of the output string depends on which argument and thus to
- // propagate labels more precisely.
- //
- // WARNING: This implementation does not support conversion specifiers with
- // positional arguments.
- static int format_buffer(char *str, size_t size, const char *fmt,
- dfsan_label *va_labels, dfsan_label *ret_label,
- dfsan_origin *va_origins, dfsan_origin *ret_origin,
- va_list ap) {
- Formatter formatter(str, fmt, size);
- while (*formatter.fmt_cur) {
- formatter.fmt_start = formatter.fmt_cur;
- formatter.width = -1;
- int retval = 0;
- if (*formatter.fmt_cur != '%') {
- // Ordinary character. Consume all the characters until a '%' or the end
- // of the string.
- for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
- ++formatter.fmt_cur) {}
- retval = formatter.format();
- dfsan_set_label(0, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- } else {
- // Conversion directive. Consume all the characters until a conversion
- // specifier or the end of the string.
- bool end_fmt = false;
- for (; *formatter.fmt_cur && !end_fmt; ) {
- switch (*++formatter.fmt_cur) {
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- switch (*(formatter.fmt_cur - 1)) {
- case 'h':
- // Also covers the 'hh' case (since the size of the arg is still
- // an int).
- retval = formatter.format(va_arg(ap, int));
- break;
- case 'l':
- if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
- *(formatter.fmt_cur - 2) == 'l') {
- retval = formatter.format(va_arg(ap, long long int));
- } else {
- retval = formatter.format(va_arg(ap, long int));
- }
- break;
- case 'q':
- retval = formatter.format(va_arg(ap, long long int));
- break;
- case 'j':
- retval = formatter.format(va_arg(ap, intmax_t));
- break;
- case 'z':
- case 't':
- retval = formatter.format(va_arg(ap, size_t));
- break;
- default:
- retval = formatter.format(va_arg(ap, int));
- }
- if (va_origins == nullptr)
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- else
- dfsan_set_label_origin(*va_labels++, *va_origins++,
- formatter.str_cur(),
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- if (*(formatter.fmt_cur - 1) == 'L') {
- retval = formatter.format(va_arg(ap, long double));
- } else {
- retval = formatter.format(va_arg(ap, double));
- }
- if (va_origins == nullptr)
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- else
- dfsan_set_label_origin(*va_labels++, *va_origins++,
- formatter.str_cur(),
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- case 'c':
- retval = formatter.format(va_arg(ap, int));
- if (va_origins == nullptr)
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- else
- dfsan_set_label_origin(*va_labels++, *va_origins++,
- formatter.str_cur(),
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- case 's': {
- char *arg = va_arg(ap, char *);
- retval = formatter.format(arg);
- if (va_origins) {
- va_origins++;
- dfsan_mem_origin_transfer(formatter.str_cur(), arg,
- formatter.num_written_bytes(retval));
- }
- va_labels++;
- dfsan_mem_shadow_transfer(formatter.str_cur(), arg,
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- }
- case 'p':
- retval = formatter.format(va_arg(ap, void *));
- if (va_origins == nullptr)
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- else
- dfsan_set_label_origin(*va_labels++, *va_origins++,
- formatter.str_cur(),
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- case 'n': {
- int *ptr = va_arg(ap, int *);
- *ptr = (int)formatter.str_off;
- va_labels++;
- if (va_origins)
- va_origins++;
- dfsan_set_label(0, ptr, sizeof(ptr));
- end_fmt = true;
- break;
- }
- case '%':
- retval = formatter.format();
- dfsan_set_label(0, formatter.str_cur(),
- formatter.num_written_bytes(retval));
- end_fmt = true;
- break;
- case '*':
- formatter.width = va_arg(ap, int);
- va_labels++;
- if (va_origins)
- va_origins++;
- break;
- default:
- break;
- }
- }
- }
- if (retval < 0) {
- return retval;
- }
- formatter.fmt_cur++;
- formatter.str_off += retval;
- }
- *ret_label = 0;
- if (ret_origin)
- *ret_origin = 0;
- // Number of bytes written in total.
- return formatter.str_off;
- }
- extern "C" {
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
- dfsan_label format_label, dfsan_label *va_labels,
- dfsan_label *ret_label, ...) {
- va_list ap;
- va_start(ap, ret_label);
- int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
- nullptr, ap);
- va_end(ap);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
- dfsan_label format_label, dfsan_label *va_labels,
- dfsan_label *ret_label, dfsan_origin str_origin,
- dfsan_origin format_origin, dfsan_origin *va_origins,
- dfsan_origin *ret_origin, ...) {
- va_list ap;
- va_start(ap, ret_origin);
- int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins,
- ret_origin, ap);
- va_end(ap);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfsw_snprintf(char *str, size_t size, const char *format,
- dfsan_label str_label, dfsan_label size_label,
- dfsan_label format_label, dfsan_label *va_labels,
- dfsan_label *ret_label, ...) {
- va_list ap;
- va_start(ap, ret_label);
- int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
- nullptr, ap);
- va_end(ap);
- return ret;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- int __dfso_snprintf(char *str, size_t size, const char *format,
- dfsan_label str_label, dfsan_label size_label,
- dfsan_label format_label, dfsan_label *va_labels,
- dfsan_label *ret_label, dfsan_origin str_origin,
- dfsan_origin size_origin, dfsan_origin format_origin,
- dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
- va_list ap;
- va_start(ap, ret_origin);
- int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
- ret_origin, ap);
- va_end(ap);
- return ret;
- }
- static void BeforeFork() {
- StackDepotLockAll();
- GetChainedOriginDepot()->LockAll();
- }
- static void AfterFork() {
- GetChainedOriginDepot()->UnlockAll();
- StackDepotUnlockAll();
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- pid_t __dfsw_fork(dfsan_label *ret_label) {
- pid_t pid = fork();
- *ret_label = 0;
- return pid;
- }
- SANITIZER_INTERFACE_ATTRIBUTE
- pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
- BeforeFork();
- pid_t pid = __dfsw_fork(ret_label);
- AfterFork();
- return pid;
- }
- // Default empty implementations (weak). Users should redefine them.
- SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
- u32 *) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,
- const uptr *end) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
- void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
- void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
- void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
- void) {}
- SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
- } // extern "C"
|