[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGfirfebdHJi13epyM5RWYfQ2TGSWExP5nmnoKra83awetAbLQ@mail.gmail.com>
Date: Mon, 26 Jan 2026 21:11:46 +0900
From: 김강민 <km.kim1503@...il.com>
To: Eric Dumazet <edumazet@...gle.com>
Cc: davem@...emloft.net, Jamal Hadi Salim <jhs@...atatu.com>, jiri@...nulli.us,
kuba@...nel.org, netdev@...r.kernel.org, pabeni@...hat.com,
xiyou.wangcong@...il.com, horms@...nel.org, syzkaller@...glegroups.com,
linux-kernel@...r.kernel.org
Subject: Re: [BUG] KASAN: slab-use-after-free Read in u32_classify
I propose the following patch and would appreciate your review.
hoff is used as an offset argument to skb_header_pointer() in
u32_classify(), and negative values can cause out-of-bounds read. As
shown in the code below, offoff follows the same pattern and requires
the same validation.
```
TC_INDIRECT_SCOPE int u32_classify(struct sk_buff *skb,
const struct tcf_proto *tp,
struct tcf_result *res)
{
...
if (n) {
...
if (n->sel.flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) {
off2 = n->sel.off + 3;
if (n->sel.flags & TC_U32_VAROFFSET) {
__be16 *data, hdata;
data = skb_header_pointer(skb,
off + n->sel.offoff,
2, &hdata);
if (!data)
goto out;
off2 += ntohs(n->sel.offmask & *data) >>
n->sel.offshift;
}
off2 &= ~3;
}
...
}
...
}
```
Therefore, I propose a patch that rejects negative hoff and offoff
values during u32 classifier configuration.
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -1104,6 +1104,11 @@ static int u32_change(struct net *net, struct
sk_buff *in_skb,
err = -EINVAL;
goto erridr;
}
+
+ if (s->hoff < 0 || s->offoff < 0) {
+ err = -EINVAL;
+ goto erridr;
+ }
n = kzalloc(struct_size(n, sel.keys, s->nkeys), GFP_KERNEL);
if (n == NULL) {
2026년 1월 26일 (월) PM 8:22, Eric Dumazet <edumazet@...gle.com>님이 작성:
>
> On Mon, Jan 26, 2026 at 10:51 AM Eric Dumazet <edumazet@...gle.com> wrote:
> >
> > On Mon, Jan 26, 2026 at 5:30 AM 김강민 <km.kim1503@...il.com> wrote:
> > >
> > > Apologies, I set the wrong title and KASAN report. The root cause is
> > > out-of-bounds, not use-after-free. Please find the correct KASAN
> > > report below.
> >
> > This is great, do you have a patch to fix the issue and get full
> > credit on the resolution ?
> >
> > Thank you
>
> Brute force patch is a bit expensive.
>
> I think we should instead add new helpers when the offset can be user
> controlled.
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 86737076101d4a8452e90fe78adcdcfdefb79169..1ad8a3e17b995f5b934dfa21448580de4f201acd
> 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -4285,8 +4285,13 @@ static inline void * __must_check
> __skb_header_pointer(const struct sk_buff *skb, int offset, int len,
> const void *data, int hlen, void *buffer)
> {
> - if (likely(hlen - offset >= len))
> - return (void *)data + offset;
> + if (likely(hlen - offset >= len)) {
> + unsigned char *ptr = (unsigned char *)data + offset;
> +
> + if (skb && unlikely(ptr < skb->head))
> + return NULL;
> + return ptr;
> + }
>
>
> scripts/bloat-o-meter -t vmlinux.old vmlinux
> add/remove: 2/0 grow/shrink: 56/1 up/down: 2539/-6 (2533)
> Function old new delta
> __skb_flow_dissect 7661 8315 +654
> ipv6_find_hdr 1005 1127 +122
> br_multicast_rcv 7973 8077 +104
> ip_tunnel_xmit 2635 2719 +84
> __skb_header_pointer - 82 +82
> ipv6_skip_exthdr 428 505 +77
>
>
> if (!skb || unlikely(skb_copy_bits(skb, offset, buffer, len) < 0))
> return NULL;
Powered by blists - more mailing lists