From: Greg Kroah-Hartman Date: Fri, 3 Jan 2025 14:47:55 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v5.4.289~70 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b0bb195e3a9629f39749dc9aed3eee7dec6fab33;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: btrfs-fix-use-after-free-in-btrfs_encoded_read_endio.patch selinux-ignore-unknown-extended-permissions.patch --- diff --git a/queue-6.1/btrfs-fix-use-after-free-in-btrfs_encoded_read_endio.patch b/queue-6.1/btrfs-fix-use-after-free-in-btrfs_encoded_read_endio.patch new file mode 100644 index 00000000000..734e2b089f7 --- /dev/null +++ b/queue-6.1/btrfs-fix-use-after-free-in-btrfs_encoded_read_endio.patch @@ -0,0 +1,211 @@ +From 05b36b04d74a517d6675bf2f90829ff1ac7e28dc Mon Sep 17 00:00:00 2001 +From: Johannes Thumshirn +Date: Wed, 13 Nov 2024 18:16:48 +0100 +Subject: btrfs: fix use-after-free in btrfs_encoded_read_endio() + +From: Johannes Thumshirn + +commit 05b36b04d74a517d6675bf2f90829ff1ac7e28dc upstream. + +Shinichiro reported the following use-after free that sometimes is +happening in our CI system when running fstests' btrfs/284 on a TCMU +runner device: + + BUG: KASAN: slab-use-after-free in lock_release+0x708/0x780 + Read of size 8 at addr ffff888106a83f18 by task kworker/u80:6/219 + + CPU: 8 UID: 0 PID: 219 Comm: kworker/u80:6 Not tainted 6.12.0-rc6-kts+ #15 + Hardware name: Supermicro Super Server/X11SPi-TF, BIOS 3.3 02/21/2020 + Workqueue: btrfs-endio btrfs_end_bio_work [btrfs] + Call Trace: + + dump_stack_lvl+0x6e/0xa0 + ? lock_release+0x708/0x780 + print_report+0x174/0x505 + ? lock_release+0x708/0x780 + ? __virt_addr_valid+0x224/0x410 + ? lock_release+0x708/0x780 + kasan_report+0xda/0x1b0 + ? lock_release+0x708/0x780 + ? __wake_up+0x44/0x60 + lock_release+0x708/0x780 + ? __pfx_lock_release+0x10/0x10 + ? __pfx_do_raw_spin_lock+0x10/0x10 + ? lock_is_held_type+0x9a/0x110 + _raw_spin_unlock_irqrestore+0x1f/0x60 + __wake_up+0x44/0x60 + btrfs_encoded_read_endio+0x14b/0x190 [btrfs] + btrfs_check_read_bio+0x8d9/0x1360 [btrfs] + ? lock_release+0x1b0/0x780 + ? trace_lock_acquire+0x12f/0x1a0 + ? __pfx_btrfs_check_read_bio+0x10/0x10 [btrfs] + ? process_one_work+0x7e3/0x1460 + ? lock_acquire+0x31/0xc0 + ? process_one_work+0x7e3/0x1460 + process_one_work+0x85c/0x1460 + ? __pfx_process_one_work+0x10/0x10 + ? assign_work+0x16c/0x240 + worker_thread+0x5e6/0xfc0 + ? __pfx_worker_thread+0x10/0x10 + kthread+0x2c3/0x3a0 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x31/0x70 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + + Allocated by task 3661: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0xaa/0xb0 + btrfs_encoded_read_regular_fill_pages+0x16c/0x6d0 [btrfs] + send_extent_data+0xf0f/0x24a0 [btrfs] + process_extent+0x48a/0x1830 [btrfs] + changed_cb+0x178b/0x2ea0 [btrfs] + btrfs_ioctl_send+0x3bf9/0x5c20 [btrfs] + _btrfs_ioctl_send+0x117/0x330 [btrfs] + btrfs_ioctl+0x184a/0x60a0 [btrfs] + __x64_sys_ioctl+0x12e/0x1a0 + do_syscall_64+0x95/0x180 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + Freed by task 3661: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3b/0x70 + __kasan_slab_free+0x4f/0x70 + kfree+0x143/0x490 + btrfs_encoded_read_regular_fill_pages+0x531/0x6d0 [btrfs] + send_extent_data+0xf0f/0x24a0 [btrfs] + process_extent+0x48a/0x1830 [btrfs] + changed_cb+0x178b/0x2ea0 [btrfs] + btrfs_ioctl_send+0x3bf9/0x5c20 [btrfs] + _btrfs_ioctl_send+0x117/0x330 [btrfs] + btrfs_ioctl+0x184a/0x60a0 [btrfs] + __x64_sys_ioctl+0x12e/0x1a0 + do_syscall_64+0x95/0x180 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + The buggy address belongs to the object at ffff888106a83f00 + which belongs to the cache kmalloc-rnd-07-96 of size 96 + The buggy address is located 24 bytes inside of + freed 96-byte region [ffff888106a83f00, ffff888106a83f60) + + The buggy address belongs to the physical page: + page: refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888106a83800 pfn:0x106a83 + flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff) + page_type: f5(slab) + raw: 0017ffffc0000000 ffff888100053680 ffffea0004917200 0000000000000004 + raw: ffff888106a83800 0000000080200019 00000001f5000000 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffff888106a83e00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc + ffff888106a83e80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc + >ffff888106a83f00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc + ^ + ffff888106a83f80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc + ffff888106a84000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ================================================================== + +Further analyzing the trace and the crash dump's vmcore file shows that +the wake_up() call in btrfs_encoded_read_endio() is calling wake_up() on +the wait_queue that is in the private data passed to the end_io handler. + +Commit 4ff47df40447 ("btrfs: move priv off stack in +btrfs_encoded_read_regular_fill_pages()") moved 'struct +btrfs_encoded_read_private' off the stack. + +Before that commit one can see a corruption of the private data when +analyzing the vmcore after a crash: + +*(struct btrfs_encoded_read_private *)0xffff88815626eec8 = { + .wait = (wait_queue_head_t){ + .lock = (spinlock_t){ + .rlock = (struct raw_spinlock){ + .raw_lock = (arch_spinlock_t){ + .val = (atomic_t){ + .counter = (int)-2005885696, + }, + .locked = (u8)0, + .pending = (u8)157, + .locked_pending = (u16)40192, + .tail = (u16)34928, + }, + .magic = (unsigned int)536325682, + .owner_cpu = (unsigned int)29, + .owner = (void *)__SCT__tp_func_btrfs_transaction_commit+0x0 = 0x0, + .dep_map = (struct lockdep_map){ + .key = (struct lock_class_key *)0xffff8881575a3b6c, + .class_cache = (struct lock_class *[2]){ 0xffff8882a71985c0, 0xffffea00066f5d40 }, + .name = (const char *)0xffff88815626f100 = "", + .wait_type_outer = (u8)37, + .wait_type_inner = (u8)178, + .lock_type = (u8)154, + }, + }, + .__padding = (u8 [24]){ 0, 157, 112, 136, 50, 174, 247, 31, 29 }, + .dep_map = (struct lockdep_map){ + .key = (struct lock_class_key *)0xffff8881575a3b6c, + .class_cache = (struct lock_class *[2]){ 0xffff8882a71985c0, 0xffffea00066f5d40 }, + .name = (const char *)0xffff88815626f100 = "", + .wait_type_outer = (u8)37, + .wait_type_inner = (u8)178, + .lock_type = (u8)154, + }, + }, + .head = (struct list_head){ + .next = (struct list_head *)0x112cca, + .prev = (struct list_head *)0x47, + }, + }, + .pending = (atomic_t){ + .counter = (int)-1491499288, + }, + .status = (blk_status_t)130, +} + +Here we can see several indicators of in-memory data corruption, e.g. the +large negative atomic values of ->pending or +->wait->lock->rlock->raw_lock->val, as well as the bogus spinlock magic +0x1ff7ae32 (decimal 536325682 above) instead of 0xdead4ead or the bogus +pointer values for ->wait->head. + +To fix this, change atomic_dec_return() to atomic_dec_and_test() to fix the +corruption, as atomic_dec_return() is defined as two instructions on +x86_64, whereas atomic_dec_and_test() is defined as a single atomic +operation. This can lead to a situation where counter value is already +decremented but the if statement in btrfs_encoded_read_endio() is not +completely processed, i.e. the 0 test has not completed. If another thread +continues executing btrfs_encoded_read_regular_fill_pages() the +atomic_dec_return() there can see an already updated ->pending counter and +continues by freeing the private data. Continuing in the endio handler the +test for 0 succeeds and the wait_queue is woken up, resulting in a +use-after-free. + +Reported-by: Shinichiro Kawasaki +Suggested-by: Damien Le Moal +Fixes: 1881fba89bd5 ("btrfs: add BTRFS_IOC_ENCODED_READ ioctl") +CC: stable@vger.kernel.org # 6.1+ +Reviewed-by: Filipe Manana +Reviewed-by: Qu Wenruo +Signed-off-by: Johannes Thumshirn +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Alva Lan +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -10469,7 +10469,7 @@ static void btrfs_encoded_read_endio(str + */ + WRITE_ONCE(priv->status, status); + } +- if (!atomic_dec_return(&priv->pending)) ++ if (atomic_dec_and_test(&priv->pending)) + wake_up(&priv->wait); + btrfs_bio_free_csum(bbio); + bio_put(&bbio->bio); diff --git a/queue-6.1/selinux-ignore-unknown-extended-permissions.patch b/queue-6.1/selinux-ignore-unknown-extended-permissions.patch new file mode 100644 index 00000000000..1b2ea7cbce3 --- /dev/null +++ b/queue-6.1/selinux-ignore-unknown-extended-permissions.patch @@ -0,0 +1,50 @@ +From 900f83cf376bdaf798b6f5dcb2eae0c822e908b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thi=C3=A9baud=20Weksteen?= +Date: Thu, 5 Dec 2024 12:09:19 +1100 +Subject: selinux: ignore unknown extended permissions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thiébaud Weksteen + +commit 900f83cf376bdaf798b6f5dcb2eae0c822e908b6 upstream. + +When evaluating extended permissions, ignore unknown permissions instead +of calling BUG(). This commit ensures that future permissions can be +added without interfering with older kernels. + +Cc: stable@vger.kernel.org +Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls") +Signed-off-by: Thiébaud Weksteen +Signed-off-by: Paul Moore +Acked-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/ss/services.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -969,7 +969,10 @@ void services_compute_xperms_decision(st + xpermd->driver)) + return; + } else { +- BUG(); ++ pr_warn_once( ++ "SELinux: unknown extended permission (%u) will be ignored\n", ++ node->datum.u.xperms->specified); ++ return; + } + + if (node->key.specified == AVTAB_XPERMS_ALLOWED) { +@@ -1006,7 +1009,8 @@ void services_compute_xperms_decision(st + node->datum.u.xperms->perms.p[i]; + } + } else { +- BUG(); ++ pr_warn_once("SELinux: unknown specified key (%u)\n", ++ node->key.specified); + } + } + diff --git a/queue-6.1/series b/queue-6.1/series index c04ad7f1175..6bede684e91 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -1 +1,3 @@ x86-hyperv-fix-hv-tsc-page-based-sched_clock-for-hibernation.patch +selinux-ignore-unknown-extended-permissions.patch +btrfs-fix-use-after-free-in-btrfs_encoded_read_endio.patch