History

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

Linus Torvalds committed 5 years ago

Commit 62090492 parents 3c3e902 345daff1 file · +7 −3Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/ucount.c+7−3
@@ -160,6 +160,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) · 159 unmodified lines
160160 {
161161 struct hlist_head *hashent = ucounts_hashentry(ns, uid);
162162 struct ucounts *ucounts, *new;
163+ long overflow;
163164
164165 spin_lock_irq(&ucounts_lock);
165166 ucounts = find_ucounts(ns, uid, hashent);
@@ -184,8 +185,12 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) · 18 unmodified lines
184185 return new;
185186 }
186187 }
188+ overflow = atomic_add_negative(1, &ucounts->count);
187189 spin_unlock_irq(&ucounts_lock);
188− ucounts = get_ucounts(ucounts);
190+ if (overflow) {
191+ put_ucounts(ucounts);
192+ return NULL;
193+ }
189194 return ucounts;
190195 }
191196
@@ -193,8 +198,7 @@ void put_ucounts(struct ucounts *ucounts) · 1 unmodified line
193198 {
194199 unsigned long flags;
195200
196− if (atomic_dec_and_test(&ucounts->count)) {
197− spin_lock_irqsave(&ucounts_lock, flags);
201+ if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
198202 hlist_del_init(&ucounts->node);
199203 spin_unlock_irqrestore(&ucounts_lock, flags);
200204 kfree(ucounts);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t