* [PATCH v2 2/2] test_bpf: Introduce an skb_segment test for frag_list whose head_frag=true and gso_size was mangled
@ 2024-06-26 6:55 Fred Li
2024-06-26 6:55 ` [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true Fred Li
2024-06-26 6:55 ` [PATCH v2 0/2] net: Fix BUG_ON for segment frag_list with mangled gso_size and head_frag is true Fred Li
0 siblings, 2 replies; 21+ messages in thread
From: Fred Li @ 2024-06-26 6:55 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, aleksander.lobakin, sashal, linux,
hawk, nbd, mkhalfella, ast, daniel, andrii, martin.lau, song,
yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa
Cc: netdev, linux-kernel, bpf, Fred Li
This is a reproducer test that mimics the input skbs
that lead to the mentioned BUG_ON and validates the
fix submitted in patch 1.
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
lib/test_bpf.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index ecde4216201e..a38d2d09ca01 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -14706,6 +14706,63 @@ static __init struct sk_buff *build_test_skb_linear_no_head_frag(void)
return NULL;
}
+static __init struct sk_buff *build_test_skb_head_frag(void)
+{
+ u32 headroom = 192, doffset = 66, alloc_size = 1536;
+ struct sk_buff *skb[2];
+ struct page *page[17];
+ int i, data_size = 125;
+ int j;
+
+ skb[0] = dev_alloc_skb(headroom + alloc_size);
+ if (!skb[0])
+ return NULL;
+
+ skb_reserve(skb[0], headroom + doffset);
+ skb_put(skb[0], data_size);
+ skb[0]->mac_header = 192;
+
+ skb[0]->protocol = htons(ETH_P_IP);
+ skb[0]->network_header = 206;
+
+ for (i = 0; i < 17; i++) {
+ page[i] = alloc_page(GFP_KERNEL);
+ if (!page[i])
+ goto err_page;
+
+ skb_add_rx_frag(skb[0], i, page[i], 0, data_size, data_size);
+ }
+
+ skb[1] = dev_alloc_skb(headroom + alloc_size);
+ if (!skb[1])
+ goto err_page;
+
+ skb_reserve(skb[1], headroom + doffset);
+ skb_put(skb[1], data_size);
+
+ /* setup shinfo */
+ skb_shinfo(skb[0])->gso_size = 75;
+ skb_shinfo(skb[0])->gso_type = SKB_GSO_TCPV4;
+ skb_shinfo(skb[0])->gso_type |= SKB_GSO_UDP_TUNNEL|SKB_GSO_TCP_FIXEDID|SKB_GSO_DODGY;
+ skb_shinfo(skb[0])->gso_segs = 0;
+ skb_shinfo(skb[0])->frag_list = skb[1];
+ skb_shinfo(skb[0])->hwtstamps.hwtstamp = 1000;
+
+ /* adjust skb[0]'s len */
+ skb[0]->len += skb[1]->len;
+ skb[0]->data_len += skb[1]->len;
+ skb[0]->truesize += skb[1]->truesize;
+
+ return skb[0];
+
+err_page:
+ kfree_skb(skb[0]);
+ for (j = 0; j < i; j++)
+ __free_page(page[j]);
+
+ return NULL;
+}
+
struct skb_segment_test {
const char *descr;
struct sk_buff *(*build_skb)(void);
@@ -14727,6 +14784,13 @@ static struct skb_segment_test skb_segment_tests[] __initconst = {
NETIF_F_LLTX | NETIF_F_GRO |
NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_STAG_TX
+ },
+ {
+ .descr = "gso_with_head_frag",
+ .build_skb = build_test_skb_head_frag,
+ .features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SHIFT |
+ NETIF_F_TSO_ECN | NETIF_F_TSO_MANGLEID | NETIF_F_TSO6 |
+ NETIF_F_GSO_SCTP | NETIF_F_GSO_UDP_L4 | NETIF_F_GSO_FRAGLIST
}
};
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true
2024-06-26 6:55 [PATCH v2 2/2] test_bpf: Introduce an skb_segment test for frag_list whose head_frag=true and gso_size was mangled Fred Li
@ 2024-06-26 6:55 ` Fred Li
2024-07-02 9:23 ` Paolo Abeni
2024-06-26 6:55 ` [PATCH v2 0/2] net: Fix BUG_ON for segment frag_list with mangled gso_size and head_frag is true Fred Li
1 sibling, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-06-26 6:55 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, aleksander.lobakin, sashal, linux,
hawk, nbd, mkhalfella, ast, daniel, andrii, martin.lau, song,
yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa
Cc: netdev, linux-kernel, bpf, Fred Li
When using calico bpf based NAT, hits a kernel BUG_ON at function
skb_segment(), line 4560. Performing NAT translation when accessing
a Service IP across subnets, the calico will encap vxlan and calls the
bpf_skb_adjust_room to decrease the gso_size, and then call bpf_redirect
send packets out.
4438 struct sk_buff *skb_segment(struct sk_buff *head_skb,
4439 netdev_features_t features)
4440 {
4441 struct sk_buff *segs = NULL;
4442 struct sk_buff *tail = NULL;
...
4558 if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
4559 (skb_headlen(list_skb) == len || sg)) {
4560 BUG_ON(skb_headlen(list_skb) > len);
4561
4562 nskb = skb_clone(list_skb, GFP_ATOMIC);
4563 if (unlikely(!nskb))
4564 goto err;
call stack:
...
[exception RIP: skb_segment+3016]
RIP: ffffffffb97df2a8 RSP: ffffa3f2cce08728 RFLAGS: 00010293
RAX: 000000000000007d RBX: 00000000fffff7b3 RCX: 0000000000000011
RDX: 0000000000000000 RSI: ffff895ea32c76c0 RDI: 00000000000008c1
RBP: ffffa3f2cce087f8 R8: 000000000000088f R9: 0000000000000011
R10: 000000000000090c R11: ffff895e47e68000 R12: ffff895eb2022f00
R13: 000000000000004b R14: ffff895ecdaf2000 R15: ffff895eb2023f00
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#9 [ffffa3f2cce08720] skb_segment at ffffffffb97ded63
...
The skb has the following properties:
doffset = 66
list_skb = skb_shinfo(skb)->frag_list
list_skb->head_frag = true
skb->len = 2441 && skb->data_len = 2250
skb_shinfo(skb)->nr_frags = 17
skb_shinfo(skb)->gso_size = 75
skb_shinfo(skb)->frags[0...16].bv_len = 125
list_skb->len = 125
list_skb->data_len = 0
When slicing the frag_list skb, there three cases:
1. Only *non* head_frag
sg will be false, only when skb_headlen(list_skb)==len is satisfied,
it will enter the branch at line 4560, and there will be no crash.
2. Mixed head_frag
sg will be false, Only when skb_headlen(list_skb)==len is satisfied,
it will enter the branch at line 4560, and there will be no crash.
3. Only frag_list with head_frag=true
sg is true, three cases below:
(1) skb_headlen(list_skb)==len is satisfied, it will enter the branch
at line 4560, and there will be no crash.
(2) skb_headlen(list_skb)<len is satisfied, it will enter the branch
at line 4560, and there will be no crash.
(3) skb_headlen(list_skb)>len is satisfied, it will be crash.
Applying this patch, three cases will be:
1. Only *non* head_frag
sg will be false. No difference with before.
2. Mixed head_frag
sg will be false. No difference with before.
3. Only frag_list with head_frag=true
sg is true, there also three cases:
(1) skb_headlen(list_skb)==len is satisfied, no difference with before.
(2) skb_headlen(list_skb)<len is satisfied, will be revert to copying
in this case.
(3) skb_headlen(list_skb)>len is satisfied, will be revert to copying
in this case.
Since commit 13acc94eff122("net: permit skb_segment on head_frag frag_list
skb"), it is allowed to segment the head_frag frag_list skb.
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
net/core/skbuff.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f0a9ef1aeaa2..b1dab1b071fc 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4556,7 +4556,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
hsize = skb_headlen(head_skb) - offset;
if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
- (skb_headlen(list_skb) == len || sg)) {
+ (skb_headlen(list_skb) == len)) {
BUG_ON(skb_headlen(list_skb) > len);
nskb = skb_clone(list_skb, GFP_ATOMIC);
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 0/2] net: Fix BUG_ON for segment frag_list with mangled gso_size and head_frag is true
2024-06-26 6:55 [PATCH v2 2/2] test_bpf: Introduce an skb_segment test for frag_list whose head_frag=true and gso_size was mangled Fred Li
2024-06-26 6:55 ` [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true Fred Li
@ 2024-06-26 6:55 ` Fred Li
1 sibling, 0 replies; 21+ messages in thread
From: Fred Li @ 2024-06-26 6:55 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, aleksander.lobakin, sashal, linux,
hawk, nbd, mkhalfella, ast, daniel, andrii, martin.lau, song,
yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa
Cc: netdev, linux-kernel, bpf, Fred Li
This serices fix the BUG_ON when segment frag_list with mangled gso_size
and head_frag is true. This patch was tested on kernel 6.6.35.
v2 changes:
Updated with remove the sg condition may be more make sense.
Fred Li (2):
net: Fix skb_segment when splitting gso_size mangled skb having
linear-headed frag_list whose head_frag=true
test_bpf: Introduce an skb_segment test for frag_list whose
head_frag=true and gso_size was mangled
lib/test_bpf.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++
net/core/skbuff.c | 2 +-
2 files changed, 65 insertions(+), 1 deletion(-)
--
2.33.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true
2024-06-26 6:55 ` [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true Fred Li
@ 2024-07-02 9:23 ` Paolo Abeni
2024-07-03 12:21 ` Fred Li
0 siblings, 1 reply; 21+ messages in thread
From: Paolo Abeni @ 2024-07-02 9:23 UTC (permalink / raw)
To: Fred Li, davem, edumazet, kuba, aleksander.lobakin, sashal, linux,
hawk, nbd, mkhalfella, ast, daniel, andrii, martin.lau, song,
yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa
Cc: netdev, linux-kernel, bpf
On Wed, 2024-06-26 at 14:55 +0800, Fred Li wrote:
> When using calico bpf based NAT, hits a kernel BUG_ON at function
> skb_segment(), line 4560. Performing NAT translation when accessing
> a Service IP across subnets, the calico will encap vxlan and calls the
> bpf_skb_adjust_room to decrease the gso_size, and then call bpf_redirect
> send packets out.
>
> 4438 struct sk_buff *skb_segment(struct sk_buff *head_skb,
> 4439 netdev_features_t features)
> 4440 {
> 4441 struct sk_buff *segs = NULL;
> 4442 struct sk_buff *tail = NULL;
> ...
> 4558 if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
> 4559 (skb_headlen(list_skb) == len || sg)) {
> 4560 BUG_ON(skb_headlen(list_skb) > len);
> 4561
> 4562 nskb = skb_clone(list_skb, GFP_ATOMIC);
> 4563 if (unlikely(!nskb))
> 4564 goto err;
>
> call stack:
> ...
> [exception RIP: skb_segment+3016]
> RIP: ffffffffb97df2a8 RSP: ffffa3f2cce08728 RFLAGS: 00010293
> RAX: 000000000000007d RBX: 00000000fffff7b3 RCX: 0000000000000011
> RDX: 0000000000000000 RSI: ffff895ea32c76c0 RDI: 00000000000008c1
> RBP: ffffa3f2cce087f8 R8: 000000000000088f R9: 0000000000000011
> R10: 000000000000090c R11: ffff895e47e68000 R12: ffff895eb2022f00
> R13: 000000000000004b R14: ffff895ecdaf2000 R15: ffff895eb2023f00
> ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
> #9 [ffffa3f2cce08720] skb_segment at ffffffffb97ded63
> ...
>
> The skb has the following properties:
> doffset = 66
> list_skb = skb_shinfo(skb)->frag_list
> list_skb->head_frag = true
> skb->len = 2441 && skb->data_len = 2250
> skb_shinfo(skb)->nr_frags = 17
> skb_shinfo(skb)->gso_size = 75
> skb_shinfo(skb)->frags[0...16].bv_len = 125
> list_skb->len = 125
> list_skb->data_len = 0
>
> When slicing the frag_list skb, there three cases:
> 1. Only *non* head_frag
> sg will be false, only when skb_headlen(list_skb)==len is satisfied,
> it will enter the branch at line 4560, and there will be no crash.
> 2. Mixed head_frag
> sg will be false, Only when skb_headlen(list_skb)==len is satisfied,
> it will enter the branch at line 4560, and there will be no crash.
> 3. Only frag_list with head_frag=true
> sg is true, three cases below:
> (1) skb_headlen(list_skb)==len is satisfied, it will enter the branch
> at line 4560, and there will be no crash.
> (2) skb_headlen(list_skb)<len is satisfied, it will enter the branch
> at line 4560, and there will be no crash.
> (3) skb_headlen(list_skb)>len is satisfied, it will be crash.
>
> Applying this patch, three cases will be:
> 1. Only *non* head_frag
> sg will be false. No difference with before.
> 2. Mixed head_frag
> sg will be false. No difference with before.
> 3. Only frag_list with head_frag=true
> sg is true, there also three cases:
> (1) skb_headlen(list_skb)==len is satisfied, no difference with before.
> (2) skb_headlen(list_skb)<len is satisfied, will be revert to copying
> in this case.
> (3) skb_headlen(list_skb)>len is satisfied, will be revert to copying
> in this case.
>
> Since commit 13acc94eff122("net: permit skb_segment on head_frag frag_list
> skb"), it is allowed to segment the head_frag frag_list skb.
>
> Signed-off-by: Fred Li <dracodingfly@gmail.com>
> ---
> net/core/skbuff.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index f0a9ef1aeaa2..b1dab1b071fc 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -4556,7 +4556,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
> hsize = skb_headlen(head_skb) - offset;
>
> if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
> - (skb_headlen(list_skb) == len || sg)) {
> + (skb_headlen(list_skb) == len)) {
> BUG_ON(skb_headlen(list_skb) > len);
>
> nskb = skb_clone(list_skb, GFP_ATOMIC);
I must admit I more than a bit lost in the many turns of skb_segment(),
but the above does not look like the correct solution, as it will make
the later BUG_ON() unreachable/meaningless.
Do I read correctly that when the BUG_ON() triggers:
list_skb->len is 125
len is 75
list_skb->frag_head is true
It looks like skb_segment() is becoming even and ever more complex to
cope with unexpected skb layouts, only possibly when skb_segment() is
called by some BPF helpers.
I think it should be up to the helper itself to adjust the skb and/or
the device features to respect skb_segment() constraints, instead of
making the common code increasingly not maintainable.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true
2024-07-02 9:23 ` Paolo Abeni
@ 2024-07-03 12:21 ` Fred Li
2024-07-06 14:26 ` Willem de Bruijn
0 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-03 12:21 UTC (permalink / raw)
To: pabeni
Cc: aleksander.lobakin, andrii, ast, bpf, daniel, davem, dracodingfly,
edumazet, haoluo, hawk, john.fastabend, jolsa, kpsingh, kuba,
linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev, sashal,
sdf, song, yonghong.song, herbert
> I must admit I more than a bit lost in the many turns of skb_segment(),
> but the above does not look like the correct solution, as it will make
> the later BUG_ON() unreachable/meaningless.
Sorry, the subsequent BUG_ON maybe should be removed in this patch, because
for skb_headlen(list_skb) > len, it will continue splitting as commit 13acc94eff122
(net: permit skb_segment on head_frag frag_list skb) does.
>
> Do I read correctly that when the BUG_ON() triggers:
>
> list_skb->len is 125
> len is 75
> list_skb->frag_head is true
>
yes, it's correct.
list_skb->len is 125
gso_size is 75, also the len in the BUG_ON conditon
list_skb->head_frag is true
> It looks like skb_segment() is becoming even and ever more complex to
> cope with unexpected skb layouts, only possibly when skb_segment() is
> called by some BPF helpers.
>
> Thanks,
>
> Paolo
I'll wait for more suggestions from others.
Thanks
Fred Li
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true
2024-07-03 12:21 ` Fred Li
@ 2024-07-06 14:26 ` Willem de Bruijn
2024-07-08 14:31 ` [PATCH] net: linearizing skb when downgrade gso_size Fred Li
` (3 more replies)
0 siblings, 4 replies; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-06 14:26 UTC (permalink / raw)
To: Fred Li, pabeni
Cc: aleksander.lobakin, andrii, ast, bpf, daniel, davem, dracodingfly,
edumazet, haoluo, hawk, john.fastabend, jolsa, kpsingh, kuba,
linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev, sashal,
sdf, song, yonghong.song, herbert
Fred Li wrote:
> > I must admit I more than a bit lost in the many turns of skb_segment(),
> > but the above does not look like the correct solution, as it will make
> > the later BUG_ON() unreachable/meaningless.
>
> Sorry, the subsequent BUG_ON maybe should be removed in this patch, because
> for skb_headlen(list_skb) > len, it will continue splitting as commit 13acc94eff122
> (net: permit skb_segment on head_frag frag_list skb) does.
>
> >
> > Do I read correctly that when the BUG_ON() triggers:
> >
> > list_skb->len is 125
> > len is 75
> > list_skb->frag_head is true
> >
>
> yes, it's correct.
> list_skb->len is 125
> gso_size is 75, also the len in the BUG_ON conditon
> list_skb->head_frag is true
>
> > It looks like skb_segment() is becoming even and ever more complex to
> > cope with unexpected skb layouts, only possibly when skb_segment() is
> > called by some BPF helpers.
> >
> > Thanks,
> >
> > Paolo
>
> I'll wait for more suggestions from others.
In general, agreed with Paolo. Segmentation is getting ever more
complex and the code hard to follow.
Maybe at some point we'll have to bite the bullet and seriously
refactor it. Or at least parts, such as the frag_list handling case.
But that kills any odds of backporting fixes, so not if we can avoid
it.
In particular, changing gso_size on skbs with frag_list is fragile.
Instead of adding another special case, how about just linearizing
sbks after BPF calls adjust_room (at least if called without
BPF_F_ADJ_ROOM_FIXED_GSO) if they have frag_list.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH] net: linearizing skb when downgrade gso_size
2024-07-06 14:26 ` Willem de Bruijn
@ 2024-07-08 14:31 ` Fred Li
2024-07-09 15:53 ` Willem de Bruijn
2024-07-17 5:35 ` [PATCH v3] " Fred Li
` (2 subsequent siblings)
3 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-08 14:31 UTC (permalink / raw)
To: willemdebruijn.kernel
Cc: aleksander.lobakin, andrii, ast, bpf, daniel, davem, dracodingfly,
edumazet, haoluo, hawk, herbert, john.fastabend, jolsa, kpsingh,
kuba, linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev,
pabeni, sashal, sdf, song, yonghong.song
Here is a patch that linearizing skb when downgrade
gso_size and sg should disabled, If there are no issues,
I will submit a formal patch shortly.
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
include/linux/skbuff.h | 22 ++++++++++++++++++++++
net/core/filter.c | 16 ++++++++++++----
net/core/skbuff.c | 19 ++-----------------
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5f11f9873341..99b7fc1e826a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2400,6 +2400,28 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb)
return skb->len - skb->data_len;
}
+static inline bool skb_is_nonsg(const struct sk_buff *skb)
+{
+ struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
+ struct sk_buff *check_skb;
+ for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
+ if (skb_headlen(check_skb) && !check_skb->head_frag) {
+ /* gso_size is untrusted, and we have a frag_list with
+ * a linear non head_frag item.
+ *
+ * If head_skb's headlen does not fit requested gso_size,
+ * it means that the frag_list members do NOT terminate
+ * on exact gso_size boundaries. Hence we cannot perform
+ * skb_frag_t page sharing. Therefore we must fallback to
+ * copying the frag_list skbs; we do so by disabling SG.
+ */
+ return true;
+ }
+ }
+
+ return false;
+}
+
static inline unsigned int __skb_pagelen(const struct sk_buff *skb)
{
unsigned int i, len = 0;
diff --git a/net/core/filter.c b/net/core/filter.c
index df4578219e82..c0e6e7f28635 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
if (skb_is_gso(skb)) {
struct skb_shared_info *shinfo = skb_shinfo(skb);
- /* Due to header grow, MSS needs to be downgraded. */
- if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
- skb_decrease_gso_size(shinfo, len_diff);
-
/* Header must be checked, and gso_segs recomputed. */
shinfo->gso_type |= gso_type;
shinfo->gso_segs = 0;
+
+ /* Due to header grow, MSS needs to be downgraded.
+ * There is BUG_ON When segment the frag_list with
+ * head_frag true so linearize skb after downgrade
+ * the MSS.
+ */
+ if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
+ skb_decrease_gso_size(shinfo, len_diff);
+ if (skb_is_nonsg(skb))
+ return skb_linearize(skb) ? : 0;
+ }
+
}
return 0;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b1dab1b071fc..81e018185527 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4458,23 +4458,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) &&
mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) {
- struct sk_buff *check_skb;
-
- for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
- if (skb_headlen(check_skb) && !check_skb->head_frag) {
- /* gso_size is untrusted, and we have a frag_list with
- * a linear non head_frag item.
- *
- * If head_skb's headlen does not fit requested gso_size,
- * it means that the frag_list members do NOT terminate
- * on exact gso_size boundaries. Hence we cannot perform
- * skb_frag_t page sharing. Therefore we must fallback to
- * copying the frag_list skbs; we do so by disabling SG.
- */
- features &= ~NETIF_F_SG;
- break;
- }
- }
+ if (skb_is_nonsg(head_skb))
+ features &= ~NETIF_F_SG;
}
__skb_push(head_skb, doffset);
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH] net: linearizing skb when downgrade gso_size
2024-07-08 14:31 ` [PATCH] net: linearizing skb when downgrade gso_size Fred Li
@ 2024-07-09 15:53 ` Willem de Bruijn
2024-07-09 20:16 ` Herbert Xu
2024-07-12 8:17 ` Fred Li
0 siblings, 2 replies; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-09 15:53 UTC (permalink / raw)
To: Fred Li, willemdebruijn.kernel
Cc: aleksander.lobakin, andrii, ast, bpf, daniel, davem, dracodingfly,
edumazet, haoluo, hawk, herbert, john.fastabend, jolsa, kpsingh,
kuba, linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev,
pabeni, sashal, sdf, song, yonghong.song
Fred Li wrote:
> Here is a patch that linearizing skb when downgrade
> gso_size and sg should disabled, If there are no issues,
> I will submit a formal patch shortly.
Target bpf.
Probably does not need quite as many direct CCs.
> Signed-off-by: Fred Li <dracodingfly@gmail.com>
> ---
> include/linux/skbuff.h | 22 ++++++++++++++++++++++
> net/core/filter.c | 16 ++++++++++++----
> net/core/skbuff.c | 19 ++-----------------
> 3 files changed, 36 insertions(+), 21 deletions(-)
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 5f11f9873341..99b7fc1e826a 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -2400,6 +2400,28 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb)
> return skb->len - skb->data_len;
> }
>
> +static inline bool skb_is_nonsg(const struct sk_buff *skb)
> +{
is_nonsg does not cover the functionality, which is fairly subtle.
But maybe we don't need this function at all, see below..
> + struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
> + struct sk_buff *check_skb;
No need for separate check_skb
> + for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
> + if (skb_headlen(check_skb) && !check_skb->head_frag) {
> + /* gso_size is untrusted, and we have a frag_list with
> + * a linear non head_frag item.
> + *
> + * If head_skb's headlen does not fit requested gso_size,
> + * it means that the frag_list members do NOT terminate
> + * on exact gso_size boundaries. Hence we cannot perform
> + * skb_frag_t page sharing. Therefore we must fallback to
> + * copying the frag_list skbs; we do so by disabling SG.
> + */
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> static inline unsigned int __skb_pagelen(const struct sk_buff *skb)
> {
> unsigned int i, len = 0;
> diff --git a/net/core/filter.c b/net/core/filter.c
> index df4578219e82..c0e6e7f28635 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
> if (skb_is_gso(skb)) {
> struct skb_shared_info *shinfo = skb_shinfo(skb);
>
> - /* Due to header grow, MSS needs to be downgraded. */
> - if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
> - skb_decrease_gso_size(shinfo, len_diff);
> -
> /* Header must be checked, and gso_segs recomputed. */
> shinfo->gso_type |= gso_type;
> shinfo->gso_segs = 0;
> +
> + /* Due to header grow, MSS needs to be downgraded.
> + * There is BUG_ON When segment the frag_list with
> + * head_frag true so linearize skb after downgrade
> + * the MSS.
> + */
> + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
> + skb_decrease_gso_size(shinfo, len_diff);
> + if (skb_is_nonsg(skb))
> + return skb_linearize(skb) ? : 0;
> + }
> +
No need for ternary statement.
Instead of the complex test in skb_is_nonsg, can we just assume that
alignment will be off if having frag_list and changing gso_size.
The same will apply to bpf_skb_net_shrink too.
Not sure that it is okay to linearize inside a BPF helper function.
Hopefully bpf experts can chime in on that.
> }
>
> return 0;
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index b1dab1b071fc..81e018185527 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -4458,23 +4458,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
>
> if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) &&
> mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) {
> - struct sk_buff *check_skb;
> -
> - for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
> - if (skb_headlen(check_skb) && !check_skb->head_frag) {
> - /* gso_size is untrusted, and we have a frag_list with
> - * a linear non head_frag item.
> - *
> - * If head_skb's headlen does not fit requested gso_size,
> - * it means that the frag_list members do NOT terminate
> - * on exact gso_size boundaries. Hence we cannot perform
> - * skb_frag_t page sharing. Therefore we must fallback to
> - * copying the frag_list skbs; we do so by disabling SG.
> - */
> - features &= ~NETIF_F_SG;
> - break;
> - }
> - }
> + if (skb_is_nonsg(head_skb))
> + features &= ~NETIF_F_SG;
> }
>
> __skb_push(head_skb, doffset);
> --
> 2.33.0
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] net: linearizing skb when downgrade gso_size
2024-07-09 15:53 ` Willem de Bruijn
@ 2024-07-09 20:16 ` Herbert Xu
2024-07-09 21:29 ` Willem de Bruijn
2024-07-12 8:17 ` Fred Li
1 sibling, 1 reply; 21+ messages in thread
From: Herbert Xu @ 2024-07-09 20:16 UTC (permalink / raw)
To: Willem de Bruijn
Cc: Fred Li, aleksander.lobakin, andrii, ast, bpf, daniel, davem,
edumazet, haoluo, hawk, john.fastabend, jolsa, kpsingh, kuba,
linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev, pabeni,
sashal, sdf, song, yonghong.song
On Tue, Jul 09, 2024 at 11:53:21AM -0400, Willem de Bruijn wrote:
>
> > + /* Due to header grow, MSS needs to be downgraded.
> > + * There is BUG_ON When segment the frag_list with
> > + * head_frag true so linearize skb after downgrade
> > + * the MSS.
> > + */
This sounds completely wrong. You should never grow the TCP header
by changing gso_size. What is the usage-scenario for this?
Think about it, if a router forwards a TCP packet, and ends up
growing its TCP header and then splits the packet into two, then
this router is brain-dead.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] net: linearizing skb when downgrade gso_size
2024-07-09 20:16 ` Herbert Xu
@ 2024-07-09 21:29 ` Willem de Bruijn
2024-07-10 23:06 ` Herbert Xu
0 siblings, 1 reply; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-09 21:29 UTC (permalink / raw)
To: Herbert Xu, Willem de Bruijn
Cc: Fred Li, aleksander.lobakin, andrii, ast, bpf, daniel, davem,
edumazet, haoluo, hawk, john.fastabend, jolsa, kpsingh, kuba,
linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev, pabeni,
sashal, sdf, song, yonghong.song
Herbert Xu wrote:
> On Tue, Jul 09, 2024 at 11:53:21AM -0400, Willem de Bruijn wrote:
> >
> > > + /* Due to header grow, MSS needs to be downgraded.
> > > + * There is BUG_ON When segment the frag_list with
> > > + * head_frag true so linearize skb after downgrade
> > > + * the MSS.
> > > + */
>
> This sounds completely wrong. You should never grow the TCP header
> by changing gso_size. What is the usage-scenario for this?
>
> Think about it, if a router forwards a TCP packet, and ends up
> growing its TCP header and then splits the packet into two, then
> this router is brain-dead.
This is an unfortunate feature, but already exists.
It decreases gso_size to account for tunnel headers.
For USO, we added BPF_F_ADJ_ROOM_FIXED_GSO to avoid this in better,
newer users.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] net: linearizing skb when downgrade gso_size
2024-07-09 21:29 ` Willem de Bruijn
@ 2024-07-10 23:06 ` Herbert Xu
0 siblings, 0 replies; 21+ messages in thread
From: Herbert Xu @ 2024-07-10 23:06 UTC (permalink / raw)
To: Willem de Bruijn
Cc: Fred Li, aleksander.lobakin, andrii, ast, bpf, daniel, davem,
edumazet, haoluo, hawk, john.fastabend, jolsa, kpsingh, kuba,
linux-kernel, linux, martin.lau, mkhalfella, nbd, netdev, pabeni,
sashal, sdf, song, yonghong.song
On Tue, Jul 09, 2024 at 05:29:59PM -0400, Willem de Bruijn wrote:
>
> This is an unfortunate feature, but already exists.
>
> It decreases gso_size to account for tunnel headers.
Growing the tunnel header is totally fine. But you should not
decrease gso_size because of that. Instead the correct course
of action is to drop the packet and generate an ICMP if it no
longer fits the MTU.
A router that resegments a TCP packet at the TCP-level (not IP)
is brain-dead.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] net: linearizing skb when downgrade gso_size
2024-07-09 15:53 ` Willem de Bruijn
2024-07-09 20:16 ` Herbert Xu
@ 2024-07-12 8:17 ` Fred Li
1 sibling, 0 replies; 21+ messages in thread
From: Fred Li @ 2024-07-12 8:17 UTC (permalink / raw)
To: willemdebruijn.kernel; +Cc: bpf, herbert, linux-kernel, netdev
> No need for ternary statement.
>
> Instead of the complex test in skb_is_nonsg, can we just assume that
> alignment will be off if having frag_list and changing gso_size.
>
> The same will apply to bpf_skb_net_shrink too.
increase gso_size may be no problem and we can use BPF_F_ADJ_ROOM_FIXED_GSO
to avoid update gso_size when shrink.
>
> Not sure that it is okay to linearize inside a BPF helper function.
> Hopefully bpf experts can chime in on that.
Thanks
Fred Li
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v3] net: linearizing skb when downgrade gso_size
2024-07-06 14:26 ` Willem de Bruijn
2024-07-08 14:31 ` [PATCH] net: linearizing skb when downgrade gso_size Fred Li
@ 2024-07-17 5:35 ` Fred Li
2024-07-17 16:32 ` Willem de Bruijn
2024-07-19 2:46 ` [PATCH v4] bpf: Fixed a segment issue " Fred Li
2024-07-22 3:08 ` [PATCH bpf v5] bpf: Fixed " Fred Li
3 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-17 5:35 UTC (permalink / raw)
To: pabeni, willemdebruijn.kernel, herbert
Cc: bpf, netdev, linux-kernel, ast, daniel, andrii, song,
yonghong.song, john.fastabend, kpsingh, Fred Li
Linearizing skb when downgrade gso_size because it may
trigger the BUG_ON when segment skb as described in [1].
v3 changes:
linearize skb if having frag_list as Willem de Bruijn suggested[2].
[1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
[2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
net/core/filter.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index df4578219e82..70919b532d68 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
if (skb_is_gso(skb)) {
struct skb_shared_info *shinfo = skb_shinfo(skb);
- /* Due to header grow, MSS needs to be downgraded. */
- if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
- skb_decrease_gso_size(shinfo, len_diff);
-
/* Header must be checked, and gso_segs recomputed. */
shinfo->gso_type |= gso_type;
shinfo->gso_segs = 0;
+
+ /* Due to header grow, MSS needs to be downgraded.
+ * There is BUG_ON When segment the frag_list with
+ * head_frag true so linearize skb after downgrade
+ * the MSS.
+ */
+ if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
+ skb_decrease_gso_size(shinfo, len_diff);
+ if (shinfo->frag_list)
+ return skb_linearize(skb);
+ }
+
}
return 0;
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v3] net: linearizing skb when downgrade gso_size
2024-07-17 5:35 ` [PATCH v3] " Fred Li
@ 2024-07-17 16:32 ` Willem de Bruijn
2024-07-18 7:42 ` Fred Li
0 siblings, 1 reply; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-17 16:32 UTC (permalink / raw)
To: Fred Li, pabeni, willemdebruijn.kernel, herbert
Cc: bpf, netdev, linux-kernel, ast, daniel, andrii, song,
yonghong.song, john.fastabend, kpsingh, Fred Li
Fred Li wrote:
> Linearizing skb when downgrade gso_size because it may
> trigger the BUG_ON when segment skb as described in [1].
>
> v3 changes:
> linearize skb if having frag_list as Willem de Bruijn suggested[2].
>
> [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
> [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
>
> Signed-off-by: Fred Li <dracodingfly@gmail.com>
A fix needs a Fixed tag.
This might be the original commit that introduced gso_size adjustment,
commit 6578171a7ff0c ("bpf: add bpf_skb_change_proto helper")
Unless support for frag_list came later.
> ---
> net/core/filter.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index df4578219e82..70919b532d68 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
> if (skb_is_gso(skb)) {
> struct skb_shared_info *shinfo = skb_shinfo(skb);
>
> - /* Due to header grow, MSS needs to be downgraded. */
> - if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
> - skb_decrease_gso_size(shinfo, len_diff);
> -
> /* Header must be checked, and gso_segs recomputed. */
> shinfo->gso_type |= gso_type;
> shinfo->gso_segs = 0;
> +
> + /* Due to header grow, MSS needs to be downgraded.
> + * There is BUG_ON When segment the frag_list with
> + * head_frag true so linearize skb after downgrade
> + * the MSS.
> + */
Super tiny nit: no capitalization of When in the middle of a sentence.
> + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
> + skb_decrease_gso_size(shinfo, len_diff);
> + if (shinfo->frag_list)
> + return skb_linearize(skb);
I previously asked whether it was safe to call pskb_expand_head from
within a BPF external function. There are actually plenty of existing
examples of this, so this is fine.
> + }
> +
> }
>
> return 0;
> --
> 2.33.0
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v3] net: linearizing skb when downgrade gso_size
2024-07-17 16:32 ` Willem de Bruijn
@ 2024-07-18 7:42 ` Fred Li
0 siblings, 0 replies; 21+ messages in thread
From: Fred Li @ 2024-07-18 7:42 UTC (permalink / raw)
To: willemdebruijn.kernel
Cc: andrii, ast, bpf, daniel, dracodingfly, herbert, john.fastabend,
kpsingh, linux-kernel, netdev, pabeni, song, yonghong.song
>
> > Linearizing skb when downgrade gso_size because it may
> > trigger the BUG_ON when segment skb as described in [1].
> >
> > v3 changes:
> > linearize skb if having frag_list as Willem de Bruijn suggested[2].
> >
> > [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
> > [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
> >
> > Signed-off-by: Fred Li <dracodingfly@gmail.com>
>
> A fix needs a Fixed tag.
>
> This might be the original commit that introduced gso_size adjustment,
> commit 6578171a7ff0c ("bpf: add bpf_skb_change_proto helper")
>
Yes, this is the original commit, but it's already fixed by commit
364745fbe981a (bpf: Do not change gso_size during bpf_skb_change_proto())
Another commit 2be7e212d5419 (bpf: add bpf_skb_adjust_room helper) introduced
gso_size too.
> Unless support for frag_list came later.
>
> > ---
> > net/core/filter.c | 16 ++++++++++++----
> > 1 file changed, 12 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/core/filter.c b/net/core/filter.c
> > index df4578219e82..70919b532d68 100644
> > --- a/net/core/filter.c
> > +++ b/net/core/filter.c
> > @@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
> > if (skb_is_gso(skb)) {
> > struct skb_shared_info *shinfo = skb_shinfo(skb);
> >
> > - /* Due to header grow, MSS needs to be downgraded. */
> > - if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
> > - skb_decrease_gso_size(shinfo, len_diff);
> > -
> > /* Header must be checked, and gso_segs recomputed. */
> > shinfo->gso_type |= gso_type;
> > shinfo->gso_segs = 0;
> > +
> > + /* Due to header grow, MSS needs to be downgraded.
> > + * There is BUG_ON When segment the frag_list with
> > + * head_frag true so linearize skb after downgrade
> > + * the MSS.
> > + */
>
> Super tiny nit: no capitalization of When in the middle of a sentence.
Thanks, i'will fix.
>
> > + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
> > + skb_decrease_gso_size(shinfo, len_diff);
> > + if (shinfo->frag_list)
> > + return skb_linearize(skb);
>
> I previously asked whether it was safe to call pskb_expand_head from
> within a BPF external function. There are actually plenty of existing
> examples of this, so this is fine.
>
> > + }
> > +
> > }
> >
> > return 0;
> > --
> > 2.33.0
> >
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v4] bpf: Fixed a segment issue when downgrade gso_size
2024-07-06 14:26 ` Willem de Bruijn
2024-07-08 14:31 ` [PATCH] net: linearizing skb when downgrade gso_size Fred Li
2024-07-17 5:35 ` [PATCH v3] " Fred Li
@ 2024-07-19 2:46 ` Fred Li
2024-07-19 18:22 ` Willem de Bruijn
2024-07-22 3:08 ` [PATCH bpf v5] bpf: Fixed " Fred Li
3 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-19 2:46 UTC (permalink / raw)
To: willemdebruijn.kernel
Cc: andrii, ast, bpf, daniel, dracodingfly, herbert, john.fastabend,
kpsingh, linux-kernel, netdev, pabeni, song, yonghong.song
Linearizing skb when downgrade gso_size because it may
trigger the BUG_ON when segment skb as described in [1].
v4 changes:
add fixed tag.
v3 changes:
linearize skb if having frag_list as Willem de Bruijn suggested[2].
[1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
[2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
Fixes: 2be7e212d5419 ("bpf: add bpf_skb_adjust_room helper")
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
net/core/filter.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index df4578219e82..71396ecfc574 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
if (skb_is_gso(skb)) {
struct skb_shared_info *shinfo = skb_shinfo(skb);
- /* Due to header grow, MSS needs to be downgraded. */
- if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
- skb_decrease_gso_size(shinfo, len_diff);
-
/* Header must be checked, and gso_segs recomputed. */
shinfo->gso_type |= gso_type;
shinfo->gso_segs = 0;
+
+ /* Due to header grow, MSS needs to be downgraded.
+ * There is BUG_ON when segment the frag_list with
+ * head_frag true so linearize skb after downgrade
+ * the MSS.
+ */
+ if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
+ skb_decrease_gso_size(shinfo, len_diff);
+ if (shinfo->frag_list)
+ return skb_linearize(skb);
+ }
+
}
return 0;
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v4] bpf: Fixed a segment issue when downgrade gso_size
2024-07-19 2:46 ` [PATCH v4] bpf: Fixed a segment issue " Fred Li
@ 2024-07-19 18:22 ` Willem de Bruijn
0 siblings, 0 replies; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-19 18:22 UTC (permalink / raw)
To: Fred Li
Cc: andrii, ast, bpf, daniel, herbert, john.fastabend, kpsingh,
linux-kernel, netdev, pabeni, song, yonghong.song
On Thu, Jul 18, 2024 at 7:47 PM Fred Li <dracodingfly@gmail.com> wrote:
>
> Linearizing skb when downgrade gso_size because it may
> trigger the BUG_ON when segment skb as described in [1].
>
> v4 changes:
> add fixed tag.
>
> v3 changes:
> linearize skb if having frag_list as Willem de Bruijn suggested[2].
>
> [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
> [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
>
> Fixes: 2be7e212d5419 ("bpf: add bpf_skb_adjust_room helper")
> Signed-off-by: Fred Li <dracodingfly@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
For next time:
- add target: [PATCH bpf]
- use imperative mood in commit messages: "Linearize ..."
https://www.kernel.org/doc/Documentation/bpf/bpf_devel_QA.rst
https://www.kernel.org/doc/Documentation/process/submitting-patches.rst
> ---
> net/core/filter.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index df4578219e82..71396ecfc574 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
> if (skb_is_gso(skb)) {
> struct skb_shared_info *shinfo = skb_shinfo(skb);
>
> - /* Due to header grow, MSS needs to be downgraded. */
> - if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
> - skb_decrease_gso_size(shinfo, len_diff);
> -
> /* Header must be checked, and gso_segs recomputed. */
> shinfo->gso_type |= gso_type;
> shinfo->gso_segs = 0;
> +
> + /* Due to header grow, MSS needs to be downgraded.
> + * There is BUG_ON when segment the frag_list with
> + * head_frag true so linearize skb after downgrade
> + * the MSS.
> + */
> + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
> + skb_decrease_gso_size(shinfo, len_diff);
> + if (shinfo->frag_list)
> + return skb_linearize(skb);
> + }
> +
> }
>
> return 0;
> --
> 2.33.0
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf v5] bpf: Fixed segment issue when downgrade gso_size
2024-07-06 14:26 ` Willem de Bruijn
` (2 preceding siblings ...)
2024-07-19 2:46 ` [PATCH v4] bpf: Fixed a segment issue " Fred Li
@ 2024-07-22 3:08 ` Fred Li
2024-07-22 16:29 ` Willem de Bruijn
3 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-22 3:08 UTC (permalink / raw)
To: willemdebruijn.kernel
Cc: andrii, ast, bpf, daniel, herbert, john.fastabend, kpsingh,
linux-kernel, netdev, pabeni, song, yonghong.song, Fred Li
Linearize skb when downgrad gso_size to prevent triggering
the BUG_ON during segment skb as described in [1].
v5 changes:
- add bpf subject prefix.
- adjust message to imperative mood.
v4 changes:
- add fixed tag.
v3 changes:
- linearize skb if having frag_list as Willem de Bruijn suggested [2].
[1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
[2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
net/core/filter.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index df4578219e82..71396ecfc574 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
if (skb_is_gso(skb)) {
struct skb_shared_info *shinfo = skb_shinfo(skb);
- /* Due to header grow, MSS needs to be downgraded. */
- if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
- skb_decrease_gso_size(shinfo, len_diff);
-
/* Header must be checked, and gso_segs recomputed. */
shinfo->gso_type |= gso_type;
shinfo->gso_segs = 0;
+
+ /* Due to header grow, MSS needs to be downgraded.
+ * There is BUG_ON when segment the frag_list with
+ * head_frag true so linearize skb after downgrade
+ * the MSS.
+ */
+ if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
+ skb_decrease_gso_size(shinfo, len_diff);
+ if (shinfo->frag_list)
+ return skb_linearize(skb);
+ }
+
}
return 0;
--
2.33.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH bpf v5] bpf: Fixed segment issue when downgrade gso_size
2024-07-22 3:08 ` [PATCH bpf v5] bpf: Fixed " Fred Li
@ 2024-07-22 16:29 ` Willem de Bruijn
2024-07-24 13:37 ` Fred Li
0 siblings, 1 reply; 21+ messages in thread
From: Willem de Bruijn @ 2024-07-22 16:29 UTC (permalink / raw)
To: Fred Li
Cc: andrii, ast, bpf, daniel, herbert, john.fastabend, kpsingh,
linux-kernel, netdev, pabeni, song, yonghong.song
On Sun, Jul 21, 2024 at 8:08 PM Fred Li <dracodingfly@gmail.com> wrote:
>
> Linearize skb when downgrad gso_size to prevent triggering
> the BUG_ON during segment skb as described in [1].
>
> v5 changes:
> - add bpf subject prefix.
> - adjust message to imperative mood.
>
> v4 changes:
> - add fixed tag.
>
> v3 changes:
> - linearize skb if having frag_list as Willem de Bruijn suggested [2].
>
> [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
> [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
>
> Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
> Signed-off-by: Fred Li <dracodingfly@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
My comments were informational, for a next patch if any, really. v4
was fine. v5 is too.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH bpf v5] bpf: Fixed segment issue when downgrade gso_size
2024-07-22 16:29 ` Willem de Bruijn
@ 2024-07-24 13:37 ` Fred Li
2024-07-25 10:09 ` Daniel Borkmann
0 siblings, 1 reply; 21+ messages in thread
From: Fred Li @ 2024-07-24 13:37 UTC (permalink / raw)
To: willemdebruijn.kernel; +Cc: bpf, linux-kernel, netdev
> >
> > Linearize skb when downgrad gso_size to prevent triggering
> > the BUG_ON during segment skb as described in [1].
> >
> > v5 changes:
> > - add bpf subject prefix.
> > - adjust message to imperative mood.
> >
> > v4 changes:
> > - add fixed tag.
> >
> > v3 changes:
> > - linearize skb if having frag_list as Willem de Bruijn suggested [2].
> >
> > [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
> > [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
> >
> > Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
> > Signed-off-by: Fred Li <dracodingfly@gmail.com>
>
> Reviewed-by: Willem de Bruijn <willemb@google.com>
>
> My comments were informational, for a next patch if any, really. v4
> was fine. v5 is too.
Thanks for your advise.
Fred Li
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH bpf v5] bpf: Fixed segment issue when downgrade gso_size
2024-07-24 13:37 ` Fred Li
@ 2024-07-25 10:09 ` Daniel Borkmann
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Borkmann @ 2024-07-25 10:09 UTC (permalink / raw)
To: Fred Li, willemdebruijn.kernel; +Cc: bpf, linux-kernel, netdev
On 7/24/24 3:37 PM, Fred Li wrote:
>>>
>>> Linearize skb when downgrad gso_size to prevent triggering
>>> the BUG_ON during segment skb as described in [1].
>>>
>>> v5 changes:
>>> - add bpf subject prefix.
>>> - adjust message to imperative mood.
>>>
>>> v4 changes:
>>> - add fixed tag.
>>>
>>> v3 changes:
>>> - linearize skb if having frag_list as Willem de Bruijn suggested [2].
>>>
>>> [1] https://lore.kernel.org/all/20240626065555.35460-2-dracodingfly@gmail.com/
>>> [2] https://lore.kernel.org/all/668d5cf1ec330_1c18c32947@willemb.c.googlers.com.notmuch/
>>>
>>> Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
>>> Signed-off-by: Fred Li <dracodingfly@gmail.com>
>>
>> Reviewed-by: Willem de Bruijn <willemb@google.com>
>>
>> My comments were informational, for a next patch if any, really. v4
>> was fine. v5 is too.
>
> Thanks for your advise.
>
> Fred Li
lgtm, I slightly improved wording & applied, thanks!
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2024-07-25 10:09 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-26 6:55 [PATCH v2 2/2] test_bpf: Introduce an skb_segment test for frag_list whose head_frag=true and gso_size was mangled Fred Li
2024-06-26 6:55 ` [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true Fred Li
2024-07-02 9:23 ` Paolo Abeni
2024-07-03 12:21 ` Fred Li
2024-07-06 14:26 ` Willem de Bruijn
2024-07-08 14:31 ` [PATCH] net: linearizing skb when downgrade gso_size Fred Li
2024-07-09 15:53 ` Willem de Bruijn
2024-07-09 20:16 ` Herbert Xu
2024-07-09 21:29 ` Willem de Bruijn
2024-07-10 23:06 ` Herbert Xu
2024-07-12 8:17 ` Fred Li
2024-07-17 5:35 ` [PATCH v3] " Fred Li
2024-07-17 16:32 ` Willem de Bruijn
2024-07-18 7:42 ` Fred Li
2024-07-19 2:46 ` [PATCH v4] bpf: Fixed a segment issue " Fred Li
2024-07-19 18:22 ` Willem de Bruijn
2024-07-22 3:08 ` [PATCH bpf v5] bpf: Fixed " Fred Li
2024-07-22 16:29 ` Willem de Bruijn
2024-07-24 13:37 ` Fred Li
2024-07-25 10:09 ` Daniel Borkmann
2024-06-26 6:55 ` [PATCH v2 0/2] net: Fix BUG_ON for segment frag_list with mangled gso_size and head_frag is true Fred Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).