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