[LTP] [PATCH] syscalls/munmap03: Fix addresses passed to munmap

Wenyuan Li 2063309626@qq.com
Sat Oct 10 04:34:24 CEST 2026


munmap03 keeps the addresses to be passed to munmap() in a table of
char **, but passes tc->addr (the address of the pointer itself) instead
of the pointed-to value. The length is dereferenced correctly, so the
mismatch only shows up at the syscall boundary where void * is accepted.

The third entry is wrong as well: "&map_addr + 1" is one pointer-width
past the map_addr object, not "map_addr + 1", i.e. not the mapping start
plus one byte.

As a consequence none of the three documented scenarios reliably
exercises the rejection reason it describes. On x86-64 with 4K pages the
addresses involved are not page-aligned, so all three requests fail with
EINVAL from the page-alignment check and the test reports TPASS while the
"len == 0" and "range outside the address space" conditions are never
reached.

Fix the table to reference properly constructed values and dereference
the address in the call:

  - out of range: use the real page-aligned mapping start with a length
    that cannot fit into the address space (SIZE_MAX), rejected by the
    "len > TASK_SIZE - start" check. This replaces the RLIMIT_DATA based
    pointer: RLIMIT_DATA is a resource limit, not a bound of the user
    address space, and rlim_max (RLIM_INFINITY) is not page-aligned
    either, so it could not reach the intended check.
  - len == 0: keep the zero length but pass the actual page-aligned
    mmap() return value, so the request reaches the end == start check.
  - unaligned: pass an explicitly constructed map_addr + 1.

The number of scenarios is unchanged.

Tested on x86-64, 4096-byte pages, kernel 6.8.0:
  - munmap03        : 3 TPASS  (strace shows three distinct inputs)
  - munmap03 -i 20  : 60 TPASS

Fixes: 0c7346cb097440902568856527be7162f5950497 ("syscalls: munmap03: Convert to new API")
Signed-off-by: Wenyuan Li <2063309626@qq.com>
---
 testcases/kernel/syscalls/munmap/munmap03.c | 22 +++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/syscalls/munmap/munmap03.c b/testcases/kernel/syscalls/munmap/munmap03.c
index be607e7..5de83fd 100644
--- a/testcases/kernel/syscalls/munmap/munmap03.c
+++ b/testcases/kernel/syscalls/munmap/munmap03.c
@@ -19,38 +19,44 @@
 
 static size_t page_sz;
 static char *map_addr;
-static char *map_addr_out;
+static char *unaligned_addr;
 static size_t map_len;
 static size_t map_len_zero;
+static size_t map_len_too_large;
 
 static struct tcase {
 	int exp_errno;
 	char **addr;
 	size_t *len;
 } tcases[] = {
-	{ EINVAL, &map_addr_out, &map_len },
+	{ EINVAL, &map_addr, &map_len_too_large },
 	{ EINVAL, &map_addr, &map_len_zero },
-	{ EINVAL, &map_addr + 1, &map_len },
+	{ EINVAL, &unaligned_addr, &map_len },
 };
 
 static void run(unsigned int i)
 {
 	struct tcase *tc = &tcases[i];
 
-	TST_EXP_FAIL(munmap(tc->addr, *tc->len), tc->exp_errno);
+	TST_EXP_FAIL(munmap(*tc->addr, *tc->len), tc->exp_errno);
 }
 
 static void setup(void)
 {
-	struct rlimit brkval;
-
 	page_sz = SAFE_SYSCONF(_SC_PAGESIZE);
 	map_len = page_sz * 2;
 	map_addr = SAFE_MMAP(NULL, map_len, PROT_READ | PROT_WRITE,
 			     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	unaligned_addr = map_addr + 1;
 
-	SAFE_GETRLIMIT(RLIMIT_DATA, &brkval);
-	map_addr_out = (char *)brkval.rlim_max;
+	/*
+	 * The range [map_addr, map_addr + map_len_too_large) can never fit
+	 * into the address space of a process, so munmap() has to reject it
+	 * with EINVAL. A length of SIZE_MAX is used instead of a pointer
+	 * derived from RLIMIT_DATA, which is a resource limit and not a
+	 * valid upper bound of the user address space.
+	 */
+	map_len_too_large = SIZE_MAX;
 }
 
 static void cleanup(void)
-- 
2.43.0



More information about the ltp mailing list