Skip to content

Commit

Permalink
Merge branch 'for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Aug 5, 2021
2 parents 3c3e902 + 345daff commit 6209049
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions kernel/ucount.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -184,17 +185,20 @@ 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;
}

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);
Expand Down

0 comments on commit 6209049

Please sign in to comment.