File Index
Files and directories
Sign in
FILE

dexcr_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/powerpc/dexcr/dexcr_test.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2
  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 process
 15 */
 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 freely
 47 */
 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 be
192	 * invoked as the child of a particular test
193	 */
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 suite
209	 */
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}
~/ Read-only file preview.