"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/linux_priv.c" (21 Feb 2022, 9354 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "linux_priv.c" see the Fossies "Dox" file reference documentation.

    1 #include "config.h"
    2 #include <seccomp.h>
    3 #include <termios.h>
    4 #include <errno.h>
    5 #include <stdlib.h>
    6 #include <sys/ioctl.h>
    7 #include <signal.h>
    8 #include <string.h>
    9 #include "memcached.h"
   10 
   11 static char *kill_msg;
   12 // Make sure to preserve the ??? position in the string, or correct the offsets
   13 // in the syssig handler.
   14 #define KILL_MSG_STR "Seccomp policy failure. Caught syscall ???. This is " \
   15     "either an exploit attempt, or your system is not supported yet.\n"
   16 
   17 static void handle_syssig(int signum, siginfo_t *si, void *thread_context) {
   18 #if defined(si_syscall)
   19     int syscall_no = si->si_syscall;
   20 #else
   21     // If system has no support for si_syscal, the information may not be
   22     // precise.
   23     int syscall_no = si->si_value.sival_int;
   24 #endif
   25 
   26     // Replace the characters in the kill message with the syscall number. We
   27     // can't safely printf (even write is not really valid, but we're crashing
   28     // anyway).
   29 
   30     kill_msg[39] = (syscall_no / 100) % 10 + '0';
   31     kill_msg[40] = (syscall_no / 10) % 10 + '0';
   32     kill_msg[41] = syscall_no % 10 + '0';
   33     if (write(2, kill_msg, strlen(kill_msg)) == -1) {
   34         // An error occurred, but we can't do anything about it here. This check
   35         // is mostly to avoid the "ignoring return value of 'write'" error on
   36         // distributions with broken gcc (no "ignore via cast to void" support).
   37     }
   38 
   39     // We can't use the nice exit() version because it causes at_exit handlers
   40     // to be looked up and run. We can't take any locks while handling the
   41     // signal, so _exit() is the only thing to do safely.
   42     _exit(EXIT_FAILURE);
   43 }
   44 
   45 static const struct sigaction act = {
   46     .sa_sigaction = handle_syssig,
   47     .sa_flags = SA_SIGINFO,
   48 };
   49 
   50 void setup_privilege_violations_handler(void) {
   51     kill_msg = malloc(strlen(KILL_MSG_STR)+1);
   52     strcpy(kill_msg, KILL_MSG_STR);
   53 
   54     sigaction(SIGSYS, &act, NULL);
   55 }
   56 
   57 // If anything crosses the policy, kill the process.
   58 #define DENY_ACTION SCMP_ACT_TRAP
   59 
   60 void drop_privileges(void) {
   61     scmp_filter_ctx ctx = seccomp_init(DENY_ACTION);
   62     if (ctx == NULL) {
   63         return;
   64     }
   65 
   66     int rc = 0;
   67     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
   68     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
   69     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
   70     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
   71     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0);
   72     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
   73     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
   74     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0);
   75     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
   76     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0);
   77     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
   78     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);
   79     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
   80     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
   81     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
   82     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
   83     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shmctl), 0);
   84     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
   85     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
   86     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
   87     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ));
   88     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCGETS));
   89     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(msync), 0);
   90     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(umask), 0);
   91 
   92 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
   93     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 0);
   94 #endif
   95     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0);
   96 
   97 #ifdef MEMCACHED_DEBUG
   98     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
   99     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
  100     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
  101     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0);
  102     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
  103     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
  104 
  105     if (settings.relaxed_privileges) {
  106         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
  107         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0);
  108         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
  109     }
  110 #endif
  111 
  112     if (rc != 0) {
  113         goto fail;
  114     }
  115 
  116     rc = seccomp_load(ctx);
  117     if (rc < 0) {
  118         goto fail;
  119     }
  120 
  121     seccomp_release(ctx);
  122     return;
  123 
  124 fail:
  125     seccomp_release(ctx);
  126     fprintf(stderr, "Failed to set a seccomp profile on the main thread\n");
  127     exit(EXIT_FAILURE);
  128 }
  129 
  130 void drop_worker_privileges(void) {
  131     scmp_filter_ctx ctx = seccomp_init(DENY_ACTION);
  132     if (ctx == NULL) {
  133         return;
  134     }
  135 
  136     int rc = 0;
  137     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
  138     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
  139     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
  140     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
  141     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0);
  142     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
  143     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
  144     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0);
  145     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 0);
  146     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
  147     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0);
  148     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
  149     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpeername), 0);
  150     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
  151     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0);
  152     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrusage), 0);
  153     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
  154     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0);
  155     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
  156     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0);
  157     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
  158     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ));
  159     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(msync), 0);
  160 
  161     // for spawning the LRU crawler
  162     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0);
  163     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
  164     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0);
  165     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
  166 
  167     // stat
  168     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockname), 0);
  169     rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
  170 
  171     if (settings.shutdown_command) {
  172         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tgkill), 0);
  173         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tkill), 0);
  174         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
  175         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
  176         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
  177         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0);
  178     }
  179 
  180     if (settings.relaxed_privileges) {
  181         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
  182         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0);
  183         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
  184         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
  185         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
  186         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
  187         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
  188         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);
  189         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
  190     } else {
  191         // stdout
  192         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 1));
  193         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 1));
  194         // stderr
  195         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 2));
  196         rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 2));
  197     }
  198 
  199     if (rc != 0) {
  200         goto fail;
  201     }
  202 
  203     rc = seccomp_load(ctx);
  204     if (rc < 0) {
  205         goto fail;
  206     }
  207 
  208     seccomp_release(ctx);
  209     return;
  210 
  211 fail:
  212     seccomp_release(ctx);
  213     fprintf(stderr, "Failed to set a seccomp profile on a worker thread\n");
  214     exit(EXIT_FAILURE);
  215 }