1/* The clone3 syscall wrapper. Linux/i386 version. 2 Copyright (C) 2021 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19/* clone3() is even more special than fork() as it mucks with stacks 20 and invokes a function in the right context after its all over. */ 21 22#include <sysdep.h> 23 24/* The userland implementation is: 25 int clone3 (struct clone_args *cl_args, size_t size, 26 int (*func)(void *arg), void *arg); 27 the kernel entry is: 28 int clone3 (struct clone_args *cl_args, size_t size); 29 30 The parameters are passed on stack from userland: 31 16(%esp) arg 32 12(%esp) func 33 8(%esp) size 34 4(%esp) cl_args 35 (%esp) Return address 36 37 The kernel expects: 38 eax: system call number 39 ebx: cl_args 40 ecx: size 41 */ 42 43#define CL_ARGS 4 44#define SIZE 8 45#define FUNC 12 46#define ARG 16 47 48 .text 49ENTRY (__clone3) 50 /* Sanity check arguments. */ 51 movl $-EINVAL, %eax 52 movl CL_ARGS(%esp), %ecx /* No NULL cl_args pointer. */ 53 testl %ecx, %ecx 54 jz SYSCALL_ERROR_LABEL 55 /* Save the function pointer in EDX which is preserved by the 56 system call. */ 57 movl FUNC(%esp), %edx /* No NULL function pointer. */ 58 testl %edx, %edx 59 jz SYSCALL_ERROR_LABEL 60 61 /* Save EBX and ESI. */ 62 pushl %ebx 63 cfi_adjust_cfa_offset (4) 64 pushl %esi 65 cfi_adjust_cfa_offset (4) 66 67 /* Save the function argument in ESI which is preserved by the 68 system call. */ 69 movl (ARG + 8)(%esp), %esi 70 71 /* Put cl_args in EBX. */ 72 movl %ecx, %ebx 73 74 /* Put size in ECX. */ 75 movl (SIZE + 8)(%esp), %ecx 76 77 /* Do the system call. */ 78 movl $SYS_ify(clone3), %eax 79 80 /* End FDE now, because in the child the unwind info will be 81 wrong. */ 82 cfi_endproc 83 84 int $0x80 85 test %eax, %eax 86 /* No need to restore EBX and ESI in child. */ 87 jz L(thread_start) 88 89 /* Restore EBX and ESI in parent. */ 90 pop %esi 91 pop %ebx 92 jl SYSCALL_ERROR_LABEL 93 94 ret 95 96L(thread_start): 97 cfi_startproc 98 /* Clearing frame pointer is insufficient, use CFI. */ 99 cfi_undefined (eip) 100 xorl %ebp, %ebp /* Terminate the stack frame. */ 101 102 /* Align stack to 16 bytes per the i386 psABI. */ 103 andl $-16, %esp 104 105 /* The PUSH below will decrement stack pointer by 4 bytes. */ 106 subl $12, %esp 107 108 /* Set up the argument for the function call. */ 109 pushl %esi /* Argument. */ 110 cfi_adjust_cfa_offset (4) 111 call *%edx /* Call function. */ 112 113 /* Call exit with return value from function call. */ 114 movl %eax, %ebx 115 movl $SYS_ify(exit), %eax 116 ENTER_KERNEL 117 cfi_endproc 118 119 cfi_startproc 120PSEUDO_END (__clone3) 121 122libc_hidden_def (__clone3) 123weak_alias (__clone3, clone3) 124