1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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/../linux/linux.h> 43 #include <machine/../linux/linux_proto.h> 44 #include <compat/linux/linux_emul.h> 45 #include <compat/linux/linux_errno.h> 46 #include <compat/linux/linux_misc.h> 47 #include <compat/linux/linux_signal.h> 48 #include <compat/linux/linux_util.h> 49 50 #define LINUX_PTRACE_TRACEME 0 51 #define LINUX_PTRACE_PEEKTEXT 1 52 #define LINUX_PTRACE_PEEKDATA 2 53 #define LINUX_PTRACE_PEEKUSER 3 54 #define LINUX_PTRACE_POKETEXT 4 55 #define LINUX_PTRACE_POKEDATA 5 56 #define LINUX_PTRACE_POKEUSER 6 57 #define LINUX_PTRACE_CONT 7 58 #define LINUX_PTRACE_KILL 8 59 #define LINUX_PTRACE_SINGLESTEP 9 60 #define LINUX_PTRACE_GETREGS 12 61 #define LINUX_PTRACE_SETREGS 13 62 #define LINUX_PTRACE_GETFPREGS 14 63 #define LINUX_PTRACE_SETFPREGS 15 64 #define LINUX_PTRACE_ATTACH 16 65 #define LINUX_PTRACE_DETACH 17 66 #define LINUX_PTRACE_SYSCALL 24 67 #define LINUX_PTRACE_SETOPTIONS 0x4200 68 #define LINUX_PTRACE_GETEVENTMSG 0x4201 69 #define LINUX_PTRACE_GETSIGINFO 0x4202 70 #define LINUX_PTRACE_GETREGSET 0x4204 71 #define LINUX_PTRACE_SEIZE 0x4206 72 #define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e 73 74 #define LINUX_PTRACE_EVENT_EXEC 4 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 0x1 89 #define LINUX_NT_PRFPREG 0x2 90 #define LINUX_NT_X86_XSTATE 0x202 91 92 #define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \ 93 LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \ 94 LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \ 95 LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \ 96 LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \ 97 LINUX_PTRACE_O_SUSPEND_SECCOMP) 98 99 #define LINUX_PTRACE_SYSCALL_INFO_NONE 0 100 #define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1 101 #define LINUX_PTRACE_SYSCALL_INFO_EXIT 2 102 103 static int 104 map_signum(int lsig, int *bsigp) 105 { 106 int bsig; 107 108 if (lsig == 0) { 109 *bsigp = 0; 110 return (0); 111 } 112 113 if (lsig < 0 || lsig > LINUX_SIGRTMAX) 114 return (EINVAL); 115 116 bsig = linux_to_bsd_signal(lsig); 117 if (bsig == SIGSTOP) 118 bsig = 0; 119 120 *bsigp = bsig; 121 return (0); 122 } 123 124 int 125 linux_ptrace_status(struct thread *td, pid_t pid, int status) 126 { 127 struct ptrace_lwpinfo lwpinfo; 128 struct linux_pemuldata *pem; 129 register_t saved_retval; 130 int error; 131 132 saved_retval = td->td_retval[0]; 133 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 134 td->td_retval[0] = saved_retval; 135 if (error != 0) { 136 linux_msg(td, "PT_LWPINFO failed with error %d", error); 137 return (status); 138 } 139 140 pem = pem_find(td->td_proc); 141 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 142 143 LINUX_PEM_SLOCK(pem); 144 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 145 lwpinfo.pl_flags & PL_FLAG_SCE) 146 status |= (LINUX_SIGTRAP | 0x80) << 8; 147 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) && 148 lwpinfo.pl_flags & PL_FLAG_SCX) { 149 if (lwpinfo.pl_flags & PL_FLAG_EXEC) 150 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXEC << 8) << 8; 151 else 152 status |= (LINUX_SIGTRAP | 0x80) << 8; 153 } 154 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) && 155 lwpinfo.pl_flags & PL_FLAG_EXITED) 156 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8; 157 LINUX_PEM_SUNLOCK(pem); 158 159 return (status); 160 } 161 162 static int 163 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data) 164 { 165 int error; 166 167 error = kern_ptrace(td, PT_READ_I, pid, addr, 0); 168 if (error == 0) 169 error = copyout(td->td_retval, data, sizeof(l_int)); 170 else if (error == ENOMEM) 171 error = EIO; 172 td->td_retval[0] = error; 173 174 return (error); 175 } 176 177 static int 178 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data) 179 { 180 struct linux_pemuldata *pem; 181 int mask; 182 183 mask = 0; 184 185 if (data & ~LINUX_PTRACE_O_MASK) { 186 linux_msg(td, "unknown ptrace option %lx set; " 187 "returning EINVAL", 188 data & ~LINUX_PTRACE_O_MASK); 189 return (EINVAL); 190 } 191 192 pem = pem_find(td->td_proc); 193 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__)); 194 195 /* 196 * PTRACE_O_EXITKILL is ignored, we do that by default. 197 */ 198 199 LINUX_PEM_XLOCK(pem); 200 if (data & LINUX_PTRACE_O_TRACESYSGOOD) { 201 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD; 202 } else { 203 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD; 204 } 205 LINUX_PEM_XUNLOCK(pem); 206 207 if (data & LINUX_PTRACE_O_TRACEFORK) 208 mask |= PTRACE_FORK; 209 210 if (data & LINUX_PTRACE_O_TRACEVFORK) 211 mask |= PTRACE_VFORK; 212 213 if (data & LINUX_PTRACE_O_TRACECLONE) 214 mask |= PTRACE_VFORK; 215 216 if (data & LINUX_PTRACE_O_TRACEEXEC) 217 mask |= PTRACE_EXEC; 218 219 if (data & LINUX_PTRACE_O_TRACEVFORKDONE) 220 mask |= PTRACE_VFORK; /* XXX: Close enough? */ 221 222 if (data & LINUX_PTRACE_O_TRACEEXIT) { 223 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT; 224 } else { 225 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT; 226 } 227 228 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask))); 229 } 230 231 static int 232 linux_ptrace_geteventmsg(struct thread *td, pid_t pid, l_ulong data) 233 { 234 235 linux_msg(td, "PTRACE_GETEVENTMSG not implemented; returning EINVAL"); 236 return (EINVAL); 237 } 238 239 static int 240 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data) 241 { 242 struct ptrace_lwpinfo lwpinfo; 243 l_siginfo_t l_siginfo; 244 int error, sig; 245 246 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 247 if (error != 0) { 248 linux_msg(td, "PT_LWPINFO failed with error %d", error); 249 return (error); 250 } 251 252 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) { 253 error = EINVAL; 254 linux_msg(td, "no PL_FLAG_SI, returning %d", error); 255 return (error); 256 } 257 258 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo); 259 memset(&l_siginfo, 0, sizeof(l_siginfo)); 260 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig); 261 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo)); 262 return (error); 263 } 264 265 static int 266 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 267 { 268 struct reg b_reg; 269 struct linux_pt_regset l_regset; 270 int error; 271 272 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 273 if (error != 0) 274 return (error); 275 276 bsd_to_linux_regset(&b_reg, &l_regset); 277 error = linux_ptrace_getregs_machdep(td, pid, &l_regset); 278 if (error != 0) 279 return (error); 280 281 error = copyout(&l_regset, (void *)data, sizeof(l_regset)); 282 return (error); 283 } 284 285 static int 286 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data) 287 { 288 struct reg b_reg; 289 struct linux_pt_regset l_regset; 290 int error; 291 292 error = copyin(data, &l_regset, sizeof(l_regset)); 293 if (error != 0) 294 return (error); 295 linux_to_bsd_regset(&b_reg, &l_regset); 296 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0); 297 return (error); 298 } 299 300 static int 301 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 302 { 303 struct reg b_reg; 304 struct linux_pt_regset l_regset; 305 struct iovec iov; 306 size_t len; 307 int error; 308 309 error = copyin((const void *)data, &iov, sizeof(iov)); 310 if (error != 0) { 311 linux_msg(td, "copyin error %d", error); 312 return (error); 313 } 314 315 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 316 if (error != 0) 317 return (error); 318 319 bsd_to_linux_regset(&b_reg, &l_regset); 320 error = linux_ptrace_getregs_machdep(td, pid, &l_regset); 321 if (error != 0) 322 return (error); 323 324 len = MIN(iov.iov_len, sizeof(l_regset)); 325 error = copyout(&l_regset, (void *)iov.iov_base, len); 326 if (error != 0) { 327 linux_msg(td, "copyout error %d", error); 328 return (error); 329 } 330 331 iov.iov_len = len; 332 error = copyout(&iov, (void *)data, sizeof(iov)); 333 if (error != 0) { 334 linux_msg(td, "iov copyout error %d", error); 335 return (error); 336 } 337 338 return (error); 339 } 340 341 static int 342 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 343 { 344 345 switch (addr) { 346 case LINUX_NT_PRSTATUS: 347 return (linux_ptrace_getregset_prstatus(td, pid, data)); 348 case LINUX_NT_PRFPREG: 349 linux_msg(td, "PTRAGE_GETREGSET NT_PRFPREG not implemented; " 350 "returning EINVAL"); 351 return (EINVAL); 352 case LINUX_NT_X86_XSTATE: 353 linux_msg(td, "PTRAGE_GETREGSET NT_X86_XSTATE not implemented; " 354 "returning EINVAL"); 355 return (EINVAL); 356 default: 357 linux_msg(td, "PTRACE_GETREGSET request %#lx not implemented; " 358 "returning EINVAL", addr); 359 return (EINVAL); 360 } 361 } 362 363 static int 364 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) 365 { 366 367 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL"); 368 return (EINVAL); 369 } 370 371 static int 372 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, 373 l_ulong len, l_ulong data) 374 { 375 struct ptrace_lwpinfo lwpinfo; 376 struct ptrace_sc_ret sr; 377 struct reg b_reg; 378 struct syscall_info si; 379 int error; 380 381 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); 382 if (error != 0) { 383 linux_msg(td, "PT_LWPINFO failed with error %d", error); 384 return (error); 385 } 386 387 memset(&si, 0, sizeof(si)); 388 389 if (lwpinfo.pl_flags & PL_FLAG_SCE) { 390 si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY; 391 si.entry.nr = lwpinfo.pl_syscall_code; 392 /* 393 * The use of PT_GET_SC_ARGS there is special, 394 * implementation of PT_GET_SC_ARGS for Linux-ABI 395 * callers emulates Linux bug which strace(1) depends 396 * on: at initialization it tests whether ptrace works 397 * by calling close(2), or some other single-argument 398 * syscall, _with six arguments_, and then verifies 399 * whether it can fetch them all using this API; 400 * otherwise it bails out. 401 */ 402 error = kern_ptrace(td, PT_GET_SC_ARGS, pid, 403 &si.entry.args, sizeof(si.entry.args)); 404 if (error != 0) { 405 linux_msg(td, "PT_GET_SC_ARGS failed with error %d", 406 error); 407 return (error); 408 } 409 } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 410 si.op = LINUX_PTRACE_SYSCALL_INFO_EXIT; 411 error = kern_ptrace(td, PT_GET_SC_RET, pid, &sr, sizeof(sr)); 412 413 if (error != 0) { 414 linux_msg(td, "PT_GET_SC_RET failed with error %d", 415 error); 416 return (error); 417 } 418 419 if (sr.sr_error == 0) { 420 si.exit.rval = sr.sr_retval[0]; 421 si.exit.is_error = 0; 422 } else if (sr.sr_error == EJUSTRETURN) { 423 /* 424 * EJUSTRETURN means the actual value to return 425 * has already been put into td_frame; instead 426 * of extracting it and trying to determine whether 427 * it's an error or not just bail out and let 428 * the ptracing process fall back to another method. 429 */ 430 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 431 } else if (sr.sr_error == ERESTART) { 432 si.exit.rval = -LINUX_ERESTARTSYS; 433 si.exit.is_error = 1; 434 } else { 435 si.exit.rval = bsd_to_linux_errno(sr.sr_error); 436 si.exit.is_error = 1; 437 } 438 } else { 439 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE; 440 } 441 442 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); 443 if (error != 0) 444 return (error); 445 446 linux_ptrace_get_syscall_info_machdep(&b_reg, &si); 447 448 len = MIN(len, sizeof(si)); 449 error = copyout(&si, (void *)data, len); 450 if (error == 0) 451 td->td_retval[0] = sizeof(si); 452 453 return (error); 454 } 455 456 int 457 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap) 458 { 459 void *addr; 460 pid_t pid; 461 int error, sig; 462 463 if (!allow_ptrace) 464 return (ENOSYS); 465 466 pid = (pid_t)uap->pid; 467 addr = (void *)uap->addr; 468 469 switch (uap->req) { 470 case LINUX_PTRACE_TRACEME: 471 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0); 472 break; 473 case LINUX_PTRACE_PEEKTEXT: 474 case LINUX_PTRACE_PEEKDATA: 475 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data); 476 if (error != 0) 477 goto out; 478 /* 479 * Linux expects this syscall to read 64 bits, not 32. 480 */ 481 error = linux_ptrace_peek(td, pid, 482 (void *)(uap->addr + 4), (void *)(uap->data + 4)); 483 break; 484 case LINUX_PTRACE_PEEKUSER: 485 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data); 486 break; 487 case LINUX_PTRACE_POKETEXT: 488 case LINUX_PTRACE_POKEDATA: 489 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data); 490 if (error != 0) 491 goto out; 492 /* 493 * Linux expects this syscall to write 64 bits, not 32. 494 */ 495 error = kern_ptrace(td, PT_WRITE_D, pid, 496 (void *)(uap->addr + 4), uap->data >> 32); 497 break; 498 case LINUX_PTRACE_POKEUSER: 499 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data); 500 break; 501 case LINUX_PTRACE_CONT: 502 error = map_signum(uap->data, &sig); 503 if (error != 0) 504 break; 505 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig); 506 break; 507 case LINUX_PTRACE_KILL: 508 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data); 509 break; 510 case LINUX_PTRACE_SINGLESTEP: 511 error = map_signum(uap->data, &sig); 512 if (error != 0) 513 break; 514 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig); 515 break; 516 case LINUX_PTRACE_GETREGS: 517 error = linux_ptrace_getregs(td, pid, (void *)uap->data); 518 break; 519 case LINUX_PTRACE_SETREGS: 520 error = linux_ptrace_setregs(td, pid, (void *)uap->data); 521 break; 522 case LINUX_PTRACE_ATTACH: 523 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data); 524 break; 525 case LINUX_PTRACE_DETACH: 526 error = map_signum(uap->data, &sig); 527 if (error != 0) 528 break; 529 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig); 530 break; 531 case LINUX_PTRACE_SYSCALL: 532 error = map_signum(uap->data, &sig); 533 if (error != 0) 534 break; 535 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig); 536 break; 537 case LINUX_PTRACE_SETOPTIONS: 538 error = linux_ptrace_setoptions(td, pid, uap->data); 539 break; 540 case LINUX_PTRACE_GETEVENTMSG: 541 error = linux_ptrace_geteventmsg(td, pid, uap->data); 542 break; 543 case LINUX_PTRACE_GETSIGINFO: 544 error = linux_ptrace_getsiginfo(td, pid, uap->data); 545 break; 546 case LINUX_PTRACE_GETREGSET: 547 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data); 548 break; 549 case LINUX_PTRACE_SEIZE: 550 error = linux_ptrace_seize(td, pid, uap->addr, uap->data); 551 break; 552 case LINUX_PTRACE_GET_SYSCALL_INFO: 553 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data); 554 break; 555 default: 556 linux_msg(td, "ptrace(%ld, ...) not implemented; " 557 "returning EINVAL", uap->req); 558 error = EINVAL; 559 break; 560 } 561 562 out: 563 if (error == EBUSY) 564 error = ESRCH; 565 566 return (error); 567 } 568