From: Jakub Jelinek Date: Fri, 12 Jan 2007 17:58:08 +0000 (+0000) Subject: * include/atomic.h (atomic_forced_read): New macro. X-Git-Tag: cvs/fedora-glibc-2_5-20070712T1701~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a055f27811cfe1b76fff6b245e07cdb04cb4a9b;p=thirdparty%2Fglibc.git * include/atomic.h (atomic_forced_read): New macro. * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure tid isn't reread from pd->tid in between ESRCH test and the syscall. --- diff --git a/ChangeLog b/ChangeLog index b4674852e35..f5596363447 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-12-21 Ulrich Drepper + + * include/atomic.h (atomic_forced_read): New macro. + 2006-12-19 Jakub Jelinek * nss/getXXbyYY_r.c: Include atomic.h. diff --git a/include/atomic.h b/include/atomic.h index a1598e3850a..d44728b215c 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -324,6 +324,12 @@ #endif +#ifndef atomic_forced_read +# define atomic_forced_read(x) \ + ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; }) +#endif + + #ifndef atomic_delay # define atomic_delay() do { /* nothing */ } while (0) #endif diff --git a/nptl/ChangeLog b/nptl/ChangeLog index f96101aa9e1..d8afffea819 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,8 @@ +2006-12-21 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure + tid isn't reread from pd->tid in between ESRCH test and the syscall. + 2006-09-24 Ulrich Drepper [BZ #3251] diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c index 9115d6f40b2..75089365c3e 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -33,7 +33,15 @@ __pthread_kill (threadid, signo) struct pthread *pd = (struct pthread *) threadid; /* Make sure the descriptor is valid. */ - if (INVALID_TD_P (pd)) + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) /* Not a valid thread handle. */ return ESRCH; @@ -53,15 +61,15 @@ __pthread_kill (threadid, signo) int val; #if __ASSUME_TGKILL val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); #else # ifdef __NR_tgkill val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); if (INTERNAL_SYSCALL_ERROR_P (val, err) && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) # endif - val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, signo); + val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); #endif return (INTERNAL_SYSCALL_ERROR_P (val, err)