Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -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)
{
{
+29 −4
Original line number Original line Diff line number Diff line
@@ -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 @@ 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)
}
}
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


+5 −1
Original line number Original line Diff line number Diff line
@@ -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);