1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun #ifndef _CLONE3_SELFTESTS_H 4*4882a593Smuzhiyun #define _CLONE3_SELFTESTS_H 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun #define _GNU_SOURCE 7*4882a593Smuzhiyun #include <sched.h> 8*4882a593Smuzhiyun #include <linux/sched.h> 9*4882a593Smuzhiyun #include <linux/types.h> 10*4882a593Smuzhiyun #include <stdint.h> 11*4882a593Smuzhiyun #include <syscall.h> 12*4882a593Smuzhiyun #include <sys/wait.h> 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #include "../kselftest.h" 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun #ifndef CLONE_INTO_CGROUP 19*4882a593Smuzhiyun #define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */ 20*4882a593Smuzhiyun #endif 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #ifndef __NR_clone3 23*4882a593Smuzhiyun #define __NR_clone3 -1 24*4882a593Smuzhiyun #endif 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun struct __clone_args { 27*4882a593Smuzhiyun __aligned_u64 flags; 28*4882a593Smuzhiyun __aligned_u64 pidfd; 29*4882a593Smuzhiyun __aligned_u64 child_tid; 30*4882a593Smuzhiyun __aligned_u64 parent_tid; 31*4882a593Smuzhiyun __aligned_u64 exit_signal; 32*4882a593Smuzhiyun __aligned_u64 stack; 33*4882a593Smuzhiyun __aligned_u64 stack_size; 34*4882a593Smuzhiyun __aligned_u64 tls; 35*4882a593Smuzhiyun #ifndef CLONE_ARGS_SIZE_VER0 36*4882a593Smuzhiyun #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ 37*4882a593Smuzhiyun #endif 38*4882a593Smuzhiyun __aligned_u64 set_tid; 39*4882a593Smuzhiyun __aligned_u64 set_tid_size; 40*4882a593Smuzhiyun #ifndef CLONE_ARGS_SIZE_VER1 41*4882a593Smuzhiyun #define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ 42*4882a593Smuzhiyun #endif 43*4882a593Smuzhiyun __aligned_u64 cgroup; 44*4882a593Smuzhiyun #ifndef CLONE_ARGS_SIZE_VER2 45*4882a593Smuzhiyun #define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ 46*4882a593Smuzhiyun #endif 47*4882a593Smuzhiyun }; 48*4882a593Smuzhiyun sys_clone3(struct __clone_args * args,size_t size)49*4882a593Smuzhiyunstatic pid_t sys_clone3(struct __clone_args *args, size_t size) 50*4882a593Smuzhiyun { 51*4882a593Smuzhiyun fflush(stdout); 52*4882a593Smuzhiyun fflush(stderr); 53*4882a593Smuzhiyun return syscall(__NR_clone3, args, size); 54*4882a593Smuzhiyun } 55*4882a593Smuzhiyun test_clone3_supported(void)56*4882a593Smuzhiyunstatic inline void test_clone3_supported(void) 57*4882a593Smuzhiyun { 58*4882a593Smuzhiyun pid_t pid; 59*4882a593Smuzhiyun struct __clone_args args = {}; 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun if (__NR_clone3 < 0) 62*4882a593Smuzhiyun ksft_exit_skip("clone3() syscall is not supported\n"); 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun /* Set to something that will always cause EINVAL. */ 65*4882a593Smuzhiyun args.exit_signal = -1; 66*4882a593Smuzhiyun pid = sys_clone3(&args, sizeof(args)); 67*4882a593Smuzhiyun if (!pid) 68*4882a593Smuzhiyun exit(EXIT_SUCCESS); 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun if (pid > 0) { 71*4882a593Smuzhiyun wait(NULL); 72*4882a593Smuzhiyun ksft_exit_fail_msg( 73*4882a593Smuzhiyun "Managed to create child process with invalid exit_signal\n"); 74*4882a593Smuzhiyun } 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun if (errno == ENOSYS) 77*4882a593Smuzhiyun ksft_exit_skip("clone3() syscall is not supported\n"); 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun ksft_print_msg("clone3() syscall supported\n"); 80*4882a593Smuzhiyun } 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun #endif /* _CLONE3_SELFTESTS_H */ 83