Look up another CVE · open CVE-2024-46765 in the interactive tracker
CVE-2024-46765
ice: protect XDP configuration with a mutex
Published 2024-09-18 (2 years ago) by the Linux kernel CNA. Subsystem drivers/net. Debian urgency: not yet assigned.
What to do, per Debian release
Debian's own status for CVE-2024-46765 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source
| Release | Status | Version | What this means |
|---|---|---|---|
| Debian 12bookworm | vulnerable | 6.1.190-1 | No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication. |
| Debian 13trixie | fixed | 6.10.11-1 | Update the kernel and reboot. Fixed in 6.10.11-1. A running kernel keeps the old code until the machine restarts. |
| Debian 14forky | fixed | 6.10.11-1 | Update the kernel and reboot. Fixed in 6.10.11-1. A running kernel keeps the old code until the machine restarts. |
| Debian unstablesid | fixed | 6.10.11-1 | Update the kernel and reboot. Fixed in 6.10.11-1. A running kernel keeps the old code until the machine restarts. |
The vulnerability
What the bug is
The main threat to data consistency in ice_xdp() is a possible asynchronous PF reset. It can be triggered by a user or by TX timeout handler. XDP setup and PF reset code access the same resources in the following sections: * ice_vsi_close() in ice_prepare_for_reset() - already rtnl-locked * ice_vsi_rebuild() for the PF VSI - not protected * ice_vsi_open() - already rtnl-locked With an unfortunate timing, such accesses can result in a crash such as the one below: [ +1.999878] ice 0000:b1:00.0: Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring 14 [ +2.002992] ice 0000:b1:00.0: Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring 18 [Mar15 18:17] ice 0000:b1:00.0 ens801f0np0: NETDEV WATCHDOG: CPU: 38: transmit queue 14 timed out 80692736 ms [ +0.000093] ice 0000:b1:00.0 ens801f0np0: tx_timeout: VSI_num: 6, Q 14, NTC: 0x0, HW_HEAD: 0x0, NTU: 0x0, INT: 0x4000001 [ +0.000012] ice 0000:b1:00.0 ens801f0np0: tx_timeout recovery level 1, txqueue 14 [ +0.394718] ice 0000:b1:00.0: PTP reset successful [ +0.006184] BUG: kernel NULL pointer dereference, address: 0000000000000098 [ +0.000045] #PF: supervisor read access in kernel mode [ +0.000023] #PF: error_code(0x0000) - not-present page [ +0.000023] PGD 0 P4D 0 [ +0.000018] Oops: 0000 [#1] PREEMPT SMP NOPTI [ +0.000023] CPU: 38 PID: 7540 Comm: kworker/38:1 Not tainted 6.8.0-rc7 #1 [ +0.000031] Hardware name: Intel Corporation S2600WFT/S2600WFT, BIOS SE5C620.86B.02.01.0014.082620210524 08/26/2021 [ +0.000036] Workqueue: ice ice_service_task [ice] [ +0.000183] RIP: 0010:ice_clean_tx_ring+0xa/0xd0 [ice] [...] [ +0.000013] Call Trace: [ +0.000016] <TASK> [ +0.000014] ? __die+0x1f/0x70 [ +0.000029] ? page_fault_oops+0x171/0x4f0 [ +0.000029] ? schedule+0x3b/0xd0 [ +0.000027] ? exc_page_fault+0x7b/0x180 [ +0.000022] ? asm_exc_page_fault+0x22/0x30 [ +0.000031] ? ice_clean_tx_ring+0xa/0xd0 [ice] [ +0.000194] ice_free_tx_ring+0xe/0x60 [ice] [ +0.000186] ice_destroy_xdp_rings+0x157/0x310 [ice] [ +0.000151] ice_vsi_decfg+0x53/0xe0 [ice] [ +0.000180] ice_vsi_rebuild+0x239/0x540 [ice] [ +0.000186] ice_vsi_rebuild_by_type+0x76/0x180 [ice] [ +0.000145] ice_rebuild+0x18c/0x840 [ice] [ +0.000145] ? delay_tsc+0x4a/0xc0 [ +0.000022] ? delay_tsc+0x92/0xc0 [ +0.000020] ice_do_reset+0x140/0x180 [ice] [ +0.000886] ice_service_task+0x404/0x1030 [ice] [ +0.000824] process_one_work+0x171/0x340 [ +0.000685] worker_thread+0x277/0x3a0 [ +0.000675] ? preempt_count_add+0x6a/0xa0 [ +0.000677] ? _raw_spin_lock_irqsave+0x23/0x50 [ +0.000679] ? __pfx_worker_thread+0x10/0x10 [ +0.000653] kthread+0xf0/0x120 [ +0.000635] ? __pfx_kthread+0x10/0x10 [ +0.000616] ret_from_fork+0x2d/0x50 [ +0.000612] ? __pfx_kthread+0x10/0x10 [ +0.000604] ret_from_fork_asm+0x1b/0x30 [ +0.000604] </TASK> The previous way of handling this through returning -EBUSY is not viable, particularly when destroying AF_XDP socket, because the kernel proceeds with removal anyway. There is plenty of code between those calls and there is no need to create a large critical section that covers all of them, same as there is no need to protect ice_vsi_rebuild() with rtnl_lock(). Add xdp_state_lock mutex to protect ice_vsi_rebuild() and ice_xdp(). Leaving unprotected sections in between would result in two states that have to be considered: 1. when the VSI is closed, but not yet rebuild 2. when VSI is already rebuild, but not yet open The latter case is actually already handled through !netif_running() case, we just need to adjust flag checking a little. The former one is not as trivial, because between ice_vsi_close() and ice_vsi_rebuild(), a lot of hardware interaction happens, this can make adding/deleting rings exit with an error. Luckily, VSI rebuild is pending and can apply new configuration for us in a managed fashion. Therefore, add an additional VSI state flag ICE_VSI_REBUILD_PENDING to indicate that ice_x ---truncated---
Where it lives
The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_xsk.c
- What this is
- INTEL ETHERNET DRIVERSMAINTAINERS section matched on drivers/net/ethernet/intel/*/ · intel-wired-lan@lists.osuosl.org · Maintained
- Kernel module
- ice
Check it on the machine
grep -wE 'CONFIG_ETHERNET|CONFIG_ICE|CONFIG_NET_VENDOR_INTEL' /boot/config-$(uname -r)Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.
lsmod | grep -w icePrints a line if that module is loaded right now, and nothing if it is not. One that is not loaded can still be loaded later by anything that needs it.
Show whether Debian builds this, per release
Debian builds this, but not on every flavour. At least one release below builds the code on some of its kernel flavours and not on others, so the answer depends on the architecture and flavour installed.
- bookwormMnot built on amd64/cloud-amd64, arm64/cloud-arm64
- trixieMnot built on amd64/cloud-amd64, arm64/cloud-arm64, armel/rpi
- forky, sidMnot built on amd64/cloud-amd64, arm64/cloud-arm64
- M
- a module where it is built at all; some flavours do not build it
- Build switches
- CONFIG_ETHERNET, CONFIG_ICE, CONFIG_NET_VENDOR_INTEL
- Reads as
- all on means the file is compiled; any one off means it is not.
From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages
Signals
- Published
- 2024-09-18 (2 years ago)source
- CVSS
- 7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it - Attack vector
- local (AV:L)source
- EPSS
- 0.24%, higher than 14.5% of all CVEssource
- CISA KEV
- not listedthe KEV catalogue
- Debian urgency
- not yet assignedsource
- Subsystem
- drivers/net
Upstream fixes
The versions the CNA records as introducing and fixing this, and the commit for each. source
| Introduced | Fixed in | Commit |
|---|---|---|
| 5.5 | 6.6.51 | 2f057db2fb29 |
| 5.5 | 6.10.10 | 391f7dae3d83 |
| 5.5 | 6.11 | 2504b8405768 |
Why the CNA scored it this way
Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source
- AV:LAttack vector, local
- Both halves of the race are driven through local syscalls — AF_XDP `bind()`/`close()` and rtnetlink `IFLA_XDP` attach/detach for `ice_xdp()`, plus locally-triggered PF resets. No remote peer input reaches this code.
- AC:LAttack complexity, low
- The attacker controls both sides: a tight AF_XDP bind/close or XDP attach/detach loop against the multi-millisecond `ice_vsi_decfg()`→`ice_vsi_cfg_def()` window in the unlocked `ice_vsi_rebuild()`, with PF resets induced repeatedly via TX-timeout recovery or reset-scheduling config paths, so the window is hit reliably by repetition.
- PR:LPrivileges required, low
- The `XDP_SETUP_XSK_POOL` entry needs only `ns_capable(net->user_ns, CAP_NET_RAW)` in `xsk_create()`, obtainable in a user namespace, and every AF_XDP bind/close calls `ndo_bpf` with no BPF program load; in the AF_XDP/XDP deployments this driver targets the E810 netdev is delegated into a container netns where that principal is unprivileged on the host.
- UI:NUser interaction, none
- The attacker performs all steps itself — opening AF_XDP sockets, toggling XDP, and inducing the reset. No victim action is involved.
- S:UScope, unchanged
- The freed ring/vector objects, the `pf->avail_txqs` bitmap, and the devres list all belong to the kernel itself, so impact stays within the kernel's security authority.
- C:HConfidentiality impact, high
- `ice_qp_dis()` and `ice_destroy_xdp_rings()` read `tx_rings[]`, `rx_rings[]`, `q_vector`, `xdp_rings[]` and `txq_map[]` after `ice_vsi_decfg()` has freed them, so a reclaimed slab's contents are read back and acted on, giving the attacker a use-after-free read of arbitrary kernel data.
- I:HIntegrity impact, high
- The same window yields UAF writes — `WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, …)`, `vsi->xdp_rings[i] = NULL`, `txq_map[…] = ICE_INVAL_Q_INDEX` into freed slabs — plus a double `devm_kfree(vsi->xdp_rings)` corrupting the devres list and a `clear_bit()` indexed by stale, groomable `txq_map` data.
- A:HAvailability impact, high
- The commit documents a hard kernel Oops (`BUG: kernel NULL pointer dereference` in `ice_clean_tx_ring` from `ice_vsi_rebuild`), and the double-free plus use-after-free of ring structures reliably panic the machine.