aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <[email protected]>2022-05-16 10:47:44 +0100
committerDavid S. Miller <[email protected]>2022-05-16 10:47:44 +0100
commit6ee1d84b2b78af4cff0d9714da81c752baf4b01e (patch)
treee41b3286e8a9a62b0ded02ecd7b63c057cd39660
parent3aba103006bcc4a7472b7c9506b3bc065ffb7992 (diff)
parentf8319dfd1b3b3be6c08795017fc30f880f8bc861 (diff)
Merge branch 'skb-drop-reason-boundary'
Menglong Dong says: ==================== net: skb: check the boundrary of skb drop reason In the commit 1330b6ef3313 ("skb: make drop reason booleanable"), SKB_NOT_DROPPED_YET is added to the enum skb_drop_reason, which makes the invalid drop reason SKB_NOT_DROPPED_YET can leak to the kfree_skb tracepoint. Once this happen (it happened, as 4th patch says), it can cause NULL pointer in drop monitor and result in kernel panic. Therefore, check the boundrary of drop reason in both kfree_skb_reason (2th patch) and drop monitor (1th patch) to prevent such case happens again. Meanwhile, fix the invalid drop reason passed to kfree_skb_reason() in tcp_v4_rcv() and tcp_v6_rcv(). Changes since v2: 1/4 - don't reset the reason and print the debug warning only (Jakub Kicinski) 4/4 - remove new lines between tags Changes since v1: - consider tcp_v6_rcv() in the 4th patch ==================== Signed-off-by: David S. Miller <[email protected]>
-rw-r--r--include/linux/skbuff.h3
-rw-r--r--net/core/drop_monitor.c2
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv6/tcp_ipv6.c1
5 files changed, 7 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9d82a8b6c8f1..5a2b29df6cab 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -510,7 +510,8 @@ enum skb_drop_reason {
(name = SKB_DROP_REASON_##reason)
#define SKB_DR_OR(name, reason) \
do { \
- if (name == SKB_DROP_REASON_NOT_SPECIFIED) \
+ if (name == SKB_DROP_REASON_NOT_SPECIFIED || \
+ name == SKB_NOT_DROPPED_YET) \
SKB_DR_SET(name, reason); \
} while (0)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index b89e3e95bffc..41cac0e4834e 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -517,7 +517,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore,
if (!nskb)
return;
- if ((unsigned int)reason >= SKB_DROP_REASON_MAX)
+ if (unlikely(reason >= SKB_DROP_REASON_MAX || reason <= 0))
reason = SKB_DROP_REASON_NOT_SPECIFIED;
cb = NET_DM_SKB_CB(nskb);
cb->reason = reason;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index bd16e158b366..2fea964f09d8 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -771,6 +771,8 @@ void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
if (!skb_unref(skb))
return;
+ DEBUG_NET_WARN_ON_ONCE(reason <= 0 || reason >= SKB_DROP_REASON_MAX);
+
trace_kfree_skb(skb, __builtin_return_address(0), reason);
__kfree_skb(skb);
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 218ad871c0e4..f09bdfc6a321 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2101,6 +2101,7 @@ bad_packet:
}
discard_it:
+ SKB_DR_OR(drop_reason, NOT_SPECIFIED);
/* Discard frame. */
kfree_skb_reason(skb, drop_reason);
return 0;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 60bdec257ba7..636ed23d9af0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1509,6 +1509,7 @@ reset:
discard:
if (opt_skb)
__kfree_skb(opt_skb);
+ SKB_DR_OR(reason, NOT_SPECIFIED);
kfree_skb_reason(skb, reason);
return 0;
csum_err: