CVE-2024-36933: nsh: Restore skb->{protocol,data,mac_header} for outer header in nsh_gso_segment().
In the Linux kernel, the following vulnerability has been resolved:
nsh: Restore skb->{protocol,data,macheader} for outer header in nshgsosegment().
syzbot triggered various splats (see [0] and links) by a crafted GSO packet of VIRTIONETHDRGSOUDP layering the following protocols:
ETHP8021AD + ETHPNSH + ETHPIPV6 + IPPROTOUDP
NSH can encapsulate IPv4, IPv6, Ethernet, NSH, and MPLS. As the inner protocol can be Ethernet, NSH GSO handler, nshgsosegment(), calls skbmacgsosegment() to invoke inner protocol GSO handlers.
nshgsosegment() does the following for the original skb before calling skbmacgsosegment()
1. reset skb->networkheader 2. save the original skb->{macheaeder,maclen} in a local variable 3. pull the NSH header 4. resets skb->macheader 5. set up skb->maclen and skb->protocol for the inner protocol.
and does the following for the segmented skb
6. set ntohs(ETHPNSH) to skb->protocol 7. push the NSH header 8. restore skb->macheader 9. set skb->macheader + maclen to skb->networkheader 10. restore skb->maclen
There are two problems in 6-7 and 8-9.
(a) After 6 & 7, skb->data points to the NSH header, so the outer header (ETHP8021AD in this case) is stripped when skb is sent out of netdev.
Also, if NSH is encapsulated by NSH + Ethernet (so NSH-Ethernet-NSH), skbpull() in the first nshgsosegment() will make skb->data point to the middle of the outer NSH or Ethernet header because the Ethernet header is not pulled by the second nshgsosegment().
(b) While restoring skb->{macheader,networkheader} in 8 & 9, nshgsosegment() does not assume that the data in the linear buffer is shifted.
However, udp6ufofragment() could shift the data and change skb->macheader accordingly as demonstrated by syzbot.
If this happens, even the restored skb->macheader points to the middle of the outer header.
It seems nshgsosegment() has never worked with outer headers so far.
At the end of nshgsosegment(), the outer header must be restored for the segmented skb, instead of the NSH header.
To do that, let's calculate the outer header position relatively from the inner header and set skb->{data,macheader,protocol} properly.
[0]: BUG: KMSAN: uninit-value in ipvlanprocessoutbound drivers/net/ipvlan/ipvlancore.c:524 [inline] BUG: KMSAN: uninit-value in ipvlanxmitmodel3 drivers/net/ipvlan/ipvlancore.c:602 [inline] BUG: KMSAN: uninit-value in ipvlanqueuexmit+0xf44/0x16b0 drivers/net/ipvlan/ipvlancore.c:668 ipvlanprocessoutbound drivers/net/ipvlan/ipvlancore.c:524 [inline] ipvlanxmitmodel3 drivers/net/ipvlan/ipvlancore.c:602 [inline] ipvlanqueuexmit+0xf44/0x16b0 drivers/net/ipvlan/ipvlancore.c:668 ipvlanstartxmit+0x5c/0x1a0 drivers/net/ipvlan/ipvlanmain.c:222 netdevstartxmit include/linux/netdevice.h:4989 [inline] netdevstartxmit include/linux/netdevice.h:5003 [inline] xmitone net/core/dev.c:3547 [inline] devhardstartxmit+0x244/0xa10 net/core/dev.c:3563 devqueuexmit+0x33ed/0x51c0 net/core/dev.c:4351 devqueuexmit include/linux/netdevice.h:3171 [inline] packetxmit+0x9c/0x6b0 net/packet/afpacket.c:276 packetsnd net/packet/afpacket.c:3081 [inline] packetsendmsg+0x8aef/0x9f10 net/packet/afpacket.c:3113 socksendmsgnosec net/socket.c:730 [inline] socksendmsg net/socket.c:745 [inline] syssendto+0x735/0xa10 net/socket.c:2191 dosyssendto net/socket.c:2203 [inline] sesyssendto net/socket.c:2199 [inline] x64syssendto+0x125/0x1c0 net/socket.c:2199 dosyscallx64 arch/x86/entry/common.c:52 [inline] dosyscall64+0xcf/0x1e0 arch/x86/entry/common.c:83 entrySYSCALL64afterhwframe+0x63/0x6b
Uninit was created at: slabpostallochook mm/slub.c:3819 [inline] slaballocnode mm/slub.c:3860 [inline] dokmallocnode mm/slub.c:3980 [inline] kmallocnodetrackcaller+0x705/0x1000 mm/slub.c:4001 kmallocreserve+0x249/0x4a0 net/core/skbuff.c:582 ---truncated---
Other sources
In the Linux kernel, the following vulnerability has been resolved:
nsh: Restore skb->{protocol,data,macheader} for outer header in nshgsosegment().
The Linux kernel CVE team has assigned CVE-2024-36933 to this issue.
Upstream advisory: https://lore.kernel.org/linux-cve-announce/2024053042-CVE-2024-36933-444e@gregkh/T
— Red Hat
Linux Kernel is vulnerable to a denial of service, caused by the use of uninitialized variable. A local authenticated attacker could exploit this vulnerability to cause a denial of service.
— IBM
Affected Software
Remediation
Event History
Frequently Asked Questions
What are the potential risks associated with CVE-2024-36933?
CVE-2024-36933 may lead to data corruption or unexpected behavior in systems using vulnerable Linux kernel versions.
Which versions of the Linux kernel are affected by CVE-2024-36933?
CVE-2024-36933 impacts kernels up to version 4.19.314, 5.4.276, 5.10.217, 5.15.159, and several others including 6.1.91 and 6.6.31.
How can I mitigate the impact of CVE-2024-36933?
The best mitigation for CVE-2024-36933 is upgrading to the latest fixed versions of the Linux kernel as specified in the vulnerability report.
What is the severity level of CVE-2024-36933?
CVE-2024-36933 is classified as a medium to high severity vulnerability depending on the specific system configuration and its usage.
Is there a known exploit for CVE-2024-36933?
As of now, there are no publicly disclosed exploits specifically targeting CVE-2024-36933.