All of lore.kernel.org
 help / color / mirror / Atom feed
From: Warner Losh <imp@bsdimp.com>
To: qemu-devel@nongnu.org
Cc: "Thomas Huth" <thuth@redhat.com>,
	"Laurent Vivier" <laurent@vivier.eu>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Wainer dos Santos Moschetta" <wainersm@redhat.com>,
	"Beraldo Leal" <bleal@redhat.com>, "Warner Losh" <imp@bsdimp.com>,
	"Kyle Evans" <kevans@freebsd.org>,
	"Stacey Son" <sson@FreeBSD.org>,
	"Karim Taha" <kariem.taha2.7@gmail.com>
Subject: [PULL 20/51] bsd-user: Implement freebsd_exec_common, used in implementing execve/fexecve.
Date: Tue,  3 Oct 2023 17:31:44 -0600	[thread overview]
Message-ID: <20231003233215.95557-21-imp@bsdimp.com> (raw)
In-Reply-To: <20231003233215.95557-1-imp@bsdimp.com>

From: Stacey Son <sson@FreeBSD.org>

Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Karim Taha <kariem.taha2.7@gmail.com>
Reviewed-by: Warner Losh <imp@bsdimp.com>
Message-Id: <20230925182425.3163-21-kariem.taha2.7@gmail.com>
---
 bsd-user/freebsd/os-proc.c | 181 ++++++++++++++++++++++++++++++++++++-
 bsd-user/main.c            |   2 +-
 bsd-user/qemu.h            |   1 +
 3 files changed, 180 insertions(+), 4 deletions(-)

diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c
index 2603c5c6538..12d78b7fc98 100644
--- a/bsd-user/freebsd/os-proc.c
+++ b/bsd-user/freebsd/os-proc.c
@@ -30,9 +30,7 @@ struct kinfo_proc;
  * Get the filename for the given file descriptor.
  * Note that this may return NULL (fail) if no longer cached in the kernel.
  */
-char *
-get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len);
-char *
+static char *
 get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
 {
     char *ret = NULL;
@@ -80,3 +78,180 @@ out:
     return ret;
 }
 
+/*
+ * execve/fexecve
+ */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+        abi_ulong guest_envp, int do_fexec)
+{
+    char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
+    int argc, envc;
+    abi_ulong gp;
+    abi_ulong addr;
+    char **q;
+    int total_size = 0;
+    void *p;
+    abi_long ret;
+
+    argc = 0;
+    for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        argc++;
+    }
+    envc = 0;
+    for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        envc++;
+    }
+
+    qarg0 = argp = g_new0(char *, argc + 9);
+    /* save the first agrument for the emulator */
+    *argp++ = (char *)getprogname();
+    qargp = argp;
+    *argp++ = (char *)getprogname();
+    qarg1 = argp;
+    envp = g_new0(char *, envc + 1);
+    for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (*q == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        total_size += strlen(*q) + 1;
+    }
+    *q++ = NULL;
+    qargend = q;
+
+    for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (*q == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        total_size += strlen(*q) + 1;
+    }
+    *q = NULL;
+
+    /*
+     * This case will not be caught by the host's execve() if its
+     * page size is bigger than the target's.
+     */
+    if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
+        ret = -TARGET_E2BIG;
+        goto execve_end;
+    }
+
+    if (do_fexec) {
+        if (((int)path_or_fd > 0 &&
+            is_target_elf_binary((int)path_or_fd)) == 1) {
+            char execpath[PATH_MAX];
+
+            /*
+             * The executable is an elf binary for the target
+             * arch.  execve() it using the emulator if we can
+             * determine the filename path from the fd.
+             */
+            if (get_filename_from_fd(getpid(), (int)path_or_fd, execpath,
+                        sizeof(execpath)) != NULL) {
+                memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+                qarg1[1] = qarg1[0];
+                qarg1[0] = (char *)"-0";
+                qarg1 += 2;
+                qargend += 2;
+                *qarg1 = execpath;
+#ifndef DONT_INHERIT_INTERP_PREFIX
+                memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+                *qarg1++ = (char *)"-L";
+                *qarg1++ = (char *)interp_prefix;
+#endif
+                ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+            } else {
+                /* Getting the filename path failed. */
+                ret = -TARGET_EBADF;
+                goto execve_end;
+            }
+        } else {
+            ret = get_errno(fexecve((int)path_or_fd, argp, envp));
+        }
+    } else {
+        int fd;
+
+        p = lock_user_string(path_or_fd);
+        if (p == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+
+        /*
+         * Check the header and see if it a target elf binary.  If so
+         * then execute using qemu user mode emulator.
+         */
+        fd = open(p, O_RDONLY | O_CLOEXEC);
+        if (fd > 0 && is_target_elf_binary(fd) == 1) {
+            close(fd);
+            /* execve() as a target binary using emulator. */
+            memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+            qarg1[1] = qarg1[0];
+            qarg1[0] = (char *)"-0";
+            qarg1 += 2;
+            qargend += 2;
+            *qarg1 = (char *)p;
+#ifndef DONT_INHERIT_INTERP_PREFIX
+            memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
+            *qarg1++ = (char *)"-L";
+            *qarg1++ = (char *)interp_prefix;
+#endif
+            ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+        } else {
+            close(fd);
+            /* Execve() as a host native binary. */
+            ret = get_errno(execve(p, argp, envp));
+        }
+        unlock_user(p, path_or_fd, 0);
+    }
+
+execve_end:
+    for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+
+    for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+
+    g_free(qarg0);
+    g_free(envp);
+
+    return ret;
+}
+
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f913cb55a72..a12b4be80f1 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -88,7 +88,7 @@ unsigned long reserved_va = MAX_RESERVED_VA;
 unsigned long reserved_va;
 #endif
 
