linux-test-project / ltp

Linux Test Project (mailing list: https://lists.linux.it/listinfo/ltp)
https://linux-test-project.readthedocs.io/
GNU General Public License v2.0
2.28k stars 999 forks source link

hugemmap24 test case failed on aarch64 #1022

Closed yup-21 closed 1 year ago

yup-21 commented 1 year ago

I executed the testcase in aarch64 : [root@localhost bin]# ./hugemmap24 tst_hugepage.c:83: TINFO: 7 hugepage(s) reserved tst_test.c:1560: TINFO: Timeout per run is 0h 00m 30s hugemmap24.c:57: TINFO: can't use slice_boundary: 0x10000000: EINVAL (22) hugemmap24.c:57: TINFO: can't use slice_boundary: 0x20000000: ENOMEM (12) hugemmap24.c:57: TINFO: can't use slice_boundary: 0x30000000: EINVAL (22) tst_test.c:1618: TBROK: Test killed by SIGSEGV!

strace -f ./hugemmap24: ... [pid 86580] mmap(0xfffffffff0000000, 2147483648, PROT_READ, MAP_SHARED|MAP_FIXED, 3, 0) = -1 EINVAL [pid 86580] write(2, "hugemmap24.c:57: \33[1;34mTINFO: \33"..., 85hugemmap24.c:57: TINFO: can't use slice_boundary: 0x30000000: EINVAL (22)) = 85 [pid 86580] mmap(NULL, 2147483648, PROT_READ, MAP_SHARED|MAP_FIXED, 3, 0) = 0 [pid 86580] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x404338} --- [pid 86580] +++ killed by SIGSEGV (core dumped) +++

cat /proc/meminfo Hugepagesize: 524288 kB

I saw that the slice_boundary on aarch64 started from 0x10000000-2*hpage_size. The 4th time mmap will access NULL, causing SIGSEGV.

What is this test case for? Why does the aarch64 need to start from 0x10000000 address different from other platforms?

metan-ucw commented 1 year ago

Obviously the test does not work with 512MB hugepages on aarch64, I will email the IBM developer who ported these tests to LTP.

rhmcruiser commented 1 year ago

Just trying to get a peek at source hugemmap24.c It starts with a description on architecture caution, it caters primarily to PowerPC slice bounds I suppose.

/*\

And possibly in here is where it bails out for the aaarch64

47 / Find 2 neighbour slices with couple huge pages free 48 around slice boundary. 49 16 is the maximum number of slices (low/high) 50 / 51 for (i = 0; i < 16-1; i++) { 52 slice_boundary += slice_size; 53 p = mmap((void )(slice_boundary-2hpage_size), 4hpage_size, 54 PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0); 55 if (p == MAP_FAILED) { 56 tst_res(TINFO|TERRNO, "can't use slice_boundary: 0x%lx", 57 slice_boundary); 58 } else { 59 SAFE_MUNMAP(p, 4hpage_size); 60 break; 61 } 62 } 63

jstancek commented 1 year ago

(copying my reply from mailing list) With so large hugepages it underflows mmap address, so I'd increase it, until we start with one larger than zero:

diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
index a465aad..9523067 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
@@ -23,7 +23,7 @@

 static int  fd = -1;
 static unsigned long slice_boundary;
-static long hpage_size, page_size;
+static unsigned long hpage_size, page_size;

 static int init_slice_boundary(int fd)
 {
@@ -40,6 +40,10 @@ static int init_slice_boundary(int fd)
        slice_size = 0x10000000;
 #endif

+       /* avoid underflow on systems with large huge pages */
+       while (slice_boundary + slice_size < 2 * hpage_size)
+               slice_boundary += slice_size;
+
        /* dummy malloc so we know where is heap */
        heap = malloc(1);
        free(heap);

Another issue however is the use of MAP_FIXED, which can stomp over existing mappings:

[pid 48607] 04:50:51 mmap(0x20000000, 2147483648, PROT_READ,
MAP_SHARED|MAP_FIXED, 3, 0) = 0x20000000
[pid 48607] 04:50:51 munmap(0x20000000, 2147483648) = 0

test may PASS, but at the end you get:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  numa_bitmask_free (bmp=0x39ae09a0) at libnuma.c:228
228             free(bmp->maskp);
(gdb) bt
#0  numa_bitmask_free (bmp=0x39ae09a0) at libnuma.c:228
#1  numa_bitmask_free (bmp=0x39ae09a0) at libnuma.c:224
#2  0x0000ffff89263360 in numa_fini () at libnuma.c:114
#3  0x0000ffff892d4cac in _dl_fini () at dl-fini.c:141
#4  0x0000ffff890d899c in __run_exit_handlers (status=status@entry=0,
listp=0xffff892105e0 <__exit_funcs>,
run_list_atexit=run_list_atexit@entry=true,
run_dtors=run_dtors@entry=true) at exit.c:108
#5  0x0000ffff890d8b1c in __GI_exit (status=status@entry=0) at exit.c:139
#6  0x000000000040ecd8 in testrun () at tst_test.c:1468
#7  fork_testrun () at tst_test.c:1592
#8  0x0000000000410728 in tst_run_tcases (argc=<optimized out>,
argv=<optimized out>, self=self@entry=0x440650 <test>) at
tst_test.c:1686
#9  0x0000000000403ef8 in main (argc=<optimized out>, argv=<optimized
out>) at ../../../../../include/tst_test.h:394

