1 /*
2 * Check decoding of sched_getattr and sched_setattr syscalls.
3 *
4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-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
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <sched.h>
17 #include <unistd.h>
18 #include "pidns.h"
19 #include "sched_attr.h"
20 #include "xlat.h"
21 #include "xlat/schedulers.h"
22
23 static const char *errstr;
24
25 static long
26 sys_sched_getattr(kernel_ulong_t pid, kernel_ulong_t attr,
27 kernel_ulong_t size, kernel_ulong_t flags)
28 {
29 long rc = syscall(__NR_sched_getattr, pid, attr, size, flags);
30 errstr = sprintrc(rc);
31 return rc;
32 }
33
34 static long
35 sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags)
36 {
37 long rc = syscall(__NR_sched_setattr, pid, attr, flags);
38 errstr = sprintrc(rc);
39 return rc;
40 }
41
42 int
43 main(void)
44 {
45 PIDNS_TEST_INIT;
46
47 static const kernel_ulong_t bogus_pid =
48 (kernel_ulong_t) 0xdefacedfacefeedULL;
49 static const kernel_ulong_t bogus_size =
50 (kernel_ulong_t) 0xdefacedcafef00dULL;
51 static const kernel_ulong_t bogus_flags =
52 (kernel_ulong_t) 0xdefaceddeadc0deULL;
53
54 const int pid = getpid();
55 const char *pid_str = pidns_pid2str(PT_TGID);
56
57 TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr);
58 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize);
59 void *const efault = attr + 1;
60
61 sys_sched_getattr(pid, 0, 0, 0);
62 pidns_print_leader();
63 printf("sched_getattr(%d%s, NULL, 0, 0) = %s\n",
64 pid, pid_str, errstr);
65
66 sys_sched_getattr(0, (unsigned long) attr, 0, 0);
67 pidns_print_leader();
68 printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr);
69
70 sys_sched_getattr(bogus_pid, 0, 0, 0);
71 pidns_print_leader();
72 printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr);
73
74 sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags);
75 pidns_print_leader();
76 printf("sched_getattr(-1, %p, %s%u, %u) = %s\n",
77 attr,
78 #if defined __arm64__ || defined __aarch64__
79 "0xdefaced<<32|",
80 #else
81 "",
82 #endif
83 (unsigned) bogus_size, (unsigned) bogus_flags, errstr);
84
85 sys_sched_getattr(0, (unsigned long) efault, SCHED_ATTR_MIN_SIZE, 0);
86 pidns_print_leader();
87 printf("sched_getattr(0, %p, %u, 0) = %s\n",
88 efault, (unsigned) SCHED_ATTR_MIN_SIZE, errstr);
89
90 if (sys_sched_getattr(0, (unsigned long) attr, SCHED_ATTR_MIN_SIZE, 0))
91 perror_msg_and_skip("sched_getattr");
92 pidns_print_leader();
93 printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
94 printxval(schedulers, attr->sched_policy, NULL);
95 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
96 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
97 ", sched_period=%" PRIu64 "}, %u, 0) = 0\n",
98 attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
99 attr->sched_nice,
100 attr->sched_priority,
101 attr->sched_runtime,
102 attr->sched_deadline,
103 attr->sched_period,
104 (unsigned) SCHED_ATTR_MIN_SIZE);
105
106 sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0);
107 pidns_print_leader();
108 printf("sched_getattr(0, %p, %u, 0) = %s\n",
109 efault, (unsigned) sizeof(*attr), errstr);
110
111 if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0))
112 perror_msg_and_skip("sched_getattr");
113 pidns_print_leader();
114 printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
115 printxval(schedulers, attr->sched_policy, NULL);
116 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
117 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
118 ", sched_period=%" PRIu64,
119 attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
120 attr->sched_nice,
121 attr->sched_priority,
122 attr->sched_runtime,
123 attr->sched_deadline,
124 attr->sched_period);
125 if (attr->size >= SCHED_ATTR_SIZE_VER1) {
126 printf(", sched_util_min=%u, sched_util_max=%u",
127 attr->sched_util_min,
128 attr->sched_util_max);
129 }
130 printf("}, %u, 0) = 0\n", (unsigned) sizeof(*attr));
131
132 #if defined __arm64__ || defined __aarch64__
133 long rc =
134 #endif
135 sys_sched_getattr(F8ILL_KULONG_MASK, (unsigned long) attr,
136 F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK);
137 #if defined __arm64__ || defined __aarch64__
138 if (rc) {
139 pidns_print_leader();
140 printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n",
141 attr, (unsigned) sizeof(*attr), errstr);
142 } else
143 #endif
144 {
145 pidns_print_leader();
146 printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
147 printxval(schedulers, attr->sched_policy, NULL);
148 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
149 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
150 ", sched_period=%" PRIu64,
151 attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
152 attr->sched_nice,
153 attr->sched_priority,
154 attr->sched_runtime,
155 attr->sched_deadline,
156 attr->sched_period);
157 if (attr->size >= SCHED_ATTR_SIZE_VER1) {
158 printf(", sched_util_min=%u, sched_util_max=%u",
159 attr->sched_util_min,
160 attr->sched_util_max);
161 }
162 printf("}, %u, 0) = 0\n", (unsigned) sizeof(*attr));
163 }
164
165 sys_sched_setattr(bogus_pid, 0, 0);
166 pidns_print_leader();
167 printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr);
168
169 attr->sched_flags |= 1;
170
171 if (sys_sched_setattr(pid, (unsigned long) attr, 0))
172 perror_msg_and_skip("sched_setattr");
173 pidns_print_leader();
174 printf("sched_setattr(%d%s, {size=%u, sched_policy=",
175 pid, pid_str, attr->size);
176 printxval(schedulers, attr->sched_policy, NULL);
177 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
178 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
179 ", sched_period=%" PRIu64,
180 "SCHED_FLAG_RESET_ON_FORK",
181 attr->sched_nice,
182 attr->sched_priority,
183 attr->sched_runtime,
184 attr->sched_deadline,
185 attr->sched_period);
186 if (attr->size >= SCHED_ATTR_SIZE_VER1) {
187 printf(", sched_util_min=%u, sched_util_max=%u",
188 attr->sched_util_min,
189 attr->sched_util_max);
190 }
191 printf("}, 0) = 0\n");
192
193 sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr,
194 F8ILL_KULONG_MASK);
195 pidns_print_leader();
196 printf("sched_setattr(0, {size=%u, sched_policy=", attr->size);
197 printxval(schedulers, attr->sched_policy, NULL);
198 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
199 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
200 ", sched_period=%" PRIu64,
201 "SCHED_FLAG_RESET_ON_FORK",
202 attr->sched_nice,
203 attr->sched_priority,
204 attr->sched_runtime,
205 attr->sched_deadline,
206 attr->sched_period);
207 if (attr->size >= SCHED_ATTR_SIZE_VER1) {
208 printf(", sched_util_min=%u, sched_util_max=%u",
209 attr->sched_util_min,
210 attr->sched_util_max);
211 }
212 printf("}, 0) = 0\n");
213
214 *psize = attr->size;
215
216 sys_sched_setattr(0, (unsigned long) psize, 0);
217 pidns_print_leader();
218 printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr);
219
220 attr->size = 0;
221
222 sys_sched_setattr(0, (unsigned long) attr, 0);
223 pidns_print_leader();
224 printf("sched_setattr(0, {size=%u, sched_policy=", attr->size);
225 printxval(schedulers, attr->sched_policy, NULL);
226 printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
227 ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
228 ", sched_period=%" PRIu64 "}, 0) = 0\n",
229 "SCHED_FLAG_RESET_ON_FORK",
230 attr->sched_nice,
231 attr->sched_priority,
232 attr->sched_runtime,
233 attr->sched_deadline,
234 attr->sched_period);
235
236 attr->size = 1;
237
238 sys_sched_setattr(0, (unsigned long) attr, 0);
239 pidns_print_leader();
240 printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n",
241 1, attr->size, errstr);
242
243 attr->size = SCHED_ATTR_MIN_SIZE - 1;
244
245 sys_sched_setattr(0, (unsigned long) attr, 0);
246 pidns_print_leader();
247 printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n",
248 SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr);
249
250 attr->size = 0x90807060;
251 attr->sched_policy = 0xca7faced;
252 attr->sched_flags = 0xbadc0ded1057da80ULL;
253 attr->sched_nice = 0xafbfcfdf;
254 attr->sched_priority = 0xb8c8d8e8;
255 attr->sched_runtime = 0xbadcaffedeadf157ULL;
256 attr->sched_deadline = 0xc0de70a57badac75ULL;
257 attr->sched_period = 0xded1ca7edda7aca7ULL;
258
259 sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
260 pidns_print_leader();
261 printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, "
262 "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, "
263 "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
264 "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 ", "
265 "sched_util_min=%u, sched_util_max=%u, ...}, %u) = %s\n",
266 (int) bogus_pid,
267 attr->size,
268 attr->sched_policy,
269 attr->sched_flags,
270 attr->sched_nice,
271 attr->sched_priority,
272 attr->sched_runtime,
273 attr->sched_deadline,
274 attr->sched_period,
275 attr->sched_util_min,
276 attr->sched_util_max,
277 (unsigned) bogus_flags, errstr);
278
279 if (F8ILL_KULONG_SUPPORTED) {
280 const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
281
282 sys_sched_getattr(0, ill, sizeof(*attr), 0);
283 printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
284 (unsigned long long) ill, (unsigned) sizeof(*attr),
285 errstr);
286
287 sys_sched_setattr(0, ill, 0);
288 printf("sched_setattr(0, %#llx, 0) = %s\n",
289 (unsigned long long) ill, errstr);
290 }
291
292
293 attr->size = 0x90807060;
294 attr->sched_policy = 0xca7faced;
295 attr->sched_flags = 0x87ULL;
296 attr->sched_nice = 0xafbfcfdf;
297 attr->sched_priority = 0xb8c8d8e8;
298 attr->sched_runtime = 0xbadcaffedeadf157ULL;
299 attr->sched_deadline = 0xc0de70a57badac75ULL;
300 attr->sched_period = 0xded1ca7edda7aca7ULL;
301
302 sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
303 pidns_print_leader();
304 printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, "
305 "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|"
306 "SCHED_FLAG_DL_OVERRUN|0x80, "
307 "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
308 "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 ", "
309 "sched_util_min=%u, sched_util_max=%u, ...}, %u) = %s\n",
310 (int) bogus_pid,
311 attr->size,
312 attr->sched_policy,
313 attr->sched_nice,
314 attr->sched_priority,
315 attr->sched_runtime,
316 attr->sched_deadline,
317 attr->sched_period,
318 attr->sched_util_min,
319 attr->sched_util_max,
320 (unsigned) bogus_flags, errstr);
321
322 if (F8ILL_KULONG_SUPPORTED) {
323 const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
324
325 sys_sched_getattr(0, ill, sizeof(*attr), 0);
326 pidns_print_leader();
327 printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
328 (unsigned long long) ill, (unsigned) sizeof(*attr),
329 errstr);
330
331 sys_sched_setattr(0, ill, 0);
332 pidns_print_leader();
333 printf("sched_setattr(0, %#llx, 0) = %s\n",
334 (unsigned long long) ill, errstr);
335 }
336
337 attr->size = SCHED_ATTR_MIN_SIZE;
338 attr->sched_policy = 0xdefaced;
339 attr->sched_flags = 0x8fULL;
340
341 sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
342 pidns_print_leader();
343 printf("sched_setattr(%d, {size=%u, "
344 "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|"
345 "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_KEEP_POLICY|0x80, "
346 "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
347 "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 "}, %u)"
348 " = %s\n",
349 (int) bogus_pid,
350 attr->size,
351 attr->sched_nice,
352 attr->sched_priority,
353 attr->sched_runtime,
354 attr->sched_deadline,
355 attr->sched_period,
356 (unsigned) bogus_flags, errstr);
357
358 if (F8ILL_KULONG_SUPPORTED) {
359 const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
360
361 sys_sched_getattr(0, ill, sizeof(*attr), 0);
362 pidns_print_leader();
363 printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
364 (unsigned long long) ill, (unsigned) sizeof(*attr),
365 errstr);
366
367 sys_sched_setattr(0, ill, 0);
368 pidns_print_leader();
369 printf("sched_setattr(0, %#llx, 0) = %s\n",
370 (unsigned long long) ill, errstr);
371 }
372
373 attr->size = SCHED_ATTR_SIZE_VER1;
374 attr->sched_flags = 0xe7ULL;
375
376 sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
377 pidns_print_leader();
378 printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, "
379 "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|"
380 "SCHED_FLAG_DL_OVERRUN|SCHED_FLAG_UTIL_CLAMP_MIN"
381 "|SCHED_FLAG_UTIL_CLAMP_MAX|0x80, "
382 "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
383 "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 ", "
384 "sched_util_min=%u, sched_util_max=%u}, %u) = %s\n",
385 (int) bogus_pid,
386 attr->size,
387 attr->sched_policy,
388 attr->sched_nice,
389 attr->sched_priority,
390 attr->sched_runtime,
391 attr->sched_deadline,
392 attr->sched_period,
393 attr->sched_util_min,
394 attr->sched_util_max,
395 (unsigned) bogus_flags, errstr);
396
397 if (F8ILL_KULONG_SUPPORTED) {
398 const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
399
400 sys_sched_getattr(0, ill, sizeof(*attr), 0);
401 pidns_print_leader();
402 printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
403 (unsigned long long) ill, (unsigned) sizeof(*attr),
404 errstr);
405
406 sys_sched_setattr(0, ill, 0);
407 pidns_print_leader();
408 printf("sched_setattr(0, %#llx, 0) = %s\n",
409 (unsigned long long) ill, errstr);
410 }
411
412 attr->sched_flags = 0xcaffee90LL;
413
414 sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
415 pidns_print_leader();
416 printf("sched_setattr(%d, {size=%u, sched_flags=SCHED_FLAG_KEEP_PARAMS"
417 "|0xcaffee80, sched_util_min=%u, sched_util_max=%u}, %u) = %s\n",
418 (int) bogus_pid,
419 attr->size,
420 attr->sched_util_min,
421 attr->sched_util_max,
422 (unsigned) bogus_flags, errstr);
423
424 if (F8ILL_KULONG_SUPPORTED) {
425 const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
426
427 sys_sched_getattr(0, ill, sizeof(*attr), 0);
428 pidns_print_leader();
429 printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
430 (unsigned long long) ill, (unsigned) sizeof(*attr),
431 errstr);
432
433 sys_sched_setattr(0, ill, 0);
434 pidns_print_leader();
435 printf("sched_setattr(0, %#llx, 0) = %s\n",
436 (unsigned long long) ill, errstr);
437 }
438
439 pidns_print_leader();
440 puts("+++ exited with 0 +++");
441 return 0;
442 }