1353944Sdim//===-- msan.cpp ----------------------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is a part of MemorySanitizer. 10353944Sdim// 11353944Sdim// MemorySanitizer runtime. 12353944Sdim//===----------------------------------------------------------------------===// 13353944Sdim 14353944Sdim#include "msan.h" 15353944Sdim#include "msan_chained_origin_depot.h" 16353944Sdim#include "msan_origin.h" 17353944Sdim#include "msan_report.h" 18353944Sdim#include "msan_thread.h" 19353944Sdim#include "msan_poisoning.h" 20353944Sdim#include "sanitizer_common/sanitizer_atomic.h" 21353944Sdim#include "sanitizer_common/sanitizer_common.h" 22353944Sdim#include "sanitizer_common/sanitizer_flags.h" 23353944Sdim#include "sanitizer_common/sanitizer_flag_parser.h" 24353944Sdim#include "sanitizer_common/sanitizer_libc.h" 25353944Sdim#include "sanitizer_common/sanitizer_procmaps.h" 26353944Sdim#include "sanitizer_common/sanitizer_stacktrace.h" 27353944Sdim#include "sanitizer_common/sanitizer_symbolizer.h" 28353944Sdim#include "sanitizer_common/sanitizer_stackdepot.h" 29353944Sdim#include "ubsan/ubsan_flags.h" 30353944Sdim#include "ubsan/ubsan_init.h" 31353944Sdim 32353944Sdim// ACHTUNG! No system header includes in this file. 33353944Sdim 34353944Sdimusing namespace __sanitizer; 35353944Sdim 36353944Sdim// Globals. 37353944Sdimstatic THREADLOCAL int msan_expect_umr = 0; 38353944Sdimstatic THREADLOCAL int msan_expected_umr_found = 0; 39353944Sdim 40353944Sdim// Function argument shadow. Each argument starts at the next available 8-byte 41353944Sdim// aligned address. 42353944SdimSANITIZER_INTERFACE_ATTRIBUTE 43353944SdimTHREADLOCAL u64 __msan_param_tls[kMsanParamTlsSize / sizeof(u64)]; 44353944Sdim 45353944Sdim// Function argument origin. Each argument starts at the same offset as the 46353944Sdim// corresponding shadow in (__msan_param_tls). Slightly weird, but changing this 47353944Sdim// would break compatibility with older prebuilt binaries. 48353944SdimSANITIZER_INTERFACE_ATTRIBUTE 49353944SdimTHREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 50353944Sdim 51353944SdimSANITIZER_INTERFACE_ATTRIBUTE 52353944SdimTHREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSize / sizeof(u64)]; 53353944Sdim 54353944SdimSANITIZER_INTERFACE_ATTRIBUTE 55353944SdimTHREADLOCAL u32 __msan_retval_origin_tls; 56353944Sdim 57353944SdimSANITIZER_INTERFACE_ATTRIBUTE 58353944SdimALIGNED(16) THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; 59353944Sdim 60353944SdimSANITIZER_INTERFACE_ATTRIBUTE 61353944SdimALIGNED(16) 62353944SdimTHREADLOCAL u32 __msan_va_arg_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 63353944Sdim 64353944SdimSANITIZER_INTERFACE_ATTRIBUTE 65353944SdimTHREADLOCAL u64 __msan_va_arg_overflow_size_tls; 66353944Sdim 67353944SdimSANITIZER_INTERFACE_ATTRIBUTE 68353944SdimTHREADLOCAL u32 __msan_origin_tls; 69353944Sdim 70353944Sdimstatic THREADLOCAL int is_in_symbolizer; 71353944Sdim 72353944Sdimextern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; 73353944Sdim 74353944Sdimint __msan_get_track_origins() { 75353944Sdim return &__msan_track_origins ? __msan_track_origins : 0; 76353944Sdim} 77353944Sdim 78353944Sdimextern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going; 79353944Sdim 80353944Sdimnamespace __msan { 81353944Sdim 82353944Sdimvoid EnterSymbolizer() { ++is_in_symbolizer; } 83353944Sdimvoid ExitSymbolizer() { --is_in_symbolizer; } 84353944Sdimbool IsInSymbolizer() { return is_in_symbolizer; } 85353944Sdim 86353944Sdimstatic Flags msan_flags; 87353944Sdim 88353944SdimFlags *flags() { 89353944Sdim return &msan_flags; 90353944Sdim} 91353944Sdim 92353944Sdimint msan_inited = 0; 93353944Sdimbool msan_init_is_running; 94353944Sdim 95353944Sdimint msan_report_count = 0; 96353944Sdim 97353944Sdim// Array of stack origins. 98353944Sdim// FIXME: make it resizable. 99353944Sdimstatic const uptr kNumStackOriginDescrs = 1024 * 1024; 100353944Sdimstatic const char *StackOriginDescr[kNumStackOriginDescrs]; 101353944Sdimstatic uptr StackOriginPC[kNumStackOriginDescrs]; 102353944Sdimstatic atomic_uint32_t NumStackOriginDescrs; 103353944Sdim 104353944Sdimvoid Flags::SetDefaults() { 105353944Sdim#define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 106353944Sdim#include "msan_flags.inc" 107353944Sdim#undef MSAN_FLAG 108353944Sdim} 109353944Sdim 110353944Sdim// keep_going is an old name for halt_on_error, 111353944Sdim// and it has inverse meaning. 112353944Sdimclass FlagHandlerKeepGoing : public FlagHandlerBase { 113353944Sdim bool *halt_on_error_; 114353944Sdim 115353944Sdim public: 116353944Sdim explicit FlagHandlerKeepGoing(bool *halt_on_error) 117353944Sdim : halt_on_error_(halt_on_error) {} 118353944Sdim bool Parse(const char *value) final { 119353944Sdim bool tmp; 120353944Sdim FlagHandler<bool> h(&tmp); 121353944Sdim if (!h.Parse(value)) return false; 122353944Sdim *halt_on_error_ = !tmp; 123353944Sdim return true; 124353944Sdim } 125357095Sdim bool Format(char *buffer, uptr size) final { 126357095Sdim const char *keep_going_str = (*halt_on_error_) ? "false" : "true"; 127357095Sdim return FormatString(buffer, size, keep_going_str); 128357095Sdim } 129353944Sdim}; 130353944Sdim 131353944Sdimstatic void RegisterMsanFlags(FlagParser *parser, Flags *f) { 132353944Sdim#define MSAN_FLAG(Type, Name, DefaultValue, Description) \ 133353944Sdim RegisterFlag(parser, #Name, Description, &f->Name); 134353944Sdim#include "msan_flags.inc" 135353944Sdim#undef MSAN_FLAG 136353944Sdim 137353944Sdim FlagHandlerKeepGoing *fh_keep_going = 138353944Sdim new (FlagParser::Alloc) FlagHandlerKeepGoing(&f->halt_on_error); 139353944Sdim parser->RegisterHandler("keep_going", fh_keep_going, 140353944Sdim "deprecated, use halt_on_error"); 141353944Sdim} 142353944Sdim 143353944Sdimstatic void InitializeFlags() { 144353944Sdim SetCommonFlagsDefaults(); 145353944Sdim { 146353944Sdim CommonFlags cf; 147353944Sdim cf.CopyFrom(*common_flags()); 148353944Sdim cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); 149353944Sdim cf.malloc_context_size = 20; 150353944Sdim cf.handle_ioctl = true; 151353944Sdim // FIXME: test and enable. 152353944Sdim cf.check_printf = false; 153353944Sdim cf.intercept_tls_get_addr = true; 154353944Sdim cf.exitcode = 77; 155353944Sdim OverrideCommonFlags(cf); 156353944Sdim } 157353944Sdim 158353944Sdim Flags *f = flags(); 159353944Sdim f->SetDefaults(); 160353944Sdim 161353944Sdim FlagParser parser; 162353944Sdim RegisterMsanFlags(&parser, f); 163353944Sdim RegisterCommonFlags(&parser); 164353944Sdim 165353944Sdim#if MSAN_CONTAINS_UBSAN 166353944Sdim __ubsan::Flags *uf = __ubsan::flags(); 167353944Sdim uf->SetDefaults(); 168353944Sdim 169353944Sdim FlagParser ubsan_parser; 170353944Sdim __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 171353944Sdim RegisterCommonFlags(&ubsan_parser); 172353944Sdim#endif 173353944Sdim 174353944Sdim // Override from user-specified string. 175353944Sdim if (__msan_default_options) 176353944Sdim parser.ParseString(__msan_default_options()); 177353944Sdim#if MSAN_CONTAINS_UBSAN 178353944Sdim const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); 179353944Sdim ubsan_parser.ParseString(ubsan_default_options); 180353944Sdim#endif 181353944Sdim 182353944Sdim parser.ParseStringFromEnv("MSAN_OPTIONS"); 183353944Sdim#if MSAN_CONTAINS_UBSAN 184353944Sdim ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 185353944Sdim#endif 186353944Sdim 187353944Sdim InitializeCommonFlags(); 188353944Sdim 189353944Sdim if (Verbosity()) ReportUnrecognizedFlags(); 190353944Sdim 191353944Sdim if (common_flags()->help) parser.PrintFlagDescriptions(); 192353944Sdim 193353944Sdim // Check if deprecated exit_code MSan flag is set. 194353944Sdim if (f->exit_code != -1) { 195353944Sdim if (Verbosity()) 196353944Sdim Printf("MSAN_OPTIONS=exit_code is deprecated! " 197353944Sdim "Please use MSAN_OPTIONS=exitcode instead.\n"); 198353944Sdim CommonFlags cf; 199353944Sdim cf.CopyFrom(*common_flags()); 200353944Sdim cf.exitcode = f->exit_code; 201353944Sdim OverrideCommonFlags(cf); 202353944Sdim } 203353944Sdim 204353944Sdim // Check flag values: 205353944Sdim if (f->origin_history_size < 0 || 206353944Sdim f->origin_history_size > Origin::kMaxDepth) { 207353944Sdim Printf( 208353944Sdim "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " 209353944Sdim "range.\n", 210353944Sdim f->origin_history_size, Origin::kMaxDepth); 211353944Sdim Die(); 212353944Sdim } 213353944Sdim // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in 214353944Sdim // StackDepotHandle::inc_use_count_unsafe. 215353944Sdim if (f->origin_history_per_stack_limit < 0 || 216353944Sdim f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { 217353944Sdim Printf( 218353944Sdim "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " 219353944Sdim "%d] range.\n", 220353944Sdim f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); 221353944Sdim Die(); 222353944Sdim } 223353944Sdim if (f->store_context_size < 1) f->store_context_size = 1; 224353944Sdim} 225353944Sdim 226353944Sdimvoid PrintWarning(uptr pc, uptr bp) { 227353944Sdim PrintWarningWithOrigin(pc, bp, __msan_origin_tls); 228353944Sdim} 229353944Sdim 230353944Sdimvoid PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) { 231353944Sdim if (msan_expect_umr) { 232353944Sdim // Printf("Expected UMR\n"); 233353944Sdim __msan_origin_tls = origin; 234353944Sdim msan_expected_umr_found = 1; 235353944Sdim return; 236353944Sdim } 237353944Sdim 238353944Sdim ++msan_report_count; 239353944Sdim 240353944Sdim GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 241353944Sdim 242353944Sdim u32 report_origin = 243353944Sdim (__msan_get_track_origins() && Origin::isValidId(origin)) ? origin : 0; 244353944Sdim ReportUMR(&stack, report_origin); 245353944Sdim 246353944Sdim if (__msan_get_track_origins() && !Origin::isValidId(origin)) { 247353944Sdim Printf( 248353944Sdim " ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin " 249353944Sdim "tracking.\n This could still be a bug in your code, too!\n", 250353944Sdim origin); 251353944Sdim } 252353944Sdim} 253353944Sdim 254353944Sdimvoid UnpoisonParam(uptr n) { 255353944Sdim internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls)); 256353944Sdim} 257353944Sdim 258353944Sdim// Backup MSan runtime TLS state. 259353944Sdim// Implementation must be async-signal-safe. 260353944Sdim// Instances of this class may live on the signal handler stack, and data size 261353944Sdim// may be an issue. 262353944Sdimvoid ScopedThreadLocalStateBackup::Backup() { 263353944Sdim va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls; 264353944Sdim} 265353944Sdim 266353944Sdimvoid ScopedThreadLocalStateBackup::Restore() { 267353944Sdim // A lame implementation that only keeps essential state and resets the rest. 268353944Sdim __msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls; 269353944Sdim 270353944Sdim internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 271353944Sdim internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 272353944Sdim internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 273353944Sdim internal_memset(__msan_va_arg_origin_tls, 0, 274353944Sdim sizeof(__msan_va_arg_origin_tls)); 275353944Sdim 276353944Sdim if (__msan_get_track_origins()) { 277353944Sdim internal_memset(&__msan_retval_origin_tls, 0, 278353944Sdim sizeof(__msan_retval_origin_tls)); 279353944Sdim internal_memset(__msan_param_origin_tls, 0, 280353944Sdim sizeof(__msan_param_origin_tls)); 281353944Sdim } 282353944Sdim} 283353944Sdim 284353944Sdimvoid UnpoisonThreadLocalState() { 285353944Sdim} 286353944Sdim 287353944Sdimconst char *GetStackOriginDescr(u32 id, uptr *pc) { 288353944Sdim CHECK_LT(id, kNumStackOriginDescrs); 289353944Sdim if (pc) *pc = StackOriginPC[id]; 290353944Sdim return StackOriginDescr[id]; 291353944Sdim} 292353944Sdim 293353944Sdimu32 ChainOrigin(u32 id, StackTrace *stack) { 294353944Sdim MsanThread *t = GetCurrentThread(); 295353944Sdim if (t && t->InSignalHandler()) 296353944Sdim return id; 297353944Sdim 298353944Sdim Origin o = Origin::FromRawId(id); 299353944Sdim stack->tag = StackTrace::TAG_UNKNOWN; 300353944Sdim Origin chained = Origin::CreateChainedOrigin(o, stack); 301353944Sdim return chained.raw_id(); 302353944Sdim} 303353944Sdim 304353944Sdim} // namespace __msan 305353944Sdim 306353944Sdimvoid __sanitizer::BufferedStackTrace::UnwindImpl( 307353944Sdim uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 308353944Sdim using namespace __msan; 309353944Sdim MsanThread *t = GetCurrentThread(); 310353944Sdim if (!t || !StackTrace::WillUseFastUnwind(request_fast)) { 311353944Sdim // Block reports from our interceptors during _Unwind_Backtrace. 312353944Sdim SymbolizerScope sym_scope; 313353944Sdim return Unwind(max_depth, pc, bp, context, 0, 0, false); 314353944Sdim } 315353944Sdim if (StackTrace::WillUseFastUnwind(request_fast)) 316353944Sdim Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true); 317353944Sdim else 318353944Sdim Unwind(max_depth, pc, 0, context, 0, 0, false); 319353944Sdim} 320353944Sdim 321353944Sdim// Interface. 322353944Sdim 323353944Sdimusing namespace __msan; 324353944Sdim 325353944Sdim#define MSAN_MAYBE_WARNING(type, size) \ 326353944Sdim void __msan_maybe_warning_##size(type s, u32 o) { \ 327353944Sdim GET_CALLER_PC_BP_SP; \ 328353944Sdim (void) sp; \ 329353944Sdim if (UNLIKELY(s)) { \ 330353944Sdim PrintWarningWithOrigin(pc, bp, o); \ 331353944Sdim if (__msan::flags()->halt_on_error) { \ 332353944Sdim Printf("Exiting\n"); \ 333353944Sdim Die(); \ 334353944Sdim } \ 335353944Sdim } \ 336353944Sdim } 337353944Sdim 338353944SdimMSAN_MAYBE_WARNING(u8, 1) 339353944SdimMSAN_MAYBE_WARNING(u16, 2) 340353944SdimMSAN_MAYBE_WARNING(u32, 4) 341353944SdimMSAN_MAYBE_WARNING(u64, 8) 342353944Sdim 343353944Sdim#define MSAN_MAYBE_STORE_ORIGIN(type, size) \ 344353944Sdim void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \ 345353944Sdim if (UNLIKELY(s)) { \ 346353944Sdim if (__msan_get_track_origins() > 1) { \ 347353944Sdim GET_CALLER_PC_BP_SP; \ 348353944Sdim (void) sp; \ 349353944Sdim GET_STORE_STACK_TRACE_PC_BP(pc, bp); \ 350353944Sdim o = ChainOrigin(o, &stack); \ 351353944Sdim } \ 352353944Sdim *(u32 *)MEM_TO_ORIGIN((uptr)p & ~3UL) = o; \ 353353944Sdim } \ 354353944Sdim } 355353944Sdim 356353944SdimMSAN_MAYBE_STORE_ORIGIN(u8, 1) 357353944SdimMSAN_MAYBE_STORE_ORIGIN(u16, 2) 358353944SdimMSAN_MAYBE_STORE_ORIGIN(u32, 4) 359353944SdimMSAN_MAYBE_STORE_ORIGIN(u64, 8) 360353944Sdim 361353944Sdimvoid __msan_warning() { 362353944Sdim GET_CALLER_PC_BP_SP; 363353944Sdim (void)sp; 364353944Sdim PrintWarning(pc, bp); 365353944Sdim if (__msan::flags()->halt_on_error) { 366353944Sdim if (__msan::flags()->print_stats) 367353944Sdim ReportStats(); 368353944Sdim Printf("Exiting\n"); 369353944Sdim Die(); 370353944Sdim } 371353944Sdim} 372353944Sdim 373353944Sdimvoid __msan_warning_noreturn() { 374353944Sdim GET_CALLER_PC_BP_SP; 375353944Sdim (void)sp; 376353944Sdim PrintWarning(pc, bp); 377353944Sdim if (__msan::flags()->print_stats) 378353944Sdim ReportStats(); 379353944Sdim Printf("Exiting\n"); 380353944Sdim Die(); 381353944Sdim} 382353944Sdim 383353944Sdimstatic void OnStackUnwind(const SignalContext &sig, const void *, 384353944Sdim BufferedStackTrace *stack) { 385353944Sdim stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 386353944Sdim common_flags()->fast_unwind_on_fatal); 387353944Sdim} 388353944Sdim 389353944Sdimstatic void MsanOnDeadlySignal(int signo, void *siginfo, void *context) { 390353944Sdim HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr); 391353944Sdim} 392353944Sdim 393353944Sdimstatic void MsanCheckFailed(const char *file, int line, const char *cond, 394353944Sdim u64 v1, u64 v2) { 395353944Sdim Report("MemorySanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file, 396353944Sdim line, cond, (uptr)v1, (uptr)v2); 397353944Sdim PRINT_CURRENT_STACK_CHECK(); 398353944Sdim Die(); 399353944Sdim} 400353944Sdim 401353944Sdimvoid __msan_init() { 402353944Sdim CHECK(!msan_init_is_running); 403353944Sdim if (msan_inited) return; 404353944Sdim msan_init_is_running = 1; 405353944Sdim SanitizerToolName = "MemorySanitizer"; 406353944Sdim 407353944Sdim AvoidCVE_2016_2143(); 408353944Sdim 409353944Sdim CacheBinaryName(); 410353944Sdim InitializeFlags(); 411353944Sdim 412353944Sdim // Install tool-specific callbacks in sanitizer_common. 413353944Sdim SetCheckFailedCallback(MsanCheckFailed); 414353944Sdim 415353944Sdim __sanitizer_set_report_path(common_flags()->log_path); 416353944Sdim 417353944Sdim InitializeInterceptors(); 418353944Sdim CheckASLR(); 419353944Sdim InitTlsSize(); 420353944Sdim InstallDeadlySignalHandlers(MsanOnDeadlySignal); 421353944Sdim InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 422353944Sdim 423353944Sdim DisableCoreDumperIfNecessary(); 424353944Sdim if (StackSizeIsUnlimited()) { 425353944Sdim VPrintf(1, "Unlimited stack, doing reexec\n"); 426353944Sdim // A reasonably large stack size. It is bigger than the usual 8Mb, because, 427353944Sdim // well, the program could have been run with unlimited stack for a reason. 428353944Sdim SetStackSizeLimitInBytes(32 * 1024 * 1024); 429353944Sdim ReExec(); 430353944Sdim } 431353944Sdim 432353944Sdim __msan_clear_on_return(); 433353944Sdim if (__msan_get_track_origins()) 434353944Sdim VPrintf(1, "msan_track_origins\n"); 435353944Sdim if (!InitShadow(__msan_get_track_origins())) { 436353944Sdim Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); 437353944Sdim Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 438353944Sdim Printf("FATAL: Disabling ASLR is known to cause this error.\n"); 439353944Sdim Printf("FATAL: If running under GDB, try " 440353944Sdim "'set disable-randomization off'.\n"); 441353944Sdim DumpProcessMap(); 442353944Sdim Die(); 443353944Sdim } 444353944Sdim 445353944Sdim Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer); 446353944Sdim 447353944Sdim InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 448353944Sdim 449353944Sdim MsanTSDInit(MsanTSDDtor); 450353944Sdim 451353944Sdim MsanAllocatorInit(); 452353944Sdim 453353944Sdim MsanThread *main_thread = MsanThread::Create(nullptr, nullptr); 454353944Sdim SetCurrentThread(main_thread); 455353944Sdim main_thread->ThreadStart(); 456353944Sdim 457353944Sdim#if MSAN_CONTAINS_UBSAN 458353944Sdim __ubsan::InitAsPlugin(); 459353944Sdim#endif 460353944Sdim 461353944Sdim VPrintf(1, "MemorySanitizer init done\n"); 462353944Sdim 463353944Sdim msan_init_is_running = 0; 464353944Sdim msan_inited = 1; 465353944Sdim} 466353944Sdim 467353944Sdimvoid __msan_set_keep_going(int keep_going) { 468353944Sdim flags()->halt_on_error = !keep_going; 469353944Sdim} 470353944Sdim 471353944Sdimvoid __msan_set_expect_umr(int expect_umr) { 472353944Sdim if (expect_umr) { 473353944Sdim msan_expected_umr_found = 0; 474353944Sdim } else if (!msan_expected_umr_found) { 475353944Sdim GET_CALLER_PC_BP_SP; 476353944Sdim (void)sp; 477353944Sdim GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 478353944Sdim ReportExpectedUMRNotFound(&stack); 479353944Sdim Die(); 480353944Sdim } 481353944Sdim msan_expect_umr = expect_umr; 482353944Sdim} 483353944Sdim 484353944Sdimvoid __msan_print_shadow(const void *x, uptr size) { 485353944Sdim if (!MEM_IS_APP(x)) { 486353944Sdim Printf("Not a valid application address: %p\n", x); 487353944Sdim return; 488353944Sdim } 489353944Sdim 490353944Sdim DescribeMemoryRange(x, size); 491353944Sdim} 492353944Sdim 493353944Sdimvoid __msan_dump_shadow(const void *x, uptr size) { 494353944Sdim if (!MEM_IS_APP(x)) { 495353944Sdim Printf("Not a valid application address: %p\n", x); 496353944Sdim return; 497353944Sdim } 498353944Sdim 499353944Sdim unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); 500353944Sdim for (uptr i = 0; i < size; i++) 501353944Sdim Printf("%x%x ", s[i] >> 4, s[i] & 0xf); 502353944Sdim Printf("\n"); 503353944Sdim} 504353944Sdim 505353944Sdimsptr __msan_test_shadow(const void *x, uptr size) { 506353944Sdim if (!MEM_IS_APP(x)) return -1; 507353944Sdim unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x); 508353944Sdim for (uptr i = 0; i < size; ++i) 509353944Sdim if (s[i]) 510353944Sdim return i; 511353944Sdim return -1; 512353944Sdim} 513353944Sdim 514353944Sdimvoid __msan_check_mem_is_initialized(const void *x, uptr size) { 515353944Sdim if (!__msan::flags()->report_umrs) return; 516353944Sdim sptr offset = __msan_test_shadow(x, size); 517353944Sdim if (offset < 0) 518353944Sdim return; 519353944Sdim 520353944Sdim GET_CALLER_PC_BP_SP; 521353944Sdim (void)sp; 522353944Sdim ReportUMRInsideAddressRange(__func__, x, size, offset); 523353944Sdim __msan::PrintWarningWithOrigin(pc, bp, 524353944Sdim __msan_get_origin(((const char *)x) + offset)); 525353944Sdim if (__msan::flags()->halt_on_error) { 526353944Sdim Printf("Exiting\n"); 527353944Sdim Die(); 528353944Sdim } 529353944Sdim} 530353944Sdim 531353944Sdimint __msan_set_poison_in_malloc(int do_poison) { 532353944Sdim int old = flags()->poison_in_malloc; 533353944Sdim flags()->poison_in_malloc = do_poison; 534353944Sdim return old; 535353944Sdim} 536353944Sdim 537353944Sdimint __msan_has_dynamic_component() { return false; } 538353944Sdim 539353944SdimNOINLINE 540353944Sdimvoid __msan_clear_on_return() { 541353944Sdim __msan_param_tls[0] = 0; 542353944Sdim} 543353944Sdim 544353944Sdimvoid __msan_partial_poison(const void* data, void* shadow, uptr size) { 545353944Sdim internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); 546353944Sdim} 547353944Sdim 548353944Sdimvoid __msan_load_unpoisoned(const void *src, uptr size, void *dst) { 549353944Sdim internal_memcpy(dst, src, size); 550353944Sdim __msan_unpoison(dst, size); 551353944Sdim} 552353944Sdim 553353944Sdimvoid __msan_set_origin(const void *a, uptr size, u32 origin) { 554353944Sdim if (__msan_get_track_origins()) SetOrigin(a, size, origin); 555353944Sdim} 556353944Sdim 557353944Sdim// 'descr' is created at compile time and contains '----' in the beginning. 558353944Sdim// When we see descr for the first time we replace '----' with a uniq id 559353944Sdim// and set the origin to (id | (31-th bit)). 560353944Sdimvoid __msan_set_alloca_origin(void *a, uptr size, char *descr) { 561353944Sdim __msan_set_alloca_origin4(a, size, descr, 0); 562353944Sdim} 563353944Sdim 564353944Sdimvoid __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) { 565353944Sdim static const u32 dash = '-'; 566353944Sdim static const u32 first_timer = 567353944Sdim dash + (dash << 8) + (dash << 16) + (dash << 24); 568353944Sdim u32 *id_ptr = (u32*)descr; 569353944Sdim bool print = false; // internal_strstr(descr + 4, "AllocaTOTest") != 0; 570353944Sdim u32 id = *id_ptr; 571353944Sdim if (id == first_timer) { 572353944Sdim u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); 573353944Sdim CHECK_LT(idx, kNumStackOriginDescrs); 574353944Sdim StackOriginDescr[idx] = descr + 4; 575353944Sdim#if SANITIZER_PPC64V1 576353944Sdim // On PowerPC64 ELFv1, the address of a function actually points to a 577353944Sdim // three-doubleword data structure with the first field containing 578353944Sdim // the address of the function's code. 579353944Sdim if (pc) 580353944Sdim pc = *reinterpret_cast<uptr*>(pc); 581353944Sdim#endif 582353944Sdim StackOriginPC[idx] = pc; 583353944Sdim id = Origin::CreateStackOrigin(idx).raw_id(); 584353944Sdim *id_ptr = id; 585353944Sdim if (print) 586353944Sdim Printf("First time: idx=%d id=%d %s %p \n", idx, id, descr + 4, pc); 587353944Sdim } 588353944Sdim if (print) 589353944Sdim Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id); 590353944Sdim __msan_set_origin(a, size, id); 591353944Sdim} 592353944Sdim 593353944Sdimu32 __msan_chain_origin(u32 id) { 594353944Sdim GET_CALLER_PC_BP_SP; 595353944Sdim (void)sp; 596353944Sdim GET_STORE_STACK_TRACE_PC_BP(pc, bp); 597353944Sdim return ChainOrigin(id, &stack); 598353944Sdim} 599353944Sdim 600353944Sdimu32 __msan_get_origin(const void *a) { 601353944Sdim if (!__msan_get_track_origins()) return 0; 602353944Sdim uptr x = (uptr)a; 603353944Sdim uptr aligned = x & ~3ULL; 604353944Sdim uptr origin_ptr = MEM_TO_ORIGIN(aligned); 605353944Sdim return *(u32*)origin_ptr; 606353944Sdim} 607353944Sdim 608353944Sdimint __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id) { 609353944Sdim Origin o = Origin::FromRawId(this_id); 610353944Sdim while (o.raw_id() != prev_id && o.isChainedOrigin()) 611353944Sdim o = o.getNextChainedOrigin(nullptr); 612353944Sdim return o.raw_id() == prev_id; 613353944Sdim} 614353944Sdim 615353944Sdimu32 __msan_get_umr_origin() { 616353944Sdim return __msan_origin_tls; 617353944Sdim} 618353944Sdim 619353944Sdimu16 __sanitizer_unaligned_load16(const uu16 *p) { 620353944Sdim *(uu16 *)&__msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); 621353944Sdim if (__msan_get_track_origins()) 622353944Sdim __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 623353944Sdim return *p; 624353944Sdim} 625353944Sdimu32 __sanitizer_unaligned_load32(const uu32 *p) { 626353944Sdim *(uu32 *)&__msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); 627353944Sdim if (__msan_get_track_origins()) 628353944Sdim __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 629353944Sdim return *p; 630353944Sdim} 631353944Sdimu64 __sanitizer_unaligned_load64(const uu64 *p) { 632353944Sdim __msan_retval_tls[0] = *(uu64 *)MEM_TO_SHADOW((uptr)p); 633353944Sdim if (__msan_get_track_origins()) 634353944Sdim __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 635353944Sdim return *p; 636353944Sdim} 637353944Sdimvoid __sanitizer_unaligned_store16(uu16 *p, u16 x) { 638353944Sdim u16 s = *(uu16 *)&__msan_param_tls[1]; 639353944Sdim *(uu16 *)MEM_TO_SHADOW((uptr)p) = s; 640353944Sdim if (s && __msan_get_track_origins()) 641353944Sdim if (uu32 o = __msan_param_origin_tls[2]) 642353944Sdim SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 643353944Sdim *p = x; 644353944Sdim} 645353944Sdimvoid __sanitizer_unaligned_store32(uu32 *p, u32 x) { 646353944Sdim u32 s = *(uu32 *)&__msan_param_tls[1]; 647353944Sdim *(uu32 *)MEM_TO_SHADOW((uptr)p) = s; 648353944Sdim if (s && __msan_get_track_origins()) 649353944Sdim if (uu32 o = __msan_param_origin_tls[2]) 650353944Sdim SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 651353944Sdim *p = x; 652353944Sdim} 653353944Sdimvoid __sanitizer_unaligned_store64(uu64 *p, u64 x) { 654353944Sdim u64 s = __msan_param_tls[1]; 655353944Sdim *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; 656353944Sdim if (s && __msan_get_track_origins()) 657353944Sdim if (uu32 o = __msan_param_origin_tls[2]) 658353944Sdim SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 659353944Sdim *p = x; 660353944Sdim} 661353944Sdim 662353944Sdimvoid __msan_set_death_callback(void (*callback)(void)) { 663353944Sdim SetUserDieCallback(callback); 664353944Sdim} 665353944Sdim 666353944Sdim#if !SANITIZER_SUPPORTS_WEAK_HOOKS 667353944Sdimextern "C" { 668353944SdimSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 669353944Sdimconst char* __msan_default_options() { return ""; } 670353944Sdim} // extern "C" 671353944Sdim#endif 672353944Sdim 673353944Sdimextern "C" { 674353944SdimSANITIZER_INTERFACE_ATTRIBUTE 675353944Sdimvoid __sanitizer_print_stack_trace() { 676353944Sdim GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 677353944Sdim stack.Print(); 678353944Sdim} 679353944Sdim} // extern "C" 680