diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-12-15 12:52:30 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-15 12:52:30 +0900 |
commit | 1af1c95e30da5b9cd2493ec3f46f32ad003386ff (patch) | |
tree | 8fa6ad4b3ac57a876b54f89a7be5426613143bf9 | |
parent | 750c605614ebc78f3c3419932bf1d03a4e3b3cf3 (diff) | |
parent | f74a7cb45c2458f90de6d37c70fa3afc1a3be279 (diff) | |
download | systemd-1af1c95e30da5b9cd2493ec3f46f32ad003386ff.tar.gz |
Merge pull request #25693 from yuwata/binfmt
binfmt: several cleanups
-rw-r--r-- | src/basic/stat-util.c | 25 | ||||
-rw-r--r-- | src/binfmt/binfmt.c | 24 | ||||
-rw-r--r-- | src/shared/binfmt-util.c | 30 | ||||
-rw-r--r-- | src/shared/binfmt-util.h | 1 | ||||
-rw-r--r-- | units/systemd-binfmt.service.in | 2 |
5 files changed, 67 insertions, 15 deletions
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 97dbcaac66..0974f6178a 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -163,26 +163,37 @@ int null_or_empty_fd(int fd) { return null_or_empty(&st); } -int path_is_read_only_fs(const char *path) { +static int fd_is_read_only_fs(int fd) { struct statvfs st; - assert(path); + assert(fd >= 0); - if (statvfs(path, &st) < 0) + if (fstatvfs(fd, &st) < 0) return -errno; if (st.f_flag & ST_RDONLY) return true; - /* On NFS, statvfs() might not reflect whether we can actually - * write to the remote share. Let's try again with - * access(W_OK) which is more reliable, at least sometimes. */ - if (access(path, W_OK) < 0 && errno == EROFS) + /* On NFS, fstatvfs() might not reflect whether we can actually write to the remote share. Let's try + * again with access(W_OK) which is more reliable, at least sometimes. */ + if (access_fd(fd, W_OK) == -EROFS) return true; return false; } +int path_is_read_only_fs(const char *path) { + _cleanup_close_ int fd = -EBADFD; + + assert(path); + + fd = open(path, O_CLOEXEC | O_PATH); + if (fd < 0) + return -errno; + + return fd_is_read_only_fs(fd); +} + int files_same(const char *filea, const char *fileb, int flags) { struct stat a, b; diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index ba209a8d47..624c63ec98 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -190,6 +190,18 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +static int binfmt_mounted_warn(void) { + int r; + + r = binfmt_mounted(); + if (r < 0) + return log_error_errno(r, "Failed to check if /proc/sys/fs/binfmt_misc is mounted: %m"); + if (r == 0) + log_debug("/proc/sys/fs/binfmt_misc is not mounted in read-write mode, skipping."); + + return r; +} + static int run(int argc, char *argv[]) { int r, k; @@ -206,13 +218,17 @@ static int run(int argc, char *argv[]) { if (arg_unregister) return disable_binfmt(); - if (argc > optind) + if (argc > optind) { + r = binfmt_mounted_warn(); + if (r <= 0) + return r; + for (int i = optind; i < argc; i++) { k = apply_file(argv[i], false); if (k < 0 && r >= 0) r = k; } - else { + } else { _cleanup_strv_free_ char **files = NULL; r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d")); @@ -225,6 +241,10 @@ static int run(int argc, char *argv[]) { return cat_files(NULL, files, 0); } + r = binfmt_mounted_warn(); + if (r <= 0) + return r; + /* Flush out all rules */ r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) diff --git a/src/shared/binfmt-util.c b/src/shared/binfmt-util.c index 724d7f27d9..a26175474b 100644 --- a/src/shared/binfmt-util.c +++ b/src/shared/binfmt-util.c @@ -5,10 +5,30 @@ #include <sys/vfs.h> #include "binfmt-util.h" +#include "errno-util.h" +#include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "missing_magic.h" #include "stat-util.h" +int binfmt_mounted(void) { + _cleanup_close_ int fd = -EBADF; + int r; + + fd = RET_NERRNO(open("/proc/sys/fs/binfmt_misc", O_CLOEXEC | O_DIRECTORY | O_PATH)); + if (fd == -ENOENT) + return false; + if (fd < 0) + return fd; + + r = fd_is_fs_type(fd, BINFMTFS_MAGIC); + if (r <= 0) + return r; + + return access_fd(fd, W_OK) >= 0; +} + int disable_binfmt(void) { int r; @@ -18,13 +38,13 @@ int disable_binfmt(void) { * We are a bit careful here, since binfmt_misc might still be an autofs which we don't want to * trigger. */ - r = path_is_fs_type("/proc/sys/fs/binfmt_misc", BINFMTFS_MAGIC); - if (r == 0 || r == -ENOENT) { - log_debug("binfmt_misc is not mounted, not detaching entries."); - return 0; - } + r = binfmt_mounted(); if (r < 0) return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m"); + if (r == 0) { + log_debug("binfmt_misc is not mounted in read-write mode, not detaching entries."); + return 0; + } r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) diff --git a/src/shared/binfmt-util.h b/src/shared/binfmt-util.h index 2f008d12ff..13f4548b7c 100644 --- a/src/shared/binfmt-util.h +++ b/src/shared/binfmt-util.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +int binfmt_mounted(void); int disable_binfmt(void); diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in index a702c0d9d7..b04412e037 100644 --- a/units/systemd-binfmt.service.in +++ b/units/systemd-binfmt.service.in @@ -18,7 +18,7 @@ After=proc-sys-fs-binfmt_misc.automount After=proc-sys-fs-binfmt_misc.mount After=local-fs.target Before=sysinit.target shutdown.target -ConditionPathIsReadWrite=/proc/sys/ +ConditionPathIsMountPoint=/proc/sys/fs/binfmt_misc ConditionDirectoryNotEmpty=|/lib/binfmt.d ConditionDirectoryNotEmpty=|/usr/lib/binfmt.d ConditionDirectoryNotEmpty=|/usr/local/lib/binfmt.d |