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 }