aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/kernel
diff options
context:
space:
mode:
authorAndrii Nakryiko <andrii@kernel.org>2025-03-17 13:45:12 -0700
committerAndrii Nakryiko <andrii@kernel.org>2025-03-17 13:45:13 -0700
commitb02f072a36560a89155a1ebcb2ca6bd881333a8b (patch)
tree62436d27fd49365a4db2b9fa92065b6aabbca28c /kernel
parentbpf, x86: Fix objtool warning for timed may_goto (diff)
parentselftests/bpf: Test freplace from user namespace (diff)
downloadwireguard-linux-b02f072a36560a89155a1ebcb2ca6bd881333a8b.tar.xz
wireguard-linux-b02f072a36560a89155a1ebcb2ca6bd881333a8b.zip
Merge branch 'support-freplace-prog-from-user-namespace'
Mykyta Yatsenko says: ==================== Support freplace prog from user namespace From: Mykyta Yatsenko <yatsenko@meta.com> Freplace programs can't be loaded from user namespace, as bpf_program__set_attach_target() requires searching for target prog BTF, which is locked under CAP_SYS_ADMIN. This patch set enables this use case by: 1. Relaxing capable check in bpf's BPF_BTF_GET_FD_BY_ID, check for CAP_BPF instead of CAP_SYS_ADMIN, support BPF token in attr argument. 2. Pass BPF token around libbpf from bpf_program__set_attach_target() to bpf syscall where capable check is. 3. Validate positive/negative scenarios in selftests This patch set is enabled by the recent libbpf change[1], that introduced bpf_object__prepare() API. Calling bpf_object__prepare() for freplace program before bpf_program__set_attach_target() initializes BPF token, which is then passed to bpf syscall by libbpf. [1] https://lore.kernel.org/all/20250303135752.158343-1-mykyta.yatsenko5@gmail.com/ ==================== Link: https://patch.msgid.link/20250317174039.161275-1-mykyta.yatsenko5@gmail.com Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/syscall.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6a8f20ee2851..380b445a304c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -4732,6 +4732,8 @@ static int bpf_prog_get_info_by_fd(struct file *file,
info.recursion_misses = stats.misses;
info.verified_insns = prog->aux->verified_insns;
+ if (prog->aux->btf)
+ info.btf_id = btf_obj_id(prog->aux->btf);
if (!bpf_capable()) {
info.jited_prog_len = 0;
@@ -4878,8 +4880,6 @@ static int bpf_prog_get_info_by_fd(struct file *file,
}
}
- if (prog->aux->btf)
- info.btf_id = btf_obj_id(prog->aux->btf);
info.attach_btf_id = prog->aux->attach_btf_id;
if (attach_btf)
info.attach_btf_obj_id = btf_obj_id(attach_btf);
@@ -5120,15 +5120,34 @@ static int bpf_btf_load(const union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_
return btf_new_fd(attr, uattr, uattr_size);
}
-#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
+#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD fd_by_id_token_fd
static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
{
+ struct bpf_token *token = NULL;
+
if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
+ if (attr->open_flags & ~BPF_F_TOKEN_FD)
+ return -EINVAL;
+
+ if (attr->open_flags & BPF_F_TOKEN_FD) {
+ token = bpf_token_get_from_fd(attr->fd_by_id_token_fd);
+ if (IS_ERR(token))
+ return PTR_ERR(token);
+ if (!bpf_token_allow_cmd(token, BPF_BTF_GET_FD_BY_ID)) {
+ bpf_token_put(token);
+ token = NULL;
+ }
+ }
+
+ if (!bpf_token_capable(token, CAP_SYS_ADMIN)) {
+ bpf_token_put(token);
return -EPERM;
+ }
+
+ bpf_token_put(token);
return btf_get_fd_by_id(attr->btf_id);
}