mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
Merge branch 'for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull ucounts fix from Eric Biederman: "Fix a subtle locking versus reference counting bug in the ucount changes, found by syzbot" * 'for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: ucounts: Fix race condition between alloc_ucounts and put_ucounts
This commit is contained in:
commit
6209049ecf
@ -160,6 +160,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
|
||||
{
|
||||
struct hlist_head *hashent = ucounts_hashentry(ns, uid);
|
||||
struct ucounts *ucounts, *new;
|
||||
long overflow;
|
||||
|
||||
spin_lock_irq(&ucounts_lock);
|
||||
ucounts = find_ucounts(ns, uid, hashent);
|
||||
@ -184,8 +185,12 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
|
||||
return new;
|
||||
}
|
||||
}
|
||||
overflow = atomic_add_negative(1, &ucounts->count);
|
||||
spin_unlock_irq(&ucounts_lock);
|
||||
ucounts = get_ucounts(ucounts);
|
||||
if (overflow) {
|
||||
put_ucounts(ucounts);
|
||||
return NULL;
|
||||
}
|
||||
return ucounts;
|
||||
}
|
||||
|
||||
@ -193,8 +198,7 @@ void put_ucounts(struct ucounts *ucounts)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (atomic_dec_and_test(&ucounts->count)) {
|
||||
spin_lock_irqsave(&ucounts_lock, flags);
|
||||
if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
|
||||
hlist_del_init(&ucounts->node);
|
||||
spin_unlock_irqrestore(&ucounts_lock, flags);
|
||||
kfree(ucounts);
|
||||
|
Loading…
Reference in New Issue
Block a user