1 /*
2 * Copyright (c) 1994-1996 Rick Sladkey <jrs@world.std.com>
3 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl>
4 * Copyright (c) 2005-2007 Roland McGrath <roland@redhat.com>
5 * Copyright (c) 2008-2015 Dmitry V. Levin <ldv@strace.io>
6 * Copyright (c) 2014-2023 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: LGPL-2.1-or-later
10 */
11
12 #include "defs.h"
13 #include "xstring.h"
14
15 #include <linux/prctl.h>
16
17 #include "xlat/prctl_options.h"
18 #include "xlat/pr_cap_ambient.h"
19 #include "xlat/pr_dumpable.h"
20 #include "xlat/pr_fp_mode.h"
21 #include "xlat/pr_mce_kill.h"
22 #include "xlat/pr_mce_kill_policy.h"
23 #include "xlat/pr_mdwe_flags.h"
24 #include "xlat/pr_pac_enabled_keys.h"
25 #include "xlat/pr_pac_keys.h"
26 #include "xlat/pr_sched_core_cmds.h"
27 #include "xlat/pr_sched_core_pidtypes.h"
28 #include "xlat/pr_set_mm.h"
29 #include "xlat/pr_set_vma.h"
30 #include "xlat/pr_sme_vl_flags.h"
31 #include "xlat/pr_spec_cmds.h"
32 #include "xlat/pr_spec_get_store_bypass_flags.h"
33 #include "xlat/pr_spec_set_store_bypass_flags.h"
34 #include "xlat/pr_sud_cmds.h"
35 #include "xlat/pr_sve_vl_flags.h"
36 #include "xlat/pr_tagged_addr_enable.h"
37 #include "xlat/pr_tagged_addr_mte_tcf.h"
38 #include "xlat/pr_tsc.h"
39 #include "xlat/pr_unalign_flags.h"
40
41 #ifndef TASK_COMM_LEN
42 # define TASK_COMM_LEN 16
43 #endif
44
45 #include <linux/seccomp.h>
46 #include "xlat/seccomp_mode.h"
47
48 #include <linux/securebits.h>
49 #include "xlat/secbits.h"
50
51 /* these constants are the same as in <linux/capability.h> */
52 enum {
53 #include "caps0.h"
54 #include "caps1.h"
55 };
56
57 #include "xlat/cap.h"
58
59 static void
60 print_prctl_args(struct tcb *tcp, const unsigned int first)
61 {
62 for (unsigned int i = first; i < n_args(tcp); ++i) {
63 tprint_arg_next();
64 PRINT_VAL_X(tcp->u_arg[i]);
65 }
66 }
67
68 static char *
69 sprint_sve_val(kernel_ulong_t arg, bool aux)
70 {
71 static char out[sizeof("0x /* PR_SVE_SET_VL_ONEXEC|PR_SVE_VL_INHERIT"
72 "|0x|0x */") + sizeof(kernel_ulong_t) * 2 * 3];
73
74 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) {
75 if (aux)
76 return NULL;
77
78 xsprintf(out, "%#" PRI_klx, arg);
79
80 return out;
81 }
82
83 kernel_ulong_t vl = arg & PR_SVE_VL_LEN_MASK;
84 kernel_ulong_t flags = arg & ~PR_SVE_VL_LEN_MASK;
85
86 if (!flags && aux)
87 return NULL;
88
89 const char *flags_str = sprintflags_ex("", pr_sve_vl_flags, flags, '\0',
90 XLAT_STYLE_ABBREV);
91
92 if (!aux && flags && xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
93 {
94 xsprintf(out, "%#" PRI_klx " /* %s%s%#" PRI_klx " */",
95 arg, flags_str ?: "", flags_str ? "|" : "", vl);
96 } else {
97 xsprintf(out, "%s%s%#" PRI_klx,
98 flags_str ?: "", flags_str ? "|" : "", vl);
99 }
100
101 return out;
102 }
103
104 static char *
105 sprint_sme_val(kernel_ulong_t arg, bool aux)
106 {
107 static char out[sizeof("0x /* PR_SME_SET_VL_ONEXEC|PR_SME_VL_INHERIT"
108 "|0x|0x */") + sizeof(kernel_ulong_t) * 2 * 3];
109
110 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) {
111 if (aux)
112 return NULL;
113
114 xsprintf(out, "%#" PRI_klx, arg);
115
116 return out;
117 }
118
119 kernel_ulong_t vl = arg & PR_SME_VL_LEN_MASK;
120 kernel_ulong_t flags = arg & ~PR_SME_VL_LEN_MASK;
121
122 if (!flags && aux)
123 return NULL;
124
125 const char *flags_str = sprintflags_ex("", pr_sme_vl_flags, flags, '\0',
126 XLAT_STYLE_ABBREV);
127
128 if (!aux && flags && xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
129 {
130 xsprintf(out, "%#" PRI_klx " /* %s%s%#" PRI_klx " */",
131 arg, flags_str ?: "", flags_str ? "|" : "", vl);
132 } else {
133 xsprintf(out, "%s%s%#" PRI_klx,
134 flags_str ?: "", flags_str ? "|" : "", vl);
135 }
136
137 return out;
138 }
139
140 static char *
141 sprint_tagged_addr_val(const kernel_ulong_t arg, bool rval)
142 {
143 static char out[sizeof("0x /* !PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_ASYNC"
144 "|0xffff<<PR_MTE_TAG_SHIFT|0x */") +
145 sizeof(kernel_ulong_t) * 2 * 2];
146
147 const kernel_ulong_t enabled = arg & PR_TAGGED_ADDR_ENABLE;
148 const kernel_ulong_t mte_tcf = arg & PR_MTE_TCF_MASK;
149 const kernel_ulong_t mte_tag = arg & PR_MTE_TAG_MASK;
150 const kernel_ulong_t rest = arg &
151 ~((kernel_ulong_t) PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_MASK
152 | PR_MTE_TAG_MASK);
153 char *pos = out;
154
155 if (!rval && (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV))
156 pos = xappendstr(out, pos, "%#" PRI_klx, arg);
157 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
158 return rval ? NULL : out;
159 if (!rval && (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE))
160 pos = xappendstr(out, pos, " /* ");
161
162 pos = xappendstr(out, pos, "%s|",
163 sprintflags_ex("", pr_tagged_addr_enable, enabled,
164 '\0', XLAT_STYLE_ABBREV));
165 pos += sprintxval_ex(pos, sizeof(out) - (pos - out),
166 pr_tagged_addr_mte_tcf, mte_tcf, NULL,
167 XLAT_STYLE_ABBREV);
168 if (mte_tag) {
169 pos = xappendstr(out, pos, "|%#" PRI_klx "<<PR_MTE_TAG_SHIFT",
170 mte_tag >> PR_MTE_TAG_SHIFT);
171 }
172 if (rest)
173 pos = xappendstr(out, pos, "|%#" PRI_klx, rest);
174
175 if (!rval && (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE))
176 pos = xappendstr(out, pos, " */");
177
178 return out;
179 }
180
181 SYS_FUNC(prctl)
182 {
183 const unsigned int option = tcp->u_arg[0];
184 const kernel_ulong_t arg2 = tcp->u_arg[1];
185 const kernel_ulong_t arg3 = tcp->u_arg[2];
186 const kernel_ulong_t arg4 = tcp->u_arg[3];
187 const kernel_ulong_t arg5 = tcp->u_arg[4];
188 unsigned int i;
189
190 if (entering(tcp))
191 printxval(prctl_options, option, "PR_???");
192
193 switch (option) {
194 case PR_GET_KEEPCAPS:
195 case PR_GET_SECCOMP:
196 case PR_GET_TIMERSLACK:
197 case PR_GET_TIMING:
198 return RVAL_DECODED;
199
200 case PR_GET_CHILD_SUBREAPER:
201 case PR_GET_ENDIAN:
202 case PR_GET_FPEMU:
203 case PR_GET_FPEXC:
204 if (entering(tcp))
205 tprint_arg_next();
206 else
207 printnum_int(tcp, arg2, "%u");
208 break;
209
210 case PR_GET_DUMPABLE:
211 if (entering(tcp))
212 break;
213 if (syserror(tcp))
214 return 0;
215 tcp->auxstr = xlookup(pr_dumpable, (kernel_ulong_t) tcp->u_rval);
216 return RVAL_STR;
217
218 case PR_GET_NAME:
219 if (entering(tcp)) {
220 tprint_arg_next();
221 } else {
222 if (syserror(tcp))
223 printaddr(arg2);
224 else
225 printstr_ex(tcp, arg2, TASK_COMM_LEN,
226 QUOTE_0_TERMINATED);
227 }
228 break;
229
230 case PR_GET_PDEATHSIG:
231 if (entering(tcp)) {
232 tprint_arg_next();
233 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
234 tprint_indirect_begin();
235 printsignal(i);
236 tprint_indirect_end();
237 }
238 break;
239
240 case PR_GET_SECUREBITS:
241 if (entering(tcp))
242 break;
243 if (syserror(tcp) || tcp->u_rval == 0)
244 return 0;
245 tcp->auxstr = sprintflags_ex("", secbits,
246 (kernel_ulong_t) tcp->u_rval, '\0',
247 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
248 return RVAL_HEX | RVAL_STR;
249
250 case PR_GET_TID_ADDRESS:
251 if (entering(tcp))
252 tprint_arg_next();
253 else
254 printnum_kptr(tcp, arg2);
255 break;
256
257 case PR_GET_TSC:
258 if (entering(tcp)) {
259 tprint_arg_next();
260 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
261 tprint_indirect_begin();
262 printxval(pr_tsc, i, "PR_TSC_???");
263 tprint_indirect_end();
264 }
265 break;
266
267 case PR_GET_UNALIGN:
268 if (entering(tcp)) {
269 tprint_arg_next();
270 } else if (!umove_or_printaddr(tcp, arg2, &i)) {
271 tprint_indirect_begin();
272 printflags(pr_unalign_flags, i, "PR_UNALIGN_???");
273 tprint_indirect_end();
274 }
275 break;
276
277 case PR_GET_FP_MODE:
278 if (entering(tcp))
279 break;
280 if (syserror(tcp) || tcp->u_rval == 0)
281 return 0;
282 tcp->auxstr = sprintflags_ex("", pr_fp_mode,
283 (kernel_ulong_t) tcp->u_rval, '\0',
284 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
285 return RVAL_HEX | RVAL_STR;
286
287 case PR_SVE_SET_VL:
288 if (entering(tcp)) {
289 tprint_arg_next();
290 tprints_string(sprint_sve_val(arg2, false));
291 return 0;
292 }
293 ATTRIBUTE_FALLTHROUGH;
294
295 case PR_SVE_GET_VL:
296 if (entering(tcp))
297 break;
298 if (syserror(tcp) || tcp->u_rval == 0)
299 return 0;
300
301 tcp->auxstr = sprint_sve_val(tcp->u_rval, true);
302
303 return RVAL_HEX | RVAL_STR;
304
305 case PR_GET_SPECULATION_CTRL:
306 if (entering(tcp)) {
307 tprint_arg_next();
308 printxval64(pr_spec_cmds, arg2, "PR_SPEC_???");
309
310 break;
311 }
312
313 if (syserror(tcp))
314 return 0;
315
316 switch (arg2) {
317 case PR_SPEC_STORE_BYPASS:
318 case PR_SPEC_INDIRECT_BRANCH:
319 case PR_SPEC_L1D_FLUSH:
320 tcp->auxstr = sprintflags_ex("",
321 pr_spec_get_store_bypass_flags,
322 (kernel_ulong_t) tcp->u_rval, '\0',
323 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
324 return RVAL_HEX | RVAL_STR;
325 }
326
327 return RVAL_STR;
328
329 case PR_SET_TAGGED_ADDR_CTRL:
330 tprint_arg_next();
331 tprints_string(sprint_tagged_addr_val(arg2, false));
332 print_prctl_args(tcp, 2);
333 return RVAL_DECODED;
334
335 case PR_GET_TAGGED_ADDR_CTRL:
336 if (entering(tcp)) {
337 print_prctl_args(tcp, 1);
338 break;
339 }
340 if (syserror(tcp))
341 return 0;
342 tcp->auxstr = sprint_tagged_addr_val(tcp->u_rval, true);
343
344 return RVAL_HEX | RVAL_STR;
345
346 case PR_SME_SET_VL:
347 if (entering(tcp)) {
348 tprint_arg_next();
349 tprints_string(sprint_sme_val(arg2, false));
350 return 0;
351 }
352 ATTRIBUTE_FALLTHROUGH;
353
354 case PR_SME_GET_VL:
355 if (entering(tcp))
356 break;
357 if (syserror(tcp) || tcp->u_rval == 0)
358 return 0;
359
360 tcp->auxstr = sprint_sme_val(tcp->u_rval, true);
361
362 return RVAL_HEX | RVAL_STR;
363
364 case PR_GET_MDWE:
365 if (entering(tcp)) {
366 print_prctl_args(tcp, 1);
367 break;
368 }
369 if (syserror(tcp))
370 return 0;
371 tcp->auxstr = sprintflags_ex("", pr_mdwe_flags,
372 (kernel_ulong_t) tcp->u_rval, '\0',
373 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
374 return RVAL_HEX | RVAL_STR;
375
376 /* PR_TASK_PERF_EVENTS_* take no arguments. */
377 case PR_TASK_PERF_EVENTS_DISABLE:
378 case PR_TASK_PERF_EVENTS_ENABLE:
379 return RVAL_DECODED;
380
381 case PR_SET_CHILD_SUBREAPER:
382 case PR_SET_ENDIAN:
383 case PR_SET_FPEMU:
384 case PR_SET_FPEXC:
385 case PR_SET_KEEPCAPS:
386 case PR_SET_TIMING:
387 tprint_arg_next();
388 PRINT_VAL_U(arg2);
389 return RVAL_DECODED;
390
391 case PR_SET_DUMPABLE:
392 tprint_arg_next();
393 printxval64(pr_dumpable, arg2, "SUID_DUMP_???");
394 return RVAL_DECODED;
395
396 case PR_CAPBSET_DROP:
397 case PR_CAPBSET_READ:
398 tprint_arg_next();
399 printxval64(cap, arg2, "CAP_???");
400 return RVAL_DECODED;
401
402 case PR_CAP_AMBIENT:
403 tprint_arg_next();
404 printxval64(pr_cap_ambient, arg2,
405 "PR_CAP_AMBIENT_???");
406 switch (arg2) {
407 case PR_CAP_AMBIENT_RAISE:
408 case PR_CAP_AMBIENT_LOWER:
409 case PR_CAP_AMBIENT_IS_SET:
410 tprint_arg_next();
411 printxval64(cap, arg3, "CAP_???");
412 print_prctl_args(tcp, 3);
413 break;
414 default:
415 print_prctl_args(tcp, 2);
416 break;
417 }
418 return RVAL_DECODED;
419
420 case PR_MCE_KILL:
421 tprint_arg_next();
422 printxval64(pr_mce_kill, arg2, "PR_MCE_KILL_???");
423 tprint_arg_next();
424 if (PR_MCE_KILL_SET == arg2)
425 printxval64(pr_mce_kill_policy, arg3,
426 "PR_MCE_KILL_???");
427 else
428 PRINT_VAL_X(arg3);
429 print_prctl_args(tcp, 3);
430 return RVAL_DECODED;
431
432 case PR_SET_NAME:
433 tprint_arg_next();
434 printstr_ex(tcp, arg2, TASK_COMM_LEN - 1,
435 QUOTE_0_TERMINATED);
436 return RVAL_DECODED;
437
438 case PR_SET_VMA:
439 tprint_arg_next();
440 printxval64(pr_set_vma, arg2, "PR_SET_VMA_???");
441 if (arg2 == PR_SET_VMA_ANON_NAME) {
442 tprint_arg_next();
443 printaddr(arg3);
444 tprint_arg_next();
445 PRINT_VAL_U(arg4);
446 tprint_arg_next();
447 printstr(tcp, arg5);
448 } else {
449 /* There are no other sub-options now, but there
450 * might be in future... */
451 print_prctl_args(tcp, 2);
452 }
453 return RVAL_DECODED;
454
455 case PR_SET_MM:
456 tprint_arg_next();
457 printxval(pr_set_mm, arg2, "PR_SET_MM_???");
458 print_prctl_args(tcp, 2);
459 return RVAL_DECODED;
460
461 case PR_SET_PDEATHSIG:
462 tprint_arg_next();
463 if (arg2 > 128)
464 PRINT_VAL_U(arg2);
465 else
466 printsignal(arg2);
467 return RVAL_DECODED;
468
469 case PR_SET_PTRACER:
470 tprint_arg_next();
471 if ((int) arg2 == -1) {
472 print_xlat_ex((int) arg2, "PR_SET_PTRACER_ANY",
473 XLAT_STYLE_FMT_D);
474 } else {
475 printpid(tcp, arg2, PT_TGID);
476 }
477 return RVAL_DECODED;
478
479 case PR_SET_SECCOMP:
480 tprint_arg_next();
481 printxval64(seccomp_mode, arg2,
482 "SECCOMP_MODE_???");
483 if (SECCOMP_MODE_STRICT == arg2)
484 return RVAL_DECODED;
485 if (SECCOMP_MODE_FILTER == arg2) {
486 tprint_arg_next();
487 decode_seccomp_fprog(tcp, arg3);
488 return RVAL_DECODED;
489 }
490 print_prctl_args(tcp, 2);
491 return RVAL_DECODED;
492
493 case PR_SET_SECUREBITS:
494 tprint_arg_next();
495 printflags64(secbits, arg2, "SECBIT_???");
496 return RVAL_DECODED;
497
498 case PR_SET_TIMERSLACK:
499 tprint_arg_next();
500 PRINT_VAL_D(arg2);
501 return RVAL_DECODED;
502
503 case PR_SET_TSC:
504 tprint_arg_next();
505 printxval(pr_tsc, arg2, "PR_TSC_???");
506 return RVAL_DECODED;
507
508 case PR_SET_UNALIGN:
509 tprint_arg_next();
510 printflags(pr_unalign_flags, arg2, "PR_UNALIGN_???");
511 return RVAL_DECODED;
512
513 case PR_SET_MDWE:
514 tprint_arg_next();
515 printflags(pr_mdwe_flags, arg2, "PR_MDWE_???");
516 print_prctl_args(tcp, 2);
517 return RVAL_DECODED;
518
519 case PR_SET_NO_NEW_PRIVS:
520 case PR_SET_THP_DISABLE:
521 case PR_SET_IO_FLUSHER:
522 tprint_arg_next();
523 PRINT_VAL_U(arg2);
524 print_prctl_args(tcp, 2);
525 return RVAL_DECODED;
526
527 case PR_MCE_KILL_GET:
528 if (entering(tcp)) {
529 print_prctl_args(tcp, 1);
530 return 0;
531 }
532 if (syserror(tcp))
533 return 0;
534 tcp->auxstr = xlookup(pr_mce_kill_policy,
535 (kernel_ulong_t) tcp->u_rval);
536 return RVAL_STR;
537
538 case PR_SET_FP_MODE:
539 tprint_arg_next();
540 printflags(pr_fp_mode, arg2, "PR_FP_MODE_???");
541 return RVAL_DECODED;
542
543 case PR_SET_SPECULATION_CTRL:
544 tprint_arg_next();
545 printxval64(pr_spec_cmds, arg2, "PR_SPEC_???");
546 tprint_arg_next();
547
548 switch (arg2) {
549 case PR_SPEC_STORE_BYPASS:
550 case PR_SPEC_INDIRECT_BRANCH:
551 case PR_SPEC_L1D_FLUSH:
552 printxval64(pr_spec_set_store_bypass_flags, arg3,
553 "PR_SPEC_???");
554 break;
555
556 default:
557 PRINT_VAL_X(arg3);
558 }
559
560 return RVAL_DECODED;
561
562 case PR_PAC_RESET_KEYS:
563 tprint_arg_next();
564 printflags_ex(arg2, "PR_PAC_???", XLAT_STYLE_DEFAULT,
565 pr_pac_enabled_keys, pr_pac_keys, NULL);
566 print_prctl_args(tcp, 2);
567
568 return RVAL_DECODED;
569
570 case PR_PAC_SET_ENABLED_KEYS:
571 tprint_arg_next();
572 printflags64(pr_pac_enabled_keys, arg2, "PR_PAC_???");
573 tprint_arg_next();
574 printflags64(pr_pac_enabled_keys, arg3, "PR_PAC_???");
575 print_prctl_args(tcp, 3);
576
577 return RVAL_DECODED;
578
579 case PR_PAC_GET_ENABLED_KEYS:
580 if (entering(tcp)) {
581 print_prctl_args(tcp, 1);
582 return 0;
583 }
584 if (syserror(tcp))
585 return 0;
586 tcp->auxstr = sprintflags_ex("", pr_pac_enabled_keys,
587 (kernel_ulong_t) tcp->u_rval, '\0',
588 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
589 return RVAL_HEX | RVAL_STR;
590
591 case PR_SET_SYSCALL_USER_DISPATCH:
592 tprint_arg_next();
593 printxval64(pr_sud_cmds, arg2, "PR_SYS_DISPATCH_???");
594 tprint_arg_next();
595 PRINT_VAL_X(arg3);
596 tprint_arg_next();
597 PRINT_VAL_X(arg4);
598 tprint_arg_next();
599 printaddr(arg5);
600
601 return RVAL_DECODED;
602
603 case PR_SCHED_CORE:
604 if (entering(tcp)) {
605 tprint_arg_next();
606 printxval(pr_sched_core_cmds, arg2, "PR_SCHED_CORE_???");
607
608 tprint_arg_next();
609 enum pid_type pt;
610 switch ((unsigned int) arg4) {
611 case PIDTYPE_PID: pt = PT_TID; break;
612 case PIDTYPE_TGID: pt = PT_TGID; break;
613 case PIDTYPE_PGID: pt = PT_PGID; break;
614 case PIDTYPE_SID: pt = PT_SID; break;
615 default: pt = PT_NONE;
616 }
617 printpid(tcp, arg3, pt);
618
619 tprint_arg_next();
620 printxval_ex(pr_sched_core_pidtypes,
621 (unsigned int) arg4, "PIDTYPE_???",
622 (xlat_verbose(xlat_verbosity)
623 == XLAT_STYLE_RAW)
624 ? XLAT_STYLE_DEFAULT
625 : XLAT_STYLE_VERBOSE);
626
627 tprint_arg_next();
628 switch ((unsigned int) arg2) {
629 case PR_SCHED_CORE_GET:
630 /* arg5 is to be decoded on exiting */
631 return 0;
632 default:
633 printaddr(arg5);
634 }
635 } else {
636 /* PR_SCHED_CORE_GET */
637 if (syserror(tcp))
638 printaddr(arg5);
639 else
640 printnum_int64(tcp, arg5, "%#" PRIx64);
641 }
642
643 return RVAL_DECODED;
644
645 case PR_GET_NO_NEW_PRIVS:
646 case PR_GET_THP_DISABLE:
647 case PR_MPX_DISABLE_MANAGEMENT:
648 case PR_MPX_ENABLE_MANAGEMENT:
649 case PR_GET_IO_FLUSHER:
650 default:
651 print_prctl_args(tcp, 1);
652 return RVAL_DECODED;
653 }
654 return 0;
655 }
656
657 #if defined X86_64 || defined X32 || defined I386
658 # include "xlat/archvals.h"
659 # include "xlat/x86_xfeature_bits.h"
660 # include "xlat/x86_xfeatures.h"
661
662 SYS_FUNC(arch_prctl)
663 {
664 const unsigned int option = tcp->u_arg[0];
665 const kernel_ulong_t addr = tcp->u_arg[1];
666
667 if (entering(tcp))
668 printxval(archvals, option, "ARCH_???");
669
670 switch (option) {
671 case ARCH_GET_GS:
672 case ARCH_GET_FS:
673 if (entering(tcp))
674 tprint_arg_next();
675 else
676 printnum_kptr(tcp, addr);
677 return 0;
678
679 case ARCH_GET_CPUID: /* has no arguments */
680 return RVAL_DECODED;
681
682 case ARCH_GET_XCOMP_SUPP:
683 case ARCH_GET_XCOMP_PERM:
684 case ARCH_GET_XCOMP_GUEST_PERM:
685 if (entering(tcp)) {
686 tprint_arg_next();
687 } else {
688 uint64_t val;
689
690 if (umove_or_printaddr(tcp, addr, &val))
691 return 0;
692
693 /* XFEATURE_MASK_* macros are not publicly exposed */
694 tprint_indirect_begin();
695 printflags_ex(val, "XFEATURE_MASK_???",
696 xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW
697 ? XLAT_STYLE_RAW : XLAT_STYLE_VERBOSE,
698 x86_xfeatures, NULL);
699 tprint_indirect_end();
700 }
701
702 return 0;
703
704 case ARCH_REQ_XCOMP_PERM:
705 case ARCH_REQ_XCOMP_GUEST_PERM:
706 if (entering(tcp)) {
707 /* XFEATURE_* enum is not publicly exposed */
708 tprint_arg_next();
709 printxvals_ex(addr, "XFEATURE_???",
710 xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW
711 ? XLAT_STYLE_RAW : XLAT_STYLE_VERBOSE,
712 x86_xfeature_bits, NULL);
713 } else {
714 if (tcp->u_rval <= 0)
715 return 0;
716
717 tcp->auxstr = sprintflags_ex("", x86_xfeatures,
718 (kernel_ulong_t) tcp->u_rval, '\0',
719 XLAT_STYLE_DEFAULT | SPFF_AUXSTR_MODE);
720
721 return RVAL_HEX | RVAL_STR;
722 }
723
724 return 0;
725
726 /* default handling: print arg2 in hexadecimal on entering */
727 case ARCH_SET_GS:
728 case ARCH_SET_FS:
729 case ARCH_SET_CPUID:
730 case ARCH_MAP_VDSO_X32:
731 case ARCH_MAP_VDSO_32:
732 case ARCH_MAP_VDSO_64:
733 default:
734 break;
735 }
736
737 tprint_arg_next();
738 PRINT_VAL_X(addr);
739
740 return RVAL_DECODED;
741 }
742 #endif /* X86_64 || X32 || I386 */