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