All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH] hugemmap/hugemmap37: migrated task-size-overrun.c from libhugetlbfs
@ 2026-07-17 11:26 Pavithra
  2026-08-04 16:14 ` Cyril Hrubis
  0 siblings, 1 reply; 2+ messages in thread
From: Pavithra @ 2026-07-17 11:26 UTC (permalink / raw)
  To: ltp; +Cc: pavrampu

This test verifies that the kernel correctly prevents mmap operations
from creating mappings that straddle the TASK_SIZE boundary when using
hugepages.

Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap37.c  | 173 ++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 8ee0e6f82..d54f5266d 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -37,6 +37,7 @@ hugemmap31 hugemmap31
 hugemmap32 hugemmap32
 hugemmap34 hugemmap34
 hugemmap35 hugemmap35
+hugemmap37 hugemmap37
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 0e59035df..b2752aec9 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -37,6 +37,7 @@
 /hugetlb/hugemmap/hugemmap32
 /hugetlb/hugemmap/hugemmap34
 /hugetlb/hugemmap/hugemmap35
+/hugetlb/hugemmap/hugemmap37
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
new file mode 100644
index 000000000..c15b4ad33
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*
+ * Origin: https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/task-size-overrun.c
+ */
+
+/*\
+ * Test that mmap correctly rejects hugepage mappings that straddle the
+ * TASK_SIZE boundary. Both MAP_FIXED (which must fail) and non-MAP_FIXED
+ * (which must either fail or relocate away from the boundary) cases are
+ * verified. A buggy kernel would allow such a mapping to succeed,
+ * violating address space limits.
+ *
+ * Requires root to mount hugetlbfs.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "hugetlb.h"
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+#include "tst_safe_macros.h"
+
+#define MAPS_BUF_SZ 4096
+#define MNTPOINT "hugetlbfs/"
+
+static long hpage_size;
+static int fd = -1;
+
+static unsigned long find_last_mapped(void)
+{
+	char line[MAPS_BUF_SZ];
+	char last[MAPS_BUF_SZ];
+	unsigned long start, end, off, ino;
+	FILE *f;
+	int found = 0;
+
+	f = SAFE_FOPEN("/proc/self/maps", "r");
+
+	/* Read all lines and save the last non-special mapping */
+	while (fgets(line, MAPS_BUF_SZ, f)) {
+		/* Skip special mappings like [vsyscall], [vdso], [vvar] */
+		if (strstr(line, "[vsyscall]") || strstr(line, "[vdso]") ||
+		    strstr(line, "[vvar]"))
+			continue;
+
+		strncpy(last, line, MAPS_BUF_SZ - 1);
+		last[MAPS_BUF_SZ - 1] = '\0';
+		found = 1;
+	}
+
+	SAFE_FCLOSE(f);
+
+	if (!found)
+		tst_brk(TBROK, "Could not find any valid mapping in /proc/self/maps");
+
+	tst_res(TINFO, "Last map: %s", last);
+	if (sscanf(last, "%lx-%lx %*s %lx %*s %ld", &start, &end, &off, &ino) != 4)
+		tst_brk(TBROK, "Failed to parse /proc/self/maps line");
+
+	tst_res(TINFO, "Last map: at 0x%lx-0x%lx", start, end);
+	return end;
+}
+
+static unsigned long find_task_size(void)
+{
+	unsigned long low, high;
+	void *p;
+	int page_size = getpagesize();
+
+	low = find_last_mapped();
+	if (!low || ((low % page_size) != 0))
+		tst_brk(TBROK, "Bogus stack end address, 0x%lx!?", low);
+
+	/* Convert to page frame number */
+	low = low / page_size;
+
+	/*
+	 * Set high to maximum possible address space
+	 * For 64-bit: (2^64 - 1) / page_size
+	 * We use -1UL which gives us the maximum unsigned long value
+	 */
+	high = (-1UL) / page_size;
+
+	tst_res(TINFO, "Binary searching for task size PFNs 0x%lx..0x%lx", low, high);
+
+	while (high > low + 1) {
+		unsigned long pfn = (low + high) / 2;
+		unsigned long addr = pfn * page_size;
+
+		p = mmap((void *)addr, page_size, PROT_READ,
+			   MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+		if (p == MAP_FAILED) {
+			tst_res(TINFO | TERRNO, "Map failed at 0x%lx", addr);
+			high = pfn;
+		} else {
+			tst_res(TINFO, "Map succeeded at 0x%lx", addr);
+			SAFE_MUNMAP(p, page_size);
+			low = pfn;
+		}
+	}
+
+	return low * page_size;
+}
+
+static void run_test(void)
+{
+	void *p;
+	unsigned long task_size;
+	unsigned long straddle_addr;
+
+	task_size = find_task_size();
+	tst_res(TINFO, "TASK_SIZE = 0x%lx", task_size);
+
+	straddle_addr = task_size - hpage_size;
+	straddle_addr = LTP_ALIGN(straddle_addr, hpage_size);
+
+	tst_res(TINFO, "Mapping without MAP_FIXED at %lx...", straddle_addr);
+	errno = 0;
+	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
+		 MAP_SHARED, fd, 0);
+	if (p == (void *)straddle_addr) {
+		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
+		SAFE_MUNMAP(p, 2*hpage_size);
+	} else if (p != MAP_FAILED) {
+		tst_res(TPASS, "mmap without MAP_FIXED correctly avoided TASK_SIZE boundary");
+		SAFE_MUNMAP(p, 2*hpage_size);
+	} else {
+		tst_res(TPASS, "mmap without MAP_FIXED correctly failed");
+	}
+
+	tst_res(TINFO, "Mapping with MAP_FIXED at %lx...", straddle_addr);
+	errno = 0;
+	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
+		 MAP_SHARED|MAP_FIXED, fd, 0);
+	if (p != MAP_FAILED) {
+		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
+		SAFE_MUNMAP(p, 2*hpage_size);
+	} else {
+		tst_res(TPASS, "mmap with MAP_FIXED correctly failed");
+	}
+}
+
+static void setup(void)
+{
+	hpage_size = tst_get_hugepage_size();
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+	.hugepages = {3, TST_NEEDS},
+};
-- 
2.55.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [LTP] [PATCH] hugemmap/hugemmap37: migrated task-size-overrun.c from libhugetlbfs
  2026-07-17 11:26 [LTP] [PATCH] hugemmap/hugemmap37: migrated task-size-overrun.c from libhugetlbfs Pavithra
@ 2026-08-04 16:14 ` Cyril Hrubis
  0 siblings, 0 replies; 2+ messages in thread
