(root)/
strace-6.5/
src/
prctl.c
       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 */