[PATCH] hugemmap36: Migrate the libhugetlbfs/testcases/truncate_above_4GB.c test

Pavithra <[email protected]>
Newsgroups gmane.linux.ltp
Message-ID <[email protected]>
Test for a bug where truncating hugepage files at offsets >= 4GB on
32-bit systems could incorrectly truncate lower pages due to a
misconversion of hugetlb_vmtruncate_list to a prio_tree.
This test verifies that:
- Pages below 4GB remain accessible after truncation at 4GB
- Pages at or above the truncation point correctly trigger SIGBUS

Signed-off-by: Pavithra <[email protected]>
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap36.c  | 160 ++++++++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 8ee0e6f82..5ea76df35 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -37,6 +37,7 @@ hugemmap31 hugemmap31
 hugemmap32 hugemmap32
 hugemmap34 hugemmap34
 hugemmap35 hugemmap35
+hugemmap36 hugemmap36
 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..1585b35bd 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/hugemmap36
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c
new file mode 100644
index 000000000..b48a34f59
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap36.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Copyright (c) 2026 Pavithra <[email protected]>
+ */
+
+/*\
+ * Test for a bug where truncating hugepage files at offsets >= 4GB on
+ * 32-bit systems could incorrectly truncate lower pages due to a
+ * misconversion of hugetlb_vmtruncate_list to a prio_tree.
+ *
+ * This test verifies that:
+ * - Pages below 4GB remain accessible after truncation at 4GB
+ * - Pages at or above the truncation point correctly trigger SIGBUS
+ *
+ * WARNING: The offsets and addresses used within are specifically
+ * calculated to trigger the bug as it existed. Don't mess with them
+ * unless you *really* know what you're doing.
+ *
+ * Requires root to mount hugetlbfs.
+ */
+
+#define _GNU_SOURCE
+#define FOURGIG ((off64_t)0x100000000ULL)
+#define MNTPOINT "hugetlbfs/"
+
+#include <signal.h>
+#include <setjmp.h>
+#include "hugetlb.h"
+
+static int page_size;
+static long hpage_size;
+static int fd = -1;
+static long long buggy_offset;
+static volatile int test_pass;
+static sigjmp_buf sig_escape;
+
+static void sigbus_handler_fail(int signum LTP_ATTRIBUTE_UNUSED,
+				siginfo_t *si LTP_ATTRIBUTE_UNUSED,
+				void *uc LTP_ATTRIBUTE_UNUSED)
+{
+	test_pass = -1;
+	siglongjmp(sig_escape, 17);
+}
+
+static void sigbus_handler_pass(int signum LTP_ATTRIBUTE_UNUSED,
+				siginfo_t *si LTP_ATTRIBUTE_UNUSED,
+				void *uc LTP_ATTRIBUTE_UNUSED)
+{
+	test_pass = 1;
+	siglongjmp(sig_escape, 17);
+}
+
+static void run_test(void)
+{
+	void *p, *q;
+	volatile unsigned int *pi, *qi;
+
+	struct sigaction sa_pass = {
+		.sa_sigaction = sigbus_handler_pass,
+		.sa_flags = SA_SIGINFO,
+	};
+
+	struct sigaction sa_fail = {
+		.sa_sigaction = sigbus_handler_fail,
+		.sa_flags = SA_SIGINFO,
+	};
+
+	test_pass = 0;
+
+	buggy_offset = FOURGIG / (hpage_size / page_size);
+	buggy_offset = (long long)PALIGN(buggy_offset, hpage_size);
+
+	/* First get arena of three hpages size, at file offset 4GB */
+	q = SAFE_MMAP(NULL, 3*hpage_size, PROT_READ|PROT_WRITE,
+		      MAP_PRIVATE, fd, FOURGIG);
+	qi = q;
+	/* Touch the high page */
+	*qi = 0;
+
+	/* This part of the test makes the problem more obvious, but
+	 * is not essential.  It can't be done on segmented powerpc, where
+	 * segment restrictions prohibit us from performing such a
+	 * mapping, so skip it there. Similarly, ia64's address space
+	 * restrictions prevent this.
+	 */
+#if (defined(__powerpc__) && defined(PPC_NO_SEGMENTS)) || \
+	!defined(__powerpc__) && !defined(__powerpc64__) && \
+	!defined(__ia64__)
+	/* Replace middle hpage by tinypage mapping to trigger
+	 * nr_ptes BUG
+	 */
+	p = SAFE_MMAP(q + hpage_size, hpage_size, PROT_READ|PROT_WRITE,
+		      MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
+	pi = p;
+	/* Touch one page to allocate its page table */
+	*pi = 0;
+#endif
+
+	/* Replace top hpage by hpage mapping at confusing file offset */
+	p = SAFE_MMAP(q + 2*hpage_size, hpage_size, PROT_READ|PROT_WRITE,
+		      MAP_FIXED|MAP_PRIVATE, fd, buggy_offset);
+	pi = p;
+	/* Touch the low page with something non-zero */
+	*pi = 1;
+
+	SAFE_FTRUNCATE(fd, FOURGIG);
+
+	SAFE_SIGACTION(SIGBUS, &sa_fail, NULL);
+	if (sigsetjmp(sig_escape, 1) == 0) {
+		if (*pi != 1) {
+			tst_res(TFAIL, "Data 1 has changed!");
+			goto cleanup;
+		}
+	} else if (test_pass == -1) {
+		tst_res(TFAIL, "Unexpected SIGBUS on low-offset page (kernel bug present)");
+		goto cleanup;
+	}
+
+	SAFE_SIGACTION(SIGBUS, &sa_pass, NULL);
+	if (sigsetjmp(sig_escape, 1) == 0) {
+		*qi;
+		tst_res(TFAIL, "Didn't SIGBUS on truncated page.");
+	}
+
+	if (test_pass)
+		tst_res(TPASS, "Expected SIGBUS");
+
+cleanup:
+	SAFE_MUNMAP(q, 3*hpage_size);
+}
+
+static void setup(void)
+{
+	page_size = getpagesize();
+	hpage_size = tst_get_hugepage_size();
+	fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+	if (hpage_size > FOURGIG)
+		tst_brk(TCONF, "Huge page size is too large!");
+}
+
+static void cleanup(void)
+{
+	if (fd != -1)
+		SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.tags = (struct tst_tag[]) {
+		{"linux-git", "856fc2950555"},
+		{}
+	},
+	.needs_root = 1,
+	.mntpoint = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.hugepages = {4, TST_NEEDS},
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+};
-- 
2.55.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.