]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: sched: sfb: fix null pointer access issue when sfb_init() fails
authorZhengchao Shao <shaozhengchao@huawei.com>
Tue, 18 Oct 2022 06:32:01 +0000 (14:32 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Oct 2022 12:47:09 +0000 (13:47 +0100)
When the default qdisc is sfb, if the qdisc of dev_queue fails to be
inited during mqprio_init(), sfb_reset() is invoked to clear resources.
In this case, the q->qdisc is NULL, and it will cause gpf issue.

The process is as follows:
qdisc_create_dflt()
sfb_init()
tcf_block_get()          --->failed, q->qdisc is NULL
...
qdisc_put()
...
sfb_reset()
qdisc_reset(q->qdisc)    --->q->qdisc is NULL
ops = qdisc->ops

The following is the Call Trace information:
general protection fault, probably for non-canonical address
0xdffffc0000000003: 0000 [#1] PREEMPT SMP KASAN
KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
RIP: 0010:qdisc_reset+0x2b/0x6f0
Call Trace:
<TASK>
sfb_reset+0x37/0xd0
qdisc_reset+0xed/0x6f0
qdisc_destroy+0x82/0x4c0
qdisc_put+0x9e/0xb0
qdisc_create_dflt+0x2c3/0x4a0
mqprio_init+0xa71/0x1760
qdisc_create+0x3eb/0x1000
tc_modify_qdisc+0x408/0x1720
rtnetlink_rcv_msg+0x38e/0xac0
netlink_rcv_skb+0x12d/0x3a0
netlink_unicast+0x4a2/0x740
netlink_sendmsg+0x826/0xcc0
sock_sendmsg+0xc5/0x100
____sys_sendmsg+0x583/0x690
___sys_sendmsg+0xe8/0x160
__sys_sendmsg+0xbf/0x160
do_syscall_64+0x35/0x80
entry_SYSCALL_64_after_hwframe+0x46/0xb0
RIP: 0033:0x7f2164122d04
</TASK>

Fixes: e23ae3556fed ("net_sched: SFB flow scheduler")
Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/sch_sfb.c

index e2389fa3cff8ac5ead731335e06fa9acff8b8ef4..73ae2e726512ad645c0c08962343446823cb7250 100644 (file)
@@ -455,7 +455,8 @@ static void sfb_reset(struct Qdisc *sch)
 {
        struct sfb_sched_data *q = qdisc_priv(sch);
 
-       qdisc_reset(q->qdisc);
+       if (likely(q->qdisc))
+               qdisc_reset(q->qdisc);
        q->slot = 0;
        q->double_buffering = false;
        sfb_zero_all_buckets(q);