xref: /linux/tools/testing/selftests/powerpc/dexcr/dexcr_test.c (revision ff2632d7d08edc11e8bd0629e9fcfebab25c78b4)
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  */
dexcr_prctl_onexec_test_child(unsigned long which,const char * status)16 static 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  */
dexcr_prctl_aspect_test(unsigned long which)48 static 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 
dexcr_prctl_ibrtpd_test(void)171 static int dexcr_prctl_ibrtpd_test(void)
172 {
173 	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_IBRTPD);
174 }
175 
dexcr_prctl_srapd_test(void)176 static int dexcr_prctl_srapd_test(void)
177 {
178 	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_SRAPD);
179 }
180 
dexcr_prctl_nphie_test(void)181 static int dexcr_prctl_nphie_test(void)
182 {
183 	return dexcr_prctl_aspect_test(PR_PPC_DEXCR_NPHIE);
184 }
185 
main(int argc,char * argv[])186 int 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 }
216