On Tue, Nov 5, 2024 at 5:48 PM Noah Goldstein <goldstein....@gmail.com> wrote:
>
> On Tue, Nov 5, 2024 at 5:37 AM Richard Henderson
> <richard.hender...@linaro.org> wrote:
> >
> > On 10/30/24 14:10, Noah Goldstein wrote:
> > > The new option '-qemu-children' makes it so that on `execve` the child
> > > process will be launch by the same `qemu` executable that is currently
> > > running along with its current commandline arguments.
> > >
> > > The motivation for the change is to make it so that plugins running
> > > through `qemu` can continue to run on children.  Why not just
> > > `binfmt`?: Plugins can be desirable regardless of system/architecture
> > > emulation, and can sometimes be useful for elf files that can run
> > > natively. Enabling `binfmt` for all natively runnable elf files may
> > > not be desirable.
> > >
> > > Signed-off-by: Noah Goldstein <goldstein....@gmail.com>
> > > ---
> > >   linux-user/main.c                             | 21 ++++++
> > >   linux-user/syscall.c                          | 21 ++++--
> > >   linux-user/user-internals.h                   |  4 ++
> > >   tests/tcg/multiarch/Makefile.target           |  8 +++
> > >   .../linux/linux-execve-qemu-children.c        | 68 +++++++++++++++++++
> > >   5 files changed, 117 insertions(+), 5 deletions(-)
> > >   create mode 100644 
> > > tests/tcg/multiarch/linux/linux-execve-qemu-children.c
> > >
> > > diff --git a/linux-user/main.c b/linux-user/main.c
> > > index 8143a0d4b0..5e3d41dc2b 100644
> > > --- a/linux-user/main.c
> > > +++ b/linux-user/main.c
> > > @@ -81,6 +81,10 @@ unsigned long mmap_min_addr;
> > >   uintptr_t guest_base;
> > >   bool have_guest_base;
> > >
> > > +bool qemu_dup_for_children;
> > > +int qemu_argc;
> > > +char **qemu_argv;
> > > +
> > >   /*
> > >    * Used to implement backwards-compatibility for the `-strace`, and
> > >    * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by
> > > @@ -451,6 +455,11 @@ static void handle_arg_jitdump(const char *arg)
> > >       perf_enable_jitdump();
> > >   }
> > >
> > > +static void handle_arg_qemu_children(const char *arg)
> > > +{
> > > +    qemu_dup_for_children = true;
> > > +}
> > > +
> > >   static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
> > >
> > >   #ifdef CONFIG_PLUGIN
> > > @@ -526,6 +535,10 @@ static const struct qemu_argument arg_table[] = {
> > >        "",           "Generate a /tmp/perf-${pid}.map file for perf"},
> > >       {"jitdump",    "QEMU_JITDUMP",     false, handle_arg_jitdump,
> > >        "",           "Generate a jit-${pid}.dump file for perf"},
> > > +    {"qemu-children",
> > > +                   "QEMU_CHILDREN",    false, handle_arg_qemu_children,
> > > +     "",           "Run child processes (created with execve) with qemu "
> > > +                   "(as instantiated for the parent)"},
> > >       {NULL, NULL, false, NULL, NULL, NULL}
> > >   };
> > >
> > > @@ -729,6 +742,14 @@ int main(int argc, char **argv, char **envp)
> > >
> > >       optind = parse_args(argc, argv);
> > >
> > > +    if (qemu_dup_for_children) {
> > > +        qemu_argc = optind;
> > > +        qemu_argv = g_new0(char *, qemu_argc);
> > > +        for (i = 0; i < optind; ++i) {
> > > +            qemu_argv[i] = strdup(argv[i]);
> >
> > g_strdup.
> ack
> >
> > > +    bool through_qemu = dirfd == AT_FDCWD && qemu_dup_for_children;
> >
> > Why is this limited to AT_FDCWD?  Why not for execvat too?
> >
>
> We could, initially it was because AFAICT qemu doesn't support executing a
> program relative to another dir, but it would be simple enough to just join
> the relative program path and path dirfd points to.
>
> Want me to add support?
> > > @@ -8628,9 +8631,16 @@ static int do_execv(CPUArchState *cpu_env, int 
> > > dirfd,
> > >       }
> > >
> > >       const char *exe = p;
> > > -    if (is_proc_myself(p, "exe")) {
> > > +    if (through_qemu) {
> > > +        int i;
> > > +        for (i = 0; i < argp_offset; ++i) {
> > > +            argp[i] = qemu_argv[i];
> > > +        }
> > > +        exe = qemu_argv[0];
> > > +    } else if (is_proc_myself(p, "exe")) {
> > >           exe = exec_path;
> > >       }
> > > +
> >
> > You still need to handle is_proc_myself, for the guest binary.

Would this by handled by basically do:

```
if (is_proc_myself(p, "exe")) {
        exe = exec_path;
        if (through_qemu)
            argp[argp_offset] = exec_path;
}
```
Or am I missing something?

> >
> > I wonder if those two cases are related.  Do we need to also add an 
> > argument so that we
> > can pass the executable to the next qemu via file descriptor?  I.e. execvat 
> > becomes
> >
> >      f = openat()
> >      execv(qemu, "-execfd", f)
> >
> > and is_proc_myself uses execfd, which we already have open.

How does passing a fd from one process to another work?

> >
> >
> > r~

Reply via email to