summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-12-15 12:52:30 +0900
committerGitHub <noreply@github.com>2022-12-15 12:52:30 +0900
commit1af1c95e30da5b9cd2493ec3f46f32ad003386ff (patch)
tree8fa6ad4b3ac57a876b54f89a7be5426613143bf9
parent750c605614ebc78f3c3419932bf1d03a4e3b3cf3 (diff)
parentf74a7cb45c2458f90de6d37c70fa3afc1a3be279 (diff)
downloadsystemd-1af1c95e30da5b9cd2493ec3f46f32ad003386ff.tar.gz
Merge pull request #25693 from yuwata/binfmt
binfmt: several cleanups
-rw-r--r--src/basic/stat-util.c25
-rw-r--r--src/binfmt/binfmt.c24
-rw-r--r--src/shared/binfmt-util.c30
-rw-r--r--src/shared/binfmt-util.h1
-rw-r--r--units/systemd-binfmt.service.in2
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