|
Message-ID: <20140610072835.GA8466@brightrain.aerifal.cx> Date: Tue, 10 Jun 2014 03:28:35 -0400 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: Thread pointer changes One of the items on the roadmap for this release cycle is: "Optimizations based on thread-pointer being always-available, and fallbacks for old kernels without thread pointer setting." I've worked out (and have POC code) how to use the modify_ldt syscall to setup a valid thread pointer on i386 for any kernel back to 1.0. For ARM, I think we should revisit the thread-pointer/atomic inlining work that was done as a sloppy workaround for kernels without the kuser_helper page. If the set_thread_area syscall fails (due to an old kernel that doesn't support it), we can setup a function pointer for the __aeabi_read_tp function that only supports a single main thread and returns its thread pointer. Likewise at this stage we could detect the presence or absence of the kuser_helper page and substitute our own fallbacks (using the instructions directly) if needed. One thing that should be checked though is whether there are any kernel versions which support EABI syscalls but not the thread-pointer setup syscall. If not, there's really no use in having a fallback for that. These slides look like they might shed some light on the history: http://wookware.org/talks/armeabidebconf.pdf For MIPS I see no way to support kernels that don't provide set_thread_area. For microblaze, powerpc, and sh, it's impossible not to support the thread pointer; it's simply loaded in a register via a userspace instruction. For x86_64, I'm not sure if pre-2.6 kernels were ever relevant (and I mean real pre-2.6, not RHEL-style 2.4 that's actually patched up to be equivalent to 2.6). But there's no way to emulate the thread pointer. Even if modify_ldt works (and I'm not sure if it does), selectors setup by it can only address 32 bits. As of 1.1.0, musl nominally _requires_ the thread pointer. However there's still a flag indicating whether it's setup (important for code that runs prior to it getting setup, especially accesses to errno) which a few functions check before accessing it. If we're going to eventually support building libc with stack protector (which would have been nice for the recent dns parser issue!) it's important that the thread pointer always be setup anyway, Right now, we have two flags in the libc structure, libc.has_thread_pointer and libc.can_do_threads. Both of these are set in __init_tp() based on the result of __set_thread_area; if it fails, they're left at 0 (false) and if it succeeds they're set to 1 (true). The idea here was that we could eventually change __set_thread_area to have a more fine-grained error reporting to let the caller know that it succeeded in setting up a thread pointer for the main thread, but not in a way that will work for running multiple threads. I'm not sure whether I'll keep this; it actually might make more sense for the arch-specific __set_thread_area to simply store its own flag, which the arch-specific __clone could then inspect and force itself to fail if CLONE_TLS is specified but can't be honored. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.