1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2017 Edward Tomasz Napierala <[email protected]> 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/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/lock.h> 37 #include <sys/proc.h> 38 #include <sys/ptrace.h> 39 #include <sys/sx.h> 40 #include <sys/syscallsubr.h> 41 42 #include <machine/pcb.h> 43 #include <machine/reg.h> 44 45 #include <amd64/linux/linux.h> 46 #include <amd64/linux/linux_proto.h> 47 #include <compat/linux/linux_emul.h> 48 #include <compat/linux/linux_errno.h> 49 #include <compat/linux/linux_misc.h> 50 #include <compat/linux/linux_signal.h> 51 #include <compat/linux/linux_util.h> 52 53 #define LINUX_PTRACE_TRACEME 0 54 #define LINUX_PTRACE_PEEKTEXT 1 55 #define LINUX_PTRACE_PEEKDATA 2 56 #define LINUX_PTRACE_PEEKUSER 3 57 #define LINUX_PTRACE_POKETEXT 4 58 #define LINUX_PTRACE_POKEDATA 5 59 #define LINUX_PTRACE_POKEUSER 6 60 #define LINUX_PTRACE_CONT 7 61 #define LINUX_PTRACE_KILL 8 62 #define LINUX_PTRACE_SINGLESTEP 9 63 #define LINUX_PTRACE_GETREGS 12 64 #define LINUX_PTRACE_SETREGS 13 65 #define LINUX_PTRACE_GETFPREGS 14 66 #define LINUX_PTRACE_SETFPREGS 15 67 #define LINUX_PTRACE_ATTACH 16 68 #define LINUX_PTRACE_DETACH 17 69 #define LINUX_PTRACE_SYSCALL 24 70 #define LINUX_PTRACE_SETOPTIONS 0x4200 71 #define LINUX_PTRACE_GETEVENTMSG 0x4201 72 #define LINUX_PTRACE_GETSIGINFO 0x4202 73 #define LINUX_PTRACE_GETREGSET 0x4204 74 #define LINUX_PTRACE_SEIZE 0x4206 75 #define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e 76 77 #define LINUX_PTRACE_EVENT_EXEC 4 78 #define LINUX_PTRACE_EVENT_EXIT 6 79 80 #define LINUX_PTRACE_O_TRACESYSGOOD 1 81 #define LINUX_PTRACE_O_TRACEFORK 2 82 #define LINUX_PTRACE_O_TRACEVFORK 4 83 #define LINUX_PTRACE_O_TRACECLONE 8 84 #define LINUX_PTRACE_O_TRACEEXEC 16 85 #define LINUX_PTRACE_O_TRACEVFORKDONE 32 86 #define LINUX_PTRACE_O_TRACEEXIT 64 87 #define LINUX_PTRACE_O_TRACESECCOMP 128 88 #define LINUX_PTRACE_O_EXITKILL 1048576 89 #define LINUX_PTRACE_O_SUSPEND_SECCOMP 2097152 90 91 #define LINUX_NT_PRSTATUS 0x1 92 #define LINUX_NT_PRFPREG 0x2 93 #define LINUX_NT_X86_XSTATE 0x202 94 95 #define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \ 96 LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \ 97 LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \ 98 LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \ 99 LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \ 100 LINUX_PTRACE_O_SUSPEND_SECCOMP) 101 102 #define LINUX_PTRACE_SYSCALL_INFO_NONE 0 103 #define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1 104 #define LINUX_PTRACE_SYSCALL_INFO_EXIT 2 105 106 #define LINUX_PTRACE_PEEKUSER_ORIG_RAX 120 107 #define LINUX_PTRACE_PEEKUSER_RIP 128 108 #define LINUX_PTRACE_PEEKUSER_CS 136 109 #define LINUX_PTRACE_PEEKUSER_DS 184 110 111 #define LINUX_ARCH_AMD64 0xc000003e 112 113 static int 114 map_signum(int lsig, int *bsigp) 115 { 116 int bsig; 117 118 if (lsig == 0) { 119 *bsigp = 0; 120 return (0); 121 } 122 123 if (lsig < 0 || lsig > LINUX_SIGRTMAX) 124 return (EINVAL); 125 126 bsig = linux_to_bsd_signal(lsig); 127 if (bsig == SIGSTOP) 128 bsig = 0; 129 130 *bsigp = bsig; 131 return (0); 132 } 133 134 int 135 linux_ptrace_status(struct thread *td, pid_t pid, int status) 136 { 137 struct ptrace_lwpinfo lwpinfo; 138 struct linux_pemuldata *pem; 139 register_t saved_retval; 140 int error; 141 142 saved_retval = td->td_retval[0]; 143 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 144 td->td_retval[0] = saved_retval; 145 if (error != 0) { 146 linux_msg(td, "PT_LWPINFO failed with error %d", error); 147 return (status); 148 } 149 150 pem = pem_find(td->td_proc); 151 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 152 153 LINUX_PEM_SLOCK(pem); 154 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 155 lwpinfo.pl_flags & PL_FLAG_SCE) 156 status |= (LINUX_SIGTRAP | 0x80) << 8; 157 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 158 lwpinfo.pl_flags & PL_FLAG_SCX) { 159 if (lwpinfo.pl_flags & PL_FLAG_EXEC) 160 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXEC << 8) << 8; 161 else 162 status |= (LINUX_SIGTRAP | 0x80) << 8; 163 } 164 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) && 165 lwpinfo.pl_flags & PL_FLAG_EXITED) 166 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8; 167 LINUX_PEM_SUNLOCK(pem); 168 169 return (status); 170 } 171 172 struct linux_pt_reg { 173 l_ulong r15; 174 l_ulong r14; 175 l_ulong r13; 176 l_ulong r12; 177 l_ulong rbp; 178 l_ulong rbx; 179 l_ulong r11; 180 l_ulong r10; 181 l_ulong r9; 182 l_ulong r8; 183 l_ulong rax; 184 l_ulong rcx; 185 l_ulong rdx; 186 l_ulong rsi; 187 l_ulong rdi; 188 l_ulong orig_rax; 189 l_ulong rip; 190 l_ulong cs; 191 l_ulong eflags; 192 l_ulong rsp; 193 l_ulong ss; 194 }; 195 196 struct syscall_info { 197 uint8_t op; 198 uint32_t arch; 199 uint64_t instruction_pointer; 200 uint64_t stack_pointer; 201 union { 202 struct { 203 uint64_t nr; 204 uint64_t args[6]; 205 } entry; 206 struct { 207 int64_t rval; 208 uint8_t is_error; 209 } exit; 210 struct { 211 uint64_t nr; 212 uint64_t args[6]; 213 uint32_t ret_data; 214 } seccomp; 215 }; 216 }; 217 218 /* 219 * Translate amd64 ptrace registers between Linux and FreeBSD formats. 220 * The translation is pretty straighforward, for all registers but 221 * orig_rax on Linux side and r_trapno and r_err in FreeBSD. 222 */ 223 static void 224 map_regs_to_linux(struct reg *b_reg, struct linux_pt_reg *l_reg) 225 { 226 227 l_reg->r15 = b_reg->r_r15; 228 l_reg->r14 = b_reg->r_r14; 229 l_reg->r13 = b_reg->r_r13; 230 l_reg->r12 = b_reg->r_r12; 231 l_reg->rbp = b_reg->r_rbp; 232 l_reg->rbx = b_reg->r_rbx; 233 l_reg->r11 = b_reg->r_r11; 234 l_reg->r10 = b_reg->r_r10; 235 l_reg->r9 = b_reg->r_r9; 236 l_reg->r8 = b_reg->r_r8; 237 l_reg->rax = b_reg->r_rax; 238 l_reg->rcx = b_reg->r_rcx; 239 l_reg->rdx = b_reg->r_rdx; 240 l_reg->rsi = b_reg->r_rsi; 241 l_reg->rdi = b_reg->r_rdi; 242 l_reg->orig_rax = b_reg->r_rax; 243 l_reg->rip = b_reg->r_rip; 244 l_reg->cs = b_reg->r_cs; 245 l_reg->eflags = b_reg->r_rflags; 246 l_reg->rsp = b_reg->r_rsp; 247 l_reg->ss = b_reg->r_ss; 248 } 249 250 void 251 bsd_to_linux_regset(struct reg *b_reg, struct linux_pt_regset *l_regset) 252 { 253 254 l_regset->r15 = b_reg->r_r15; 255 l_regset->r14 = b_reg->r_r14; 256 l_regset->r13 = b_reg->r_r13; 257 l_regset->r12 = b_reg->r_r12; 258 l_regset->rbp = b_reg->r_rbp; 259 l_regset->rbx = b_reg->r_rbx; 260 l_regset->r11 = b_reg->r_r11; 261 l_regset->r10 = b_reg->r_r10; 262 l_regset->r9 = b_reg->r_r9; 263 l_regset->r8 = b_reg->r_r8; 264 l_regset->rax = b_reg->r_rax; 265 l_regset->rcx = b_reg->r_rcx; 266 l_regset->rdx = b_reg->r_rdx; 267 l_regset->rsi = b_reg->r_rsi; 268 l_regset->rdi = b_reg->r_rdi; 269 l_regset->orig_rax = b_reg->r_rax; 270 l_regset->rip = b_reg->r_rip; 271 l_regset->cs = b_reg->r_cs; 272 l_regset->eflags = b_reg->r_rflags; 273 l_regset->rsp = b_reg->r_rsp; 274 l_regset->ss = b_reg->r_ss; 275 l_regset->fs_base = 0; 276 l_regset->gs_base = 0; 277 l_regset->ds = b_reg->r_ds; 278 l_regset->es = b_reg->r_es; 279 l_regset->fs = b_reg->r_fs; 280 l_regset->gs = b_reg->r_gs; 281 } 282 283 static void 284 map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg) 285 { 286 b_reg->r_r15 = l_reg->r15; 287 b_reg->r_r14 = l_reg->r14; 288 b_reg->r_r13 = l_reg->r13; 289 b_reg->r_r12 = l_reg->r12; 290 b_reg->r_r11 = l_reg->r11; 291 b_reg->r_r10 = l_reg->r10; 292 b_reg->r_r9 = l_reg->r9; 293 b_reg->r_r8 = l_reg->r8; 294 b_reg->r_rdi = l_reg->rdi; 295 b_reg->r_rsi = l_reg->rsi; 296 b_reg->r_rbp = l_reg->rbp; 297 b_reg->r_rbx = l_reg->rbx; 298 b_reg->r_rdx = l_reg->rdx; 299 b_reg->r_rcx = l_reg->rcx; 300 b_reg->r_rax = l_reg->rax; 301 302 /* 303 * XXX: Are zeroes the right thing to put here? 304 */ 305 b_reg->r_trapno = 0; 306 b_reg->r_fs = 0; 307 b_reg->r_gs = 0; 308 b_reg->r_err = 0; 309 b_reg->r_es = 0; 310 b_reg->r_ds = 0; 311 312 b_reg->r_rip = l_reg->rip; 313 b_reg->r_cs = l_reg->cs; 314 b_reg->r_rflags = l_reg->eflags; 315 b_reg->r_rsp = l_reg->rsp; 316 b_reg->r_ss = l_reg->ss; 317 } 318 319 static int 320 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data) 321 { 322 int error; 323 324 error = kern_ptrace(td, PT_READ_I, pid, addr, 0); 325 if (error == 0) 326 error = copyout(td->td_retval, data, sizeof(l_int)); 327 else if (error == ENOMEM) 328 error = EIO; 329 td->td_retval[0] = error; 330 331 return (error); 332 } 333 334 static int 335 linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data) 336 { 337 struct reg b_reg; 338 uint64_t val; 339 int error; 340 341 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 342 if (error != 0) 343 return (error); 344 345 switch ((uintptr_t)addr) { 346 case LINUX_PTRACE_PEEKUSER_ORIG_RAX: 347 val = b_reg.r_rax; 348 break; 349 case LINUX_PTRACE_PEEKUSER_RIP: 350 val = b_reg.r_rip; 351 break; 352 case LINUX_PTRACE_PEEKUSER_CS: 353 val = b_reg.r_cs; 354 break; 355 case LINUX_PTRACE_PEEKUSER_DS: 356 val = b_reg.r_ds; 357 break; 358 default: 359 linux_msg(td, "PTRACE_PEEKUSER offset %ld not implemented; " 360 "returning EINVAL", (uintptr_t)addr); 361 return (EINVAL); 362 } 363 364 error = copyout(&val, data, sizeof(val)); 365 td->td_retval[0] = error; 366 367 return (error); 368 } 369 370 static int 371 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data) 372 { 373 374 linux_msg(td, "PTRACE_POKEUSER not implemented; returning EINVAL"); 375 return (EINVAL); 376 } 377 378 static int 379 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data) 380 { 381 struct linux_pemuldata *pem; 382 int mask; 383 384 mask = 0; 385 386 if (data & ~LINUX_PTRACE_O_MASK) { 387 linux_msg(td, "unknown ptrace option %lx set; " 388 "returning EINVAL", 389 data & ~LINUX_PTRACE_O_MASK); 390 return (EINVAL); 391 } 392 393 pem = pem_find(td->td_proc); 394 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 395 396 /* 397 * PTRACE_O_EXITKILL is ignored, we do that by default. 398 */ 399 400 LINUX_PEM_XLOCK(pem); 401 if (data & LINUX_PTRACE_O_TRACESYSGOOD) { 402 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD; 403 } else { 404 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD; 405 } 406 LINUX_PEM_XUNLOCK(pem); 407 408 if (data & LINUX_PTRACE_O_TRACEFORK) 409 mask |= PTRACE_FORK; 410 411 if (data & LINUX_PTRACE_O_TRACEVFORK) 412 mask |= PTRACE_VFORK; 413 414 if (data & LINUX_PTRACE_O_TRACECLONE) 415 mask |= PTRACE_VFORK; 416 417 if (data & LINUX_PTRACE_O_TRACEEXEC) 418 mask |= PTRACE_EXEC; 419 420 if (data & LINUX_PTRACE_O_TRACEVFORKDONE) 421 mask |= PTRACE_VFORK; /* XXX: Close enough? */ 422 423 if (data & LINUX_PTRACE_O_TRACEEXIT) { 424 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT; 425 } else { 426 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT; 427 } 428 429 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask))); 430 } 431 432 static int 433 linux_ptrace_geteventmsg(struct thread *td, pid_t pid, l_ulong data) 434 { 435 436 linux_msg(td, "PTRACE_GETEVENTMSG not implemented; returning EINVAL"); 437 return (EINVAL); 438 } 439 440 static int 441 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data) 442 { 443 struct ptrace_lwpinfo lwpinfo; 444 l_siginfo_t l_siginfo; 445 int error, sig; 446 447 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 448 if (error != 0) { 449 linux_msg(td, "PT_LWPINFO failed with error %d", error); 450 return (error); 451 } 452 453 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) { 454 error = EINVAL; 455 linux_msg(td, "no PL_FLAG_SI, returning %d", error); 456 return (error); 457 } 458 459 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo); 460 memset(&l_siginfo, 0, sizeof(l_siginfo)); 461 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig); 462 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo)); 463 return (error); 464 } 465 466 static int 467 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 468 { 469 struct ptrace_lwpinfo lwpinfo; 470 struct reg b_reg; 471 struct linux_pt_reg l_reg; 472 int error; 473 474 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 475 if (error != 0) 476 return (error); 477 478 map_regs_to_linux(&b_reg, &l_reg); 479 480 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 481 if (error != 0) { 482 linux_msg(td, "PT_LWPINFO failed with error %d", error); 483 return (error); 484 } 485 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 486 /* 487 * The strace(1) utility depends on RAX being set to -ENOSYS 488 * on syscall entry; otherwise it loops printing those: 489 * 490 * [ Process PID=928 runs in 64 bit mode. ] 491 * [ Process PID=928 runs in x32 mode. ] 492 */ 493 l_reg.rax = -38; /* -ENOSYS */ 494 495 /* 496 * Undo the mangling done in exception.S:fast_syscall_common(). 497 */ 498 l_reg.r10 = l_reg.rcx; 499 } 500 501 error = copyout(&l_reg, (void *)data, sizeof(l_reg)); 502 return (error); 503 } 504 505 static int 506 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data) 507 { 508 struct reg b_reg; 509 struct linux_pt_reg l_reg; 510 int error; 511 512 error = copyin(data, &l_reg, sizeof(l_reg)); 513 if (error != 0) 514 return (error); 515 map_regs_from_linux(&b_reg, &l_reg); 516 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0); 517 return (error); 518 } 519 520 static int 521 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 522 { 523 struct ptrace_lwpinfo lwpinfo; 524 struct reg b_reg; 525 struct linux_pt_regset l_regset; 526 struct iovec iov; 527 struct pcb *pcb; 528 size_t len; 529 int error; 530 531 error = copyin((const void *)data, &iov, sizeof(iov)); 532 if (error != 0) { 533 linux_msg(td, "copyin error %d", error); 534 return (error); 535 } 536 537 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 538 if (error != 0) 539 return (error); 540 541 pcb = td->td_pcb; 542 if (td == curthread) 543 update_pcb_bases(pcb); 544 545 bsd_to_linux_regset(&b_reg, &l_regset); 546 l_regset.fs_base = pcb->pcb_fsbase; 547 l_regset.gs_base = pcb->pcb_gsbase; 548 549 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 550 if (error != 0) { 551 linux_msg(td, "PT_LWPINFO failed with error %d", error); 552 return (error); 553 } 554 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 555 /* 556 * Undo the mangling done in exception.S:fast_syscall_common(). 557 */ 558 l_regset.r10 = l_regset.rcx; 559 } 560 561 if (lwpinfo.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) { 562 /* 563 * In Linux, the syscall number - passed to the syscall 564 * as rax - is preserved in orig_rax; rax gets overwritten 565 * with syscall return value. 566 */ 567 l_regset.orig_rax = lwpinfo.pl_syscall_code; 568 } 569 570 len = MIN(iov.iov_len, sizeof(l_regset)); 571 error = copyout(&l_regset, (void *)iov.iov_base, len); 572 if (error != 0) { 573 linux_msg(td, "copyout error %d", error); 574 return (error); 575 } 576 577 iov.iov_len = len; 578 error = copyout(&iov, (void *)data, sizeof(iov)); 579 if (error != 0) { 580 linux_msg(td, "iov copyout error %d", error); 581 return (error); 582 } 583 584 return (error); 585 } 586 587 static int 588 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 589 { 590 591 switch (addr) { 592 case LINUX_NT_PRSTATUS: 593 return (linux_ptrace_getregset_prstatus(td, pid, data)); 594 case LINUX_NT_PRFPREG: 595 linux_msg(td, "PTRAGE_GETREGSET NT_PRFPREG not implemented; " 596 "returning EINVAL"); 597 return (EINVAL); 598 case LINUX_NT_X86_XSTATE: 599 linux_msg(td, "PTRAGE_GETREGSET NT_X86_XSTATE not implemented; " 600 "returning EINVAL"); 601 return (EINVAL); 602 default: 603 linux_msg(td, "PTRACE_GETREGSET request %#lx not implemented; " 604 "returning EINVAL", addr); 605 return (EINVAL); 606 } 607 } 608 609 static int 610 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 611 { 612 613 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL"); 614 return (EINVAL); 615 } 616 617 static int 618 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, 619 l_ulong len, l_ulong data) 620 { 621 struct ptrace_lwpinfo lwpinfo; 622 struct ptrace_sc_ret sr; 623 struct reg b_reg; 624 struct syscall_info si; 625 int error; 626 627 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 628 if (error != 0) { 629 linux_msg(td, "PT_LWPINFO failed with error %d", error); 630 return (error); 631 } 632 633 memset(&si, 0, sizeof(si)); 634 635 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 636 si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY; 637 si.entry.nr = lwpinfo.pl_syscall_code; 638 /* 639 * The use of PT_GET_SC_ARGS there is special, 640 * implementation of PT_GET_SC_ARGS for Linux-ABI 641 * callers emulates Linux bug which strace(1) depends 642 * on: at initialization it tests whether ptrace works 643 * by calling close(2), or some other single-argument 644 * syscall, _with six arguments_, and then verifies 645 * whether it can fetch them all using this API; 646 * otherwise it bails out. 647 */ 648 error = kern_ptrace(td, PT_GET_SC_ARGS, pid, 649 &si.entry.args, sizeof(si.entry.args)); 650 if (error != 0) { 651 linux_msg(td, "PT_GET_SC_ARGS failed with error %d", 652 error); 653 return (error); 654 } 655 } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 656 si.op = LINUX_PTRACE_SYSCALL_INFO_EXIT; 657 error = kern_ptrace(td, PT_GET_SC_RET, pid, &sr, sizeof(sr)); 658 659 if (error != 0) { 660 linux_msg(td, "PT_GET_SC_RET failed with error %d", 661 error); 662 return (error); 663 } 664 665 if (sr.sr_error == 0) { 666 si.exit.rval = sr.sr_retval[0]; 667 si.exit.is_error = 0; 668 } else if (sr.sr_error == EJUSTRETURN) { 669 /* 670 * EJUSTRETURN means the actual value to return 671 * has already been put into td_frame; instead 672 * of extracting it and trying to determine whether 673 * it's an error or not just bail out and let 674 * the ptracing process fall back to another method. 675 */ 676 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 677 } else if (sr.sr_error == ERESTART) { 678 si.exit.rval = -LINUX_ERESTARTSYS; 679 si.exit.is_error = 1; 680 } else { 681 si.exit.rval = bsd_to_linux_errno(sr.sr_error); 682 si.exit.is_error = 1; 683 } 684 } else { 685 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 686 } 687 688 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 689 if (error != 0) 690 return (error); 691 692 si.arch = LINUX_ARCH_AMD64; 693 si.instruction_pointer = b_reg.r_rip; 694 si.stack_pointer = b_reg.r_rsp; 695 696 len = MIN(len, sizeof(si)); 697 error = copyout(&si, (void *)data, len); 698 if (error == 0) 699 td->td_retval[0] = sizeof(si); 700 701 return (error); 702 } 703 704 int 705 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 706 { 707 void *addr; 708 pid_t pid; 709 int error, sig; 710 711 if (!allow_ptrace) 712 return (ENOSYS); 713 714 pid = (pid_t)uap->pid; 715 addr = (void *)uap->addr; 716 717 switch (uap->req) { 718 case LINUX_PTRACE_TRACEME: 719 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 720 break; 721 case LINUX_PTRACE_PEEKTEXT: 722 case LINUX_PTRACE_PEEKDATA: 723 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 724 if (error != 0) 725 goto out; 726 /* 727 * Linux expects this syscall to read 64 bits, not 32. 728 */ 729 error = linux_ptrace_peek(td, pid, 730 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 731 break; 732 case LINUX_PTRACE_PEEKUSER: 733 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data); 734 break; 735 case LINUX_PTRACE_POKETEXT: 736 case LINUX_PTRACE_POKEDATA: 737 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 738 if (error != 0) 739 goto out; 740 /* 741 * Linux expects this syscall to write 64 bits, not 32. 742 */ 743 error = kern_ptrace(td, PT_WRITE_D, pid, 744 (void *)(uap->addr + 4), uap->data >> 32); 745 break; 746 case LINUX_PTRACE_POKEUSER: 747 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data); 748 break; 749 case LINUX_PTRACE_CONT: 750 error = map_signum(uap->data, &sig); 751 if (error != 0) 752 break; 753 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 754 break; 755 case LINUX_PTRACE_KILL: 756 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 757 break; 758 case LINUX_PTRACE_SINGLESTEP: 759 error = map_signum(uap->data, &sig); 760 if (error != 0) 761 break; 762 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 763 break; 764 case LINUX_PTRACE_GETREGS: 765 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 766 break; 767 case LINUX_PTRACE_SETREGS: 768 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 769 break; 770 case LINUX_PTRACE_ATTACH: 771 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 772 break; 773 case LINUX_PTRACE_DETACH: 774 error = map_signum(uap->data, &sig); 775 if (error != 0) 776 break; 777 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 778 break; 779 case LINUX_PTRACE_SYSCALL: 780 error = map_signum(uap->data, &sig); 781 if (error != 0) 782 break; 783 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 784 break; 785 case LINUX_PTRACE_SETOPTIONS: 786 error = linux_ptrace_setoptions(td, pid, uap->data); 787 break; 788 case LINUX_PTRACE_GETEVENTMSG: 789 error = linux_ptrace_geteventmsg(td, pid, uap->data); 790 break; 791 case LINUX_PTRACE_GETSIGINFO: 792 error = linux_ptrace_getsiginfo(td, pid, uap->data); 793 break; 794 case LINUX_PTRACE_GETREGSET: 795 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 796 break; 797 case LINUX_PTRACE_SEIZE: 798 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 799 break; 800 case LINUX_PTRACE_GET_SYSCALL_INFO: 801 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data); 802 break; 803 default: 804 linux_msg(td, "ptrace(%ld, ...) not implemented; " 805 "returning EINVAL", uap->req); 806 error = EINVAL; 807 break; 808 } 809 810 out: 811 if (error == EBUSY) 812 error = ESRCH; 813 814 return (error); 815 } 816