mirror of https://gitee.com/openkylin/qemu.git
[PATCH, HACK]: linux-user: handle binfmt-misc P flag as a separate exe name
Updated: Wed, 31 Aug 2022 12:30:17 +0300 A hackish way to distinguish the case when qemu-user binary is executed using in-kernel binfmt-misc subsystem with P flag (preserve argv). We register binfmt interpreter under name /usr/libexec/qemu-binfmt/qemu-foo-binfmt-P (which is just a symlink to ../../bin/qemu-foo), and if run like that, qemu-user binary will "know" it should interpret argv[1] & argv[2] in a special way. Gbp-Pq: Name linux-user-binfmt-P.diff Signed-off-by: Cong Liu <liucong2@kylinos.cn>
This commit is contained in:
parent
ad73066ff7
commit
59164a8de4
|
@ -562,7 +562,7 @@ static void usage(int exitcode)
|
|||
exit(exitcode);
|
||||
}
|
||||
|
||||
static int parse_args(int argc, char **argv)
|
||||
static int parse_args(int argc, char **argv, bool *preserve_argv0)
|
||||
{
|
||||
const char *r;
|
||||
int optind;
|
||||
|
@ -579,6 +579,28 @@ static int parse_args(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* HACK alert.
|
||||
* when run as an interpreter using kernel's binfmt-misc mechanism,
|
||||
* we have to know where are we (our own binary), where's the binary being run,
|
||||
* and what it's argv[0] element.
|
||||
* Only with the P interpreter flag kernel passes all 3 elements as first 3 argv[],
|
||||
* but we can't distinguish if we were run with or without this P flag.
|
||||
* So we register a special name with binfmt-misc system, a name which ends up
|
||||
* in "-binfmt-P", and if our argv[0] ends up with that, we assume we were run
|
||||
* from kernel's binfmt with P flag and our first 3 args are from kernel.
|
||||
*/
|
||||
if (strlen(argv[0]) > sizeof("binfmt-P") &&
|
||||
strcmp(argv[0] + strlen(argv[0]) - sizeof("binfmt-P"), "-binfmt-P") == 0) {
|
||||
if (argc < 3) {
|
||||
(void) fprintf(stderr, "qemu: %s has to be run using kernel binfmt-misc subsystem\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exec_path = argv[1];
|
||||
handle_arg_argv0(argv[2]);
|
||||
*preserve_argv0 = true;
|
||||
return 2;
|
||||
}
|
||||
|
||||
optind = 1;
|
||||
for (;;) {
|
||||
if (optind >= argc) {
|
||||
|
@ -648,7 +670,7 @@ int main(int argc, char **argv, char **envp)
|
|||
int ret;
|
||||
int execfd;
|
||||
unsigned long max_reserved_va;
|
||||
bool preserve_argv0;
|
||||
bool preserve_argv0 = 0;
|
||||
|
||||
error_init(argv[0]);
|
||||
module_call_init(MODULE_INIT_TRACE);
|
||||
|
@ -678,7 +700,7 @@ int main(int argc, char **argv, char **envp)
|
|||
qemu_add_opts(&qemu_trace_opts);
|
||||
qemu_plugin_add_opts();
|
||||
|
||||
optind = parse_args(argc, argv);
|
||||
optind = parse_args(argc, argv, &preserve_argv0);
|
||||
|
||||
qemu_set_log_filename_flags(last_log_filename,
|
||||
last_log_mask | (enable_strace * LOG_STRACE),
|
||||
|
@ -717,7 +739,9 @@ int main(int argc, char **argv, char **envp)
|
|||
|
||||
/*
|
||||
* get binfmt_misc flags
|
||||
* but only if not already done by parse_args() above
|
||||
*/
|
||||
if (!preserve_argv0) {
|
||||
preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
|
||||
|
||||
/*
|
||||
|
@ -728,6 +752,7 @@ int main(int argc, char **argv, char **envp)
|
|||
if (optind + 1 < argc && preserve_argv0) {
|
||||
optind++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_model == NULL) {
|
||||
cpu_model = cpu_get_model(get_elf_eflags(execfd));
|
||||
|
|
Loading…
Reference in New Issue