mirror of
git://git.musl-libc.org/musl
synced 2025-02-28 08:40:25 +00:00
fix false ownership of stdio FILEs due to tid reuse
this is analogous commit fffc5cda10
which fixed the corresponding issue for mutexes.
the robust list can't be used here because the locks do not share a
common layout with mutexes. at some point it may make sense to simply
incorporate a mutex object into the FILE structure and use it, but
that would be a much more invasive change, and it doesn't mesh well
with the current design that uses a simpler code path for internal
locking and pulls in the recursive-mutex-like code when the flockfile
API is used explicitly.
This commit is contained in:
parent
b8ca9eb530
commit
5345c9b884
@ -44,6 +44,7 @@ struct pthread {
|
||||
int exitlock[2];
|
||||
int startlock[2];
|
||||
unsigned long sigmask[_NSIG/8/sizeof(long)];
|
||||
void *stdio_locks;
|
||||
};
|
||||
|
||||
struct __timer {
|
||||
|
@ -46,6 +46,7 @@ struct _IO_FILE {
|
||||
void *mustbezero_2;
|
||||
unsigned char *shend;
|
||||
off_t shlim, shcnt;
|
||||
FILE *prev_locked, *next_locked;
|
||||
};
|
||||
|
||||
size_t __stdio_read(FILE *, unsigned char *, size_t);
|
||||
|
@ -1,4 +1,8 @@
|
||||
#include "stdio_impl.h"
|
||||
#include "libc.h"
|
||||
|
||||
static void dummy(FILE *f) { }
|
||||
weak_alias(dummy, __unlist_locked_file);
|
||||
|
||||
int fclose(FILE *f)
|
||||
{
|
||||
@ -7,6 +11,8 @@ int fclose(FILE *f)
|
||||
|
||||
FFINALLOCK(f);
|
||||
|
||||
__unlist_locked_file(f);
|
||||
|
||||
if (!(perm = f->flags & F_PERM)) {
|
||||
OFLLOCK();
|
||||
if (f->prev) f->prev->next = f->next;
|
||||
|
@ -2,9 +2,26 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <limits.h>
|
||||
|
||||
void __do_orphaned_stdio_locks()
|
||||
{
|
||||
FILE *f;
|
||||
for (f=__pthread_self()->stdio_locks; f; f=f->next_locked)
|
||||
a_store(&f->lock, 0x40000000);
|
||||
}
|
||||
|
||||
void __unlist_locked_file(FILE *f)
|
||||
{
|
||||
if (f->lockcount) {
|
||||
if (f->next_locked) f->next_locked->prev_locked = f->prev_locked;
|
||||
if (f->prev_locked) f->prev_locked->next_locked = f->next_locked;
|
||||
else __pthread_self()->stdio_locks = f->next_locked;
|
||||
}
|
||||
}
|
||||
|
||||
int ftrylockfile(FILE *f)
|
||||
{
|
||||
int tid = __pthread_self()->tid;
|
||||
pthread_t self = __pthread_self();
|
||||
int tid = self->tid;
|
||||
if (f->lock == tid) {
|
||||
if (f->lockcount == LONG_MAX)
|
||||
return -1;
|
||||
@ -15,5 +32,8 @@ int ftrylockfile(FILE *f)
|
||||
if (f->lock || a_cas(&f->lock, 0, tid))
|
||||
return -1;
|
||||
f->lockcount = 1;
|
||||
f->prev_locked = 0;
|
||||
f->next_locked = self->stdio_locks;
|
||||
self->stdio_locks = f;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
#include "stdio_impl.h"
|
||||
#include "pthread_impl.h"
|
||||
|
||||
void __unlist_locked_file(FILE *);
|
||||
|
||||
void funlockfile(FILE *f)
|
||||
{
|
||||
if (!--f->lockcount) __unlockfile(f);
|
||||
if (f->lockcount == 1) {
|
||||
__unlist_locked_file(f);
|
||||
f->lockcount = 0;
|
||||
__unlockfile(f);
|
||||
} else {
|
||||
f->lockcount--;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ weak_alias(dummy_0, __acquire_ptc);
|
||||
weak_alias(dummy_0, __release_ptc);
|
||||
weak_alias(dummy_0, __pthread_tsd_run_dtors);
|
||||
weak_alias(dummy_0, __do_private_robust_list);
|
||||
weak_alias(dummy_0, __do_orphaned_stdio_locks);
|
||||
|
||||
_Noreturn void pthread_exit(void *result)
|
||||
{
|
||||
@ -66,6 +67,7 @@ _Noreturn void pthread_exit(void *result)
|
||||
}
|
||||
|
||||
__do_private_robust_list();
|
||||
__do_orphaned_stdio_locks();
|
||||
|
||||
if (self->detached && self->map_base) {
|
||||
/* Detached threads must avoid the kernel clear_child_tid
|
||||
|
Loading…
Reference in New Issue
Block a user