utrace: Support non-contiguous syscall numbers
authorMichal Sojka <sojkam1@fel.cvut.cz>
Sun, 24 Sep 2017 14:38:21 +0000 (16:38 +0200)
committerJohn Crispin <john@phrozen.org>
Thu, 28 Sep 2017 06:26:56 +0000 (08:26 +0200)
commit1c48104ffc7f8d2c27dd8660a03a7728540fa946
tree9762fc45eeac6dfd58b4ad1bd3d5342ad038744d
parent582cf97315178b0f1a97ef38d6f9388cf63900fd
utrace: Support non-contiguous syscall numbers

ARM architecture does not have its system call numbers contiguous. So
far, utrace ignored the non-contiguous system calls, but it makes it
difficult to setup seccomp whitelists. This patch adds support for
these extra out-of-range syscalls.

It extends the generated file syscall_names.h to include a few
functions. Now, for ARM this file looks like:

    #include <asm/unistd.h>
    static const char *__syscall_names[] = {
     [280] = "waitid",
     [148] = "fdatasync",
    ...
     [252] = "epoll_wait",
     [74] = "sethostname",
    };
    static inline const char *syscall_name(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return __syscall_names[i];
      switch (i) {
        case 0x0f0001: return "breakpoint";
        case 0x0f0003: return "usr26";
        case 0x0f0004: return "usr32";
        case 0x0f0005: return "set_tls";
        case 0x0f0002: return "cacheflush";
      default: return (void*)0;
      }
    }
    static inline int syscall_index(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return i;
      switch (i) {
      case 0x0f0001: return ARRAY_SIZE(__syscall_names) + 0;
      case 0x0f0003: return ARRAY_SIZE(__syscall_names) + 1;
      case 0x0f0004: return ARRAY_SIZE(__syscall_names) + 2;
      case 0x0f0005: return ARRAY_SIZE(__syscall_names) + 3;
      case 0x0f0002: return ARRAY_SIZE(__syscall_names) + 4;
      default: return -1;
      }
    }
    static inline int syscall_index_to_number(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return i;
      switch (i) {
      case ARRAY_SIZE(__syscall_names) + 0: return 0x0f0001;
      case ARRAY_SIZE(__syscall_names) + 1: return 0x0f0003;
      case ARRAY_SIZE(__syscall_names) + 2: return 0x0f0004;
      case ARRAY_SIZE(__syscall_names) + 3: return 0x0f0005;
      case ARRAY_SIZE(__syscall_names) + 4: return 0x0f0002;
      default: return -1;
      }
    }
    #define SYSCALL_COUNT (ARRAY_SIZE(__syscall_names) + 5)

For x86, which does not have extra syscalls, the file looks this way:

    #include <asm/unistd.h>
    static const char *__syscall_names[] = {
     [247] = "waitid",
     [75] = "fdatasync",
     ...
     [232] = "epoll_wait",
     [170] = "sethostname",
    };
    static inline const char *syscall_name(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return __syscall_names[i];
      switch (i) {
      default: return (void*)0;
      }
    }
    static inline int syscall_index(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return i;
      switch (i) {
      default: return -1;
      }
    }
    static inline int syscall_index_to_number(unsigned i) {
      if (i < ARRAY_SIZE(__syscall_names))
        return i;
      switch (i) {
      default: return -1;
      }
    }
    #define SYSCALL_COUNT (ARRAY_SIZE(__syscall_names) + 0)

Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
jail/seccomp.c
make_syscall_h.sh
trace/trace.c