1 /* 2 * FreeBSD process related emulation code 3 * 4 * Copyright (c) 2013-15 Stacey D. Son 5 * 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. 10 * 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. 15 * 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/>. 18 */ 19 #include "qemu/osdep.h" 20 21 #include <sys/param.h> 22 #include <sys/queue.h> 23 #include <sys/sysctl.h> 24 struct kinfo_proc; 25 #include <libprocstat.h> 26 27 #include "qemu.h" 28 29 /* 30 * Get the filename for the given file descriptor. 31 * Note that this may return NULL (fail) if no longer cached in the kernel. 32 */ 33 static char * 34 get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len) 35 { 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; 42 43 procstat = procstat_open_sysctl(); 44 if (procstat == NULL) { 45 goto out; 46 } 47 48 kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt); 49 if (kp == NULL) { 50 goto out; 51 } 52 53 head = procstat_getfiles(procstat, kp, 0); 54 if (head == NULL) { 55 goto out; 56 } 57 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; 63 } 64 break; 65 } 66 } 67 68 out: 69 if (head != NULL) { 70 procstat_freefiles(procstat, head); 71 } 72 if (kp != NULL) { 73 procstat_freeprocs(procstat, kp); 74 } 75 if (procstat != NULL) { 76 procstat_close(procstat); 77 } 78 return ret; 79 } 80 81 /* 82 * execve/fexecve 83 */ 84 abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, 85 abi_ulong guest_envp, int do_fexec) 86 { 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; 95 96 argc = 0; 97 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { 98 if (get_user_ual(addr, gp)) { 99 return -TARGET_EFAULT; 100 } 101 if (!addr) { 102 break; 103 } 104 argc++; 105 } 106 envc = 0; 107 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { 108 if (get_user_ual(addr, gp)) { 109 return -TARGET_EFAULT; 110 } 111 if (!addr) { 112 break; 113 } 114 envc++; 115 } 116 117 qarg0 = argp = g_new0(char *, argc + 9); 118 /* save the first agrument 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; 128 } 129 if (!addr) { 130 break; 131 } 132 *q = lock_user_string(addr); 133 if (*q == NULL) { 134 ret = -TARGET_EFAULT; 135 goto execve_end; 136 } 137 total_size += strlen(*q) + 1; 138 } 139 *q++ = NULL; 140 qargend = q; 141 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; 146 } 147 if (!addr) { 148 break; 149 } 150 *q = lock_user_string(addr); 151 if (*q == NULL) { 152 ret = -TARGET_EFAULT; 153 goto execve_end; 154 } 155 total_size += strlen(*q) + 1; 156 } 157 *q = NULL; 158 159 /* 160 * This case will not be caught by the host's execve() if its 161 * page size is bigger than the target's. 162 */ 163 if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) { 164 ret = -TARGET_E2BIG; 165 goto execve_end; 166 } 167 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]; 172 173 /* 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. 177 */ 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; 196 } 197 } else { 198 ret = get_errno(fexecve((int)path_or_fd, argp, envp)); 199 } 200 } else { 201 int fd; 202 203 p = lock_user_string(path_or_fd); 204 if (p == NULL) { 205 ret = -TARGET_EFAULT; 206 goto execve_end; 207 } 208 209 /* 210 * Check the header and see if it a target elf binary. If so 211 * then execute using qemu user mode emulator. 212 */ 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)); 233 } 234 unlock_user(p, path_or_fd, 0); 235 } 236 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; 241 } 242 unlock_user(*q, addr, 0); 243 } 244 245 for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) { 246 if (get_user_ual(addr, gp) || !addr) { 247 break; 248 } 249 unlock_user(*q, addr, 0); 250 } 251 252 g_free(qarg0); 253 g_free(envp); 254 255 return ret; 256 } 257 258 #include <sys/procctl.h> 259 260 static abi_long 261 t2h_procctl_cmd(int target_cmd, int *host_cmd) 262 { 263 switch (target_cmd) { 264 case TARGET_PROC_SPROTECT: 265 *host_cmd = PROC_SPROTECT; 266 break; 267 268 case TARGET_PROC_REAP_ACQUIRE: 269 *host_cmd = PROC_REAP_ACQUIRE; 270 break; 271 272 case TARGET_PROC_REAP_RELEASE: 273 *host_cmd = PROC_REAP_RELEASE; 274 break; 275 276 case TARGET_PROC_REAP_STATUS: 277 *host_cmd = PROC_REAP_STATUS; 278 break; 279 280 case TARGET_PROC_REAP_KILL: 281 *host_cmd = PROC_REAP_KILL; 282 break; 283 284 default: 285 return -TARGET_EINVAL; 286 } 287 288 return 0; 289 } 290 291 static abi_long 292 h2t_reaper_status(struct procctl_reaper_status *host_rs, 293 abi_ulong target_rs_addr) 294 { 295 struct target_procctl_reaper_status *target_rs; 296 297 if (!lock_user_struct(VERIFY_WRITE, target_rs, target_rs_addr, 0)) { 298 return -TARGET_EFAULT; 299 } 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); 306 307 return 0; 308 } 309 310 static abi_long 311 t2h_reaper_kill(abi_ulong target_rk_addr, struct procctl_reaper_kill *host_rk) 312 { 313 struct target_procctl_reaper_kill *target_rk; 314 315 if (!lock_user_struct(VERIFY_READ, target_rk, target_rk_addr, 1)) { 316 return -TARGET_EFAULT; 317 } 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); 324 325 return 0; 326 } 327 328 static abi_long 329 h2t_reaper_kill(struct procctl_reaper_kill *host_rk, abi_ulong target_rk_addr) 330 { 331 struct target_procctl_reaper_kill *target_rk; 332 333 if (!lock_user_struct(VERIFY_WRITE, target_rk, target_rk_addr, 0)) { 334 return -TARGET_EFAULT; 335 } 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); 342 343 return 0; 344 } 345 346 static abi_long 347 h2t_procctl_reaper_pidinfo(struct procctl_reaper_pidinfo *host_pi, 348 abi_ulong target_pi_addr) 349 { 350 struct target_procctl_reaper_pidinfo *target_pi; 351 352 if (!lock_user_struct(VERIFY_WRITE, target_pi, target_pi_addr, 0)) { 353 return -TARGET_EFAULT; 354 } 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); 359 360 return 0; 361 } 362 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) 366 { 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; 380 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; 391 } 392 #else 393 id = (id_t)arg2; 394 target_cmd = (int)arg3; 395 target_arg = arg4; 396 #endif 397 398 error = t2h_procctl_cmd(target_cmd, &host_cmd); 399 if (error) { 400 return error; 401 } 402 switch (host_cmd) { 403 case PROC_SPROTECT: 404 data = &flags; 405 break; 406 407 case PROC_REAP_ACQUIRE: 408 case PROC_REAP_RELEASE: 409 if (target_arg == 0) { 410 data = NULL; 411 } else { 412 error = -TARGET_EINVAL; 413 } 414 break; 415 416 case PROC_REAP_STATUS: 417 data = &host.rs; 418 break; 419 420 case PROC_REAP_GETPIDS: 421 if (!lock_user_struct(VERIFY_READ, target_rp, target_arg, 1)) { 422 return -TARGET_EFAULT; 423 } 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); 430 431 if (host.rp.rp_pids == NULL) { 432 error = -TARGET_ENOMEM; 433 } else { 434 data = &host.rp; 435 } 436 break; 437 438 case PROC_REAP_KILL: 439 error = t2h_reaper_kill(target_arg, &host.rk); 440 break; 441 } 442 443 if (error) { 444 return error; 445 } 446 error = get_errno(procctl(idtype, id, host_cmd, data)); 447 448 if (error) { 449 return error; 450 } 451 switch (host_cmd) { 452 case PROC_SPROTECT: 453 if (put_user_s32(flags, target_arg)) { 454 return -TARGET_EFAULT; 455 } 456 break; 457 458 case PROC_REAP_STATUS: 459 error = h2t_reaper_status(&host.rs, target_arg); 460 break; 461 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; 470 } 471 } 472 break; 473 474 case PROC_REAP_KILL: 475 error = h2t_reaper_kill(&host.rk, target_arg); 476 break; 477 } 478 479 return error; 480 } 481