1 /*
2  * Copyright (C) 2013-2021 Canonical, Ltd.
3  * Copyright (C) 2021 Colin Ian King
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * This code is a complete clean re-write of the stress tool by
20  * Colin Ian King <colin.king@canonical.com> and attempts to be
21  * backwardly compatible with the stress tool by Amos Waterland
22  * <apw@rossby.metr.ou.edu> but has more stress tests and more
23  * functionality.
24  *
25  */
26 #include "stress-ng.h"
27 
28 static const stress_help_t help[] = {
29 	{ NULL,	"procfs N",	"start N workers reading portions of /proc" },
30 	{ NULL,	"procfs-ops N",	"stop procfs workers after N bogo read operations" },
31 	{ NULL,	NULL,		NULL }
32 };
33 
34 #if defined(HAVE_SYS_PRCTL_H) &&		\
35     defined(HAVE_PRCTL) &&			\
36     (defined(PR_SET_PDEATHSIG) ||		/* 1 */ \
37      defined(PR_GET_PDEATHSIG) ||		/* 2 */	\
38      defined(PR_GET_DUMPABLE) ||		/* 3 */ \
39      defined(PR_SET_DUMPABLE) ||		/* 4 */ \
40      defined(PR_GET_UNALIGN)) ||		/* 5 */ \
41      defined(PR_SET_UNALIGN) ||			/* 6 */ \
42      defined(PR_GET_KEEPCAPS) ||		/* 7 */ \
43      defined(PR_SET_KEEPCAPS) ||		/* 8 */ \
44      defined(PR_GET_FPEMU) ||			/* 9 */ \
45      defined(PR_SET_FPEMU) ||			/* 10 */ \
46      defined(PR_GET_FPEXC) ||			/* 11 */ \
47      defined(PR_SET_FPEXC) ||			/* 12 */ \
48      defined(PR_GET_TIMING) ||			/* 13 */ \
49      defined(PR_SET_TIMING) ||			/* 14 */ \
50      defined(PR_SET_NAME) ||			/* 15 */ \
51      defined(PR_GET_NAME) ||			/* 16 */ \
52      defined(PR_GET_ENDIAN) ||			/* 19 */ \
53      defined(PR_SET_ENDIAN) ||			/* 20 */ \
54      defined(PR_GET_SECCOMP) ||			/* 21 */ \
55      defined(PR_SET_SECCOMP) ||			/* 22 */ \
56      defined(PR_CAPBSET_READ) ||		/* 23 */ \
57      defined(PR_CAPBSET_DROP) ||		/* 24 */ \
58      defined(PR_GET_TSC) ||			/* 25 */ \
59      defined(PR_SET_TSC) ||			/* 26 */ \
60      defined(PR_GET_SECUREBITS) ||		/* 27 */ \
61      defined(PR_SET_SECUREBITS) ||		/* 28 */ \
62      defined(PR_GET_TIMERSLACK) ||		/* 29 */ \
63      defined(PR_SET_TIMERSLACK) ||		/* 30 */ \
64      defined(PR_TASK_PERF_EVENTS_DISABLE) ||	/* 31 */ \
65      defined(PR_TASK_PERF_EVENTS_ENABLE) ||	/* 32 */ \
66      defined(PR_MCE_KILL) ||			/* 33 */ \
67      defined(PR_MCE_KILL_GET) ||		/* 34 */ \
68      defined(PR_SET_MM) ||			/* 35 */ \
69      defined(PR_SET_CHILD_SUBREAPER) ||		/* 36 */ \
70      defined(PR_GET_CHILD_SUBREAPER) ||		/* 37 */ \
71      defined(PR_SET_NO_NEW_PRIVS) ||		/* 38 */ \
72      defined(PR_GET_NO_NEW_PRIVS) ||		/* 39 */ \
73      defined(PR_GET_TID_ADDRESS) ||		/* 40 */ \
74      defined(PR_SET_THP_DISABLE) ||		/* 41 */ \
75      defined(PR_GET_THP_DISABLE) ||		/* 42 */ \
76      defined(PR_MPX_ENABLE_MANAGEMENT) ||	/* 43 */ \
77      defined(PR_MPX_DISABLE_MANAGEMENT) ||	/* 44 */ \
78      defined(PR_SET_FP_MODE) ||			/* 45 */ \
79      defined(PR_GET_FP_MODE) ||			/* 46 */ \
80      defined(PR_CAP_AMBIENT) ||			/* 47 */ \
81      defined(PR_SVE_SET_VL) ||			/* 50 */ \
82      defined(PR_SVE_GET_VL) ||			/* 51 */ \
83      defined(PR_GET_SPECULATION_CTRL) || 	/* 52 */ \
84      defined(PR_SET_SPECULATION_CTRL) || 	/* 53 */ \
85      defined(PR_PAC_RESET_KEYS) ||		/* 54 */ \
86      defined(PR_SET_TAGGED_ADDR_CTRL) ||	/* 55 */ \
87      defined(PR_GET_TAGGED_ADDR_CTRL) ||	/* 56 */ \
88      defined(PR_SET_IO_FLUSHER) ||		/* 57 */ \
89      defined(PR_GET_IO_FLUSHER) ||		/* 58 */ \
90      defined(PR_SET_SYSCALL_USER_DISPATCH) ||	/* 59 */ \
91      defined(PR_PAC_SET_ENABLED_KEYS) ||	/* 60 */ \
92      defined(PR_PAC_GET_ENABLED_KEYS) ||	/* 61 */ \
93      defined(PR_SCHED_CORE) ||			/* 62 */ \
94      defined(PR_SET_PTRACER)			/* 0x59616d61 */
95 
96 #if defined(PR_SET_MM) &&		\
97     defined(PR_SET_MM_AUXV)
98 
99 /*
100  *  getauxv_addr()
101  *	find the address of the auxv vector. This
102  *	is located at the end of the environment.
103  *	Returns NULL if not found.
104  */
getauxv_addr(void)105 static inline void *getauxv_addr(void)
106 {
107 	char **env = environ;
108 
109 	while (env && *env++)
110 		;
111 
112 	return (void *)env;
113 }
114 #endif
115 
116 /*
117  *  stress_arch_prctl()
118  *	exercise arch_prctl(), currently just
119  *	x86-64 for now.
120  */
stress_arch_prctl(void)121 static inline void stress_arch_prctl(void)
122 {
123 #if defined(HAVE_ASM_PRCTL_H) &&		\
124     defined(HAVE_SYS_PRCTL_H) &&		\
125     defined(ARCH_GET_CPUID) &&			\
126     (defined(__x86_64__) || defined(__x86_64))
127 	{
128 		int ret;
129 
130 		/* GET_CPUID setting, 2nd arg is ignored */
131 		ret = shim_arch_prctl(ARCH_GET_CPUID, 0);
132 #if defined(ARCH_SET_CPUID)
133 		if (ret >= 0)
134 			ret = shim_arch_prctl(ARCH_SET_CPUID, (unsigned long)ret);
135 		(void)ret;
136 #endif
137 	}
138 #endif
139 
140 #if defined(HAVE_ASM_PRCTL_H) &&		\
141     defined(HAVE_SYS_PRCTL_H) &&		\
142     defined(ARCH_GET_FS) &&			\
143     (defined(__x86_64__) || defined(__x86_64))
144 	{
145 		int ret;
146 		unsigned long fs;
147 
148 		ret = shim_arch_prctl(ARCH_GET_FS, (unsigned long)&fs);
149 #if defined(ARCH_SET_FS)
150 		if (ret == 0)
151 			ret = shim_arch_prctl(ARCH_SET_FS, fs);
152 		(void)ret;
153 #endif
154 	}
155 #endif
156 
157 #if defined(HAVE_ASM_PRCTL_H) &&		\
158     defined(HAVE_SYS_PRCTL_H) &&		\
159     defined(ARCH_GET_GS) &&			\
160     (defined(__x86_64__) || defined(__x86_64))
161 	{
162 		int ret;
163 		unsigned long gs;
164 
165 		ret = shim_arch_prctl(ARCH_GET_GS, (unsigned long)&gs);
166 #if defined(ARCH_SET_GS)
167 		if (ret == 0)
168 			ret = shim_arch_prctl(ARCH_SET_GS, gs);
169 		(void)ret;
170 #endif
171 	}
172 #endif
173 
174 #if defined(HAVE_ASM_PRCTL_H) &&		\
175     defined(HAVE_SYS_PRCTL_H) &&		\
176     defined(ARCH_GET_XCOMP_SUPP) &&		\
177     (defined(__x86_64__) || defined(__x86_64))
178 	{
179 		uint64_t features;
180 		int ret;
181 
182 		ret = shim_arch_prctl(ARCH_GET_XCOMP_SUPP, (unsigned long)&features);
183 		(void)ret;
184 	}
185 #endif
186 #if defined(HAVE_ASM_PRCTL_H) &&		\
187     defined(HAVE_SYS_PRCTL_H) &&		\
188     defined(ARCH_GET_XCOMP_PERM) &&		\
189     (defined(__x86_64__) || defined(__x86_64))
190 	{
191 		uint64_t features;
192 		int ret;
193 
194 		ret = shim_arch_prctl(ARCH_GET_XCOMP_PERM, (unsigned long)&features);
195 		(void)ret;
196 	}
197 #endif
198 #if defined(HAVE_ASM_PRCTL_H) &&		\
199     defined(HAVE_SYS_PRCTL_H) &&		\
200     defined(ARCH_REQ_XCOMP_PERM) &&		\
201     (defined(__x86_64__) || defined(__x86_64))
202 	{
203 		unsigned long idx;
204 		int ret;
205 
206 		for (idx = 0; idx < 255; idx++) {
207 			errno = 0;
208 			ret = shim_arch_prctl(ARCH_REQ_XCOMP_PERM, idx);
209 			if ((ret < 0) && (errno == -EINVAL))
210 				break;
211 		}
212 	}
213 #endif
214 }
215 
216 #if defined(PR_SET_SYSCALL_USER_DISPATCH) &&	\
217     defined(PR_SYS_DISPATCH_ON)	&&		\
218     defined(PR_SYS_DISPATCH_OFF) &&		\
219     defined(__NR_kill) &&			\
220     defined(STRESS_ARCH_X86)
221 
222 typedef struct {
223 	int  sig;	/* signal number */
224 	int  syscall;	/* syscall number */
225 	int  code;	/* code, should be 2 */
226 	bool handled;	/* set to true if we handle SIGSYS */
227 	char selector;	/* prctl mode selector byte */
228 } stress_prctl_sigsys_info_t;
229 
230 static stress_prctl_sigsys_info_t prctl_sigsys_info;
231 
232 #define PRCTL_SYSCALL_OFF()	\
233 	do { prctl_sigsys_info.selector = SYSCALL_DISPATCH_FILTER_ALLOW; } while (0)
234 #define PRCTL_SYSCALL_ON()	\
235 	do { prctl_sigsys_info.selector = SYSCALL_DISPATCH_FILTER_BLOCK; } while (0)
236 
stress_prctl_sigsys_handler(int sig,siginfo_t * info,void * ucontext)237 static void stress_prctl_sigsys_handler(int sig, siginfo_t *info, void *ucontext)
238 {
239 	(void)ucontext;
240 
241 	/*
242 	 *  Turn syscall emulation off otherwise we end up
243 	 *  producing another SIGSYS when we do a signal
244 	 *  return
245 	 */
246 	PRCTL_SYSCALL_OFF();
247 
248 	/* Save state */
249 	prctl_sigsys_info.sig = sig;
250 	prctl_sigsys_info.syscall = info->si_syscall;
251 	prctl_sigsys_info.code = info->si_code;
252 	prctl_sigsys_info.handled = true;
253 }
254 
255 /*
256  *  stress_prctl_syscall_user_dispatch()
257  * 	exercise syscall emulation by trapping a kill() system call
258  */
stress_prctl_syscall_user_dispatch(const stress_args_t * args)259 static int stress_prctl_syscall_user_dispatch(const stress_args_t *args)
260 {
261 	int ret, rc = EXIT_FAILURE;
262 	struct sigaction action, oldaction;
263 	const pid_t pid = getpid();
264 
265 	(void)memset(&action, 0, sizeof(action));
266 	(void)sigemptyset(&action.sa_mask);
267 	action.sa_sigaction = stress_prctl_sigsys_handler;
268 	action.sa_flags = SA_SIGINFO;
269 
270 	ret = sigaction(SIGSYS, &action, &oldaction);
271 	if (ret < 0)
272 		return 0;
273 
274 	(void)memset(&prctl_sigsys_info, 0, sizeof(prctl_sigsys_info));
275 
276 	/* syscall emulation off */
277 	PRCTL_SYSCALL_OFF();
278 
279 	ret = prctl(PR_SET_SYSCALL_USER_DISPATCH,
280 		PR_SYS_DISPATCH_ON, 0, 0, &prctl_sigsys_info.selector);
281 	if (ret < 0) {
282 		/* EINVAL will occur on kernels where this is not supported */
283 		if ((errno == EINVAL) || (errno == ENOSYS))
284 			return 0;
285 		pr_err("%s: prctl PR_SET_SYSCALL_USER_DISPATCH enable failed, errno=%d (%s)\n",
286 			args->name, errno, strerror(errno));
287 		goto err;
288 	}
289 
290 	/* syscall emulation on */
291 	PRCTL_SYSCALL_ON();
292 	(void)kill(pid, 0);
293 
294 	/* Turn off */
295 	ret = prctl(PR_SET_SYSCALL_USER_DISPATCH,
296 		PR_SYS_DISPATCH_OFF, 0, 0, 0);
297 	if (ret < 0) {
298 		pr_err("%s: prctl PR_SET_SYSCALL_USER_DISPATCH disable failed, errno=%d (%s)\n",
299 			args->name, errno, strerror(errno));
300 		goto err;
301 	}
302 
303 	if (!prctl_sigsys_info.handled) {
304 		pr_err("%s: prctl PR_SET_SYSCALL_USER_DISPATCH syscall emulation failed\n",
305 			args->name);
306 		goto err;
307 	}
308 
309 	if (prctl_sigsys_info.syscall != __NR_kill) {
310 		pr_err("%s: prctl PR_SET_SYSCALL_USER_DISPATCH syscall expected syscall 0x%x, got 0x%x instead\n",
311 			args->name, __NR_kill, prctl_sigsys_info.syscall);
312 		goto err;
313 	}
314 
315 	rc = EXIT_SUCCESS;
316 err:
317 	ret = sigaction(SIGSYS, &oldaction, NULL);
318 	(void)ret;
319 
320 	return rc;
321 }
322 #else
stress_prctl_syscall_user_dispatch(const stress_args_t * args)323 static int stress_prctl_syscall_user_dispatch(const stress_args_t *args)
324 {
325 	(void)args;
326 
327 	return 0;
328 }
329 #endif
330 
stress_prctl_child(const stress_args_t * args,const pid_t mypid)331 static int stress_prctl_child(const stress_args_t *args, const pid_t mypid)
332 {
333 	int ret;
334 
335 	(void)args;
336 	(void)mypid;
337 
338 #if defined(PR_CAP_AMBIENT)
339 	/* skip for now */
340 #endif
341 #if defined(PR_CAPBSET_READ) &&	\
342     defined(CAP_CHOWN)
343 	ret = prctl(PR_CAPBSET_READ, CAP_CHOWN);
344 	(void)ret;
345 #endif
346 
347 #if defined(PR_CAPBSET_DROP) &&	\
348     defined(CAP_CHOWN)
349 	ret = prctl(PR_CAPBSET_DROP, CAP_CHOWN);
350 	(void)ret;
351 #endif
352 
353 #if defined(PR_GET_CHILD_SUBREAPER)
354 	{
355 		int reaper = 0;
356 
357 		ret = prctl(PR_GET_CHILD_SUBREAPER, &reaper);
358 		(void)ret;
359 
360 #if defined(PR_SET_CHILD_SUBREAPER)
361 		if (ret == 0) {
362 			ret = prctl(PR_SET_CHILD_SUBREAPER, !reaper);
363 			(void)ret;
364 			ret = prctl(PR_SET_CHILD_SUBREAPER, reaper);
365 			(void)ret;
366 		}
367 #endif
368 	}
369 #endif
370 
371 #if defined(PR_GET_DUMPABLE)
372 	{
373 		ret = prctl(PR_GET_DUMPABLE);
374 		(void)ret;
375 
376 #if defined(PR_SET_DUMPABLE)
377 		if (ret >= 0) {
378 			ret = prctl(PR_SET_DUMPABLE, ret);
379 			(void)ret;
380 		}
381 #endif
382 	}
383 #endif
384 
385 #if defined(PR_GET_ENDIAN)
386 	/* PowerPC only, but try it on all arches */
387 	{
388 		int endian;
389 
390 		ret = prctl(PR_GET_ENDIAN, &endian);
391 		(void)ret;
392 
393 #if defined(PR_SET_ENDIAN)
394 		if (ret == 0) {
395 			ret = prctl(PR_SET_ENDIAN, endian);
396 			(void)ret;
397 		}
398 #endif
399 	}
400 #endif
401 
402 #if defined(PR_GET_FP_MODE)
403 	/* MIPS only, but try it on all arches */
404 	{
405 		int mode;
406 
407 		mode = prctl(PR_GET_FP_MODE);
408 		(void)mode;
409 
410 #if defined(PR_SET_FP_MODE)
411 		if (mode >= 0) {
412 			ret = prctl(PR_SET_FP_MODE, mode);
413 			(void)ret;
414 		}
415 #endif
416 	}
417 #endif
418 
419 #if defined(PR_SVE_GET_VL)
420 	/* Get vector length */
421 	{
422 		int vl;
423 
424 		vl = prctl(PR_SVE_GET_VL);
425 		(void)vl;
426 
427 #if defined(PR_SVE_SET_VL)
428 		if (vl >= 0) {
429 			ret = prctl(PR_SVE_SET_VL, vl);
430 			(void)ret;
431 		}
432 #endif
433 	}
434 #endif
435 
436 #if defined(PR_GET_TAGGED_ADDR_CTRL)
437 	{
438 		int ctrl;
439 
440 		/* exercise invalid args */
441 		ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, ~0, ~0, ~0, ~0);
442 		(void)ctrl;
443 		ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
444 		(void)ctrl;
445 
446 #if defined(PR_SET_TAGGED_ADDR_CTRL)
447 		if (ctrl >= 0) {
448 			/* exercise invalid args */
449 			ret = prctl(PR_SET_TAGGED_ADDR_CTRL, ~0, ~0, ~0, ~0);
450 			(void)ret;
451 			ret = prctl(PR_SET_TAGGED_ADDR_CTRL, ctrl, 0, 0, 0);
452 			(void)ret;
453 		}
454 #endif
455 	}
456 #endif
457 
458 #if defined(PR_GET_FPEMU)
459 	/* ia64 only, but try it on all arches */
460 	{
461 		int control;
462 
463 		ret = prctl(PR_GET_FPEMU, &control);
464 		(void)ret;
465 
466 #if defined(PR_SET_FPEMU)
467 		if (ret == 0) {
468 			ret = prctl(PR_SET_FPEMU, control);
469 			(void)ret;
470 		}
471 #endif
472 	}
473 #endif
474 
475 #if defined(PR_GET_FPEXC)
476 	/* PowerPC only, but try it on all arches */
477 	{
478 		int mode;
479 
480 		ret = prctl(PR_GET_FPEXC, &mode);
481 		(void)ret;
482 
483 #if defined(PR_SET_FPEXC)
484 		if (ret == 0) {
485 			ret = prctl(PR_SET_FPEXC, mode);
486 			(void)ret;
487 		}
488 #endif
489 	}
490 #endif
491 
492 #if defined(PR_GET_KEEPCAPS)
493 	{
494 		int flag = 0;
495 
496 		ret = prctl(PR_GET_KEEPCAPS, &flag);
497 		(void)ret;
498 
499 #if defined(PR_SET_KEEPCAPS)
500 		if (ret == 0) {
501 			ret = prctl(PR_SET_KEEPCAPS, !flag);
502 			(void)ret;
503 			ret = prctl(PR_SET_KEEPCAPS, flag);
504 			(void)ret;
505 		}
506 #endif
507 	}
508 #endif
509 
510 #if defined(PR_MCE_KILL_GET)
511 	/* exercise invalid args */
512 	ret = prctl(PR_MCE_KILL_GET, ~0, ~0, ~0, ~0);
513 	(void)ret;
514 	/* now exercise what is expected */
515 	ret = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0);
516 	(void)ret;
517 #endif
518 
519 #if defined(PR_MCE_KILL)
520 	/* exercise invalid args */
521 	ret = prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, ~0, ~0, ~0);
522 	(void)ret;
523 	ret = prctl(PR_MCE_KILL, PR_MCE_KILL_SET, ~0, ~0, ~0);
524 	(void)ret;
525 	ret = prctl(PR_MCE_KILL, ~0, ~0, ~0, ~0);
526 	(void)ret;
527 	/* now exercise what is expected */
528 	ret = prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0, 0, 0);
529 	(void)ret;
530 #endif
531 
532 #if defined(PR_SET_MM) &&	\
533     defined(PR_SET_MM_BRK)
534 	ret = prctl(PR_SET_MM, PR_SET_MM_BRK, sbrk(0), 0, 0);
535 	(void)ret;
536 #endif
537 
538 #if defined(PR_SET_MM) &&		\
539     defined(PR_SET_MM_START_CODE) &&	\
540     defined(PR_SET_MM_END_CODE)
541 	{
542 		char *start, *end;
543 		const intptr_t mask = ~((intptr_t)args->page_size - 1);
544 		intptr_t addr;
545 
546 		(void)stress_text_addr(&start, &end);
547 
548 		addr = ((intptr_t)start) & mask;
549 		ret = prctl(PR_SET_MM, PR_SET_MM_START_CODE, addr, 0, 0);
550 		(void)ret;
551 
552 		addr = ((intptr_t)end) & mask;
553 		ret = prctl(PR_SET_MM, PR_SET_MM_END_CODE, addr, 0, 0);
554 		(void)ret;
555 	}
556 #endif
557 
558 #if defined(PR_SET_MM) &&		\
559     defined(PR_SET_MM_ENV_START)
560 	{
561 		const intptr_t mask = ~((intptr_t)args->page_size - 1);
562 		const intptr_t addr = ((intptr_t)environ) & mask;
563 
564 		ret = prctl(PR_SET_MM, PR_SET_MM_ENV_START, addr, 0, 0);
565 		(void)ret;
566 	}
567 #endif
568 
569 #if defined(PR_SET_MM) &&		\
570     defined(PR_SET_MM_AUXV)
571 	{
572 		void *auxv = getauxv_addr();
573 
574 		if (auxv) {
575 			ret = prctl(PR_SET_MM, PR_SET_MM_AUXV, auxv, 0, 0);
576 			(void)ret;
577 		}
578 	}
579 #endif
580 
581 #if defined(PR_MPX_ENABLE_MANAGEMENT)
582 	/* no longer implemented, use invalid args to force -EINVAL */
583 	ret = prctl(PR_MPX_ENABLE_MANAGEMENT, ~0, ~0, ~0, ~0);
584 	(void)ret;
585 #endif
586 
587 #if defined(PR_MPX_DISABLE_MANAGEMENT)
588 	/* no longer implemented, use invalid args to force -EINVAL */
589 	ret = prctl(PR_MPX_DISABLE_MANAGEMENT, ~0, ~0, ~0, ~0);
590 	(void)ret;
591 #endif
592 
593 #if defined(PR_GET_NAME)
594 	{
595 		char name[17];
596 
597 		(void)memset(name, 0, sizeof name);
598 
599 		ret = prctl(PR_GET_NAME, name);
600 		(void)ret;
601 
602 #if defined(PR_SET_NAME)
603 		if (ret == 0) {
604 			ret = prctl(PR_SET_NAME, name);
605 			(void)ret;
606 		}
607 #endif
608 	}
609 #endif
610 
611 #if defined(PR_GET_NO_NEW_PRIVS)
612 	{
613 		ret = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
614 		(void)ret;
615 
616 #if defined(PR_SET_NO_NEW_PRIVS)
617 		if (ret >= 0) {
618 			/* exercise invalid args */
619 			ret = prctl(PR_SET_NO_NEW_PRIVS, ret, ~0, ~0, ~0);
620 			(void)ret;
621 			/* now exercise what is expected */
622 			ret = prctl(PR_SET_NO_NEW_PRIVS, ret, 0, 0, 0);
623 			(void)ret;
624 		}
625 #endif
626 	}
627 #endif
628 
629 #if defined(PR_GET_PDEATHSIG)
630 	{
631 		int sig;
632 
633 		ret = prctl(PR_GET_PDEATHSIG, &sig);
634 		(void)ret;
635 
636 #if defined(PR_SET_PDEATHSIG)
637 		if (ret == 0) {
638 			/* Exercise invalid signal */
639 			ret = prctl(PR_SET_PDEATHSIG, 0x10000);
640 			(void)ret;
641 			ret = prctl(PR_SET_PDEATHSIG, sig);
642 			(void)ret;
643 		}
644 #endif
645 	}
646 #endif
647 
648 #if defined(PR_SET_PTRACER)
649 	{
650 		ret = prctl(PR_SET_PTRACER, mypid, 0, 0, 0);
651 		(void)ret;
652 #if defined(PR_SET_PTRACER_ANY)
653 		ret = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
654 		(void)ret;
655 #endif
656 		ret = prctl(PR_SET_PTRACER, 0, 0, 0, 0);
657 		(void)ret;
658 	}
659 #endif
660 
661 #if defined(PR_GET_SECCOMP)
662 	{
663 		ret = prctl(PR_GET_SECCOMP);
664 		(void)ret;
665 
666 #if defined(PR_SET_SECCOMP)
667 	/* skip this for the moment */
668 #endif
669 	}
670 #endif
671 
672 #if defined(PR_GET_SECUREBITS)
673 	{
674 		ret = prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);
675 		(void)ret;
676 
677 #if defined(PR_SET_SECUREBITS)
678 		if (ret >= 0) {
679 			ret = prctl(PR_SET_SECUREBITS, ret, 0, 0, 0);
680 			(void)ret;
681 		}
682 #endif
683 	}
684 #endif
685 
686 #if defined(PR_GET_THP_DISABLE)
687 	{
688 		ret = prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0);
689 		(void)ret;
690 
691 #if defined(PR_SET_THP_DISABLE)
692 		if (ret >= 0) {
693 			/* exercise invalid args */
694 			ret = prctl(PR_SET_THP_DISABLE, 0, 0, ~0, ~0);
695 			(void)ret;
696 			/* now exercise what is expected */
697 			ret = prctl(PR_SET_THP_DISABLE, 0, 0, 0, 0);
698 			(void)ret;
699 		}
700 #endif
701 	}
702 #endif
703 
704 #if defined(PR_TASK_PERF_EVENTS_DISABLE)
705 	ret = prctl(PR_TASK_PERF_EVENTS_DISABLE);
706 	(void)ret;
707 #endif
708 
709 #if defined(PR_TASK_PERF_EVENTS_ENABLE)
710 	ret = prctl(PR_TASK_PERF_EVENTS_ENABLE);
711 	(void)ret;
712 #endif
713 
714 #if defined(PR_GET_TID_ADDRESS)
715 	{
716 		uint64_t val;
717 
718 		ret = prctl(PR_GET_TID_ADDRESS, &val);
719 		(void)ret;
720 	}
721 #endif
722 
723 #if defined(PR_GET_TIMERSLACK)
724 	{
725 		int slack;
726 
727 		slack = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0);
728 		(void)slack;
729 
730 #if defined(PR_SET_TIMERSLACK)
731 		if (slack >= 0) {
732 			/* Zero timer slack will set to default timer slack */
733 			ret = prctl(PR_SET_TIMERSLACK, 0, 0, 0, 0);
734 			(void)ret;
735 			/* And restore back to original setting */
736 			ret = prctl(PR_SET_TIMERSLACK, slack, 0, 0, 0);
737 			(void)ret;
738 		}
739 #endif
740 	}
741 #endif
742 
743 #if defined(PR_GET_TIMING)
744 	{
745 		ret = prctl(PR_GET_TIMING, 0, 0, 0, 0);
746 		(void)ret;
747 
748 #if defined(PR_SET_TIMING)
749 		if (ret >= 0) {
750 			ret = prctl(PR_SET_TIMING, ret, 0, 0, 0);
751 			(void)ret;
752 		}
753 #endif
754 	}
755 #endif
756 
757 #if defined(PR_GET_TSC)
758 	{
759 		/* x86 only, but try it on all arches */
760 		int state;
761 
762 		ret = prctl(PR_GET_TSC, &state, 0, 0, 0);
763 		(void)ret;
764 
765 #if defined(PR_SET_TSC)
766 		if (ret == 0) {
767 			ret = prctl(PR_SET_TSC, state, 0, 0, 0);
768 			(void)ret;
769 		}
770 #endif
771 	}
772 #endif
773 
774 #if defined(PR_GET_UNALIGN)
775 	{
776 		/* ia64, parisc, powerpc, alpha, sh, tile, but try it on all arches */
777 		unsigned int control;
778 
779 		ret = prctl(PR_GET_UNALIGN, &control, 0, 0, 0);
780 		(void)ret;
781 
782 #if defined(PR_SET_UNALIGN)
783 		if (ret == 0) {
784 			ret = prctl(PR_SET_UNALIGN, control, 0, 0, 0);
785 			(void)ret;
786 		}
787 #endif
788 	}
789 #endif
790 
791 #if defined(PR_GET_SPECULATION_CTRL)
792 	{
793 		int val;
794 
795 		/* exercise invalid args */
796 		ret = prctl(PR_GET_SPECULATION_CTRL, ~0, ~0, ~0, ~0);
797 		(void)ret;
798 
799 #if defined(PR_SPEC_STORE_BYPASS)
800 		val = prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0);
801 		(void)val;
802 
803 		if (val & PR_SPEC_PRCTL) {
804 			val &= ~PR_SPEC_PRCTL;
805 #if defined(PR_SPEC_ENABLE)
806 
807 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
808 			(void)ret;
809 #endif
810 #if defined(PR_SPEC_DISABLE)
811 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
812 			(void)ret;
813 #endif
814 			/* ..and restore */
815 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, val, 0, 0);
816 			(void)ret;
817 #endif
818 		}
819 
820 #if defined(PR_SPEC_INDIRECT_BRANCH)
821 		val = prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
822 		if (val & PR_SPEC_PRCTL) {
823 			val &= ~PR_SPEC_PRCTL;
824 #if defined(PR_SPEC_ENABLE)
825 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
826 			(void)ret;
827 #endif
828 #if defined(PR_SPEC_DISABLE)
829 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
830 			(void)ret;
831 #endif
832 			/* ..and restore */
833 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, val, 0, 0);
834 			(void)ret;
835 		}
836 #endif
837 
838 #if defined(PR_SPEC_L1D_FLUSH)
839 		val = prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, 0, 0, 0);
840 		if (val & PR_SPEC_PRCTL) {
841 			val &= ~PR_SPEC_PRCTL;
842 #if defined(PR_SPEC_ENABLE)
843 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_ENABLE, 0, 0);
844 			(void)ret;
845 #endif
846 #if defined(PR_SPEC_DISABLE)
847 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_DISABLE, 0, 0);
848 			(void)ret;
849 #endif
850 			/* ..and restore */
851 			ret = prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, val, 0, 0);
852 			(void)ret;
853 		}
854 #endif
855 	}
856 #endif
857 
858 #if defined(PR_SET_SPECULATION_CTRL)
859 	{
860 		/* exercise invalid args */
861 		ret = prctl(PR_SET_SPECULATION_CTRL, ~0, ~0, ~0, ~0);
862 		(void)ret;
863 	}
864 #endif
865 
866 #if defined(PR_GET_IO_FLUSHER)
867 	{
868 		ret = prctl(PR_GET_IO_FLUSHER, 0, 0, 0, 0);
869 		(void)ret;
870 
871 #if defined(PR_SET_IO_FLUSHER)
872 		ret = prctl(PR_SET_IO_FLUSHER, ret, 0, 0, 0);
873 		(void)ret;
874 #endif
875 	}
876 #endif
877 
878 #if defined(PR_SCHED_CORE) &&	\
879     defined(PR_SCHED_CORE_GET)
880 	{
881 		unsigned long cookie = 0;
882 		const pid_t bad_pid = stress_get_unused_pid_racy(false);
883 
884 		ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, 0, SHIM_PIDTYPE_PID, &cookie);
885 		(void)ret;
886 		ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, getpid(), SHIM_PIDTYPE_PID, &cookie);
887 		(void)ret;
888 		ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, bad_pid, SHIM_PIDTYPE_PID, &cookie);
889 		(void)ret;
890 	}
891 #endif
892 
893 #if defined(PR_SCHED_CORE) &&		\
894     defined(PR_SCHED_CORE_CREATE) &&	\
895     defined(PR_SCHED_CORE_SHARE_TO)
896 	{
897 		const pid_t ppid = getppid();
898 
899 		ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, ppid, SHIM_PIDTYPE_PID, 0);
900 		(void)ret;
901 	}
902 #endif
903 
904 #if defined(PR_SCHED_CORE) &&		\
905     defined(PR_SCHED_CORE_CREATE) &&	\
906     defined(PR_SCHED_CORE_SHARE_FROM)
907 	{
908 		const pid_t ppid = getppid();
909 
910 		ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, ppid, SHIM_PIDTYPE_PID, 0);
911 		(void)ret;
912 	}
913 #endif
914 
915 #if defined(PR_PAC_RESET_KEYS)
916 	{
917 		/* exercise invalid args */
918 		ret = prctl(PR_PAC_RESET_KEYS, ~0, ~0, ~0, ~0);
919 		(void)ret;
920 	}
921 #endif
922 	stress_arch_prctl();
923 
924 	stress_prctl_syscall_user_dispatch(args);
925 
926 	/* exercise bad ptrcl command */
927 	{
928 		ret = prctl(-1, ~0, ~0, ~0, ~0);
929 		(void)ret;
930 		ret = prctl(0xf00000, ~0, ~0, ~0, ~0);
931 		(void)ret;
932 	}
933 
934 	(void)ret;
935 
936 	return 0;
937 }
938 
939 /*
940  *  stress_prctl()
941  *	stress seccomp
942  */
stress_prctl(const stress_args_t * args)943 static int stress_prctl(const stress_args_t *args)
944 {
945 	stress_set_proc_state(args->name, STRESS_STATE_RUN);
946 
947 	do {
948 		pid_t pid;
949 again:
950 		pid = fork();
951 		if (pid == -1) {
952 			if (stress_redo_fork(errno))
953 				goto again;
954 			if (!keep_stressing(args))
955 				goto finish;
956 			pr_fail("%s: fork failed, errno=%d (%s)\n",
957 				args->name, errno, strerror(errno));
958 			break;
959 		}
960 		if (pid == 0) {
961 			int rc;
962 			pid_t mypid = getpid();
963 
964 			(void)sched_settings_apply(true);
965 
966 			rc = stress_prctl_child(args, mypid);
967 			_exit(rc);
968 		}
969 		if (pid > 0) {
970 			int status;
971 
972 			/* Wait for child to exit or get killed by seccomp */
973 			if (shim_waitpid(pid, &status, 0) < 0) {
974 				if (errno != EINTR)
975 					pr_dbg("%s: waitpid failed, errno = %d (%s)\n",
976 						args->name, errno, strerror(errno));
977 			} else {
978 				/* Did the child hit a weird error? */
979 				if (WIFEXITED(status) &&
980 				    (WEXITSTATUS(status) != EXIT_SUCCESS)) {
981 					pr_fail("%s: aborting because of unexpected "
982 						"failure in child process\n", args->name);
983 					return EXIT_FAILURE;
984 				}
985 			}
986 		}
987 		inc_counter(args);
988 	} while (keep_stressing(args));
989 
990 finish:
991 	stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
992 
993 	return EXIT_SUCCESS;
994 }
995 
996 stressor_info_t stress_prctl_info = {
997 	.stressor = stress_prctl,
998 	.class = CLASS_OS,
999 	.help = help
1000 };
1001 #else
1002 stressor_info_t stress_prctl_info = {
1003 	.stressor = stress_not_implemented,
1004 	.class = CLASS_OS,
1005 	.help = help
1006 };
1007 #endif
1008