Trapping System Calls with seccomp

75 views Asked by At

As a proof of concept, I wrote a simple wrapper that traps a specific system call (e.g., mmap) from the wrapped program using seccomp:

#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <seccomp.h>
#include <sys/mman.h>
#include <unistd.h>

void handler(int signum, siginfo_t* si, void* ctx) {
  std::cout << "sigsys: " << si->si_syscall << std::endl;

  auto uctx = (ucontext_t*) ctx;
  auto addr = (void*) uctx->uc_mcontext.gregs[REG_RDI];
  auto length = (size_t) uctx->uc_mcontext.gregs[REG_RSI];
  auto prot = (int) uctx->uc_mcontext.gregs[REG_RDX];
  auto flags = (int) uctx->uc_mcontext.gregs[REG_R10];
  auto fd = (int) uctx->uc_mcontext.gregs[REG_R8];
  auto offset = (off_t) uctx->uc_mcontext.gregs[REG_R9];

  std::cout << "addr:   " << addr   << "\n"
            << "length: " << length << "\n"
            << "prot:   " << prot   << "\n"
            << "flags:  " << flags  << "\n"
            << "fd:     " << fd     << "\n"
            << "offset: " << offset << std::endl;

  auto ptr = mmap(addr, length, prot, flags, fd, offset);
  std::cout << "ptr: " << ptr << std::endl;
  uctx->uc_mcontext.gregs[REG_RAX] = (greg_t) ptr;
}

int main(int argc, char* argv[]) {
  if (argc == 0) {
    perror("argc");
    exit(EXIT_FAILURE);
  }

  struct sigaction sa = {};
  sa.sa_flags = SA_SIGINFO;
  sa.sa_sigaction = handler;
  sigaction(SIGSYS, &sa, NULL);

  auto ctx = seccomp_init(SCMP_ACT_ALLOW);
  seccomp_rule_add(ctx, SCMP_ACT_TRAP, SCMP_SYS(mmap), 0);
  seccomp_load(ctx);
  execve(argv[1], nullptr, nullptr);
  seccomp_release(ctx);

  return EXIT_SUCCESS;
}

I compile and run it as follows (where test is the wrapped program):

c++ -std=c++11 -o trap trap.cc -lseccomp
./trap test

The goal is to trap the original system call, print out some debugging information, and then execute the original system call with possibly modified arguments. In the sample code, everything works great up until calling mmap in the signal handler, which crashes the program (from strace):

mmap(NULL, 76616, PROT_READ, MAP_PRIVATE, 3, 0) = 0x9
--- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x7fc93f90d186, si_syscall=__NR_mmap, si_arch=AUDIT_ARCH_X86_64} ---
+++ killed by SIGSYS (core dumped) +++
Bad system call (core dumped)

I assume this is because the seccomp rule also prevents the handler from calling mmap. Is there a simple way to get around this, or an alternative/better approach?

0

There are 0 answers