mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	On aarch64, alpha, arm, hppa, mips, nios2, powerpc, sh, sparc, tile, and x86_64 the clone syscall jumps to _exit after the child execution and the function ends the process execution by calling exit_group. This behavior have a small issue where threads created with CLONE_THREAD using clone syscall directly will eventually exit the whole group altogether instead of just the thread created. Also, s390, microblaze, ia64, i386, and m68k differs by calling exit syscall directly. This patch changes all architectures to call the exit syscall directly, as for s390, microblaze, ia64, i386, and m68k. This do not have change glibc internal behavior in any sort, since the only usage of clone implementation in posix_spawn calls _exit directly in the created child (fork uses a direct call to clone). Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, powerpc-linux-gnu, powerpc64le-linux-gnu, sparc64-linux-gnu, and sparcv9-linux-gnu. [BZ #21512] * sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Call exit syscall instead of jump to _exit. (CLONE_VM_BIT): Remove unused define. (CLONE_VM): Likewise. (CLONE_THREAD_BIT): Likewise. (CLONE_THREAD): Likewise. * sysdeps/unix/sysv/linux/alpha/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. * sysdeps/unix/sysv/linux/arm/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. (CLONE_THREAD): Likewise. * sysdeps/unix/sysv/linux/i386/clone.S (CLONE_VM): Likewise. * sysdeps/unix/sysv/linux/ia64/clone2.S (__clone2): Call exit syscall instead of jump to _exit. * sysdeps/unix/sysv/linux/hppa/clone.S (__clone): Likewise. * sysdeps/unix/sysv/linux/mips/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. (CLONE_THREAD): Likewise. * sysdeps/unix/sysv/linux/nios2/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. (CLONE_THREAD): Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. (CLONE_THREAD): Likewise. * sysdeps/unix/sysv/linux/sh/clone.S (__clone): Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. * sysdeps/unix/sysv/linux/tile/clone.S (__clone): Likewise. * sysdeps/unix/sysv/linux/x86_64/clone.S (__clone): Likewise. (CLONE_VM): Remove unused define. * sysdeps/unix/sysv/linux/Makefile (tests): Add tst-clone3. * sysdeps/unix/sysv/linux/tst-clone3.c: New file. Fix
		
			
				
	
	
		
			113 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* Wrapper around clone system call.  PowerPC64 version.
 | |
|    Copyright (C) 1997-2017 Free Software Foundation, Inc.
 | |
|    This file is part of the GNU C Library.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, see
 | |
|    <http://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| #include <sysdep.h>
 | |
| #define _ERRNO_H	1
 | |
| #include <bits/errno.h>
 | |
| 
 | |
| /* This is the only really unusual system call in PPC linux, but not
 | |
|    because of any weirdness in the system call itself; because of
 | |
|    all the freaky stuff we have to do to make the call useful.  */
 | |
| 
 | |
| /* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4],
 | |
|                   int flags [r5], void *arg [r6], void *parent_tid [r7],
 | |
|                   void *tls [r8], void *child_tid [r9]); */
 | |
| 
 | |
| ENTRY (__clone)
 | |
| 	CALL_MCOUNT 7
 | |
| 
 | |
| 	/* Check for child_stack == NULL || fn == NULL.  */
 | |
| 	cmpdi	cr0,r4,0
 | |
| 	cmpdi	cr1,r3,0
 | |
| 	cror	cr0*4+eq,cr1*4+eq,cr0*4+eq
 | |
| 	beq-	cr0,L(badargs)
 | |
| 
 | |
| 	/* Save some regs in the "red zone".  */
 | |
| 	std	r29,-24(r1)
 | |
| 	std	r30,-16(r1)
 | |
| 	std	r31,-8(r1)
 | |
| 	cfi_offset(r29,-24)
 | |
| 	cfi_offset(r30,-16)
 | |
| 	cfi_offset(r31,-8)
 | |
| 
 | |
| 	/* Set up stack frame for child.  */
 | |
| 	clrrdi	r4,r4,4
 | |
| 	li	r0,0
 | |
| 	stdu	r0,-FRAME_MIN_SIZE_PARM(r4)
 | |
| 
 | |
| 	/* Save fn, args, stack across syscall.  */
 | |
| 	mr	r30,r3			/* Function in r30.  */
 | |
| 	mr	r29,r5			/* Flags in r29.  */
 | |
| 	mr	r31,r6			/* Argument in r31.  */
 | |
| 
 | |
| 	/* 'flags' argument is first parameter to clone syscall.
 | |
| 	   Second is the stack pointer, already in r4.  */
 | |
| 	mr	r3,r5
 | |
| 	/* Move the parent_tid, child_tid and tls arguments. */
 | |
| 	mr	r5,r7
 | |
| 	mr	r6,r8
 | |
| 	mr	r7,r9
 | |
| 
 | |
| 	/* End FDE now, because in the child the unwind info will be
 | |
| 	   wrong.  */
 | |
| 	cfi_endproc
 | |
| 
 | |
| 	/* Do the call.  */
 | |
| 	DO_CALL(SYS_ify(clone))
 | |
| 
 | |
| 	/* Check for child process.  */
 | |
| 	cmpdi	cr1,r3,0
 | |
| 	crandc	cr1*4+eq,cr1*4+eq,cr0*4+so
 | |
| 	bne-	cr1,L(parent)		/* The '-' is to minimise the race.  */
 | |
| 
 | |
| 	std	r2,FRAME_TOC_SAVE(r1)
 | |
| 	/* Call procedure.  */
 | |
| 	PPC64_LOAD_FUNCPTR r30
 | |
| 	mr	r3,r31
 | |
| 	bctrl
 | |
| 	ld	r2,FRAME_TOC_SAVE(r1)
 | |
| 
 | |
| 	DO_CALL(SYS_ify(exit))
 | |
| 	/* We won't ever get here but provide a nop so that the linker
 | |
| 	   will insert a toc adjusting stub if necessary.  */
 | |
| 	nop
 | |
| 
 | |
| L(badargs):
 | |
| 	cfi_startproc
 | |
| 	li	r3,EINVAL
 | |
| 	TAIL_CALL_SYSCALL_ERROR
 | |
| 
 | |
| L(parent):
 | |
| 	/* Parent.  Restore registers & return.  */
 | |
| 	cfi_offset(r29,-24)
 | |
| 	cfi_offset(r30,-16)
 | |
| 	cfi_offset(r31,-8)
 | |
| 	ld	r29,-24(r1)
 | |
| 	ld	r30,-16(r1)
 | |
| 	ld	r31,-8(r1)
 | |
| 	cfi_restore(r29)
 | |
| 	cfi_restore(r30)
 | |
| 	cfi_restore(r31)
 | |
| 
 | |
| 	PSEUDO_RET
 | |
| 
 | |
| END (__clone)
 | |
| 
 | |
| libc_hidden_def (__clone)
 | |
| weak_alias (__clone, clone)
 |