Bug#632192: [PATCH] introduce environment variables for all qemu-user options
This patch will be useful, but there is a security problem in its current form. The qemu-user-static package installs binfmt-misc entries with "flags: OC", which makes the binary honor setuid bits. Regardless of whether it is a good idea or not, the envvars ought to be ignored in such a case. Some clever checks using getresuid(), or just geteuid() and getuid() when getresuid() is not available, surely have to done. There is probably some existing code for this in other programs... Best regards, -- Yann -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Bug#632192: [PATCH] introduce environment variables for all qemu-user options
Rework option parsing code for linux-user in a table-driven manner to allow environment variables for all commandline options. Also generate usage() output from option table. Fix complains from checkpatch.pl, also have envlist global Signed-off-by: Johannes Schauer --- linux-user/main.c | 530 ++--- 1 files changed, 342 insertions(+), 188 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index dbba8be..74c5198 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -40,6 +40,11 @@ char *exec_path; int singlestep; +const char *filename; +const char *argv0; +int gdbstub_port; +envlist_t *envlist; +const char *cpu_model; unsigned long mmap_min_addr; #if defined(CONFIG_USE_GUEST_BASE) unsigned long guest_base; @@ -47,6 +52,8 @@ int have_guest_base; unsigned long reserved_va; #endif +static void usage(void); + static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release = CONFIG_UNAME_RELEASE; @@ -2624,50 +2631,6 @@ void cpu_loop (CPUState *env) } #endif /* TARGET_ALPHA */ -static void usage(void) -{ -printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" - "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n" - "Linux CPU emulator (compiled for %s emulation)\n" - "\n" - "Standard options:\n" - "-hprint this help\n" - "-g port wait gdb connection to port\n" - "-L path set the elf interpreter prefix (default=%s)\n" - "-s size set the stack size in bytes (default=%ld)\n" - "-cpu modelselect CPU (-cpu ? for list)\n" - "-drop-ld-preload drop LD_PRELOAD for target process\n" - "-E var=value sets/modifies targets environment variable(s)\n" - "-U varunsets targets environment variable(s)\n" - "-0 argv0 forces target process argv[0] to be argv0\n" -#if defined(CONFIG_USE_GUEST_BASE) - "-B addressset guest_base address to address\n" - "-R size reserve size bytes for guest virtual address space\n" -#endif - "\n" - "Debug options:\n" - "-d options activate log (logfile=%s)\n" - "-p pagesize set the host page size to 'pagesize'\n" - "-singlestep always run in singlestep mode\n" - "-strace log system calls\n" - "\n" - "Environment variables:\n" - "QEMU_STRACE Print system calls and arguments similar to the\n" - " 'strace' program. Enable by setting to any value.\n" - "You can use -E and -U options to set/unset environment variables\n" - "for target process. It is possible to provide several variables\n" - "by repeating the option. For example:\n" - "-E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" - "Note that if you provide several changes to single variable\n" - "last change will stay in effect.\n" - , - TARGET_ARCH, - interp_prefix, - guest_stack_size, - DEBUG_LOGFILE); -exit(1); -} - THREAD CPUState *thread_env; void task_settid(TaskState *ts) @@ -2703,24 +2666,351 @@ void init_task_state(TaskState *ts) } ts->sigqueue_table[i].next = NULL; } - + +static void handle_arg_help(const char *arg) +{ +usage(); +} + +static void handle_arg_log(const char *arg) +{ +int mask; +const CPULogItem *item; + +mask = cpu_str_to_log_mask(arg); +if (!mask) { +printf("Log items (comma separated):\n"); +for (item = cpu_log_items; item->mask != 0; item++) { +printf("%-10s %s\n", item->name, item->help); +} +exit(1); +} +cpu_set_log(mask); +} + +static void handle_arg_set_env(const char *arg) +{ +char *r, *p, *token; +r = p = strdup(arg); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_setenv(envlist, token) != 0) { +usage(); +} +} +free(r); +} + +static void handle_arg_unset_env(const char *arg) +{ +char *r, *p, *token; +r = p = strdup(arg); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_unsetenv(envlist, token) != 0) { +usage(); +} +} +free(r); +} + +static void handle_arg_argv0(const char *arg) +{ +argv0 = strdup(arg); +} + +static void handle_arg_stack_size(const char *arg) +{ +char *p; +guest_stack_size = strtoul(arg, &p, 0); +if (guest_stack_size == 0) { +usage(); +} + +if (*p == 'M') { +guest_stack_size *= 1024 * 1024; +} else if (*p == 'k' || *p == 'K') { +guest_stack_size *= 1024; +} +} + +static void handle_arg_ld_prefix(const char *arg) +{ +interp_prefix = strdup(arg); +} + +s
Bug#632192: [PATCH] introduce environment variables for all qemu-user options
On 31 July 2011 22:40, Johannes Schauer wrote: > Rework option parsing code for linux-user in a table-driven manner to allow > environment variables for all commandline options. > > Also generate usage() output from option table. Thanks for this, it looks good. A couple of minor points: (1) what's the rationale for having most of the things the arg-parsing-functions change be global variables but passing envlist as an argument to each function? It's only used by two of the functions so maybe that should just be a global too. (2) scripts/checkpatch.pl complains about a number of formatting nits; mostly these are in existing code you've just moved around, but I think it's worth fixing them in passing anyway. -- PMM -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Bug#632192: [PATCH] introduce environment variables for all qemu-user options
Rework option parsing code for linux-user in a table-driven manner to allow environment variables for all commandline options. Also generate usage() output from option table. Signed-off-by: Johannes Schauer --- linux-user/main.c | 518 ++--- 1 files changed, 331 insertions(+), 187 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index dbba8be..95e8651 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -40,6 +40,10 @@ char *exec_path; int singlestep; +const char *filename; +const char *argv0 = NULL; +int gdbstub_port = 0; +const char *cpu_model; unsigned long mmap_min_addr; #if defined(CONFIG_USE_GUEST_BASE) unsigned long guest_base; @@ -47,6 +51,8 @@ int have_guest_base; unsigned long reserved_va; #endif +static void usage(void); + static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release = CONFIG_UNAME_RELEASE; @@ -2624,50 +2630,6 @@ void cpu_loop (CPUState *env) } #endif /* TARGET_ALPHA */ -static void usage(void) -{ -printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" - "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n" - "Linux CPU emulator (compiled for %s emulation)\n" - "\n" - "Standard options:\n" - "-hprint this help\n" - "-g port wait gdb connection to port\n" - "-L path set the elf interpreter prefix (default=%s)\n" - "-s size set the stack size in bytes (default=%ld)\n" - "-cpu modelselect CPU (-cpu ? for list)\n" - "-drop-ld-preload drop LD_PRELOAD for target process\n" - "-E var=value sets/modifies targets environment variable(s)\n" - "-U varunsets targets environment variable(s)\n" - "-0 argv0 forces target process argv[0] to be argv0\n" -#if defined(CONFIG_USE_GUEST_BASE) - "-B addressset guest_base address to address\n" - "-R size reserve size bytes for guest virtual address space\n" -#endif - "\n" - "Debug options:\n" - "-d options activate log (logfile=%s)\n" - "-p pagesize set the host page size to 'pagesize'\n" - "-singlestep always run in singlestep mode\n" - "-strace log system calls\n" - "\n" - "Environment variables:\n" - "QEMU_STRACE Print system calls and arguments similar to the\n" - " 'strace' program. Enable by setting to any value.\n" - "You can use -E and -U options to set/unset environment variables\n" - "for target process. It is possible to provide several variables\n" - "by repeating the option. For example:\n" - "-E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" - "Note that if you provide several changes to single variable\n" - "last change will stay in effect.\n" - , - TARGET_ARCH, - interp_prefix, - guest_stack_size, - DEBUG_LOGFILE); -exit(1); -} - THREAD CPUState *thread_env; void task_settid(TaskState *ts) @@ -2703,24 +2665,342 @@ void init_task_state(TaskState *ts) } ts->sigqueue_table[i].next = NULL; } - + +static void handle_arg_help(const char *arg, envlist_t *envlist) +{ +usage(); +} + +static void handle_arg_log(const char *arg, envlist_t *envlist) +{ +int mask; +const CPULogItem *item; + +mask = cpu_str_to_log_mask(arg); +if (!mask) { +printf("Log items (comma separated):\n"); +for(item = cpu_log_items; item->mask != 0; item++) { +printf("%-10s %s\n", item->name, item->help); +} +exit(1); +} +cpu_set_log(mask); +} + +static void handle_arg_set_env(const char *arg, envlist_t *envlist) +{ +char *r, *p, *token; +r = p = strdup(arg); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_setenv(envlist, token) != 0) +usage(); +} +free(r); +} + +static void handle_arg_unset_env(const char *arg, envlist_t *envlist) +{ +char *r, *p, *token; +r = p = strdup(arg); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_unsetenv(envlist, token) != 0) +usage(); +} +free(r); +} + +static void handle_arg_argv0(const char *arg, envlist_t *envlist) +{ +argv0 = strdup(arg); +} + +static void handle_arg_stack_size(const char *arg, envlist_t *envlist) +{ +char *p; +guest_stack_size = strtoul(arg, &p, 0); +if (guest_stack_size == 0) +usage(); +if (*p == 'M') +guest_stack_size *= 1024 * 1024; +else if (*p == 'k' || *p == 'K') +guest_stack_size *= 1024; +} + +static void handle_arg_ld_prefix(const char *arg, envlist_t *envlist) +{ +interp_prefix =
Bug#632192: [PATCH] introduce environment variables for all qemu-user options
From: Johannes Schauer A first try to introduce a generic setup for mapping environment variables to command line options. I'm afraid to code something for platforms I can't do runtime tests on, so this is only for linux-user for now. Signed-off-by: Johannes Schauer --- linux-user/main.c | 147 +++- 1 files changed, 144 insertions(+), 3 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index dbba8be..fb986e3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2640,26 +2640,51 @@ static void usage(void) "-E var=value sets/modifies targets environment variable(s)\n" "-U varunsets targets environment variable(s)\n" "-0 argv0 forces target process argv[0] to be argv0\n" + "-r uname set qemu uname release string\n" #if defined(CONFIG_USE_GUEST_BASE) "-B addressset guest_base address to address\n" "-R size reserve size bytes for guest virtual address space\n" #endif "\n" + "Standard environment variables:\n" + "QEMU_GDB see the -g option\n" + "QEMU_LD_PREFIXsee the -L option\n" + "QEMU_STACK_SIZE see the -s option\n" + "QEMU_CPU see the -cpu option\n" + "QEMU_SET_ENV see the -E option, comma separated list of arguments\n" + "QEMU_UNSET_ENVsee the -U option, comma separated list of arguments\n" + "QEMU_ARGV0see the -0 option\n" + "QEMU_UNAMEsee the -r option\n" +#if defined(CONFIG_USE_GUEST_BASE) + "QEMU_GUEST_BASE see the -B option\n" + "QEMU_RESERVED_VA see the -R option\n" +#endif + "\n" "Debug options:\n" "-d options activate log (logfile=%s)\n" "-p pagesize set the host page size to 'pagesize'\n" "-singlestep always run in singlestep mode\n" "-strace log system calls\n" "\n" - "Environment variables:\n" - "QEMU_STRACE Print system calls and arguments similar to the\n" - " 'strace' program. Enable by setting to any value.\n" + "Debug environment variables:\n" + "QEMU_LOG see the -d option\n" + "QEMU_PAGESIZE see the -p option\n" + "QEMU_SINGLESTEP see the -singlestep option\n" + "QEMU_STRACE see the -strace option\n" + "\n" "You can use -E and -U options to set/unset environment variables\n" "for target process. It is possible to provide several variables\n" "by repeating the option. For example:\n" "-E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" "Note that if you provide several changes to single variable\n" "last change will stay in effect.\n" + "Using the environment variables QEMU_SET_ENV and QEMU_UNSET_ENV\n" + "to set/unset environment variables for target process is\n" + "possible by a comma separated list of values in getsubopt(3)\n" + "style. For example:\n" + "QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" + "Note that if you provide several changes to single variable\n" + "last change will stay in effect.\n" , TARGET_ARCH, interp_prefix, @@ -2758,6 +2783,122 @@ int main(int argc, char **argv, char **envp) cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ #endif +if ((r = getenv("QEMU_LOG")) != NULL) { +int mask; +const CPULogItem *item; +mask = cpu_str_to_log_mask(r); +if (!mask) { +printf("Log items (comma separated):\n"); +for(item = cpu_log_items; item->mask != 0; item++) { +printf("%-10s %s\n", item->name, item->help); +} +exit(1); +} +cpu_set_log(mask); +} +if ((r = getenv("QEMU_SET_ENV")) != NULL) { +char *p, *token; +p = strdup(r); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_setenv(envlist, token) != 0) +usage(); +} +free(p); +} +if ((r = getenv("QEMU_UNSET_ENV")) != NULL) { +char *p, *token; +p = strdup(r); +while ((token = strsep(&p, ",")) != NULL) { +if (envlist_unsetenv(envlist, token) != 0) +usage(); +} +free(p); +} +if ((r = getenv("QEMU_ARGV0")) != NULL) { +argv0 = strdup(r); +} +if ((r = getenv("QEMU_STACK_SIZE")) != NULL) { +guest_stack_size = strtoul(r, (char **)&r, 0); +if (guest_stack_size == 0) +usage(); +if (*r == 'M') +guest_stack_size *= 1024 * 1024; +else if (*r == 'k' || *r ==