1// SPDX-License-Identifier: LGPL-2.1-or-later 2/* 3 * Copyright (C) 2013 LG Electronics. 4 * Author: Joonsoo Kim 5 */ 6 7/*\ 8 * [Description] 9 * 10 * Test to preserve a reserved page against no-reserved mapping. If all 11 * hugepages are reserved, access to no-reserved shared mapping cause a 12 * process die, instead of stealing a hugepage which is reserved for other 13 * process. 14 */ 15 16#include <setjmp.h> 17#include "hugetlb.h" 18 19#define MNTPOINT "hugetlbfs/" 20static long hpage_size; 21static int fd1 = -1, fd2 = -1; 22static sigjmp_buf sig_escape; 23static void *sig_expected = MAP_FAILED; 24 25static void sig_handler(int signum, siginfo_t *si, void *uc) 26{ 27 (void)uc; 28 29 if (signum == SIGBUS) { 30 if (si->si_addr == sig_expected) 31 siglongjmp(sig_escape, 1); 32 tst_res(TFAIL, "SIGBUS somewhere unexpected: %p (expected: %p)", 33 si->si_addr, sig_expected); 34 } else { 35 tst_res(TFAIL, "Unexpected signal %s", strsignal(signum)); 36 } 37} 38 39static int test_write(void *p) 40{ 41 volatile char *pl = p; 42 43 if (sigsetjmp(sig_escape, 1)) { 44 /* We got a SIGBUS */ 45 return 1; 46 } 47 48 sig_expected = p; 49 barrier(); 50 *pl = 's'; 51 return 0; 52} 53 54static void run_test(void) 55{ 56 int nr_hugepages; 57 int surp_hugepages; 58 int ret; 59 char *p, *q; 60 struct sigaction sa = { 61 .sa_sigaction = sig_handler, 62 .sa_flags = SA_SIGINFO, 63 }; 64 65 nr_hugepages = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE); 66 67 SAFE_SIGACTION(SIGBUS, &sa, NULL); 68 69 p = SAFE_MMAP(NULL, hpage_size * nr_hugepages, 70 PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); 71 72 tst_res(TINFO, "Reserve all hugepages %d", nr_hugepages); 73 74 q = SAFE_MMAP(NULL, hpage_size, 75 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, fd2, 0); 76 77 tst_res(TINFO, "Write to %p to steal reserved page", q); 78 79 surp_hugepages = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP); 80 ret = test_write(q); 81 if (ret == 1) { 82 tst_res(TPASS, "Successful with SIGSEGV received"); 83 goto cleanup; 84 } 85 86 /* Provisioning succeeded because of overcommit */ 87 if (SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP) == 88 surp_hugepages + 1) { 89 tst_res(TPASS, "Successful because of surplus pages"); 90 goto cleanup; 91 } 92 93 tst_res(TFAIL, "Steal reserved page"); 94cleanup: 95 SAFE_MUNMAP(p, hpage_size * nr_hugepages); 96 SAFE_MUNMAP(q, hpage_size); 97} 98 99static void setup(void) 100{ 101 hpage_size = tst_get_hugepage_size(); 102 fd1 = tst_creat_unlinked(MNTPOINT, 0); 103 fd2 = tst_creat_unlinked(MNTPOINT, 0); 104} 105 106static void cleanup(void) 107{ 108 if (fd1 >= 0) 109 SAFE_CLOSE(fd1); 110 if (fd2 >= 0) 111 SAFE_CLOSE(fd2); 112} 113 114static struct tst_test test = { 115 .needs_root = 1, 116 .mntpoint = MNTPOINT, 117 .needs_hugetlbfs = 1, 118 .needs_tmpdir = 1, 119 .setup = setup, 120 .cleanup = cleanup, 121 .test_all = run_test, 122 .hugepages = {2, TST_NEEDS}, 123}; 124