diff mbox series

[net] net: prevent skb corruption on frag list segmentation

Message ID ecbccca7b88acfd07164623c40f93cf0842645d3.1688716558.git.pabeni@redhat.com (mailing list archive)
State Accepted
Commit c329b261afe71197d9da83c1f18eb45a7e97e089
Delegated to: Netdev Maintainers
Headers show
Series [net] net: prevent skb corruption on frag list segmentation | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net, async
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1343 this patch: 1343
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 1364 this patch: 1364
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1366 this patch: 1366
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 11 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Paolo Abeni July 7, 2023, 8:11 a.m. UTC
Ian reported several skb corruptions triggered by rx-gro-list,
collecting different oops alike:

[   62.624003] BUG: kernel NULL pointer dereference, address: 00000000000000c0
[   62.631083] #PF: supervisor read access in kernel mode
[   62.636312] #PF: error_code(0x0000) - not-present page
[   62.641541] PGD 0 P4D 0
[   62.644174] Oops: 0000 [#1] PREEMPT SMP NOPTI
[   62.648629] CPU: 1 PID: 913 Comm: napi/eno2-79 Not tainted 6.4.0 #364
[   62.655162] Hardware name: Supermicro Super Server/A2SDi-12C-HLN4F, BIOS 1.7a 10/13/2022
[   62.663344] RIP: 0010:__udp_gso_segment (./include/linux/skbuff.h:2858
./include/linux/udp.h:23 net/ipv4/udp_offload.c:228 net/ipv4/udp_offload.c:261
net/ipv4/udp_offload.c:277)
[   62.687193] RSP: 0018:ffffbd3a83b4f868 EFLAGS: 00010246
[   62.692515] RAX: 00000000000000ce RBX: 0000000000000000 RCX: 0000000000000000
[   62.699743] RDX: ffffa124def8a000 RSI: 0000000000000079 RDI: ffffa125952a14d4
[   62.706970] RBP: ffffa124def8a000 R08: 0000000000000022 R09: 00002000001558c9
[   62.714199] R10: 0000000000000000 R11: 00000000be554639 R12: 00000000000000e2
[   62.721426] R13: ffffa125952a1400 R14: ffffa125952a1400 R15: 00002000001558c9
[   62.728654] FS:  0000000000000000(0000) GS:ffffa127efa40000(0000)
knlGS:0000000000000000
[   62.736852] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   62.742702] CR2: 00000000000000c0 CR3: 00000001034b0000 CR4: 00000000003526e0
[   62.749948] Call Trace:
[   62.752498]  <TASK>
[   62.779267] inet_gso_segment (net/ipv4/af_inet.c:1398)
[   62.787605] skb_mac_gso_segment (net/core/gro.c:141)
[   62.791906] __skb_gso_segment (net/core/dev.c:3403 (discriminator 2))
[   62.800492] validate_xmit_skb (./include/linux/netdevice.h:4862
net/core/dev.c:3659)
[   62.804695] validate_xmit_skb_list (net/core/dev.c:3710)
[   62.809158] sch_direct_xmit (net/sched/sch_generic.c:330)
[   62.813198] __dev_queue_xmit (net/core/dev.c:3805 net/core/dev.c:4210)
net/netfilter/core.c:626)
[   62.821093] br_dev_queue_push_xmit (net/bridge/br_forward.c:55)
[   62.825652] maybe_deliver (net/bridge/br_forward.c:193)
[   62.829420] br_flood (net/bridge/br_forward.c:233)
[   62.832758] br_handle_frame_finish (net/bridge/br_input.c:215)
[   62.837403] br_handle_frame (net/bridge/br_input.c:298
net/bridge/br_input.c:416)
[   62.851417] __netif_receive_skb_core.constprop.0 (net/core/dev.c:5387)
[   62.866114] __netif_receive_skb_list_core (net/core/dev.c:5570)
[   62.871367] netif_receive_skb_list_internal (net/core/dev.c:5638
net/core/dev.c:5727)
[   62.876795] napi_complete_done (./include/linux/list.h:37
./include/net/gro.h:434 ./include/net/gro.h:429 net/core/dev.c:6067)
[   62.881004] ixgbe_poll (drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:3191)
[   62.893534] __napi_poll (net/core/dev.c:6498)
[   62.897133] napi_threaded_poll (./include/linux/netpoll.h:89
net/core/dev.c:6640)
[   62.905276] kthread (kernel/kthread.c:379)
[   62.913435] ret_from_fork (arch/x86/entry/entry_64.S:314)
[   62.917119]  </TASK>

In the critical scenario, rx-gro-list GRO-ed packets are fed, via a
bridge, both to the local input path and to an egress device (tun).

The segmentation of such packets unsafely writes to the cloned skbs
with shared heads.

This change addresses the issue by uncloning as needed the
to-be-segmented skbs.

Reported-by: Ian Kumlien <ian.kumlien@gmail.com>
Tested-by: Ian Kumlien <ian.kumlien@gmail.com>
Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/core/skbuff.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Eric Dumazet July 7, 2023, 2:14 p.m. UTC | #1
On Fri, Jul 7, 2023 at 10:11 AM Paolo Abeni <pabeni@redhat.com> wrote:
>
> Ian reported several skb corruptions triggered by rx-gro-list,
> collecting different oops alike:
>
> Reported-by: Ian Kumlien <ian.kumlien@gmail.com>
> Tested-by: Ian Kumlien <ian.kumlien@gmail.com>
> Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>

