Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/sched: cls_u32: use skb_header_pointer_careful()

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>

authored by

Eric Dumazet and committed by
Jakub Kicinski
cabd1a97 13e00fdc

+6 -7
+6 -7
net/sched/cls_u32.c
··· 161 161 int toff = off + key->off + (off2 & key->offmask); 162 162 __be32 *data, hdata; 163 163 164 - if (skb_headroom(skb) + toff > INT_MAX) 165 - goto out; 166 - 167 - data = skb_header_pointer(skb, toff, 4, &hdata); 164 + data = skb_header_pointer_careful(skb, toff, 4, 165 + &hdata); 168 166 if (!data) 169 167 goto out; 170 168 if ((*data ^ key->val) & key->mask) { ··· 212 214 if (ht->divisor) { 213 215 __be32 *data, hdata; 214 216 215 - data = skb_header_pointer(skb, off + n->sel.hoff, 4, 216 - &hdata); 217 + data = skb_header_pointer_careful(skb, 218 + off + n->sel.hoff, 219 + 4, &hdata); 217 220 if (!data) 218 221 goto out; 219 222 sel = ht->divisor & u32_hash_fold(*data, &n->sel, ··· 228 229 if (n->sel.flags & TC_U32_VAROFFSET) { 229 230 __be16 *data, hdata; 230 231 231 - data = skb_header_pointer(skb, 232 + data = skb_header_pointer_careful(skb, 232 233 off + n->sel.offoff, 233 234 2, &hdata); 234 235 if (!data)