(root)/
strace-6.5/
tests/
arch_prctl.c
       1  /*
       2   * Check decoding of arch_prctl syscall.
       3   *
       4   * Copyright (c) 2021-2022 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include "scno.h"
      12  
      13  #ifdef __NR_arch_prctl
      14  
      15  # include <stdio.h>
      16  # include <stdlib.h>
      17  # include <unistd.h>
      18  # include <linux/prctl.h>
      19  
      20  # define XLAT_MACROS_ONLY
      21  #  include "xlat/archvals.h"
      22  # undef XLAT_MACROS_ONLY
      23  
      24  # include "xlat.h"
      25  # include "xlat/x86_xfeature_bits.h"
      26  # include "xlat/x86_xfeatures.h"
      27  
      28  # ifdef INJECT_RETVAL
      29  #  define INJ_STR " (INJECTED)\n"
      30  # else
      31  #  define INJ_STR "\n"
      32  # endif
      33  
      34  # define ARRAY_END(a_) ((a_) + ARRAY_SIZE(a_))
      35  
      36  static long
      37  sys_arch_prctl(unsigned int cmd, kernel_ulong_t arg)
      38  {
      39  	return syscall(__NR_arch_prctl, cmd, arg, (unsigned long) -3U,
      40  						  (unsigned long) -4U,
      41  						  (unsigned long) -5U);
      42  }
      43  
      44  static long
      45  arch_prctl_marker(void)
      46  {
      47  	return sys_arch_prctl(-1U, (unsigned long) -2U);
      48  }
      49  
      50  int
      51  main(int argc, char *argv[])
      52  {
      53  	const kernel_ulong_t dummy = (kernel_ulong_t) 0xbadfaceddeadbeefULL;
      54  	const char *errstr;
      55  	long rc;
      56  
      57  	arch_prctl_marker();
      58  
      59  # ifdef INJECT_RETVAL
      60  	unsigned long num_skip;
      61  	long inject_retval;
      62  	bool locked = false;
      63  
      64  	if (argc < 3)
      65  		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
      66  
      67  	num_skip = strtoul(argv[1], NULL, 0);
      68  	inject_retval = strtol(argv[2], NULL, 0);
      69  
      70  	for (size_t i = 0; i < num_skip; i++) {
      71  		if (arch_prctl_marker() != inject_retval)
      72  			continue;
      73  
      74  		locked = true;
      75  		break;
      76  	}
      77  
      78  	if (!locked)
      79  		error_msg_and_fail("Have not locked on arch_prctl(-1, -2)"
      80  				   " returning %ld", inject_retval);
      81  # endif /* INJECT_RETVAL */
      82  
      83  	TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, u64_p);
      84  
      85  	/* Unknown commands */
      86  	static const uint32_t unk_cmds[] = {
      87  		0, 0x1,
      88  		0x1000, 0x1005,
      89  		0x1010, 0x1013,
      90  		0x1020, 0x1026,
      91  		0x1030, 0x1031,
      92  		0x1100, 0x1101,
      93  		0x2000, 0x2004,
      94  		0x2010, 0x2011,
      95  		0x2100, 0x2101,
      96  		0x3000, 0x3001,
      97  		0xdeadc0de };
      98  
      99  	for (size_t i = 0; i < ARRAY_SIZE(unk_cmds); i++) {
     100  		rc = sys_arch_prctl(unk_cmds[i], 0);
     101  		printf("arch_prctl(" XLAT_UNKNOWN_FMT("%#x", "ARCH_???")
     102  		       ", 0) = %s" INJ_STR,
     103  		       unk_cmds[i], sprintrc(rc));
     104  
     105  		rc = sys_arch_prctl(unk_cmds[i], (kernel_ulong_t) dummy);
     106  		printf("arch_prctl(" XLAT_UNKNOWN_FMT("%#x", "ARCH_???")
     107  		       ", %#llx) = %s" INJ_STR,
     108  		       unk_cmds[i], (unsigned long long) dummy, sprintrc(rc));
     109  
     110  		rc = sys_arch_prctl(unk_cmds[i], (uintptr_t) u64_p);
     111  		printf("arch_prctl(" XLAT_UNKNOWN_FMT("%#x", "ARCH_???")
     112  		       ", %p) = %s" INJ_STR,
     113  		       unk_cmds[i], u64_p, sprintrc(rc));
     114  	}
     115  
     116  	/* Default decoding */
     117  	static const struct strval32 def_cmds[] = {
     118  		{ ARG_XLAT_KNOWN(0x1001, "ARCH_SET_GS") },
     119  # ifdef INJECT_RETVAL
     120  		{ ARG_XLAT_KNOWN(0x1002, "ARCH_SET_FS") },
     121  # endif
     122  		{ ARG_XLAT_KNOWN(0x1012, "ARCH_SET_CPUID") },
     123  		{ ARG_XLAT_KNOWN(0x2001, "ARCH_MAP_VDSO_X32") },
     124  		{ ARG_XLAT_KNOWN(0x2002, "ARCH_MAP_VDSO_32") },
     125  		{ ARG_XLAT_KNOWN(0x2003, "ARCH_MAP_VDSO_64") },
     126  	};
     127  
     128  	for (const struct strval32 *p = def_cmds; p < ARRAY_END(def_cmds); p++)
     129  	{
     130  		rc = sys_arch_prctl(p->val, (kernel_ulong_t) dummy);
     131  		printf("arch_prctl(%s, %#llx) = %s" INJ_STR,
     132  		       p->str, (unsigned long long) dummy, sprintrc(rc));
     133  
     134  		rc = sys_arch_prctl(p->val, (uintptr_t) u64_p);
     135  		printf("arch_prctl(%s, %p) = %s" INJ_STR,
     136  		       p->str, u64_p, sprintrc(rc));
     137  
     138  		rc = sys_arch_prctl(p->val, 0);
     139  		printf("arch_prctl(%s, 0) = %s" INJ_STR, p->str, sprintrc(rc));
     140  	}
     141  
     142  	/* ARCH_GET_GS, ARCH_GET_FS */
     143  	static const struct strval32 kptr_cmds[] = {
     144  # ifdef INJECT_RETVAL
     145  		{ ARG_XLAT_KNOWN(0x1003, "ARCH_GET_FS") },
     146  # endif
     147  		{ ARG_XLAT_KNOWN(0x1004, "ARCH_GET_GS") },
     148  	};
     149  	TAIL_ALLOC_OBJECT_CONST_PTR(kernel_ulong_t, kulong_p);
     150  	const kernel_ulong_t ptrs[] = {
     151  		(kernel_ulong_t) 0xdeadfacecafebeefULL,
     152  		(uintptr_t) (kulong_p + 1),
     153  		(uintptr_t) kulong_p ,
     154  		0
     155  	};
     156  
     157  	for (const struct strval32 *p = kptr_cmds; p < ARRAY_END(kptr_cmds);
     158  	     p++) {
     159  		rc = sys_arch_prctl(p->val, 0);
     160  		printf("arch_prctl(%s, NULL) = %s" INJ_STR,
     161  		       p->str, sprintrc(rc));
     162  
     163  		rc = sys_arch_prctl(p->val, (uintptr_t) (kulong_p + 1));
     164  		printf("arch_prctl(%s, %p) = %s" INJ_STR,
     165  		       p->str, kulong_p + 1, sprintrc(rc));
     166  
     167  		for (size_t j = 0; j < ARRAY_SIZE(ptrs); j++) {
     168  			*kulong_p = ptrs[j];
     169  			uint32_t wr_cmd = p->val == ARCH_GET_GS ? ARCH_SET_GS
     170  								: ARCH_SET_FS;
     171  # if !XLAT_RAW
     172  			const char *wr_str = p->val == ARCH_GET_GS
     173  						? "ARCH_SET_GS" : "ARCH_SET_FS";
     174  # endif
     175  			rc = sys_arch_prctl(wr_cmd, *kulong_p);
     176  			printf("arch_prctl(" XLAT_FMT ", %#llx) = %s" INJ_STR,
     177  			       XLAT_SEL(wr_cmd, wr_str),
     178  			       (unsigned long long) *kulong_p, sprintrc(rc));
     179  
     180  			rc = sys_arch_prctl(p->val, (uintptr_t) kulong_p);
     181  			errstr = sprintrc(rc);
     182  			printf("arch_prctl(%s, ", p->str);
     183  			if (rc >= 0) {
     184  				if (*kulong_p) {
     185  					printf("[%#llx]",
     186  					       (unsigned long long) *kulong_p);
     187  				} else {
     188  					printf("[NULL]");
     189  				}
     190  			} else {
     191  				printf("%p", kulong_p);
     192  			}
     193  			printf(") = %s" INJ_STR, errstr);
     194  		}
     195  	}
     196  
     197  	/* ARCH_GET_CPUID */
     198  	rc = sys_arch_prctl(ARCH_GET_CPUID, 0xdeadc0de);
     199  	printf("arch_prctl(" XLAT_FMT ") = %s" INJ_STR,
     200  	       XLAT_ARGS(ARCH_GET_CPUID), sprintrc(rc));
     201  
     202  	/* xfeature mask get */
     203  	static const struct strval32 xfget_cmds[] = {
     204  		{ ARG_XLAT_KNOWN(0x1021, "ARCH_GET_XCOMP_SUPP") },
     205  		{ ARG_XLAT_KNOWN(0x1022, "ARCH_GET_XCOMP_PERM") },
     206  		{ ARG_XLAT_KNOWN(0x1024, "ARCH_GET_XCOMP_GUEST_PERM") },
     207  	};
     208  	static const struct strval64 xfget_vals[] = {
     209  		{ ARG_STR(0) },
     210  		{ ARG_XLAT_UNKNOWN(0x1, "XFEATURE_MASK_FP") },
     211  		{ ARG_XLAT_UNKNOWN(0x2, "XFEATURE_MASK_SSE") },
     212  		{ ARG_XLAT_UNKNOWN(0x3, "XFEATURE_MASK_FPSSE") },
     213  		{ ARG_XLAT_UNKNOWN(0x20, "XFEATURE_MASK_OPMASK") },
     214  		{ ARG_XLAT_UNKNOWN(0xc0, "XFEATURE_MASK_ZMM_Hi256"
     215  					 "|XFEATURE_MASK_Hi16_ZMM") },
     216  		{ ARG_XLAT_UNKNOWN(0xe0, "XFEATURE_MASK_AVX512") },
     217  		{ ARG_XLAT_UNKNOWN(0x20000, "XFEATURE_MASK_XTILE_CFG") },
     218  		{ ARG_XLAT_UNKNOWN(0x40000, "XFEATURE_MASK_XTILE_DATA") },
     219  		{ ARG_XLAT_UNKNOWN(0x60000, "XFEATURE_MASK_XTILE") },
     220  		{ ARG_XLAT_UNKNOWN(0xbadfaced,
     221  				   "XFEATURE_MASK_FP|XFEATURE_MASK_YMM"
     222  				   "|XFEATURE_MASK_BNDREGS|XFEATURE_MASK_AVX512"
     223  				   "|XFEATURE_MASK_PASID|XFEATURE_MASK_LBR"
     224  				   "|XFEATURE_MASK_XTILE|0xbad92800") },
     225  		{ ARG_XLAT_UNKNOWN(0x687ff,
     226  				   "XFEATURE_MASK_FPSSE|XFEATURE_MASK_YMM"
     227  				   "|XFEATURE_MASK_BNDREGS|XFEATURE_MASK_BNDCSR"
     228  				   "|XFEATURE_MASK_AVX512|XFEATURE_MASK_PT"
     229  				   "|XFEATURE_MASK_PKRU|XFEATURE_MASK_PASID"
     230  				   "|XFEATURE_MASK_LBR|XFEATURE_MASK_XTILE") },
     231  		{ ARG_XLAT_UNKNOWN(0xfffffffffff97800, "XFEATURE_MASK_???") },
     232  	};
     233  
     234  	for (const struct strval32 *p = xfget_cmds; p < ARRAY_END(xfget_cmds);
     235  	     p++) {
     236  		rc = sys_arch_prctl(p->val, 0);
     237  		printf("arch_prctl(%s, NULL) = %s" INJ_STR,
     238  		       p->str, sprintrc(rc));
     239  
     240  		rc = sys_arch_prctl(p->val, (uintptr_t) (u64_p + 1));
     241  		printf("arch_prctl(%s, %p) = %s" INJ_STR,
     242  		       p->str, u64_p + 1, sprintrc(rc));
     243  
     244  		for (const struct strval64 *q = xfget_vals;
     245  		     q < ARRAY_END(xfget_vals); q++) {
     246  			*u64_p = q->val;
     247  			rc = sys_arch_prctl(p->val, (uintptr_t) u64_p);
     248  			errstr = sprintrc(rc);
     249  			printf("arch_prctl(%s, ", p->str);
     250  			if (rc >= 0) {
     251  # ifdef INJECT_RETVAL
     252  				printf("[%s]", q->str);
     253  # else
     254  				if (*u64_p) {
     255  					printf("[%#llx" NRAW(" /* "),
     256  					       (unsigned long long) *u64_p);
     257  #  if !XLAT_RAW
     258  					printflags(x86_xfeatures, *u64_p, NULL);
     259  #  endif
     260  					printf(NRAW(" */") "]");
     261  				} else {
     262  					printf("[0]");
     263  				}
     264  # endif
     265  			} else {
     266  				printf("%p", u64_p);
     267  			}
     268  			printf(") = %s" INJ_STR, errstr);
     269  		}
     270  	}
     271  
     272  	/* xfeature in arg, xfeature mask in ret */
     273  	static const struct strval32 xfreq_cmds[] = {
     274  		{ ARG_XLAT_KNOWN(0x1023, "ARCH_REQ_XCOMP_PERM") },
     275  		{ ARG_XLAT_KNOWN(0x1025, "ARCH_REQ_XCOMP_GUEST_PERM") },
     276  	};
     277  	static const struct strval32 xfreq_vals[] = {
     278  		{ ARG_XLAT_UNKNOWN(0, "XFEATURE_FP") },
     279  		{ ARG_XLAT_UNKNOWN(0x8, "XFEATURE_PT_UNIMPLEMENTED_SO_FAR") },
     280  		{ ARG_XLAT_UNKNOWN(0xb, "XFEATURE_???") },
     281  		{ ARG_XLAT_UNKNOWN(0xc, "XFEATURE_???") },
     282  		{ ARG_XLAT_UNKNOWN(0xd, "XFEATURE_???") },
     283  		{ ARG_XLAT_UNKNOWN(0xe, "XFEATURE_???") },
     284  		{ ARG_XLAT_UNKNOWN(0xf, "XFEATURE_LBR") },
     285  		{ ARG_XLAT_UNKNOWN(0x10, "XFEATURE_???") },
     286  		{ ARG_XLAT_UNKNOWN(0x11, "XFEATURE_XTILE_CFG") },
     287  		{ ARG_XLAT_UNKNOWN(0x12, "XFEATURE_XTILE_DATA") },
     288  		{ ARG_XLAT_UNKNOWN(0x13, "XFEATURE_???") },
     289  		{ ARG_XLAT_UNKNOWN(0xdeadface, "XFEATURE_???") },
     290  	};
     291  
     292  	for (const struct strval32 *p = xfreq_cmds; p < ARRAY_END(xfreq_cmds);
     293  	     p++) {
     294  		for (const struct strval32 *q = xfreq_vals;
     295  		     q < ARRAY_END(xfreq_vals); q++) {
     296  			rc = sys_arch_prctl(p->val, q->val);
     297  			errstr = sprintrc(rc);
     298  			printf("arch_prctl(%s, %s) = ", p->str, q->str);
     299  			if (rc > 0) {
     300  				printf("%#lx", rc);
     301  # if !XLAT_RAW
     302  				if (rc & x86_xfeatures->flags_mask) {
     303  					printf(" (");
     304  					printflags(x86_xfeatures, rc, NULL);
     305  					printf(")");
     306  				}
     307  # endif
     308  				printf(INJ_STR);
     309  			} else {
     310  				printf("%s" INJ_STR, errstr);
     311  			}
     312  		}
     313  	}
     314  
     315  	puts("+++ exited with 0 +++");
     316  	return 0;
     317  }
     318  
     319  #else
     320  
     321  SKIP_MAIN_UNDEFINED("__NR_arch_prctl")
     322  
     323  #endif