diff options
author | Laurent Vivier <laurent@vivier.eu> | 2021-02-22 11:50:04 +0100 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2021-03-13 10:45:11 +0100 |
commit | 6e1c0d7b951e19c53b8467e8bc4b71ee73a394ea (patch) | |
tree | 6c93ac93fb4d9b8546cc3e711bd7e21af8dd278d /linux-user/main.c | |
parent | 08f3a96b33e7eef39b651af9edb5e6de8ff13371 (diff) |
linux-user: manage binfmt-misc preserve-arg[0] flag
Add --preserve-argv0 in qemu-binfmt-conf.sh to configure the preserve-argv0
flag.
This patch allows to use new flag in AT_FLAGS to detect if
preserve-argv0 is configured for this interpreter:
argv[0] (the full pathname provided by binfmt-misc) is removed and
replaced by argv[1] (the original argv[0] provided by binfmt-misc when
'P'/preserve-arg[0] is set)
For instance with this patch and kernel support for AT_FLAGS:
$ sudo chroot m68k-chroot sh -c 'echo $0'
sh
without this patch:
$ sudo chroot m68k-chroot sh -c 'echo $0'
/usr/bin/sh
The new flag is available in kernel (v5.12) since:
2347961b11d4 ("binfmt_misc: pass binfmt_misc flags to the interpreter")
This can be tested with something like:
# cp ..../qemu-ppc /chroot/powerpc/jessie
# qemu-binfmt-conf.sh --qemu-path / --systemd ppc --credential yes \
--persistent no --preserve-argv0 yes
# systemctl restart systemd-binfmt.service
# cat /proc/sys/fs/binfmt_misc/qemu-ppc
enabled
interpreter //qemu-ppc
flags: POC
offset 0
magic 7f454c4601020100000000000000000000020014
mask ffffffffffffff00fffffffffffffffffffeffff
# chroot /chroot/powerpc/jessie sh -c 'echo $0'
sh
# qemu-binfmt-conf.sh --qemu-path / --systemd ppc --credential yes \
--persistent no --preserve-argv0 no
# systemctl restart systemd-binfmt.service
# cat /proc/sys/fs/binfmt_misc/qemu-ppc
enabled
interpreter //qemu-ppc
flags: OC
offset 0
magic 7f454c4601020100000000000000000000020014
mask ffffffffffffff00fffffffffffffffffffeffff
# chroot /chroot/powerpc/jessie sh -c 'echo $0'
/bin/sh
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20210222105004.1642234-1-laurent@vivier.eu>
Diffstat (limited to 'linux-user/main.c')
-rw-r--r-- | linux-user/main.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index 4f4746dce8..f956afccab 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -26,6 +26,7 @@ #include <sys/syscall.h> #include <sys/resource.h> #include <sys/shm.h> +#include <linux/binfmts.h> #include "qapi/error.h" #include "qemu.h" @@ -49,6 +50,11 @@ #include "cpu_loop-common.h" #include "crypto/init.h" +#ifndef AT_FLAGS_PRESERVE_ARGV0 +#define AT_FLAGS_PRESERVE_ARGV0_BIT 0 +#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT) +#endif + char *exec_path; int singlestep; @@ -632,6 +638,7 @@ int main(int argc, char **argv, char **envp) int execfd; int log_mask; unsigned long max_reserved_va; + bool preserve_argv0; error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); @@ -688,6 +695,9 @@ int main(int argc, char **argv, char **envp) init_qemu_uname_release(); + /* + * Manage binfmt-misc open-binary flag + */ execfd = qemu_getauxval(AT_EXECFD); if (execfd == 0) { execfd = open(exec_path, O_RDONLY); @@ -697,6 +707,20 @@ int main(int argc, char **argv, char **envp) } } + /* + * get binfmt_misc flags + */ + preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0); + + /* + * Manage binfmt-misc preserve-arg[0] flag + * argv[optind] full path to the binary + * argv[optind + 1] original argv[0] + */ + if (optind + 1 < argc && preserve_argv0) { + optind++; + } + if (cpu_model == NULL) { cpu_model = cpu_get_model(get_elf_eflags(execfd)); } |