1 //===-- sanitizer_procmaps_bsd.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Information about the process mappings 10 // (FreeBSD, OpenBSD and NetBSD-specific parts). 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_platform.h" 14 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD 15 #include "sanitizer_common.h" 16 #if SANITIZER_FREEBSD 17 #include "sanitizer_freebsd.h" 18 #endif 19 #include "sanitizer_procmaps.h" 20 21 // clang-format off 22 #include <sys/types.h> 23 #include <sys/sysctl.h> 24 // clang-format on 25 #include <unistd.h> 26 #if SANITIZER_FREEBSD 27 #include <sys/user.h> 28 #endif 29 30 #include <limits.h> 31 #if SANITIZER_OPENBSD 32 #define KVME_PROT_READ KVE_PROT_READ 33 #define KVME_PROT_WRITE KVE_PROT_WRITE 34 #define KVME_PROT_EXEC KVE_PROT_EXEC 35 #endif 36 37 // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode. 38 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) 39 #include <osreldate.h> 40 #if __FreeBSD_version <= 902001 // v9.2 41 #define kinfo_vmentry xkinfo_vmentry 42 #endif 43 #endif 44 45 namespace __sanitizer { 46 47 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { 48 const int Mib[] = { 49 #if SANITIZER_FREEBSD 50 CTL_KERN, 51 KERN_PROC, 52 KERN_PROC_VMMAP, 53 getpid() 54 #elif SANITIZER_OPENBSD 55 CTL_KERN, 56 KERN_PROC_VMMAP, 57 getpid() 58 #elif SANITIZER_NETBSD 59 CTL_VM, 60 VM_PROC, 61 VM_PROC_MAP, 62 getpid(), 63 sizeof(struct kinfo_vmentry) 64 #else 65 #error "not supported" 66 #endif 67 }; 68 69 uptr Size = 0; 70 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); 71 CHECK_EQ(Err, 0); 72 CHECK_GT(Size, 0); 73 74 #if !SANITIZER_OPENBSD 75 size_t MmapedSize = Size * 4 / 3; 76 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); 77 Size = MmapedSize; 78 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); 79 CHECK_EQ(Err, 0); 80 proc_maps->data = (char *)VmMap; 81 #else 82 size_t PageSize = GetPageSize(); 83 size_t MmapedSize = Size; 84 MmapedSize = ((MmapedSize - 1) / PageSize + 1) * PageSize; 85 char *Mem = (char *)MmapOrDie(MmapedSize, "ReadProcMaps()"); 86 Size = 2 * Size + 10 * sizeof(struct kinfo_vmentry); 87 if (Size > 0x10000) 88 Size = 0x10000; 89 Size = (Size / sizeof(struct kinfo_vmentry)) * sizeof(struct kinfo_vmentry); 90 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), Mem, &Size, NULL, 0); 91 CHECK_EQ(Err, 0); 92 MmapedSize = Size; 93 proc_maps->data = Mem; 94 #endif 95 96 proc_maps->mmaped_size = MmapedSize; 97 proc_maps->len = Size; 98 } 99 100 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { 101 CHECK(!Error()); // can not fail 102 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; 103 if (data_.current >= last) 104 return false; 105 const struct kinfo_vmentry *VmEntry = 106 (const struct kinfo_vmentry *)data_.current; 107 108 segment->start = (uptr)VmEntry->kve_start; 109 segment->end = (uptr)VmEntry->kve_end; 110 segment->offset = (uptr)VmEntry->kve_offset; 111 112 segment->protection = 0; 113 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) 114 segment->protection |= kProtectionRead; 115 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) 116 segment->protection |= kProtectionWrite; 117 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) 118 segment->protection |= kProtectionExecute; 119 120 #if !SANITIZER_OPENBSD 121 if (segment->filename != NULL && segment->filename_size > 0) { 122 internal_snprintf(segment->filename, 123 Min(segment->filename_size, (uptr)PATH_MAX), "%s", 124 VmEntry->kve_path); 125 } 126 #endif 127 128 #if SANITIZER_FREEBSD 129 data_.current += VmEntry->kve_structsize; 130 #else 131 data_.current += sizeof(*VmEntry); 132 #endif 133 134 return true; 135 } 136 137 } // namespace __sanitizer 138 139 #endif 140