Tags: patch Attached is a patch which seems to implement this correctly. I was able to verify that it registers the binfmt correctly, but I haven't actually run it through a system with a new enough kernel yet.
This is against upstream rather than a debian patch. Since upstream doesn't have a bug tracker, I'm assuming it will be picked up correctly here. Please let me know if there's a better place to send it. -- Dan Nicholson | +1.206.437.0833 | Endless
From 805f0588efc33b5e57cfc2608c4960a82ea149c3 Mon Sep 17 00:00:00 2001 From: Dan Nicholson <nichol...@endlessm.com> Date: Tue, 27 Jun 2017 13:20:22 -0500 Subject: [PATCH] Add support for fix binary flag Recent kernels provide a binfmt flag F referred to as fix binary[1]. This flag instructs the kernel to open the interpreter immediately and use always use the opened image. This has a big advantage in containers or chroots where the interpreter may not exist at the specified path. A primary use case would be for a static linked QEMU user emulator where an architecture can be emulated in a container or chroot without any alterations so long as the binfmt configuration is handled on the host. 1. https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html --- man/update-binfmts.man8 | 7 ++++++- src/format.c | 5 +++++ src/format.h | 1 + src/update-binfmts.c | 17 +++++++++++++++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/man/update-binfmts.man8 b/man/update-binfmts.man8 index a5e5f7a..01b7163 100644 --- a/man/update-binfmts.man8 +++ b/man/update-binfmts.man8 @@ -237,6 +237,10 @@ Whether to preserve the original .Li argv[0] when running the interpreter, rather than overwriting it with the full path to the binary. +.It Fl Fl fix-binary Cm yes , Fl Fl fix-binary Cm no +Whether to open the emulator binary immediately and always use the opened +image. This allows the emulator from the host to be used regardless of usage +in changeroots or different mount namespaces. .El .Ss FORMAT FILES A format file is a sequence of options, one per line, corresponding roughly @@ -259,8 +263,9 @@ The .Ar extension , .Ar detector , .Ar credentials , +.Ar preserve , and -.Ar preserve +.Ar fix-binary options correspond to the command-line options of the same names. .Sh EXIT STATUS .Bl -tag -width 4n diff --git a/src/format.c b/src/format.c index 0bfdfe1..89bbbb2 100644 --- a/src/format.c +++ b/src/format.c @@ -77,6 +77,7 @@ struct binfmt *binfmt_load (const char *name, const char *filename, int quiet) READ_LINE (detector, 1); READ_LINE (credentials, 1); READ_LINE (preserve, 1); + READ_LINE (fix_binary, 1); #undef READ_LINE @@ -108,6 +109,7 @@ struct binfmt *binfmt_new (const char *name, Hash_table *args) SET_FIELD (detector); SET_FIELD (credentials); SET_FIELD (preserve); + SET_FIELD (fix_binary); #undef SET_FIELD @@ -182,6 +184,7 @@ int binfmt_write (const struct binfmt *binfmt, const char *filename) WRITE_FIELD (detector); WRITE_FIELD (credentials); WRITE_FIELD (preserve); + WRITE_FIELD (fix_binary); #undef WRITE_FIELD @@ -207,6 +210,7 @@ void binfmt_print (const struct binfmt *binfmt) PRINT_FIELD (detector); PRINT_FIELD (credentials); PRINT_FIELD (preserve); + PRINT_FIELD (fix_binary); #undef PRINT_FIELD } @@ -231,6 +235,7 @@ void binfmt_free (struct binfmt *binfmt) free (binfmt->detector); free (binfmt->credentials); free (binfmt->preserve); + free (binfmt->fix_binary); free (binfmt); } diff --git a/src/format.h b/src/format.h index 54a09e0..82fa924 100644 --- a/src/format.h +++ b/src/format.h @@ -32,6 +32,7 @@ struct binfmt { char *detector; char *credentials; char *preserve; + char *fix_binary; }; struct binfmt *binfmt_load (const char *name, const char *filename, int quiet); diff --git a/src/update-binfmts.c b/src/update-binfmts.c index 857b214..6aea32c 100644 --- a/src/update-binfmts.c +++ b/src/update-binfmts.c @@ -363,6 +363,7 @@ static int act_enable (const char *name) const char *interpreter; const char *credentials; const char *preserve; + const char *fix_binary; char *regstring; procdir_name = xasprintf ("%s/%s", procdir, name); @@ -417,10 +418,13 @@ static int act_enable (const char *name) ? "C" : ""; preserve = (binfmt->preserve && !strcmp (binfmt->preserve, "yes")) ? "P" : ""; - regstring = xasprintf (":%s:%c:%s:%s:%s:%s:%s%s\n", + fix_binary = + (binfmt->fix_binary && !strcmp (binfmt->fix_binary, "yes")) + ? "F" : ""; + regstring = xasprintf (":%s:%c:%s:%s:%s:%s:%s%s%s\n", name, type, binfmt->offset, binfmt->magic, binfmt->mask, interpreter, - credentials, preserve); + credentials, preserve, fix_binary); if (test) printf ("enable %s with the following format string:\n %s", name, regstring); @@ -808,6 +812,7 @@ enum opts { OPT_DETECTOR, OPT_CREDENTIALS, OPT_PRESERVE, + OPT_FIX_BINARY, OPT_PACKAGE, OPT_ADMINDIR, OPT_IMPORTDIR, @@ -850,6 +855,8 @@ static struct argp_option options[] = { "use credentials of original binary for interpreter (yes/no)" }, { "preserve", OPT_PRESERVE, "YES/NO", OPTION_HIDDEN, "preserve argv[0] of original binary for interpreter (yes/no)" }, + { "fix-binary", OPT_FIX_BINARY, "YES/NO", OPTION_HIDDEN, + "open intepreter binary immediately and always use open image (yes/no)" }, { "package", OPT_PACKAGE, "PACKAGE-NAME", 0, "for --install and --remove, specify the current package name", 1 }, { "admindir", OPT_ADMINDIR, "DIRECTORY", 0, @@ -876,6 +883,7 @@ static struct { const char *detector; const char *credentials; const char *preserve; + const char *fix_binary; } spec; static const char *mode_name (enum opts m) @@ -1004,6 +1012,10 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) spec.preserve = arg; return 0; + case OPT_FIX_BINARY: + spec.fix_binary = arg; + return 0; + case OPT_PACKAGE: if (package) argp_error (state, "more than one --package option given"); @@ -1116,6 +1128,7 @@ int main (int argc, char **argv) ADD_SPEC (detector); ADD_SPEC (credentials); ADD_SPEC (preserve); + ADD_SPEC (fix_binary); #undef ADD_SPEC binfmt = binfmt_new (name, format_args); -- 2.1.4