diff options
-rw-r--r-- | lib/lsan/lsan_common_mac.cc | 21 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 12 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_procmaps_mac.cc | 9 |
4 files changed, 40 insertions, 7 deletions
diff --git a/lib/lsan/lsan_common_mac.cc b/lib/lsan/lsan_common_mac.cc index ade94340a..ac27c7af6 100644 --- a/lib/lsan/lsan_common_mac.cc +++ b/lib/lsan/lsan_common_mac.cc @@ -92,8 +92,25 @@ LoadedModule *GetLinker() { return nullptr; } // required on Darwin. void InitializePlatformSpecificModules() {} +// Sections which can't contain contain global pointers. This list errs on the +// side of caution to avoid false positives, at the expense of performance. +// +// Other potentially safe sections include: +// __all_image_info, __crash_info, __const, __got, __interpose, __objc_msg_break +// +// Sections which definitely cannot be included here are: +// __objc_data, __objc_const, __data, __bss, __common, __thread_data, +// __thread_bss, __thread_vars, __objc_opt_rw, __objc_opt_ptrs +static const char *kSkippedSecNames[] = { + "__cfstring", "__la_symbol_ptr", "__mod_init_func", + "__mod_term_func", "__nl_symbol_ptr", "__objc_classlist", + "__objc_classrefs", "__objc_imageinfo", "__objc_nlclslist", + "__objc_protolist", "__objc_selrefs", "__objc_superrefs"}; + // Scans global variables for heap pointers. void ProcessGlobalRegions(Frontier *frontier) { + for (auto name : kSkippedSecNames) CHECK(ARRAY_SIZE(name) < kMaxSegName); + MemoryMappingLayout memory_mapping(false); InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128); memory_mapping.DumpListOfModules(&modules); @@ -107,6 +124,10 @@ void ProcessGlobalRegions(Frontier *frontier) { // Sections storing global variables are writable and non-executable if (range.executable || !range.writable) continue; + for (auto name : kSkippedSecNames) { + if (!internal_strcmp(range.name, name)) continue; + } + ScanGlobalRange(range.beg, range.end, frontier); } } diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 8d51e1ed1..87e04240a 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -183,9 +183,10 @@ void LoadedModule::clear() { } void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable, - bool writable) { + bool writable, const char *name) { void *mem = InternalAlloc(sizeof(AddressRange)); - AddressRange *r = new(mem) AddressRange(beg, end, executable, writable); + AddressRange *r = + new(mem) AddressRange(beg, end, executable, writable, name); ranges_.push_back(r); if (executable && end > max_executable_address_) max_executable_address_ = end; diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 9c801f151..9e65639b9 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -624,6 +624,7 @@ inline const char *ModuleArchToString(ModuleArch arch) { } const uptr kModuleUUIDSize = 16; +const uptr kMaxSegName = 16; // Represents a binary loaded into virtual memory (e.g. this can be an // executable or a shared object). @@ -642,7 +643,8 @@ class LoadedModule { void set(const char *module_name, uptr base_address, ModuleArch arch, u8 uuid[kModuleUUIDSize], bool instrumented); void clear(); - void addAddressRange(uptr beg, uptr end, bool executable, bool writable); + void addAddressRange(uptr beg, uptr end, bool executable, bool writable, + const char *name = nullptr); bool containsAddress(uptr address) const; const char *full_name() const { return full_name_; } @@ -658,13 +660,17 @@ class LoadedModule { uptr end; bool executable; bool writable; + char name[kMaxSegName]; - AddressRange(uptr beg, uptr end, bool executable, bool writable) + AddressRange(uptr beg, uptr end, bool executable, bool writable, + const char *name) : next(nullptr), beg(beg), end(end), executable(executable), - writable(writable) {} + writable(writable) { + internal_strncpy(this->name, (name ? name : ""), ARRAY_SIZE(this->name)); + } }; const IntrusiveList<AddressRange> &ranges() const { return ranges_; } diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc index 4b26a1f2c..106294cac 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -38,6 +38,7 @@ namespace __sanitizer { // Contains information used to iterate through sections. struct MemoryMappedSegmentData { + char name[kMaxSegName]; uptr nsects; char *current_load_cmd_addr; u32 lc_type; @@ -53,7 +54,8 @@ static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data, uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr; uptr sec_end = sec_start + sc->size; - module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable); + module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable, + sc->sectname); } void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) { @@ -63,7 +65,8 @@ void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) { // it will confuse libignore, and because the extra granularity // of information is not needed by any sanitizers. if (!data_ || !data_->nsects || IsExecutable()) { - module->addAddressRange(start, end, IsExecutable(), IsWritable()); + module->addAddressRange(start, end, IsExecutable(), IsWritable(), + data_ ? data_->name : nullptr); return; } @@ -212,6 +215,8 @@ bool MemoryMappingLayout::NextSegmentLoad(MemoryMappedSegment *segment) { segment->data_->lc_type = kLCSegment; segment->data_->base_virt_addr = base_virt_addr; segment->data_->addr_mask = addr_mask; + internal_strncpy(segment->data_->name, sc->segname, + ARRAY_SIZE(segment->data_->name)); } // Return the initial protection. |