linux/net/sched
Aldo Ariel Panzardo f43ee0c073 net/sched: serialize qdisc_rtab_list against concurrent get/put
qdisc_get_rtab() and qdisc_put_rtab() mutate the process-global singly
linked list qdisc_rtab_list and a plain non-atomic 'int refcnt' with no
lock. This was only safe because every caller historically held the RTNL
mutex, which serialized all rate-table lookups, inserts and frees.

That invariant no longer holds. cls_flower sets
TCF_PROTO_OPS_DOIT_UNLOCKED, so tc_new_tfilter() keeps rtnl_held == false
for it and sets TCA_ACT_FLAGS_NO_RTNL. That flag propagates through
tcf_exts_validate_ex() -> tcf_action_init() -> tcf_action_init_1() ->
tcf_police_init(), which calls qdisc_get_rtab()/qdisc_put_rtab() with the
RTNL mutex NOT held. Two RTM_NEWTFILTER requests on different CPUs, each
adding a flower filter with a police action carrying the same rate, then
race on qdisc_rtab_list and on the non-atomic refcnt, leading to a
use-after-free / double-free of the kmalloc-2k struct qdisc_rate_table.
qdisc_rtab_list is a single global (not per-netns), so the corrupted
object is shared system-wide.

  BUG: KASAN: slab-use-after-free in qdisc_put_rtab+0x12f/0x160
   qdisc_put_rtab+0x12f/0x160
   tcf_police_init+0xda9/0x1590
   tcf_action_init_1+0x460/0x6b0
   tcf_action_init+0x439/0xa40
   tcf_exts_validate_ex+0x42d/0x550
   fl_change+0xddd/0x7da0
   tc_new_tfilter+0xaa7/0x2420
   rtnetlink_rcv_msg+0x95e/0xe90
  which belongs to the cache kmalloc-2k of size 2048

Protect qdisc_rtab_list and the refcount with a dedicated spinlock. The
(sleeping, GFP_KERNEL) allocation in qdisc_get_rtab() is performed before
taking the lock; if a concurrent inserter added an identical table in the
meantime the freshly allocated one is freed under the lock, so no
duplicate is leaked. qdisc_put_rtab() now decrements the refcount and
unlinks under the same lock.

