1 /*
2 * Check decoding of prctl PR_SCHED_CORE operation.
3 *
4 * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>.
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 <inttypes.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <linux/prctl.h>
18
19 #include "pidns.h"
20
21 struct op_str {
22 unsigned int op;
23 const char *str;
24 };
25
26 #ifdef INJECT_RETVAL
27 # define NUM_SKIP 256
28 # define INJ_STR " (INJECTED)"
29 #else
30 # define NUM_SKIP 1
31 # define INJ_STR ""
32 #endif
33
34 int
35 main(int argc, char *argv[])
36 {
37 PIDNS_TEST_INIT;
38
39 long rc;
40
41 unsigned long num_skip = NUM_SKIP;
42
43 if (argc >= 2)
44 num_skip = strtoul(argv[1], NULL, 0);
45
46 for (size_t i = 0; i < num_skip; i++) {
47 rc = prctl_marker();
48 #ifdef PIDNS_TRANSLATION
49 const char *errstr = sprintrc(rc);
50 pidns_print_leader();
51 printf("prctl(" XLAT_UNKNOWN(0xffffffff, "PR_???")
52 ", 0xfffffffe, 0xfffffffd, 0xfffffffc, 0xfffffffb) = ");
53
54 if (rc < 0) {
55 puts(errstr);
56 } else {
57 printf("%ld (INJECTED)\n", rc);
58 }
59 #endif
60
61 if (rc < 0)
62 continue;
63
64 break;
65 }
66
67 static const struct {
68 unsigned int decode_ptr:1,
69 valid:1;
70 unsigned int op;
71 const char *str;
72 } ops[] = {
73 { true, true, ARG_STR(PR_SCHED_CORE_GET) },
74 { false, true, ARG_STR(PR_SCHED_CORE_CREATE) },
75 { false, true, ARG_STR(PR_SCHED_CORE_SHARE_TO) },
76 { false, true, ARG_STR(PR_SCHED_CORE_SHARE_FROM) },
77 { false, false, 4, "PR_SCHED_CORE_???" },
78 };
79 static const struct {
80 unsigned int val;
81 const char *str;
82 } pidtypes[] = {
83 { 0, "PIDTYPE_PID" },
84 { 1, "PIDTYPE_TGID" },
85 { 2, "PIDTYPE_PGID" },
86 { 3, "PIDTYPE_SID" },
87 { 4, "PIDTYPE_???" },
88 { -1U, "PIDTYPE_???" },
89 };
90
91 int ids[5];
92 ids[0] = syscall(__NR_gettid);
93 ids[1] = getpid();
94 ids[2] = getpgid(0);
95 ids[3] = getsid(0);
96 ids[4] = -1;
97
98 TAIL_ALLOC_OBJECT_VAR_PTR(uint64_t, uptr);
99 uint64_t *uptrs[] = { NULL, uptr + 1, uptr };
100
101 for (size_t i = 0; i < ARRAY_SIZE(ops); i++) {
102 for (size_t j = 0; j < ARRAY_SIZE(pidtypes); j++) {
103 for (size_t k = 0; k < ARRAY_SIZE(uptrs); k++) {
104 *uptr = 0xdeadc0debadc0dedULL;
105 rc = syscall(__NR_prctl, PR_SCHED_CORE,
106 ops[i].op | F8ILL_KULONG_MASK,
107 ids[MIN(pidtypes[j].val, 4)]
108 | F8ILL_KULONG_MASK,
109 pidtypes[j].val
110 | F8ILL_KULONG_MASK,
111 uptrs[k]);
112 const char *errstr = sprintrc(rc);
113
114 pidns_print_leader();
115 printf("prctl("
116 XLAT_KNOWN(0x3e, "PR_SCHED_CORE") ", ");
117 if (ops[i].valid) {
118 printf(XLAT_FMT,
119 XLAT_SEL(ops[i].op, ops[i].str));
120 } else {
121 printf("%#x"
122 NRAW(" /* PR_SCHED_CORE_??? */"),
123 ops[i].op);
124 }
125 printf(", %d%s, %#x" NRAW(" /* %s */") ", ",
126 ids[MIN(pidtypes[j].val, 4)],
127 pidns_pid2str(pidtypes[j].val),
128 pidtypes[j].val
129 #if !XLAT_RAW
130 , pidtypes[j].str
131 #endif
132 );
133
134 if (uptrs[k]) {
135 if (uptrs[k] == uptr
136 && ops[i].decode_ptr && rc >= 0)
137 #ifdef INJECT_RETVAL
138 printf("[0xdeadc0debadc0ded]");
139 #else
140 printf("[%#" PRIx64 "]", *uptr);
141 #endif
142 else
143 printf("%p", uptrs[k]);
144 } else {
145 printf("NULL");
146 }
147
148 printf(") = %s" INJ_STR "\n", errstr);
149 }
150 }
151 }
152
153 pidns_print_leader();
154 puts("+++ exited with 0 +++");
155 return 0;
156 }