-static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
+const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
 const char *qemu_uname_release;
 char qemu_proc_pathname[PATH_MAX];  /* full path to exeutable */
 
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 41c7bd31d3c..6047805ae38 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -111,6 +111,7 @@ typedef struct TaskState {
 } __attribute__((aligned(16))) TaskState;
 
 void stop_all_tasks(void);
+extern const char *interp_prefix;
 extern const char *qemu_uname_release;
 
 /*
-- 
2.41.0



  parent reply	other threads:[~2023-10-03 23:41 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-03 23:31 [PULL 00/51] Bsd user mmap patches Warner Losh
2023-10-03 23:31 ` [PULL 01/51] bsd-user: define TARGET_RFSPAWN for rfork to use vfork(2) semantics, and fix RLIM_INFINITY Warner Losh
2023-10-03 23:31 ` [PULL 02/51] bsd-user: Define procctl(2) related structs Warner Losh
2023-10-03 23:31 ` [PULL 03/51] bsd-user: Implement host_to_target_siginfo Warner Losh
2023-10-03 23:31 ` [PULL 04/51] bsd-user: Add freebsd_exec_common and do_freebsd_procctl to qemu.h Warner Losh
2023-10-03 23:31 ` [PULL 05/51] bsd-user: add extern declarations for bsd-proc.c conversion functions Warner Losh
2023-10-03 23:31 ` [PULL 06/51] bsd-user: Implement target_to_host_resource conversion function Warner Losh
2023-10-03 23:31 ` [PULL 07/51] bsd-user: Implement target_to_host_rlim and host_to_target_rlim conversion Warner Losh
2023-10-03 23:31 ` [PULL 08/51] bsd-user: Implement host_to_target_rusage and host_to_target_wrusage Warner Losh
2023-10-03 23:31 ` [PULL 09/51] bsd-user: Implement host_to_target_waitstatus conversion Warner Losh
2023-10-03 23:31 ` [PULL 10/51] bsd-user: Get number of cpus Warner Losh
2023-10-03 23:31 ` [PULL 11/51] bsd-user: Implement getgroups(2) and setgroups(2) system calls Warner Losh
2023-10-03 23:31 ` [PULL 12/51] bsd-user: Implement umask(2), setlogin(2) and getlogin(2) Warner Losh
2023-10-03 23:31 ` [PULL 13/51] bsd-user: Implement getrusage(2) Warner Losh
2023-10-03 23:31 ` [PULL 14/51] bsd-user: Implement getrlimit(2) and setrlimit(2) Warner Losh
2023-10-03 23:31 ` [PULL 15/51] bsd-user: Implement several get/set system calls: Warner Losh
2023-10-03 23:31 ` [PULL 16/51] bsd-user: Implement get/set[resuid/resgid/sid] and issetugid Warner Losh
2023-10-03 23:31 ` [PULL 17/51] bsd-user: Add stubs for profil(2), ktrace(2), utrace(2) and ptrace(2) Warner Losh
2023-10-03 23:31 ` [PULL 18/51] bsd-user: Implement getpriority(2) and setpriority(2) Warner Losh
2023-10-03 23:31 ` [PULL 19/51] bsd-user: Implement get_filename_from_fd Warner Losh
2023-10-03 23:31 ` Warner Losh [this message]
2023-10-03 23:31 ` [PULL 21/51] bsd-user: Implement procctl(2) along with necessary conversion functions Warner Losh
2023-10-03 23:31 ` [PULL 22/51] bsd-user: Implement execve(2) and fexecve(2) system calls Warner Losh
2023-10-03 23:31 ` [PULL 23/51] bsd-user: Implement wait4(2) and wait6(2) " Warner Losh
2023-10-03 23:31 ` [PULL 24/51] bsd-user: Implement setloginclass(2) and getloginclass(2) " Warner Losh
2023-10-03 23:31 ` [PULL 25/51] bsd-user: Implement pdgetpid(2) and the undocumented setugid Warner Losh
2023-10-03 23:31 ` [PULL 26/51] bsd-user: Implement fork(2) and vfork(2) system calls Warner Losh
2023-10-03 23:31 ` [PULL 27/51] bsd-user: Implement rfork(2) system call Warner Losh
2023-10-03 23:31 ` [PULL 28/51] bsd-user: Implement pdfork(2) " Warner Losh
2023-10-03 23:31 ` [PULL 29/51] bsd-user: Implement struct target_ipc_perm Warner Losh
2023-10-03 23:31 ` [PULL 30/51] bsd-user: Implement struct target_shmid_ds Warner Losh
2023-10-03 23:31 ` [PULL 31/51] bsd-user: Declarations for ipc_perm and shmid_ds conversion functions Warner Losh
2023-10-03 23:31 ` [PULL 32/51] bsd-user: Introduce freebsd/os-misc.h to the source tree Warner Losh
2023-10-03 23:31 ` [PULL 33/51] bsd-user: Implement shm_open2(2) system call Warner Losh
2023-10-03 23:31 ` [PULL 34/51] bsd-user: Implement shm_rename(2) " Warner Losh
2023-10-03 23:31 ` [PULL 35/51] bsd-user: Add bsd-mem.c to meson.build Warner Losh
2023-10-03 23:32 ` [PULL 36/51] bsd-user: Implement target_set_brk function in bsd-mem.c instead of os-syscall.c Warner Losh
2023-10-03 23:32 ` [PULL 37/51] bsd-user: Implement ipc_perm conversion between host and target Warner Losh
2023-10-03 23:32 ` [PULL 38/51] bsd-user: Implement shmid_ds " Warner Losh
2023-10-03 23:32 ` [PULL 39/51] bsd-user: Introduce bsd-mem.h to the source tree Warner Losh
2023-10-03 23:32 ` [PULL 40/51] bsd-user: Implement mmap(2) and munmap(2) Warner Losh
2023-10-03 23:32 ` [PULL 41/51] bsd-user: Implement mprotect(2) Warner Losh
2023-10-03 23:32 ` [PULL 42/51] bsd-user: Implement msync(2) Warner Losh
2023-10-03 23:32 ` [PULL 43/51] bsd-user: Implement mlock(2), munlock(2), mlockall(2), munlockall(2), minherit(2) Warner Losh
2023-10-03 23:32 ` [PULL 44/51] bsd-user: Implment madvise(2) to match the linux-user implementation Warner Losh
2023-10-03 23:32 ` [PULL 45/51] bsd-user: Implement mincore(2) Warner Losh
2023-10-03 23:32 ` [PULL 46/51] bsd-user: Implement do_obreak function Warner Losh
2023-10-03 23:32 ` [PULL 47/51] bsd-user: Implement shm_open(2) Warner Losh
2023-10-03 23:32 ` [PULL 48/51] bsd-user: Implement shm_unlink(2) and shmget(2) Warner Losh
2023-10-03 23:32 ` [PULL 49/51] bsd-user: Implement shmctl(2) Warner Losh
2023-10-03 23:32 ` [PULL 50/51] bsd-user: Implement shmat(2) and shmdt(2) Warner Losh
2023-10-03 23:32 ` [PULL 51/51] bsd-user: Add stubs for vadvise(), sbrk() and sstk() Warner Losh
2023-10-04 18:33 ` [PULL 00/51] Bsd user mmap patches Stefan Hajnoczi

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=20231003233215.95557-21-imp@bsdimp.com \
    --to=imp@bsdimp.com \
    --cc=alex.bennee@linaro.org \
    --cc=bleal@redhat.com \
    --cc=kariem.taha2.7@gmail.com \
    --cc=kevans@freebsd.org \
    --cc=laurent@vivier.eu \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sson@FreeBSD.org \
    --cc=thuth@redhat.com \
    --cc=wainersm@redhat.com \
    /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.