1 // SPDX-License-Identifier: GPL-2.0
3 /* Based on Christian Brauner's clone3() example */
8 #include <linux/types.h>
9 #include <linux/sched.h>
13 #include <sys/syscall.h>
14 #include <sys/types.h>
20 #include "../kselftest.h"
21 #include "clone3_selftests.h"
26 CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG
,
27 CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG
,
28 CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG
,
29 CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG
,
32 static int call_clone3(uint64_t flags
, size_t size
, enum test_mode test_mode
)
34 struct __clone_args args
= {
36 .exit_signal
= SIGCHLD
,
39 struct clone_args_extended
{
40 struct __clone_args args
;
41 __aligned_u64 excess_space
[2];
47 memset(&args_ext
, 0, sizeof(args_ext
));
48 if (size
> sizeof(struct __clone_args
))
49 args_ext
.excess_space
[1] = 1;
52 size
= sizeof(struct __clone_args
);
55 case CLONE3_ARGS_ALL_0
:
59 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG
:
60 args
.exit_signal
= 0xbadc0ded00000000ULL
;
62 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG
:
63 args
.exit_signal
= 0x0000000080000000ULL
;
65 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG
:
66 args
.exit_signal
= 0x0000000000000100ULL
;
68 case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG
:
69 args
.exit_signal
= 0x00000000000000f0ULL
;
73 memcpy(&args_ext
.args
, &args
, sizeof(struct __clone_args
));
75 pid
= sys_clone3((struct __clone_args
*)&args_ext
, size
);
77 ksft_print_msg("%s - Failed to create new process\n",
83 ksft_print_msg("I am the child, my PID is %d\n", getpid());
87 ksft_print_msg("I am the parent (%d). My child's pid is %d\n",
90 if (waitpid(-1, &status
, __WALL
) < 0) {
91 ksft_print_msg("Child returned %s\n", strerror(errno
));
94 if (WEXITSTATUS(status
))
95 return WEXITSTATUS(status
);
100 static void test_clone3(uint64_t flags
, size_t size
, int expected
,
101 enum test_mode test_mode
)
106 "[%d] Trying clone3() with flags %#" PRIx64
" (size %zu)\n",
107 getpid(), flags
, size
);
108 ret
= call_clone3(flags
, size
, test_mode
);
109 ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n",
110 getpid(), ret
, expected
);
112 ksft_test_result_fail(
113 "[%d] Result (%d) is different than expected (%d)\n",
114 getpid(), ret
, expected
);
116 ksft_test_result_pass(
117 "[%d] Result (%d) matches expectation (%d)\n",
118 getpid(), ret
, expected
);
121 int main(int argc
, char *argv
[])
125 uid_t uid
= getuid();
129 test_clone3_supported();
131 /* Just a simple clone3() should return 0.*/
132 test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST
);
134 /* Do a clone3() in a new PID NS.*/
136 test_clone3(CLONE_NEWPID
, 0, 0, CLONE3_ARGS_NO_TEST
);
138 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
140 /* Do a clone3() with CLONE_ARGS_SIZE_VER0. */
141 test_clone3(0, CLONE_ARGS_SIZE_VER0
, 0, CLONE3_ARGS_NO_TEST
);
143 /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */
144 test_clone3(0, CLONE_ARGS_SIZE_VER0
- 8, -EINVAL
, CLONE3_ARGS_NO_TEST
);
146 /* Do a clone3() with sizeof(struct clone_args) + 8 */
147 test_clone3(0, sizeof(struct __clone_args
) + 8, 0, CLONE3_ARGS_NO_TEST
);
149 /* Do a clone3() with exit_signal having highest 32 bits non-zero */
150 test_clone3(0, 0, -EINVAL
, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG
);
152 /* Do a clone3() with negative 32-bit exit_signal */
153 test_clone3(0, 0, -EINVAL
, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG
);
155 /* Do a clone3() with exit_signal not fitting into CSIGNAL mask */
156 test_clone3(0, 0, -EINVAL
, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG
);
158 /* Do a clone3() with NSIG < exit_signal < CSIG */
159 test_clone3(0, 0, -EINVAL
, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG
);
161 test_clone3(0, sizeof(struct __clone_args
) + 8, 0, CLONE3_ARGS_ALL_0
);
163 test_clone3(0, sizeof(struct __clone_args
) + 16, -E2BIG
,
166 test_clone3(0, sizeof(struct __clone_args
) * 2, -E2BIG
,
169 /* Do a clone3() with > page size */
170 test_clone3(0, getpagesize() + 8, -E2BIG
, CLONE3_ARGS_NO_TEST
);
172 /* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */
174 test_clone3(CLONE_NEWPID
, CLONE_ARGS_SIZE_VER0
, 0,
175 CLONE3_ARGS_NO_TEST
);
177 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
179 /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */
180 test_clone3(CLONE_NEWPID
, CLONE_ARGS_SIZE_VER0
- 8, -EINVAL
,
181 CLONE3_ARGS_NO_TEST
);
183 /* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */
185 test_clone3(CLONE_NEWPID
, sizeof(struct __clone_args
) + 8, 0,
186 CLONE3_ARGS_NO_TEST
);
188 ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
190 /* Do a clone3() with > page size in a new PID NS */
191 test_clone3(CLONE_NEWPID
, getpagesize() + 8, -E2BIG
,
192 CLONE3_ARGS_NO_TEST
);
194 return !ksft_get_fail_cnt() ? ksft_exit_pass() : ksft_exit_fail();