In the Linux kernel, the following vulnerability has been resolved:
net: ip_tunnel: prevent perpetual headroom growth
syzkaller triggered following kasan splat: BUG: KASAN: use-after-free in skbflowdissect+0x19d1/0x7a50 net/core/flowdissector.c:1170 Read of size 1 at addr ffff88812fb4000e by task syz-executor183/5191 [..] kasanreport+0xda/0x110 mm/kasan/report.c:588 _skbflowdissect+0x19d1/0x7a50 net/core/flowdissector.c:1170 skbflowdissectflowkeys include/linux/skbuff.h:1514 [inline] skbgethash net/core/flowdissector.c:1791 [inline] _skbgethash+0xc7/0x540 net/core/flowdissector.c:1856 skbgethash include/linux/skbuff.h:1556 [inline] iptunnelxmit+0x1855/0x33c0 net/ipv4/iptunnel.c:748 ipiptunnelxmit+0x3cc/0x4e0 net/ipv4/ipip.c:308 _netdevstartxmit include/linux/netdevice.h:4940 [inline] netdevstartxmit include/linux/netdevice.h:4954 [inline] xmitone net/core/dev.c:3548 [inline] devhardstartxmit+0x13d/0x6d0 net/core/dev.c:3564 _devqueuexmit+0x7c1/0x3d60 net/core/dev.c:4349 devqueuexmit include/linux/netdevice.h:3134 [inline] neighconnectedoutput+0x42c/0x5d0 net/core/neighbour.c:1592 ... ipfinishoutput2+0x833/0x2550 net/ipv4/ipoutput.c:235 ipfinishoutput+0x31/0x310 net/ipv4/ipoutput.c:323 .. iptunnelxmit+0x5b4/0x9b0 net/ipv4/iptunnelcore.c:82 iptunnelxmit+0x1dbc/0x33c0 net/ipv4/iptunnel.c:831 ipgrexmit+0x4a1/0x980 net/ipv4/ipgre.c:665 _netdevstartxmit include/linux/netdevice.h:4940 [inline] netdevstartxmit include/linux/netdevice.h:4954 [inline] xmitone net/core/dev.c:3548 [inline] devhardstartxmit+0x13d/0x6d0 net/core/dev.c:3564 ...
The splat occurs because skb->data points past skb->head allocated area. This is because neigh layer does: _skbpull(skb, skbnetworkoffset(skb));
... but skbnetworkoffset() returns a negative offset and _skbpull() arg is unsigned. IOW, we skb->data gets "adjusted" by a huge value.
The negative value is returned because skb->head and skb->data distance is more than 64k and skb->network_header (u16) has wrapped around.
The bug is in the iptunnel infrastructure, which can cause dev->neededheadroom to increment ad infinitum.
The syzkaller reproducer consists of packets getting routed via a gre tunnel, and route of gre encapsulated packets pointing at another (ipip) tunnel. The ipip encapsulation finds gre0 as next output device.
This results in the following pattern:
1). First packet is to be sent out via gre0. Route lookup found an output device, ipip0.
2). iptunnelxmit for gre0 bumps gre0->neededheadroom based on the future output device, rt.dev->neededheadroom (ipip0).
3). ip output / start_xmit moves skb on to ipip0. which runs the same code path again (xmit recursion).
4). Routing step for the post-gre0-encap packet finds gre0 as output device to use for ipip0 encapsulated packet.
tunl0->needed_headroom is then incremented based on the (already bumped) gre0 device headroom.
This repeats for every future packet:
gre0->neededheadroom gets inflated because previous packets' ipip0 step incremented rt->dev (gre0) headroom, and ipip0 incremented because gre0 neededheadroom was increased.
For each subsequent packet, gre/ipip0->needed_headroom grows until post-expand-head reallocations result in a skb->head/data distance of more than 64k.
Once that happens, skb->networkheader (u16) wraps around when pskbexpandhead tries to make sure that skbnetwork_offset() is unchanged after the headroom expansion/reallocation.
After this skbnetworkoffset(skb) returns a different (and negative) result post headroom expansion.
The next trip to neigh layer (or anything else that would _skbpull the network header) makes skb->data point to a memory location outside skb->head area.
v2: Cap the needed_headroom update to an arbitarily chosen upperlimit to prevent perpetual increase instead of dropping the headroom increment completely.
[ { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "317070658082330445228397434126225967461", "59603959152007123360909021218369666153", "105107173658111002661643537530692112484", "268172504227671498849739837858763497002", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-047ea4e5", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5ae1e9922bbdbaeb9cfbe91085ab75927488ac0f", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "331367822149557714975608662864274274117", "length": 2478.0 }, "id": "CVE-2024-26804-06a54bc7", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@f81e94d2dcd2397137edcb8b85f4c5bed5d22383", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "317070658082330445228397434126225967461", "59603959152007123360909021218369666153", "105107173658111002661643537530692112484", "268172504227671498849739837858763497002", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-08fe48bd", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@a0a1db40b23e8ff86dea2786c5ea1470bb23ecb9", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "41285791288256524916924811937802862789", "length": 4060.0 }, "id": "CVE-2024-26804-14226c22", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@2e95350fe9db9d53c701075060ac8ac883b68aee", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "317070658082330445228397434126225967461", "59603959152007123360909021218369666153", "105107173658111002661643537530692112484", "268172504227671498849739837858763497002", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-165fb676", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@049d7989c67e8dd50f07a2096dbafdb41331fb9b", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "250012914181599785617592577249166080709", "105616106125420898536482543306885110535", "104752178020866876983336327283095815661", "188957734895923409372853704606211848916", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-1d829f72", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@f81e94d2dcd2397137edcb8b85f4c5bed5d22383", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "305376067012947949186701454187065227429", "length": 4054.0 }, "id": "CVE-2024-26804-463fdc74", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@ab63de24ebea36fe73ac7121738595d704b66d96", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "41285791288256524916924811937802862789", "length": 4060.0 }, "id": "CVE-2024-26804-521fdfa6", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@f81e94d2dcd2397137edcb8b85f4c5bed5d22383", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "250012914181599785617592577249166080709", "105616106125420898536482543306885110535", "104752178020866876983336327283095815661", "188957734895923409372853704606211848916", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-5e4e43c2", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@ab63de24ebea36fe73ac7121738595d704b66d96", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "244966785084554984854367069933484128113", "length": 4070.0 }, "id": "CVE-2024-26804-63e4f4cb", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@049d7989c67e8dd50f07a2096dbafdb41331fb9b", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "331367822149557714975608662864274274117", "length": 2478.0 }, "id": "CVE-2024-26804-66c95423", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@afec0c5cd2ed71ca95a8b36a5e6d03333bf34282", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "250012914181599785617592577249166080709", "105616106125420898536482543306885110535", "104752178020866876983336327283095815661", "188957734895923409372853704606211848916", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-8e488f89", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@afec0c5cd2ed71ca95a8b36a5e6d03333bf34282", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "16730121147616881839311522094785645011", "length": 2593.0 }, "id": "CVE-2024-26804-90567ac4", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@a0a1db40b23e8ff86dea2786c5ea1470bb23ecb9", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "244966785084554984854367069933484128113", "length": 4070.0 }, "id": "CVE-2024-26804-9dc8875e", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5ae1e9922bbdbaeb9cfbe91085ab75927488ac0f", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "16730121147616881839311522094785645011", "length": 2593.0 }, "id": "CVE-2024-26804-a4382259", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@049d7989c67e8dd50f07a2096dbafdb41331fb9b", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "41285791288256524916924811937802862789", "length": 4060.0 }, "id": "CVE-2024-26804-add90ae8", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@afec0c5cd2ed71ca95a8b36a5e6d03333bf34282", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "30217834856816955475642405691943974643", "length": 2519.0 }, "id": "CVE-2024-26804-b3eb8171", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@ab63de24ebea36fe73ac7121738595d704b66d96", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "331367822149557714975608662864274274117", "length": 2478.0 }, "id": "CVE-2024-26804-c7a6940c", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@2e95350fe9db9d53c701075060ac8ac883b68aee", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "line_hashes": [ "220839571136594025072962289351596911055", "13518951914971555228624126993156303094", "52757577149571324847901336207145682357", "31861101163133196454529451861938917881", "331090157315786363969448646089415489353", "247009853258172743036478812529117520171", "18355173978989901471153751638460135162", "229798714650253884024685803170349423881", "24147994919884648589342983233098590692", "225469384063526485180726191632952081249", "248018093101098016168935073483585960458", "17526286446801064082417159979044759534", "336267430090813710735652507553829032067", "312781251085459068579469203321295389719", "257555264412032436255291887390196287067", "44562893062949417808297081179752379635", "250012914181599785617592577249166080709", "105616106125420898536482543306885110535", "104752178020866876983336327283095815661", "188957734895923409372853704606211848916", "70836973327991865793181992315340257533", "94773072489331470510351946687348607749", "304887427392621088856524694886592454717" ], "threshold": 0.9 }, "id": "CVE-2024-26804-e0339aae", "target": { "file": "net/ipv4/ip_tunnel.c" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@2e95350fe9db9d53c701075060ac8ac883b68aee", "signature_version": "v1", "signature_type": "Line", "deprecated": false }, { "digest": { "function_hash": "244966785084554984854367069933484128113", "length": 4070.0 }, "id": "CVE-2024-26804-ebd325b9", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@a0a1db40b23e8ff86dea2786c5ea1470bb23ecb9", "signature_version": "v1", "signature_type": "Function", "deprecated": false }, { "digest": { "function_hash": "16730121147616881839311522094785645011", "length": 2593.0 }, "id": "CVE-2024-26804-f7bcec72", "target": { "file": "net/ipv4/ip_tunnel.c", "function": "ip_md_tunnel_xmit" }, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5ae1e9922bbdbaeb9cfbe91085ab75927488ac0f", "signature_version": "v1", "signature_type": "Function", "deprecated": false } ]