]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: Don't call fsopen() as privileged user
authorMatteo Croce <teknoraver@meta.com>
Tue, 1 Jul 2025 18:31:23 +0000 (20:31 +0200)
committerAndrii Nakryiko <andrii@kernel.org>
Wed, 2 Jul 2025 17:42:54 +0000 (10:42 -0700)
In the BPF token example, the fsopen() syscall is called as privileged
user. This is unneeded because fsopen() can be called also as
unprivileged user from the user namespace.
As the `fs_fd` file descriptor which was sent back and forth is still the
same, keep it open instead of cloning and closing it twice via SCM_RIGHTS.

cfr. https://github.com/systemd/systemd/pull/36134

Signed-off-by: Matteo Croce <teknoraver@meta.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/bpf/20250701183123.31781-1-technoboy85@gmail.com
tools/testing/selftests/bpf/prog_tests/token.c

index f9392df23f8ab25df0202346965bca8039657183..cfc032b910c40c3b9a66c1315556b64fe1af5606 100644 (file)
@@ -115,7 +115,7 @@ static int create_bpffs_fd(void)
 
 static int materialize_bpffs_fd(int fs_fd, struct bpffs_opts *opts)
 {
-       int mnt_fd, err;
+       int err;
 
        /* set up token delegation mount options */
        err = set_delegate_mask(fs_fd, "delegate_cmds", opts->cmds, opts->cmds_str);
@@ -136,12 +136,7 @@ static int materialize_bpffs_fd(int fs_fd, struct bpffs_opts *opts)
        if (err < 0)
                return -errno;
 
-       /* create O_PATH fd for detached mount */
-       mnt_fd = sys_fsmount(fs_fd, 0, 0);
-       if (err < 0)
-               return -errno;
-
-       return mnt_fd;
+       return 0;
 }
 
 /* send FD over Unix domain (AF_UNIX) socket */
@@ -287,6 +282,7 @@ static void child(int sock_fd, struct bpffs_opts *opts, child_callback_fn callba
 {
        int mnt_fd = -1, fs_fd = -1, err = 0, bpffs_fd = -1, token_fd = -1;
        struct token_lsm *lsm_skel = NULL;
+       char one;
 
        /* load and attach LSM "policy" before we go into unpriv userns */
        lsm_skel = token_lsm__open_and_load();
@@ -333,13 +329,19 @@ static void child(int sock_fd, struct bpffs_opts *opts, child_callback_fn callba
        err = sendfd(sock_fd, fs_fd);
        if (!ASSERT_OK(err, "send_fs_fd"))
                goto cleanup;
-       zclose(fs_fd);
+
+       /* wait that the parent reads the fd, does the fsconfig() calls
+        * and send us a signal that it is done
+        */
+       err = read(sock_fd, &one, sizeof(one));
+       if (!ASSERT_GE(err, 0, "read_one"))
+               goto cleanup;
 
        /* avoid mucking around with mount namespaces and mounting at
-        * well-known path, just get detach-mounted BPF FS fd back from parent
+        * well-known path, just create O_PATH fd for detached mount
         */
-       err = recvfd(sock_fd, &mnt_fd);
-       if (!ASSERT_OK(err, "recv_mnt_fd"))
+       mnt_fd = sys_fsmount(fs_fd, 0, 0);
+       if (!ASSERT_OK_FD(mnt_fd, "mnt_fd"))
                goto cleanup;
 
        /* try to fspick() BPF FS and try to add some delegation options */
@@ -429,24 +431,24 @@ again:
 
 static void parent(int child_pid, struct bpffs_opts *bpffs_opts, int sock_fd)
 {
-       int fs_fd = -1, mnt_fd = -1, token_fd = -1, err;
+       int fs_fd = -1, token_fd = -1, err;
+       char one = 1;
 
        err = recvfd(sock_fd, &fs_fd);
        if (!ASSERT_OK(err, "recv_bpffs_fd"))
                goto cleanup;
 
-       mnt_fd = materialize_bpffs_fd(fs_fd, bpffs_opts);
-       if (!ASSERT_GE(mnt_fd, 0, "materialize_bpffs_fd")) {
+       err = materialize_bpffs_fd(fs_fd, bpffs_opts);
+       if (!ASSERT_GE(err, 0, "materialize_bpffs_fd")) {
                err = -EINVAL;
                goto cleanup;
        }
-       zclose(fs_fd);
 
-       /* pass BPF FS context object to parent */
-       err = sendfd(sock_fd, mnt_fd);
-       if (!ASSERT_OK(err, "send_mnt_fd"))
+       /* notify the child that we did the fsconfig() calls and it can proceed. */
+       err = write(sock_fd, &one, sizeof(one));
+       if (!ASSERT_EQ(err, sizeof(one), "send_one"))
                goto cleanup;
-       zclose(mnt_fd);
+       zclose(fs_fd);
 
        /* receive BPF token FD back from child for some extra tests */
        err = recvfd(sock_fd, &token_fd);
@@ -459,7 +461,6 @@ static void parent(int child_pid, struct bpffs_opts *bpffs_opts, int sock_fd)
 cleanup:
        zclose(sock_fd);
        zclose(fs_fd);
-       zclose(mnt_fd);
        zclose(token_fd);
 
        if (child_pid > 0)