(root)/
strace-6.5/
tests-mx32/
prctl-mdwe.c
       1  /*
       2   * Check decoding of prctl PR_GET_MDWE/PR_SET_MDWE operations.
       3   *
       4   * Copyright (c) 2021-2023 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 <errno.h>
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <unistd.h>
      16  #include <linux/prctl.h>
      17  
      18  static long injected_val;
      19  
      20  static long
      21  do_prctl(kernel_ulong_t cmd, kernel_ulong_t arg2, kernel_ulong_t arg3,
      22  	 kernel_ulong_t arg4, kernel_ulong_t arg5)
      23  {
      24  	long rc = syscall(__NR_prctl, cmd, arg2, arg3, arg4, arg5);
      25  
      26  	if (rc != injected_val) {
      27  		error_msg_and_fail("Return value (%ld) differs from expected "
      28  						   "injected value (%ld)",
      29  						   rc, injected_val);
      30  	}
      31  
      32  	return rc;
      33  }
      34  
      35  int
      36  main(int argc, char **argv)
      37  {
      38  	static const kernel_ulong_t bogus_arg2 =
      39  			(kernel_ulong_t) 0xdecafeedbeefda7eULL;
      40  	static const kernel_ulong_t bogus_arg3 =
      41  			(kernel_ulong_t) 0xbadc0dedfacef00dULL;
      42  	static const kernel_ulong_t bogus_arg4 =
      43  			(kernel_ulong_t) 0xcafeda7efeedbeefULL;
      44  	static const kernel_ulong_t bogus_arg5 =
      45  			(kernel_ulong_t) 0xfa57beeffacefeedULL;
      46  
      47  	static const struct {
      48  		long arg;
      49  		const char *str;
      50  	} get_strs[] = {
      51  			{-1,         ""},
      52  			{0,          ""},
      53  			{1,          " (PR_MDWE_REFUSE_EXEC_GAIN)"},
      54  			{2,          ""},
      55  			{3,          " (PR_MDWE_REFUSE_EXEC_GAIN|0x2)"},
      56  			{0x7ea1cafe, ""},
      57  	};
      58  	static const struct {
      59  		kernel_ulong_t arg;
      60  		const char *str;
      61  	} set_strs[] = {
      62  			{0,          "0"},
      63  			{1,          "PR_MDWE_REFUSE_EXEC_GAIN"},
      64  			{2,          "0x2 /* PR_MDWE_??? */"},
      65  			{3,          "PR_MDWE_REFUSE_EXEC_GAIN|0x2"},
      66  			{0x7ea1cafe, "0x7ea1cafe /* PR_MDWE_??? */"}
      67  	};
      68  
      69  	long rc;
      70  	unsigned long num_skip;
      71  	const char *str = NULL;
      72  	bool locked = false;
      73  
      74  	if (argc < 3)
      75  		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
      76  
      77  	num_skip = strtoul(argv[1], NULL, 0);
      78  	injected_val = strtol(argv[2], NULL, 0);
      79  
      80  	for (size_t i = 0; i < num_skip; i++) {
      81  		if ((prctl_marker() != injected_val) ||
      82  		    ((injected_val == -1) && (errno != ENOTTY)))
      83  			continue;
      84  
      85  		locked = true;
      86  		break;
      87  	}
      88  
      89  	if (!locked)
      90  		error_msg_and_fail("Have not locked on prctl(-1, -2, -3, -4"
      91  				   ", -5) returning %ld", injected_val);
      92  
      93  	/* PR_GET_MDWE */
      94  	for (unsigned int j = 0; j < 2; j++) {
      95  		if (j) {
      96  			rc = do_prctl(PR_GET_MDWE, bogus_arg2, bogus_arg3,
      97  						   bogus_arg4, bogus_arg5);
      98  		} else {
      99  			rc = do_prctl(PR_GET_MDWE, 0, 0, 0, 0);
     100  		}
     101  
     102  		const char *errstr = sprintrc(rc);
     103  
     104  		for (size_t i = 0; i < ARRAY_SIZE(get_strs); i++) {
     105  			if (get_strs[i].arg == rc) {
     106  				str = get_strs[i].str;
     107  				break;
     108  			}
     109  		}
     110  		if (!str)
     111  			error_msg_and_fail("Unknown return value: %ld", rc);
     112  
     113  		printf("prctl(PR_GET_MDWE, %s) = ", j ?
     114  #if SIZEOF_KERNEL_LONG_T > 4
     115  		       "0xdecafeedbeefda7e, 0xbadc0dedfacef00d"
     116  		       ", 0xcafeda7efeedbeef, 0xfa57beeffacefeed"
     117  #else
     118  		       "0xbeefda7e, 0xfacef00d, 0xfeedbeef, 0xfacefeed"
     119  #endif
     120  		       : "0, 0, 0, 0");
     121  		if (rc < 0)
     122  			printf("%s", errstr);
     123  		else
     124  			printf("%#lx", rc);
     125  		printf("%s (INJECTED)\n", str);
     126  	}
     127  
     128  	/* PR_SET_FP_MODE */
     129  	for (size_t i = 0; i < ARRAY_SIZE(set_strs); i++) {
     130  		rc = do_prctl(PR_SET_MDWE, set_strs[i].arg, 0, 0, 0);
     131  		printf("prctl(PR_SET_MDWE, %s, 0, 0, 0) = %s (INJECTED)\n",
     132  		       set_strs[i].str, sprintrc(rc));
     133  
     134  		rc = do_prctl(PR_SET_MDWE, set_strs[i].arg,
     135  			      bogus_arg3, bogus_arg4, bogus_arg5);
     136  		printf("prctl(PR_SET_MDWE, %s, %s) = %s (INJECTED)\n",
     137  		       set_strs[i].str,
     138  #if SIZEOF_KERNEL_LONG_T > 4
     139  		       "0xbadc0dedfacef00d, 0xcafeda7efeedbeef"
     140  		       ", 0xfa57beeffacefeed"
     141  #else
     142  		       "0xfacef00d, 0xfeedbeef, 0xfacefeed"
     143  #endif
     144  		       , sprintrc(rc));
     145  	}
     146  
     147  	puts("+++ exited with 0 +++");
     148  	return 0;
     149  }