From 0f48695cd47437f14ceeb2eeeea65c9ca997dc9d Mon Sep 17 00:00:00 2001 From: Menglong Dong Date: Tue, 16 Aug 2022 17:07:11 +0800 Subject: [PATCH 1/2] net: bpf: disable the usage of bpf_dispatcher for XDP The usage of bpf_dispatcher for XDP caused kernel panic, and the reason has not found. Therefore, disable it for now. Signed-off-by: Menglong Dong Reviewed-by: robinlai --- net/core/dev.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 7aa91887a..bfe39b84b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8426,9 +8426,6 @@ static int dev_xdp_install(struct net_device *dev, bpf_op_t bpf_op, xdp.prog = prog; err = bpf_op(dev, &xdp); - if (!err && non_hw) - bpf_prog_change_xdp(prev_prog, prog); - if (prev_prog) bpf_prog_put(prev_prog); From 6bea6f6ce1320816bc754e7a6a98fa15947e7628 Mon Sep 17 00:00:00 2001 From: Menglong Dong Date: Thu, 11 Aug 2022 19:13:00 +0800 Subject: [PATCH 2/2] net: skb: prevent the split of kfree_skb_reason() by gcc [upstream commit c205cc7534a97f2d6fbd2a23a94ed7c036c6e2aa] Sometimes, gcc will optimize the function by spliting it to two or more functions. In this case, kfree_skb_reason() is splited to kfree_skb_reason and kfree_skb_reason.part.0. However, the function/tracepoint trace_kfree_skb() in it needs the return address of kfree_skb_reason(). This split makes the call chains becomes: kfree_skb_reason() -> kfree_skb_reason.part.0 -> trace_kfree_skb() which makes the return address that passed to trace_kfree_skb() be kfree_skb(). Therefore, introduce '__fix_address', which is the combination of '__noclone' and 'noinline', and apply it to kfree_skb_reason() to prevent to from being splited or made inline. (Is it better to simply apply '__noclone oninline' to kfree_skb_reason? I'm thinking maybe other functions have the same problems) Meanwhile, wrap 'skb_unref()' with 'unlikely()', as the compiler thinks it is likely return true and splits kfree_skb_reason(). Signed-off-by: Menglong Dong Signed-off-by: David S. Miller --- include/linux/compiler_attributes.h | 7 +++++++ include/linux/skbuff.h | 3 ++- net/core/skbuff.c | 5 +++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h index cdf016596..080ca3230 100644 --- a/include/linux/compiler_attributes.h +++ b/include/linux/compiler_attributes.h @@ -270,4 +270,11 @@ */ #define __weak __attribute__((__weak__)) +/* + * Used by functions that use '__builtin_return_address'. These function + * don't want to be splited or made inline, which can make + * the '__builtin_return_address' get unexpected address. + */ +#define __fix_address noinline __noclone + #endif /* __LINUX_COMPILER_ATTRIBUTES_H */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 572fbdd16..25c26bea4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1018,7 +1018,8 @@ static inline bool skb_unref(struct sk_buff *skb) return true; } -void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason); +void __fix_address +kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason); /** * kfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2785d6232..8bb85225e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -703,9 +703,10 @@ EXPORT_SYMBOL(__kfree_skb); * hit zero. Meanwhile, pass the drop reason to 'kfree_skb' * tracepoint. */ -void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason) +void __fix_address +kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason) { - if (!skb_unref(skb)) + if (unlikely(!skb_unref(skb))) return; WARN_ON_ONCE(reason <= 0 || reason >= SKB_DROP_REASON_MAX);