xref: /openbmc/linux/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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