2 * FreeBSD process related emulation code
4 * Copyright (c) 2013-15 Stacey D. Son
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
21 #include <sys/param.h>
22 #include <sys/queue.h>
23 #include <sys/sysctl.h>
25 #include <libprocstat.h>
30 * Get the filename for the given file descriptor.
31 * Note that this may return NULL (fail) if no longer cached in the kernel.
34 get_filename_from_fd(pid_t pid
, int fd
, char *filename
, size_t len
)
38 struct procstat
*procstat
= NULL
;
39 struct kinfo_proc
*kp
= NULL
;
40 struct filestat_list
*head
= NULL
;
43 procstat
= procstat_open_sysctl();
44 if (procstat
== NULL
) {
48 kp
= procstat_getprocs(procstat
, KERN_PROC_PID
, pid
, &cnt
);
53 head
= procstat_getfiles(procstat
, kp
, 0);
58 STAILQ_FOREACH(fst
, head
, next
) {
59 if (fd
== fst
->fs_fd
) {
60 if (fst
->fs_path
!= NULL
) {
61 (void)strlcpy(filename
, fst
->fs_path
, len
);
70 procstat_freefiles(procstat
, head
);
73 procstat_freeprocs(procstat
, kp
);
75 if (procstat
!= NULL
) {
76 procstat_close(procstat
);
84 abi_long
freebsd_exec_common(abi_ulong path_or_fd
, abi_ulong guest_argp
,
85 abi_ulong guest_envp
, int do_fexec
)
87 char **argp
, **envp
, **qargp
, **qarg1
, **qarg0
, **qargend
;
97 for (gp
= guest_argp
; gp
; gp
+= sizeof(abi_ulong
)) {
98 if (get_user_ual(addr
, gp
)) {
99 return -TARGET_EFAULT
;
107 for (gp
= guest_envp
; gp
; gp
+= sizeof(abi_ulong
)) {
108 if (get_user_ual(addr
, gp
)) {
109 return -TARGET_EFAULT
;
117 qarg0
= argp
= g_new0(char *, argc
+ 9);
118 /* save the first argument for the emulator */
119 *argp
++ = (char *)getprogname();
121 *argp
++ = (char *)getprogname();
123 envp
= g_new0(char *, envc
+ 1);
124 for (gp
= guest_argp
, q
= argp
; gp
; gp
+= sizeof(abi_ulong
), q
++) {
125 if (get_user_ual(addr
, gp
)) {
126 ret
= -TARGET_EFAULT
;
132 *q
= lock_user_string(addr
);
134 ret
= -TARGET_EFAULT
;
137 total_size
+= strlen(*q
) + 1;
142 for (gp
= guest_envp
, q
= envp
; gp
; gp
+= sizeof(abi_ulong
), q
++) {
143 if (get_user_ual(addr
, gp
)) {
144 ret
= -TARGET_EFAULT
;
150 *q
= lock_user_string(addr
);
152 ret
= -TARGET_EFAULT
;
155 total_size
+= strlen(*q
) + 1;
160 * This case will not be caught by the host's execve() if its
161 * page size is bigger than the target's.
163 if (total_size
> MAX_ARG_PAGES
* TARGET_PAGE_SIZE
) {
169 if (((int)path_or_fd
> 0 &&
170 is_target_elf_binary((int)path_or_fd
)) == 1) {
171 char execpath
[PATH_MAX
];
174 * The executable is an elf binary for the target
175 * arch. execve() it using the emulator if we can
176 * determine the filename path from the fd.
178 if (get_filename_from_fd(getpid(), (int)path_or_fd
, execpath
,
179 sizeof(execpath
)) != NULL
) {
180 memmove(qarg1
+ 2, qarg1
, (qargend
- qarg1
) * sizeof(*qarg1
));
182 qarg1
[0] = (char *)"-0";
186 #ifndef DONT_INHERIT_INTERP_PREFIX
187 memmove(qarg1
+ 2, qarg1
, (qargend
- qarg1
) * sizeof(*qarg1
));
188 *qarg1
++ = (char *)"-L";
189 *qarg1
++ = (char *)interp_prefix
;
191 ret
= get_errno(execve(qemu_proc_pathname
, qargp
, envp
));
193 /* Getting the filename path failed. */
198 ret
= get_errno(fexecve((int)path_or_fd
, argp
, envp
));
203 p
= lock_user_string(path_or_fd
);
205 ret
= -TARGET_EFAULT
;
210 * Check the header and see if it a target elf binary. If so
211 * then execute using qemu user mode emulator.
213 fd
= open(p
, O_RDONLY
| O_CLOEXEC
);
214 if (fd
> 0 && is_target_elf_binary(fd
) == 1) {
216 /* execve() as a target binary using emulator. */
217 memmove(qarg1
+ 2, qarg1
, (qargend
- qarg1
) * sizeof(*qarg1
));
219 qarg1
[0] = (char *)"-0";
223 #ifndef DONT_INHERIT_INTERP_PREFIX
224 memmove(qarg1
+ 2, qarg1
, (qargend
- qarg1
) * sizeof(*qarg1
));
225 *qarg1
++ = (char *)"-L";
226 *qarg1
++ = (char *)interp_prefix
;
228 ret
= get_errno(execve(qemu_proc_pathname
, qargp
, envp
));
231 /* Execve() as a host native binary. */
232 ret
= get_errno(execve(p
, argp
, envp
));
234 unlock_user(p
, path_or_fd
, 0);
238 for (gp
= guest_argp
, q
= argp
; *q
; gp
+= sizeof(abi_ulong
), q
++) {
239 if (get_user_ual(addr
, gp
) || !addr
) {
242 unlock_user(*q
, addr
, 0);
245 for (gp
= guest_envp
, q
= envp
; *q
; gp
+= sizeof(abi_ulong
), q
++) {
246 if (get_user_ual(addr
, gp
) || !addr
) {
249 unlock_user(*q
, addr
, 0);
258 #include <sys/procctl.h>
261 t2h_procctl_cmd(int target_cmd
, int *host_cmd
)
263 switch (target_cmd
) {
264 case TARGET_PROC_SPROTECT
:
265 *host_cmd
= PROC_SPROTECT
;
268 case TARGET_PROC_REAP_ACQUIRE
:
269 *host_cmd
= PROC_REAP_ACQUIRE
;
272 case TARGET_PROC_REAP_RELEASE
:
273 *host_cmd
= PROC_REAP_RELEASE
;
276 case TARGET_PROC_REAP_STATUS
:
277 *host_cmd
= PROC_REAP_STATUS
;
280 case TARGET_PROC_REAP_KILL
:
281 *host_cmd
= PROC_REAP_KILL
;
285 return -TARGET_EINVAL
;
292 h2t_reaper_status(struct procctl_reaper_status
*host_rs
,
293 abi_ulong target_rs_addr
)
295 struct target_procctl_reaper_status
*target_rs
;
297 if (!lock_user_struct(VERIFY_WRITE
, target_rs
, target_rs_addr
, 0)) {
298 return -TARGET_EFAULT
;
300 __put_user(host_rs
->rs_flags
, &target_rs
->rs_flags
);
301 __put_user(host_rs
->rs_children
, &target_rs
->rs_children
);
302 __put_user(host_rs
->rs_descendants
, &target_rs
->rs_descendants
);
303 __put_user(host_rs
->rs_reaper
, &target_rs
->rs_reaper
);
304 __put_user(host_rs
->rs_pid
, &target_rs
->rs_pid
);
305 unlock_user_struct(target_rs
, target_rs_addr
, 1);
311 t2h_reaper_kill(abi_ulong target_rk_addr
, struct procctl_reaper_kill
*host_rk
)
313 struct target_procctl_reaper_kill
*target_rk
;
315 if (!lock_user_struct(VERIFY_READ
, target_rk
, target_rk_addr
, 1)) {
316 return -TARGET_EFAULT
;
318 __get_user(host_rk
->rk_sig
, &target_rk
->rk_sig
);
319 __get_user(host_rk
->rk_flags
, &target_rk
->rk_flags
);
320 __get_user(host_rk
->rk_subtree
, &target_rk
->rk_subtree
);
321 __get_user(host_rk
->rk_killed
, &target_rk
->rk_killed
);
322 __get_user(host_rk
->rk_fpid
, &target_rk
->rk_fpid
);
323 unlock_user_struct(target_rk
, target_rk_addr
, 0);
329 h2t_reaper_kill(struct procctl_reaper_kill
*host_rk
, abi_ulong target_rk_addr
)
331 struct target_procctl_reaper_kill
*target_rk
;
333 if (!lock_user_struct(VERIFY_WRITE
, target_rk
, target_rk_addr
, 0)) {
334 return -TARGET_EFAULT
;
336 __put_user(host_rk
->rk_sig
, &target_rk
->rk_sig
);
337 __put_user(host_rk
->rk_flags
, &target_rk
->rk_flags
);
338 __put_user(host_rk
->rk_subtree
, &target_rk
->rk_subtree
);
339 __put_user(host_rk
->rk_killed
, &target_rk
->rk_killed
);
340 __put_user(host_rk
->rk_fpid
, &target_rk
->rk_fpid
);
341 unlock_user_struct(target_rk
, target_rk_addr
, 1);
347 h2t_procctl_reaper_pidinfo(struct procctl_reaper_pidinfo
*host_pi
,
348 abi_ulong target_pi_addr
)
350 struct target_procctl_reaper_pidinfo
*target_pi
;
352 if (!lock_user_struct(VERIFY_WRITE
, target_pi
, target_pi_addr
, 0)) {
353 return -TARGET_EFAULT
;
355 __put_user(host_pi
->pi_pid
, &target_pi
->pi_pid
);
356 __put_user(host_pi
->pi_subtree
, &target_pi
->pi_subtree
);
357 __put_user(host_pi
->pi_flags
, &target_pi
->pi_flags
);
358 unlock_user_struct(target_pi
, target_pi_addr
, 1);
364 do_freebsd_procctl(void *cpu_env
, int idtype
, abi_ulong arg2
, abi_ulong arg3
,
365 abi_ulong arg4
, abi_ulong arg5
, abi_ulong arg6
)
367 abi_long error
= 0, target_rp_pids
;
370 uint32_t u
, target_rp_count
;
372 struct procctl_reaper_status rs
;
373 struct procctl_reaper_pids rp
;
374 struct procctl_reaper_kill rk
;
376 struct target_procctl_reaper_pids
*target_rp
;
377 id_t id
; /* 64-bit */
379 abi_ulong target_arg
;
381 #if TARGET_ABI_BITS == 32
382 /* See if we need to align the register pairs. */
383 if (regpairs_aligned(cpu_env
)) {
384 id
= (id_t
)target_arg64(arg3
, arg4
);
385 target_cmd
= (int)arg5
;
388 id
= (id_t
)target_arg64(arg2
, arg3
);
389 target_cmd
= (int)arg4
;
394 target_cmd
= (int)arg3
;
398 error
= t2h_procctl_cmd(target_cmd
, &host_cmd
);
407 case PROC_REAP_ACQUIRE
:
408 case PROC_REAP_RELEASE
:
409 if (target_arg
== 0) {
412 error
= -TARGET_EINVAL
;
416 case PROC_REAP_STATUS
:
420 case PROC_REAP_GETPIDS
:
421 if (!lock_user_struct(VERIFY_READ
, target_rp
, target_arg
, 1)) {
422 return -TARGET_EFAULT
;
424 __get_user(target_rp_count
, &target_rp
->rp_count
);
425 __get_user(target_rp_pids
, &target_rp
->rp_pids
);
426 unlock_user_struct(target_rp
, target_arg
, 0);
427 host
.rp
.rp_count
= target_rp_count
;
428 host
.rp
.rp_pids
= g_try_new(struct procctl_reaper_pidinfo
,
431 if (host
.rp
.rp_pids
== NULL
) {
432 error
= -TARGET_ENOMEM
;
439 error
= t2h_reaper_kill(target_arg
, &host
.rk
);
446 error
= get_errno(procctl(idtype
, id
, host_cmd
, data
));
453 if (put_user_s32(flags
, target_arg
)) {
454 return -TARGET_EFAULT
;
458 case PROC_REAP_STATUS
:
459 error
= h2t_reaper_status(&host
.rs
, target_arg
);
462 case PROC_REAP_GETPIDS
:
463 /* copyout reaper pidinfo */
464 for (u
= 0; u
< target_rp_count
; u
++) {
465 error
= h2t_procctl_reaper_pidinfo(&host
.rp
.rp_pids
[u
],
467 (u
* sizeof(struct target_procctl_reaper_pidinfo
)));
475 error
= h2t_reaper_kill(&host
.rk
, target_arg
);