summaryrefslogtreecommitdiff
path: root/src/thread/pthread_create.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-01-15 23:17:38 -0500
committerRich Felker <dalias@aerifal.cx>2015-01-15 23:17:38 -0500
commit78a8ef47c4d92b7680c52a85f80a81e29da86bb9 (patch)
tree1363937775b3086470251c8ad9c7f292ce9b6bd9 /src/thread/pthread_create.c
parent7152a61a3ab16eacd8ecb94b81641d76c78958b0 (diff)
downloadmusl-78a8ef47c4d92b7680c52a85f80a81e29da86bb9.tar.gz
overhaul __synccall and fix AS-safety and other issues in set*id
multi-threaded set*id and setrlimit use the internal __synccall function to work around the kernel's wrongful treatment of these process properties as thread-local. the old implementation of __synccall failed to be AS-safe, despite POSIX requiring setuid and setgid to be AS-safe, and was not rigorous in assuring that all threads were caught. in a worst case, threads late in the process of exiting could retain permissions after setuid reported success, in which case attacks to regain dropped permissions may have been possible under the right conditions. the new implementation of __synccall depends on the presence of /proc/self/task and will fail if it can't be opened, but is able to determine that it has caught all threads, and does not use any locks except its own. it thereby achieves AS-safety simply by blocking signals to preclude re-entry in the same thread. with this commit, all known conformance and safety issues in set*id functions should be fixed.
Diffstat (limited to 'src/thread/pthread_create.c')
-rw-r--r--src/thread/pthread_create.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 1a47ed15..64971d56 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -139,6 +139,8 @@ weak_alias(dummy, __pthread_tsd_size);
static void *dummy_tsd[1] = { 0 };
weak_alias(dummy_tsd, __pthread_tsd_main);
+volatile int __block_new_threads = 0;
+
static FILE *volatile dummy_file = 0;
weak_alias(dummy_file, __stdin_used);
weak_alias(dummy_file, __stdout_used);
@@ -178,6 +180,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
if (attrp && !c11) attr = *attrp;
__acquire_ptc();
+ if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
if (attr._a_stackaddr) {
size_t need = libc.tls_size + __pthread_tsd_size;