Commit 248f346f authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 928631e0
...@@ -335,6 +335,8 @@ extern const struct bpf_verifier_ops xdp_analyzer_ops; ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type) ...@@ -1078,12 +1093,12 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type)
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) ...@@ -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,6 +7157,10 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, ...@@ -7157,6 +7157,10 @@ 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;
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); 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment