(root)/
strace-6.5/
tests/
prctl-sme.c
       1  /*
       2   * Check decoding of prctl PR_SME_SET_VL/PR_SME_GET_VL operations.
       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  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <unistd.h>
      15  #include <linux/prctl.h>
      16  
      17  #ifdef INJECT_RETVAL
      18  # define INJ_STR " (INJECTED)"
      19  #else
      20  # define INJ_STR ""
      21  #endif
      22  
      23  #ifndef EXT
      24  # define EXT SME
      25  #endif
      26  
      27  #define EXT_STR STRINGIFY_VAL(EXT)
      28  #define GLUE_(a_, b_, c_) a_ ## b_ ## c_
      29  #define GLUE(a_, b_, c_) GLUE_(a_, b_, c_)
      30  #define _(pfx_, sfx_) GLUE(pfx_, EXT, sfx_)
      31  
      32  #if !XLAT_RAW
      33  static void
      34  print_sme_vl_arg(kernel_ulong_t arg)
      35  {
      36  	kernel_ulong_t flags = arg & ~_(PR_, _VL_LEN_MASK);
      37  
      38  	if (arg < 0x10000)
      39  		return;
      40  
      41  	printf(" (");
      42  
      43  	if (flags & _(PR_, _SET_VL_ONEXEC))
      44  		printf("PR_" EXT_STR "_SET_VL_ONEXEC");
      45  	if (flags & _(PR_, _VL_INHERIT)) {
      46  		printf("%sPR_" EXT_STR "_VL_INHERIT",
      47  		       flags & _(PR_, _SET_VL_ONEXEC) ? "|" : "");
      48  	}
      49  
      50  	kernel_ulong_t leftover =
      51  			flags & ~(_(PR_, _SET_VL_ONEXEC)|_(PR_, _VL_INHERIT));
      52  	if (leftover) {
      53  		printf("%s%#llx",
      54  		       leftover == flags ? "" : "|",
      55  		       (unsigned long long) leftover);
      56  	}
      57  
      58  	kernel_ulong_t lens = arg & _(PR_, _VL_LEN_MASK);
      59  	printf("%s%#llx", flags ? "|" : "", (unsigned long long) lens);
      60  
      61  	printf(")");
      62  }
      63  
      64  #endif /* !XLAT_RAW */
      65  
      66  int
      67  main(int argc, char *argv[])
      68  {
      69  	const char *errstr;
      70  	long rc;
      71  	size_t i;
      72  
      73  	prctl_marker();
      74  
      75  #ifdef INJECT_RETVAL
      76  	unsigned long num_skip;
      77  	long inject_retval;
      78  	bool locked = false;
      79  
      80  	if (argc < 3)
      81  		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
      82  
      83  	num_skip = strtoul(argv[1], NULL, 0);
      84  	inject_retval = strtol(argv[2], NULL, 0);
      85  
      86  	for (size_t i = 0; i < num_skip; i++) {
      87  		if (prctl_marker() != inject_retval)
      88  			continue;
      89  
      90  		locked = true;
      91  		break;
      92  	}
      93  
      94  	if (!locked)
      95  		error_msg_and_fail("Have not locked on prctl(-1, -2, -3, -4"
      96  				   ", -5) returning %ld", inject_retval);
      97  #endif /* INJECT_RETVAL */
      98  
      99  	static const struct {
     100  		kernel_ulong_t val;
     101  		const char *str;
     102  		bool known;
     103  	} args[] = {
     104  		{ ARG_STR(0) },
     105  		{ ARG_STR(0xdead) },
     106  		{ ARG_XLAT_KNOWN(0x10000, "0x10000|0") },
     107  		{ ARG_XLAT_KNOWN(0x2ea57, "PR_" EXT_STR "_VL_INHERIT|0xea57") },
     108  		{ ARG_XLAT_KNOWN(0x40000, "PR_" EXT_STR "_SET_VL_ONEXEC|0") },
     109  		{ ARG_XLAT_KNOWN(0xfacefeed, "PR_" EXT_STR "_SET_VL_ONEXEC"
     110  					     "|PR_" EXT_STR "_VL_INHERIT"
     111  					     "|0xfac80000|0xfeed") },
     112  		{ ARG_XLAT_KNOWN(0xbad00000, "0xbad00000|0") },
     113  		{ ARG_XLAT_KNOWN(0xde90ded, "0xde90000|0xded") },
     114  		{ (kernel_ulong_t) 0xbadc0ded0000faceULL,
     115  #if SIZEOF_KERNEL_LONG_T > 4
     116  		  XLAT_KNOWN(0xbadc0ded0000face, "0xbadc0ded00000000|0xface")
     117  #else
     118  		  "0xface"
     119  #endif
     120  		},
     121  	};
     122  
     123  	for (i = 0; i < ARRAY_SIZE(args); i++) {
     124  		rc = syscall(__NR_prctl, _(PR_, _SET_VL), args[i].val, 1, 2, 3);
     125  		errstr = sprintrc(rc);
     126  		printf("prctl(" XLAT_FMT ", %s) = ",
     127  		       XLAT_SEL(_(PR_, _SET_VL), "PR_" EXT_STR "_SET_VL"),
     128  		       args[i].str);
     129  		if (rc >= 0) {
     130  			printf("%#lx", rc);
     131  #if !XLAT_RAW
     132  			print_sme_vl_arg(rc);
     133  #endif /* !XLAT_RAW */
     134  			puts(INJ_STR);
     135  		} else {
     136  			printf("%s" INJ_STR "\n", errstr);
     137  		}
     138  	}
     139  
     140  	rc = syscall(__NR_prctl, _(PR_, _GET_VL), 1, 2, 3, 4);
     141  	errstr = sprintrc(rc);
     142  	printf("prctl(" XLAT_FMT ") = ",
     143  	       XLAT_SEL(_(PR_, _GET_VL), "PR_" EXT_STR "_GET_VL"));
     144  	if (rc >= 0) {
     145  		printf("%#lx", rc);
     146  #if !XLAT_RAW
     147  		print_sme_vl_arg(rc);
     148  #endif /* !XLAT_RAW */
     149  		puts(INJ_STR);
     150  	} else {
     151  		printf("%s" INJ_STR "\n", errstr);
     152  	}
     153  
     154  	puts("+++ exited with 0 +++");
     155  	return 0;
     156  }