(gdb) info proc map
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x430000    0x30000        0x0
/root/ltp.upstream/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24
            0x430000           0x440000    0x10000    0x20000
/root/ltp.upstream/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24
            0x440000           0x450000    0x10000    0x30000
/root/ltp.upstream/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24
      0xffff890a0000     0xffff89200000   0x160000        0x0
/usr/lib64/[libc-2.28.so](http://libc-2.28.so/)
      0xffff89200000     0xffff89210000    0x10000   0x150000
/usr/lib64/[libc-2.28.so](http://libc-2.28.so/)
      0xffff89210000     0xffff89220000    0x10000   0x160000
/usr/lib64/[libc-2.28.so](http://libc-2.28.so/)
      0xffff89220000     0xffff89240000    0x20000        0x0
/usr/lib64/[libpthread-2.28.so](http://libpthread-2.28.so/)
      0xffff89240000     0xffff89250000    0x10000    0x10000
/usr/lib64/[libpthread-2.28.so](http://libpthread-2.28.so/)
      0xffff89250000     0xffff89260000    0x10000    0x20000
/usr/lib64/[libpthread-2.28.so](http://libpthread-2.28.so/)
      0xffff89260000     0xffff89270000    0x10000        0x0
/usr/lib64/libnuma.so.1.0.0
      0xffff89270000     0xffff89280000    0x10000        0x0
/usr/lib64/libnuma.so.1.0.0
      0xffff89280000     0xffff89290000    0x10000    0x10000
/usr/lib64/libnuma.so.1.0.0
      0xffff89290000     0xffff892a0000    0x10000        0x0
/dev/shm/ltp_hugemmap24_48644 (deleted)
      0xffff892d0000     0xffff89300000    0x30000        0x0
/usr/lib64/[ld-2.28.so](http://ld-2.28.so/)
      0xffff89300000     0xffff89310000    0x10000    0x20000
/usr/lib64/[ld-2.28.so](http://ld-2.28.so/)
      0xffff89310000     0xffff89320000    0x10000    0x30000
/usr/lib64/[ld-2.28.so](http://ld-2.28.so/)
yup-21 commented 1 year ago

Hi, I was able to retest in the same test environment with selinux turned on and it passed, when the mmap NULL pointer returned -EACCES instead of being interrupted by SIGSEGV. Also, the above patches seem to pass the test after merging, is there a plan to merge them?

wangli5665 commented 1 year ago

I re-wrote a V2 patch base on Jan's work. It'd be great if any of you help test this:

--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
@@ -23,7 +23,7 @@

 static int  fd = -1;
 static unsigned long slice_boundary;
-static long hpage_size, page_size;
+static unsigned long hpage_size, page_size;

 static int init_slice_boundary(int fd)
 {
@@ -44,6 +44,13 @@ static int init_slice_boundary(int fd)
        heap = malloc(1);
        free(heap);

+        /* Avoid underflow on systems with large huge pages.
+         * Here additionally plus heap address to reduce the possibility
+         * of MAP_FIXED stomp over existing mappings.
+         */
+       while (slice_boundary + slice_size < (unsigned long)heap + 2*hpage_size)
+               slice_boundary += slice_size;
+
        /* Find 2 neighbour slices with couple huge pages free
         * around slice boundary.
         * 16 is the maximum number of slices (low/high)
wangli5665 commented 1 year ago

patch sent to ML: https://lists.linux.it/pipermail/ltp/2023-April/033670.html