mirror of
				https://gitlab.com/qemu-project/qemu.git
				synced 2025-10-30 07:57:14 +08:00 
			
		
		
		
	bsd-user: Simplify the implementation of execve
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 <dfr@rabson.org> Reviewed-by: Warner Losh <imp@bsdimp.com> Signed-off-by: Warner Losh <imp@bsdimp.com> Acked-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
		| @ -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; | ||||
| @ -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)) { | ||||
| @ -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)) { | ||||
| @ -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); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -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 */ | ||||
| @ -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; | ||||
| @ -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); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Doug Rabson
					Doug Rabson