1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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/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_misc.h> 49#include <compat/linux/linux_signal.h> 50#include <compat/linux/linux_util.h> 51 52#define LINUX_PTRACE_TRACEME 0 53#define LINUX_PTRACE_PEEKTEXT 1 54#define LINUX_PTRACE_PEEKDATA 2 55#define LINUX_PTRACE_PEEKUSER 3 56#define LINUX_PTRACE_POKETEXT 4 57#define LINUX_PTRACE_POKEDATA 5 58#define LINUX_PTRACE_POKEUSER 6 59#define LINUX_PTRACE_CONT 7 60#define LINUX_PTRACE_KILL 8 61#define LINUX_PTRACE_SINGLESTEP 9 62#define LINUX_PTRACE_GETREGS 12 63#define LINUX_PTRACE_SETREGS 13 64#define LINUX_PTRACE_GETFPREGS 14 65#define LINUX_PTRACE_SETFPREGS 15 66#define LINUX_PTRACE_ATTACH 16 67#define LINUX_PTRACE_DETACH 17 68#define LINUX_PTRACE_SYSCALL 24 69#define LINUX_PTRACE_SETOPTIONS 0x4200 70#define LINUX_PTRACE_GETSIGINFO 0x4202 71#define LINUX_PTRACE_GETREGSET 0x4204 72#define LINUX_PTRACE_SEIZE 0x4206 73#define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e 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 static int 561 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 562{ 563 564 linux_msg(td, "PTRACE_GET_SYSCALL_INFO not implemented; returning EINVAL"); 565 return (EINVAL); 566} 567 568 int 569 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 570{ 571 void *addr; 572 pid_t pid; 573 int error, sig; 574 575 pid = (pid_t)uap->pid; 576 addr = (void *)uap->addr; 577 578 switch (uap->req) { 579 case LINUX_PTRACE_TRACEME: 580 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 581 break; 582 case LINUX_PTRACE_PEEKTEXT: 583 case LINUX_PTRACE_PEEKDATA: 584 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 585 if (error != 0) 586 return (error); 587 /* 588 * Linux expects this syscall to read 64 bits, not 32. 589 */ 590 error = linux_ptrace_peek(td, pid, 591 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 592 break; 593 case LINUX_PTRACE_PEEKUSER: 594 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data); 595 break; 596 case LINUX_PTRACE_POKETEXT: 597 error = kern_ptrace(td, PT_WRITE_I, pid, addr, uap->data); 598 break; 599 case LINUX_PTRACE_POKEDATA: 600 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 601 break; 602 case LINUX_PTRACE_POKEUSER: 603 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data); 604 break; 605 case LINUX_PTRACE_CONT: 606 error = map_signum(uap->data, &sig); 607 if (error != 0) 608 break; 609 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 610 break; 611 case LINUX_PTRACE_KILL: 612 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 613 break; 614 case LINUX_PTRACE_SINGLESTEP: 615 error = map_signum(uap->data, &sig); 616 if (error != 0) 617 break; 618 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 619 break; 620 case LINUX_PTRACE_GETREGS: 621 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 622 break; 623 case LINUX_PTRACE_SETREGS: 624 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 625 break; 626 case LINUX_PTRACE_ATTACH: 627 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 628 break; 629 case LINUX_PTRACE_DETACH: 630 error = map_signum(uap->data, &sig); 631 if (error != 0) 632 break; 633 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 634 break; 635 case LINUX_PTRACE_SYSCALL: 636 error = map_signum(uap->data, &sig); 637 if (error != 0) 638 break; 639 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 640 break; 641 case LINUX_PTRACE_SETOPTIONS: 642 error = linux_ptrace_setoptions(td, pid, uap->data); 643 break; 644 case LINUX_PTRACE_GETSIGINFO: 645 error = linux_ptrace_getsiginfo(td, pid, uap->data); 646 break; 647 case LINUX_PTRACE_GETREGSET: 648 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 649 break; 650 case LINUX_PTRACE_SEIZE: 651 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 652 break; 653 case LINUX_PTRACE_GET_SYSCALL_INFO: 654 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data); 655 break; 656 default: 657 linux_msg(td, "ptrace(%ld, ...) not implemented; " 658 "returning EINVAL", uap->req); 659 error = EINVAL; 660 break; 661 } 662 663 return (error); 664} 665