summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-02-19 11:04:36 -0500
committerRich Felker <dalias@aerifal.cx>2011-02-19 11:04:36 -0500
commit19eb13b9a4cf2f787f60b6e2a6d26a6cd7d3ffd2 (patch)
treec02fa747b1ad7370b689af34f15139cb62fa9863
parenta49c119276742d7d212fb88f83a8f559ca549e72 (diff)
downloadmusl-19eb13b9a4cf2f787f60b6e2a6d26a6cd7d3ffd2.tar.gz
musl-19eb13b9a4cf2f787f60b6e2a6d26a6cd7d3ffd2.tar.bz2
musl-19eb13b9a4cf2f787f60b6e2a6d26a6cd7d3ffd2.tar.xz
musl-19eb13b9a4cf2f787f60b6e2a6d26a6cd7d3ffd2.zip
race condition fix: block all signals before decrementing thread count
the existence of a (kernelspace) thread must never have observable effects after the thread count is decremented. if signals are not blocked, it could end up handling the signal for rsyscall and contributing towards the count of threads which have changed ids, causing a thread to be missed. this could lead to one thread retaining unwanted privilege level. this change may also address other subtle race conditions in application code that uses signals.
-rw-r--r--src/thread/i386/__unmapself.s9
-rw-r--r--src/thread/pthread_create.c2
-rw-r--r--src/thread/x86_64/__unmapself.s13
3 files changed, 2 insertions, 22 deletions
diff --git a/src/thread/i386/__unmapself.s b/src/thread/i386/__unmapself.s
index 5c674966..bcf6e7fe 100644
--- a/src/thread/i386/__unmapself.s
+++ b/src/thread/i386/__unmapself.s
@@ -2,15 +2,6 @@
.global __unmapself
.type __unmapself,%function
__unmapself:
- call 1f
- .long -1
- .long -1
-1: popl %ecx
- xorl %ebx,%ebx
- xorl %edx,%edx
- movl $8,%esi
- movl $175,%eax
- int $128
movl $91,%eax
movl 4(%esp),%ebx
movl 8(%esp),%ecx
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 7c436957..c73c5211 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -25,6 +25,8 @@ void __pthread_unwind_next(struct __ptcb *cb)
}
}
+ syscall4(__NR_sigprocmask, SIG_BLOCK, (long)(uint64_t[1]){-1}, 0, 8);
+
if (!a_fetch_add(&libc.threads_minus_1, -1))
exit(0);
diff --git a/src/thread/x86_64/__unmapself.s b/src/thread/x86_64/__unmapself.s
index 59092eaa..d36257d0 100644
--- a/src/thread/x86_64/__unmapself.s
+++ b/src/thread/x86_64/__unmapself.s
@@ -3,19 +3,6 @@
.global __unmapself
.type __unmapself,%function
__unmapself:
- call 1f /* glibc ABI compat */
- .long -1
- .long -1
-1: push %rsi /* save arg2 for munmap */
- push %rdx /* save arg3 for munmap */
- mov %rdi,%rsi /* rt_sigprocmask() args: move arg1 to rsi */
- xor %rdi,%rdi
- xor %rdx,%rdx
- movq $8,%r10
- movl $14,%eax /* __NR_rt_sigprocmask */
- syscall /* call rt_sigprocmask(0,arg1,0,8) */
- pop %rsi /* munmap() args: reload from stack */
- pop %rdi
movl $11,%eax /* __NR_munmap */
syscall /* munmap(arg2,arg3) */
xor %rdi,%rdi /* exit() args: always return success */