]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/sched: cls_u32: use skb_header_pointer_careful()
authorEric Dumazet <edumazet@google.com>
Wed, 28 Jan 2026 14:15:39 +0000 (14:15 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 30 Jan 2026 02:25:22 +0000 (18:25 -0800)
skb_header_pointer() does not fully validate negative @offset values.

Use skb_header_pointer_careful() instead.

GangMin Kim provided a report and a repro fooling u32_classify():

BUG: KASAN: slab-out-of-bounds in u32_classify+0x1180/0x11b0
net/sched/cls_u32.c:221

Fixes: fbc2e7d9cf49 ("cls_u32: use skb_header_pointer() to dereference data safely")
Reported-by: GangMin Kim <km.kim1503@gmail.com>
Closes: https://lore.kernel.org/netdev/CANn89iJkyUZ=mAzLzC4GdcAgLuPnUoivdLaOs6B9rq5_erj76w@mail.gmail.com/T/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260128141539.3404400-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sched/cls_u32.c

index 2a1c00048fd6f4b700bee11c80502aa3ff993331..58e849c0acf412d3a5ed5cd9a2b32929a720cb17 100644 (file)
@@ -161,10 +161,8 @@ next_knode:
                        int toff = off + key->off + (off2 & key->offmask);
                        __be32 *data, hdata;
 
-                       if (skb_headroom(skb) + toff > INT_MAX)
-                               goto out;
-
-                       data = skb_header_pointer(skb, toff, 4, &hdata);
+                       data = skb_header_pointer_careful(skb, toff, 4,
+                                                         &hdata);
                        if (!data)
                                goto out;
                        if ((*data ^ key->val) & key->mask) {
@@ -214,8 +212,9 @@ check_terminal:
                if (ht->divisor) {
                        __be32 *data, hdata;
 
-                       data = skb_header_pointer(skb, off + n->sel.hoff, 4,
-                                                 &hdata);
+                       data = skb_header_pointer_careful(skb,
+                                                         off + n->sel.hoff,
+                                                         4, &hdata);
                        if (!data)
                                goto out;
                        sel = ht->divisor & u32_hash_fold(*data, &n->sel,
@@ -229,7 +228,7 @@ check_terminal:
                        if (n->sel.flags & TC_U32_VAROFFSET) {
                                __be16 *data, hdata;
 
-                               data = skb_header_pointer(skb,
+                               data = skb_header_pointer_careful(skb,
                                                          off + n->sel.offoff,
                                                          2, &hdata);
                                if (!data)