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

Configure Feed

Select the types of activity you want to include in your feed.

bpf: net_sched: Disable attaching bpf qdisc to non root

Do not allow users to attach bpf qdiscs to classful qdiscs. This is to
prevent accidentally breaking existings classful qdiscs if they rely on
some data in the child qdisc. This restriction can potentially be lifted
in the future. Note that, we still allow bpf qdisc to be attached to mq.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20250409214606.2000194-7-ameryhung@gmail.com

authored by

Amery Hung and committed by
Martin KaFai Lau
e582778f 544e0a1f

+23 -2
+23 -2
net/sched/bpf_qdisc.c
··· 142 142 return 0; 143 143 144 144 /* r6 = r1; // r6 will be "u64 *ctx". r1 is "u64 *ctx". 145 + * r2 = r1[16]; // r2 will be "struct netlink_ext_ack *extack" 145 146 * r1 = r1[0]; // r1 will be "struct Qdisc *sch" 146 - * r0 = bpf_qdisc_init_prologue(r1); 147 + * r0 = bpf_qdisc_init_prologue(r1, r2); 148 + * if r0 == 0 goto pc+1; 149 + * BPF_EXIT; 147 150 * r1 = r6; // r1 will be "u64 *ctx". 148 151 */ 149 152 *insn++ = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); 153 + *insn++ = BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 16); 150 154 *insn++ = BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0); 151 155 *insn++ = BPF_CALL_KFUNC(0, bpf_qdisc_init_prologue_ids[0]); 156 + *insn++ = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1); 157 + *insn++ = BPF_EXIT_INSN(); 152 158 *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); 153 159 *insn++ = prog->insnsi[0]; 154 160 ··· 227 221 } 228 222 229 223 /* bpf_qdisc_init_prologue - Hidden kfunc called in prologue of .init. */ 230 - __bpf_kfunc void bpf_qdisc_init_prologue(struct Qdisc *sch) 224 + __bpf_kfunc int bpf_qdisc_init_prologue(struct Qdisc *sch, 225 + struct netlink_ext_ack *extack) 231 226 { 232 227 struct bpf_sched_data *q = qdisc_priv(sch); 228 + struct net_device *dev = qdisc_dev(sch); 229 + struct Qdisc *p; 230 + 231 + if (sch->parent != TC_H_ROOT) { 232 + p = qdisc_lookup(dev, TC_H_MAJ(sch->parent)); 233 + if (!p) 234 + return -ENOENT; 235 + 236 + if (!(p->flags & TCQ_F_MQROOT)) { 237 + NL_SET_ERR_MSG(extack, "BPF qdisc only supported on root or mq"); 238 + return -EINVAL; 239 + } 240 + } 233 241 234 242 qdisc_watchdog_init(&q->watchdog, sch); 243 + return 0; 235 244 } 236 245 237 246 /* bpf_qdisc_reset_destroy_epilogue - Hidden kfunc called in epilogue of .reset