11f7256e7SThiago Jung Bauermann // SPDX-License-Identifier: GPL-2.0+
21f7256e7SThiago Jung Bauermann /*
31f7256e7SThiago Jung Bauermann * Ptrace test for Memory Protection Key registers
41f7256e7SThiago Jung Bauermann *
51f7256e7SThiago Jung Bauermann * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
61f7256e7SThiago Jung Bauermann * Copyright (C) 2018 IBM Corporation.
71f7256e7SThiago Jung Bauermann */
81f7256e7SThiago Jung Bauermann #include "ptrace.h"
91f7256e7SThiago Jung Bauermann #include "child.h"
101f7256e7SThiago Jung Bauermann
111f7256e7SThiago Jung Bauermann #ifndef __NR_pkey_alloc
121f7256e7SThiago Jung Bauermann #define __NR_pkey_alloc 384
131f7256e7SThiago Jung Bauermann #endif
141f7256e7SThiago Jung Bauermann
151f7256e7SThiago Jung Bauermann #ifndef __NR_pkey_free
161f7256e7SThiago Jung Bauermann #define __NR_pkey_free 385
171f7256e7SThiago Jung Bauermann #endif
181f7256e7SThiago Jung Bauermann
191f7256e7SThiago Jung Bauermann #ifndef NT_PPC_PKEY
201f7256e7SThiago Jung Bauermann #define NT_PPC_PKEY 0x110
211f7256e7SThiago Jung Bauermann #endif
221f7256e7SThiago Jung Bauermann
231f7256e7SThiago Jung Bauermann #ifndef PKEY_DISABLE_EXECUTE
241f7256e7SThiago Jung Bauermann #define PKEY_DISABLE_EXECUTE 0x4
251f7256e7SThiago Jung Bauermann #endif
261f7256e7SThiago Jung Bauermann
271f7256e7SThiago Jung Bauermann #define AMR_BITS_PER_PKEY 2
281f7256e7SThiago Jung Bauermann #define PKEY_REG_BITS (sizeof(u64) * 8)
291f7256e7SThiago Jung Bauermann #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY))
301f7256e7SThiago Jung Bauermann
311f7256e7SThiago Jung Bauermann static const char user_read[] = "[User Read (Running)]";
321f7256e7SThiago Jung Bauermann static const char user_write[] = "[User Write (Running)]";
331f7256e7SThiago Jung Bauermann static const char ptrace_read_running[] = "[Ptrace Read (Running)]";
341f7256e7SThiago Jung Bauermann static const char ptrace_write_running[] = "[Ptrace Write (Running)]";
351f7256e7SThiago Jung Bauermann
361f7256e7SThiago Jung Bauermann /* Information shared between the parent and the child. */
371f7256e7SThiago Jung Bauermann struct shared_info {
381f7256e7SThiago Jung Bauermann struct child_sync child_sync;
391f7256e7SThiago Jung Bauermann
401f7256e7SThiago Jung Bauermann /* AMR value the parent expects to read from the child. */
411f7256e7SThiago Jung Bauermann unsigned long amr1;
421f7256e7SThiago Jung Bauermann
431f7256e7SThiago Jung Bauermann /* AMR value the parent is expected to write to the child. */
441f7256e7SThiago Jung Bauermann unsigned long amr2;
451f7256e7SThiago Jung Bauermann
461f7256e7SThiago Jung Bauermann /* AMR value that ptrace should refuse to write to the child. */
479a11f12eSAneesh Kumar K.V unsigned long invalid_amr;
481f7256e7SThiago Jung Bauermann
491f7256e7SThiago Jung Bauermann /* IAMR value the parent expects to read from the child. */
501f7256e7SThiago Jung Bauermann unsigned long expected_iamr;
511f7256e7SThiago Jung Bauermann
521f7256e7SThiago Jung Bauermann /* UAMOR value the parent expects to read from the child. */
531f7256e7SThiago Jung Bauermann unsigned long expected_uamor;
541f7256e7SThiago Jung Bauermann
551f7256e7SThiago Jung Bauermann /*
561f7256e7SThiago Jung Bauermann * IAMR and UAMOR values that ptrace should refuse to write to the child
571f7256e7SThiago Jung Bauermann * (even though they're valid ones) because userspace doesn't have
581f7256e7SThiago Jung Bauermann * access to those registers.
591f7256e7SThiago Jung Bauermann */
609a11f12eSAneesh Kumar K.V unsigned long invalid_iamr;
619a11f12eSAneesh Kumar K.V unsigned long invalid_uamor;
621f7256e7SThiago Jung Bauermann };
631f7256e7SThiago Jung Bauermann
sys_pkey_alloc(unsigned long flags,unsigned long init_access_rights)641f7256e7SThiago Jung Bauermann static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights)
651f7256e7SThiago Jung Bauermann {
661f7256e7SThiago Jung Bauermann return syscall(__NR_pkey_alloc, flags, init_access_rights);
671f7256e7SThiago Jung Bauermann }
681f7256e7SThiago Jung Bauermann
child(struct shared_info * info)691f7256e7SThiago Jung Bauermann static int child(struct shared_info *info)
701f7256e7SThiago Jung Bauermann {
711f7256e7SThiago Jung Bauermann unsigned long reg;
721f7256e7SThiago Jung Bauermann bool disable_execute = true;
731f7256e7SThiago Jung Bauermann int pkey1, pkey2, pkey3;
741f7256e7SThiago Jung Bauermann int ret;
751f7256e7SThiago Jung Bauermann
761f7256e7SThiago Jung Bauermann /* Wait until parent fills out the initial register values. */
771f7256e7SThiago Jung Bauermann ret = wait_parent(&info->child_sync);
781f7256e7SThiago Jung Bauermann if (ret)
791f7256e7SThiago Jung Bauermann return ret;
801f7256e7SThiago Jung Bauermann
811f7256e7SThiago Jung Bauermann /* Get some pkeys so that we can change their bits in the AMR. */
821f7256e7SThiago Jung Bauermann pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE);
831f7256e7SThiago Jung Bauermann if (pkey1 < 0) {
841f7256e7SThiago Jung Bauermann pkey1 = sys_pkey_alloc(0, 0);
851f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(pkey1 < 0, &info->child_sync);
861f7256e7SThiago Jung Bauermann
871f7256e7SThiago Jung Bauermann disable_execute = false;
881f7256e7SThiago Jung Bauermann }
891f7256e7SThiago Jung Bauermann
901f7256e7SThiago Jung Bauermann pkey2 = sys_pkey_alloc(0, 0);
911f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(pkey2 < 0, &info->child_sync);
921f7256e7SThiago Jung Bauermann
931f7256e7SThiago Jung Bauermann pkey3 = sys_pkey_alloc(0, 0);
941f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(pkey3 < 0, &info->child_sync);
951f7256e7SThiago Jung Bauermann
961f7256e7SThiago Jung Bauermann info->amr1 |= 3ul << pkeyshift(pkey1);
971f7256e7SThiago Jung Bauermann info->amr2 |= 3ul << pkeyshift(pkey2);
980eaa3b5cSAneesh Kumar K.V /*
990eaa3b5cSAneesh Kumar K.V * invalid amr value where we try to force write
1000eaa3b5cSAneesh Kumar K.V * things which are deined by a uamor setting.
1010eaa3b5cSAneesh Kumar K.V */
1020eaa3b5cSAneesh Kumar K.V info->invalid_amr = info->amr2 | (~0x0UL & ~info->expected_uamor);
1031f7256e7SThiago Jung Bauermann
1043563b9beSAneesh Kumar K.V /*
1053563b9beSAneesh Kumar K.V * if PKEY_DISABLE_EXECUTE succeeded we should update the expected_iamr
1063563b9beSAneesh Kumar K.V */
1071f7256e7SThiago Jung Bauermann if (disable_execute)
1081f7256e7SThiago Jung Bauermann info->expected_iamr |= 1ul << pkeyshift(pkey1);
10929e8131cSRam Pai else
11029e8131cSRam Pai info->expected_iamr &= ~(1ul << pkeyshift(pkey1));
11129e8131cSRam Pai
1123563b9beSAneesh Kumar K.V /*
1133563b9beSAneesh Kumar K.V * We allocated pkey2 and pkey 3 above. Clear the IAMR bits.
1143563b9beSAneesh Kumar K.V */
1153563b9beSAneesh Kumar K.V info->expected_iamr &= ~(1ul << pkeyshift(pkey2));
1163563b9beSAneesh Kumar K.V info->expected_iamr &= ~(1ul << pkeyshift(pkey3));
1171f7256e7SThiago Jung Bauermann
1181f7256e7SThiago Jung Bauermann /*
1190eaa3b5cSAneesh Kumar K.V * Create an IAMR value different from expected value.
1200eaa3b5cSAneesh Kumar K.V * Kernel will reject an IAMR and UAMOR change.
1211f7256e7SThiago Jung Bauermann */
1220eaa3b5cSAneesh Kumar K.V info->invalid_iamr = info->expected_iamr | (1ul << pkeyshift(pkey1) | 1ul << pkeyshift(pkey2));
1230eaa3b5cSAneesh Kumar K.V info->invalid_uamor = info->expected_uamor & ~(0x3ul << pkeyshift(pkey1));
1241f7256e7SThiago Jung Bauermann
1251f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n",
1261f7256e7SThiago Jung Bauermann user_write, info->amr1, pkey1, pkey2, pkey3);
1271f7256e7SThiago Jung Bauermann
128828ca432SSandipan Das set_amr(info->amr1);
1291f7256e7SThiago Jung Bauermann
1301f7256e7SThiago Jung Bauermann /* Wait for parent to read our AMR value and write a new one. */
1311f7256e7SThiago Jung Bauermann ret = prod_parent(&info->child_sync);
1321f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(ret, &info->child_sync);
1331f7256e7SThiago Jung Bauermann
1341f7256e7SThiago Jung Bauermann ret = wait_parent(&info->child_sync);
1351f7256e7SThiago Jung Bauermann if (ret)
1361f7256e7SThiago Jung Bauermann return ret;
1371f7256e7SThiago Jung Bauermann
1381f7256e7SThiago Jung Bauermann reg = mfspr(SPRN_AMR);
1391f7256e7SThiago Jung Bauermann
1401f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx\n", user_read, reg);
1411f7256e7SThiago Jung Bauermann
1421f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
1431f7256e7SThiago Jung Bauermann
1441f7256e7SThiago Jung Bauermann /*
1451f7256e7SThiago Jung Bauermann * Wait for parent to try to write an invalid AMR value.
1461f7256e7SThiago Jung Bauermann */
1471f7256e7SThiago Jung Bauermann ret = prod_parent(&info->child_sync);
1481f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(ret, &info->child_sync);
1491f7256e7SThiago Jung Bauermann
1501f7256e7SThiago Jung Bauermann ret = wait_parent(&info->child_sync);
1511f7256e7SThiago Jung Bauermann if (ret)
1521f7256e7SThiago Jung Bauermann return ret;
1531f7256e7SThiago Jung Bauermann
1541f7256e7SThiago Jung Bauermann reg = mfspr(SPRN_AMR);
1551f7256e7SThiago Jung Bauermann
1561f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx\n", user_read, reg);
1571f7256e7SThiago Jung Bauermann
1581f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
1591f7256e7SThiago Jung Bauermann
1601f7256e7SThiago Jung Bauermann /*
1611f7256e7SThiago Jung Bauermann * Wait for parent to try to write an IAMR and a UAMOR value. We can't
1621f7256e7SThiago Jung Bauermann * verify them, but we can verify that the AMR didn't change.
1631f7256e7SThiago Jung Bauermann */
1641f7256e7SThiago Jung Bauermann ret = prod_parent(&info->child_sync);
1651f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(ret, &info->child_sync);
1661f7256e7SThiago Jung Bauermann
1671f7256e7SThiago Jung Bauermann ret = wait_parent(&info->child_sync);
1681f7256e7SThiago Jung Bauermann if (ret)
1691f7256e7SThiago Jung Bauermann return ret;
1701f7256e7SThiago Jung Bauermann
1711f7256e7SThiago Jung Bauermann reg = mfspr(SPRN_AMR);
1721f7256e7SThiago Jung Bauermann
1731f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx\n", user_read, reg);
1741f7256e7SThiago Jung Bauermann
1751f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
1761f7256e7SThiago Jung Bauermann
1771f7256e7SThiago Jung Bauermann /* Now let parent now that we are finished. */
1781f7256e7SThiago Jung Bauermann
1791f7256e7SThiago Jung Bauermann ret = prod_parent(&info->child_sync);
1801f7256e7SThiago Jung Bauermann CHILD_FAIL_IF(ret, &info->child_sync);
1811f7256e7SThiago Jung Bauermann
1821f7256e7SThiago Jung Bauermann return TEST_PASS;
1831f7256e7SThiago Jung Bauermann }
1841f7256e7SThiago Jung Bauermann
parent(struct shared_info * info,pid_t pid)1851f7256e7SThiago Jung Bauermann static int parent(struct shared_info *info, pid_t pid)
1861f7256e7SThiago Jung Bauermann {
1871f7256e7SThiago Jung Bauermann unsigned long regs[3];
1881f7256e7SThiago Jung Bauermann int ret, status;
1891f7256e7SThiago Jung Bauermann
1901f7256e7SThiago Jung Bauermann /*
1911f7256e7SThiago Jung Bauermann * Get the initial values for AMR, IAMR and UAMOR and communicate them
1921f7256e7SThiago Jung Bauermann * to the child.
1931f7256e7SThiago Jung Bauermann */
1941f7256e7SThiago Jung Bauermann ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
195*68877ff2SBenjamin Gray PARENT_SKIP_IF_UNSUPPORTED(ret, &info->child_sync, "PKEYs not supported");
1961f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
1971f7256e7SThiago Jung Bauermann
1980eaa3b5cSAneesh Kumar K.V info->amr1 = info->amr2 = regs[0];
1990eaa3b5cSAneesh Kumar K.V info->expected_iamr = regs[1];
2000eaa3b5cSAneesh Kumar K.V info->expected_uamor = regs[2];
2011f7256e7SThiago Jung Bauermann
2021f7256e7SThiago Jung Bauermann /* Wake up child so that it can set itself up. */
2031f7256e7SThiago Jung Bauermann ret = prod_child(&info->child_sync);
2041f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2051f7256e7SThiago Jung Bauermann
2061f7256e7SThiago Jung Bauermann ret = wait_child(&info->child_sync);
2071f7256e7SThiago Jung Bauermann if (ret)
2081f7256e7SThiago Jung Bauermann return ret;
2091f7256e7SThiago Jung Bauermann
2101f7256e7SThiago Jung Bauermann /* Verify that we can read the pkey registers from the child. */
2111f7256e7SThiago Jung Bauermann ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
2121f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2131f7256e7SThiago Jung Bauermann
2141f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
2151f7256e7SThiago Jung Bauermann ptrace_read_running, regs[0], regs[1], regs[2]);
2161f7256e7SThiago Jung Bauermann
2171f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[0] != info->amr1, &info->child_sync);
2181f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
2191f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
2201f7256e7SThiago Jung Bauermann
2211f7256e7SThiago Jung Bauermann /* Write valid AMR value in child. */
2221f7256e7SThiago Jung Bauermann ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr2, 1);
2231f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2241f7256e7SThiago Jung Bauermann
2251f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr2);
2261f7256e7SThiago Jung Bauermann
2271f7256e7SThiago Jung Bauermann /* Wake up child so that it can verify it changed. */
2281f7256e7SThiago Jung Bauermann ret = prod_child(&info->child_sync);
2291f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2301f7256e7SThiago Jung Bauermann
2311f7256e7SThiago Jung Bauermann ret = wait_child(&info->child_sync);
2321f7256e7SThiago Jung Bauermann if (ret)
2331f7256e7SThiago Jung Bauermann return ret;
2341f7256e7SThiago Jung Bauermann
2351f7256e7SThiago Jung Bauermann /* Write invalid AMR value in child. */
2369a11f12eSAneesh Kumar K.V ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->invalid_amr, 1);
2371f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2381f7256e7SThiago Jung Bauermann
2399a11f12eSAneesh Kumar K.V printf("%-30s AMR: %016lx\n", ptrace_write_running, info->invalid_amr);
2401f7256e7SThiago Jung Bauermann
2411f7256e7SThiago Jung Bauermann /* Wake up child so that it can verify it didn't change. */
2421f7256e7SThiago Jung Bauermann ret = prod_child(&info->child_sync);
2431f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2441f7256e7SThiago Jung Bauermann
2451f7256e7SThiago Jung Bauermann ret = wait_child(&info->child_sync);
2461f7256e7SThiago Jung Bauermann if (ret)
2471f7256e7SThiago Jung Bauermann return ret;
2481f7256e7SThiago Jung Bauermann
2491f7256e7SThiago Jung Bauermann /* Try to write to IAMR. */
2501f7256e7SThiago Jung Bauermann regs[0] = info->amr1;
2519a11f12eSAneesh Kumar K.V regs[1] = info->invalid_iamr;
2521f7256e7SThiago Jung Bauermann ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 2);
2531f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(!ret, &info->child_sync);
2541f7256e7SThiago Jung Bauermann
2551f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx IAMR: %016lx\n",
2561f7256e7SThiago Jung Bauermann ptrace_write_running, regs[0], regs[1]);
2571f7256e7SThiago Jung Bauermann
2581f7256e7SThiago Jung Bauermann /* Try to write to IAMR and UAMOR. */
2599a11f12eSAneesh Kumar K.V regs[2] = info->invalid_uamor;
2601f7256e7SThiago Jung Bauermann ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 3);
2611f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(!ret, &info->child_sync);
2621f7256e7SThiago Jung Bauermann
2631f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
2641f7256e7SThiago Jung Bauermann ptrace_write_running, regs[0], regs[1], regs[2]);
2651f7256e7SThiago Jung Bauermann
2661f7256e7SThiago Jung Bauermann /* Verify that all registers still have their expected values. */
2671f7256e7SThiago Jung Bauermann ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
2681f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2691f7256e7SThiago Jung Bauermann
2701f7256e7SThiago Jung Bauermann printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
2711f7256e7SThiago Jung Bauermann ptrace_read_running, regs[0], regs[1], regs[2]);
2721f7256e7SThiago Jung Bauermann
2731f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[0] != info->amr2, &info->child_sync);
2741f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
2751f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
2761f7256e7SThiago Jung Bauermann
2771f7256e7SThiago Jung Bauermann /* Wake up child so that it can verify AMR didn't change and wrap up. */
2781f7256e7SThiago Jung Bauermann ret = prod_child(&info->child_sync);
2791f7256e7SThiago Jung Bauermann PARENT_FAIL_IF(ret, &info->child_sync);
2801f7256e7SThiago Jung Bauermann
2811f7256e7SThiago Jung Bauermann ret = wait(&status);
2821f7256e7SThiago Jung Bauermann if (ret != pid) {
2831f7256e7SThiago Jung Bauermann printf("Child's exit status not captured\n");
2841f7256e7SThiago Jung Bauermann ret = TEST_PASS;
2851f7256e7SThiago Jung Bauermann } else if (!WIFEXITED(status)) {
2861f7256e7SThiago Jung Bauermann printf("Child exited abnormally\n");
2871f7256e7SThiago Jung Bauermann ret = TEST_FAIL;
2881f7256e7SThiago Jung Bauermann } else
2891f7256e7SThiago Jung Bauermann ret = WEXITSTATUS(status) ? TEST_FAIL : TEST_PASS;
2901f7256e7SThiago Jung Bauermann
2911f7256e7SThiago Jung Bauermann return ret;
2921f7256e7SThiago Jung Bauermann }
2931f7256e7SThiago Jung Bauermann
ptrace_pkey(void)2941f7256e7SThiago Jung Bauermann static int ptrace_pkey(void)
2951f7256e7SThiago Jung Bauermann {
2961f7256e7SThiago Jung Bauermann struct shared_info *info;
2971f7256e7SThiago Jung Bauermann int shm_id;
2981f7256e7SThiago Jung Bauermann int ret;
2991f7256e7SThiago Jung Bauermann pid_t pid;
3001f7256e7SThiago Jung Bauermann
3011f7256e7SThiago Jung Bauermann shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT);
3021f7256e7SThiago Jung Bauermann info = shmat(shm_id, NULL, 0);
3031f7256e7SThiago Jung Bauermann
3041f7256e7SThiago Jung Bauermann ret = init_child_sync(&info->child_sync);
3051f7256e7SThiago Jung Bauermann if (ret)
3061f7256e7SThiago Jung Bauermann return ret;
3071f7256e7SThiago Jung Bauermann
3081f7256e7SThiago Jung Bauermann pid = fork();
3091f7256e7SThiago Jung Bauermann if (pid < 0) {
3101f7256e7SThiago Jung Bauermann perror("fork() failed");
3111f7256e7SThiago Jung Bauermann ret = TEST_FAIL;
3121f7256e7SThiago Jung Bauermann } else if (pid == 0)
3131f7256e7SThiago Jung Bauermann ret = child(info);
3141f7256e7SThiago Jung Bauermann else
3151f7256e7SThiago Jung Bauermann ret = parent(info, pid);
3161f7256e7SThiago Jung Bauermann
3171f7256e7SThiago Jung Bauermann shmdt(info);
3181f7256e7SThiago Jung Bauermann
3191f7256e7SThiago Jung Bauermann if (pid) {
3201f7256e7SThiago Jung Bauermann destroy_child_sync(&info->child_sync);
3211f7256e7SThiago Jung Bauermann shmctl(shm_id, IPC_RMID, NULL);
3221f7256e7SThiago Jung Bauermann }
3231f7256e7SThiago Jung Bauermann
3241f7256e7SThiago Jung Bauermann return ret;
3251f7256e7SThiago Jung Bauermann }
3261f7256e7SThiago Jung Bauermann
main(int argc,char * argv[])3271f7256e7SThiago Jung Bauermann int main(int argc, char *argv[])
3281f7256e7SThiago Jung Bauermann {
3291f7256e7SThiago Jung Bauermann return test_harness(ptrace_pkey, "ptrace_pkey");
3301f7256e7SThiago Jung Bauermann }
331