[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