diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-21 20:38:53 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-21 20:38:53 -0700 |
commit | 6ca014cd2ddb5c56f962ec68f220be049fdcd7a3 (patch) | |
tree | 851ff1f4a6ae4a95d8850e6a2e6ca62dacf9b7fc /kernel | |
parent | 8565d64430f8278bea38dab0a3ab60b4e11c71e4 (diff) | |
parent | 3d8dcf278b1ee1eff1e90be848fa2237db4c07a7 (diff) |
Merge branch 'keys-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull watch_queue fixes from David Howells:
"Here are fixes for a couple more watch_queue bugs, both found by syzbot:
- Fix error cleanup in watch_queue_set_size() where it tries to clean
up all the pointers in the page list, even if they've not been
allocated yet[1]. Unfortunately, __free_page() doesn't treat a NULL
pointer as being "do nothing".
A second report[2] looks like it's probably the same bug, but on
arm64 rather than x86_64, but there's no reproducer.
- Fix a missing kfree in free_watch() to actually free the watch[3]"
Link: https://lore.kernel.org/r/000000000000b1807c05daad8f98@google.com/ [1]
Link: https://lore.kernel.org/r/000000000000035b9c05daae8a5e@google.com/ [2]
Link: https://lore.kernel.org/r/000000000000bc8eaf05dab91c63@google.com/ [3]
* 'keys-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
watch_queue: Actually free the watch
watch_queue: Fix NULL dereference in error cleanup
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/watch_queue.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c index 00703444a219..3990e4df3d7b 100644 --- a/kernel/watch_queue.c +++ b/kernel/watch_queue.c @@ -271,7 +271,7 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes) return 0; error_p: - for (i = 0; i < nr_pages; i++) + while (--i >= 0) __free_page(pages[i]); kfree(pages); error: @@ -395,6 +395,7 @@ static void free_watch(struct rcu_head *rcu) put_watch_queue(rcu_access_pointer(watch->queue)); atomic_dec(&watch->cred->user->nr_watches); put_cred(watch->cred); + kfree(watch); } static void __put_watch(struct kref *kref) |