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