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