brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · 7a86571 Raw
216 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 3#include <errno.h>4#include <fcntl.h>5#include <stdlib.h>6#include <string.h>7#include <sys/prctl.h>8#include <unistd.h>9 10#include "dexcr.h"11#include "utils.h"12 13/*14 * Helper function for testing the behaviour of a newly exec-ed process15 */16static int dexcr_prctl_onexec_test_child(unsigned long which, const char *status)17{18	unsigned long dexcr = mfspr(SPRN_DEXCR_RO);19	unsigned long aspect = pr_which_to_aspect(which);20	int ctrl = pr_get_dexcr(which);21 22	if (!strcmp(status, "set")) {23		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET),24				 "setting aspect across exec not applied");25 26		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC),27				 "setting aspect across exec not inherited");28 29		FAIL_IF_EXIT_MSG(!(aspect & dexcr), "setting aspect across exec did not take effect");30	} else if (!strcmp(status, "clear")) {31		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR),32				 "clearing aspect across exec not applied");33 34		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC),35				 "clearing aspect across exec not inherited");36 37		FAIL_IF_EXIT_MSG(aspect & dexcr, "clearing aspect across exec did not take effect");38	} else {39		FAIL_IF_EXIT_MSG(true, "unknown expected status");40	}41 42	return 0;43}44 45/*46 * Test that the given prctl value can be manipulated freely47 */48static int dexcr_prctl_aspect_test(unsigned long which)49{50	unsigned long aspect = pr_which_to_aspect(which);51	pid_t pid;52	int ctrl;53	int err;54	int errno_save;55 56	SKIP_IF_MSG(!dexcr_exists(), "DEXCR not supported");57	SKIP_IF_MSG(!pr_dexcr_aspect_supported(which), "DEXCR aspect not supported");58	SKIP_IF_MSG(!pr_dexcr_aspect_editable(which), "DEXCR aspect not editable with prctl");59 60	/* We reject invalid combinations of arguments */61	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR);62	errno_save = errno;63	FAIL_IF_MSG(err != -1, "simultaneous set and clear should be rejected");64	FAIL_IF_MSG(errno_save != EINVAL, "simultaneous set and clear should be rejected with EINVAL");65 66	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET_ONEXEC | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);67	errno_save = errno;68	FAIL_IF_MSG(err != -1, "simultaneous set and clear on exec should be rejected");69	FAIL_IF_MSG(errno_save != EINVAL, "simultaneous set and clear on exec should be rejected with EINVAL");70 71	/* We set the aspect */72	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET);73	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET failed");74 75	ctrl = pr_get_dexcr(which);76	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET), "config value not PR_PPC_DEXCR_CTRL_SET");77	FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_CLEAR, "config value unexpected clear flag");78	FAIL_IF_MSG(!(aspect & mfspr(SPRN_DEXCR_RO)), "setting aspect did not take effect");79 80	/* We clear the aspect */81	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR);82	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR failed");83 84	ctrl = pr_get_dexcr(which);85	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "config value not PR_PPC_DEXCR_CTRL_CLEAR");86	FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_SET, "config value unexpected set flag");87	FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "clearing aspect did not take effect");88 89	/* We make it set on exec (doesn't change our current value) */90	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET_ONEXEC);91	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET_ONEXEC failed");92 93	ctrl = pr_get_dexcr(which);94	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "process aspect should still be cleared");95	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_SET_ONEXEC");96	FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC, "config value unexpected clear on exec flag");97	FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "scheduling aspect to set on exec should not change it now");98 99	/* We make it clear on exec (doesn't change our current value) */100	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);101	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");102 103	ctrl = pr_get_dexcr(which);104	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "process aspect config should still be cleared");105	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC");106	FAIL_IF_MSG(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC, "config value unexpected set on exec flag");107	FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "process aspect should still be cleared");108 109	/* We allow setting the current and on-exec value in a single call */110	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);111	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");112 113	ctrl = pr_get_dexcr(which);114	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET), "config value not PR_PPC_DEXCR_CTRL_SET");115	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC");116	FAIL_IF_MSG(!(aspect & mfspr(SPRN_DEXCR_RO)), "process aspect should be set");117 118	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_CLEAR | PR_PPC_DEXCR_CTRL_SET_ONEXEC);119	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_CLEAR | PR_PPC_DEXCR_CTRL_SET_ONEXEC failed");120 121	ctrl = pr_get_dexcr(which);122	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR), "config value not PR_PPC_DEXCR_CTRL_CLEAR");123	FAIL_IF_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC), "config value not PR_PPC_DEXCR_CTRL_SET_ONEXEC");124	FAIL_IF_MSG(aspect & mfspr(SPRN_DEXCR_RO), "process aspect should be clear");125 126	/* Verify the onexec value is applied across exec */127	pid = fork();128	if (!pid) {129		char which_str[32] = {};130		char *args[] = { "dexcr_prctl_onexec_test_child", which_str, "set", NULL };131		unsigned int ctrl = pr_get_dexcr(which);132 133		sprintf(which_str, "%lu", which);134 135		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC),136				 "setting aspect on exec not copied across fork");137 138		FAIL_IF_EXIT_MSG(mfspr(SPRN_DEXCR_RO) & aspect,139				 "setting aspect on exec wrongly applied to fork");140 141		execve("/proc/self/exe", args, NULL);142		_exit(errno);143	}144	await_child_success(pid);145 146	err = pr_set_dexcr(which, PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC);147	FAIL_IF_MSG(err, "PR_PPC_DEXCR_CTRL_SET | PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC failed");148 149	pid = fork();150	if (!pid) {151		char which_str[32] = {};152		char *args[] = { "dexcr_prctl_onexec_test_child", which_str, "clear", NULL };153		unsigned int ctrl = pr_get_dexcr(which);154 155		sprintf(which_str, "%lu", which);156 157		FAIL_IF_EXIT_MSG(!(ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC),158				 "clearing aspect on exec not copied across fork");159 160		FAIL_IF_EXIT_MSG(!(mfspr(SPRN_DEXCR_RO) & aspect),161				 "clearing aspect on exec wrongly applied to fork");162 163		execve("/proc/self/exe", args, NULL);164		_exit(errno);165	}166	await_child_success(pid);167 168	return 0;169}170 171static int dexcr_prctl_ibrtpd_test(void)172{173	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_IBRTPD);174}175 176static int dexcr_prctl_srapd_test(void)177{178	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_SRAPD);179}180 181static int dexcr_prctl_nphie_test(void)182{183	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_NPHIE);184}185 186int main(int argc, char *argv[])187{188	int err = 0;189 190	/*191	 * Some tests require checking what happens across exec, so we may be192	 * invoked as the child of a particular test193	 */194	if (argc > 1) {195		if (argc == 3 && !strcmp(argv[0], "dexcr_prctl_onexec_test_child")) {196			unsigned long which;197 198			err = parse_ulong(argv[1], strlen(argv[1]), &which, 10);199			FAIL_IF_MSG(err, "failed to parse which value for child");200 201			return dexcr_prctl_onexec_test_child(which, argv[2]);202		}203 204		FAIL_IF_MSG(true, "unknown test case");205	}206 207	/*208	 * Otherwise we are the main test invocation and run the full suite209	 */210	err |= test_harness(dexcr_prctl_ibrtpd_test, "dexcr_prctl_ibrtpd");211	err |= test_harness(dexcr_prctl_srapd_test, "dexcr_prctl_srapd");212	err |= test_harness(dexcr_prctl_nphie_test, "dexcr_prctl_nphie");213 214	return err;215}216