From: Jiri Pirko <j...@mellanox.com> In order to remove tp->q usage in cls_bpf, the offload->netdev check needs to be moved to individual drivers as only they will have access to appropriate struct net_device.
Signed-off-by: Jiri Pirko <j...@mellanox.com> --- drivers/net/ethernet/netronome/nfp/bpf/main.c | 2 ++ include/linux/bpf.h | 16 +++++++++++ kernel/bpf/syscall.c | 39 +++++++++++++++++++++------ net/sched/cls_bpf.c | 6 +---- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index e379b78..c303e08 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c @@ -102,6 +102,8 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type, return -EOPNOTSUPP; if (nn->dp.bpf_offload_xdp) return -EBUSY; + if (!bpf_prog_can_attach_netdev(cls_bpf->prog, nn->dp.netdev)) + return -EINVAL; /* Only support TC direct action */ if (!cls_bpf->exts_integrated || diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c397934..df7b7bc 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -337,10 +337,14 @@ struct bpf_prog *bpf_prog_get(u32 ufd); struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type); struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type, struct net_device *netdev); +struct bpf_prog *bpf_prog_get_type_dev_nocheck(u32 ufd, + enum bpf_prog_type type); struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i); void bpf_prog_sub(struct bpf_prog *prog, int i); struct bpf_prog * __must_check bpf_prog_inc(struct bpf_prog *prog); struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog); +bool bpf_prog_can_attach_netdev(struct bpf_prog *prog, + struct net_device *netdev); void bpf_prog_put(struct bpf_prog *prog); int __bpf_prog_charge(struct user_struct *user, u32 pages); void __bpf_prog_uncharge(struct user_struct *user, u32 pages); @@ -438,6 +442,12 @@ static inline struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, return ERR_PTR(-EOPNOTSUPP); } +static inline struct bpf_prog * +bpf_prog_get_type_dev_nocheck(u32 ufd, enum bpf_prog_type type) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i) { @@ -463,6 +473,12 @@ bpf_prog_inc_not_zero(struct bpf_prog *prog) return ERR_PTR(-EOPNOTSUPP); } +static inline bool bpf_prog_can_attach_netdev(struct bpf_prog *prog, + struct net_device *netdev) +{ + return true; +} + static inline int __bpf_prog_charge(struct user_struct *user, u32 pages) { return 0; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 09badc3..d880038 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1057,22 +1057,33 @@ struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog) } EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero); -static bool bpf_prog_can_attach(struct bpf_prog *prog, - enum bpf_prog_type *attach_type, +bool bpf_prog_can_attach_netdev(struct bpf_prog *prog, struct net_device *netdev) { struct bpf_dev_offload *offload = prog->aux->offload; + if (offload && offload->netdev != netdev) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(bpf_prog_can_attach_netdev); + +static bool bpf_prog_can_attach(struct bpf_prog *prog, + enum bpf_prog_type *attach_type, + struct net_device *netdev, bool check_netdev) +{ if (prog->type != *attach_type) return false; - if (offload && offload->netdev != netdev) + if (check_netdev && !bpf_prog_can_attach_netdev(prog, netdev)) return false; return true; } static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type, - struct net_device *netdev) + struct net_device *netdev, + bool check_netdev) { struct fd f = fdget(ufd); struct bpf_prog *prog; @@ -1080,7 +1091,8 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type, prog = ____bpf_prog_get(f); if (IS_ERR(prog)) return prog; - if (attach_type && !bpf_prog_can_attach(prog, attach_type, netdev)) { + if (attach_type && !bpf_prog_can_attach(prog, attach_type, + netdev, check_netdev)) { prog = ERR_PTR(-EINVAL); goto out; } @@ -1093,12 +1105,12 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type, struct bpf_prog *bpf_prog_get(u32 ufd) { - return __bpf_prog_get(ufd, NULL, NULL); + return __bpf_prog_get(ufd, NULL, NULL, true); } struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type) { - struct bpf_prog *prog = __bpf_prog_get(ufd, &type, NULL); + struct bpf_prog *prog = __bpf_prog_get(ufd, &type, NULL, true); if (!IS_ERR(prog)) trace_bpf_prog_get_type(prog); @@ -1109,7 +1121,7 @@ EXPORT_SYMBOL_GPL(bpf_prog_get_type); struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type, struct net_device *netdev) { - struct bpf_prog *prog = __bpf_prog_get(ufd, &type, netdev); + struct bpf_prog *prog = __bpf_prog_get(ufd, &type, netdev, true); if (!IS_ERR(prog)) trace_bpf_prog_get_type(prog); @@ -1117,6 +1129,17 @@ struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type, } EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev); +struct bpf_prog *bpf_prog_get_type_dev_nocheck(u32 ufd, + enum bpf_prog_type type) +{ + struct bpf_prog *prog = __bpf_prog_get(ufd, &type, NULL, false); + + if (!IS_ERR(prog)) + trace_bpf_prog_get_type(prog); + return prog; +} +EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev_nocheck); + /* last field in 'union bpf_attr' used by this command */ #define BPF_PROG_LOAD_LAST_FIELD prog_target_ifindex diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index fb680da..8b3927b 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -386,11 +386,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, bpf_fd = nla_get_u32(tb[TCA_BPF_FD]); - if (gen_flags & TCA_CLS_FLAGS_SKIP_SW) - fp = bpf_prog_get_type_dev(bpf_fd, BPF_PROG_TYPE_SCHED_CLS, - qdisc_dev(tp->q)); - else - fp = bpf_prog_get_type(bpf_fd, BPF_PROG_TYPE_SCHED_CLS); + fp = bpf_prog_get_type_dev_nocheck(bpf_fd, BPF_PROG_TYPE_SCHED_CLS); if (IS_ERR(fp)) return PTR_ERR(fp); -- 2.9.5