text: /*
   * syscall reporting example for seccomp
   *
   * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
   * Authors:
   *  Will Drewry <wad@chromium.org>
   *  Kees Cook <keescook@chromium.org>
   *
   * The code may be used by anyone for any purpose, and can serve as a
   * starting point for developing applications using mode 2 seccomp.
   */
  #include "syscall-reporter.h"
  #include "syscall-names.h"
  
  const char * const msg_needed = "Looks like you also need syscall: ";
  
  /* Since "sprintf" is technically not signal-safe, reimplement %d here. */
  static void write_uint(char *buf, unsigned int val)
  {
  	int width = 0;
  	unsigned int tens;
  
  	if (val == 0) {
  		strcpy(buf, "0");
  		return;
  	}
  	for (tens = val; tens; tens /= 10)
  		++ width;
  	buf[width] = '\0';
  	for (tens = val; tens; tens /= 10)
  		buf[--width] = '0' + (tens % 10);
  }
  
  static void reporter(int nr, siginfo_t *info, void *void_context)
  {
  #ifdef SECCOMP
  	char buf[128];
  	ucontext_t *ctx = (ucontext_t *)(void_context);
  	unsigned int syscall;
  	if (info->si_code != SYS_SECCOMP)
  		return;
  	if (!ctx)
  		return;
  	syscall = ctx->uc_mcontext.gregs[REG_SYSCALL];
  	strcpy(buf, msg_needed);
  	if (syscall < sizeof(syscall_names)) {
  		strcat(buf, syscall_names[syscall]);
  		strcat(buf, "(");
  	}
  	write_uint(buf + strlen(buf), syscall);
  	if (syscall < sizeof(syscall_names))
  		strcat(buf, ")");
  	strcat(buf, "\n");
  	write(STDERR_FILENO, buf, strlen(buf));
  	_exit(1);
  #endif
  }
  
  int install_syscall_reporter(void)
  {
  #ifdef SECCOMP
  	struct sigaction act;
  	sigset_t mask;
  	memset(&act, 0, sizeof(act));
  	sigemptyset(&mask);
  	sigaddset(&mask, SIGSYS);
  
  	act.sa_sigaction = &reporter;
  	act.sa_flags = SA_SIGINFO;
  	if (sigaction(SIGSYS, &act, NULL) < 0) {
  		perror("sigaction");
  		return -1;
  	}
  	if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
  		perror("sigprocmask");
  		return -1;
  	}
  #endif
  	return 0;
  }
  