[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