Commit df86ca0d authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Daniel Borkmann

bpf: Allow attach TRACING programs through LINK_CREATE command

Allow attaching BTF-aware TRACING programs, previously attachable only
through BPF_RAW_TRACEPOINT_OPEN command, through LINK_CREATE command:

  - BTF-aware raw tracepoints (tp_btf in libbpf lingo);
  - fentry/fexit/fmod_ret programs;
  - BPF LSM programs.

This change converges all bpf_link-based attachments under LINK_CREATE
command allowing to further extend the API with features like BPF cookie
under "multiplexed" link_create section of bpf_attr.

Non-BTF-aware raw tracepoints are left under BPF_RAW_TRACEPOINT_OPEN,
but there is nothing preventing opening them up to LINK_CREATE as well.
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: default avatarKuifeng Lee <kuifeng@fb.com>
Link: https://lore.kernel.org/bpf/20220421033945.3602803-2-andrii@kernel.org
parent e8c5e1a0
...@@ -3030,66 +3030,45 @@ static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *pro ...@@ -3030,66 +3030,45 @@ static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *pro
} }
#endif /* CONFIG_PERF_EVENTS */ #endif /* CONFIG_PERF_EVENTS */
#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd static int bpf_raw_tp_link_attach(struct bpf_prog *prog,
const char __user *user_tp_name)
static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
{ {
struct bpf_link_primer link_primer; struct bpf_link_primer link_primer;
struct bpf_raw_tp_link *link; struct bpf_raw_tp_link *link;
struct bpf_raw_event_map *btp; struct bpf_raw_event_map *btp;
struct bpf_prog *prog;
const char *tp_name; const char *tp_name;
char buf[128]; char buf[128];
int err; int err;
if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
return -EINVAL;
prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
if (IS_ERR(prog))
return PTR_ERR(prog);
switch (prog->type) { switch (prog->type) {
case BPF_PROG_TYPE_TRACING: case BPF_PROG_TYPE_TRACING:
case BPF_PROG_TYPE_EXT: case BPF_PROG_TYPE_EXT:
case BPF_PROG_TYPE_LSM: case BPF_PROG_TYPE_LSM:
if (attr->raw_tracepoint.name) { if (user_tp_name)
/* The attach point for this category of programs /* The attach point for this category of programs
* should be specified via btf_id during program load. * should be specified via btf_id during program load.
*/ */
err = -EINVAL; return -EINVAL;
goto out_put_prog;
}
if (prog->type == BPF_PROG_TYPE_TRACING && if (prog->type == BPF_PROG_TYPE_TRACING &&
prog->expected_attach_type == BPF_TRACE_RAW_TP) { prog->expected_attach_type == BPF_TRACE_RAW_TP) {
tp_name = prog->aux->attach_func_name; tp_name = prog->aux->attach_func_name;
break; break;
} }
err = bpf_tracing_prog_attach(prog, 0, 0); return bpf_tracing_prog_attach(prog, 0, 0);
if (err >= 0)
return err;
goto out_put_prog;
case BPF_PROG_TYPE_RAW_TRACEPOINT: case BPF_PROG_TYPE_RAW_TRACEPOINT:
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE: case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
if (strncpy_from_user(buf, if (strncpy_from_user(buf, user_tp_name, sizeof(buf) - 1) < 0)
u64_to_user_ptr(attr->raw_tracepoint.name), return -EFAULT;
sizeof(buf) - 1) < 0) {
err = -EFAULT;
goto out_put_prog;
}
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
tp_name = buf; tp_name = buf;
break; break;
default: default:
err = -EINVAL; return -EINVAL;
goto out_put_prog;
} }
btp = bpf_get_raw_tracepoint(tp_name); btp = bpf_get_raw_tracepoint(tp_name);
if (!btp) { if (!btp)
err = -ENOENT; return -ENOENT;
goto out_put_prog;
}
link = kzalloc(sizeof(*link), GFP_USER); link = kzalloc(sizeof(*link), GFP_USER);
if (!link) { if (!link) {
...@@ -3116,11 +3095,29 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr) ...@@ -3116,11 +3095,29 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
out_put_btp: out_put_btp:
bpf_put_raw_tracepoint(btp); bpf_put_raw_tracepoint(btp);
out_put_prog:
bpf_prog_put(prog);
return err; return err;
} }
#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
{
struct bpf_prog *prog;
int fd;
if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
return -EINVAL;
prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
if (IS_ERR(prog))
return PTR_ERR(prog);
fd = bpf_raw_tp_link_attach(prog, u64_to_user_ptr(attr->raw_tracepoint.name));
if (fd < 0)
bpf_prog_put(prog);
return fd;
}
static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
enum bpf_attach_type attach_type) enum bpf_attach_type attach_type)
{ {
...@@ -3189,7 +3186,13 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) ...@@ -3189,7 +3186,13 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
case BPF_CGROUP_SETSOCKOPT: case BPF_CGROUP_SETSOCKOPT:
return BPF_PROG_TYPE_CGROUP_SOCKOPT; return BPF_PROG_TYPE_CGROUP_SOCKOPT;
case BPF_TRACE_ITER: case BPF_TRACE_ITER:
case BPF_TRACE_RAW_TP:
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
case BPF_MODIFY_RETURN:
return BPF_PROG_TYPE_TRACING; return BPF_PROG_TYPE_TRACING;
case BPF_LSM_MAC:
return BPF_PROG_TYPE_LSM;
case BPF_SK_LOOKUP: case BPF_SK_LOOKUP:
return BPF_PROG_TYPE_SK_LOOKUP; return BPF_PROG_TYPE_SK_LOOKUP;
case BPF_XDP: case BPF_XDP:
...@@ -4246,21 +4249,6 @@ static int bpf_map_do_batch(const union bpf_attr *attr, ...@@ -4246,21 +4249,6 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
return err; return err;
} }
static int tracing_bpf_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
struct bpf_prog *prog)
{
if (attr->link_create.attach_type != prog->expected_attach_type)
return -EINVAL;
if (prog->expected_attach_type == BPF_TRACE_ITER)
return bpf_iter_link_attach(attr, uattr, prog);
else if (prog->type == BPF_PROG_TYPE_EXT)
return bpf_tracing_prog_attach(prog,
attr->link_create.target_fd,
attr->link_create.target_btf_id);
return -EINVAL;
}
#define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies #define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
static int link_create(union bpf_attr *attr, bpfptr_t uattr) static int link_create(union bpf_attr *attr, bpfptr_t uattr)
{ {
...@@ -4282,15 +4270,13 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) ...@@ -4282,15 +4270,13 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
switch (prog->type) { switch (prog->type) {
case BPF_PROG_TYPE_EXT: case BPF_PROG_TYPE_EXT:
ret = tracing_bpf_link_attach(attr, uattr, prog); break;
goto out;
case BPF_PROG_TYPE_PERF_EVENT: case BPF_PROG_TYPE_PERF_EVENT:
case BPF_PROG_TYPE_TRACEPOINT: case BPF_PROG_TYPE_TRACEPOINT:
if (attr->link_create.attach_type != BPF_PERF_EVENT) { if (attr->link_create.attach_type != BPF_PERF_EVENT) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
ptype = prog->type;
break; break;
case BPF_PROG_TYPE_KPROBE: case BPF_PROG_TYPE_KPROBE:
if (attr->link_create.attach_type != BPF_PERF_EVENT && if (attr->link_create.attach_type != BPF_PERF_EVENT &&
...@@ -4298,7 +4284,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) ...@@ -4298,7 +4284,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
ptype = prog->type;
break; break;
default: default:
ptype = attach_type_to_prog_type(attr->link_create.attach_type); ptype = attach_type_to_prog_type(attr->link_create.attach_type);
...@@ -4309,7 +4294,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) ...@@ -4309,7 +4294,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
break; break;
} }
switch (ptype) { switch (prog->type) {
case BPF_PROG_TYPE_CGROUP_SKB: case BPF_PROG_TYPE_CGROUP_SKB:
case BPF_PROG_TYPE_CGROUP_SOCK: case BPF_PROG_TYPE_CGROUP_SOCK:
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
...@@ -4319,8 +4304,25 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) ...@@ -4319,8 +4304,25 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
case BPF_PROG_TYPE_CGROUP_SOCKOPT: case BPF_PROG_TYPE_CGROUP_SOCKOPT:
ret = cgroup_bpf_link_attach(attr, prog); ret = cgroup_bpf_link_attach(attr, prog);
break; break;
case BPF_PROG_TYPE_EXT:
ret = bpf_tracing_prog_attach(prog,
attr->link_create.target_fd,
attr->link_create.target_btf_id);
break;
case BPF_PROG_TYPE_LSM:
case BPF_PROG_TYPE_TRACING: case BPF_PROG_TYPE_TRACING:
ret = tracing_bpf_link_attach(attr, uattr, prog); if (attr->link_create.attach_type != prog->expected_attach_type) {
ret = -EINVAL;
goto out;
}
if (prog->expected_attach_type == BPF_TRACE_RAW_TP)
ret = bpf_raw_tp_link_attach(prog, NULL);
else if (prog->expected_attach_type == BPF_TRACE_ITER)
ret = bpf_iter_link_attach(attr, uattr, prog);
else
ret = bpf_tracing_prog_attach(prog,
attr->link_create.target_fd,
attr->link_create.target_btf_id);
break; break;
case BPF_PROG_TYPE_FLOW_DISSECTOR: case BPF_PROG_TYPE_FLOW_DISSECTOR:
case BPF_PROG_TYPE_SK_LOOKUP: case BPF_PROG_TYPE_SK_LOOKUP:
......
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