system/qdev-monitor: move drain_call_rcu call under if (!dev) in qmp_device_add()
[qemu/ar7.git] / bsd-user / freebsd / os-proc.c
blobe0203e259b0e5b93c5d03c3a6157eb3c941f785a
1 /*
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>
24 struct kinfo_proc;
25 #include <libprocstat.h>
27 #include "qemu.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.
33 static char *
34 get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
36 char *ret = NULL;
37 unsigned int cnt;
38 struct procstat *procstat = NULL;
39 struct kinfo_proc *kp = NULL;
40 struct filestat_list *head = NULL;
41 struct filestat *fst;
43 procstat = procstat_open_sysctl();
44 if (procstat == NULL) {
45 goto out;
48 kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
49 if (kp == NULL) {
50 goto out;
53 head = procstat_getfiles(procstat, kp, 0);
54 if (head == NULL) {
55 goto out;
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);
62 ret = filename;
64 break;
68 out:
69 if (head != NULL) {
70 procstat_freefiles(procstat, head);
72 if (kp != NULL) {
73 procstat_freeprocs(procstat, kp);
75 if (procstat != NULL) {
76 procstat_close(procstat);
78 return ret;
82 * execve/fexecve
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;
88 int argc, envc;
89 abi_ulong gp;
90 abi_ulong addr;
91 char **q;
92 int total_size = 0;
93 void *p;
94 abi_long ret;
96 argc = 0;
97 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
98 if (get_user_ual(addr, gp)) {
99 return -TARGET_EFAULT;
101 if (!addr) {
102 break;
104 argc++;
106 envc = 0;
107 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
108 if (get_user_ual(addr, gp)) {
109 return -TARGET_EFAULT;
111 if (!addr) {
112 break;
114 envc++;
117 qarg0 = argp = g_new0(char *, argc + 9);
118 /* save the first argument for the emulator */
119 *argp++ = (char *)getprogname();
120 qargp = argp;
121 *argp++ = (char *)getprogname();
122 qarg1 = argp;
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;
127 goto execve_end;
129 if (!addr) {
130 break;
132 *q = lock_user_string(addr);
133 if (*q == NULL) {
134 ret = -TARGET_EFAULT;
135 goto execve_end;
137 total_size += strlen(*q) + 1;
139 *q++ = NULL;
140 qargend = q;
142 for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
143 if (get_user_ual(addr, gp)) {
144 ret = -TARGET_EFAULT;
145 goto execve_end;
147 if (!addr) {
148 break;
150 *q = lock_user_string(addr);
151 if (*q == NULL) {
152 ret = -TARGET_EFAULT;
153 goto execve_end;
155 total_size += strlen(*q) + 1;
157 *q = NULL;
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) {
164 ret = -TARGET_E2BIG;
165 goto execve_end;
168 if (do_fexec) {
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));
181 qarg1[1] = qarg1[0];
182 qarg1[0] = (char *)"-0";
183 qarg1 += 2;
184 qargend += 2;
185 *qarg1 = execpath;
186 #ifndef DONT_INHERIT_INTERP_PREFIX
187 memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
188 *qarg1++ = (char *)"-L";
189 *qarg1++ = (char *)interp_prefix;
190 #endif
191 ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
192 } else {
193 /* Getting the filename path failed. */
194 ret = -TARGET_EBADF;
195 goto execve_end;
197 } else {
198 ret = get_errno(fexecve((int)path_or_fd, argp, envp));
200 } else {
201 int fd;
203 p = lock_user_string(path_or_fd);
204 if (p == NULL) {
205 ret = -TARGET_EFAULT;
206 goto execve_end;
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) {
215 close(fd);
216 /* execve() as a target binary using emulator. */
217 memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
218 qarg1[1] = qarg1[0];
219 qarg1[0] = (char *)"-0";
220 qarg1 += 2;
221 qargend += 2;
222 *qarg1 = (char *)p;
223 #ifndef DONT_INHERIT_INTERP_PREFIX
224 memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1));
225 *qarg1++ = (char *)"-L";
226 *qarg1++ = (char *)interp_prefix;
227 #endif
228 ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
229 } else {
230 close(fd);
231 /* Execve() as a host native binary. */
232 ret = get_errno(execve(p, argp, envp));
234 unlock_user(p, path_or_fd, 0);
237 execve_end:
238 for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
239 if (get_user_ual(addr, gp) || !addr) {
240 break;
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) {
247 break;
249 unlock_user(*q, addr, 0);
252 g_free(qarg0);
253 g_free(envp);
255 return ret;
258 #include <sys/procctl.h>
260 static abi_long
261 t2h_procctl_cmd(int target_cmd, int *host_cmd)
263 switch (target_cmd) {
264 case TARGET_PROC_SPROTECT:
265 *host_cmd = PROC_SPROTECT;
266 break;
268 case TARGET_PROC_REAP_ACQUIRE:
269 *host_cmd = PROC_REAP_ACQUIRE;
270 break;
272 case TARGET_PROC_REAP_RELEASE:
273 *host_cmd = PROC_REAP_RELEASE;
274 break;
276 case TARGET_PROC_REAP_STATUS:
277 *host_cmd = PROC_REAP_STATUS;
278 break;
280 case TARGET_PROC_REAP_KILL:
281 *host_cmd = PROC_REAP_KILL;
282 break;
284 default:
285 return -TARGET_EINVAL;
288 return 0;
291 static abi_long
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);
307 return 0;
310 static abi_long
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);
325 return 0;
328 static abi_long
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);
343 return 0;
346 static abi_long
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);
360 return 0;
363 abi_long
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;
368 void *data;
369 int host_cmd, flags;
370 uint32_t u, target_rp_count;
371 g_autofree union {
372 struct procctl_reaper_status rs;
373 struct procctl_reaper_pids rp;
374 struct procctl_reaper_kill rk;
375 } host;
376 struct target_procctl_reaper_pids *target_rp;
377 id_t id; /* 64-bit */
378 int target_cmd;
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;
386 target_arg = arg6;
387 } else {
388 id = (id_t)target_arg64(arg2, arg3);
389 target_cmd = (int)arg4;
390 target_arg = arg5;
392 #else
393 id = (id_t)arg2;
394 target_cmd = (int)arg3;
395 target_arg = arg4;
396 #endif
398 error = t2h_procctl_cmd(target_cmd, &host_cmd);
399 if (error) {
400 return error;
402 switch (host_cmd) {
403 case PROC_SPROTECT:
404 data = &flags;
405 break;
407 case PROC_REAP_ACQUIRE:
408 case PROC_REAP_RELEASE:
409 if (target_arg == 0) {
410 data = NULL;
411 } else {
412 error = -TARGET_EINVAL;
414 break;
416 case PROC_REAP_STATUS:
417 data = &host.rs;
418 break;
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,
429 target_rp_count);
431 if (host.rp.rp_pids == NULL) {
432 error = -TARGET_ENOMEM;
433 } else {
434 data = &host.rp;
436 break;
438 case PROC_REAP_KILL:
439 error = t2h_reaper_kill(target_arg, &host.rk);
440 break;
443 if (error) {
444 return error;
446 error = get_errno(procctl(idtype, id, host_cmd, data));
448 if (error) {
449 return error;
451 switch (host_cmd) {
452 case PROC_SPROTECT:
453 if (put_user_s32(flags, target_arg)) {
454 return -TARGET_EFAULT;
456 break;
458 case PROC_REAP_STATUS:
459 error = h2t_reaper_status(&host.rs, target_arg);
460 break;
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],
466 target_rp_pids +
467 (u * sizeof(struct target_procctl_reaper_pidinfo)));
468 if (error) {
469 break;
472 break;
474 case PROC_REAP_KILL:
475 error = h2t_reaper_kill(&host.rk, target_arg);
476 break;
479 return error;