1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-22 13:33:56 +03:00

binfmt: add logging information

In delete_rule(), we already checked that the rule name is a valid file name
(i.e. no slashes), so we can just trivially append.

Also, let's always reject rules that we would later fail to delete. It's
probably better to avoid such confusion.

And print the operations we do with file name and line number. I hope this
helps with cases like https://github.com/systemd/systemd/pull/21178. At least
we'll know what rule failed.

$ sudo SYSTEMD_LOG_LEVEL=debug build/systemd-binfmt
Flushed all binfmt_misc rules.
Applying /etc/binfmt.d/kshcomp.conf…
/etc/binfmt.d/kshcomp.conf:1: binary format 'kshcomp' registered.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-11-10 15:44:06 +01:00
parent 33068a0f5e
commit 99a041d1ce

View File

@ -27,77 +27,82 @@ static bool arg_cat_config = false;
static PagerFlags arg_pager_flags = 0; static PagerFlags arg_pager_flags = 0;
static bool arg_unregister = false; static bool arg_unregister = false;
static int delete_rule(const char *rule) { static int delete_rule(const char *rulename) {
_cleanup_free_ char *x = NULL, *fn = NULL; const char *fn = strjoina("/proc/sys/fs/binfmt_misc/", rulename);
char *e;
assert(rule);
assert(rule[0]);
e = strchrnul(rule + 1, rule[0]);
x = strndup(rule + 1, e - rule - 1);
if (!x)
return log_oom();
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);
fn = path_join("/proc/sys/fs/binfmt_misc", x);
if (!fn)
return log_oom();
return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER); return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
} }
static int apply_rule(const char *rule) { static int apply_rule(const char *filename, unsigned line, const char *rule) {
assert(filename);
assert(line > 0);
assert(rule);
assert(rule[0]);
_cleanup_free_ char *rulename = NULL;
const char *e;
int r; int r;
(void) delete_rule(rule); e = strchrnul(rule + 1, rule[0]);
rulename = strndup(rule + 1, e - rule - 1);
if (!rulename)
return log_oom();
if (!filename_is_valid(rulename) ||
STR_IN_SET(rulename, "register", "status"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s:%u: Rule name '%s' is not valid, refusing.",
filename, line, rulename);
r = delete_rule(rulename);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "%s:%u: Failed to delete rule '%s', ignoring: %m",
filename, line, rulename);
if (r >= 0)
log_debug("%s:%u: Rule '%s' deleted.", filename, line, rulename);
r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER); r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to add binary format: %m"); return log_error_errno(r, "%s:%u: Failed to add binary format '%s': %m",
filename, line, rulename);
log_debug("%s:%u: Binary format '%s' registered.", filename, line, rulename);
return 0; return 0;
} }
static int apply_file(const char *path, bool ignore_enoent) { static int apply_file(const char *filename, bool ignore_enoent) {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *pp = NULL; _cleanup_free_ char *pp = NULL;
int r; int r;
assert(path); assert(filename);
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f, &pp); r = search_and_fopen(filename, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f, &pp);
if (r < 0) { if (r < 0) {
if (ignore_enoent && r == -ENOENT) if (ignore_enoent && r == -ENOENT)
return 0; return 0;
return log_error_errno(r, "Failed to open file '%s': %m", path); return log_error_errno(r, "Failed to open file '%s': %m", filename);
} }
log_debug("apply: %s", pp); log_debug("Applying %s…", pp);
for (;;) { for (unsigned line = 1;; line++) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *text = NULL;
char *p; char *p;
int k; int k;
k = read_line(f, LONG_LINE_MAX, &line); k = read_line(f, LONG_LINE_MAX, &text);
if (k < 0) if (k < 0)
return log_error_errno(k, "Failed to read file '%s': %m", pp); return log_error_errno(k, "Failed to read file '%s': %m", pp);
if (k == 0) if (k == 0)
break; break;
p = strstrip(line); p = strstrip(text);
if (isempty(p)) if (isempty(p))
continue; continue;
if (strchr(COMMENTS, p[0])) if (strchr(COMMENTS, p[0]))
continue; continue;
k = apply_rule(p); k = apply_rule(filename, line, p);
if (k < 0 && r == 0) if (k < 0 && r >= 0)
r = k; r = k;
} }
@ -203,7 +208,7 @@ static int run(int argc, char *argv[]) {
if (argc > optind) if (argc > optind)
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 {
@ -221,11 +226,15 @@ static int run(int argc, char *argv[]) {
} }
/* Flush out all rules */ /* Flush out all rules */
(void) 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)
log_warning_errno(r, "Failed to flush binfmt_misc rules, ignoring: %m");
else
log_debug("Flushed all binfmt_misc rules.");
STRV_FOREACH(f, files) { STRV_FOREACH(f, files) {
k = apply_file(*f, true); k = apply_file(*f, true);
if (k < 0 && r == 0) if (k < 0 && r >= 0)
r = k; r = k;
} }
} }