[LTP] [PATCH 12/13] mem: vma03: Rewrite to the new test library

Cyril Hrubis chrubis@suse.cz
Wed Jun 24 11:18:59 CEST 2026


We also drop the __NR_mmap2 ifdef because the lapi/syscalls.h defines
the fallbacks to -1 when a syscall is not implemented on an achitecture,
so the macro is always defined.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 testcases/kernel/mem/vma/vma03.c | 189 ++++++++++++-------------------
 1 file changed, 73 insertions(+), 116 deletions(-)

diff --git a/testcases/kernel/mem/vma/vma03.c b/testcases/kernel/mem/vma/vma03.c
index da1f5be99..7694e7e9a 100644
--- a/testcases/kernel/mem/vma/vma03.c
+++ b/testcases/kernel/mem/vma/vma03.c
@@ -1,149 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2026 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * CVE-2011-2496 regression test.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
+ * Verify that :manpage:`mremap(2)` correctly rejects an expansion that
+ * would cause the page-offset (pgoff) inside the mapping to wrap around
+ * due to overflow.
  *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * The normal :manpage:`mmap(2)` paths all prevent creating a mapping
+ * whose pgoff could wrap, but an expanding :manpage:`mremap(2)` was
+ * able to take a valid mapping and grow it past the wrap boundary.
  *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like.  Any license provided herein, whether
- * implied or otherwise, applies only to this software file.  Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
+ * The test uses :manpage:`mmap2(2)` to create a file-backed mapping at
+ * a pgoff near ``ULONG_MAX``, then attempts to double its size with
+ * :manpage:`mremap(2)`. The kernel must reject this with ``EINVAL``.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-/*
- * This is a reproducer for CVE-2011-2496.
- *
- * The normal mmap paths all avoid creating a mapping where the pgoff
- * inside the mapping could wrap around due to overflow.  However, an
- * expanding mremap() can take such a non-wrapping mapping and make it
- * bigger and cause a wrapping condition. There is also another case
- * where we expand mappings hiding in plain sight: the automatic stack
- * expansion.
- *
- * This program tries to remap a mapping with a new size that would
- * wrap pgoff. Notice that it only works on 32-bit arch for now.
+ * This test only runs on 32-bit systems with a 32-bit kernel because
+ * the overflow requires a 32-bit ``unsigned long`` address space.
  */
 
 #define _GNU_SOURCE
-#include "config.h"
-#include <sys/types.h>
 #include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <errno.h>
-#include <fcntl.h>
 #include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
 
-#include "test.h"
-#include "tso_safe_macros.h"
-#include "tst_kernel.h"
+#include "tst_test.h"
 #include "lapi/abisize.h"
+#include "lapi/syscalls.h"
 
-char *TCID = "vma03";
-int TST_TOTAL = 1;
-
-#ifdef __NR_mmap2
 #define TESTFILE "testfile"
 
+static int fd = -1;
 static size_t pgsz;
-static int fd;
+static void *map = MAP_FAILED;
 
-static void *mmap2(void *addr, size_t length, int prot,
-		   int flags, int fd, off_t pgoffset);
-static void setup(void);
-static void cleanup(void);
-
-int main(int argc, char *argv[])
+static void setup(void)
 {
-	int lc;
-	void *map, *remap;
-	off_t pgoff;
-
-	if (TST_ABI != 32 || tst_kernel_bits() != 32) {
-		tst_brkm(TCONF, NULL,
-			 "test is designed for 32-bit system only.");
-	}
+	if (TST_ABI != 32 || tst_kernel_bits() != 32)
+		tst_brk(TCONF, "test is designed for 32-bit systems only");
 
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	pgsz = sysconf(_SC_PAGE_SIZE);
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-
-		fd = SAFE_OPEN(NULL, TESTFILE, O_RDWR);
-
-		/*
-		 * The pgoff is counted in 4K units and must be page-aligned,
-		 * hence we must align it down to page_size/4096 in a case that
-		 * the system has page_size > 4K.
-		 */
-		pgoff = (ULONG_MAX - 1)&(~((pgsz-1)>>12));
-		map = mmap2(NULL, pgsz, PROT_READ | PROT_WRITE, MAP_PRIVATE,
-			    fd, pgoff);
-		if (map == MAP_FAILED)
-			tst_brkm(TBROK | TERRNO, cleanup, "mmap2");
-
-		remap = mremap(map, pgsz, 2 * pgsz, 0);
-		if (remap == MAP_FAILED) {
-			if (errno == EINVAL)
-				tst_resm(TPASS, "mremap failed as expected.");
-			else
-				tst_resm(TFAIL | TERRNO, "mremap");
-			munmap(map, pgsz);
-		} else {
-			tst_resm(TFAIL, "mremap succeeded unexpectedly.");
-			munmap(remap, 2 * pgsz);
-		}
-
-		close(fd);
-	}
+	pgsz = getpagesize();
 
-	cleanup();
-	tst_exit();
+	SAFE_CREAT(TESTFILE, 0644);
 }
 
-static void *mmap2(void *addr, size_t length, int prot,
-		   int flags, int fd, off_t pgoffset)
+static void run(void)
 {
-	return (void *)syscall(SYS_mmap2, addr, length, prot,
-			       flags, fd, pgoffset);
-}
+	/*
+	 * pgoff is counted in 4K units, must be page-aligned, so
+	 * align down to page_size/4096 for systems with page_size > 4K.
+	 */
+	off_t pgoff = (ULONG_MAX - 1) & (~((pgsz - 1) >> 12));
 
-static void setup(void)
-{
-	tst_sig(FORK, DEF_HANDLER, cleanup);
+	fd = SAFE_OPEN(TESTFILE, O_RDWR);
+
+	map = (void *)tst_syscall(__NR_mmap2, NULL, pgsz,
+				  PROT_READ | PROT_WRITE,
+				  MAP_PRIVATE, fd, pgoff);
+
+	if (map == MAP_FAILED) {
+		tst_brk(TBROK | TERRNO, "mmap2(%s, pgoff=%ld)",
+			TESTFILE, (long)pgoff);
+	}
+
+	void *remap = mremap(map, pgsz, 2 * pgsz, 0);
 
-	tst_tmpdir();
+	if (remap == MAP_FAILED) {
+		if (errno == EINVAL)
+			tst_res(TPASS, "mremap() failed with EINVAL as expected");
+		else
+			tst_res(TFAIL | TERRNO, "mremap() failed unexpectedly");
 
-	fd = SAFE_CREAT(NULL, TESTFILE, 0644);
-	close(fd);
+		SAFE_MUNMAP(map, pgsz);
+	} else {
+		tst_res(TFAIL, "mremap() succeeded unexpectedly");
+		SAFE_MUNMAP(remap, 2 * pgsz);
+	}
 
-	TEST_PAUSE;
+	map = MAP_FAILED;
+	SAFE_CLOSE(fd);
 }
 
 static void cleanup(void)
 {
-	tst_rmdir();
-}
-#else /* __NR_mmap2 */
-int main(int argc, char *argv[])
-{
-	tst_brkm(TCONF, NULL, "__NR_mmap2 is not defined on your system");
+	if (map != MAP_FAILED)
+		SAFE_MUNMAP(map, pgsz);
+
+	if (fd != -1)
+		SAFE_CLOSE(fd);
 }
-#endif
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "982134ba6261"},
+		{"CVE", "2011-2496"},
+		{}
+	}
+};
-- 
2.53.0



More information about the ltp mailing list