]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/sched: cls_u32: skip hash tables in u32_bind_class()
authorZhang Changzhong <zhangchangzhong@huawei.com>
Fri, 7 Aug 2026 07:50:38 +0000 (15:50 +0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 12 Aug 2026 01:28:43 +0000 (18:28 -0700)
u32_walk() enumerates both struct tc_u_hnode and struct tc_u_knode
through the walker callback. u32_bind_class() unconditionally casts the
passed fh to tc_u_knode and accesses &n->res, so when fh is actually a
tc_u_hnode, which has no tcf_result member, this results in a
slab-out-of-bounds read of res->classid in tc_cls_bind_class().

The issue can be reproduced with the following commands:

    tc qdisc add dev lo root handle 1: hfsc
    tc class add dev lo parent 1: classid 1:1 hfsc sc rate 1000kbit
    tc filter add dev lo parent 1:1 protocol ip prio 1 u32 match u32 0 0 flowid 1:1
    tc class add dev lo parent 1: classid 1:2 hfsc sc rate 2000kbit

Fix this by skipping hash tables via the TC_U32_KEY(handle) check.

Fixes: 07d79fc7d94e ("net_sched: add reverse binding for tc class")
Signed-off-by: Zhang Changzhong <zhangchangzhong@huawei.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/1786089038-36366-1-git-send-email-zhangchangzhong@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sched/cls_u32.c

index ac98b1c2144a7821861b7459816704a556f74ae8..c297d7dbcf916369e50847b3e56e6ffea3e18373 100644 (file)
@@ -1346,6 +1346,9 @@ static void u32_bind_class(void *fh, u32 classid, unsigned long cl, void *q,
 {
        struct tc_u_knode *n = fh;
 
+       if (TC_U32_KEY(n->handle) == 0)
+               return;
+
        tc_cls_bind_class(classid, cl, q, &n->res, base);
 }