xref: /freebsd-13.1/sys/amd64/linux/linux_ptrace.c (revision d22ff249)
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