1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 #ifndef _CLONE3_SELFTESTS_H
4 #define _CLONE3_SELFTESTS_H
5 
6 #define _GNU_SOURCE
7 #include <sched.h>
8 #include <stdint.h>
9 #include <syscall.h>
10 #include <linux/types.h>
11 
12 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
13 
14 #ifndef __NR_clone3
15 #define __NR_clone3 -1
16 struct clone_args {
17 	__aligned_u64 flags;
18 	__aligned_u64 pidfd;
19 	__aligned_u64 child_tid;
20 	__aligned_u64 parent_tid;
21 	__aligned_u64 exit_signal;
22 	__aligned_u64 stack;
23 	__aligned_u64 stack_size;
24 	__aligned_u64 tls;
25 	__aligned_u64 set_tid;
26 	__aligned_u64 set_tid_size;
27 };
28 #endif
29 
30 static pid_t sys_clone3(struct clone_args *args, size_t size)
31 {
32 	fflush(stdout);
33 	fflush(stderr);
34 	return syscall(__NR_clone3, args, size);
35 }
36 
37 static inline void test_clone3_supported(void)
38 {
39 	pid_t pid;
40 	struct clone_args args = {};
41 
42 	if (__NR_clone3 < 0)
43 		ksft_exit_skip("clone3() syscall is not supported\n");
44 
45 	/* Set to something that will always cause EINVAL. */
46 	args.exit_signal = -1;
47 	pid = sys_clone3(&args, sizeof(args));
48 	if (!pid)
49 		exit(EXIT_SUCCESS);
50 
51 	if (pid > 0) {
52 		wait(NULL);
53 		ksft_exit_fail_msg(
54 			"Managed to create child process with invalid exit_signal\n");
55 	}
56 
57 	if (errno == ENOSYS)
58 		ksft_exit_skip("clone3() syscall is not supported\n");
59 
60 	ksft_print_msg("clone3() syscall supported\n");
61 }
62 
63 #endif /* _CLONE3_SELFTESTS_H */
64