[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20201201035545.3013177-4-andrii@kernel.org>
Date: Mon, 30 Nov 2020 19:55:40 -0800
From: Andrii Nakryiko <andrii@...nel.org>
To: <bpf@...r.kernel.org>, <netdev@...r.kernel.org>, <ast@...com>,
<daniel@...earbox.net>
CC: <andrii@...nel.org>, <kernel-team@...com>
Subject: [PATCH v2 bpf-next 3/8] bpf: allow to specify kernel module BTFs when attaching BPF programs
Add ability for user-space programs to specify non-vmlinux BTF when attaching
BTF-powered BPF programs: raw_tp, fentry/fexit/fmod_ret, LSM, etc. For this,
add attach_btf_obj_id field which contains BTF object ID for either vmlinux or
module. For backwards compatibility (and simplicity) reasons, 0 denotes
vmlinux BTF. Only kernel BTF (vmlinux or module) can be specified.
Signed-off-by: Andrii Nakryiko <andrii@...nel.org>
---
include/linux/btf.h | 2 ++
include/uapi/linux/bpf.h | 1 +
kernel/bpf/btf.c | 25 +++++++++++++++++++------
kernel/bpf/syscall.c | 22 +++++++++++++++++++---
tools/include/uapi/linux/bpf.h | 1 +
5 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index fb608e4de076..53ce2bc6dc54 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -89,7 +89,9 @@ int btf_type_snprintf_show(const struct btf *btf, u32 type_id, void *obj,
char *buf, int len, u64 flags);
int btf_get_fd_by_id(u32 id);
+struct btf *btf_get_by_id(int id);
u32 btf_obj_id(const struct btf *btf);
+bool btf_is_kernel(const struct btf *btf);
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
const struct btf_member *m,
u32 expected_offset, u32 expected_size);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c3458ec1f30a..60b95b51ccb8 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -558,6 +558,7 @@ union bpf_attr {
__u32 line_info_cnt; /* number of bpf_line_info records */
__u32 attach_btf_id; /* in-kernel BTF type id to attach to */
__u32 attach_prog_fd; /* 0 to attach to vmlinux */
+ __u32 attach_btf_obj_id; /* vmlinux/module BTF object ID for BTF type */
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7a19bf5bfe97..12876b272c6b 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5652,6 +5652,19 @@ struct btf *btf_get_by_fd(int fd)
return btf;
}
+struct btf *btf_get_by_id(int id)
+{
+ struct btf *btf;
+
+ rcu_read_lock();
+ btf = idr_find(&btf_idr, id);
+ if (!btf || !refcount_inc_not_zero(&btf->refcnt))
+ btf = ERR_PTR(-ENOENT);
+ rcu_read_unlock();
+
+ return btf;
+}
+
int btf_get_info_by_fd(const struct btf *btf,
const union bpf_attr *attr,
union bpf_attr __user *uattr)
@@ -5717,12 +5730,7 @@ int btf_get_fd_by_id(u32 id)
struct btf *btf;
int fd;
- rcu_read_lock();
- btf = idr_find(&btf_idr, id);
- if (!btf || !refcount_inc_not_zero(&btf->refcnt))
- btf = ERR_PTR(-ENOENT);
- rcu_read_unlock();
-
+ btf = btf_get_by_id(id);
if (IS_ERR(btf))
return PTR_ERR(btf);
@@ -5738,6 +5746,11 @@ u32 btf_obj_id(const struct btf *btf)
return btf->id;
}
+bool btf_is_kernel(const struct btf *btf)
+{
+ return btf->kernel_btf;
+}
+
static int btf_id_cmp_func(const void *a, const void *b)
{
const int *pa = a, *pb = b;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5ee00611af53..3af073642664 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1968,7 +1968,7 @@ static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
static int
bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
enum bpf_attach_type expected_attach_type,
- u32 btf_id, u32 prog_fd)
+ u32 btf_obj_id, u32 btf_id, u32 prog_fd)
{
if (btf_id) {
if (btf_id > BTF_MAX_TYPE)
@@ -1985,6 +1985,9 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
}
}
+ if (btf_obj_id && (!btf_id || prog_fd))
+ return -EINVAL;
+
if (prog_fd && prog_type != BPF_PROG_TYPE_TRACING &&
prog_type != BPF_PROG_TYPE_EXT)
return -EINVAL;
@@ -2097,7 +2100,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
}
/* last field in 'union bpf_attr' used by this command */
-#define BPF_PROG_LOAD_LAST_FIELD attach_prog_fd
+#define BPF_PROG_LOAD_LAST_FIELD attach_btf_obj_id
static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
{
@@ -2146,6 +2149,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
bpf_prog_load_fixup_attach_type(attr);
if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
+ attr->attach_btf_obj_id,
attr->attach_btf_id,
attr->attach_prog_fd))
return -EINVAL;
@@ -2158,7 +2162,19 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
prog->expected_attach_type = attr->expected_attach_type;
prog->aux->attach_btf_id = attr->attach_btf_id;
- if (attr->attach_btf_id && !attr->attach_prog_fd) {
+ if (attr->attach_btf_obj_id) {
+ struct btf *btf;
+
+ btf = btf_get_by_id(attr->attach_btf_obj_id);
+ if (IS_ERR(btf))
+ return PTR_ERR(btf);
+ if (!btf_is_kernel(btf)) {
+ btf_put(btf);
+ return -EINVAL;
+ }
+
+ prog->aux->attach_btf = btf;
+ } else if (attr->attach_btf_id && !attr->attach_prog_fd) {
struct btf *btf;
btf = bpf_get_btf_vmlinux();
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index c3458ec1f30a..60b95b51ccb8 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -558,6 +558,7 @@ union bpf_attr {
__u32 line_info_cnt; /* number of bpf_line_info records */
__u32 attach_btf_id; /* in-kernel BTF type id to attach to */
__u32 attach_prog_fd; /* 0 to attach to vmlinux */
+ __u32 attach_btf_obj_id; /* vmlinux/module BTF object ID for BTF type */
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
--
2.24.1
Powered by blists - more mailing lists