> -----Original Message----- > From: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > Sent: Monday, August 15, 2022 12:18 > To: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>; Lutomirski, Andy > <luto@xxxxxxxxxx>; Peter Zijlstra <peterz@xxxxxxxxxxxxx> > Cc: x86@xxxxxxxxxx; Kostya Serebryany <kcc@xxxxxxxxxx>; Andrey Ryabinin > <ryabinin.a.a@xxxxxxxxx>; Andrey Konovalov <andreyknvl@xxxxxxxxx>; > Alexander Potapenko <glider@xxxxxxxxxx>; Taras Madan > <tarasmadan@xxxxxxxxxx>; Dmitry Vyukov <dvyukov@xxxxxxxxxx>; H . J . Lu > <hjl.tools@xxxxxxxxx>; Andi Kleen <ak@xxxxxxxxxxxxxxx>; Edgecombe, Rick P > <rick.p.edgecombe@xxxxxxxxx>; linux-mm@xxxxxxxxx; linux- > kernel@xxxxxxxxxxxxxxx; Zhang, Weihong <weihong.zhang@xxxxxxxxx>; Kirill A . > Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > Subject: [PATCHv6 09/11] selftests/x86/lam: Add mmap and SYSCALL test > cases for linear-address masking > > From: Weihong Zhang <weihong.zhang@xxxxxxxxx> > > Add mmap and SYSCALL test cases. > > SYSCALL test cases: > > - LAM supports set metadata in high bits 62:57 (LAM_U57) of a user pointer, > pass > the pointer to SYSCALL, SYSCALL can dereference the pointer and return > correct > result. > > - Disable LAM, pass a pointer with metadata in high bits to SYSCALL, > SYSCALL returns -1 (EFAULT). > > MMAP test cases: > > - Enable LAM_U57, MMAP with low address (below bits 47), set metadata > in high bits of the address, dereference the address should be > allowed. > > - Enable LAM_U57, MMAP with high address (above bits 47), set metadata > in high bits of the address, dereference the address should be > allowed. > > Signed-off-by: Weihong Zhang <weihong.zhang@xxxxxxxxx> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > --- > tools/testing/selftests/x86/lam.c | 135 +++++++++++++++++++++++++++++- > 1 file changed, 132 insertions(+), 3 deletions(-) > > diff --git a/tools/testing/selftests/x86/lam.c b/tools/testing/selftests/x86/lam.c > index 4c6c6dbf7db6..e9e92ab7fea8 100644 > --- a/tools/testing/selftests/x86/lam.c > +++ b/tools/testing/selftests/x86/lam.c > @@ -7,6 +7,7 @@ > #include <signal.h> > #include <setjmp.h> > #include <sys/mman.h> > +#include <sys/utsname.h> > #include <sys/wait.h> > #include <inttypes.h> > > @@ -27,11 +28,18 @@ > /* Specified test function bits */ > #define FUNC_MALLOC 0x1 > #define FUNC_BITS 0x2 > +#define FUNC_MMAP 0x4 > +#define FUNC_SYSCALL 0x8 > > -#define TEST_MASK 0x3 > +#define TEST_MASK 0xf > + > +#define LOW_ADDR (0x1UL << 30) > +#define HIGH_ADDR (0x3UL << 48) > > #define MALLOC_LEN 32 > > +#define PAGE_SIZE (4 << 10) > + > struct testcases { > unsigned int later; > int expected; /* 2: SIGSEGV Error; 1: other errors */ @@ -47,6 +55,7 > @@ jmp_buf segv_env; static void segv_handler(int sig) { > ksft_print_msg("Get segmentation fault(%d).", sig); > + > siglongjmp(segv_env, 1); > } > > @@ -59,6 +68,16 @@ static inline int cpu_has_lam(void) > return (cpuinfo[0] & (1 << 26)); > } > > +/* Check 5-level page table feature in CPUID.(EAX=07H, > +ECX=00H):ECX.[bit 16] */ static inline int cpu_has_la57(void) { > + unsigned int cpuinfo[4]; > + > + __cpuid_count(0x7, 0, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]); > + > + return (cpuinfo[2] & (1 << 16)); > +} > + > /* > * Set tagged address and read back untag mask. > * check if the untagged mask is expected. > @@ -204,6 +223,68 @@ static int handle_malloc(struct testcases *test) > return ret; > } > > +static int handle_mmap(struct testcases *test) { > + void *ptr; > + unsigned int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; > + int ret = 0; > + > + if (test->later == 0 && test->lam != 0) > + if (set_lam(test->lam) != 0) > + return 1; > + > + ptr = mmap((void *)test->addr, PAGE_SIZE, PROT_READ | > PROT_WRITE, > + flags, -1, 0); > + if (ptr == MAP_FAILED) { > + if (test->addr == HIGH_ADDR) > + if (!cpu_has_la57()) > + return 3; /* unsupport LA57 */ > + return 1; > + } > + > + if (test->later != 0 && test->lam != 0) > + if (set_lam(test->lam) != 0) > + ret = 1; > + > + if (ret == 0) { > + if (sigsetjmp(segv_env, 1) == 0) { > + signal(SIGSEGV, segv_handler); > + ret = handle_lam_test(ptr, test->lam); > + } else { > + ret = 2; > + } > + } > + > + munmap(ptr, PAGE_SIZE); > + return ret; > +} > + > +static int handle_syscall(struct testcases *test) { > + struct utsname unme, *pu; > + int ret = 0; > + > + if (test->later == 0 && test->lam != 0) > + if (set_lam(test->lam) != 0) > + return 1; > + > + if (sigsetjmp(segv_env, 1) == 0) { > + signal(SIGSEGV, segv_handler); > + pu = (struct utsname *)get_metadata((uint64_t)&unme, test- > >lam); > + ret = uname(pu); > + if (ret < 0) > + ret = 1; > + } else { > + ret = 2; > + } > + > + if (test->later != 0 && test->lam != 0) > + if (set_lam(test->lam) != -1 && ret == 0) > + ret = 1; > + > + return ret; > +} > + > static int fork_test(struct testcases *test) { > int ret, child_ret; > @@ -259,7 +340,6 @@ static struct testcases malloc_cases[] = { > }, > }; > > - > static struct testcases bits_cases[] = { > { > .test_func = handle_max_bits, > @@ -267,11 +347,54 @@ static struct testcases bits_cases[] = { > }, > }; > > +static struct testcases syscall_cases[] = { > + { > + .later = 0, > + .lam = LAM_U57_BITS, > + .test_func = handle_syscall, > + .msg = "SYSCALL: LAM_U57. syscall with metadata\n", > + }, > + { > + .later = 1, > + .expected = 1, > + .lam = LAM_U57_BITS, > + .test_func = handle_syscall, > + .msg = "SYSCALL:[Negtive] Disable LAM. Dereferencing pointer [Hu, Robert] Trivial, Negtive --> Negative. > with metadata.\n", > + }, > +}; > + > +static struct testcases mmap_cases[] = { [Hu, Robert] Can mmap also have negative case? > + { > + .later = 1, > + .expected = 0, > + .lam = LAM_U57_BITS, > + .addr = HIGH_ADDR, > + .test_func = handle_mmap, > + .msg = "MMAP: First mmap high address, then set > LAM_U57.\n", > + }, > + { > + .later = 0, > + .expected = 0, > + .lam = LAM_U57_BITS, > + .addr = HIGH_ADDR, > + .test_func = handle_mmap, > + .msg = "MMAP: First LAM_U57, then High address.\n", > + }, > + { > + .later = 0, > + .expected = 0, > + .lam = LAM_U57_BITS, > + .addr = LOW_ADDR, > + .test_func = handle_mmap, > + .msg = "MMAP: First LAM_U57, then Low address.\n", > + }, > +}; > + > static void cmd_help(void) > { > printf("usage: lam [-h] [-t test list]\n"); > printf("\t-t test list: run tests specified in the test list, default:0x%x\n", > TEST_MASK); > - printf("\t\t0x1:malloc; 0x2:max_bits;\n"); > + printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall.\n"); > printf("\t-h: help\n"); > } > > @@ -311,6 +434,12 @@ int main(int argc, char **argv) > if (tests & FUNC_BITS) > run_test(bits_cases, ARRAY_SIZE(bits_cases)); > > + if (tests & FUNC_MMAP) > + run_test(mmap_cases, ARRAY_SIZE(mmap_cases)); > + > + if (tests & FUNC_SYSCALL) > + run_test(syscall_cases, ARRAY_SIZE(syscall_cases)); > + > ksft_set_plan(tests_cnt); > > return ksft_exit_pass(); > -- > 2.35.1