Re: [PATCH net] net/sched: cls_bpf: reject dev-bound programs bound to a different device
Jamal Hadi Salim <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.kernel.vger.bpf,org.kernel.vger.netdev |
|---|---|
| Message-ID | <CAM0EoMm0xj=R4c+3yoBJyEDgNAmsaCospYT9jxVTTihJzSnvPg@mail.gmail.com> |
On Sun, Aug 9, 2026 at 5:44 AM Jamal Hadi Salim <[email protected]> wrote: > > cls_bpf_prog_from_efd() obtained a SCHED_CLS program via > bpf_prog_get_type_dev() but never verified that a device-bound (offloaded) > program's bound netdev matches the TC netdev the classifier is being > attached to. This let a program loaded with prog_ifindex for device A be > attached via cls_bpf + skip_sw to device B; deleting device A then > destroyed the program's offload state while it was still attached to > device B, triggering a netdevsim WARN (panic with panic_on_warn=1). > > Mirror the XDP attach path (net/core/dev.c) and reject the attach with > -EINVAL when a dev-bound program's bound device does not match the > target device. > > Fixes: 6c8dfe21c435 ("cls_bpf: allow attaching programs loaded for specific device") Fixes: 2b3486bc2d23 ("bpf: Introduce device-bound XDP programs") cheers, jamal > Reported-by: [email protected] > Tested-by: Victor Nogueira <[email protected]> > Signed-off-by: Jamal Hadi Salim <[email protected]> > --- > net/sched/cls_bpf.c | 18 ++++++++++++++++-- > 1 file changed, 16 insertions(+), 2 deletions(-) > > diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c > index 001d8c4ebfed..6d19155becc8 100644 > --- a/net/sched/cls_bpf.c > +++ b/net/sched/cls_bpf.c > @@ -374,7 +374,8 @@ static int cls_bpf_prog_from_ops(struct nlattr **tb, struct cls_bpf_prog *prog) > } > > static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, > - u32 gen_flags, const struct tcf_proto *tp) > + u32 gen_flags, const struct tcf_proto *tp, > + struct netlink_ext_ack *extack) > { > struct bpf_prog *fp; > char *name = NULL; > @@ -388,6 +389,19 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, > if (IS_ERR(fp)) > return PTR_ERR(fp); > > + if (bpf_prog_is_dev_bound(fp->aux)) { > + struct tcf_block *block = tp->chain->block; > + struct net_device *dev; > + > + dev = block->q ? qdisc_dev(block->q) : NULL; > + if (!dev || !bpf_offload_dev_match(fp, dev)) { > + NL_SET_ERR_MSG(extack, > + "Program is bound to a different device"); > + bpf_prog_put(fp); > + return -EINVAL; > + } > + } > + > if (tb[TCA_BPF_NAME]) { > name = nla_memdup(tb[TCA_BPF_NAME], GFP_KERNEL); > if (!name) { > @@ -492,7 +506,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, > prog->gen_flags = gen_flags; > > ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) : > - cls_bpf_prog_from_efd(tb, prog, gen_flags, tp); > + cls_bpf_prog_from_efd(tb, prog, gen_flags, tp, extack); > if (ret < 0) > goto errout_idr; > > -- > 2.34.1 >