1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-04 17:47:03 +03:00

Merge pull request #25693 from yuwata/binfmt

binfmt: several cleanups
This commit is contained in:
Yu Watanabe 2022-12-15 12:52:30 +09:00 committed by GitHub
commit 1af1c95e30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 15 deletions

View File

@ -163,26 +163,37 @@ int null_or_empty_fd(int fd) {
return null_or_empty(&st); 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; struct statvfs st;
assert(path); assert(fd >= 0);
if (statvfs(path, &st) < 0) if (fstatvfs(fd, &st) < 0)
return -errno; return -errno;
if (st.f_flag & ST_RDONLY) if (st.f_flag & ST_RDONLY)
return true; return true;
/* On NFS, statvfs() might not reflect whether we can actually /* On NFS, fstatvfs() might not reflect whether we can actually write to the remote share. Let's try
* write to the remote share. Let's try again with * again with access(W_OK) which is more reliable, at least sometimes. */
* access(W_OK) which is more reliable, at least sometimes. */ if (access_fd(fd, W_OK) == -EROFS)
if (access(path, W_OK) < 0 && errno == EROFS)
return true; return true;
return false; 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) { int files_same(const char *filea, const char *fileb, int flags) {
struct stat a, b; struct stat a, b;

View File

@ -190,6 +190,18 @@ static int parse_argv(int argc, char *argv[]) {
return 1; 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[]) { static int run(int argc, char *argv[]) {
int r, k; int r, k;
@ -206,13 +218,17 @@ static int run(int argc, char *argv[]) {
if (arg_unregister) if (arg_unregister)
return disable_binfmt(); 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++) { for (int i = optind; i < argc; i++) {
k = apply_file(argv[i], false); k = apply_file(argv[i], false);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
r = k; r = k;
} }
else { } else {
_cleanup_strv_free_ char **files = NULL; _cleanup_strv_free_ char **files = NULL;
r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d")); 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); return cat_files(NULL, files, 0);
} }
r = binfmt_mounted_warn();
if (r <= 0)
return r;
/* Flush out all rules */ /* Flush out all rules */
r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER); r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) if (r < 0)

View File

@ -5,10 +5,30 @@
#include <sys/vfs.h> #include <sys/vfs.h>
#include "binfmt-util.h" #include "binfmt-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "missing_magic.h" #include "missing_magic.h"
#include "stat-util.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 disable_binfmt(void) {
int r; 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 * We are a bit careful here, since binfmt_misc might still be an autofs which we don't want to
* trigger. */ * trigger. */
r = path_is_fs_type("/proc/sys/fs/binfmt_misc", BINFMTFS_MAGIC); r = binfmt_mounted();
if (r == 0 || r == -ENOENT) {
log_debug("binfmt_misc is not mounted, not detaching entries.");
return 0;
}
if (r < 0) if (r < 0)
return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m"); 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); r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) if (r < 0)

View File

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once #pragma once
int binfmt_mounted(void);
int disable_binfmt(void); int disable_binfmt(void);

View File

@ -18,7 +18,7 @@ After=proc-sys-fs-binfmt_misc.automount
After=proc-sys-fs-binfmt_misc.mount After=proc-sys-fs-binfmt_misc.mount
After=local-fs.target After=local-fs.target
Before=sysinit.target shutdown.target Before=sysinit.target shutdown.target
ConditionPathIsReadWrite=/proc/sys/ ConditionPathIsMountPoint=/proc/sys/fs/binfmt_misc
ConditionDirectoryNotEmpty=|/lib/binfmt.d ConditionDirectoryNotEmpty=|/lib/binfmt.d
ConditionDirectoryNotEmpty=|/usr/lib/binfmt.d ConditionDirectoryNotEmpty=|/usr/lib/binfmt.d
ConditionDirectoryNotEmpty=|/usr/local/lib/binfmt.d ConditionDirectoryNotEmpty=|/usr/local/lib/binfmt.d