1 /* 2 * Check decoding of ptrace syscall. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2018 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <asm/unistd.h> 33 34 #include <errno.h> 35 #include "ptrace.h" 36 #include <inttypes.h> 37 #include <signal.h> 38 #include <stdint.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <sys/wait.h> 42 #include <unistd.h> 43 #include <linux/audit.h> 44 45 static const char *errstr; 46 47 static long 48 do_ptrace(unsigned long request, unsigned long pid, 49 unsigned long addr, unsigned long data) 50 { 51 long rc = syscall(__NR_ptrace, request, pid, addr, data); 52 errstr = sprintrc(rc); 53 return rc; 54 } 55 56 static void 57 test_peeksiginfo(unsigned long pid, const unsigned long bad_request) 58 { 59 do_ptrace(PTRACE_PEEKSIGINFO, pid, 0, bad_request); 60 printf("ptrace(PTRACE_PEEKSIGINFO, %u, NULL, %#lx) = %s\n", 61 (unsigned) pid, bad_request, errstr); 62 63 struct psi { 64 unsigned long long off; 65 unsigned int flags, nr; 66 }; 67 TAIL_ALLOC_OBJECT_CONST_PTR(struct psi, psi); 68 69 psi->off = 0xdeadbeeffacefeedULL; 70 psi->flags = 1; 71 psi->nr = 42; 72 73 do_ptrace(PTRACE_PEEKSIGINFO, pid, (unsigned long) psi, bad_request); 74 printf("ptrace(PTRACE_PEEKSIGINFO, %u, {off=%llu" 75 ", flags=PTRACE_PEEKSIGINFO_SHARED, nr=%u}, %#lx) = %s\n", 76 (unsigned) pid, psi->off, psi->nr, bad_request, errstr); 77 78 pid = fork(); 79 if ((pid_t) pid < 0) 80 perror_msg_and_fail("fork"); 81 82 if (!pid) { 83 sigset_t mask; 84 sigemptyset(&mask); 85 sigaddset(&mask, SIGUSR1); 86 sigaddset(&mask, SIGUSR2); 87 sigaddset(&mask, SIGALRM); 88 89 if (sigprocmask(SIG_BLOCK, &mask, NULL)) 90 perror_msg_and_fail("sigprocmask"); 91 92 raise(SIGUSR1); 93 raise(SIGUSR2); 94 raise(SIGALRM); 95 96 if (do_ptrace(PTRACE_TRACEME, 0, 0, 0)) 97 perror_msg_and_fail("child: PTRACE_TRACEME"); 98 99 raise(SIGSTOP); 100 _exit(0); 101 } 102 103 const unsigned int nsigs = 4; 104 const uid_t uid = geteuid(); 105 siginfo_t *sigs = tail_alloc(sizeof(*sigs) * nsigs); 106 107 psi->off = 0; 108 psi->flags = 0; 109 psi->nr = nsigs; 110 111 for (;;) { 112 int status, tracee, saved; 113 114 errno = 0; 115 tracee = wait(&status); 116 if (tracee <= 0) { 117 if (errno == EINTR) 118 continue; 119 saved = errno; 120 kill(pid, SIGKILL); 121 errno = saved; 122 perror_msg_and_fail("wait"); 123 } 124 if (WIFEXITED(status)) { 125 if (WEXITSTATUS(status) == 0) 126 break; 127 error_msg_and_fail("unexpected exit status %u", 128 WEXITSTATUS(status)); 129 } 130 if (WIFSIGNALED(status)) 131 error_msg_and_fail("unexpected signal %u", 132 WTERMSIG(status)); 133 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { 134 kill(pid, SIGKILL); 135 error_msg_and_fail("unexpected wait status %x", 136 status); 137 } 138 139 long rc = do_ptrace(PTRACE_PEEKSIGINFO, pid, 140 (unsigned long) psi, (unsigned long) sigs); 141 if (rc < 0) { 142 printf("ptrace(PTRACE_PEEKSIGINFO, %u" 143 ", {off=%llu, flags=0, nr=%u}, %p) = %s\n", 144 (unsigned) pid, psi->off, psi->nr, sigs, 145 errstr); 146 } else { 147 printf("ptrace(PTRACE_PEEKSIGINFO, %u" 148 ", {off=%llu, flags=0, nr=%u}" 149 ", [{si_signo=SIGUSR1, si_code=SI_TKILL" 150 ", si_pid=%u, si_uid=%u}" 151 ", {si_signo=SIGUSR2, si_code=SI_TKILL" 152 ", si_pid=%u, si_uid=%u}" 153 ", {si_signo=SIGALRM, si_code=SI_TKILL" 154 ", si_pid=%u, si_uid=%u}" 155 "]) = %s\n", 156 (unsigned) pid, psi->off, psi->nr, 157 (unsigned) pid, (unsigned) uid, 158 (unsigned) pid, (unsigned) uid, 159 (unsigned) pid, (unsigned) uid, 160 errstr); 161 } 162 163 if (do_ptrace(PTRACE_CONT, pid, 0, 0)) { 164 saved = errno; 165 kill(pid, SIGKILL); 166 errno = saved; 167 perror_msg_and_fail("ptrace"); 168 } 169 printf("ptrace(PTRACE_CONT, %ld, NULL, SIG_0) = 0\n", pid); 170 } 171 } 172 173 int 174 main(void) 175 { 176 const unsigned long bad_request = 177 (unsigned long) 0xdeadbeeffffffeedULL; 178 const unsigned long bad_data = 179 (unsigned long) 0xdeadcafefffff00dULL; 180 const unsigned long pid = 181 (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); 182 183 TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, filter_off); 184 185 const unsigned int sigset_size = get_sigset_size(); 186 187 void *const k_set = tail_alloc(sigset_size); 188 TAIL_ALLOC_OBJECT_CONST_PTR(siginfo_t, sip); 189 190 do_ptrace(bad_request, pid, 0, 0); 191 printf("ptrace(%#lx /* PTRACE_??? */, %u, NULL, NULL) = %s\n", 192 bad_request, (unsigned) pid, errstr); 193 194 do_ptrace(PTRACE_PEEKDATA, pid, bad_request, bad_data); 195 #ifdef IA64 196 printf("ptrace(PTRACE_PEEKDATA, %u, %#lx) = %s\n", 197 (unsigned) pid, bad_request, errstr); 198 #else 199 printf("ptrace(PTRACE_PEEKDATA, %u, %#lx, %#lx) = %s\n", 200 (unsigned) pid, bad_request, bad_data, errstr); 201 #endif 202 203 do_ptrace(PTRACE_PEEKTEXT, pid, bad_request, bad_data); 204 #ifdef IA64 205 printf("ptrace(PTRACE_PEEKTEXT, %u, %#lx) = %s\n", 206 (unsigned) pid, bad_request, errstr); 207 #else 208 printf("ptrace(PTRACE_PEEKTEXT, %u, %#lx, %#lx) = %s\n", 209 (unsigned) pid, bad_request, bad_data, errstr); 210 #endif 211 212 do_ptrace(PTRACE_PEEKUSER, pid, bad_request, bad_data); 213 #ifdef IA64 214 printf("ptrace(PTRACE_PEEKUSER, %u, %#lx) = %s\n", 215 (unsigned) pid, bad_request, errstr); 216 #else 217 printf("ptrace(PTRACE_PEEKUSER, %u, %#lx, %#lx) = %s\n", 218 (unsigned) pid, bad_request, bad_data, errstr); 219 #endif 220 221 do_ptrace(PTRACE_POKEUSER, pid, bad_request, bad_data); 222 printf("ptrace(PTRACE_POKEUSER, %u, %#lx, %#lx) = %s\n", 223 (unsigned) pid, bad_request, bad_data, errstr); 224 225 do_ptrace(PTRACE_ATTACH, pid, 0, 0); 226 printf("ptrace(PTRACE_ATTACH, %u) = %s\n", (unsigned) pid, errstr); 227 228 do_ptrace(PTRACE_INTERRUPT, pid, 0, 0); 229 printf("ptrace(PTRACE_INTERRUPT, %u) = %s\n", (unsigned) pid, errstr); 230 231 do_ptrace(PTRACE_KILL, pid, 0, 0); 232 printf("ptrace(PTRACE_KILL, %u) = %s\n", (unsigned) pid, errstr); 233 234 do_ptrace(PTRACE_LISTEN, pid, 0, 0); 235 printf("ptrace(PTRACE_LISTEN, %u) = %s\n", (unsigned) pid, errstr); 236 237 sigset_t libc_set; 238 sigemptyset(&libc_set); 239 sigaddset(&libc_set, SIGUSR1); 240 memcpy(k_set, &libc_set, sigset_size); 241 242 do_ptrace(PTRACE_SETSIGMASK, pid, sigset_size, (unsigned long) k_set); 243 printf("ptrace(PTRACE_SETSIGMASK, %u, %u, [USR1]) = %s\n", 244 (unsigned) pid, sigset_size, errstr); 245 246 do_ptrace(PTRACE_GETSIGMASK, pid, sigset_size, (unsigned long) k_set); 247 printf("ptrace(PTRACE_GETSIGMASK, %u, %u, %p) = %s\n", 248 (unsigned) pid, sigset_size, k_set, errstr); 249 250 do_ptrace(PTRACE_SECCOMP_GET_FILTER, pid, 42, 0); 251 printf("ptrace(PTRACE_SECCOMP_GET_FILTER, %u, 42, NULL) = %s\n", 252 (unsigned) pid, errstr); 253 254 do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data, 0); 255 printf("ptrace(PTRACE_SECCOMP_GET_METADATA, %u, %lu, NULL) = %s\n", 256 (unsigned) pid, bad_data, errstr); 257 258 do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, 7, 259 (unsigned long) filter_off); 260 printf("ptrace(PTRACE_SECCOMP_GET_METADATA, %u, 7, %p) = %s\n", 261 (unsigned) pid, filter_off, errstr); 262 263 *filter_off = 0xfacefeeddeadc0deULL; 264 do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data, 265 (unsigned long) filter_off); 266 printf("ptrace(PTRACE_SECCOMP_GET_METADATA, %u, %lu, " 267 "{filter_off=%" PRIu64 "}) = %s\n", 268 (unsigned) pid, bad_data, *filter_off, errstr); 269 270 do_ptrace(PTRACE_GETEVENTMSG, pid, bad_request, bad_data); 271 printf("ptrace(PTRACE_GETEVENTMSG, %u, %#lx, %#lx) = %s\n", 272 (unsigned) pid, bad_request, bad_data, errstr); 273 274 memset(sip, -1, sizeof(*sip)); 275 sip->si_signo = SIGIO; 276 sip->si_code = 1; 277 sip->si_errno = ENOENT; 278 sip->si_band = -2; 279 280 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 281 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGIO" 282 ", si_code=POLL_IN, si_errno=ENOENT, si_band=-2}) = %s\n", 283 (unsigned) pid, bad_request, errstr); 284 285 memset(sip, -1, sizeof(*sip)); 286 sip->si_signo = SIGTRAP; 287 sip->si_code = 1; 288 sip->si_errno = ENOENT; 289 sip->si_pid = 2; 290 sip->si_uid = 3; 291 sip->si_ptr = (void *) bad_request; 292 293 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 294 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGTRAP" 295 ", si_code=TRAP_BRKPT, si_errno=ENOENT, si_pid=2, si_uid=3" 296 ", si_value={int=%d, ptr=%p}}) = %s\n", 297 (unsigned) pid, bad_request, sip->si_int, sip->si_ptr, 298 errstr); 299 300 memset(sip, -1, sizeof(*sip)); 301 sip->si_signo = SIGILL; 302 sip->si_code = 1; 303 sip->si_errno = ENOENT; 304 sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; 305 306 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 307 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGILL" 308 ", si_code=ILL_ILLOPC, si_errno=ENOENT, si_addr=%p}) = %s\n", 309 (unsigned) pid, bad_request, sip->si_addr, errstr); 310 311 memset(sip, -1, sizeof(*sip)); 312 sip->si_signo = SIGFPE; 313 sip->si_code = 1; 314 sip->si_errno = ENOENT; 315 sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; 316 317 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 318 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGFPE" 319 ", si_code=FPE_INTDIV, si_errno=ENOENT, si_addr=%p}) = %s\n", 320 (unsigned) pid, bad_request, sip->si_addr, errstr); 321 322 memset(sip, -1, sizeof(*sip)); 323 sip->si_signo = SIGBUS; 324 sip->si_code = 1; 325 sip->si_errno = -2; 326 sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; 327 328 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 329 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGBUS" 330 ", si_code=BUS_ADRALN, si_errno=%d, si_addr=%p}) = %s\n", 331 (unsigned) pid, bad_request, sip->si_errno, sip->si_addr, 332 errstr); 333 334 memset(sip, -1, sizeof(*sip)); 335 sip->si_signo = SIGPROF; 336 sip->si_code = 0xbadc0ded; 337 sip->si_errno = -2; 338 sip->si_pid = 0; 339 sip->si_uid = 3; 340 sip->si_ptr = 0; 341 342 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 343 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGPROF" 344 ", si_code=%#x, si_errno=%d, si_pid=0, si_uid=3}) = %s\n", 345 (unsigned) pid, bad_request, sip->si_code, sip->si_errno, 346 errstr); 347 348 #ifdef HAVE_SIGINFO_T_SI_SYSCALL 349 memset(sip, -1, sizeof(*sip)); 350 sip->si_signo = SIGSYS; 351 sip->si_code = 1; 352 sip->si_errno = ENOENT; 353 sip->si_call_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; 354 sip->si_syscall = -1U; 355 sip->si_arch = AUDIT_ARCH_X86_64; 356 357 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 358 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGSYS" 359 ", si_code=SYS_SECCOMP, si_errno=ENOENT, si_call_addr=%p" 360 ", si_syscall=%u, si_arch=AUDIT_ARCH_X86_64})" 361 " = %s\n", 362 (unsigned) pid, bad_request, sip->si_call_addr, sip->si_syscall, 363 errstr); 364 365 sip->si_errno = 3141592653U; 366 sip->si_call_addr = NULL; 367 sip->si_syscall = __NR_read; 368 sip->si_arch = 0xda7a1057; 369 370 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 371 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGSYS" 372 ", si_code=SYS_SECCOMP, si_errno=%d, si_call_addr=NULL" 373 ", si_syscall=__NR_read, si_arch=%#x /* AUDIT_ARCH_??? */})" 374 " = %s\n", 375 (unsigned) pid, bad_request, sip->si_errno, sip->si_arch, 376 errstr); 377 #endif 378 379 #if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN 380 memset(sip, -1, sizeof(*sip)); 381 sip->si_signo = SIGHUP; 382 sip->si_code = SI_TIMER; 383 sip->si_errno = ENOENT; 384 sip->si_timerid = 0xdeadbeef; 385 sip->si_overrun = -1; 386 sip->si_ptr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; 387 388 do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (unsigned long) sip); 389 printf("ptrace(PTRACE_SETSIGINFO, %u, %#lx, {si_signo=SIGHUP" 390 ", si_code=SI_TIMER, si_errno=ENOENT, si_timerid=%#x" 391 ", si_overrun=%d, si_value={int=%d, ptr=%p}}) = %s\n", 392 (unsigned) pid, bad_request, sip->si_timerid, sip->si_overrun, 393 sip->si_int, sip->si_ptr, errstr); 394 #endif 395 396 do_ptrace(PTRACE_GETSIGINFO, pid, bad_request, (unsigned long) sip); 397 printf("ptrace(PTRACE_GETSIGINFO, %u, %#lx, %p)" 398 " = %s\n", (unsigned) pid, bad_request, sip, errstr); 399 400 do_ptrace(PTRACE_CONT, pid, 0, SIGUSR1); 401 printf("ptrace(PTRACE_CONT, %u, NULL, SIGUSR1) = %s\n", 402 (unsigned) pid, errstr); 403 404 do_ptrace(PTRACE_DETACH, pid, 0, SIGUSR2); 405 printf("ptrace(PTRACE_DETACH, %u, NULL, SIGUSR2) = %s\n", 406 (unsigned) pid, errstr); 407 408 do_ptrace(PTRACE_SYSCALL, pid, 0, SIGUSR1); 409 printf("ptrace(PTRACE_SYSCALL, %u, NULL, SIGUSR1) = %s\n", 410 (unsigned) pid, errstr); 411 412 #ifdef PTRACE_SINGLESTEP 413 do_ptrace(PTRACE_SINGLESTEP, pid, 0, SIGUSR2); 414 printf("ptrace(PTRACE_SINGLESTEP, %u, NULL, SIGUSR2) = %s\n", 415 (unsigned) pid, errstr); 416 #endif 417 418 #ifdef PTRACE_SINGLEBLOCK 419 do_ptrace(PTRACE_SINGLEBLOCK, pid, 0, SIGUSR1); 420 printf("ptrace(PTRACE_SINGLEBLOCK, %u, NULL, SIGUSR1) = %s\n", 421 (unsigned) pid, errstr); 422 #endif 423 424 #ifdef PTRACE_SYSEMU 425 do_ptrace(PTRACE_SYSEMU, pid, 0, SIGUSR2); 426 printf("ptrace(PTRACE_SYSEMU, %u, NULL, SIGUSR2) = %s\n", 427 (unsigned) pid, errstr); 428 #endif 429 #ifdef PTRACE_SYSEMU_SINGLESTEP 430 do_ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, SIGUSR1); 431 printf("ptrace(PTRACE_SYSEMU_SINGLESTEP, %u, NULL, SIGUSR1) = %s\n", 432 (unsigned) pid, errstr); 433 #endif 434 435 do_ptrace(PTRACE_SETOPTIONS, 436 pid, 0, PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE); 437 printf("ptrace(PTRACE_SETOPTIONS, %u, NULL" 438 ", PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE) = %s\n", 439 (unsigned) pid, errstr); 440 441 do_ptrace(PTRACE_SEIZE, pid, bad_request, PTRACE_O_TRACESYSGOOD); 442 printf("ptrace(PTRACE_SEIZE, %u, %#lx, PTRACE_O_TRACESYSGOOD) = %s\n", 443 (unsigned) pid, bad_request, errstr); 444 445 do_ptrace(PTRACE_SETREGSET, pid, 1, bad_request); 446 printf("ptrace(PTRACE_SETREGSET, %u, NT_PRSTATUS, %#lx) = %s\n", 447 (unsigned) pid, bad_request, errstr); 448 449 do_ptrace(PTRACE_GETREGSET, pid, 3, bad_request); 450 printf("ptrace(PTRACE_GETREGSET, %u, NT_PRPSINFO, %#lx) = %s\n", 451 (unsigned) pid, bad_request, errstr); 452 453 test_peeksiginfo(pid, bad_request); 454 455 do_ptrace(PTRACE_TRACEME, 0, 0, 0); 456 printf("ptrace(PTRACE_TRACEME) = %s\n", errstr); 457 458 puts("+++ exited with 0 +++"); 459 return 0; 460 } 461