]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: BPF token support for BPF_BTF_GET_FD_BY_ID
authorMykyta Yatsenko <yatsenko@meta.com>
Mon, 17 Mar 2025 17:40:36 +0000 (17:40 +0000)
committerAndrii Nakryiko <andrii@kernel.org>
Mon, 17 Mar 2025 20:45:11 +0000 (13:45 -0700)
Currently BPF_BTF_GET_FD_BY_ID requires CAP_SYS_ADMIN, which does not
allow running it from user namespace. This creates a problem when
freplace program running from user namespace needs to query target
program BTF.
This patch relaxes capable check from CAP_SYS_ADMIN to CAP_BPF and adds
support for BPF token that can be passed in attributes to syscall.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20250317174039.161275-2-mykyta.yatsenko5@gmail.com
include/uapi/linux/bpf.h
kernel/bpf/syscall.c
tools/include/uapi/linux/bpf.h

index bb37897c039398dd3568cd007586d9b088ddeb32..661de2444965480494020489f03744950f7a357a 100644 (file)
@@ -1652,6 +1652,7 @@ union bpf_attr {
                };
                __u32           next_id;
                __u32           open_flags;
+               __s32           fd_by_id_token_fd;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
index 6a8f20ee285119b4cd0004e0e265247054ec6a7d..419f82c78203942cc12bdbb9fcb2eeb51b18e944 100644 (file)
@@ -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);
 }
index bb37897c039398dd3568cd007586d9b088ddeb32..661de2444965480494020489f03744950f7a357a 100644 (file)
@@ -1652,6 +1652,7 @@ union bpf_attr {
                };
                __u32           next_id;
                __u32           open_flags;
+               __s32           fd_by_id_token_fd;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */