diff options
22 files changed, 250 insertions, 141 deletions
diff --git a/ChangeLog b/ChangeLog index ca96f0933c..b837538a5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2016-04-29 Adhemerval Zanella <adhemerval.zanella@linaro.org> + + [BZ #19957] + * sysdeps/unix/sysv/linux/Makefile [$(subdir) == nptl] (test): Remove + tst-getpid2. + (test): Add tst-clone2. + * sysdeps/unix/sysv/linux/tst-clone2.c: New file. + * sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Do not change + pid/tid fields for CLONE_VM. + * sysdeps/unix/sysv/linux/alpha/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/arm/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/hppa/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/ia64/clone2.S (__clone): Likewise, + * sysdeps/unix/sysv/linux/i386/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/mips/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/m68k/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/nios2/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S (__clone): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (__clone): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/sh/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/tile/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/x86_64/clone.S (__clone): Likewise. + * sysdeps/unix/sysv/linux/tst-getpid2.c: Remove file. + 2016-04-29 Florian Weimer <fweimer@redhat.com> [BZ #19642] diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 9999600633..9b4e2e1f7c 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -42,7 +42,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \ bits/socket_type.h bits/syscall.h bits/sysctl.h \ bits/mman-linux.h -tests += tst-clone tst-fanotify tst-personality +tests += tst-clone tst-clone2 tst-fanotify tst-personality # Generate the list of SYS_* macros for the system calls (__NR_* macros). @@ -194,7 +194,7 @@ CFLAGS-gai.c += -DNEED_NETLINK endif ifeq ($(subdir),nptl) -tests += tst-setgetname tst-align-clone tst-getpid1 tst-getpid2 \ +tests += tst-setgetname tst-align-clone tst-getpid1 \ tst-thread-affinity-pthread tst-thread-affinity-pthread2 \ tst-thread-affinity-sched endif diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S index 8f3ab40954..76baa7a698 100644 --- a/sysdeps/unix/sysv/linux/aarch64/clone.S +++ b/sysdeps/unix/sysv/linux/aarch64/clone.S @@ -72,17 +72,15 @@ thread_start: cfi_undefined (x30) mov x29, 0 - tbnz x11, #CLONE_THREAD_BIT, 3f - mov x0, #-1 - tbnz x11, #CLONE_VM_BIT, 2f + tbnz x11, #CLONE_VM_BIT, 1f + mov x8, #SYS_ify(getpid) svc 0x0 -2: mrs x1, tpidr_el0 sub x1, x1, #PTHREAD_SIZEOF str w0, [x1, #PTHREAD_PID_OFFSET] str w0, [x1, #PTHREAD_TID_OFFSET] -3: +1: /* Pick the function arg and execute. */ mov x0, x12 diff --git a/sysdeps/unix/sysv/linux/alpha/clone.S b/sysdeps/unix/sysv/linux/alpha/clone.S index 556aa63105..6a3154f9a7 100644 --- a/sysdeps/unix/sysv/linux/alpha/clone.S +++ b/sysdeps/unix/sysv/linux/alpha/clone.S @@ -24,7 +24,6 @@ #include <bits/errno.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, pid_t *ptid, void *tls, pid_t *ctid); @@ -94,7 +93,7 @@ thread_start: /* Check and see if we need to reset the PID. */ ldq t0, 16(sp) - lda t1, CLONE_THREAD + lda t1, CLONE_VM and t0, t1, t2 beq t2, 2f 1: @@ -123,11 +122,7 @@ thread_start: .align 4 2: rduniq - lda t1, CLONE_VM mov v0, s0 - lda v0, -1 - and t0, t1, t2 - bne t2, 3f lda v0, __NR_getxpid callsys 3: diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S index c103123965..7ff681804b 100644 --- a/sysdeps/unix/sysv/linux/arm/clone.S +++ b/sysdeps/unix/sysv/linux/arm/clone.S @@ -70,19 +70,16 @@ PSEUDO_END (__clone) 1: .fnstart .cantunwind - tst ip, #CLONE_THREAD - bne 3f + tst ip, #CLONE_VM + bne 2f GET_TLS (lr) mov r1, r0 - tst ip, #CLONE_VM ldr r7, =SYS_ify(getpid) - ite ne - movne r0, #-1 - swieq 0x0 + swi 0x0 NEGOFF_ADJ_BASE (r1, TID_OFFSET) str r0, NEGOFF_OFF1 (r1, TID_OFFSET) str r0, NEGOFF_OFF2 (r1, PID_OFFSET, TID_OFFSET) -3: +2: @ pick the function arg and call address off the stack and execute ldr r0, [sp, #4] ldr ip, [sp], #8 diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S index 0a18137118..3d037f1430 100644 --- a/sysdeps/unix/sysv/linux/hppa/clone.S +++ b/sysdeps/unix/sysv/linux/hppa/clone.S @@ -133,19 +133,13 @@ ENTRY(__clone) .LthreadStart: # define CLONE_VM_BIT 23 /* 0x00000100 */ -# define CLONE_THREAD_BIT 15 /* 0x00010000 */ /* Load original clone flags. - If CLONE_THREAD was passed, don't reset the PID/TID. - If CLONE_VM was passed, we need to store -1 to PID/TID. - If CLONE_VM and CLONE_THREAD were not set store the result - of getpid to PID/TID. */ + If CLONE_VM was passed, don't modify PID/TID. + Otherwise store the result of getpid to PID/TID. */ ldw -56(%sp), %r26 - bb,<,n %r26, CLONE_THREAD_BIT, 1f - bb,< %r26, CLONE_VM_BIT, 2f - ldi -1, %ret0 + bb,<,n %r26, CLONE_VM_BIT, 1f ble 0x100(%sr2, %r0) ldi __NR_getpid, %r20 -2: mfctl %cr27, %r26 stw %ret0, PID_THREAD_OFFSET(%r26) stw %ret0, TID_THREAD_OFFSET(%r26) diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S index ef447d161d..25f2a9c340 100644 --- a/sysdeps/unix/sysv/linux/i386/clone.S +++ b/sysdeps/unix/sysv/linux/i386/clone.S @@ -40,7 +40,6 @@ #define SYS_clone 120 #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 .text ENTRY (__clone) @@ -108,7 +107,7 @@ L(thread_start): cfi_undefined (eip); /* Note: %esi is zero. */ movl %esi,%ebp /* terminate the stack frame */ - testl $CLONE_THREAD, %edi + testl $CLONE_VM, %edi je L(newpid) L(haspid): call *%ebx @@ -124,9 +123,6 @@ L(here): .subsection 2 L(newpid): - testl $CLONE_VM, %edi - movl $-1, %eax - jne L(nomoregetpid) movl $SYS_ify(getpid), %eax ENTER_KERNEL L(nomoregetpid): diff --git a/sysdeps/unix/sysv/linux/ia64/clone2.S b/sysdeps/unix/sysv/linux/ia64/clone2.S index fc046eb2a5..b4cfdfc959 100644 --- a/sysdeps/unix/sysv/linux/ia64/clone2.S +++ b/sysdeps/unix/sysv/linux/ia64/clone2.S @@ -67,12 +67,10 @@ ENTRY(__clone2) (CHILD) mov loc0=gp (PARENT) ret ;; - tbit.nz p6,p0=in3,16 /* CLONE_THREAD */ - tbit.z p7,p10=in3,8 /* CLONE_VM */ + tbit.nz p6,p0=in3,8 /* CLONE_VM */ (p6) br.cond.dptk 1f ;; mov r15=SYS_ify (getpid) -(p10) addl r8=-1,r0 (p7) break __BREAK_SYSCALL ;; add r9=PID,r13 diff --git a/sysdeps/unix/sysv/linux/m68k/clone.S b/sysdeps/unix/sysv/linux/m68k/clone.S index 33474cc12c..aec12cb98b 100644 --- a/sysdeps/unix/sysv/linux/m68k/clone.S +++ b/sysdeps/unix/sysv/linux/m68k/clone.S @@ -25,7 +25,6 @@ #include <tls.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, void *parent_tidptr, void *tls, void *child_tidptr) */ @@ -100,16 +99,10 @@ thread_start: cfi_undefined (pc) /* Mark end of stack */ subl %fp, %fp /* terminate the stack frame */ /* Check and see if we need to reset the PID. */ - movel %d1, %a1 - andl #CLONE_THREAD, %d1 - jne donepid - movel %a1, %d1 - movel #-1, %d0 andl #CLONE_VM, %d1 - jne gotpid + jne donepid movel #SYS_ify (getpid), %d0 trap #0 -gotpid: movel %a0, -(%sp) movel %d0, -(%sp) bsrl __m68k_read_tp@PLTPC diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S index feb8250eca..39634c5cf0 100644 --- a/sysdeps/unix/sysv/linux/mips/clone.S +++ b/sysdeps/unix/sysv/linux/mips/clone.S @@ -131,9 +131,8 @@ L(thread_start): /* The stackframe has been created on entry of clone(). */ /* Check and see if we need to reset the PID. */ - LONG_L a0,(PTRSIZE*2)(sp) - and a1,a0,CLONE_THREAD - beqz a1,L(restore_pid) + and a1,a0,CLONE_VM + beqz a1,L(restore_pid) L(donepid): /* Restore the arg for user's function. */ @@ -153,12 +152,8 @@ L(donepid): #endif L(restore_pid): - and a1,a0,CLONE_VM - li v0,-1 - bnez a1,L(gotpid) li v0,__NR_getpid syscall -L(gotpid): READ_THREAD_POINTER(v1) INT_S v0,PID_OFFSET(v1) INT_S v0,TID_OFFSET(v1) diff --git a/sysdeps/unix/sysv/linux/nios2/clone.S b/sysdeps/unix/sysv/linux/nios2/clone.S index e4d3970983..30b6e4a6c8 100644 --- a/sysdeps/unix/sysv/linux/nios2/clone.S +++ b/sysdeps/unix/sysv/linux/nios2/clone.S @@ -26,7 +26,6 @@ #include <tcb-offsets.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, void *parent_tidptr, void *tls, void *child_tidptr) */ @@ -71,13 +70,9 @@ thread_start: /* We expect the argument registers to be preserved across system calls and across task cloning, so flags should be in r4 here. */ - andhi r2, r4, %hi(CLONE_THREAD) + andi r2, r4, CLONE_VM bne r2, zero, 2f - andi r3, r4, CLONE_VM - movi r2, -1 - bne r3, zero, 3f DO_CALL (getpid, 0) -3: stw r2, PID_OFFSET(r23) stw r2, TID_OFFSET(r23) 2: diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S index eb973db0b8..9d496f0a4c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S @@ -76,13 +76,11 @@ ENTRY (__clone) crandc cr1*4+eq,cr1*4+eq,cr0*4+so bne- cr1,L(parent) /* The '-' is to minimise the race. */ - andis. r0,r28,CLONE_THREAD>>16 - bne+ r0,L(oldpid) - andi. r0,r28,CLONE_VM - li r3,-1 - bne- r0,L(nomoregetpid) + /* If CLONE_VM is set do not update the pid/tid field. */ + andi. r0,r29,CLONE_VM + bne+ cr0,L(oldpid) + DO_CALL(SYS_ify(getpid)) -L(nomoregetpid): stw r3,TID(r2) stw r3,PID(r2) L(oldpid): diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S index 959fdb7b76..7c59b9b4e9 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -78,13 +78,11 @@ ENTRY (__clone) crandc cr1*4+eq,cr1*4+eq,cr0*4+so bne- cr1,L(parent) /* The '-' is to minimise the race. */ - andis. r0,r29,CLONE_THREAD>>16 + /* If CLONE_VM is set do not update the pid/tid field. */ + rldicl. r0,r29,56,63 /* flags & CLONE_VM. */ bne+ cr0,L(oldpid) - andi. r0,r29,CLONE_VM - li r3,-1 - bne- cr0,L(nomoregetpid) + DO_CALL(SYS_ify(getpid)) -L(nomoregetpid): stw r3,TID(r13) stw r3,PID(r13) L(oldpid): diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S index f774e909ee..2f8fa0b840 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S +++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S @@ -54,13 +54,10 @@ error: PSEUDO_END (__clone) thread_start: - tmh %r3,1 /* CLONE_THREAD == 0x00010000 */ - jne 1f - lhi %r2,-1 tml %r3,256 /* CLONE_VM == 0x00000100 */ - jne 2f + jne 1f svc SYS_ify(getpid) -2: ear %r3,%a0 + ear %r3,%a0 st %r2,PID(%r3) st %r2,TID(%r3) 1: diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S index 928a881268..fb816922ca 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S +++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S @@ -55,13 +55,10 @@ error: PSEUDO_END (__clone) thread_start: - tmh %r3,1 /* CLONE_THREAD == 0x00010000 */ + tmll %r3,256 /* CLONE_VM == 0x00000100 */ jne 1f - lhi %r2,-1 - tml %r3,256 /* CLONE_VM == 0x00000100 */ - jne 2f svc SYS_ify(getpid) -2: ear %r3,%a0 + ear %r3,%a0 sllg %r3,%r3,32 ear %r3,%a1 st %r2,PID(%r3) diff --git a/sysdeps/unix/sysv/linux/sh/clone.S b/sysdeps/unix/sysv/linux/sh/clone.S index a73dd7d9e3..4cd7df117c 100644 --- a/sysdeps/unix/sysv/linux/sh/clone.S +++ b/sysdeps/unix/sysv/linux/sh/clone.S @@ -67,15 +67,11 @@ ENTRY(__clone) /* terminate the stack frame */ mov #0, r14 mov r4, r0 - shlr16 r0 - tst #1, r0 // CLONE_THREAD = (1 << 16) + shlr8 r0 + tst #1, r0 // CLONE_VM = (1 << 8) bf/s 4f mov r4, r0 /* new pid */ - shlr8 r0 - tst #1, r0 // CLONE_VM = (1 << 8) - bf/s 3f - mov #-1, r0 mov #+SYS_ify(getpid), r3 trapa #0x15 3: diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S index 68f8202e82..d6c92f6133 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S @@ -25,7 +25,6 @@ #include <sysdep.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, pid_t *ptid, void *tls, pid_t *ctid); */ @@ -80,15 +79,10 @@ END(__clone) .type __thread_start,@function __thread_start: - sethi %hi(CLONE_THREAD), %l0 - andcc %g4, %l0, %g0 + andcc %g4, CLONE_VM, %g0 bne 1f - andcc %g4, CLONE_VM, %g0 - bne,a 2f - mov -1,%o0 set __NR_getpid,%g1 ta 0x10 -2: st %o0,[%g7 + PID] st %o0,[%g7 + TID] 1: diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S index cecffa7fb9..b0f62660a7 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S @@ -25,7 +25,6 @@ #include <sysdep.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, pid_t *ptid, void *tls, pid_t *ctid); */ @@ -77,15 +76,11 @@ END(__clone) .type __thread_start,@function __thread_start: - sethi %hi(CLONE_THREAD), %l0 - andcc %g4, %l0, %g0 + andcc %g4, CLONE_VM, %g0 bne,pt %icc, 1f - andcc %g4, CLONE_VM, %g0 - bne,a,pn %icc, 2f - mov -1,%o0 set __NR_getpid,%g1 ta 0x6d -2: st %o0,[%g7 + PID] + st %o0,[%g7 + PID] st %o0,[%g7 + TID] 1: mov %g0, %fp /* terminate backtrace */ diff --git a/sysdeps/unix/sysv/linux/tile/clone.S b/sysdeps/unix/sysv/linux/tile/clone.S index a300eb59ff..d1d36462e7 100644 --- a/sysdeps/unix/sysv/linux/tile/clone.S +++ b/sysdeps/unix/sysv/linux/tile/clone.S @@ -164,43 +164,14 @@ ENTRY (__clone) cfi_def_cfa_offset (FRAME_SIZE) cfi_undefined (lr) /* Check and see if we need to reset the PID, which we do if - CLONE_THREAD isn't set, i.e. we're not staying in the thread group. - If CLONE_VM is set, we're doing some kind of thread-like clone, - so we set the tid/pid to -1 to disable using the cached values - in getpid(). Otherwise (if CLONE_VM isn't set), it's a - fork-like clone, and we go ahead and write the cached values + CLONE_VM isn't set, i.e. it's a fork-like clone with a new + address space. In that case we update the cached values from the true system pid (retrieved via __NR_getpid syscall). */ -#ifdef __tilegx__ - { - moveli r0, hw1_last(CLONE_VM) - moveli r1, hw1_last(CLONE_THREAD) - } - { - shl16insli r0, r0, hw0(CLONE_VM) - shl16insli r1, r1, hw0(CLONE_THREAD) - } -#else - { - moveli r0, lo16(CLONE_VM) - moveli r1, lo16(CLONE_THREAD) - } - { - auli r0, r0, ha16(CLONE_VM) - auli r1, r1, ha16(CLONE_THREAD) - } -#endif - { - and r0, r30, r0 - and r1, r30, r1 - } - BNEZ r1, .Lno_reset_pid /* CLONE_THREAD is set */ - { - movei r0, -1 - BNEZ r0, .Lgotpid /* CLONE_VM is set */ - } + moveli r0, CLONE_VM + and r0, r30, r0 + BNEZ r0, .Lno_reset_pid /* CLONE_VM is set */ moveli TREG_SYSCALL_NR_NAME, __NR_getpid swint1 -.Lgotpid: ADDLI_PTR r2, tp, PID_OFFSET { ST4 r2, r0 diff --git a/sysdeps/unix/sysv/linux/tst-clone2.c b/sysdeps/unix/sysv/linux/tst-clone2.c new file mode 100644 index 0000000000..68a7e6d6e2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-clone2.c @@ -0,0 +1,178 @@ +/* Test if CLONE_VM does not change pthread pid/tid field (BZ #19957) + Copyright (C) 2016 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 <sched.h> +#include <signal.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <stddef.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <tls.h> /* for THREAD_* macros. */ + +static int sig; +static int pipefd[2]; + +static int +f (void *a) +{ + close (pipefd[0]); + + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + pid_t tid = THREAD_GETMEM (THREAD_SELF, tid); + + while (write (pipefd[1], &pid, sizeof pid) < 0) + continue; + while (write (pipefd[1], &tid, sizeof tid) < 0) + continue; + + return 0; +} + + +static int +clone_test (int clone_flags) +{ + sig = SIGRTMIN; + sigset_t ss; + sigemptyset (&ss); + sigaddset (&ss, sig); + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) + { + printf ("sigprocmask failed: %m\n"); + return 1; + } + + if (pipe2 (pipefd, O_CLOEXEC)) + { + printf ("sigprocmask failed: %m\n"); + return 1; + } + + pid_t ppid = getpid (); + +#ifdef __ia64__ + extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, + void *__arg, ...); + char st[256 * 1024] __attribute__ ((aligned)); + pid_t p = __clone2 (f, st, sizeof (st), clone_flags, 0); +#else + char st[128 * 1024] __attribute__ ((aligned)); +#if _STACK_GROWS_DOWN + pid_t p = clone (f, st + sizeof (st), clone_flags, 0); +#elif _STACK_GROWS_UP + pid_t p = clone (f, st, clone_flags, 0); +#else +#error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif +#endif + close (pipefd[1]); + + if (p == -1) + { + printf ("clone failed: %m\n"); + return 1; + } + + pid_t pid, tid; + if (read (pipefd[0], &pid, sizeof pid) != sizeof pid) + { + printf ("read pid failed: %m\n"); + kill (p, SIGKILL); + return 1; + } + if (read (pipefd[0], &tid, sizeof tid) != sizeof tid) + { + printf ("read pid failed: %m\n"); + kill (p, SIGKILL); + return 1; + } + + close (pipefd[0]); + + int ret = 0; + + /* For CLONE_VM glibc clone implementation does not change the pthread + pid/tid field. */ + if ((clone_flags & CLONE_VM) == CLONE_VM) + { + if ((ppid != pid) || (ppid != tid)) + { + printf ("parent pid (%i) != received pid/tid (%i/%i)\n", + (int)ppid, (int)pid, (int)tid); + ret = 1; + } + } + /* For any other flag clone updates the new pthread pid and tid with + the clone return value. */ + else + { + if ((p != pid) || (p != tid)) + { + printf ("child pid (%i) != received pid/tid (%i/%i)\n", + (int)p, (int)pid, (int)tid); + ret = 1; + } + } + + int e; + if (waitpid (p, &e, __WCLONE) != p) + { + puts ("waitpid failed"); + kill (p, SIGKILL); + return 1; + } + if (!WIFEXITED (e)) + { + if (WIFSIGNALED (e)) + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); + else + puts ("did not terminate correctly"); + return 1; + } + if (WEXITSTATUS (e) != 0) + { + printf ("exit code %d\n", WEXITSTATUS (e)); + return 1; + } + + return ret; +} + +int +do_test (void) +{ + /* First, check that the clone implementation, without any flag, updates + the struct pthread to contain the new PID and TID. */ + int ret = clone_test (0); + /* Second, check that with CLONE_VM the struct pthread PID and TID fields + remain unmodified after the clone. Any modifications would cause problem + for the parent as described in bug 19957. */ + ret += clone_test (CLONE_VM); + return ret; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/tst-getpid2.c b/sysdeps/unix/sysv/linux/tst-getpid2.c deleted file mode 100644 index fc98cb60db..0000000000 --- a/sysdeps/unix/sysv/linux/tst-getpid2.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_CLONE_FLAGS CLONE_VM -#include "tst-getpid1.c" diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S index 1a50957df3..66f4b11490 100644 --- a/sysdeps/unix/sysv/linux/x86_64/clone.S +++ b/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -24,7 +24,6 @@ #include <asm-syntax.h> #define CLONE_VM 0x00000100 -#define CLONE_THREAD 0x00010000 /* The userland implementation is: int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg), @@ -92,14 +91,11 @@ L(thread_start): the outermost frame obviously. */ xorl %ebp, %ebp - testq $CLONE_THREAD, %rdi + andq $CLONE_VM, %rdi jne 1f - testq $CLONE_VM, %rdi - movl $-1, %eax - jne 2f movl $SYS_ify(getpid), %eax syscall -2: movl %eax, %fs:PID + movl %eax, %fs:PID movl %eax, %fs:TID 1: |