Hi Alex,

On 9/3/26 16:27, Alex Bennée wrote:
Per madvise(2) and the Linux kernel implementation (madvise_walk_vmas),
madvise() must validate that the requested range is currently mapped
and return -ENOMEM if any page in the range is unmapped.

Add a page_check_range(start, len, PAGE_VALID) check for valid advice
values before proceeding with the advice actions. In addition, extend the
tcg multiarch test linux-madvise.c to test this behaviour.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4382
AI-used-for: importing and validating test case
Signed-off-by: Alex Bennée <[email protected]>

---
NOTE
   - again testing the minimal agents which did stop and say:

*(Note: Per user policy, git commits are never executed automatically by the 
agent. Please review the diff with `git diff` and commit the changes if you are 
satisfied.)*

   but non-the-less imported the test and wrote a crap patch which I
   have re-done dropping a load of unneeded verbosity.


Did you test this patch?
If yes, did it work for you?
I'm asking, because I tried the testcase from the bug report, and
in qemu I still get 0 (success).

Helge

---
  linux-user/mmap.c                         | 12 ++++++++++++
  tests/tcg/multiarch/linux/linux-madvise.c | 20 ++++++++++++++++++++
  2 files changed, 32 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index cc0c2ee6c27..4066072ff45 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1307,6 +1307,16 @@ abi_long target_madvise(abi_ulong start, abi_ulong 
len_in, int advice)
       * though.
       */
      mmap_lock();
+
+    /*
+     * Whatever advice if the pages are not currently mapped, or are
+     * outside the address space of the process.
+     */
+    if (!page_check_range(start, len, PAGE_VALID)) {
+        ret = -TARGET_ENOMEM;
+        goto unlock;
+    }
+
      switch (advice) {
      case MADV_NORMAL:
      case MADV_RANDOM:
@@ -1358,6 +1368,8 @@ abi_long target_madvise(abi_ulong start, abi_ulong 
len_in, int advice)
          ret = -EINVAL; /* not yet known advise */
          break;
      }
+
+ unlock:
      mmap_unlock();
return ret;
diff --git a/tests/tcg/multiarch/linux/linux-madvise.c 
b/tests/tcg/multiarch/linux/linux-madvise.c
index 539fb3b7726..ebb9666c919 100644
--- a/tests/tcg/multiarch/linux/linux-madvise.c
+++ b/tests/tcg/multiarch/linux/linux-madvise.c
@@ -1,4 +1,5 @@
  #include <assert.h>
+#include <errno.h>
  #include <stdlib.h>
  #include <sys/mman.h>
  #include <unistd.h>
@@ -63,10 +64,29 @@ static void test_file(void)
      assert(ret == 0);
  }
+static void test_unmapped(void)
+{
+    int pagesize = getpagesize();
+    void *page;
+    int ret;
+
+    page = mmap(NULL, pagesize, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+    assert(page != MAP_FAILED);
+
+    ret = munmap(page, pagesize);
+    assert(ret == 0);
+
+    errno = 0;
+    ret = madvise(page, pagesize, MADV_NORMAL);
+    assert(ret == -1);
+    assert(errno == ENOMEM);
+}
+
  int main(void)
  {
      test_anonymous();
      test_file();
+    test_unmapped();
return EXIT_SUCCESS;
  }


Reply via email to