From fa33606fe951575be823f2aa9b9211fac63d309c Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 12 Jan 2024 06:31:33 +1300 Subject: [PATCH] Allow failed MADV_REMOVEs when the only target mappings (if any) are MAP_PRIVATE tcmalloc does this and it's perfectly fine because such MADV_REMOVEs have no effect. --- CMakeLists.txt | 3 ++- src/record_syscall.cc | 17 ++++++++++++++--- src/test/madvise_remove.c | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/test/madvise_remove.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ba4f101cff..a11da5e55ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1076,9 +1076,10 @@ set(BASIC_TESTS legacy_ugid x86/lsl madvise - madvise_free madvise_dontneed_private + madvise_free madvise_misc + madvise_remove madvise_wipeonfork map_fixed map_shared_syscall diff --git a/src/record_syscall.cc b/src/record_syscall.cc index 0b9c1c006a1..fccc882e16d 100644 --- a/src/record_syscall.cc +++ b/src/record_syscall.cc @@ -6488,10 +6488,21 @@ static void record_madvise(RecordTask* t) { ranges.insert(ranges.end(), pages_present.begin(), pages_present.end()); } break; - case MADV_REMOVE: - // We don't handle this yet... - ASSERT(t, false) << "Possibly-partial MADV_REMOVEs not handled yet"; + case MADV_REMOVE: { + for (const auto& m : t->vm()->maps_containing_or_after(start)) { + if (m.map.start() >= end) { + break; + } + if (m.map.flags() & MAP_PRIVATE) { + // Private mappings fail cleanly with MADV_REMOVE so we + // don't need to worry about any effects on them. + continue; + } + // We don't handle this yet... + ASSERT(t, false) << "Possibly-partial MADV_REMOVEs not handled yet"; + } break; + } default: break; } diff --git a/src/test/madvise_remove.c b/src/test/madvise_remove.c new file mode 100644 index 00000000000..0cf11a5fbdb --- /dev/null +++ b/src/test/madvise_remove.c @@ -0,0 +1,18 @@ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include "util.h" + +int main(void) { + size_t page_size = sysconf(_SC_PAGESIZE); + char* p = + mmap(NULL, page_size*3, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + test_assert(p != MAP_FAILED); + test_assert(0 == munmap(p + page_size, page_size)); + + test_assert(-1 == madvise(p, page_size, MADV_REMOVE)); + test_assert(errno == EINVAL); + + atomic_puts("EXIT-SUCCESS"); + + return 0; +}