1 /*
2 * Check decoding of prctl PR_PAC_RESET_KEYS operation.
3 *
4 * Copyright (c) 2021 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 #include "xlat.h"
18 #include "xlat/pr_pac_enabled_keys.h"
19
20 #ifdef INJECT_RETVAL
21 # define INJ_STR " (INJECTED)"
22 #else
23 # define INJ_STR ""
24 #endif
25
26 #define PR_PAC_ENABLE_FLAGS_MASK \
27 (PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY)
28
29 int
30 main(int argc, char *argv[])
31 {
32 prctl_marker();
33
34 #ifdef INJECT_RETVAL
35 unsigned long num_skip;
36 long inject_retval;
37 bool locked = false;
38
39 if (argc < 3)
40 error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
41
42 num_skip = strtoul(argv[1], NULL, 0);
43 inject_retval = strtol(argv[2], NULL, 0);
44
45 for (size_t i = 0; i < num_skip; i++) {
46 if (prctl_marker() != inject_retval)
47 continue;
48
49 locked = true;
50 break;
51 }
52
53 if (!locked)
54 error_msg_and_fail("Have not locked on prctl(-1, -2, -3, -4"
55 ", -5) returning %ld", inject_retval);
56 #endif /* INJECT_RETVAL */
57
58 static const struct {
59 kernel_ulong_t val;
60 const char *str;
61 } args[] = {
62 { ARG_STR(0) },
63 { ARG_STR(PR_PAC_APIAKEY) },
64 { ARG_STR(PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY|0x10) },
65 { 0x7ffffff0, NVERB("0x7ffffff0 /* ") "PR_PAC_???" NVERB(" */") },
66 };
67 long rc;
68 const char *errstr;
69 size_t i = 0;
70
71 for (i = 0; i < ARRAY_SIZE(args); i++) {
72 for (size_t j = 0; j < ARRAY_SIZE(args); j++) {
73 rc = syscall(__NR_prctl, PR_PAC_SET_ENABLED_KEYS,
74 args[i].val, args[j].val, 0, 1);
75 errstr = sprintrc(rc);
76 printf("prctl("
77 XLAT_KNOWN(0x3c, "PR_PAC_SET_ENABLED_KEYS"));
78 if (args[i].val) {
79 printf(", " XLAT_FMT_LL,
80 XLAT_SEL((unsigned long long) args[i].val,
81 args[i].str));
82 } else {
83 printf(", 0");
84 }
85 if (args[j].val) {
86 printf(", " XLAT_FMT_LL,
87 XLAT_SEL((unsigned long long) args[j].val,
88 args[j].str));
89 } else {
90 printf(", 0");
91 }
92 printf(", 0, 0x1) = %s" INJ_STR "\n", errstr);
93 }
94 }
95
96 rc = syscall(__NR_prctl, PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0);
97 errstr = sprintrc(rc);
98 printf("prctl(" XLAT_KNOWN(0x3d, "PR_PAC_GET_ENABLED_KEYS")
99 ", 0, 0, 0, 0) = ");
100
101 if (rc > 0) {
102 printf("%#lx", rc);
103 #if !XLAT_RAW
104 for (i = 0; i < ARRAY_SIZE(args); i++) {
105 if (!(rc & PR_PAC_ENABLE_FLAGS_MASK))
106 break;
107
108 if (args[i].val == (unsigned long) rc) {
109 printf(" (%s)", args[i].str);
110 break;
111 }
112 }
113
114 if (i == ARRAY_SIZE(args)) {
115 printf(" (");
116 printflags(pr_pac_enabled_keys, rc, "PR_PAC_???");
117 printf(")");
118 }
119 #endif /* !XLAT_RAW */
120 puts(INJ_STR);
121 } else {
122 printf("%s" INJ_STR "\n", errstr);
123 }
124
125
126 puts("+++ exited with 0 +++");
127 return 0;
128 }