0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #if defined(__i386__) || defined(__x86_64__)
0013 #define SUPPORTED_ARCH 1
0014 #endif
0015
0016 #if defined(SUPPORTED_ARCH)
0017 #define __USE_GNU 1
0018 #define _GNU_SOURCE 1
0019
0020 #include <linux/types.h>
0021 #include <linux/filter.h>
0022 #include <linux/seccomp.h>
0023 #include <linux/unistd.h>
0024 #include <signal.h>
0025 #include <stdio.h>
0026 #include <stddef.h>
0027 #include <string.h>
0028 #include <sys/prctl.h>
0029 #include <unistd.h>
0030
0031 #define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
0032 #define syscall_nr (offsetof(struct seccomp_data, nr))
0033
0034 #if defined(__i386__)
0035 #define REG_RESULT REG_EAX
0036 #define REG_SYSCALL REG_EAX
0037 #define REG_ARG0 REG_EBX
0038 #define REG_ARG1 REG_ECX
0039 #define REG_ARG2 REG_EDX
0040 #define REG_ARG3 REG_ESI
0041 #define REG_ARG4 REG_EDI
0042 #define REG_ARG5 REG_EBP
0043 #elif defined(__x86_64__)
0044 #define REG_RESULT REG_RAX
0045 #define REG_SYSCALL REG_RAX
0046 #define REG_ARG0 REG_RDI
0047 #define REG_ARG1 REG_RSI
0048 #define REG_ARG2 REG_RDX
0049 #define REG_ARG3 REG_R10
0050 #define REG_ARG4 REG_R8
0051 #define REG_ARG5 REG_R9
0052 #endif
0053
0054 #ifndef PR_SET_NO_NEW_PRIVS
0055 #define PR_SET_NO_NEW_PRIVS 38
0056 #endif
0057
0058 #ifndef SYS_SECCOMP
0059 #define SYS_SECCOMP 1
0060 #endif
0061
0062 static void emulator(int nr, siginfo_t *info, void *void_context)
0063 {
0064 ucontext_t *ctx = (ucontext_t *)(void_context);
0065 int syscall;
0066 char *buf;
0067 ssize_t bytes;
0068 size_t len;
0069 if (info->si_code != SYS_SECCOMP)
0070 return;
0071 if (!ctx)
0072 return;
0073 syscall = ctx->uc_mcontext.gregs[REG_SYSCALL];
0074 buf = (char *) ctx->uc_mcontext.gregs[REG_ARG1];
0075 len = (size_t) ctx->uc_mcontext.gregs[REG_ARG2];
0076
0077 if (syscall != __NR_write)
0078 return;
0079 if (ctx->uc_mcontext.gregs[REG_ARG0] != STDERR_FILENO)
0080 return;
0081
0082 ctx->uc_mcontext.gregs[REG_RESULT] = -1;
0083 if (write(STDOUT_FILENO, "[ERR] ", 6) > 0) {
0084 bytes = write(STDOUT_FILENO, buf, len);
0085 ctx->uc_mcontext.gregs[REG_RESULT] = bytes;
0086 }
0087 return;
0088 }
0089
0090 static int install_emulator(void)
0091 {
0092 struct sigaction act;
0093 sigset_t mask;
0094 memset(&act, 0, sizeof(act));
0095 sigemptyset(&mask);
0096 sigaddset(&mask, SIGSYS);
0097
0098 act.sa_sigaction = &emulator;
0099 act.sa_flags = SA_SIGINFO;
0100 if (sigaction(SIGSYS, &act, NULL) < 0) {
0101 perror("sigaction");
0102 return -1;
0103 }
0104 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
0105 perror("sigprocmask");
0106 return -1;
0107 }
0108 return 0;
0109 }
0110
0111 static int install_filter(void)
0112 {
0113 struct sock_filter filter[] = {
0114
0115 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr),
0116
0117 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 0, 1),
0118 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
0119 #ifdef __NR_sigreturn
0120 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 0, 1),
0121 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
0122 #endif
0123 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit_group, 0, 1),
0124 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
0125 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 0, 1),
0126 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
0127 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 1, 0),
0128 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 3, 2),
0129
0130
0131 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
0132 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDIN_FILENO, 4, 0),
0133 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
0134
0135
0136 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
0137 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDOUT_FILENO, 1, 0),
0138
0139 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDERR_FILENO, 1, 2),
0140
0141 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
0142 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
0143 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
0144 };
0145 struct sock_fprog prog = {
0146 .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
0147 .filter = filter,
0148 };
0149
0150 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
0151 perror("prctl(NO_NEW_PRIVS)");
0152 return 1;
0153 }
0154
0155
0156 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
0157 perror("prctl");
0158 return 1;
0159 }
0160 return 0;
0161 }
0162
0163 #define payload(_c) (_c), sizeof((_c))
0164 int main(int argc, char **argv)
0165 {
0166 char buf[4096];
0167 ssize_t bytes = 0;
0168 if (install_emulator())
0169 return 1;
0170 if (install_filter())
0171 return 1;
0172 syscall(__NR_write, STDOUT_FILENO,
0173 payload("OHAI! WHAT IS YOUR NAME? "));
0174 bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf));
0175 syscall(__NR_write, STDOUT_FILENO, payload("HELLO, "));
0176 syscall(__NR_write, STDOUT_FILENO, buf, bytes);
0177 syscall(__NR_write, STDERR_FILENO,
0178 payload("Error message going to STDERR\n"));
0179 return 0;
0180 }
0181 #else
0182
0183
0184
0185
0186
0187 int main(void)
0188 {
0189 return 1;
0190 }
0191 #endif