From: Yu Watanabe Date: Thu, 17 Jul 2025 18:53:28 +0000 (+0900) Subject: core: it is not necessary to send message after fsconfig() for bpffs X-Git-Tag: v258-rc1~30^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9eabf827507091fea8a623cddd0c06848b89c62e;p=thirdparty%2Fsystemd.git core: it is not necessary to send message after fsconfig() for bpffs Instead, let's wait for the helper process being finished. --- diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index dcef723b46c..82a6a12a984 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -2298,9 +2298,6 @@ static int bpffs_helper(const ExecContext *c, int socket_fd) { if (fsconfig(fs_fd, FSCONFIG_CMD_CREATE, /* key = */ NULL, /* value = */ NULL, /* aux = */ 0) < 0) return log_debug_errno(errno, "Failed to create bpffs superblock: %m"); - if (write(socket_fd, (uint8_t[1]) {}, 1) < 0) - return log_debug_errno(errno, "Failed to send data to child: %m"); - return 0; } @@ -3671,7 +3668,9 @@ static int apply_mount_namespace( bool needs_sandboxing, uid_t exec_directory_uid, gid_t exec_directory_gid, + PidRef *bpffs_pidref, int bpffs_socket_fd, + int bpffs_errno_pipe, char **reterr_path) { _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT; @@ -3886,7 +3885,9 @@ static int apply_mount_namespace( .proc_subset = needs_sandboxing ? context->proc_subset : PROC_SUBSET_ALL, .private_bpf = needs_sandboxing ? context->private_bpf : PRIVATE_BPF_NO, + .bpffs_pidref = bpffs_pidref, .bpffs_socket_fd = bpffs_socket_fd, + .bpffs_errno_pipe = bpffs_errno_pipe, }; r = setup_namespace(¶meters, reterr_path); @@ -4527,7 +4528,9 @@ static int setup_delegated_namespaces( const ExecCommand *command, bool needs_sandboxing, bool have_cap_sys_admin, + PidRef *bpffs_pidref, int bpffs_socket_fd, + int bpffs_errno_pipe, int *reterr_exit_status) { int r; @@ -4650,7 +4653,9 @@ static int setup_delegated_namespaces( needs_sandboxing, uid, gid, + bpffs_pidref, bpffs_socket_fd, + bpffs_errno_pipe, &error_path); if (r < 0) { *reterr_exit_status = EXIT_NAMESPACE; @@ -5762,7 +5767,9 @@ int exec_invoke( command, needs_sandboxing, have_cap_sys_admin, + &bpffs_pidref, bpffs_socket_fd, + bpffs_errno_pipe, exit_status); if (r < 0) return r; @@ -5822,29 +5829,15 @@ int exec_invoke( command, needs_sandboxing, have_cap_sys_admin, + &bpffs_pidref, bpffs_socket_fd, + bpffs_errno_pipe, exit_status); if (r < 0) return r; - if (context->private_bpf != PRIVATE_BPF_NO) { - r = pidref_wait_for_terminate_and_check("(sd-bpffs)", &bpffs_pidref, /* flags = */ 0); - if (r < 0) { - *exit_status = EXIT_BPF; - return r; - } - /* If something strange happened with the child, let's consider this fatal, too */ - if (r != EXIT_SUCCESS) { - *exit_status = EXIT_BPF; - ssize_t ss = read(bpffs_errno_pipe, &r, sizeof(r)); - if (ss == sizeof(r)) - return log_debug_errno(r, "bpffs helper exited with error: %m"); - if (ss < 0) - return log_debug_errno(errno, "Failed to read from the bpffs helper errno pipe: %m"); - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Short read from the bpffs helper errno pipe."); - } - pidref_done(&bpffs_pidref); - } + /* Kill unnecessary process, for the case that e.g. when the bpffs mount point is hidden. */ + pidref_done_sigkill_wait(&bpffs_pidref); if (needs_sandboxing && exec_needs_cgroup_namespace(context) && params->cgroup_path) { /* Move ourselves into the subcgroup now *after* we've unshared the cgroup namespace, which diff --git a/src/core/namespace.c b/src/core/namespace.c index c384d67898a..4391c127554 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1735,11 +1735,13 @@ static int mount_overlay(const MountEntry *m) { return 1; } -static int mount_bpffs(const MountEntry *m, int socket_fd) { +static int mount_bpffs(const MountEntry *m, PidRef *pidref, int socket_fd, int errno_pipe) { int r; assert(m); + assert(pidref_is_set(pidref)); assert(socket_fd >= 0); + assert(errno_pipe >= 0); _cleanup_close_ int fs_fd = fsopen("bpf", FSOPEN_CLOEXEC); if (fs_fd < 0) @@ -1749,8 +1751,21 @@ static int mount_bpffs(const MountEntry *m, int socket_fd) { if (r < 0) return log_debug_errno(r, "Failed to send bpffs fd to child: %m"); - if (read(socket_fd, (uint8_t[1]) {}, 1) < 0) - return log_debug_errno(errno, "Failed to receive data from child: %m"); + r = pidref_wait_for_terminate_and_check("(sd-bpffs)", pidref, /* flags = */ 0); + if (r < 0) + return r; + + /* If something strange happened with the child, let's consider this fatal, too */ + if (r != EXIT_SUCCESS) { + ssize_t ss = read(errno_pipe, &r, sizeof(r)); + if (ss < 0) + return log_debug_errno(errno, "Failed to read from the bpffs helper errno pipe: %m"); + if (ss != sizeof(r)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Short read from the bpffs helper errno pipe."); + return log_debug_errno(r, "bpffs helper exited with error: %m"); + } + + pidref_done(pidref); _cleanup_close_ int mnt_fd = fsmount(fs_fd, /* flags = */ 0, /* mount_attrs = */ 0); if (mnt_fd < 0) @@ -2020,7 +2035,7 @@ static int apply_one_mount( return mount_overlay(m); case MOUNT_BPFFS: - return mount_bpffs(m, p->bpffs_socket_fd); + return mount_bpffs(m, p->bpffs_pidref, p->bpffs_socket_fd, p->bpffs_errno_pipe); default: assert_not_reached(); diff --git a/src/core/namespace.h b/src/core/namespace.h index 42e146a7e8e..4e9d87e266f 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -200,7 +200,9 @@ typedef struct NamespaceParameters { PrivateTmp private_var_tmp; PrivatePIDs private_pids; + PidRef *bpffs_pidref; int bpffs_socket_fd; + int bpffs_errno_pipe; } NamespaceParameters; int setup_namespace(const NamespaceParameters *p, char **reterr_path);