2 * Check decoding of clone3 syscall.
4 * Copyright (c) 2019 The strace developers.
7 * SPDX-License-Identifier: GPL-2.0-or-later
19 #ifdef HAVE_LINUX_SCHED_H
20 # include <linux/sched.h>
23 #ifdef HAVE_STRUCT_USER_DESC
32 #ifndef RETVAL_INJECTED
33 # define RETVAL_INJECTED 0
36 #ifndef HAVE_STRUCT_CLONE_ARGS
38 # include <linux/types.h>
40 # define XLAT_MACROS_ONLY
41 # include "xlat/clone_flags.h"
42 # undef XLAT_MACROS_ONLY
54 #endif /* !HAVE_STRUCT_CLONE_ARGS */
56 enum validity_flag_bits {
64 #define _(x_) x_ = 1 << x_##_BIT
76 static const int child_exit_status = 42;
79 static const long injected_retval = 42;
81 # define INJ_STR " (INJECTED)\n"
82 #else /* !RETVAL_INJECTED */
84 #endif /* RETVAL_INJECTED */
94 while (waitpid(pid, &status, WEXITED | __WCLONE) != pid) {
96 perror_msg_and_fail("waitpid(%d)", pid);
102 do_clone3_(void *args, kernel_ulong_t size, bool should_fail, int line)
104 long rc = syscall(__NR_clone3, args, size);
107 if (rc != injected_retval)
108 perror_msg_and_fail("%d: Unexpected injected return value "
109 "of a clone3() call (%ld instead of %ld)",
110 line, rc, injected_retval);
113 static int unimplemented_error = -1;
117 error_msg_and_fail("%d: Unexpected success"
118 " of a clone3() call", line);
119 if (unimplemented_error < 0)
120 unimplemented_error =
121 (errno == EINVAL) ? ENOSYS : errno;
123 if (rc < 0 && errno != unimplemented_error)
124 perror_msg_and_fail("%d: Unexpected failure"
125 " of a clone3() call", line);
129 _exit(child_exit_status);
131 if (rc > 0 && ((struct clone_args *) args)->exit_signal)
138 #define do_clone3(args_, size_, should_fail_) \
139 do_clone3_((args_), (size_), (should_fail_), __LINE__)
142 print_addr64(const char *pfx, uint64_t addr)
145 printf("%s%#" PRIx64, pfx, addr);
147 printf("%sNULL", pfx);
151 print_tls(const char *pfx, uint64_t arg_ptr, enum validity_flags vf)
153 #if defined HAVE_STRUCT_USER_DESC && defined __i386__
154 if (!(vf & TLS_VALID)) {
155 print_addr64(pfx, arg_ptr);
159 struct user_desc *arg = (struct user_desc *) (uintptr_t) arg_ptr;
161 printf("%s{entry_number=%d"
166 ", read_exec_only=%u"
167 ", limit_in_pages=%u"
168 ", seg_not_present=%u"
178 arg->seg_not_present,
181 print_addr64(pfx, arg_ptr);
186 print_clone3(struct clone_args *const arg, long rc, kernel_ulong_t sz,
187 enum validity_flags valid,
188 const char *flags_str, const char *es_str)
190 int saved_errno = errno;
192 if (!(valid & STRUCT_VALID)) {
198 printf("{flags=%#" PRIx64, (uint64_t) arg->flags);
200 if (flags_str[0] == '0')
201 printf("{flags=%#" PRIx64, (uint64_t) arg->flags);
203 printf("{flags=%#" PRIx64 " /* %s */",
204 (uint64_t) arg->flags, flags_str);
206 printf("{flags=%s", flags_str);
209 if (arg->flags & CLONE_PIDFD)
210 print_addr64(", pidfd=", arg->pidfd);
212 if (arg->flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
213 if (valid & CHILD_TID_VALID)
214 printf(", child_tid=[%d]",
215 *(int *) (uintptr_t) arg->child_tid);
217 print_addr64(", child_tid=", arg->child_tid);
220 if (arg->flags & CLONE_PARENT_SETTID)
221 print_addr64(", parent_tid=", arg->parent_tid);
223 printf(", exit_signal=%s", es_str);
224 print_addr64(", stack=", arg->stack);
225 printf(", stack_size=%" PRIx64, (uint64_t) arg->stack_size);
227 if (arg->flags & CLONE_SETTLS)
228 print_tls("tls=", arg->tls, valid);
237 if (arg->flags & CLONE_PIDFD) {
238 if (valid & PIDFD_VALID)
239 printf(" => {pidfd=[%d]",
240 *(int *) (uintptr_t) arg->pidfd);
242 print_addr64(" => {pidfd=", arg->pidfd);
247 if (arg->flags & CLONE_PARENT_SETTID) {
248 printf(comma ? ", " : " => {");
250 if (valid & PARENT_TID_VALID)
251 printf("parent_tid=[%d]",
252 *(int *) (uintptr_t) arg->parent_tid);
254 print_addr64("parent_tid=", arg->parent_tid);
267 main(int argc, char *argv[])
269 static const struct {
270 struct clone_args args;
272 enum validity_flags vf;
273 const char *flags_str;
277 false, 0, "0", "0" },
278 { { .flags = CLONE_PARENT_SETTID },
279 false, 0, "CLONE_PARENT_SETTID", "0" },
282 struct clone_args *arg = tail_alloc(sizeof(*arg));
283 struct clone_args *arg2 = tail_alloc(sizeof(*arg2) + 8);
284 int *pidfd = tail_alloc(sizeof(*pidfd));
285 int *child_tid = tail_alloc(sizeof(*child_tid));
286 int *parent_tid = tail_alloc(sizeof(*parent_tid));
289 #if defined HAVE_STRUCT_USER_DESC
290 struct user_desc *tls = tail_alloc(sizeof(*tls));
292 fill_memory(tls, sizeof(*tls));
294 int *tls = tail_alloc(sizeof(*tls));
298 *child_tid = 0xdeadface;
299 *parent_tid = 0xfeedbeef;
301 rc = do_clone3(NULL, 0, true);
302 printf("clone3(NULL, 0) = %s" INJ_STR, sprintrc(rc));
304 rc = do_clone3(arg + 1, sizeof(*arg), true);
305 printf("clone3(%p, %zu) = %s" INJ_STR,
306 arg + 1, sizeof(*arg), sprintrc(rc));
308 rc = do_clone3((char *) arg + sizeof(uint64_t),
309 sizeof(*arg) - sizeof(uint64_t), true);
310 printf("clone3(%p, %zu) = %s" INJ_STR,
311 (char *) arg + sizeof(uint64_t), sizeof(*arg) - sizeof(uint64_t),
315 memset(arg, 0, sizeof(*arg));
316 memset(arg2, 0, sizeof(*arg2) + 8);
318 rc = do_clone3(arg, 64, false);
319 printf("clone3({flags=0, exit_signal=0, stack=NULL, stack_size=0}, 64)"
323 rc = do_clone3(arg, sizeof(*arg) + 8, true);
324 printf("clone3({flags=0, exit_signal=0, stack=NULL, stack_size=0, ???}"
328 ", %zu) = %s" INJ_STR,
329 sizeof(*arg) + 8, sprintrc(rc));
331 rc = do_clone3(arg2, sizeof(*arg2) + 8, false);
332 printf("clone3({flags=0, exit_signal=0, stack=NULL, stack_size=0}"
333 ", %zu) = %s" INJ_STR,
334 sizeof(*arg2) + 8, sprintrc(rc));
337 * NB: the following check is purposedly fragile (it will break
338 * when system's struct clone_args has additional fields,
339 * so it signalises that the decoder needs to be updated.
341 arg2[1].flags = 0xfacefeeddeadc0de;
342 arg2->exit_signal = 0xdeadface00000000ULL | SIGCHLD;
343 rc = do_clone3(arg2, sizeof(*arg2) + 8, true);
344 printf("clone3({flags=0, exit_signal=%llu, stack=NULL, stack_size=0"
345 ", /* bytes %zu..%zu */ "
347 "\"\\xfa\\xce\\xfe\\xed\\xde\\xad\\xc0\\xde\""
349 "\"\\xde\\xc0\\xad\\xde\\xed\\xfe\\xce\\xfa\""
352 "} => {/* bytes %zu..%zu */ "
354 "\"\\xfa\\xce\\xfe\\xed\\xde\\xad\\xc0\\xde\""
356 "\"\\xde\\xc0\\xad\\xde\\xed\\xfe\\xce\\xfa\""
358 #endif /* RETVAL_INJECTED */
359 "}, %zu) = %s" INJ_STR,
360 0xdeadface00000000ULL | SIGCHLD,
361 sizeof(*arg2), sizeof(*arg2) + 7,
363 sizeof(*arg2), sizeof(*arg2) + 7,
365 sizeof(*arg2) + 8, sprintrc(rc));
367 arg2->exit_signal = 0xdeadc0de;
368 rc = do_clone3(arg2, sizeof(*arg) + 16, true);
369 printf("clone3({flags=0, exit_signal=3735929054, stack=NULL"
370 ", stack_size=0, ???}"
374 ", %zu) = %s" INJ_STR,
375 sizeof(*arg) + 16, sprintrc(rc));
377 arg->flags = 0xfacefeedbeefc0de;
378 arg->exit_signal = 0x1e55c0de;
379 rc = do_clone3(arg, 64, true);
380 printf("clone3({flags=%s, child_tid=NULL, exit_signal=508936414"
381 ", stack=NULL, stack_size=0, tls=NULL}, 64) = %s" INJ_STR,
382 XLAT_KNOWN(0xfacefeedbeefc0de, "CLONE_VFORK|CLONE_PARENT"
383 "|CLONE_THREAD|CLONE_NEWNS|CLONE_SYSVSEM|CLONE_SETTLS"
384 "|CLONE_CHILD_CLEARTID|CLONE_UNTRACED|CLONE_NEWCGROUP"
385 "|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|CLONE_IO"
386 "|0xfacefeed004000de"), sprintrc(rc));
388 arg->flags = 0xdec0dead004000ffULL;
389 arg->exit_signal = 250;
390 arg->stack = 0xface1e55beeff00dULL;
391 arg->stack_size = 0xcaffeedefacedca7ULL;
392 rc = do_clone3(arg, 64, true);
393 printf("clone3({flags=%s, exit_signal=250"
394 ", stack=0xface1e55beeff00d, stack_size=0xcaffeedefacedca7}, 64)"
396 XLAT_UNKNOWN(0xdec0dead004000ff, "CLONE_???"),
399 arg->exit_signal = SIGCHLD;
403 const char *flag_str;
405 const char *field_name;
409 { ARG_STR(CLONE_PIDFD),
410 (uint64_t *) &arg->pidfd,
411 "pidfd", pidfd, true },
412 { ARG_STR(CLONE_CHILD_SETTID),
413 (uint64_t *) &arg->child_tid,
414 "child_tid", child_tid },
415 { ARG_STR(CLONE_CHILD_CLEARTID),
416 (uint64_t *) &arg->child_tid,
417 "child_tid", child_tid },
418 { ARG_STR(CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID),
419 (uint64_t *) &arg->child_tid,
420 "child_tid", child_tid },
421 { ARG_STR(CLONE_PARENT_SETTID),
422 (uint64_t *) &arg->parent_tid,
423 "parent_tid", parent_tid, true },
426 for (size_t i = 0; i < ARRAY_SIZE(pid_fields); i++) {
430 arg->flags = 0xbad0000000000001ULL | pid_fields[i].flag;
433 snprintf(flag_str, sizeof(flag_str), "%#" PRIx64,
434 (uint64_t) arg->flags);
436 snprintf(flag_str, sizeof(flag_str),
437 "%#" PRIx64 " /* %s|0xbad0000000000001 */",
438 (uint64_t) arg->flags, pid_fields[i].flag_str);
440 snprintf(flag_str, sizeof(flag_str), "%s|0xbad0000000000001",
441 pid_fields[i].flag_str);
444 pid_fields[i].field[0] = 0;
445 rc = do_clone3(arg, 64, true);
446 rc_str = sprintrc(rc);
447 printf("clone3({flags=%s, %s=NULL"
448 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
449 ", stack=0xface1e55beeff00d"
450 ", stack_size=0xcaffeedefacedca7}",
451 flag_str, pid_fields[i].field_name);
453 if (pid_fields[i].deref_exiting)
454 printf(" => {%s=NULL}", pid_fields[i].field_name);
455 #endif /* RETVAL_INJECTED */
456 printf(", 64) = %s" INJ_STR, rc_str);
458 pid_fields[i].field[0] = (uintptr_t) (pid_fields[i].ptr + 1);
459 rc = do_clone3(arg, 64, true);
460 rc_str = sprintrc(rc);
461 printf("clone3({flags=%s, %s=%p"
462 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
463 ", stack=0xface1e55beeff00d"
464 ", stack_size=0xcaffeedefacedca7}",
465 flag_str, pid_fields[i].field_name,
466 pid_fields[i].ptr + 1);
468 if (pid_fields[i].deref_exiting)
469 printf(" => {%s=%p}",
470 pid_fields[i].field_name, pid_fields[i].ptr + 1);
471 #endif /* RETVAL_INJECTED */
472 printf(", 64) = %s" INJ_STR, rc_str);
474 pid_fields[i].field[0] = (uintptr_t) pid_fields[i].ptr;
475 rc = do_clone3(arg, 64, true);
476 rc_str = sprintrc(rc);
477 printf("clone3({flags=%s, %s=%p"
478 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
479 ", stack=0xface1e55beeff00d"
480 ", stack_size=0xcaffeedefacedca7}",
481 flag_str, pid_fields[i].field_name,
484 if (pid_fields[i].deref_exiting)
485 printf(" => {%s=[%d]}",
486 pid_fields[i].field_name, *pid_fields[i].ptr);
487 #endif /* RETVAL_INJECTED */
488 printf(", 64) = %s" INJ_STR, rc_str);
491 arg->flags = 0xbad0000000000001ULL | CLONE_SETTLS;
492 rc = do_clone3(arg, 64, true);
493 printf("clone3({flags="
494 XLAT_KNOWN(0xbad0000000080001, "CLONE_SETTLS|0xbad0000000000001")
495 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
496 ", stack=0xface1e55beeff00d"
497 ", stack_size=0xcaffeedefacedca7, tls=NULL}, 64) = %s" INJ_STR,
500 arg->tls = (uintptr_t) (tls + 1);
501 rc = do_clone3(arg, 64, true);
502 printf("clone3({flags="
503 XLAT_KNOWN(0xbad0000000080001, "CLONE_SETTLS|0xbad0000000000001")
504 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
505 ", stack=0xface1e55beeff00d"
506 ", stack_size=0xcaffeedefacedca7, tls=%p}, 64) = %s" INJ_STR,
507 tls + 1, sprintrc(rc));
509 arg->tls = (uintptr_t) tls;
510 rc = do_clone3(arg, 64, true);
511 printf("clone3({flags="
512 XLAT_KNOWN(0xbad0000000080001, "CLONE_SETTLS|0xbad0000000000001")
513 ", exit_signal=" XLAT_KNOWN(SIGCHLD, "SIGCHLD")
514 ", stack=0xface1e55beeff00d, stack_size=0xcaffeedefacedca7, tls="
515 #if defined HAVE_STRUCT_USER_DESC && defined __i386__
516 "{entry_number=2206368128, base_addr=0x87868584"
517 ", limit=0x8b8a8988, seg_32bit=0, contents=2, read_exec_only=1"
518 ", limit_in_pages=0, seg_not_present=0, useable=0}"
522 "}, 64) = %s" INJ_STR,
523 #if !defined HAVE_STRUCT_USER_DESC || !defined __i386__
528 for (size_t i = 0; i < ARRAY_SIZE(arg_vals); i++) {
529 memcpy(arg, &arg_vals[i].args, sizeof(*arg));
531 rc = do_clone3(arg, sizeof(*arg), arg_vals[i].should_fail);
533 print_clone3(arg, rc, sizeof(*arg),
534 arg_vals[i].vf | STRUCT_VALID,
535 arg_vals[i].flags_str, arg_vals[i].es_str);
536 printf(", %zu) = %s" INJ_STR, sizeof(*arg), sprintrc(rc));
539 puts("+++ exited with 0 +++");