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_setoptions(struct thread *td, pid_t pid, l_ulong data) 323 { 324 struct linux_pemuldata *pem; 325 int mask; 326 327 mask = 0; 328 329 if (data & ~LINUX_PTRACE_O_MASK) { 330 linux_msg(td, "unknown ptrace option %lx set; " 331 "returning EINVAL", 332 data & ~LINUX_PTRACE_O_MASK); 333 return (EINVAL); 334 } 335 336 pem = pem_find(td->td_proc); 337 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 338 339 /* 340 * PTRACE_O_EXITKILL is ignored, we do that by default. 341 */ 342 343 LINUX_PEM_XLOCK(pem); 344 if (data & LINUX_PTRACE_O_TRACESYSGOOD) { 345 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD; 346 } else { 347 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD; 348 } 349 LINUX_PEM_XUNLOCK(pem); 350 351 if (data & LINUX_PTRACE_O_TRACEFORK) 352 mask |= PTRACE_FORK; 353 354 if (data & LINUX_PTRACE_O_TRACEVFORK) 355 mask |= PTRACE_VFORK; 356 357 if (data & LINUX_PTRACE_O_TRACECLONE) 358 mask |= PTRACE_VFORK; 359 360 if (data & LINUX_PTRACE_O_TRACEEXEC) 361 mask |= PTRACE_EXEC; 362 363 if (data & LINUX_PTRACE_O_TRACEVFORKDONE) 364 mask |= PTRACE_VFORK; /* XXX: Close enough? */ 365 366 if (data & LINUX_PTRACE_O_TRACEEXIT) { 367 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT; 368 } else { 369 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT; 370 } 371 372 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask))); 373 } 374 375 static int 376 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data) 377 { 378 struct ptrace_lwpinfo lwpinfo; 379 l_siginfo_t l_siginfo; 380 int error, sig; 381 382 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 383 if (error != 0) { 384 linux_msg(td, "PT_LWPINFO failed with error %d", error); 385 return (error); 386 } 387 388 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) { 389 error = EINVAL; 390 linux_msg(td, "no PL_FLAG_SI, returning %d", error); 391 return (error); 392 } 393 394 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo); 395 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig); 396 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo)); 397 return (error); 398 } 399 400 static int 401 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 402 { 403 struct ptrace_lwpinfo lwpinfo; 404 struct reg b_reg; 405 struct linux_pt_reg l_reg; 406 int error; 407 408 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 409 if (error != 0) 410 return (error); 411 412 map_regs_to_linux(&b_reg, &l_reg); 413 414 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 415 if (error != 0) { 416 linux_msg(td, "PT_LWPINFO failed with error %d", error); 417 return (error); 418 } 419 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 420 /* 421 * The strace(1) utility depends on RAX being set to -ENOSYS 422 * on syscall entry; otherwise it loops printing those: 423 * 424 * [ Process PID=928 runs in 64 bit mode. ] 425 * [ Process PID=928 runs in x32 mode. ] 426 */ 427 l_reg.rax = -38; /* -ENOSYS */ 428 429 /* 430 * Undo the mangling done in exception.S:fast_syscall_common(). 431 */ 432 l_reg.r10 = l_reg.rcx; 433 } 434 435 error = copyout(&l_reg, (void *)data, sizeof(l_reg)); 436 return (error); 437 } 438 439 static int 440 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data) 441 { 442 struct reg b_reg; 443 struct linux_pt_reg l_reg; 444 int error; 445 446 error = copyin(data, &l_reg, sizeof(l_reg)); 447 if (error != 0) 448 return (error); 449 map_regs_from_linux(&b_reg, &l_reg); 450 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0); 451 return (error); 452 } 453 454 static int 455 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 456 { 457 struct ptrace_lwpinfo lwpinfo; 458 struct reg b_reg; 459 struct linux_pt_regset l_regset; 460 struct iovec iov; 461 struct pcb *pcb; 462 unsigned long fsbase, gsbase; 463 size_t len; 464 int error; 465 466 error = copyin((const void *)data, &iov, sizeof(iov)); 467 if (error != 0) { 468 linux_msg(td, "copyin error %d", error); 469 return (error); 470 } 471 472 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 473 if (error != 0) 474 return (error); 475 476 pcb = td->td_pcb; 477 if (td == curthread) 478 update_pcb_bases(pcb); 479 fsbase = pcb->pcb_fsbase; 480 gsbase = pcb->pcb_gsbase; 481 482 map_regs_to_linux_regset(&b_reg, fsbase, gsbase, &l_regset); 483 484 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 485 if (error != 0) { 486 linux_msg(td, "PT_LWPINFO failed with error %d", error); 487 return (error); 488 } 489 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 490 /* 491 * The strace(1) utility depends on RAX being set to -ENOSYS 492 * on syscall entry; otherwise it loops printing those: 493 * 494 * [ Process PID=928 runs in 64 bit mode. ] 495 * [ Process PID=928 runs in x32 mode. ] 496 */ 497 l_regset.rax = -38; /* -ENOSYS */ 498 499 /* 500 * Undo the mangling done in exception.S:fast_syscall_common(). 501 */ 502 l_regset.r10 = l_regset.rcx; 503 } 504 505 len = MIN(iov.iov_len, sizeof(l_regset)); 506 error = copyout(&l_regset, (void *)iov.iov_base, len); 507 if (error != 0) { 508 linux_msg(td, "copyout error %d", error); 509 return (error); 510 } 511 512 iov.iov_len -= len; 513 error = copyout(&iov, (void *)data, sizeof(iov)); 514 if (error != 0) { 515 linux_msg(td, "iov copyout error %d", error); 516 return (error); 517 } 518 519 return (error); 520 } 521 522 static int 523 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 524 { 525 526 switch (addr) { 527 case LINUX_NT_PRSTATUS: 528 return (linux_ptrace_getregset_prstatus(td, pid, data)); 529 default: 530 linux_msg(td, "PTRACE_GETREGSET request %ld not implemented; " 531 "returning EINVAL", addr); 532 return (EINVAL); 533 } 534 } 535 536 static int 537 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 538 { 539 540 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL"); 541 return (EINVAL); 542 } 543 544 int 545 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 546 { 547 void *addr; 548 pid_t pid; 549 int error, sig; 550 551 pid = (pid_t)uap->pid; 552 addr = (void *)uap->addr; 553 554 switch (uap->req) { 555 case LINUX_PTRACE_TRACEME: 556 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 557 break; 558 case LINUX_PTRACE_PEEKTEXT: 559 case LINUX_PTRACE_PEEKDATA: 560 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 561 if (error != 0) 562 return (error); 563 /* 564 * Linux expects this syscall to read 64 bits, not 32. 565 */ 566 error = linux_ptrace_peek(td, pid, 567 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 568 break; 569 case LINUX_PTRACE_POKETEXT: 570 error = kern_ptrace(td, PT_WRITE_I, pid, addr, uap->data); 571 break; 572 case LINUX_PTRACE_POKEDATA: 573 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 574 break; 575 case LINUX_PTRACE_CONT: 576 error = map_signum(uap->data, &sig); 577 if (error != 0) 578 break; 579 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 580 break; 581 case LINUX_PTRACE_KILL: 582 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 583 break; 584 case LINUX_PTRACE_SINGLESTEP: 585 error = map_signum(uap->data, &sig); 586 if (error != 0) 587 break; 588 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 589 break; 590 case LINUX_PTRACE_GETREGS: 591 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 592 break; 593 case LINUX_PTRACE_SETREGS: 594 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 595 break; 596 case LINUX_PTRACE_ATTACH: 597 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 598 break; 599 case LINUX_PTRACE_DETACH: 600 error = map_signum(uap->data, &sig); 601 if (error != 0) 602 break; 603 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 604 break; 605 case LINUX_PTRACE_SYSCALL: 606 error = map_signum(uap->data, &sig); 607 if (error != 0) 608 break; 609 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 610 break; 611 case LINUX_PTRACE_SETOPTIONS: 612 error = linux_ptrace_setoptions(td, pid, uap->data); 613 break; 614 case LINUX_PTRACE_GETSIGINFO: 615 error = linux_ptrace_getsiginfo(td, pid, uap->data); 616 break; 617 case LINUX_PTRACE_GETREGSET: 618 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 619 break; 620 case LINUX_PTRACE_SEIZE: 621 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 622 break; 623 default: 624 linux_msg(td, "ptrace(%ld, ...) not implemented; " 625 "returning EINVAL", uap->req); 626 error = EINVAL; 627 break; 628 } 629 630 return (error); 631 } 632