1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2017 Edward Tomasz Napierala <trasz@FreeBSD.org> 5 * 6 * This software was developed by SRI International and the University of 7 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 8 * ("CTSRD"), as part of the DARPA CRASH research programme. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/lock.h> 34 #include <sys/proc.h> 35 #include <sys/ptrace.h> 36 #include <sys/sx.h> 37 #include <sys/syscallsubr.h> 38 39 #include <machine/../linux/linux.h> 40 #include <machine/../linux/linux_proto.h> 41 #include <compat/linux/linux_emul.h> 42 #include <compat/linux/linux_errno.h> 43 #include <compat/linux/linux_misc.h> 44 #include <compat/linux/linux_signal.h> 45 #include <compat/linux/linux_util.h> 46 47 #define LINUX_PTRACE_TRACEME 0 48 #define LINUX_PTRACE_PEEKTEXT 1 49 #define LINUX_PTRACE_PEEKDATA 2 50 #define LINUX_PTRACE_PEEKUSER 3 51 #define LINUX_PTRACE_POKETEXT 4 52 #define LINUX_PTRACE_POKEDATA 5 53 #define LINUX_PTRACE_POKEUSER 6 54 #define LINUX_PTRACE_CONT 7 55 #define LINUX_PTRACE_KILL 8 56 #define LINUX_PTRACE_SINGLESTEP 9 57 #define LINUX_PTRACE_GETREGS 12 58 #define LINUX_PTRACE_SETREGS 13 59 #define LINUX_PTRACE_GETFPREGS 14 60 #define LINUX_PTRACE_SETFPREGS 15 61 #define LINUX_PTRACE_ATTACH 16 62 #define LINUX_PTRACE_DETACH 17 63 #define LINUX_PTRACE_SYSCALL 24 64 #define LINUX_PTRACE_SETOPTIONS 0x4200 65 #define LINUX_PTRACE_GETEVENTMSG 0x4201 66 #define LINUX_PTRACE_GETSIGINFO 0x4202 67 #define LINUX_PTRACE_GETREGSET 0x4204 68 #define LINUX_PTRACE_SEIZE 0x4206 69 #define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e 70 71 #define LINUX_PTRACE_EVENT_EXEC 4 72 #define LINUX_PTRACE_EVENT_EXIT 6 73 74 #define LINUX_PTRACE_O_TRACESYSGOOD 1 75 #define LINUX_PTRACE_O_TRACEFORK 2 76 #define LINUX_PTRACE_O_TRACEVFORK 4 77 #define LINUX_PTRACE_O_TRACECLONE 8 78 #define LINUX_PTRACE_O_TRACEEXEC 16 79 #define LINUX_PTRACE_O_TRACEVFORKDONE 32 80 #define LINUX_PTRACE_O_TRACEEXIT 64 81 #define LINUX_PTRACE_O_TRACESECCOMP 128 82 #define LINUX_PTRACE_O_EXITKILL 1048576 83 #define LINUX_PTRACE_O_SUSPEND_SECCOMP 2097152 84 85 #define LINUX_NT_PRSTATUS 0x1 86 #define LINUX_NT_PRFPREG 0x2 87 #define LINUX_NT_X86_XSTATE 0x202 88 89 #define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \ 90 LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \ 91 LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \ 92 LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \ 93 LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \ 94 LINUX_PTRACE_O_SUSPEND_SECCOMP) 95 96 #define LINUX_PTRACE_SYSCALL_INFO_NONE 0 97 #define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1 98 #define LINUX_PTRACE_SYSCALL_INFO_EXIT 2 99 100 static int 101 map_signum(int lsig, int *bsigp) 102 { 103 int bsig; 104 105 if (lsig == 0) { 106 *bsigp = 0; 107 return (0); 108 } 109 110 if (lsig < 0 || lsig > LINUX_SIGRTMAX) 111 return (EINVAL); 112 113 bsig = linux_to_bsd_signal(lsig); 114 if (bsig == SIGSTOP) 115 bsig = 0; 116 117 *bsigp = bsig; 118 return (0); 119 } 120 121 int 122 linux_ptrace_status(struct thread *td, pid_t pid, int status) 123 { 124 struct ptrace_lwpinfo lwpinfo; 125 struct linux_pemuldata *pem; 126 register_t saved_retval; 127 int error; 128 129 saved_retval = td->td_retval[0]; 130 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 131 td->td_retval[0] = saved_retval; 132 if (error != 0) { 133 linux_msg(td, "PT_LWPINFO failed with error %d", error); 134 return (status); 135 } 136 137 pem = pem_find(td->td_proc); 138 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 139 140 LINUX_PEM_SLOCK(pem); 141 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 142 lwpinfo.pl_flags & PL_FLAG_SCE) 143 status |= (LINUX_SIGTRAP | 0x80) << 8; 144 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 145 lwpinfo.pl_flags & PL_FLAG_SCX) { 146 if (lwpinfo.pl_flags & PL_FLAG_EXEC) 147 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXEC << 8) << 8; 148 else 149 status |= (LINUX_SIGTRAP | 0x80) << 8; 150 } 151 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) && 152 lwpinfo.pl_flags & PL_FLAG_EXITED) 153 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8; 154 LINUX_PEM_SUNLOCK(pem); 155 156 return (status); 157 } 158 159 static int 160 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data) 161 { 162 int error; 163 164 error = kern_ptrace(td, PT_READ_I, pid, addr, 0); 165 if (error == 0) 166 error = copyout(td->td_retval, data, sizeof(l_int)); 167 else if (error == ENOMEM) 168 error = EIO; 169 td->td_retval[0] = error; 170 171 return (error); 172 } 173 174 static int 175 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data) 176 { 177 struct linux_pemuldata *pem; 178 int mask; 179 180 mask = 0; 181 182 if (data & ~LINUX_PTRACE_O_MASK) { 183 linux_msg(td, "unknown ptrace option %lx set; " 184 "returning EINVAL", 185 data & ~LINUX_PTRACE_O_MASK); 186 return (EINVAL); 187 } 188 189 pem = pem_find(td->td_proc); 190 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 191 192 /* 193 * PTRACE_O_EXITKILL is ignored, we do that by default. 194 */ 195 196 LINUX_PEM_XLOCK(pem); 197 if (data & LINUX_PTRACE_O_TRACESYSGOOD) { 198 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD; 199 } else { 200 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD; 201 } 202 LINUX_PEM_XUNLOCK(pem); 203 204 if (data & LINUX_PTRACE_O_TRACEFORK) 205 mask |= PTRACE_FORK; 206 207 if (data & LINUX_PTRACE_O_TRACEVFORK) 208 mask |= PTRACE_VFORK; 209 210 if (data & LINUX_PTRACE_O_TRACECLONE) 211 mask |= PTRACE_VFORK; 212 213 if (data & LINUX_PTRACE_O_TRACEEXEC) 214 mask |= PTRACE_EXEC; 215 216 if (data & LINUX_PTRACE_O_TRACEVFORKDONE) 217 mask |= PTRACE_VFORK; /* XXX: Close enough? */ 218 219 if (data & LINUX_PTRACE_O_TRACEEXIT) { 220 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT; 221 } else { 222 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT; 223 } 224 225 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask))); 226 } 227 228 static int 229 linux_ptrace_geteventmsg(struct thread *td, pid_t pid, l_ulong data) 230 { 231 232 linux_msg(td, "PTRACE_GETEVENTMSG not implemented; returning EINVAL"); 233 return (EINVAL); 234 } 235 236 static int 237 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data) 238 { 239 struct ptrace_lwpinfo lwpinfo; 240 l_siginfo_t l_siginfo; 241 int error, sig; 242 243 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 244 if (error != 0) { 245 linux_msg(td, "PT_LWPINFO failed with error %d", error); 246 return (error); 247 } 248 249 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) { 250 error = EINVAL; 251 linux_msg(td, "no PL_FLAG_SI, returning %d", error); 252 return (error); 253 } 254 255 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo); 256 memset(&l_siginfo, 0, sizeof(l_siginfo)); 257 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig); 258 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo)); 259 return (error); 260 } 261 262 static int 263 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 264 { 265 struct reg b_reg; 266 struct linux_pt_regset l_regset; 267 int error; 268 269 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 270 if (error != 0) 271 return (error); 272 273 bsd_to_linux_regset(&b_reg, &l_regset); 274 error = linux_ptrace_getregs_machdep(td, pid, &l_regset); 275 if (error != 0) 276 return (error); 277 278 error = copyout(&l_regset, (void *)data, sizeof(l_regset)); 279 return (error); 280 } 281 282 static int 283 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data) 284 { 285 struct reg b_reg; 286 struct linux_pt_regset l_regset; 287 int error; 288 289 error = copyin(data, &l_regset, sizeof(l_regset)); 290 if (error != 0) 291 return (error); 292 linux_to_bsd_regset(&b_reg, &l_regset); 293 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0); 294 return (error); 295 } 296 297 static int 298 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 299 { 300 struct reg b_reg; 301 struct linux_pt_regset l_regset; 302 struct iovec iov; 303 size_t len; 304 int error; 305 306 error = copyin((const void *)data, &iov, sizeof(iov)); 307 if (error != 0) { 308 linux_msg(td, "copyin error %d", error); 309 return (error); 310 } 311 312 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 313 if (error != 0) 314 return (error); 315 316 bsd_to_linux_regset(&b_reg, &l_regset); 317 error = linux_ptrace_getregs_machdep(td, pid, &l_regset); 318 if (error != 0) 319 return (error); 320 321 len = MIN(iov.iov_len, sizeof(l_regset)); 322 error = copyout(&l_regset, (void *)iov.iov_base, len); 323 if (error != 0) { 324 linux_msg(td, "copyout error %d", error); 325 return (error); 326 } 327 328 iov.iov_len = len; 329 error = copyout(&iov, (void *)data, sizeof(iov)); 330 if (error != 0) { 331 linux_msg(td, "iov copyout error %d", error); 332 return (error); 333 } 334 335 return (error); 336 } 337 338 static int 339 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 340 { 341 342 switch (addr) { 343 case LINUX_NT_PRSTATUS: 344 return (linux_ptrace_getregset_prstatus(td, pid, data)); 345 case LINUX_NT_PRFPREG: 346 linux_msg(td, "PTRAGE_GETREGSET NT_PRFPREG not implemented; " 347 "returning EINVAL"); 348 return (EINVAL); 349 case LINUX_NT_X86_XSTATE: 350 linux_msg(td, "PTRAGE_GETREGSET NT_X86_XSTATE not implemented; " 351 "returning EINVAL"); 352 return (EINVAL); 353 default: 354 linux_msg(td, "PTRACE_GETREGSET request %#lx not implemented; " 355 "returning EINVAL", addr); 356 return (EINVAL); 357 } 358 } 359 360 static int 361 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 362 { 363 364 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL"); 365 return (EINVAL); 366 } 367 368 static int 369 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, 370 l_ulong len, l_ulong data) 371 { 372 struct ptrace_lwpinfo lwpinfo; 373 struct ptrace_sc_ret sr; 374 struct reg b_reg; 375 struct syscall_info si; 376 int error; 377 378 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 379 if (error != 0) { 380 linux_msg(td, "PT_LWPINFO failed with error %d", error); 381 return (error); 382 } 383 384 memset(&si, 0, sizeof(si)); 385 386 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 387 si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY; 388 si.entry.nr = lwpinfo.pl_syscall_code; 389 /* 390 * The use of PT_GET_SC_ARGS there is special, 391 * implementation of PT_GET_SC_ARGS for Linux-ABI 392 * callers emulates Linux bug which strace(1) depends 393 * on: at initialization it tests whether ptrace works 394 * by calling close(2), or some other single-argument 395 * syscall, _with six arguments_, and then verifies 396 * whether it can fetch them all using this API; 397 * otherwise it bails out. 398 */ 399 error = kern_ptrace(td, PT_GET_SC_ARGS, pid, 400 &si.entry.args, sizeof(si.entry.args)); 401 if (error != 0) { 402 linux_msg(td, "PT_GET_SC_ARGS failed with error %d", 403 error); 404 return (error); 405 } 406 } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 407 si.op = LINUX_PTRACE_SYSCALL_INFO_EXIT; 408 error = kern_ptrace(td, PT_GET_SC_RET, pid, &sr, sizeof(sr)); 409 410 if (error != 0) { 411 linux_msg(td, "PT_GET_SC_RET failed with error %d", 412 error); 413 return (error); 414 } 415 416 if (sr.sr_error == 0) { 417 si.exit.rval = sr.sr_retval[0]; 418 si.exit.is_error = 0; 419 } else if (sr.sr_error == EJUSTRETURN) { 420 /* 421 * EJUSTRETURN means the actual value to return 422 * has already been put into td_frame; instead 423 * of extracting it and trying to determine whether 424 * it's an error or not just bail out and let 425 * the ptracing process fall back to another method. 426 */ 427 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 428 } else if (sr.sr_error == ERESTART) { 429 si.exit.rval = -LINUX_ERESTARTSYS; 430 si.exit.is_error = 1; 431 } else { 432 si.exit.rval = bsd_to_linux_errno(sr.sr_error); 433 si.exit.is_error = 1; 434 } 435 } else { 436 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 437 } 438 439 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 440 if (error != 0) 441 return (error); 442 443 linux_ptrace_get_syscall_info_machdep(&b_reg, &si); 444 445 len = MIN(len, sizeof(si)); 446 error = copyout(&si, (void *)data, len); 447 if (error == 0) 448 td->td_retval[0] = sizeof(si); 449 450 return (error); 451 } 452 453 int 454 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 455 { 456 void *addr; 457 pid_t pid; 458 int error, sig; 459 460 if (!allow_ptrace) 461 return (ENOSYS); 462 463 pid = (pid_t)uap->pid; 464 addr = (void *)uap->addr; 465 466 switch (uap->req) { 467 case LINUX_PTRACE_TRACEME: 468 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 469 break; 470 case LINUX_PTRACE_PEEKTEXT: 471 case LINUX_PTRACE_PEEKDATA: 472 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 473 if (error != 0) 474 goto out; 475 /* 476 * Linux expects this syscall to read 64 bits, not 32. 477 */ 478 error = linux_ptrace_peek(td, pid, 479 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 480 break; 481 case LINUX_PTRACE_PEEKUSER: 482 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data); 483 break; 484 case LINUX_PTRACE_POKETEXT: 485 case LINUX_PTRACE_POKEDATA: 486 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 487 if (error != 0) 488 goto out; 489 /* 490 * Linux expects this syscall to write 64 bits, not 32. 491 */ 492 error = kern_ptrace(td, PT_WRITE_D, pid, 493 (void *)(uap->addr + 4), uap->data >> 32); 494 break; 495 case LINUX_PTRACE_POKEUSER: 496 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data); 497 break; 498 case LINUX_PTRACE_CONT: 499 error = map_signum(uap->data, &sig); 500 if (error != 0) 501 break; 502 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 503 break; 504 case LINUX_PTRACE_KILL: 505 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 506 break; 507 case LINUX_PTRACE_SINGLESTEP: 508 error = map_signum(uap->data, &sig); 509 if (error != 0) 510 break; 511 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 512 break; 513 case LINUX_PTRACE_GETREGS: 514 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 515 break; 516 case LINUX_PTRACE_SETREGS: 517 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 518 break; 519 case LINUX_PTRACE_ATTACH: 520 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 521 break; 522 case LINUX_PTRACE_DETACH: 523 error = map_signum(uap->data, &sig); 524 if (error != 0) 525 break; 526 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 527 break; 528 case LINUX_PTRACE_SYSCALL: 529 error = map_signum(uap->data, &sig); 530 if (error != 0) 531 break; 532 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 533 break; 534 case LINUX_PTRACE_SETOPTIONS: 535 error = linux_ptrace_setoptions(td, pid, uap->data); 536 break; 537 case LINUX_PTRACE_GETEVENTMSG: 538 error = linux_ptrace_geteventmsg(td, pid, uap->data); 539 break; 540 case LINUX_PTRACE_GETSIGINFO: 541 error = linux_ptrace_getsiginfo(td, pid, uap->data); 542 break; 543 case LINUX_PTRACE_GETREGSET: 544 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 545 break; 546 case LINUX_PTRACE_SEIZE: 547 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 548 break; 549 case LINUX_PTRACE_GET_SYSCALL_INFO: 550 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data); 551 break; 552 default: 553 linux_msg(td, "ptrace(%ld, ...) not implemented; " 554 "returning EINVAL", uap->req); 555 error = EINVAL; 556 break; 557 } 558 559 out: 560 if (error == EBUSY) 561 error = ESRCH; 562 563 return (error); 564 } 565