Last active
August 6, 2019 12:32
-
-
Save adaszko/b2fbd0acf5b7a54a1aa519febef858e6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Intercept select set of syscalls made by PID (passed as a CLI argument) and | |
| * invoke jstack *before* returning from the syscall. | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <errno.h> | |
| #include <string.h> | |
| #include <syscall.h> | |
| #include <sys/types.h> | |
| #include <sys/wait.h> | |
| #include <sys/user.h> | |
| #include <sys/ptrace.h> | |
| int main(int argc, char *argv[]) | |
| { | |
| if (argc != 2) { | |
| printf("usage: %s PID | tee report.txt\n", argv[0]); | |
| return 1; | |
| } | |
| pid_t pid = atoi(argv[1]); | |
| printf("Watching PID %d...\n", pid); | |
| char jstack_command[128]; | |
| sprintf(jstack_command, "jstack %d", pid); | |
| if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) { | |
| perror("PTRACE_SEIZE"); | |
| exit(__LINE__); | |
| } | |
| if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) { | |
| perror("PTRACE_INTERRUPT"); | |
| exit(__LINE__); | |
| } | |
| int status = 0; | |
| if (waitpid(pid, &status, __WALL) == -1) { | |
| perror("waitpid"); | |
| exit(EXIT_FAILURE); | |
| } | |
| for (;;) { | |
| if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1) { | |
| perror("PTRACE_SYSCALL"); | |
| exit(__LINE__); | |
| } | |
| if (waitpid(pid, &status, 0) == -1) { | |
| perror("waitpid"); | |
| exit(__LINE__); | |
| } | |
| if (WIFEXITED(status)) { | |
| printf("Tracee exited\n"); | |
| break; | |
| } | |
| /* Gather system call arguments */ | |
| struct user_regs_struct regs; | |
| if (ptrace(PTRACE_GETREGS, pid, 0, ®s) == -1) { | |
| perror("PTRACE_GETREGS"); | |
| exit(__LINE__); | |
| } | |
| long syscall = regs.orig_rax; | |
| if (syscall == SYS_mmap) { | |
| fprintf(stdout, "mmap(%lx, %ld, %ld, %ld, %ld, %ld)", | |
| (long)regs.rdi, | |
| (long)regs.rsi, | |
| (long)regs.rdx, | |
| (long)regs.r10, | |
| (long)regs.r8, | |
| (long)regs.r9); | |
| if (system(jstack_command) < 0) { | |
| perror("system"); | |
| exit(__LINE__); | |
| } | |
| } | |
| else if (syscall == SYS_munmap) { | |
| fprintf(stdout, "munmap(%lx, %ld, %ld, %ld, %ld, %ld)", | |
| (long)regs.rdi, | |
| (long)regs.rsi, | |
| (long)regs.rdx, | |
| (long)regs.r10, | |
| (long)regs.r8, | |
| (long)regs.r9); | |
| if (system(jstack_command) < 0) { | |
| perror("system"); | |
| exit(__LINE__); | |
| } | |
| } | |
| else if (syscall == SYS_mremap) { | |
| fprintf(stdout, "mremap(%lx, %ld, %ld, %ld, %ld, %ld)", | |
| (long)regs.rdi, | |
| (long)regs.rsi, | |
| (long)regs.rdx, | |
| (long)regs.r10, | |
| (long)regs.r8, | |
| (long)regs.r9); | |
| if (system(jstack_command) < 0) { | |
| perror("system"); | |
| exit(__LINE__); | |
| } | |
| } | |
| if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1) { | |
| perror("PTRACE_SYSCALL"); | |
| exit(__LINE__); | |
| } | |
| if (waitpid(pid, 0, 0) == -1) { | |
| perror("waitpid"); | |
| exit(__LINE__); | |
| } | |
| if (syscall == SYS_mmap || syscall == SYS_munmap || syscall == SYS_mremap) { | |
| if (ptrace(PTRACE_GETREGS, pid, 0, ®s) == -1) { | |
| fprintf(stdout, " = ?\n"); | |
| perror("PTRACE_GETREGS"); | |
| exit(__LINE__); | |
| } | |
| if (syscall == SYS_mmap) { | |
| fprintf(stdout, "mmap(...) = %ld\n", (long)regs.rax); | |
| } else if (syscall == SYS_munmap) { | |
| fprintf(stdout, "munmap(...) = %ld\n", (long)regs.rax); | |
| } else if (syscall == SYS_mremap) { | |
| fprintf(stdout, "mremap(...) = %ld\n", (long)regs.rax); | |
| } | |
| } | |
| } | |
| return 0; | |
| } | |
| // vim:shiftwidth=4:expandtab:autoindent:tabstop=4:smartindent |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment