Message ID | 20240403163419.90388-1-geetika@linux.ibm.com |
---|---|
State | Changes Requested |
Headers | show |
Series | Add hugemmap42, migrated task-size-overrun.c from libhugetlbfs | expand |
Hi! > +// SPDX-License-Identifier: LGPL-2.1-or-later > +/* > + * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation. > + */ > + > +/*\ > + *[Descripiton] > + * > + * Origin: https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/task-size-overrun.c > + * > + * This test verifies the behavior of mmap across the TASK_SIZE boundary. > + * It checks whether mmap with and without MAP_FIXED correctly handles > + * mappings that straddle the TASK_SIZE boundary. > + * > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/mman.h> > +#include <errno.h> > +#include <assert.h> > + > +#include "hugetlb.h" > +#include "tst_test.h" > +#include "tst_safe_stdio.h" > +#include "tst_safe_macros.h" > + > +#define MAPS_BUF_SZ 4096 > +#define _LARGEFILE64_SOURCE > +#define MNTPOINT "hugetlbfs/" > +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) > + > +static long hpage_size; > +static int fd; > +static char line[MAPS_BUF_SZ]; > +static char *tmp; > +static unsigned long start, end, off, ino; > +static FILE *f; > +static void *p; > +static unsigned long task_size; > +static unsigned long straddle_addr; Most of these are used only in a single function, some even shadowed by another declaration inside of these functions. We should really create global variables only for things that are used in several functions. As far as I can these are only hpage_size and fd. > +static unsigned long find_last_mapped(void) > +{ > + f = SAFE_FOPEN("/proc/self/maps", "r"); > + do { > + tmp = fgets(line, MAPS_BUF_SZ, f); ^ sizeof(line) is a bit better > + } while (tmp); > + SAFE_FCLOSE(f); > + > + tst_res(TINFO, "Last map: %s", line); > + SAFE_SSCANF(line, "%lx-%lx %*s %lx %*s %ld %*s", &start, &end, &off, &ino); > + tst_res(TINFO, "Last map: at 0x%lx-0x%lx\n", start, end); > + return end; > +} > + > +static unsigned long find_task_size(void) > +{ > + unsigned long low, high; /* PFNs */ > + void *p; > + > + low = find_last_mapped(); > + if (!low || ((low % getpagesize()) != 0)) > + tst_brk(TBROK, "Bogus stack end address, 0x%lx!?", low); > + low = low / getpagesize(); > + > + /* This sum should get us (2^(wordsize) - 2 pages) */ > + high = (unsigned long)(-2 * getpagesize()) / tst_get_hugepage_size(); > + tst_res(TINFO, "Binary searching for task size PFNs 0x%lx..0x%lx\n", low, high); > + > + while (high > low + 1) { > + unsigned long pfn = (low + high) / 2; > + unsigned long addr = pfn * getpagesize(); > + > + assert((pfn >= low) && (pfn <= high)); > + > + p = mmap((void *)addr, getpagesize(), 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\n", addr); > + SAFE_MUNMAP(p, getpagesize()); > + low = pfn; > + } > + } > + > + return low * getpagesize(); > +} > + > +static void run_test(void) > +{ > + task_size = find_task_size(); > + tst_res(TINFO, "TASK_SIZE = 0x%lx\n", task_size); > + > + straddle_addr = task_size - hpage_size; > + straddle_addr = 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); > + tst_res(TINFO | TERRNO, "Error encountered"); This is misleading, we are printing "error" encountered even that the call is supposed to work. > + if (p == (void *)straddle_addr) { > + tst_res(TFAIL, "Apparently suceeded in mapping across TASK_SIZE boundary"); > + goto windup; > + } > + > + 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); > + tst_res(TINFO | TERRNO, "Error encountered"); > + if (p != MAP_FAILED) { > + tst_res(TFAIL, "Apparently suceeded in mapping across TASK_SIZE boundary"); > + goto windup; > + } We should use the newly indroduced macro TST_EXP_FAIL_PTR_VOID() from: http://patchwork.ozlabs.org/project/ltp/patch/20240403032859.3826-2-wegao@suse.com/ I will have a look at that patchset later on, but I guess that it will be accepted soon enough so that you can use it here. Also I will have a look into adding TST_EXP_PASS_PTR_VOID() so that we can use it in the first case above. > + > + tst_res(TPASS, "Test passed!"); > + > +windup: > + tst_res(TINFO, "Test Completed."); Can we please not to print this message, it's a bit useless. > +} > + > +static void setup(void) > +{ > + hpage_size = getpagesize(); > + fd = tst_creat_unlinked(MNTPOINT, 0); > +} > + > +static void cleanup(void) > +{ > + if (fd > 0) > + 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.39.3 (Apple Git-146) > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp
diff --git a/runtest/hugetlb b/runtest/hugetlb index 299c07ac9..9165051cb 100644 --- a/runtest/hugetlb +++ b/runtest/hugetlb @@ -35,6 +35,7 @@ hugemmap29 hugemmap29 hugemmap30 hugemmap30 hugemmap31 hugemmap31 hugemmap32 hugemmap32 +hugemmap42 hugemmap42 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 c96fe8bfc..f215fb2b8 100644 --- a/testcases/kernel/mem/.gitignore +++ b/testcases/kernel/mem/.gitignore @@ -34,6 +34,7 @@ /hugetlb/hugemmap/hugemmap30 /hugetlb/hugemmap/hugemmap31 /hugetlb/hugemmap/hugemmap32 +/hugetlb/hugemmap/hugemmap42 /hugetlb/hugeshmat/hugeshmat01 /hugetlb/hugeshmat/hugeshmat02 /hugetlb/hugeshmat/hugeshmat03 diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap42.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap42.c new file mode 100644 index 000000000..b36002d03 --- /dev/null +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap42.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation. + */ + +/*\ + *[Descripiton] + * + * Origin: https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/task-size-overrun.c + * + * This test verifies the behavior of mmap across the TASK_SIZE boundary. + * It checks whether mmap with and without MAP_FIXED correctly handles + * mappings that straddle the TASK_SIZE boundary. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <errno.h> +#include <assert.h> + +#include "hugetlb.h" +#include "tst_test.h" +#include "tst_safe_stdio.h" +#include "tst_safe_macros.h" + +#define MAPS_BUF_SZ 4096 +#define _LARGEFILE64_SOURCE +#define MNTPOINT "hugetlbfs/" +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +static long hpage_size; +static int fd; +static char line[MAPS_BUF_SZ]; +static char *tmp; +static unsigned long start, end, off, ino; +static FILE *f; +static void *p; +static unsigned long task_size; +static unsigned long straddle_addr; + +static unsigned long find_last_mapped(void) +{ + f = SAFE_FOPEN("/proc/self/maps", "r"); + do { + tmp = fgets(line, MAPS_BUF_SZ, f); + } while (tmp); + SAFE_FCLOSE(f); + + tst_res(TINFO, "Last map: %s", line); + SAFE_SSCANF(line, "%lx-%lx %*s %lx %*s %ld %*s", &start, &end, &off, &ino); + tst_res(TINFO, "Last map: at 0x%lx-0x%lx\n", start, end); + return end; +} + +static unsigned long find_task_size(void) +{ + unsigned long low, high; /* PFNs */ + void *p; + + low = find_last_mapped(); + if (!low || ((low % getpagesize()) != 0)) + tst_brk(TBROK, "Bogus stack end address, 0x%lx!?", low); + low = low / getpagesize(); + + /* This sum should get us (2^(wordsize) - 2 pages) */ + high = (unsigned long)(-2 * getpagesize()) / tst_get_hugepage_size(); + tst_res(TINFO, "Binary searching for task size PFNs 0x%lx..0x%lx\n", low, high); + + while (high > low + 1) { + unsigned long pfn = (low + high) / 2; + unsigned long addr = pfn * getpagesize(); + + assert((pfn >= low) && (pfn <= high)); + + p = mmap((void *)addr, getpagesize(), 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\n", addr); + SAFE_MUNMAP(p, getpagesize()); + low = pfn; + } + } + + return low * getpagesize(); +} + +static void run_test(void) +{ + task_size = find_task_size(); + tst_res(TINFO, "TASK_SIZE = 0x%lx\n", task_size); + + straddle_addr = task_size - hpage_size; + straddle_addr = 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); + tst_res(TINFO | TERRNO, "Error encountered"); + if (p == (void *)straddle_addr) { + tst_res(TFAIL, "Apparently suceeded in mapping across TASK_SIZE boundary"); + goto windup; + } + + 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); + tst_res(TINFO | TERRNO, "Error encountered"); + if (p != MAP_FAILED) { + tst_res(TFAIL, "Apparently suceeded in mapping across TASK_SIZE boundary"); + goto windup; + } + + tst_res(TPASS, "Test passed!"); + +windup: + tst_res(TINFO, "Test Completed."); +} + +static void setup(void) +{ + hpage_size = getpagesize(); + fd = tst_creat_unlinked(MNTPOINT, 0); +} + +static void cleanup(void) +{ + if (fd > 0) + 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}, +};
This test is migrated from : https://github.com/libhugetlbfs/libhugetlbfs/blob/master/tests/task-size-overrun.c This test verifies the behavior of mmap across the TASK_SIZE boundary. It checks whether mmap with and without MAP_FIXED correctly handles mappings that straddle the TASK_SIZE boundary. Verified that test runs with multiple iterations (2,4,8,10,20) Verified that test has no warnings. Signed-off-by: Geetika <geetika@linux.ibm.com> --- runtest/hugetlb | 1 + testcases/kernel/mem/.gitignore | 1 + .../kernel/mem/hugetlb/hugemmap/hugemmap42.c | 148 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap42.c