1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2017 Edward Tomasz Napierala <[email protected]> 5 * All rights reserved. 6 * 7 * This software was developed by SRI International and the University of 8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 9 * ("CTSRD"), as part of the DARPA CRASH research programme. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/lock.h> 38 #include <sys/proc.h> 39 #include <sys/ptrace.h> 40 #include <sys/sx.h> 41 #include <sys/syscallsubr.h> 42 43 #include <machine/pcb.h> 44 #include <machine/reg.h> 45 46 #include <amd64/linux/linux.h> 47 #include <amd64/linux/linux_proto.h> 48 #include <compat/linux/linux_emul.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_GETSIGINFO 0x4202 72 #define LINUX_PTRACE_GETREGSET 0x4204 73 #define LINUX_PTRACE_SEIZE 0x4206 74 #define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e 75 76 #define LINUX_PTRACE_EVENT_EXIT 6 77 78 #define LINUX_PTRACE_O_TRACESYSGOOD 1 79 #define LINUX_PTRACE_O_TRACEFORK 2 80 #define LINUX_PTRACE_O_TRACEVFORK 4 81 #define LINUX_PTRACE_O_TRACECLONE 8 82 #define LINUX_PTRACE_O_TRACEEXEC 16 83 #define LINUX_PTRACE_O_TRACEVFORKDONE 32 84 #define LINUX_PTRACE_O_TRACEEXIT 64 85 #define LINUX_PTRACE_O_TRACESECCOMP 128 86 #define LINUX_PTRACE_O_EXITKILL 1048576 87 #define LINUX_PTRACE_O_SUSPEND_SECCOMP 2097152 88 89 #define LINUX_NT_PRSTATUS 1 90 91 #define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \ 92 LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \ 93 LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \ 94 LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \ 95 LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \ 96 LINUX_PTRACE_O_SUSPEND_SECCOMP) 97 98 static int 99 map_signum(int lsig, int *bsigp) 100 { 101 int bsig; 102 103 if (lsig == 0) { 104 *bsigp = 0; 105 return (0); 106 } 107 108 if (lsig < 0 || lsig > LINUX_SIGRTMAX) 109 return (EINVAL); 110 111 bsig = linux_to_bsd_signal(lsig); 112 if (bsig == SIGSTOP) 113 bsig = 0; 114 115 *bsigp = bsig; 116 return (0); 117 } 118 119 int 120 linux_ptrace_status(struct thread *td, pid_t pid, int status) 121 { 122 struct ptrace_lwpinfo lwpinfo; 123 struct linux_pemuldata *pem; 124 register_t saved_retval; 125 int error; 126 127 saved_retval = td->td_retval[0]; 128 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 129 td->td_retval[0] = saved_retval; 130 if (error != 0) { 131 linux_msg(td, "PT_LWPINFO failed with error %d", error); 132 return (status); 133 } 134 135 pem = pem_find(td->td_proc); 136 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 137 138 LINUX_PEM_SLOCK(pem); 139 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 140 lwpinfo.pl_flags & PL_FLAG_SCE) 141 status |= (LINUX_SIGTRAP | 0x80) << 8; 142 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 143 lwpinfo.pl_flags & PL_FLAG_SCX) 144 status |= (LINUX_SIGTRAP | 0x80) << 8; 145 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) && 146 lwpinfo.pl_flags & PL_FLAG_EXITED) 147 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8; 148 LINUX_PEM_SUNLOCK(pem); 149 150 return (status); 151 } 152 153 struct linux_pt_reg { 154 l_ulong r15; 155 l_ulong r14; 156 l_ulong r13; 157 l_ulong r12; 158 l_ulong rbp; 159 l_ulong rbx; 160 l_ulong r11; 161 l_ulong r10; 162 l_ulong r9; 163 l_ulong r8; 164 l_ulong rax; 165 l_ulong rcx; 166 l_ulong rdx; 167 l_ulong rsi; 168 l_ulong rdi; 169 l_ulong orig_rax; 170 l_ulong rip; 171 l_ulong cs; 172 l_ulong eflags; 173 l_ulong rsp; 174 l_ulong ss; 175 }; 176 177 struct linux_pt_regset { 178 l_ulong r15; 179 l_ulong r14; 180 l_ulong r13; 181 l_ulong r12; 182 l_ulong rbp; 183 l_ulong rbx; 184 l_ulong r11; 185 l_ulong r10; 186 l_ulong r9; 187 l_ulong r8; 188 l_ulong rax; 189 l_ulong rcx; 190 l_ulong rdx; 191 l_ulong rsi; 192 l_ulong rdi; 193 l_ulong orig_rax; 194 l_ulong rip; 195 l_ulong cs; 196 l_ulong eflags; 197 l_ulong rsp; 198 l_ulong ss; 199 l_ulong fs_base; 200 l_ulong gs_base; 201 l_ulong ds; 202 l_ulong es; 203 l_ulong fs; 204 l_ulong gs; 205 }; 206 207 /* 208 * Translate amd64 ptrace registers between Linux and FreeBSD formats. 209 * The translation is pretty straighforward, for all registers but 210 * orig_rax on Linux side and r_trapno and r_err in FreeBSD. 211 */ 212 static void 213 map_regs_to_linux(struct reg *b_reg, struct linux_pt_reg *l_reg) 214 { 215 216 l_reg->r15 = b_reg->r_r15; 217 l_reg->r14 = b_reg->r_r14; 218 l_reg->r13 = b_reg->r_r13; 219 l_reg->r12 = b_reg->r_r12; 220 l_reg->rbp = b_reg->r_rbp; 221 l_reg->rbx = b_reg->r_rbx; 222 l_reg->r11 = b_reg->r_r11; 223 l_reg->r10 = b_reg->r_r10; 224 l_reg->r9 = b_reg->r_r9; 225 l_reg->r8 = b_reg->r_r8; 226 l_reg->rax = b_reg->r_rax; 227 l_reg->rcx = b_reg->r_rcx; 228 l_reg->rdx = b_reg->r_rdx; 229 l_reg->rsi = b_reg->r_rsi; 230 l_reg->rdi = b_reg->r_rdi; 231 l_reg->orig_rax = b_reg->r_rax; 232 l_reg->rip = b_reg->r_rip; 233 l_reg->cs = b_reg->r_cs; 234 l_reg->eflags = b_reg->r_rflags; 235 l_reg->rsp = b_reg->r_rsp; 236 l_reg->ss = b_reg->r_ss; 237 } 238 239 static void 240 map_regs_to_linux_regset(struct reg *b_reg, unsigned long fs_base, 241 unsigned long gs_base, struct linux_pt_regset *l_regset) 242 { 243 244 l_regset->r15 = b_reg->r_r15; 245 l_regset->r14 = b_reg->r_r14; 246 l_regset->r13 = b_reg->r_r13; 247 l_regset->r12 = b_reg->r_r12; 248 l_regset->rbp = b_reg->r_rbp; 249 l_regset->rbx = b_reg->r_rbx; 250 l_regset->r11 = b_reg->r_r11; 251 l_regset->r10 = b_reg->r_r10; 252 l_regset->r9 = b_reg->r_r9; 253 l_regset->r8 = b_reg->r_r8; 254 l_regset->rax = b_reg->r_rax; 255 l_regset->rcx = b_reg->r_rcx; 256 l_regset->rdx = b_reg->r_rdx; 257 l_regset->rsi = b_reg->r_rsi; 258 l_regset->rdi = b_reg->r_rdi; 259 l_regset->orig_rax = b_reg->r_rax; 260 l_regset->rip = b_reg->r_rip; 261 l_regset->cs = b_reg->r_cs; 262 l_regset->eflags = b_reg->r_rflags; 263 l_regset->rsp = b_reg->r_rsp; 264 l_regset->ss = b_reg->r_ss; 265 l_regset->fs_base = fs_base; 266 l_regset->gs_base = gs_base; 267 l_regset->ds = b_reg->r_ds; 268 l_regset->es = b_reg->r_es; 269 l_regset->fs = b_reg->r_fs; 270 l_regset->gs = b_reg->r_gs; 271 } 272 273 static void 274 map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg) 275 { 276 b_reg->r_r15 = l_reg->r15; 277 b_reg->r_r14 = l_reg->r14; 278 b_reg->r_r13 = l_reg->r13; 279 b_reg->r_r12 = l_reg->r12; 280 b_reg->r_r11 = l_reg->r11; 281 b_reg->r_r10 = l_reg->r10; 282 b_reg->r_r9 = l_reg->r9; 283 b_reg->r_r8 = l_reg->r8; 284 b_reg->r_rdi = l_reg->rdi; 285 b_reg->r_rsi = l_reg->rsi; 286 b_reg->r_rbp = l_reg->rbp; 287 b_reg->r_rbx = l_reg->rbx; 288 b_reg->r_rdx = l_reg->rdx; 289 b_reg->r_rcx = l_reg->rcx; 290 b_reg->r_rax = l_reg->rax; 291 292 /* 293 * XXX: Are zeroes the right thing to put here? 294 */ 295 b_reg->r_trapno = 0; 296 b_reg->r_fs = 0; 297 b_reg->r_gs = 0; 298 b_reg->r_err = 0; 299 b_reg->r_es = 0; 300 b_reg->r_ds = 0; 301 302 b_reg->r_rip = l_reg->rip; 303 b_reg->r_cs = l_reg->cs; 304 b_reg->r_rflags = l_reg->eflags; 305 b_reg->r_rsp = l_reg->rsp; 306 b_reg->r_ss = l_reg->ss; 307 } 308 309 static int 310 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data) 311 { 312 int error; 313 314 error = kern_ptrace(td, PT_READ_I, pid, addr, 0); 315 if (error == 0) 316 error = copyout(td->td_retval, data, sizeof(l_int)); 317 td->td_retval[0] = error; 318 319 return (error); 320 } 321 322 static int 323 linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data) 324 { 325 326 linux_msg(td, "PTRACE_PEEKUSER not implemented; returning EINVAL"); 327 return (EINVAL); 328 } 329 330 static int 331 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data) 332 { 333 334 linux_msg(td, "PTRACE_POKEUSER not implemented; returning EINVAL"); 335 return (EINVAL); 336 } 337 338 static int 339 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data) 340 { 341 struct linux_pemuldata *pem; 342 int mask; 343 344 mask = 0; 345 346 if (data & ~LINUX_PTRACE_O_MASK) { 347 linux_msg(td, "unknown ptrace option %lx set; " 348 "returning EINVAL", 349 data & ~LINUX_PTRACE_O_MASK); 350 return (EINVAL); 351 } 352 353 pem = pem_find(td->td_proc); 354 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 355 356 /* 357 * PTRACE_O_EXITKILL is ignored, we do that by default. 358 */ 359 360 LINUX_PEM_XLOCK(pem); 361 if (data & LINUX_PTRACE_O_TRACESYSGOOD) { 362 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD; 363 } else { 364 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD; 365 } 366 LINUX_PEM_XUNLOCK(pem); 367 368 if (data & LINUX_PTRACE_O_TRACEFORK) 369 mask |= PTRACE_FORK; 370 371 if (data & LINUX_PTRACE_O_TRACEVFORK) 372 mask |= PTRACE_VFORK; 373 374 if (data & LINUX_PTRACE_O_TRACECLONE) 375 mask |= PTRACE_VFORK; 376 377 if (data & LINUX_PTRACE_O_TRACEEXEC) 378 mask |= PTRACE_EXEC; 379 380 if (data & LINUX_PTRACE_O_TRACEVFORKDONE) 381 mask |= PTRACE_VFORK; /* XXX: Close enough? */ 382 383 if (data & LINUX_PTRACE_O_TRACEEXIT) { 384 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT; 385 } else { 386 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT; 387 } 388 389 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask))); 390 } 391 392 static int 393 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data) 394 { 395 struct ptrace_lwpinfo lwpinfo; 396 l_siginfo_t l_siginfo; 397 int error, sig; 398 399 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 400 if (error != 0) { 401 linux_msg(td, "PT_LWPINFO failed with error %d", error); 402 return (error); 403 } 404 405 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) { 406 error = EINVAL; 407 linux_msg(td, "no PL_FLAG_SI, returning %d", error); 408 return (error); 409 } 410 411 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo); 412 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig); 413 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo)); 414 return (error); 415 } 416 417 static int 418 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 419 { 420 struct ptrace_lwpinfo lwpinfo; 421 struct reg b_reg; 422 struct linux_pt_reg l_reg; 423 int error; 424 425 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 426 if (error != 0) 427 return (error); 428 429 map_regs_to_linux(&b_reg, &l_reg); 430 431 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 432 if (error != 0) { 433 linux_msg(td, "PT_LWPINFO failed with error %d", error); 434 return (error); 435 } 436 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 437 /* 438 * The strace(1) utility depends on RAX being set to -ENOSYS 439 * on syscall entry; otherwise it loops printing those: 440 * 441 * [ Process PID=928 runs in 64 bit mode. ] 442 * [ Process PID=928 runs in x32 mode. ] 443 */ 444 l_reg.rax = -38; /* -ENOSYS */ 445 446 /* 447 * Undo the mangling done in exception.S:fast_syscall_common(). 448 */ 449 l_reg.r10 = l_reg.rcx; 450 } 451 452 error = copyout(&l_reg, (void *)data, sizeof(l_reg)); 453 return (error); 454 } 455 456 static int 457 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data) 458 { 459 struct reg b_reg; 460 struct linux_pt_reg l_reg; 461 int error; 462 463 error = copyin(data, &l_reg, sizeof(l_reg)); 464 if (error != 0) 465 return (error); 466 map_regs_from_linux(&b_reg, &l_reg); 467 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0); 468 return (error); 469 } 470 471 static int 472 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 473 { 474 struct ptrace_lwpinfo lwpinfo; 475 struct reg b_reg; 476 struct linux_pt_regset l_regset; 477 struct iovec iov; 478 struct pcb *pcb; 479 unsigned long fsbase, gsbase; 480 size_t len; 481 int error; 482 483 error = copyin((const void *)data, &iov, sizeof(iov)); 484 if (error != 0) { 485 linux_msg(td, "copyin error %d", error); 486 return (error); 487 } 488 489 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 490 if (error != 0) 491 return (error); 492 493 pcb = td->td_pcb; 494 if (td == curthread) 495 update_pcb_bases(pcb); 496 fsbase = pcb->pcb_fsbase; 497 gsbase = pcb->pcb_gsbase; 498 499 map_regs_to_linux_regset(&b_reg, fsbase, gsbase, &l_regset); 500 501 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 502 if (error != 0) { 503 linux_msg(td, "PT_LWPINFO failed with error %d", error); 504 return (error); 505 } 506 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 507 /* 508 * The strace(1) utility depends on RAX being set to -ENOSYS 509 * on syscall entry; otherwise it loops printing those: 510 * 511 * [ Process PID=928 runs in 64 bit mode. ] 512 * [ Process PID=928 runs in x32 mode. ] 513 */ 514 l_regset.rax = -38; /* -ENOSYS */ 515 516 /* 517 * Undo the mangling done in exception.S:fast_syscall_common(). 518 */ 519 l_regset.r10 = l_regset.rcx; 520 } 521 522 len = MIN(iov.iov_len, sizeof(l_regset)); 523 error = copyout(&l_regset, (void *)iov.iov_base, len); 524 if (error != 0) { 525 linux_msg(td, "copyout error %d", error); 526 return (error); 527 } 528 529 iov.iov_len -= len; 530 error = copyout(&iov, (void *)data, sizeof(iov)); 531 if (error != 0) { 532 linux_msg(td, "iov copyout error %d", error); 533 return (error); 534 } 535 536 return (error); 537 } 538 539 static int 540 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 541 { 542 543 switch (addr) { 544 case LINUX_NT_PRSTATUS: 545 return (linux_ptrace_getregset_prstatus(td, pid, data)); 546 default: 547 linux_msg(td, "PTRACE_GETREGSET request %ld not implemented; " 548 "returning EINVAL", addr); 549 return (EINVAL); 550 } 551 } 552 553 static int 554 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 555 { 556 557 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL"); 558 return (EINVAL); 559 } 560 561 static int 562 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 563 { 564 565 linux_msg(td, "PTRACE_GET_SYSCALL_INFO not implemented; returning EINVAL"); 566 return (EINVAL); 567 } 568 569 int 570 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 571 { 572 void *addr; 573 pid_t pid; 574 int error, sig; 575 576 pid = (pid_t)uap->pid; 577 addr = (void *)uap->addr; 578 579 switch (uap->req) { 580 case LINUX_PTRACE_TRACEME: 581 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 582 break; 583 case LINUX_PTRACE_PEEKTEXT: 584 case LINUX_PTRACE_PEEKDATA: 585 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 586 if (error != 0) 587 return (error); 588 /* 589 * Linux expects this syscall to read 64 bits, not 32. 590 */ 591 error = linux_ptrace_peek(td, pid, 592 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 593 break; 594 case LINUX_PTRACE_PEEKUSER: 595 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data); 596 break; 597 case LINUX_PTRACE_POKETEXT: 598 error = kern_ptrace(td, PT_WRITE_I, pid, addr, uap->data); 599 break; 600 case LINUX_PTRACE_POKEDATA: 601 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 602 break; 603 case LINUX_PTRACE_POKEUSER: 604 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data); 605 break; 606 case LINUX_PTRACE_CONT: 607 error = map_signum(uap->data, &sig); 608 if (error != 0) 609 break; 610 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 611 break; 612 case LINUX_PTRACE_KILL: 613 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 614 break; 615 case LINUX_PTRACE_SINGLESTEP: 616 error = map_signum(uap->data, &sig); 617 if (error != 0) 618 break; 619 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 620 break; 621 case LINUX_PTRACE_GETREGS: 622 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 623 break; 624 case LINUX_PTRACE_SETREGS: 625 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 626 break; 627 case LINUX_PTRACE_ATTACH: 628 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 629 break; 630 case LINUX_PTRACE_DETACH: 631 error = map_signum(uap->data, &sig); 632 if (error != 0) 633 break; 634 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 635 break; 636 case LINUX_PTRACE_SYSCALL: 637 error = map_signum(uap->data, &sig); 638 if (error != 0) 639 break; 640 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 641 break; 642 case LINUX_PTRACE_SETOPTIONS: 643 error = linux_ptrace_setoptions(td, pid, uap->data); 644 break; 645 case LINUX_PTRACE_GETSIGINFO: 646 error = linux_ptrace_getsiginfo(td, pid, uap->data); 647 break; 648 case LINUX_PTRACE_GETREGSET: 649 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 650 break; 651 case LINUX_PTRACE_SEIZE: 652 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 653 break; 654 case LINUX_PTRACE_GET_SYSCALL_INFO: 655 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data); 656 break; 657 default: 658 linux_msg(td, "ptrace(%ld, ...) not implemented; " 659 "returning EINVAL", uap->req); 660 error = EINVAL; 661 break; 662 } 663 664 return (error); 665 } 666