From: Cyril Hrubis @ 2026-08-04 16:14 UTC (permalink / raw)
  To: Pavithra; +Cc: ltp

Hi!
Pushed with following diff, thanks.

Changes:

- use TDEBUG for the verbose messages
- use TST_EXP_* macros, on Linux mmap() without MAP_FIXED ignores the
  address hint and always succeeds
- moved the code that locates task_size into the test setup() so that
  it's called exactly once on test with -i 10

diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
index c15b4ad33..addd717e3 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap37.c
@@ -34,6 +34,7 @@
 #define MNTPOINT "hugetlbfs/"
 
 static long hpage_size;
+static unsigned long task_size;
 static int fd = -1;
 
 static unsigned long find_last_mapped(void)
@@ -100,10 +101,10 @@ static unsigned long find_task_size(void)
 		p = mmap((void *)addr, page_size, PROT_READ,
 			   MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
 		if (p == MAP_FAILED) {
-			tst_res(TINFO | TERRNO, "Map failed at 0x%lx", addr);
+			tst_res(TDEBUG | TERRNO, "Map failed at 0x%lx", addr);
 			high = pfn;
 		} else {
-			tst_res(TINFO, "Map succeeded at 0x%lx", addr);
+			tst_res(TDEBUG, "Map succeeded at 0x%lx", addr);
 			SAFE_MUNMAP(p, page_size);
 			low = pfn;
 		}
@@ -114,45 +115,35 @@ static unsigned long find_task_size(void)
 
 static void run_test(void)
 {
-	void *p;
-	unsigned long task_size;
 	unsigned long straddle_addr;
 
-	task_size = find_task_size();
-	tst_res(TINFO, "TASK_SIZE = 0x%lx", task_size);
-
 	straddle_addr = task_size - hpage_size;
 	straddle_addr = LTP_ALIGN(straddle_addr, hpage_size);
 
 	tst_res(TINFO, "Mapping without MAP_FIXED at %lx...", straddle_addr);
-	errno = 0;
-	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
-		 MAP_SHARED, fd, 0);
-	if (p == (void *)straddle_addr) {
-		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else if (p != MAP_FAILED) {
-		tst_res(TPASS, "mmap without MAP_FIXED correctly avoided TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else {
-		tst_res(TPASS, "mmap without MAP_FIXED correctly failed");
-	}
+
+	TST_EXP_PASS_PTR_VOID(mmap((void *)straddle_addr, 2*hpage_size,
+	                      PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0));
+
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, 2*hpage_size);
 
 	tst_res(TINFO, "Mapping with MAP_FIXED at %lx...", straddle_addr);
-	errno = 0;
-	p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE,
-		 MAP_SHARED|MAP_FIXED, fd, 0);
-	if (p != MAP_FAILED) {
-		tst_res(TFAIL, "Apparently succeeded in mapping across TASK_SIZE boundary");
-		SAFE_MUNMAP(p, 2*hpage_size);
-	} else {
-		tst_res(TPASS, "mmap with MAP_FIXED correctly failed");
-	}
+
+	TST_EXP_FAIL_PTR_VOID(mmap((void *)straddle_addr, 2*hpage_size,
+	                      PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0), ENOMEM);
+
+	if (TST_RET_PTR != MAP_FAILED)
+		SAFE_MUNMAP(TST_RET_PTR, 2*hpage_size);
 }
 
 static void setup(void)
 {
 	hpage_size = tst_get_hugepage_size();
+
+	task_size = find_task_size();
+	tst_res(TINFO, "TASK_SIZE = 0x%lx", task_size);
+
 	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
 }
 



-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-04 16:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17 11:26 [LTP] [PATCH] hugemmap/hugemmap37: migrated task-size-overrun.c from libhugetlbfs Pavithra
2026-08-04 16:14 ` Cyril Hrubis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.