1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *                     Linux for s390 port by D.J. Barrow
8  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9  * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
10  *                    port by Greg Banks <gbanks@pocketpenguins.com>
11  *
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. The name of the author may not be used to endorse or promote products
23  *    derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include "defs.h"
38 
39 #ifdef HAVE_ELF_H
40 # include <elf.h>
41 #endif
42 
43 #include "xlat/nt_descriptor_types.h"
44 
45 #include "regs.h"
46 #include "ptrace.h"
47 #include "xlat/ptrace_cmds.h"
48 #include "xlat/ptrace_setoptions_flags.h"
49 #include "xlat/ptrace_peeksiginfo_flags.h"
50 
51 #define uoff(member)	offsetof(struct user, member)
52 #define XLAT_UOFF(member)	{ uoff(member), "offsetof(struct user, " #member ")" }
53 
54 static const struct xlat struct_user_offsets[] = {
55 #include "userent.h"
56 	XLAT_END
57 };
58 
59 static void
print_user_offset_addr(const kernel_ulong_t addr)60 print_user_offset_addr(const kernel_ulong_t addr)
61 {
62 	const struct xlat *x;
63 
64 	for (x = struct_user_offsets; x->str; ++x) {
65 		if (x->val >= addr)
66 			break;
67 	}
68 
69 	if (!x->str) {
70 		printaddr(addr);
71 	} else if (x->val > addr) {
72 		if (x == struct_user_offsets) {
73 			printaddr(addr);
74 		} else {
75 			--x;
76 			tprintf("%s + %" PRI_klu,
77 				x->str, addr - (kernel_ulong_t) x->val);
78 		}
79 	} else {
80 		tprints(x->str);
81 	}
82 }
83 
SYS_FUNC(ptrace)84 SYS_FUNC(ptrace)
85 {
86 	const kernel_ulong_t request = tcp->u_arg[0];
87 	const int pid = tcp->u_arg[1];
88 	const kernel_ulong_t addr = tcp->u_arg[2];
89 	const kernel_ulong_t data = tcp->u_arg[3];
90 
91 	if (entering(tcp)) {
92 		/* request */
93 		printxval64(ptrace_cmds, request, "PTRACE_???");
94 
95 		if (request == PTRACE_TRACEME) {
96 			/* pid, addr, and data are ignored. */
97 			return RVAL_DECODED;
98 		}
99 
100 		/* pid */
101 		tprintf(", %d", pid);
102 
103 		/* addr */
104 		switch (request) {
105 		case PTRACE_ATTACH:
106 		case PTRACE_INTERRUPT:
107 		case PTRACE_KILL:
108 		case PTRACE_LISTEN:
109 			/* addr and data are ignored */
110 			return RVAL_DECODED;
111 		case PTRACE_PEEKUSER:
112 		case PTRACE_POKEUSER:
113 			tprints(", ");
114 			print_user_offset_addr(addr);
115 			break;
116 		case PTRACE_GETREGSET:
117 		case PTRACE_SETREGSET:
118 			tprints(", ");
119 			printxval(nt_descriptor_types, addr, "NT_???");
120 			break;
121 		case PTRACE_GETSIGMASK:
122 		case PTRACE_SETSIGMASK:
123 		case PTRACE_SECCOMP_GET_FILTER:
124 			tprintf(", %" PRI_klu, addr);
125 			break;
126 		case PTRACE_PEEKSIGINFO: {
127 			tprints(", ");
128 			struct {
129 				uint64_t off;
130 				uint32_t flags;
131 				uint32_t nr;
132 			} psi;
133 			if (umove_or_printaddr(tcp, addr, &psi)) {
134 				tprints(", ");
135 				printaddr(data);
136 				return RVAL_DECODED;
137 			}
138 			tprintf("{off=%" PRIu64 ", flags=", psi.off);
139 			printflags(ptrace_peeksiginfo_flags, psi.flags,
140 				   "PTRACE_PEEKSIGINFO_???");
141 			tprintf(", nr=%u}", psi.nr);
142 			break;
143 		}
144 		default:
145 			tprints(", ");
146 			printaddr(addr);
147 		}
148 
149 # if defined IA64 || defined SPARC || defined SPARC64
150 		switch (request) {
151 #  ifdef IA64
152 		case PTRACE_PEEKDATA:
153 		case PTRACE_PEEKTEXT:
154 		case PTRACE_PEEKUSER:
155 			/* data is ignored */
156 			return RVAL_DECODED | RVAL_HEX;
157 #  endif /* IA64 */
158 #  if defined SPARC || defined SPARC64
159 		case PTRACE_GETREGS:
160 		case PTRACE_SETREGS:
161 		case PTRACE_GETFPREGS:
162 		case PTRACE_SETFPREGS:
163 			/* data is ignored */
164 			return RVAL_DECODED;
165 #  endif /* SPARC || SPARC64 */
166 		}
167 # endif /* IA64 || SPARC || SPARC64 */
168 
169 		tprints(", ");
170 
171 		/* data */
172 		switch (request) {
173 		case PTRACE_CONT:
174 		case PTRACE_DETACH:
175 		case PTRACE_SYSCALL:
176 #ifdef PTRACE_SINGLESTEP
177 		case PTRACE_SINGLESTEP:
178 #endif
179 #ifdef PTRACE_SINGLEBLOCK
180 		case PTRACE_SINGLEBLOCK:
181 #endif
182 #ifdef PTRACE_SYSEMU
183 		case PTRACE_SYSEMU:
184 #endif
185 #ifdef PTRACE_SYSEMU_SINGLESTEP
186 		case PTRACE_SYSEMU_SINGLESTEP:
187 #endif
188 			printsignal(data);
189 			break;
190 		case PTRACE_SEIZE:
191 		case PTRACE_SETOPTIONS:
192 #ifdef PTRACE_OLDSETOPTIONS
193 		case PTRACE_OLDSETOPTIONS:
194 #endif
195 			printflags64(ptrace_setoptions_flags, data, "PTRACE_O_???");
196 			break;
197 		case PTRACE_SETSIGINFO:
198 			printsiginfo_at(tcp, data);
199 			break;
200 		case PTRACE_SETSIGMASK:
201 			print_sigset_addr_len(tcp, data, addr);
202 			break;
203 		case PTRACE_SETREGSET:
204 			tprint_iov(tcp, /*len:*/ 1, data, IOV_DECODE_ADDR);
205 			break;
206 #ifndef IA64
207 		case PTRACE_PEEKDATA:
208 		case PTRACE_PEEKTEXT:
209 		case PTRACE_PEEKUSER:
210 #endif
211 		case PTRACE_GETEVENTMSG:
212 		case PTRACE_GETREGSET:
213 		case PTRACE_GETSIGINFO:
214 		case PTRACE_GETSIGMASK:
215 		case PTRACE_PEEKSIGINFO:
216 		case PTRACE_SECCOMP_GET_FILTER:
217 			if (verbose(tcp)) {
218 				/* print data on exiting syscall */
219 				return 0;
220 			}
221 			/* fall through */
222 		default:
223 			printaddr(data);
224 			break;
225 		}
226 
227 		return RVAL_DECODED;
228 	} else {
229 		switch (request) {
230 #ifndef IA64
231 		case PTRACE_PEEKDATA:
232 		case PTRACE_PEEKTEXT:
233 		case PTRACE_PEEKUSER:
234 			printnum_ptr(tcp, data);
235 			break;
236 #endif
237 		case PTRACE_GETEVENTMSG:
238 			printnum_ulong(tcp, data);
239 			break;
240 		case PTRACE_GETREGSET:
241 			tprint_iov(tcp, /*len:*/ 1, data, IOV_DECODE_ADDR);
242 			break;
243 		case PTRACE_GETSIGINFO:
244 			printsiginfo_at(tcp, data);
245 			break;
246 		case PTRACE_GETSIGMASK:
247 			print_sigset_addr_len(tcp, data, addr);
248 			break;
249 		case PTRACE_PEEKSIGINFO:
250 			print_siginfo_array(tcp, data, tcp->u_rval);
251 			break;
252 		case PTRACE_SECCOMP_GET_FILTER:
253 			print_seccomp_fprog(tcp, data, tcp->u_rval);
254 			break;
255 		}
256 	}
257 	return 0;
258 }
259