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