Fixes: 470502de5b ("net: sched: unlock rules update API")
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
Cc: stable@vger.kernel.org
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260715114114.446841-1-qwe.aldo@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-07-22 15:07:53 -07:00
..
act_api.c net/sched: act_pedit: fix TOCTOU heap OOB write in tc offload 2026-07-06 12:52:01 +02:00
act_bpf.c net/sched: act_bpf: use rcu_dereference_bh() to read the filter 2026-06-30 18:27:26 -07:00
act_connmark.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
act_csum.c net/sched: act_csum: don't mangle UDP tunnel GSO packets 2026-06-14 13:27:39 +02:00
act_ct.c net/sched: act_ct: fix nf_connlabels leak on two error paths 2026-06-21 15:00:47 -07:00
act_ctinfo.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
act_gact.c
act_gate.c net/sched: act_gate: snapshot parameters with RCU on replace 2026-02-27 16:10:36 -08:00
act_ife.c net/sched: add qstats_cpu_drop_inc() helper 2026-05-04 18:59:07 -07:00
act_meta_mark.c
act_meta_skbprio.c
act_meta_skbtcindex.c
act_mirred.c net/sched: act_mirred: Fix return code in early mirred redirect error paths 2026-05-28 12:26:36 +02:00
act_mpls.c net/sched: add qstats_cpu_drop_inc() helper 2026-05-04 18:59:07 -07:00
act_nat.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
act_pedit.c net/sched: act_pedit: fix TOCTOU heap OOB write in tc offload 2026-07-06 12:52:01 +02:00
act_police.c net/sched: add qstats_cpu_drop_inc() helper 2026-05-04 18:59:07 -07:00
act_sample.c
act_simple.c net/sched: Remove redundant memset(0) call in reset_policy() 2025-08-12 17:13:29 -07:00
act_skbedit.c net/sched: add qstats_cpu_drop_inc() helper 2026-05-04 18:59:07 -07:00
act_skbmod.c net/sched: rename qstats_overlimit_inc() to qstats_cpu_overlimit_inc() 2026-04-29 16:42:44 -07:00
act_tunnel_key.c net/sched: act_tunnel_key: Defer dst_release to RCU callback 2026-07-17 12:13:20 +02:00
act_vlan.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
bpf_qdisc.c bpf: net_sched: Use the correct destructor kfunc type 2026-01-12 18:53:57 -08:00
cls_api.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
cls_basic.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cls_bpf.c net/sched: cls_bpf: prevent unbounded recursion in offload rollback 2026-05-27 17:46:35 -07:00
cls_cgroup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cls_flow.c net/sched: cls_flow: Dont expose folded kernel pointers 2026-06-11 15:04:56 -07:00
cls_flower.c net/sched: cls_flower: revert unintended changes 2026-04-30 13:47:01 +02:00
cls_fw.c net/sched: cls_fw: fix NULL dereference of "old" filters before change() 2026-04-12 08:49:13 -07:00
cls_matchall.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cls_route.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cls_u32.c net: sched: cls_u32: Avoid memcpy() false-positive warning in u32_init_knode() 2026-03-10 19:39:35 -07:00
em_canid.c net/sched: em_canid: fix uninit-value in em_canid_match 2025-11-26 16:28:10 +01:00
em_cmp.c net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr() 2025-11-24 18:53:14 -08:00
em_ipset.c
em_ipt.c
em_meta.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
em_nbyte.c net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr() 2025-11-24 18:53:14 -08:00
em_text.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
em_u32.c
ematch.c
Kconfig sched: Add enqueue/dequeue of dualpi2 qdisc 2025-07-23 17:52:07 -07:00
Makefile sched: Add enqueue/dequeue of dualpi2 qdisc 2025-07-23 17:52:07 -07:00
sch_api.c net/sched: serialize qdisc_rtab_list against concurrent get/put 2026-07-22 15:07:53 -07:00
sch_blackhole.c
sch_cake.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_cbs.c net: sched: avoid printing uninitialized link speed 2026-06-11 15:44:55 +02:00
sch_choke.c net/sched: add qdisc_qlen_inc() and qdisc_qlen_dec() 2026-05-11 18:28:07 -07:00
sch_codel.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-06-16 14:59:58 -07:00
sch_drr.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_dualpi2.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_etf.c net/sched: add qdisc_qlen_inc() and qdisc_qlen_dec() 2026-05-11 18:28:07 -07:00
sch_ets.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_fifo.c pfifo_tail_enqueue: Drop new packet when sch->limit == 0 2025-02-05 18:13:58 -08:00
sch_fq_codel.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_fq_pie.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_fq.c net_sched: sch_fq: convert skb->tstamp if not monotonic 2026-06-08 16:00:06 -07:00
sch_frag.c net: convert remaining ipv6_stub users to direct function calls 2026-03-29 11:21:23 -07:00
sch_generic.c net: do not acquire dev->tx_global_lock in netdev_watchdog_up() 2026-06-23 14:40:33 -07:00
sch_gred.c net/sched: annotate data-races around sch->qstats.backlog 2026-05-11 18:28:07 -07:00
sch_hfsc.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_hhf.c net/sched: hhf: clear heavy-hitter state on reset 2026-07-01 09:09:38 +01:00
sch_htb.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_ingress.c clsact: Fix use-after-free in init/destroy rollback asymmetry 2026-03-17 12:09:16 +01:00
sch_mq.c net/sched: mq: no longer acquire qdisc spinlocks in dump operations 2026-05-11 18:28:08 -07:00
sch_mqprio_lib.c
sch_mqprio_lib.h
sch_mqprio.c net/sched: mq_prio: no longer acquire qdisc spinlocks in mqprio_dump_class_stats() 2026-05-11 18:28:08 -07:00
sch_multiq.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_netem.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-05-28 14:02:21 -07:00
sch_pie.c net/sched: sch_pie: annotate more data-races in pie_dump_stats() 2026-05-01 17:54:57 -07:00
sch_plug.c
sch_prio.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_qfq.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_red.c net/sched: annotate data-races around sch->qstats.backlog 2026-05-11 18:28:07 -07:00
sch_sfb.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_sfq.c net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains 2026-07-20 18:16:43 -07:00
sch_skbprio.c net/sched: add qdisc_qlen_inc() and qdisc_qlen_dec() 2026-05-11 18:28:07 -07:00
sch_taprio.c net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked 2026-06-26 18:52:26 -07:00
sch_tbf.c net/sched: tbf: add extack to offload params 2026-05-22 17:23:37 -07:00
sch_teql.c net/sched: sch_teql: move rcu_read_lock()/spin_lock() from _bh variants 2026-07-03 16:02:38 +02:00