Commit 3505cb9f authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov
Browse files

bpf: Add attach_type checks under bpf_prog_attach_check_attach_type



Add extra attach_type checks from link_create under
bpf_prog_attach_check_attach_type.

Suggested-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarYafang Shao <laoar.shao@gmail.com>
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20230809083440.3209381-3-jolsa@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent c5487f8d
Loading
Loading
Loading
Loading
+52 −68
Original line number Diff line number Diff line
@@ -3655,34 +3655,6 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
	return fd;
}

static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
					     enum bpf_attach_type attach_type)
{
	switch (prog->type) {
	case BPF_PROG_TYPE_CGROUP_SOCK:
	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
	case BPF_PROG_TYPE_CGROUP_SOCKOPT:
	case BPF_PROG_TYPE_SK_LOOKUP:
		return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
	case BPF_PROG_TYPE_CGROUP_SKB:
		if (!capable(CAP_NET_ADMIN))
			/* cg-skb progs can be loaded by unpriv user.
			 * check permissions at attach time.
			 */
			return -EPERM;
		return prog->enforce_expected_attach_type &&
			prog->expected_attach_type != attach_type ?
			-EINVAL : 0;
	case BPF_PROG_TYPE_KPROBE:
		if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
		    attach_type != BPF_TRACE_KPROBE_MULTI)
			return -EINVAL;
		return 0;
	default:
		return 0;
	}
}

static enum bpf_prog_type
attach_type_to_prog_type(enum bpf_attach_type attach_type)
{
@@ -3749,6 +3721,58 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
	}
}

static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
					     enum bpf_attach_type attach_type)
{
	enum bpf_prog_type ptype;

	switch (prog->type) {
	case BPF_PROG_TYPE_CGROUP_SOCK:
	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
	case BPF_PROG_TYPE_CGROUP_SOCKOPT:
	case BPF_PROG_TYPE_SK_LOOKUP:
		return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
	case BPF_PROG_TYPE_CGROUP_SKB:
		if (!capable(CAP_NET_ADMIN))
			/* cg-skb progs can be loaded by unpriv user.
			 * check permissions at attach time.
			 */
			return -EPERM;
		return prog->enforce_expected_attach_type &&
			prog->expected_attach_type != attach_type ?
			-EINVAL : 0;
	case BPF_PROG_TYPE_EXT:
		return 0;
	case BPF_PROG_TYPE_NETFILTER:
		if (attach_type != BPF_NETFILTER)
			return -EINVAL;
		return 0;
	case BPF_PROG_TYPE_PERF_EVENT:
	case BPF_PROG_TYPE_TRACEPOINT:
		if (attach_type != BPF_PERF_EVENT)
			return -EINVAL;
		return 0;
	case BPF_PROG_TYPE_KPROBE:
		if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
		    attach_type != BPF_TRACE_KPROBE_MULTI)
			return -EINVAL;
		if (attach_type != BPF_PERF_EVENT &&
		    attach_type != BPF_TRACE_KPROBE_MULTI)
			return -EINVAL;
		return 0;
	case BPF_PROG_TYPE_SCHED_CLS:
		if (attach_type != BPF_TCX_INGRESS &&
		    attach_type != BPF_TCX_EGRESS)
			return -EINVAL;
		return 0;
	default:
		ptype = attach_type_to_prog_type(attach_type);
		if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type)
			return -EINVAL;
		return 0;
	}
}

#define BPF_PROG_ATTACH_LAST_FIELD expected_revision

#define BPF_F_ATTACH_MASK_BASE	\
@@ -4855,7 +4879,6 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
#define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
static int link_create(union bpf_attr *attr, bpfptr_t uattr)
{
	enum bpf_prog_type ptype;
	struct bpf_prog *prog;
	int ret;

@@ -4874,45 +4897,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
	if (ret)
		goto out;

	switch (prog->type) {
	case BPF_PROG_TYPE_EXT:
		break;
	case BPF_PROG_TYPE_NETFILTER:
		if (attr->link_create.attach_type != BPF_NETFILTER) {
			ret = -EINVAL;
			goto out;
		}
		break;
	case BPF_PROG_TYPE_PERF_EVENT:
	case BPF_PROG_TYPE_TRACEPOINT:
		if (attr->link_create.attach_type != BPF_PERF_EVENT) {
			ret = -EINVAL;
			goto out;
		}
		break;
	case BPF_PROG_TYPE_KPROBE:
		if (attr->link_create.attach_type != BPF_PERF_EVENT &&
		    attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI) {
			ret = -EINVAL;
			goto out;
		}
		break;
	case BPF_PROG_TYPE_SCHED_CLS:
		if (attr->link_create.attach_type != BPF_TCX_INGRESS &&
		    attr->link_create.attach_type != BPF_TCX_EGRESS) {
			ret = -EINVAL;
			goto out;
		}
		break;
	default:
		ptype = attach_type_to_prog_type(attr->link_create.attach_type);
		if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
			ret = -EINVAL;
			goto out;
		}
		break;
	}

	switch (prog->type) {
	case BPF_PROG_TYPE_CGROUP_SKB:
	case BPF_PROG_TYPE_CGROUP_SOCK: