diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2959.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2959.patch | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2959.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2959.patch new file mode 100644 index 000000000..f8117d0a7 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2959.patch @@ -0,0 +1,97 @@ +From 189b0ddc245139af81198d1a3637cac74f96e13a Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Thu, 26 May 2022 07:34:52 +0100 +Subject: [PATCH] pipe: Fix missing lock in pipe_resize_ring() + +pipe_resize_ring() needs to take the pipe->rd_wait.lock spinlock to +prevent post_one_notification() from trying to insert into the ring +whilst the ring is being replaced. + +The occupancy check must be done after the lock is taken, and the lock +must be taken after the new ring is allocated. + +The bug can lead to an oops looking something like: + + BUG: KASAN: use-after-free in post_one_notification.isra.0+0x62e/0x840 + Read of size 4 at addr ffff88801cc72a70 by task poc/27196 + ... + Call Trace: + post_one_notification.isra.0+0x62e/0x840 + __post_watch_notification+0x3b7/0x650 + key_create_or_update+0xb8b/0xd20 + __do_sys_add_key+0x175/0x340 + __x64_sys_add_key+0xbe/0x140 + do_syscall_64+0x5c/0xc0 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +Reported by Selim Enes Karaduman @Enesdex working with Trend Micro Zero +Day Initiative. + +Fixes: c73be61cede5 ("pipe: Add general notification queue support") +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-17291 +Signed-off-by: David Howells <dhowells@redhat.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + fs/pipe.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index e140ea150bbb14..11358569a7779a 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -1245,30 +1245,33 @@ unsigned int round_pipe_size(unsigned long size) + + /* + * Resize the pipe ring to a number of slots. ++ * ++ * Note the pipe can be reduced in capacity, but only if the current ++ * occupancy doesn't exceed nr_slots; if it does, EBUSY will be ++ * returned instead. + */ + int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) + { + struct pipe_buffer *bufs; + unsigned int head, tail, mask, n; + +- /* +- * We can shrink the pipe, if arg is greater than the ring occupancy. +- * Since we don't expect a lot of shrink+grow operations, just free and +- * allocate again like we would do for growing. If the pipe currently +- * contains more buffers than arg, then return busy. +- */ +- mask = pipe->ring_size - 1; +- head = pipe->head; +- tail = pipe->tail; +- n = pipe_occupancy(pipe->head, pipe->tail); +- if (nr_slots < n) +- return -EBUSY; +- + bufs = kcalloc(nr_slots, sizeof(*bufs), + GFP_KERNEL_ACCOUNT | __GFP_NOWARN); + if (unlikely(!bufs)) + return -ENOMEM; + ++ spin_lock_irq(&pipe->rd_wait.lock); ++ mask = pipe->ring_size - 1; ++ head = pipe->head; ++ tail = pipe->tail; ++ ++ n = pipe_occupancy(head, tail); ++ if (nr_slots < n) { ++ spin_unlock_irq(&pipe->rd_wait.lock); ++ kfree(bufs); ++ return -EBUSY; ++ } ++ + /* + * The pipe array wraps around, so just start the new one at zero + * and adjust the indices. +@@ -1300,6 +1303,8 @@ int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) + pipe->tail = tail; + pipe->head = head; + ++ spin_unlock_irq(&pipe->rd_wait.lock); ++ + /* This might have made more room for writers */ + wake_up_interruptible(&pipe->wr_wait); + return 0; |