|
Packit |
4e8bc4 |
#include "config.h"
|
|
Packit |
4e8bc4 |
#include <seccomp.h>
|
|
Packit |
4e8bc4 |
#include <termios.h>
|
|
Packit |
4e8bc4 |
#include <errno.h>
|
|
Packit |
4e8bc4 |
#include <stdlib.h>
|
|
Packit |
4e8bc4 |
#include <sys/ioctl.h>
|
|
Packit |
4e8bc4 |
#include <signal.h>
|
|
Packit |
4e8bc4 |
#include <string.h>
|
|
Packit |
4e8bc4 |
#include "memcached.h"
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static char *kill_msg;
|
|
Packit |
4e8bc4 |
// Make sure to preserve the ??? position in the string, or correct the offsets
|
|
Packit |
4e8bc4 |
// in the syssig handler.
|
|
Packit |
4e8bc4 |
#define KILL_MSG_STR "Seccomp policy failure. Caught syscall ???. This is " \
|
|
Packit |
4e8bc4 |
"either an exploit attempt, or your system is not supported yet.\n"
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static void handle_syssig(int signum, siginfo_t *si, void *thread_context) {
|
|
Packit |
4e8bc4 |
#if defined(si_syscall)
|
|
Packit |
4e8bc4 |
int syscall_no = si->si_syscall;
|
|
Packit |
4e8bc4 |
#else
|
|
Packit |
4e8bc4 |
// If system has no support for si_syscal, the information may not be
|
|
Packit |
4e8bc4 |
// precise.
|
|
Packit |
4e8bc4 |
int syscall_no = si->si_value.sival_int;
|
|
Packit |
4e8bc4 |
#endif
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// Replace the characters in the kill message with the syscall number. We
|
|
Packit |
4e8bc4 |
// can't safely printf (even write is not really valid, but we're crashing
|
|
Packit |
4e8bc4 |
// anyway).
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
kill_msg[39] = (syscall_no / 100) % 10 + '0';
|
|
Packit |
4e8bc4 |
kill_msg[40] = (syscall_no / 10) % 10 + '0';
|
|
Packit |
4e8bc4 |
kill_msg[41] = syscall_no % 10 + '0';
|
|
Packit |
4e8bc4 |
if (write(2, kill_msg, strlen(kill_msg)) == -1) {
|
|
Packit |
4e8bc4 |
// An error occurred, but we can't do anything about it here. This check
|
|
Packit |
4e8bc4 |
// is mostly to avoid the "ignoring return value of 'write'" error on
|
|
Packit |
4e8bc4 |
// distributions with broken gcc (no "ignore via cast to void" support).
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// We can't use the nice exit() version because it causes at_exit handlers
|
|
Packit |
4e8bc4 |
// to be looked up and run. We can't take any locks while handling the
|
|
Packit |
4e8bc4 |
// signal, so _exit() is the only thing to do safely.
|
|
Packit |
4e8bc4 |
_exit(EXIT_FAILURE);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static const struct sigaction act = {
|
|
Packit |
4e8bc4 |
.sa_sigaction = handle_syssig,
|
|
Packit |
4e8bc4 |
.sa_flags = SA_SIGINFO,
|
|
Packit |
4e8bc4 |
};
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
void setup_privilege_violations_handler(void) {
|
|
Packit |
4e8bc4 |
kill_msg = malloc(strlen(KILL_MSG_STR)+1);
|
|
Packit |
4e8bc4 |
strcpy(kill_msg, KILL_MSG_STR);
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
sigaction(SIGSYS, &act, NULL);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// If anything crosses the policy, kill the process.
|
|
Packit |
4e8bc4 |
#define DENY_ACTION SCMP_ACT_TRAP
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
void drop_privileges(void) {
|
|
Packit |
4e8bc4 |
scmp_filter_ctx ctx = seccomp_init(DENY_ACTION);
|
|
Packit |
4e8bc4 |
if (ctx == NULL) {
|
|
Packit |
4e8bc4 |
return;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
int rc = 0;
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shmctl), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ));
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCGETS));
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 0);
|
|
Packit |
4e8bc4 |
#endif
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
#ifdef MEMCACHED_DEBUG
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
if (settings.relaxed_privileges) {
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
#endif
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
if (rc != 0) {
|
|
Packit |
4e8bc4 |
goto fail;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
rc = seccomp_load(ctx);
|
|
Packit |
4e8bc4 |
if (rc < 0) {
|
|
Packit |
4e8bc4 |
goto fail;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
seccomp_release(ctx);
|
|
Packit |
4e8bc4 |
return;
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
fail:
|
|
Packit |
4e8bc4 |
seccomp_release(ctx);
|
|
Packit |
4e8bc4 |
fprintf(stderr, "Failed to set a seccomp profile on the main thread\n");
|
|
Packit |
4e8bc4 |
exit(EXIT_FAILURE);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
void drop_worker_privileges(void) {
|
|
Packit |
4e8bc4 |
scmp_filter_ctx ctx = seccomp_init(DENY_ACTION);
|
|
Packit |
4e8bc4 |
if (ctx == NULL) {
|
|
Packit |
4e8bc4 |
return;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
int rc = 0;
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpeername), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrusage), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ));
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// for spawning the LRU crawler
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// stat
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockname), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
if (settings.shutdown_command) {
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tgkill), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tkill), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
if (settings.relaxed_privileges) {
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);
|
|
Packit |
4e8bc4 |
} else {
|
|
Packit |
4e8bc4 |
// stdout
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 1));
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 1));
|
|
Packit |
4e8bc4 |
// stderr
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 2));
|
|
Packit |
4e8bc4 |
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 2));
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
if (rc != 0) {
|
|
Packit |
4e8bc4 |
goto fail;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
rc = seccomp_load(ctx);
|
|
Packit |
4e8bc4 |
if (rc < 0) {
|
|
Packit |
4e8bc4 |
goto fail;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
seccomp_release(ctx);
|
|
Packit |
4e8bc4 |
return;
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
fail:
|
|
Packit |
4e8bc4 |
seccomp_release(ctx);
|
|
Packit |
4e8bc4 |
fprintf(stderr, "Failed to set a seccomp profile on a worker thread\n");
|
|
Packit |
4e8bc4 |
exit(EXIT_FAILURE);
|
|
Packit |
4e8bc4 |
}
|