diff --git a/seccomp/secccomp.c b/seccomp/secccomp.c new file mode 100644 index 0000000..e653d2e --- /dev/null +++ b/seccomp/secccomp.c @@ -0,0 +1,116 @@ +/*************************************************************************\ +* Copyright (C) Michael Kerrisk, 2022. * +* * +* This program is free software. You may use, modify, and redistribute it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation, either version 3 or (at your option) any * +* later version. This program is distributed without any warranty. See * +* the file COPYING.gpl-v3 for details. * +\*************************************************************************/ + +/* seccomp_trap_sigsys.c + + Demonstrate that SECCOMP_RET_TRAP causes a SIGSYS signal that + can be caught by the program. After the handler returns, execution + of the main program continues. +*/ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "tlpi_hdr.h" + +/* For the x32 ABI, all system call numbers have bit 30 set */ + +#define X32_SYSCALL_BIT 0x40000000 + +static int +seccomp(unsigned int operation, unsigned int flags, void *args) +{ + return syscall(__NR_seccomp, operation, flags, args); +} + +static void +install_filter(void) +{ + struct sock_filter filter[] = { + /* Load architecture */ + + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, + (offsetof(struct seccomp_data, arch))), + + /* Kill process if the architecture is not what we expect */ + + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), + + /* Load system call number */ + + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, + (offsetof(struct seccomp_data, nr))), + + /* Kill the process if this is an x32 system call (bit 30 is set) */ + + BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, X32_SYSCALL_BIT, 0, 1), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS), + + /* getppid() results in SIGSYS; all other system calls are allowed */ + + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_getppid, 0, 1), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW) + }; + + struct sock_fprog prog = { + .len = sizeof(filter) / sizeof(filter[0]), + .filter = filter, + }; + + if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog) == -1) + return -10; + /* On Linux 3.16 and earlier, we must instead use: + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) + errExit("prctl-PR_SET_SECCOMP"); + */ +} + +static void /* Handler for SIGINT signal */ +sigHandler(int sig) +{ + printf("SIGSYS!\n"); /* UNSAFE (see Section 21.1.2) */ +} + +int +main(int argc, char *argv[]) +{ + /* Set up seccomp filter */ + + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) + return -11; + + install_filter(); + + /* Establish handler for SIGSYS */ + + struct sigaction sa; + sa.sa_flags = 0; + sa.sa_handler = sigHandler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGSYS, &sa, NULL) == -1) + return -18; + + printf("About to call getppid()\n"); + + (void) getppid(); /* Results in SIGSYS; system call is not executed */ + + /* After the SIGSYS handler returns, execution continues in main() */ + + printf("Bye\n"); + + exit(EXIT_SUCCESS); +} diff --git a/seccomp/tlpi_hdr.h b/seccomp/tlpi_hdr.h new file mode 100644 index 0000000..906b586 --- /dev/null +++ b/seccomp/tlpi_hdr.h @@ -0,0 +1,82 @@ +/*************************************************************************\ +* Copyright (C) Michael Kerrisk, 2022. * +* * +* This program is free software. You may use, modify, and redistribute it * +* under the terms of the GNU Lesser General Public License as published * +* by the Free Software Foundation, either version 3 or (at your option) * +* any later version. This program is distributed without any warranty. * +* See the files COPYING.lgpl-v3 and COPYING.gpl-v3 for details. * +\*************************************************************************/ + +/* tlpi_hdr.h + + Standard header file used by nearly all of our example programs. +*/ +#ifndef TLPI_HDR_H +#define TLPI_HDR_H /* Prevent accidental double inclusion */ + +#include /* Type definitions used by many programs */ +#include /* Standard I/O functions */ +#include /* Prototypes of commonly used library functions, + plus EXIT_SUCCESS and EXIT_FAILURE constants */ +#include /* Prototypes for many system calls */ +#include /* Declares errno and defines error constants */ +#include /* Commonly used string-handling functions */ +#include /* 'bool' type plus 'true' and 'false' constants */ + +//#include "get_num.h" /* Declares our functions for handling numeric +// arguments (getInt(), getLong()) */ + +//#include "error_functions.h" /* Declares our error-handling functions */ + +/* Unfortunately some UNIX implementations define FALSE and TRUE - + here we'll undefine them */ + +#ifdef TRUE +#undef TRUE +#endif + +#ifdef FALSE +#undef FALSE +#endif + +typedef enum { FALSE, TRUE } Boolean; + +#define min(m,n) ((m) < (n) ? (m) : (n)) +#define max(m,n) ((m) > (n) ? (m) : (n)) + +/* Some systems don't define 'socklen_t' */ + +#if defined(__sgi) +typedef int socklen_t; +#endif + +#if defined(__sun) +#include /* Has definition of FASYNC */ +#endif + +#if ! defined(O_ASYNC) && defined(FASYNC) +/* Some systems define FASYNC instead of O_ASYNC */ +#define O_ASYNC FASYNC +#endif + +#if defined(MAP_ANON) && ! defined(MAP_ANONYMOUS) +/* BSD derivatives usually have MAP_ANON, not MAP_ANONYMOUS */ +#define MAP_ANONYMOUS MAP_ANON + +#endif + +#if ! defined(O_SYNC) && defined(O_FSYNC) +/* Some implementations have O_FSYNC instead of O_SYNC */ +#define O_SYNC O_FSYNC +#endif + +#if defined(__FreeBSD__) + +/* FreeBSD uses these alternate names for fields in the sigval structure */ + +#define sival_int sigval_int +#define sival_ptr sigval_ptr +#endif + +#endif