(root)/
strace-6.5/
tests-m32/
prctl-tagged-addr.c
       1  /*
       2   * Check decoding of prctl PR_SET_TAGGED_ADDR_CTRL and PR_GET_TAGGED_ADDR_CTRL
       3   * operations.
       4   *
       5   * Copyright (c) 2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <unistd.h>
      16  #include <linux/prctl.h>
      17  
      18  #if !XLAT_RAW
      19  static void
      20  print_tagged_addr_arg(kernel_ulong_t arg)
      21  {
      22  	kernel_ulong_t val = arg & PR_TAGGED_ADDR_ENABLE;
      23  
      24  	printf("%sPR_TAGGED_ADDR_ENABLE", val ? "" : "!");
      25  	arg &= ~val;
      26  	val = arg & PR_MTE_TCF_MASK;
      27  	switch (val) {
      28  	case PR_MTE_TCF_NONE:  printf("|PR_MTE_TCF_NONE");  break;
      29  	case PR_MTE_TCF_SYNC:  printf("|PR_MTE_TCF_SYNC");  break;
      30  	case PR_MTE_TCF_ASYNC: printf("|PR_MTE_TCF_ASYNC"); break;
      31  	case PR_MTE_TCF_MASK:  printf("|PR_MTE_TCF_MASK");  break;
      32  	}
      33  	arg &= ~val;
      34  	val = arg & PR_MTE_TAG_MASK;
      35  	if (val) {
      36  		printf("|%#llx<<PR_MTE_TAG_SHIFT",
      37  		       (unsigned long long) val >> PR_MTE_TAG_SHIFT);
      38  	}
      39  	arg &= ~val;
      40  	if (arg)
      41  		printf("|%#llx", (unsigned long long) arg);
      42  }
      43  #endif /* !XLAT_RAW */
      44  
      45  #ifdef INJECT_RETVAL
      46  # define INJ_STR " (INJECTED)"
      47  #else
      48  # define INJ_STR ""
      49  #endif
      50  
      51  #if SIZEOF_KERNEL_LONG_T == 8
      52  # define HIBITS(a) a
      53  #else
      54  # define HIBITS(a)
      55  #endif
      56  
      57  int
      58  main(int argc, char *argv[])
      59  {
      60  	prctl_marker();
      61  
      62  #ifdef INJECT_RETVAL
      63  	unsigned long num_skip;
      64  	long inject_retval;
      65  	bool locked = false;
      66  
      67  	if (argc < 3)
      68  		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
      69  
      70  	num_skip = strtoul(argv[1], NULL, 0);
      71  	inject_retval = strtol(argv[2], NULL, 0);
      72  
      73  	for (size_t i = 0; i < num_skip; i++) {
      74  		if (prctl_marker() != inject_retval)
      75  			continue;
      76  
      77  		locked = true;
      78  		break;
      79  	}
      80  
      81  	if (!locked)
      82  		error_msg_and_fail("Have not locked on prctl(-1, -2, -3, -4"
      83  				   ", -5) returning %ld", inject_retval);
      84  #endif /* INJECT_RETVAL */
      85  
      86  	static const struct {
      87  		kernel_ulong_t val;
      88  		const char *str;
      89  	} args[] = {
      90  		{ 0, "!PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_NONE" },
      91  		{ /* 1 */ ARG_STR(PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_NONE) },
      92  		{ 2, "!PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_SYNC" },
      93  		{ /* 5 */ ARG_STR(PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_ASYNC) },
      94  		{ 6, "!PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_MASK" },
      95  		{ 8, "!PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_NONE|0x1<<PR_MTE_TAG_SHIFT" },
      96  		{ /* 13 */ ARG_STR(PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_ASYNC|0x1<<PR_MTE_TAG_SHIFT) },
      97  		{ 0x57ae57f4, "!PR_TAGGED_ADDR_ENABLE|PR_MTE_TCF_ASYNC"
      98  			      "|0xcafe<<PR_MTE_TAG_SHIFT|0x57a80000" },
      99  		{ (kernel_ulong_t) -1LLU, "PR_TAGGED_ADDR_ENABLE"
     100  					  "|PR_MTE_TCF_MASK"
     101  					  "|0xffff<<PR_MTE_TAG_SHIFT"
     102  					  "|0x" HIBITS("ffffffff") "fff80000" },
     103  	};
     104  	long rc;
     105  	size_t i = 0;
     106  
     107  	for (i = 0; i < ARRAY_SIZE(args); i++) {
     108  		rc = syscall(__NR_prctl, PR_SET_TAGGED_ADDR_CTRL,
     109  			     args[i].val, 1, 2, 3);
     110  		printf("prctl(" XLAT_KNOWN(0x37, "PR_SET_TAGGED_ADDR_CTRL") ", "
     111  		       XLAT_FMT_LL ", 0x1, 0x2, 0x3) = %s" INJ_STR "\n",
     112  		       XLAT_SEL((unsigned long long) args[i].val, args[i].str),
     113  		       sprintrc(rc));
     114  	}
     115  
     116  	rc = syscall(__NR_prctl, PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
     117  	const char *errstr = sprintrc(rc);
     118  	printf("prctl(" XLAT_KNOWN(0x38, "PR_GET_TAGGED_ADDR_CTRL")
     119  	       ", 0, 0, 0, 0) = ");
     120  	if (rc >= 0) {
     121  		printf("%#lx", rc);
     122  #if !XLAT_RAW
     123  		for (i = 0; i < ARRAY_SIZE(args); i++) {
     124  			if (args[i].val == (unsigned long) rc) {
     125  				printf(" (%s)", args[i].str);
     126  				break;
     127  			}
     128  		}
     129  
     130  		if (i == ARRAY_SIZE(args)) {
     131  			printf(" (");
     132  			print_tagged_addr_arg(rc);
     133  			printf(")");
     134  		}
     135  #endif /* !XLAT_RAW */
     136  		puts(INJ_STR);
     137  	} else {
     138  		printf("%s" INJ_STR "\n", errstr);
     139  	}
     140  
     141  	puts("+++ exited with 0 +++");
     142  	return 0;
     143  }