summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2024-10-01 11:47:08 +0200
committerPaolo Abeni <pabeni@redhat.com>2024-10-01 11:47:08 +0200
commit23e19f2473c8762438baa1bcf3f71ee16dfcd535 (patch)
treea1459d6153629dc225628a0994b929b7251e227a
parente9d591b16c0ed8489aedc86cac237145815d14dc (diff)
parentab9a9a9e9647392a19e7a885b08000e89c86b535 (diff)
downloadlinux-23e19f2473c8762438baa1bcf3f71ee16dfcd535.tar.gz
linux-23e19f2473c8762438baa1bcf3f71ee16dfcd535.tar.bz2
linux-23e19f2473c8762438baa1bcf3f71ee16dfcd535.zip
Merge branch 'net-two-fixes-for-qdisc_pkt_len_init'
Eric Dumazet says: ==================== net: two fixes for qdisc_pkt_len_init() Inspired by one syzbot report. At least one qdisc (fq_codel) depends on qdisc_skb_cb(skb)->pkt_len having a sane value (not zero) With the help of af_packet, syzbot was able to fool qdisc_pkt_len_init() to precisely set qdisc_skb_cb(skb)->pkt_len to zero. First patch fixes this issue. Second one (a separate one to help future bisections) adds more sanity check to SKB_GSO_DODGY users. ==================== Link: https://patch.msgid.link/20240924150257.1059524-1-edumazet@google.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--net/core/dev.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 74cf78a6b512..ea5fbcd133ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3758,7 +3758,7 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
sizeof(_tcphdr), &_tcphdr);
if (likely(th))
hdr_len += __tcp_hdrlen(th);
- } else {
+ } else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
struct udphdr _udphdr;
if (skb_header_pointer(skb, hdr_len,
@@ -3766,10 +3766,14 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)
hdr_len += sizeof(struct udphdr);
}
- if (shinfo->gso_type & SKB_GSO_DODGY)
- gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
- shinfo->gso_size);
+ if (unlikely(shinfo->gso_type & SKB_GSO_DODGY)) {
+ int payload = skb->len - hdr_len;
+ /* Malicious packet. */
+ if (payload <= 0)
+ return;
+ gso_segs = DIV_ROUND_UP(payload, shinfo->gso_size);
+ }
qdisc_skb_cb(skb)->pkt_len += (gso_segs - 1) * hdr_len;
}
}