1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-25 01:34:28 +03:00

Merge pull request #15566 from poettering/destroy-binfmt

unregister binary formats during shutdown
This commit is contained in:
Lennart Poettering 2020-04-23 21:15:22 +02:00 committed by GitHub
commit bf39cb7b92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 9 deletions

View File

@ -41,6 +41,14 @@
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>--unregister</option></term>
<listitem><para>If passed, instead of registering configured binary formats in the kernel, the
reverse operation is executed: all currently registered binary formats are unregistered from the
kernel.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="cat-config" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />

View File

@ -10,6 +10,7 @@
#include <sys/types.h>
#include "alloc-util.h"
#include "binfmt-util.h"
#include "conf-files.h"
#include "def.h"
#include "fd-util.h"
@ -24,6 +25,7 @@
static bool arg_cat_config = false;
static PagerFlags arg_pager_flags = 0;
static bool arg_unregister = false;
static int delete_rule(const char *rule) {
_cleanup_free_ char *x = NULL, *fn = NULL;
@ -32,18 +34,17 @@ static int delete_rule(const char *rule) {
assert(rule);
assert(rule[0]);
x = strdup(rule);
e = strchrnul(rule + 1, rule[0]);
x = strndup(rule + 1, e - rule - 1);
if (!x)
return log_oom();
e = strchrnul(x+1, x[0]);
*e = 0;
if (!filename_is_valid(x + 1))
if (!filename_is_valid(x) ||
STR_IN_SET(x, "register", "status"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Rule file name '%s' is not valid, refusing.", x + 1);
"Rule file name '%s' is not valid, refusing.", x);
fn = path_join("/proc/sys/fs/binfmt_misc", x+1);
fn = path_join("/proc/sys/fs/binfmt_misc", x);
if (!fn)
return log_oom();
@ -116,6 +117,7 @@ static int help(void) {
" --version Show package version\n"
" --cat-config Show configuration files\n"
" --no-pager Do not pipe output into a pager\n"
" --unregister Unregister all existing entries\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
@ -129,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_CAT_CONFIG,
ARG_NO_PAGER,
ARG_UNREGISTER,
};
static const struct option options[] = {
@ -136,6 +139,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "unregister", no_argument, NULL, ARG_UNREGISTER },
{}
};
@ -162,6 +166,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_UNREGISTER:
arg_unregister = true;
break;
case '?':
return -EINVAL;
@ -169,9 +177,9 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
if (arg_cat_config && argc > optind)
if ((arg_unregister || arg_cat_config) && argc > optind)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Positional arguments are not allowed with --cat-config");
"Positional arguments are not allowed with --cat-config or --unregister");
return 1;
}
@ -189,6 +197,9 @@ static int run(int argc, char *argv[]) {
r = 0;
if (arg_unregister)
return disable_binfmt();
if (argc > optind) {
int i;

33
src/shared/binfmt-util.c Normal file
View File

@ -0,0 +1,33 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/vfs.h>
#include "binfmt-util.h"
#include "fileio.h"
#include "missing_magic.h"
#include "stat-util.h"
int disable_binfmt(void) {
int r;
/* Flush out all rules. This is important during shutdown to cover for rules using "F", since those
* might pin a file and thus block us from unmounting stuff cleanly.
*
* 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;
}
if (r < 0)
return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m");
r = write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_warning_errno(r, "Failed to unregister binfmt_misc entries: %m");
log_debug("Unregistered all remaining binfmt_misc entries.");
return 0;
}

4
src/shared/binfmt-util.h Normal file
View File

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

View File

@ -12,6 +12,8 @@ shared_sources = files('''
barrier.h
base-filesystem.c
base-filesystem.h
binfmt-util.c
binfmt-util.h
bitmap.c
bitmap.h
blkid-util.h

View File

@ -16,6 +16,7 @@
#include "alloc-util.h"
#include "async.h"
#include "binfmt-util.h"
#include "cgroup-setup.h"
#include "cgroup-util.h"
#include "def.h"
@ -386,6 +387,7 @@ int main(int argc, char *argv[]) {
sync_with_progress();
disable_coredumps();
disable_binfmt();
log_info("Sending SIGTERM to remaining processes...");
broadcast_signal(SIGTERM, true, true, arg_timeout);

View File

@ -28,4 +28,5 @@ ConditionDirectoryNotEmpty=|/run/binfmt.d
Type=oneshot
RemainAfterExit=yes
ExecStart=@rootlibexecdir@/systemd-binfmt
ExecStop=@rootlibexecdir@/systemd-binfmt --unregister
TimeoutSec=90s