| 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-26853: igc: avoid returning frame twice in XDP_REDIRECT |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| igc: avoid returning frame twice in XDP_REDIRECT |
| |
| When a frame can not be transmitted in XDP_REDIRECT |
| (e.g. due to a full queue), it is necessary to free |
| it by calling xdp_return_frame_rx_napi. |
| |
| However, this is the responsibility of the caller of |
| the ndo_xdp_xmit (see for example bq_xmit_all in |
| kernel/bpf/devmap.c) and thus calling it inside |
| igc_xdp_xmit (which is the ndo_xdp_xmit of the igc |
| driver) as well will lead to memory corruption. |
| |
| In fact, bq_xmit_all expects that it can return all |
| frames after the last successfully transmitted one. |
| Therefore, break for the first not transmitted frame, |
| but do not call xdp_return_frame_rx_napi in igc_xdp_xmit. |
| This is equally implemented in other Intel drivers |
| such as the igb. |
| |
| There are two alternatives to this that were rejected: |
| 1. Return num_frames as all the frames would have been |
| transmitted and release them inside igc_xdp_xmit. |
| While it might work technically, it is not what |
| the return value is meant to represent (i.e. the |
| number of SUCCESSFULLY transmitted packets). |
| 2. Rework kernel/bpf/devmap.c and all drivers to |
| support non-consecutively dropped packets. |
| Besides being complex, it likely has a negative |
| performance impact without a significant gain |
| since it is anyway unlikely that the next frame |
| can be transmitted if the previous one was dropped. |
| |
| The memory corruption can be reproduced with |
| the following script which leads to a kernel panic |
| after a few seconds. It basically generates more |
| traffic than a i225 NIC can transmit and pushes it |
| via XDP_REDIRECT from a virtual interface to the |
| physical interface where frames get dropped. |
| |
| #!/bin/bash |
| INTERFACE=enp4s0 |
| INTERFACE_IDX=`cat /sys/class/net/$INTERFACE/ifindex` |
| |
| sudo ip link add dev veth1 type veth peer name veth2 |
| sudo ip link set up $INTERFACE |
| sudo ip link set up veth1 |
| sudo ip link set up veth2 |
| |
| cat << EOF > redirect.bpf.c |
| |
| SEC("prog") |
| int redirect(struct xdp_md *ctx) |
| { |
| return bpf_redirect($INTERFACE_IDX, 0); |
| } |
| |
| char _license[] SEC("license") = "GPL"; |
| EOF |
| clang -O2 -g -Wall -target bpf -c redirect.bpf.c -o redirect.bpf.o |
| sudo ip link set veth2 xdp obj redirect.bpf.o |
| |
| cat << EOF > pass.bpf.c |
| |
| SEC("prog") |
| int pass(struct xdp_md *ctx) |
| { |
| return XDP_PASS; |
| } |
| |
| char _license[] SEC("license") = "GPL"; |
| EOF |
| clang -O2 -g -Wall -target bpf -c pass.bpf.c -o pass.bpf.o |
| sudo ip link set $INTERFACE xdp obj pass.bpf.o |
| |
| cat << EOF > trafgen.cfg |
| |
| { |
| /* Ethernet Header */ |
| 0xe8, 0x6a, 0x64, 0x41, 0xbf, 0x46, |
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| const16(ETH_P_IP), |
| |
| /* IPv4 Header */ |
| 0b01000101, 0, # IPv4 version, IHL, TOS |
| const16(1028), # IPv4 total length (UDP length + 20 bytes (IP header)) |
| const16(2), # IPv4 ident |
| 0b01000000, 0, # IPv4 flags, fragmentation off |
| 64, # IPv4 TTL |
| 17, # Protocol UDP |
| csumip(14, 33), # IPv4 checksum |
| |
| /* UDP Header */ |
| 10, 0, 1, 1, # IP Src - adapt as needed |
| 10, 0, 1, 2, # IP Dest - adapt as needed |
| const16(6666), # UDP Src Port |
| const16(6666), # UDP Dest Port |
| const16(1008), # UDP length (UDP header 8 bytes + payload length) |
| csumudp(14, 34), # UDP checksum |
| |
| /* Payload */ |
| fill('W', 1000), |
| } |
| EOF |
| |
| sudo trafgen -i trafgen.cfg -b3000MB -o veth1 --cpp |
| |
| The Linux kernel CVE team has assigned CVE-2024-26853 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 5.13 with commit 4ff3203610928cac82d5627ce803559e78d61b91 and fixed in 6.1.82 with commit 63a3c1f3c9ecc654d851e7906d05334cd0c236e2 |
| Issue introduced in 5.13 with commit 4ff3203610928cac82d5627ce803559e78d61b91 and fixed in 6.6.22 with commit 8df393af9e7e8dfd62e9c41dbaa4d2ff53bf794a |
| Issue introduced in 5.13 with commit 4ff3203610928cac82d5627ce803559e78d61b91 and fixed in 6.7.10 with commit 1b3b8231386a572bac8cd5b6fd7e944b84f9bb1f |
| Issue introduced in 5.13 with commit 4ff3203610928cac82d5627ce803559e78d61b91 and fixed in 6.8 with commit ef27f655b438bed4c83680e4f01e1cde2739854b |
| |
| 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-26853 |
| 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: |
| drivers/net/ethernet/intel/igc/igc_main.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/63a3c1f3c9ecc654d851e7906d05334cd0c236e2 |
| https://git.kernel.org/stable/c/8df393af9e7e8dfd62e9c41dbaa4d2ff53bf794a |
| https://git.kernel.org/stable/c/1b3b8231386a572bac8cd5b6fd7e944b84f9bb1f |
| https://git.kernel.org/stable/c/ef27f655b438bed4c83680e4f01e1cde2739854b |