Skip to content

Commit

Permalink
bsd-user: Simplify the implementation of execve
Browse files Browse the repository at this point in the history
This removes the logic which prepends the emulator to each call to
execve and fexecve. This is not necessary with the existing
imgact_binmisc support and it avoids the need to install the emulator
binary into jail environments when using 'binmiscctl --pre-open'.

Signed-off-by: Doug Rabson <[email protected]>
Reviewed-by: Warner Losh <[email protected]>
Signed-off-by: Warner Losh <[email protected]>
Acked-by: Richard Henderson <[email protected]>
  • Loading branch information
dfr authored and bsdimp committed Jul 23, 2024
1 parent ce6c541 commit e6e102b
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 133 deletions.
118 changes: 3 additions & 115 deletions bsd-user/freebsd/os-proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,65 +26,13 @@ struct kinfo_proc;

#include "qemu.h"

/*
* Get the filename for the given file descriptor.
* Note that this may return NULL (fail) if no longer cached in the kernel.
*/
static char *
get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
{
char *ret = NULL;
unsigned int cnt;
struct procstat *procstat = NULL;
struct kinfo_proc *kp = NULL;
struct filestat_list *head = NULL;
struct filestat *fst;

procstat = procstat_open_sysctl();
if (procstat == NULL) {
goto out;
}

kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
if (kp == NULL) {
goto out;
}

head = procstat_getfiles(procstat, kp, 0);
if (head == NULL) {
goto out;
}

STAILQ_FOREACH(fst, head, next) {
if (fd == fst->fs_fd) {
if (fst->fs_path != NULL) {
(void)strlcpy(filename, fst->fs_path, len);
ret = filename;
}
break;
}
}

out:
if (head != NULL) {
procstat_freefiles(procstat, head);
}
if (kp != NULL) {
procstat_freeprocs(procstat, kp);
}
if (procstat != NULL) {
procstat_close(procstat);
}
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;
char **argp, **envp, **qarg0;
int argc, envc;
abi_ulong gp;
abi_ulong addr;
Expand Down Expand Up @@ -117,9 +65,7 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
qarg0 = argp = g_new0(char *, argc + 9);
/* save the first argument 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)) {
Expand All @@ -137,7 +83,6 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
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)) {
Expand Down Expand Up @@ -166,71 +111,14 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
}

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));
}
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));
}
ret = get_errno(execve(p, argp, envp));
unlock_user(p, path_or_fd, 0);
}

Expand Down
18 changes: 0 additions & 18 deletions bsd-user/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ unsigned long reserved_va;

const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */

unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
Expand Down Expand Up @@ -247,22 +246,6 @@ adjust_ssize(void)
setrlimit(RLIMIT_STACK, &rl);
}

static void save_proc_pathname(char *argv0)
{
int mib[4];
size_t len;

mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;

len = sizeof(qemu_proc_pathname);
if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
perror("sysctl");
}
}

int main(int argc, char **argv)
{
const char *filename;
Expand Down Expand Up @@ -292,7 +275,6 @@ int main(int argc, char **argv)
usage();
}

save_proc_pathname(argv[0]);

error_init(argv[0]);
module_call_init(MODULE_INIT_TRACE);
Expand Down

0 comments on commit e6e102b

Please sign in to comment.