Reviewed-by: Eric Dumazet <edumazet@google.com>
patchwork-bot+netdevbpf@kernel.org July 8, 2023, 9:13 a.m. UTC | #2
Hello:

This patch was applied to netdev/net.git (main)
by David S. Miller <davem@davemloft.net>:

On Fri,  7 Jul 2023 10:11:10 +0200 you wrote:
> Ian reported several skb corruptions triggered by rx-gro-list,
> collecting different oops alike:
> 
> [   62.624003] BUG: kernel NULL pointer dereference, address: 00000000000000c0
> [   62.631083] #PF: supervisor read access in kernel mode
> [   62.636312] #PF: error_code(0x0000) - not-present page
> [   62.641541] PGD 0 P4D 0
> [   62.644174] Oops: 0000 [#1] PREEMPT SMP NOPTI
> [   62.648629] CPU: 1 PID: 913 Comm: napi/eno2-79 Not tainted 6.4.0 #364
> [   62.655162] Hardware name: Supermicro Super Server/A2SDi-12C-HLN4F, BIOS 1.7a 10/13/2022
> [   62.663344] RIP: 0010:__udp_gso_segment (./include/linux/skbuff.h:2858
> ./include/linux/udp.h:23 net/ipv4/udp_offload.c:228 net/ipv4/udp_offload.c:261
> net/ipv4/udp_offload.c:277)
> [   62.687193] RSP: 0018:ffffbd3a83b4f868 EFLAGS: 00010246
> [   62.692515] RAX: 00000000000000ce RBX: 0000000000000000 RCX: 0000000000000000
> [   62.699743] RDX: ffffa124def8a000 RSI: 0000000000000079 RDI: ffffa125952a14d4
> [   62.706970] RBP: ffffa124def8a000 R08: 0000000000000022 R09: 00002000001558c9
> [   62.714199] R10: 0000000000000000 R11: 00000000be554639 R12: 00000000000000e2
> [   62.721426] R13: ffffa125952a1400 R14: ffffa125952a1400 R15: 00002000001558c9
> [   62.728654] FS:  0000000000000000(0000) GS:ffffa127efa40000(0000)
> knlGS:0000000000000000
> [   62.736852] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   62.742702] CR2: 00000000000000c0 CR3: 00000001034b0000 CR4: 00000000003526e0
> [   62.749948] Call Trace:
> [   62.752498]  <TASK>
> [   62.779267] inet_gso_segment (net/ipv4/af_inet.c:1398)
> [   62.787605] skb_mac_gso_segment (net/core/gro.c:141)
> [   62.791906] __skb_gso_segment (net/core/dev.c:3403 (discriminator 2))
> [   62.800492] validate_xmit_skb (./include/linux/netdevice.h:4862
> net/core/dev.c:3659)
> [   62.804695] validate_xmit_skb_list (net/core/dev.c:3710)
> [   62.809158] sch_direct_xmit (net/sched/sch_generic.c:330)
> [   62.813198] __dev_queue_xmit (net/core/dev.c:3805 net/core/dev.c:4210)
> net/netfilter/core.c:626)
> [   62.821093] br_dev_queue_push_xmit (net/bridge/br_forward.c:55)
> [   62.825652] maybe_deliver (net/bridge/br_forward.c:193)
> [   62.829420] br_flood (net/bridge/br_forward.c:233)
> [   62.832758] br_handle_frame_finish (net/bridge/br_input.c:215)
> [   62.837403] br_handle_frame (net/bridge/br_input.c:298
> net/bridge/br_input.c:416)
> [   62.851417] __netif_receive_skb_core.constprop.0 (net/core/dev.c:5387)
> [   62.866114] __netif_receive_skb_list_core (net/core/dev.c:5570)
> [   62.871367] netif_receive_skb_list_internal (net/core/dev.c:5638
> net/core/dev.c:5727)
> [   62.876795] napi_complete_done (./include/linux/list.h:37
> ./include/net/gro.h:434 ./include/net/gro.h:429 net/core/dev.c:6067)
> [   62.881004] ixgbe_poll (drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:3191)
> [   62.893534] __napi_poll (net/core/dev.c:6498)
> [   62.897133] napi_threaded_poll (./include/linux/netpoll.h:89
> net/core/dev.c:6640)
> [   62.905276] kthread (kernel/kthread.c:379)
> [   62.913435] ret_from_fork (arch/x86/entry/entry_64.S:314)
> [   62.917119]  </TASK>
> 
> [...]

Here is the summary with links:
  - [net] net: prevent skb corruption on frag list segmentation
    https://git.kernel.org/netdev/net/c/c329b261afe7

You are awesome, thank you!
diff mbox series

Patch

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6c5915efbc17..a298992060e6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4261,6 +4261,11 @@  struct sk_buff *skb_segment_list(struct sk_buff *skb,
 
 	skb_push(skb, -skb_network_offset(skb) + offset);
 
+	/* Ensure the head is writeable before touching the shared info */
+	err = skb_unclone(skb, GFP_ATOMIC);
+	if (err)
+		goto err_linearize;
+
 	skb_shinfo(skb)->frag_list = NULL;
 
 	while (list_skb) {