All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joel Holdsworth <joel.holdsworth@vcatechnology.com>
To: Laurent Vivier <laurent@vivier.eu>, qemu-devel@nongnu.org
Cc: riku.voipio@iki.fi, Vasileios.Kalintiris@imgtec.com,
	Petros Angelatos <petrosagg@resin.io>
Subject: Re: [Qemu-devel] [PATCH v2 1/4] linux-user: add option to intercept execve() syscalls
Date: Mon, 20 Jun 2016 21:04:57 +0100	[thread overview]
Message-ID: <57684C69.1020605@vcatechnology.com> (raw)
In-Reply-To: <61123e80-fab0-0b7e-f4b1-c6e7ee1bdcbb@vivier.eu>

On 15/06/16 20:31, Laurent Vivier wrote:
>
> Le 14/06/2016 à 21:26, Joel Holdsworth a écrit :
>> From: Petros Angelatos <petrosagg@resin.io>
>>
>> In order for one to use QEMU user mode emulation under a chroot, it is
>> required to use binfmt_misc. This can be avoided by QEMU never doing a
>> raw execve() to the host system.
>>
>> Introduce a new option, -execve, that uses the current QEMU interpreter
>> to intercept execve().
>>
>> qemu_execve() will prepend the interpreter path , similar to what
>> binfmt_misc would do, and then pass the modified execve() to the host.
>>
>> It is necessary to parse hashbang scripts in that function otherwise
>> the kernel will try to run the interpreter of a script without QEMU and
>> get an invalid exec format error.
>>
>> Signed-off-by: Petros Angelatos <petrosagg@resin.io>
>> Tested-by: Laurent Vivier <laurent@vivier.eu>
>> Reviewed-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>   linux-user/main.c    |  37 ++++++++++++++
>>   linux-user/qemu.h    |   1 +
>>   linux-user/syscall.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++-----
>>   3 files changed, 164 insertions(+), 11 deletions(-)
>>
>> diff --git a/linux-user/main.c b/linux-user/main.c
>> index f8a8764..429dc06 100644
>> --- a/linux-user/main.c
>> +++ b/linux-user/main.c
>> @@ -18,6 +18,8 @@
>>    */
>>   #include "qemu/osdep.h"
>>   #include "qemu-version.h"
>> +
>> +#include <sys/auxv.h>
>>   #include <sys/mman.h>
>>   #include <sys/syscall.h>
>>   #include <sys/resource.h>
>> @@ -79,6 +81,7 @@ static void usage(int exitcode);
>>   
>>   static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
>>   const char *qemu_uname_release;
>> +const char *qemu_execve_path;
>>   
>>   /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
>>      we allocate a bigger stack. Need a better solution, for example
>> @@ -3947,6 +3950,38 @@ static void handle_arg_guest_base(const char *arg)
>>       have_guest_base = 1;
>>   }
>>   
>> +static void handle_arg_execve(const char *arg)
>> +{
>> +    const char *execfn;
>> +    char buf[PATH_MAX];
>> +    char *ret;
>> +    int len;
>> +
>> +    /* try getauxval() */
>> +    execfn = (const char *) getauxval(AT_EXECFN);
>> +
>> +    if (execfn != 0) {
>> +        ret = realpath(execfn, buf);
>> +
>> +        if (ret != NULL) {
>> +            qemu_execve_path = strdup(buf);
>> +            return;
>> +        }
>> +    }
>> +
>> +    /* try /proc/self/exe */
>> +    len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
>> +
>> +    if (len != -1) {
>> +        buf[len] = '\0';
>> +        qemu_execve_path = strdup(buf);
>> +        return;
>> +    }
>> +
>> +    fprintf(stderr, "qemu_execve: unable to determine intepreter's path\n");
>> +    exit(EXIT_FAILURE);
>> +}
>> +
>>   static void handle_arg_reserved_va(const char *arg)
>>   {
>>       char *p;
>> @@ -4032,6 +4067,8 @@ static const struct qemu_argument arg_table[] = {
>>        "uname",      "set qemu uname release string to 'uname'"},
>>       {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
>>        "address",    "set guest_base address to 'address'"},
>> +    {"execve",     "QEMU_EXECVE",      false, handle_arg_execve,
>> +     "",           "use this interpreter when a process calls execve()"},
>>       {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
>>        "size",       "reserve 'size' bytes for guest virtual address space"},
>>       {"d",          "QEMU_LOG",         true,  handle_arg_log,
>> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
>> index 56f29c3..567bcc1 100644
>> --- a/linux-user/qemu.h
>> +++ b/linux-user/qemu.h
>> @@ -149,6 +149,7 @@ void init_task_state(TaskState *ts);
>>   void task_settid(TaskState *);
>>   void stop_all_tasks(void);
>>   extern const char *qemu_uname_release;
>> +extern const char *qemu_execve_path;
>>   extern unsigned long mmap_min_addr;
>>   
>>   /* ??? See if we can avoid exposing so much of the loader internals.  */
>> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
>> index 71ccbd9..a478f56 100644
>> --- a/linux-user/syscall.c
>> +++ b/linux-user/syscall.c
>> @@ -106,6 +106,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
>>   #include <linux/rtnetlink.h>
>>   #endif
>>   #include <linux/audit.h>
>> +#include <linux/binfmts.h>
>>   #include "linux_loop.h"
>>   #include "uname.h"
>>   
>> @@ -6659,6 +6660,128 @@ static target_timer_t get_timer_id(abi_long arg)
>>       return timerid;
>>   }
>>   
>> +/* qemu_execve() Must return target values and target errnos. */
>> +static abi_long qemu_execve(char *filename, char *argv[],
>> +                  char *envp[])
>> +{
>> +    char *i_arg = NULL, *i_name = NULL;
>> +    char **new_argp;
>> +    int argc, fd, ret, i, offset = 3;
>> +    char *cp;
>> +    char buf[BINPRM_BUF_SIZE];
>> +
>> +    /* normal execve case */
>> +    if (qemu_execve_path == NULL || *qemu_execve_path == 0) {
>> +        return get_errno(execve(filename, argv, envp));
> You need a safe_execve() here, too.
>
> Laurent
Thanks - now fixed on my branch. I will resubmit when the discussion has 
died down.

Joel

  reply	other threads:[~2016-06-20 20:05 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-14 19:26 [Qemu-devel] linux-user: add option to intercept execve() syscalls Joel Holdsworth
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 1/4] " Joel Holdsworth
2016-06-15 19:31   ` Laurent Vivier
2016-06-20 20:04     ` Joel Holdsworth [this message]
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 2/4] linux-user: pass environment arguments in execve Joel Holdsworth
2016-06-15 19:59   ` Laurent Vivier
2016-06-20 19:51     ` Joel Holdsworth
2016-06-20 20:29       ` Laurent Vivier
2016-06-20 21:27         ` Joel Holdsworth
2016-06-20 21:40           ` Peter Maydell
2016-06-20 22:15             ` Joel Holdsworth
2016-06-20 22:54               ` Peter Maydell
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 3/4] linux-user: pass elf interpreter prefix " Joel Holdsworth
2016-06-15 20:06   ` Laurent Vivier
2016-06-20 19:57     ` Joel Holdsworth
2016-06-14 19:26 ` [Qemu-devel] [PATCH v2 4/4] linux-user: pass strace argument " Joel Holdsworth
2016-06-15 20:37   ` Laurent Vivier
2016-06-20 20:02     ` Joel Holdsworth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57684C69.1020605@vcatechnology.com \
    --to=joel.holdsworth@vcatechnology.com \
    --cc=Vasileios.Kalintiris@imgtec.com \
    --cc=laurent@vivier.eu \
    --cc=petrosagg@resin.io \
    --cc=qemu-devel@nongnu.org \
    --cc=riku.voipio@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.