summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorLines
2019-02-20fix spurious undefined behavior in getaddrinfoRich Felker-3/+2
addressing &out[k].sa was arguably undefined, despite &out[k] being defined the slot one past the end of an array, since the member access .sa is intervening between the [] operator and the & operator.
2019-02-20fix invalid free of partial addrinfo list with multiple servicesRich Felker-1/+1
the backindex stored by getaddrinfo to allow freeaddrinfo to perform partial-free wrongly used the address result index, rather than the output slot index, and thus was only valid when they were equal (nservs==1). patch based on report with proposed fix by Markus Wichmann.
2019-02-18install dynamic tls synchronously at dlopen, streamline accessRich Felker-160/+86
previously, dynamic loading of new libraries with thread-local storage allocated the storage needed for all existing threads at load-time, precluding late failure that can't be handled, but left installation in existing threads to take place lazily on first access. this imposed an additional memory access and branch on every dynamic tls access, and imposed a requirement, which was not actually met, that the dynamic tlsdesc asm functions preserve all call-clobbered registers before calling C code to to install new dynamic tls on first access. the x86[_64] versions of this code wrongly omitted saving and restoring of fpu/vector registers, assuming the compiler would not generate anything using them in the called C code. the arm and aarch64 versions saved known existing registers, but failed to be future-proof against expansion of the register file. now that we track live threads in a list, it's possible to install the new dynamic tls for each thread at dlopen time. for the most part, synchronization is not needed, because if a thread has not synchronized with completion of the dlopen, there is no way it can meaningfully request access to a slot past the end of the old dtv, which remains valid for accessing slots which already existed. however, it is necessary to ensure that, if a thread sees its new dtv pointer, it sees correct pointers in each of the slots that existed prior to the dlopen. my understanding is that, on most real-world coherency architectures including all the ones we presently support, a built-in consume order guarantees this; however, don't rely on that. instead, the SYS_membarrier syscall is used to ensure that all threads see the stores to the slots of their new dtv prior to the installation of the new dtv. if it is not supported, the same is implemented in userspace via signals, using the same mechanism as __synccall. the __tls_get_addr function, variants, and dynamic tlsdesc asm functions are all updated to remove the fallback paths for claiming new dynamic tls, and are now all branch-free.
2019-02-17fix data race between new pthread_key_delete and dtor executionRich Felker-2/+4
access to clear the entry in each thread's tsd array for the key being deleted was not synchronized with __pthread_tsd_run_dtors. I probably made this mistake from a mistaken belief that the thread list lock was held during the latter, which of course is not possible since it executes application code in a still-live-thread context. while we're at it, expand the interval during which signals are blocked to cover taking the write lock on key_lock, so that a signal at an inopportune time doesn't block forward progress of readers.
2019-02-16introduce namespace-safe rwlock aliases; use in pthread_key_createRich Felker-20/+41
commit 84d061d5a31c9c773e29e1e2b1ffe8cb9557bc58 inadvertently introduced namespace violations by using the pthread-namespace rwlock functions in pthread_key_create, which is in turn used for C11 tss. fix that and possible future uses of rwlocks elsewhere.
2019-02-16rewrite pthread_key_delete to use global thread listRich Felker-75/+19
with the availability of the thread list, there is no need to mark tsd key slots dirty and clean them up only when a free slot can't be found. instead, directly iterate threads and clear any value associated with the key being deleted. no synchronization is necessary for the clearing, since there is no way the slot can be accessed without having synchronized with the creation of a new key occupying the same slot, which is already sequenced after and synchronized with the deletion of the old key.
2019-02-16rewrite __synccall in terms of global thread listRich Felker-124/+59
the __synccall mechanism provides stop-the-world synchronous execution of a callback in all threads of the process. it is used to implement multi-threaded setuid/setgid operations, since Linux lacks them at the kernel level, and for some other less-critical purposes. this change eliminates dependency on /proc/self/task to determine the set of live threads, which in addition to being an unwanted dependency and a potential point of resource-exhaustion failure, turned out to be inaccurate. test cases provided by Alexey Izbyshev showed that it could fail to reflect newly created threads. due to how the presignaling phase worked, this usually yielded a deadlock if hit, but in the worst case it could also result in threads being silently missed (allowed to continue running without executing the callback).
2019-02-15track all live threads in an AS-safe, fully-consistent linked listRich Felker-43/+94
the hard problem here is unlinking threads from a list when they exit without creating a window of inconsistency where the kernel task for a thread still exists and is still executing instructions in userspace, but is not reflected in the list. the magic solution here is getting rid of per-thread exit futex addresses (set_tid_address), and instead using the exit futex to unlock the global thread list. since pthread_join can no longer see the thread enter a detach_state of EXITED (which depended on the exit futex address pointing to the detach_state), it must now observe the unlocking of the thread list lock before it can unmap the joined thread and return. it doesn't actually have to take the lock. for this, a __tl_sync primitive is offered, with a signature that will allow it to be enhanced for quick return even under contention on the lock, if needed. for now, the exiting thread always performs a futex wake on its detach_state. a future change could optimize this out except when there is already a joiner waiting. initial/dynamic variants of detached state no longer need to be tracked separately, since the futex address is always set to the global list lock, not a thread-local address that could become invalid on detached thread exit. all detached threads, however, must perform a second sigprocmask syscall to block implementation-internal signals, since locking the thread list with them already blocked is not permissible. the arch-independent C version of __unmapself no longer needs to take a lock or setup its own futex address to release the lock, since it must necessarily be called with the thread list lock already held, guaranteeing exclusive access to the temporary stack. changes to libc.threads_minus_1 no longer need to be atomic, since they are guarded by the thread list lock. it is largely vestigial at this point, and can be replaced with a cheaper boolean indicating whether the process is multithreaded at some point in the future.
2019-02-15always block signals for starting new threads, refactor start argsRich Felker-68/+56
whether signals need to be blocked at thread start, and whether unblocking is necessary in the entry point function, has historically depended on intricacies of the cancellation design and on whether there are scheduling operations to perform on the new thread before its successful creation can be committed. future changes to track an AS-safe list of live threads will require signals to be blocked whenever changes are made to the list, so ... prior to commits b8742f32602add243ee2ce74d804015463726899 and 40bae2d32fd6f3ffea437fa745ad38a1fe77b27e, a signal mask for the entry function to restore was part of the pthread structure. it was removed to trim down the size of the structure, which both saved a small amount of stack space and improved code generation on archs where small immediate displacements are less costly than arbitrary ones, by limiting the range of offsets between the base of the thread structure, its members, and the thread pointer. these commits moved the saved mask to a special structure used only when special scheduling was needed, in which case the pthread_create caller and new thread had to synchronize with each other and could use this memory to pass a mask. this commit partially reverts the above two commits, but instead of putting the mask back in the pthread structure, it moves all "start argument" members out of the pthread structure, trimming it down further, and puts them in a separate structure passed on the new thread's stack. the code path for explicit scheduling of the new thread is also changed to synchronize with the calling thread in such a way to avoid spurious futex wakes.
2019-02-15for SIGEV_THREAD timer threads, replace signal handler with sigwaitinfoRich Felker-21/+16
this eliminates some ugly hacks that were repurposing the start function and start argument fields in the pthread structure for timer use, and the need to longjmp out of a signal handler.
2019-02-15defer free of thread-local dlerror buffers from inconsistent contextRich Felker-2/+20
__dl_thread_cleanup is called from the context of an exiting thread that is not in a consistent state valid for calling application code. since commit c9f415d7ea2dace5bf77f6518b6afc36bb7a5732, it's possible (and supported usage) for the allocator to have been replaced by the application, so __dl_thread_cleanup can no longer call free. instead, reuse the message buffer as a linked-list pointer, and queue it to be freed the next time any dynamic linker error message is generated.
2019-02-13fix behavior of gets when input line contains a null byteRich Felker-3/+8
the way gets was implemented in terms of fgets, it used the location of the null termination to determine where to find and remove the newline, if any. an embedded null byte prevented this from working. this also fixes a one-byte buffer overflow, whereby when gets read an N-byte line (not counting newline), it would store two null terminators for a total of N+2 bytes. it's unlikely that anyone would care that a function whose use is pretty much inherently a buffer overflow writes too much, but it could break the only possible correct uses of this function, in conjunction with input of known format from a trusted/same-privilege-domain source, where the buffer length may have been selected to exactly match a line length contract. there seems to be no correct way to implement gets in terms of a single call to fgets or scanf, and using multiple calls would require explicit locking, so we might as well just write the logic out explicitly character-at-a-time. this isn't fast, but nobody cares if a catastrophically unsafe function that's so bad it was removed from the C language is fast.
2019-02-12redesign robust mutex states to eliminate data races on type fieldRich Felker-12/+23
in order to implement ENOTRECOVERABLE, the implementation has traditionally used a bit of the mutex type field to indicate that it's recovered after EOWNERDEAD and will go into ENOTRECOVERABLE state if pthread_mutex_consistent is not called before unlocking. while it's only the thread that holds the lock that needs access to this information (except possibly for the sake of pthread_mutex_consistent choosing between EINVAL and EPERM for erroneous calls), the change to the type field is formally a data race with all other threads that perform any operation on the mutex. no individual bits race, and no write races are possible, so things are "okay" in some sense, but it's still not good. this patch moves the recovery/consistency state to the mutex owner/lock field which is rightfully mutable. bit 30, the same bit the kernel uses with a zero owner to indicate that the previous owner died holding the lock, is now used with a nonzero owner to indicate that the mutex is held but has not yet been marked consistent. note that the kernel ABI also reserves bit 29 not to appear in any tid, so the sentinel value we use for ENOTRECOVERABLE, 0x7fffffff, does not clash with any tid plus bit 30.
2019-02-07fail fdopendir for O_PATH file descriptorsRich Felker-0/+4
fdopendir is specified to fail with EBADF if the file descriptor passed is not open for reading. while O_PATH is an extension and arguably exempt from this requirement, it's used, albeit incompletely, to implement O_SEARCH, and fdopendir should fail when passed an O_SEARCH file descriptor. the new check is performed after fstat so that we don't have to consider the possibility that the fd is invalid. an alternate solution would be attempting to pre-fill the buffer using getdents, which would fail with EBADF for us, but that seems more complex and error-prone and involves either code duplication or refactoring, so the simple fix with an additional inexpensive syscall is what I've made for now.
2019-02-07update line discipline constantsBobby Bingham-0/+12
2019-02-07move arch-invariant definitions out of bits/ioctl.hBobby Bingham-682/+98
2019-02-07locale: ensure dcngettext() preserves errnoA. Wilcox-0/+3
Some packages call gettext to format a message to be sent to perror. If the currently set user locale points to a non-existent .mo file, open via __map_file in dcngettext will set errno to ENOENT. Maintainer's notes: Non-modification of errno is a documented part of the interface contract for the GNU version of this function and likely other versions. The issue being fixed here seems to be a regression from commit 1b52863e244ecee5b5935b6d36bb9e6efe84c035, which enabled setting of errno from __map_file.