Skip to content

Instantly share code, notes, and snippets.

@adaszko adaszko/mmaptrace.c
Last active Aug 6, 2019

Embed
What would you like to do?
/*
* 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, &regs) == -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, &regs) == -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
You can’t perform that action at this time.