| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2024-57996: net_sched: sch_sfq: don't allow 1 packet limit |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| net_sched: sch_sfq: don't allow 1 packet limit |
| |
| The current implementation does not work correctly with a limit of |
| 1. iproute2 actually checks for this and this patch adds the check in |
| kernel as well. |
| |
| This fixes the following syzkaller reported crash: |
| |
| UBSAN: array-index-out-of-bounds in net/sched/sch_sfq.c:210:6 |
| index 65535 is out of range for type 'struct sfq_head[128]' |
| CPU: 0 PID: 2569 Comm: syz-executor101 Not tainted 5.10.0-smp-DEV #1 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 |
| Call Trace: |
| __dump_stack lib/dump_stack.c:79 [inline] |
| dump_stack+0x125/0x19f lib/dump_stack.c:120 |
| ubsan_epilogue lib/ubsan.c:148 [inline] |
| __ubsan_handle_out_of_bounds+0xed/0x120 lib/ubsan.c:347 |
| sfq_link net/sched/sch_sfq.c:210 [inline] |
| sfq_dec+0x528/0x600 net/sched/sch_sfq.c:238 |
| sfq_dequeue+0x39b/0x9d0 net/sched/sch_sfq.c:500 |
| sfq_reset+0x13/0x50 net/sched/sch_sfq.c:525 |
| qdisc_reset+0xfe/0x510 net/sched/sch_generic.c:1026 |
| tbf_reset+0x3d/0x100 net/sched/sch_tbf.c:319 |
| qdisc_reset+0xfe/0x510 net/sched/sch_generic.c:1026 |
| dev_reset_queue+0x8c/0x140 net/sched/sch_generic.c:1296 |
| netdev_for_each_tx_queue include/linux/netdevice.h:2350 [inline] |
| dev_deactivate_many+0x6dc/0xc20 net/sched/sch_generic.c:1362 |
| __dev_close_many+0x214/0x350 net/core/dev.c:1468 |
| dev_close_many+0x207/0x510 net/core/dev.c:1506 |
| unregister_netdevice_many+0x40f/0x16b0 net/core/dev.c:10738 |
| unregister_netdevice_queue+0x2be/0x310 net/core/dev.c:10695 |
| unregister_netdevice include/linux/netdevice.h:2893 [inline] |
| __tun_detach+0x6b6/0x1600 drivers/net/tun.c:689 |
| tun_detach drivers/net/tun.c:705 [inline] |
| tun_chr_close+0x104/0x1b0 drivers/net/tun.c:3640 |
| __fput+0x203/0x840 fs/file_table.c:280 |
| task_work_run+0x129/0x1b0 kernel/task_work.c:185 |
| exit_task_work include/linux/task_work.h:33 [inline] |
| do_exit+0x5ce/0x2200 kernel/exit.c:931 |
| do_group_exit+0x144/0x310 kernel/exit.c:1046 |
| __do_sys_exit_group kernel/exit.c:1057 [inline] |
| __se_sys_exit_group kernel/exit.c:1055 [inline] |
| __x64_sys_exit_group+0x3b/0x40 kernel/exit.c:1055 |
| do_syscall_64+0x6c/0xd0 |
| entry_SYSCALL_64_after_hwframe+0x61/0xcb |
| RIP: 0033:0x7fe5e7b52479 |
| Code: Unable to access opcode bytes at RIP 0x7fe5e7b5244f. |
| RSP: 002b:00007ffd3c800398 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 |
| RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fe5e7b52479 |
| RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000 |
| RBP: 00007fe5e7bcd2d0 R08: ffffffffffffffb8 R09: 0000000000000014 |
| R10: 0000000000000000 R11: 0000000000000246 R12: 00007fe5e7bcd2d0 |
| R13: 0000000000000000 R14: 00007fe5e7bcdd20 R15: 00007fe5e7b24270 |
| |
| The crash can be also be reproduced with the following (with a tc |
| recompiled to allow for sfq limits of 1): |
| |
| tc qdisc add dev dummy0 handle 1: root tbf rate 1Kbit burst 100b lat 1s |
| ../iproute2-6.9.0/tc/tc qdisc add dev dummy0 handle 2: parent 1:10 sfq limit 1 |
| ifconfig dummy0 up |
| ping -I dummy0 -f -c2 -W0.1 8.8.8.8 |
| sleep 1 |
| |
| Scenario that triggers the crash: |
| |
| * the first packet is sent and queued in TBF and SFQ; qdisc qlen is 1 |
| |
| * TBF dequeues: it peeks from SFQ which moves the packet to the |
| gso_skb list and keeps qdisc qlen set to 1. TBF is out of tokens so |
| it schedules itself for later. |
| |
| * the second packet is sent and TBF tries to queues it to SFQ. qdisc |
| qlen is now 2 and because the SFQ limit is 1 the packet is dropped |
| by SFQ. At this point qlen is 1, and all of the SFQ slots are empty, |
| however q->tail is not NULL. |
| |
| At this point, assuming no more packets are queued, when sch_dequeue |
| runs again it will decrement the qlen for the current empty slot |
| causing an underflow and the subsequent out of bounds access. |
| |
| The Linux kernel CVE team has assigned CVE-2024-57996 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 2.6.12 with commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 and fixed in 6.1.129 with commit 35d0137305ae2f97260a9047f445bd4434bd6cc7 |
| Issue introduced in 2.6.12 with commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 and fixed in 6.6.76 with commit 833e9a1c27b82024db7ff5038a51651f48f05e5e |
| Issue introduced in 2.6.12 with commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 and fixed in 6.12.13 with commit 7d8947f2153ee9c5ab4cb17861a11cc45f30e8c4 |
| Issue introduced in 2.6.12 with commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 and fixed in 6.13.2 with commit 7fefc294204f10a3405f175f4ac2be16d63f135e |
| Issue introduced in 2.6.12 with commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 and fixed in 6.14 with commit 10685681bafce6febb39770f3387621bf5d67d0b |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2024-57996 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| net/sched/sch_sfq.c |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/35d0137305ae2f97260a9047f445bd4434bd6cc7 |
| https://git.kernel.org/stable/c/833e9a1c27b82024db7ff5038a51651f48f05e5e |
| https://git.kernel.org/stable/c/7d8947f2153ee9c5ab4cb17861a11cc45f30e8c4 |
| https://git.kernel.org/stable/c/7fefc294204f10a3405f175f4ac2be16d63f135e |
| https://git.kernel.org/stable/c/10685681bafce6febb39770f3387621bf5d67d0b |