diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -197,16 +197,16 @@ } void *res = real_mmap(addr, length, prot, flags, fd, offset); if (res != (void *)-1) { - void *end_res = (char *)res + (rounded_length - 1); - if (!MemIsApp(reinterpret_cast(res)) || - !MemIsApp(reinterpret_cast(end_res))) { + uptr beg = reinterpret_cast(res); + DCHECK(IsAligned(beg, GetPageSize())); + if (!MemIsApp(beg) || !MemIsApp(beg + rounded_length - 1)) { // Application has attempted to map more memory than is supported by // HWASan. Act as if we ran out of memory. internal_munmap(res, length); errno = errno_ENOMEM; return (void *)-1; } - __hwasan::TagMemory(reinterpret_cast(addr), length, 0); + __hwasan::TagMemoryAligned(beg, rounded_length, 0); } return res; @@ -214,7 +214,17 @@ template static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) { - __hwasan::TagMemory(reinterpret_cast(addr), length, 0); + // We should not tag if munmap fail, but it's to late to tag after + // real_munmap, as the pages could be mmaped by another thread. + uptr beg = reinterpret_cast(addr); + SIZE_T rounded_length = RoundUpTo(length, GetPageSize()); + // Protect from unmapping the shadow. + if (!IsAligned(beg, GetPageSize()) || !MemIsApp(beg) || + !MemIsApp(beg + rounded_length - 1)) { + errno = errno_EINVAL; + return -1; + } + __hwasan::TagMemoryAligned(beg, rounded_length, 0); return real_munmap(addr, length); } diff --git a/compiler-rt/test/hwasan/TestCases/munmap.c b/compiler-rt/test/hwasan/TestCases/munmap.c --- a/compiler-rt/test/hwasan/TestCases/munmap.c +++ b/compiler-rt/test/hwasan/TestCases/munmap.c @@ -1,5 +1,6 @@ // RUN: %clang_hwasan %s -o %t -// RUN: %run %t 2>&1 +// RUN: %run %t 1 2>&1 +// RUN: %run %t 2 2>&1 // REQUIRES: pointer-tagging @@ -7,9 +8,11 @@ #include #include #include +#include int main(int argc, char **argv) { - const int kSize = 4096; + const size_t kPS = sysconf(_SC_PAGESIZE); + const int kSize = kPS / atoi(argv[1]); const int kTag = 47; // Get any mmaped pointer. @@ -27,26 +30,36 @@ } // Manually tag the pointer and the memory. - __hwasan_tag_memory(r, kTag, kSize); + __hwasan_tag_memory(r, kTag, kPS); int *p1 = __hwasan_tag_pointer(r, kTag); // Check that the pointer and the tag match. - if (__hwasan_test_shadow(p1, kSize) != -1) { + if (__hwasan_test_shadow(p1, kPS) != -1) { fprintf(stderr, "Failed to tag.\n"); abort(); } + if (munmap((char *)r + 1, kSize) == 0) { + perror("munmap should fail: "); + abort(); + } + + if (__hwasan_test_shadow(p1, kPS) != -1) { + fprintf(stderr, "Still must be tagged.\n"); + abort(); + } + // First munmmap and then mmap the same pointer using MAP_FIXED. if (munmap((char *)r, kSize) != 0) { perror("Failed to unmap: "); abort(); } - if (__hwasan_test_shadow(r, kSize) != -1) { + if (__hwasan_test_shadow(r, kPS) != -1) { fprintf(stderr, "Shadow memory was not cleaned by munmap.\n"); abort(); } - __hwasan_tag_memory(r, kTag, kSize); + __hwasan_tag_memory(r, kTag, kPS); int *p2 = (int *)mmap(r, kSize, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); @@ -57,7 +70,7 @@ } // Make sure we can access the shadow with an untagged pointer. - if (__hwasan_test_shadow(p2, kSize) != -1) { + if (__hwasan_test_shadow(p2, kPS) != -1) { fprintf(stderr, "Shadow memory was not cleaned by mmap.\n"); abort(); }