xdp: allow attaching programs loaded for specific device
Pass the netdev pointer to bpf_prog_get_type(). This way BPF code can decide whether the device matches what the code was loaded/translated for. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
928631e054
commit
248f346ffe
|
@ -335,6 +335,8 @@ extern const struct bpf_verifier_ops xdp_analyzer_ops;
|
||||||
|
|
||||||
struct bpf_prog *bpf_prog_get(u32 ufd);
|
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(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 * __must_check bpf_prog_add(struct bpf_prog *prog, int i);
|
struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i);
|
||||||
void bpf_prog_sub(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(struct bpf_prog *prog);
|
||||||
|
@ -428,6 +430,14 @@ static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
|
||||||
{
|
{
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct bpf_prog *bpf_prog_get_type_dev(u32 ufd,
|
||||||
|
enum bpf_prog_type type,
|
||||||
|
struct net_device *netdev)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog,
|
static inline struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog,
|
||||||
int i)
|
int i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1057,7 +1057,22 @@ struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
|
EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
|
||||||
|
|
||||||
static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type)
|
static bool bpf_prog_can_attach(struct bpf_prog *prog,
|
||||||
|
enum bpf_prog_type *attach_type,
|
||||||
|
struct net_device *netdev)
|
||||||
|
{
|
||||||
|
struct bpf_dev_offload *offload = prog->aux->offload;
|
||||||
|
|
||||||
|
if (prog->type != *attach_type)
|
||||||
|
return false;
|
||||||
|
if (offload && offload->netdev != 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 fd f = fdget(ufd);
|
struct fd f = fdget(ufd);
|
||||||
struct bpf_prog *prog;
|
struct bpf_prog *prog;
|
||||||
|
@ -1065,7 +1080,7 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type)
|
||||||
prog = ____bpf_prog_get(f);
|
prog = ____bpf_prog_get(f);
|
||||||
if (IS_ERR(prog))
|
if (IS_ERR(prog))
|
||||||
return prog;
|
return prog;
|
||||||
if (attach_type && (prog->type != *attach_type || prog->aux->offload)) {
|
if (attach_type && !bpf_prog_can_attach(prog, attach_type, netdev)) {
|
||||||
prog = ERR_PTR(-EINVAL);
|
prog = ERR_PTR(-EINVAL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1078,12 +1093,12 @@ out:
|
||||||
|
|
||||||
struct bpf_prog *bpf_prog_get(u32 ufd)
|
struct bpf_prog *bpf_prog_get(u32 ufd)
|
||||||
{
|
{
|
||||||
return __bpf_prog_get(ufd, NULL);
|
return __bpf_prog_get(ufd, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
|
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
|
||||||
{
|
{
|
||||||
struct bpf_prog *prog = __bpf_prog_get(ufd, &type);
|
struct bpf_prog *prog = __bpf_prog_get(ufd, &type, NULL);
|
||||||
|
|
||||||
if (!IS_ERR(prog))
|
if (!IS_ERR(prog))
|
||||||
trace_bpf_prog_get_type(prog);
|
trace_bpf_prog_get_type(prog);
|
||||||
|
@ -1091,6 +1106,16 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bpf_prog_get_type);
|
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);
|
||||||
|
|
||||||
|
if (!IS_ERR(prog))
|
||||||
|
trace_bpf_prog_get_type(prog);
|
||||||
|
return prog;
|
||||||
|
}
|
||||||
|
|
||||||
/* last field in 'union bpf_attr' used by this command */
|
/* last field in 'union bpf_attr' used by this command */
|
||||||
#define BPF_PROG_LOAD_LAST_FIELD prog_target_ifindex
|
#define BPF_PROG_LOAD_LAST_FIELD prog_target_ifindex
|
||||||
|
|
||||||
|
|
|
@ -7157,7 +7157,11 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
|
||||||
__dev_xdp_attached(dev, bpf_op, NULL))
|
__dev_xdp_attached(dev, bpf_op, NULL))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
|
if (bpf_op == ops->ndo_bpf)
|
||||||
|
prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,
|
||||||
|
dev);
|
||||||
|
else
|
||||||
|
prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
|
||||||
if (IS_ERR(prog))
|
if (IS_ERR(prog))
|
||||||
return PTR_ERR(prog);
|
return PTR_ERR(prog);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue