Commit 118c8e9a authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Daniel Borkmann
Browse files

bpf: support BPF_PROG_QUERY for BPF_FLOW_DISSECTOR attach_type



target_fd is target namespace. If there is a flow dissector BPF program
attached to that namespace, its (single) id is returned.

v5:
* drop net ref right after rcu unlock (Daniel Borkmann)

v4:
* add missing put_net (Jann Horn)

v3:
* add missing inline to skb_flow_dissector_prog_query static def
  (kbuild test robot <lkp@intel.com>)

v2:
* don't sleep in rcu critical section (Jakub Kicinski)
* check input prog_cnt (exit early)

Cc: Jann Horn <jannh@google.com>
Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent ead442a0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1258,11 +1258,19 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
			     unsigned int key_count);

#ifdef CONFIG_NET
int skb_flow_dissector_prog_query(const union bpf_attr *attr,
				  union bpf_attr __user *uattr);
int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
				       struct bpf_prog *prog);

int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr);
#else
static inline int skb_flow_dissector_prog_query(const union bpf_attr *attr,
						union bpf_attr __user *uattr)
{
	return -EOPNOTSUPP;
}

static inline int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
						     struct bpf_prog *prog)
{
+2 −0
Original line number Diff line number Diff line
@@ -2009,6 +2009,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
		break;
	case BPF_LIRC_MODE2:
		return lirc_prog_query(attr, uattr);
	case BPF_FLOW_DISSECTOR:
		return skb_flow_dissector_prog_query(attr, uattr);
	default:
		return -EINVAL;
	}
+39 −0
Original line number Diff line number Diff line
@@ -65,6 +65,45 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
}
EXPORT_SYMBOL(skb_flow_dissector_init);

int skb_flow_dissector_prog_query(const union bpf_attr *attr,
				  union bpf_attr __user *uattr)
{
	__u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
	u32 prog_id, prog_cnt = 0, flags = 0;
	struct bpf_prog *attached;
	struct net *net;

	if (attr->query.query_flags)
		return -EINVAL;

	net = get_net_ns_by_fd(attr->query.target_fd);
	if (IS_ERR(net))
		return PTR_ERR(net);

	rcu_read_lock();
	attached = rcu_dereference(net->flow_dissector_prog);
	if (attached) {
		prog_cnt = 1;
		prog_id = attached->aux->id;
	}
	rcu_read_unlock();

	put_net(net);

	if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
		return -EFAULT;
	if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
		return -EFAULT;

	if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
		return 0;

	if (copy_to_user(prog_ids, &prog_id, sizeof(u32)))
		return -EFAULT;

	return 0;
}

int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
				       struct bpf_prog *prog)
{