18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Ptrace test for Memory Protection Key registers 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 68c2ecf20Sopenharmony_ci * Copyright (C) 2018 IBM Corporation. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include "ptrace.h" 98c2ecf20Sopenharmony_ci#include "child.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifndef __NR_pkey_alloc 128c2ecf20Sopenharmony_ci#define __NR_pkey_alloc 384 138c2ecf20Sopenharmony_ci#endif 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifndef __NR_pkey_free 168c2ecf20Sopenharmony_ci#define __NR_pkey_free 385 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#ifndef NT_PPC_PKEY 208c2ecf20Sopenharmony_ci#define NT_PPC_PKEY 0x110 218c2ecf20Sopenharmony_ci#endif 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifndef PKEY_DISABLE_EXECUTE 248c2ecf20Sopenharmony_ci#define PKEY_DISABLE_EXECUTE 0x4 258c2ecf20Sopenharmony_ci#endif 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define AMR_BITS_PER_PKEY 2 288c2ecf20Sopenharmony_ci#define PKEY_REG_BITS (sizeof(u64) * 8) 298c2ecf20Sopenharmony_ci#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY)) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const char user_read[] = "[User Read (Running)]"; 328c2ecf20Sopenharmony_cistatic const char user_write[] = "[User Write (Running)]"; 338c2ecf20Sopenharmony_cistatic const char ptrace_read_running[] = "[Ptrace Read (Running)]"; 348c2ecf20Sopenharmony_cistatic const char ptrace_write_running[] = "[Ptrace Write (Running)]"; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* Information shared between the parent and the child. */ 378c2ecf20Sopenharmony_cistruct shared_info { 388c2ecf20Sopenharmony_ci struct child_sync child_sync; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* AMR value the parent expects to read from the child. */ 418c2ecf20Sopenharmony_ci unsigned long amr1; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* AMR value the parent is expected to write to the child. */ 448c2ecf20Sopenharmony_ci unsigned long amr2; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* AMR value that ptrace should refuse to write to the child. */ 478c2ecf20Sopenharmony_ci unsigned long invalid_amr; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* IAMR value the parent expects to read from the child. */ 508c2ecf20Sopenharmony_ci unsigned long expected_iamr; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* UAMOR value the parent expects to read from the child. */ 538c2ecf20Sopenharmony_ci unsigned long expected_uamor; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* 568c2ecf20Sopenharmony_ci * IAMR and UAMOR values that ptrace should refuse to write to the child 578c2ecf20Sopenharmony_ci * (even though they're valid ones) because userspace doesn't have 588c2ecf20Sopenharmony_ci * access to those registers. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci unsigned long invalid_iamr; 618c2ecf20Sopenharmony_ci unsigned long invalid_uamor; 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci return syscall(__NR_pkey_alloc, flags, init_access_rights); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int child(struct shared_info *info) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci unsigned long reg; 728c2ecf20Sopenharmony_ci bool disable_execute = true; 738c2ecf20Sopenharmony_ci int pkey1, pkey2, pkey3; 748c2ecf20Sopenharmony_ci int ret; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Wait until parent fills out the initial register values. */ 778c2ecf20Sopenharmony_ci ret = wait_parent(&info->child_sync); 788c2ecf20Sopenharmony_ci if (ret) 798c2ecf20Sopenharmony_ci return ret; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* Get some pkeys so that we can change their bits in the AMR. */ 828c2ecf20Sopenharmony_ci pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE); 838c2ecf20Sopenharmony_ci if (pkey1 < 0) { 848c2ecf20Sopenharmony_ci pkey1 = sys_pkey_alloc(0, 0); 858c2ecf20Sopenharmony_ci CHILD_FAIL_IF(pkey1 < 0, &info->child_sync); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci disable_execute = false; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci pkey2 = sys_pkey_alloc(0, 0); 918c2ecf20Sopenharmony_ci CHILD_FAIL_IF(pkey2 < 0, &info->child_sync); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci pkey3 = sys_pkey_alloc(0, 0); 948c2ecf20Sopenharmony_ci CHILD_FAIL_IF(pkey3 < 0, &info->child_sync); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci info->amr1 |= 3ul << pkeyshift(pkey1); 978c2ecf20Sopenharmony_ci info->amr2 |= 3ul << pkeyshift(pkey2); 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * invalid amr value where we try to force write 1008c2ecf20Sopenharmony_ci * things which are deined by a uamor setting. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci info->invalid_amr = info->amr2 | (~0x0UL & ~info->expected_uamor); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* 1058c2ecf20Sopenharmony_ci * if PKEY_DISABLE_EXECUTE succeeded we should update the expected_iamr 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci if (disable_execute) 1088c2ecf20Sopenharmony_ci info->expected_iamr |= 1ul << pkeyshift(pkey1); 1098c2ecf20Sopenharmony_ci else 1108c2ecf20Sopenharmony_ci info->expected_iamr &= ~(1ul << pkeyshift(pkey1)); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * We allocated pkey2 and pkey 3 above. Clear the IAMR bits. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci info->expected_iamr &= ~(1ul << pkeyshift(pkey2)); 1168c2ecf20Sopenharmony_ci info->expected_iamr &= ~(1ul << pkeyshift(pkey3)); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * Create an IAMR value different from expected value. 1208c2ecf20Sopenharmony_ci * Kernel will reject an IAMR and UAMOR change. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci info->invalid_iamr = info->expected_iamr | (1ul << pkeyshift(pkey1) | 1ul << pkeyshift(pkey2)); 1238c2ecf20Sopenharmony_ci info->invalid_uamor = info->expected_uamor & ~(0x3ul << pkeyshift(pkey1)); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n", 1268c2ecf20Sopenharmony_ci user_write, info->amr1, pkey1, pkey2, pkey3); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci set_amr(info->amr1); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Wait for parent to read our AMR value and write a new one. */ 1318c2ecf20Sopenharmony_ci ret = prod_parent(&info->child_sync); 1328c2ecf20Sopenharmony_ci CHILD_FAIL_IF(ret, &info->child_sync); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret = wait_parent(&info->child_sync); 1358c2ecf20Sopenharmony_ci if (ret) 1368c2ecf20Sopenharmony_ci return ret; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci reg = mfspr(SPRN_AMR); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx\n", user_read, reg); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * Wait for parent to try to write an invalid AMR value. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci ret = prod_parent(&info->child_sync); 1488c2ecf20Sopenharmony_ci CHILD_FAIL_IF(ret, &info->child_sync); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci ret = wait_parent(&info->child_sync); 1518c2ecf20Sopenharmony_ci if (ret) 1528c2ecf20Sopenharmony_ci return ret; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci reg = mfspr(SPRN_AMR); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx\n", user_read, reg); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* 1618c2ecf20Sopenharmony_ci * Wait for parent to try to write an IAMR and a UAMOR value. We can't 1628c2ecf20Sopenharmony_ci * verify them, but we can verify that the AMR didn't change. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci ret = prod_parent(&info->child_sync); 1658c2ecf20Sopenharmony_ci CHILD_FAIL_IF(ret, &info->child_sync); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci ret = wait_parent(&info->child_sync); 1688c2ecf20Sopenharmony_ci if (ret) 1698c2ecf20Sopenharmony_ci return ret; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci reg = mfspr(SPRN_AMR); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx\n", user_read, reg); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* Now let parent now that we are finished. */ 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci ret = prod_parent(&info->child_sync); 1808c2ecf20Sopenharmony_ci CHILD_FAIL_IF(ret, &info->child_sync); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return TEST_PASS; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic int parent(struct shared_info *info, pid_t pid) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci unsigned long regs[3]; 1888c2ecf20Sopenharmony_ci int ret, status; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* 1918c2ecf20Sopenharmony_ci * Get the initial values for AMR, IAMR and UAMOR and communicate them 1928c2ecf20Sopenharmony_ci * to the child. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ci ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); 1958c2ecf20Sopenharmony_ci PARENT_SKIP_IF_UNSUPPORTED(ret, &info->child_sync); 1968c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci info->amr1 = info->amr2 = regs[0]; 1998c2ecf20Sopenharmony_ci info->expected_iamr = regs[1]; 2008c2ecf20Sopenharmony_ci info->expected_uamor = regs[2]; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* Wake up child so that it can set itself up. */ 2038c2ecf20Sopenharmony_ci ret = prod_child(&info->child_sync); 2048c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci ret = wait_child(&info->child_sync); 2078c2ecf20Sopenharmony_ci if (ret) 2088c2ecf20Sopenharmony_ci return ret; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Verify that we can read the pkey registers from the child. */ 2118c2ecf20Sopenharmony_ci ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); 2128c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", 2158c2ecf20Sopenharmony_ci ptrace_read_running, regs[0], regs[1], regs[2]); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[0] != info->amr1, &info->child_sync); 2188c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync); 2198c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* Write valid AMR value in child. */ 2228c2ecf20Sopenharmony_ci ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr2, 1); 2238c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr2); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Wake up child so that it can verify it changed. */ 2288c2ecf20Sopenharmony_ci ret = prod_child(&info->child_sync); 2298c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = wait_child(&info->child_sync); 2328c2ecf20Sopenharmony_ci if (ret) 2338c2ecf20Sopenharmony_ci return ret; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Write invalid AMR value in child. */ 2368c2ecf20Sopenharmony_ci ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->invalid_amr, 1); 2378c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx\n", ptrace_write_running, info->invalid_amr); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* Wake up child so that it can verify it didn't change. */ 2428c2ecf20Sopenharmony_ci ret = prod_child(&info->child_sync); 2438c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ret = wait_child(&info->child_sync); 2468c2ecf20Sopenharmony_ci if (ret) 2478c2ecf20Sopenharmony_ci return ret; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Try to write to IAMR. */ 2508c2ecf20Sopenharmony_ci regs[0] = info->amr1; 2518c2ecf20Sopenharmony_ci regs[1] = info->invalid_iamr; 2528c2ecf20Sopenharmony_ci ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 2); 2538c2ecf20Sopenharmony_ci PARENT_FAIL_IF(!ret, &info->child_sync); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx IAMR: %016lx\n", 2568c2ecf20Sopenharmony_ci ptrace_write_running, regs[0], regs[1]); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Try to write to IAMR and UAMOR. */ 2598c2ecf20Sopenharmony_ci regs[2] = info->invalid_uamor; 2608c2ecf20Sopenharmony_ci ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 3); 2618c2ecf20Sopenharmony_ci PARENT_FAIL_IF(!ret, &info->child_sync); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", 2648c2ecf20Sopenharmony_ci ptrace_write_running, regs[0], regs[1], regs[2]); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* Verify that all registers still have their expected values. */ 2678c2ecf20Sopenharmony_ci ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); 2688c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", 2718c2ecf20Sopenharmony_ci ptrace_read_running, regs[0], regs[1], regs[2]); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[0] != info->amr2, &info->child_sync); 2748c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync); 2758c2ecf20Sopenharmony_ci PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Wake up child so that it can verify AMR didn't change and wrap up. */ 2788c2ecf20Sopenharmony_ci ret = prod_child(&info->child_sync); 2798c2ecf20Sopenharmony_ci PARENT_FAIL_IF(ret, &info->child_sync); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci ret = wait(&status); 2828c2ecf20Sopenharmony_ci if (ret != pid) { 2838c2ecf20Sopenharmony_ci printf("Child's exit status not captured\n"); 2848c2ecf20Sopenharmony_ci ret = TEST_PASS; 2858c2ecf20Sopenharmony_ci } else if (!WIFEXITED(status)) { 2868c2ecf20Sopenharmony_ci printf("Child exited abnormally\n"); 2878c2ecf20Sopenharmony_ci ret = TEST_FAIL; 2888c2ecf20Sopenharmony_ci } else 2898c2ecf20Sopenharmony_ci ret = WEXITSTATUS(status) ? TEST_FAIL : TEST_PASS; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return ret; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic int ptrace_pkey(void) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct shared_info *info; 2978c2ecf20Sopenharmony_ci int shm_id; 2988c2ecf20Sopenharmony_ci int ret; 2998c2ecf20Sopenharmony_ci pid_t pid; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT); 3028c2ecf20Sopenharmony_ci info = shmat(shm_id, NULL, 0); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci ret = init_child_sync(&info->child_sync); 3058c2ecf20Sopenharmony_ci if (ret) 3068c2ecf20Sopenharmony_ci return ret; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci pid = fork(); 3098c2ecf20Sopenharmony_ci if (pid < 0) { 3108c2ecf20Sopenharmony_ci perror("fork() failed"); 3118c2ecf20Sopenharmony_ci ret = TEST_FAIL; 3128c2ecf20Sopenharmony_ci } else if (pid == 0) 3138c2ecf20Sopenharmony_ci ret = child(info); 3148c2ecf20Sopenharmony_ci else 3158c2ecf20Sopenharmony_ci ret = parent(info, pid); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci shmdt(info); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (pid) { 3208c2ecf20Sopenharmony_ci destroy_child_sync(&info->child_sync); 3218c2ecf20Sopenharmony_ci shmctl(shm_id, IPC_RMID, NULL); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci return ret; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci return test_harness(ptrace_pkey, "ptrace_pkey"); 3308c2ecf20Sopenharmony_ci} 331