aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-08-27 02:39:20 -0400
committerMike Frysinger <vapier@gentoo.org>2021-04-17 00:56:53 -0400
commit24dd6026cab83b17bbf727feb07ced35fe75bb75 (patch)
tree14b2b9ed271af2819bd02fd1bb6004692cec7cf1 /security.c
parentrefresh http:// URIs (diff)
downloadpax-utils-24dd6026cab83b17bbf727feb07ced35fe75bb75.tar.gz
pax-utils-24dd6026cab83b17bbf727feb07ced35fe75bb75.tar.bz2
pax-utils-24dd6026cab83b17bbf727feb07ced35fe75bb75.zip
security: pregen seccomp bpf programsv1.3
Since the bpf programs are the same across runs, generate it ahead of time. This way we don't have to link against libseccomp and run the library calls at runtime which helps cut out most overhead. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'security.c')
-rw-r--r--security.c214
1 files changed, 24 insertions, 190 deletions
diff --git a/security.c b/security.c
index 802e586..4fecfa3 100644
--- a/security.c
+++ b/security.c
@@ -6,6 +6,7 @@
*/
#include "paxinc.h"
+#include "seccomp-bpf.h"
#ifdef __linux__
@@ -26,202 +27,23 @@
#define CLONE_NEWUTS 0
#endif
+#ifndef PR_SET_SECCOMP
+#define PR_SET_SECCOMP 22
+#endif
+#ifndef SECCOMP_MODE_FILTER
+#define SECCOMP_MODE_FILTER 2
+#endif
+
#ifdef __SANITIZE_ADDRESS__
/* ASAN does some weird stuff. */
# define ALLOW_PIDNS 0
+# undef WANT_SECCOMP
#else
# define ALLOW_PIDNS 1
#endif
-#ifdef WANT_SECCOMP
-# include <seccomp.h>
-
-/* Simple helper to add all of the syscalls in an array. */
-static int pax_seccomp_rules_add(scmp_filter_ctx ctx, int syscalls[], size_t num)
-{
- static uint8_t prio;
- size_t i;
- for (i = 0; i < num; ++i) {
- if (syscalls[i] < 0)
- continue;
-
- if (seccomp_syscall_priority(ctx, syscalls[i], prio++) < 0) {
- warnp("seccomp_syscall_priority failed");
- return -1;
- }
- if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) < 0) {
- warnp("seccomp_rule_add failed");
- return -1;
- }
- }
- return 0;
-}
-#define pax_seccomp_rules_add(ctx, syscalls) pax_seccomp_rules_add(ctx, syscalls, ARRAY_SIZE(syscalls))
-
-static void
-pax_seccomp_sigal(__unused__ int signo, siginfo_t *info, __unused__ void *context)
-{
-#ifdef si_syscall
- warn("seccomp violated: syscall %i", info->si_syscall);
- fflush(stderr);
- warn(" syscall = %s",
- seccomp_syscall_resolve_num_arch(seccomp_arch_native(), info->si_syscall));
- fflush(stderr);
-#else
- warn("seccomp violated: syscall unknown (no si_syscall)");
-#endif
- kill(getpid(), SIGSYS);
- _exit(1);
-}
-
-static void pax_seccomp_signal_init(void)
-{
- struct sigaction act;
- sigemptyset(&act.sa_mask);
- act.sa_sigaction = pax_seccomp_sigal,
- act.sa_flags = SA_SIGINFO | SA_RESETHAND;
- sigaction(SIGSYS, &act, NULL);
-}
-
-static void pax_seccomp_init(bool allow_forking)
-{
- /* Order determines priority (first == lowest prio). */
- int base_syscalls[] = {
- /* We write the most w/scanelf. */
- SCMP_SYS(write),
- SCMP_SYS(writev),
- SCMP_SYS(pwrite64),
- SCMP_SYS(pwritev),
-
- /* Then the stat family of functions. */
- SCMP_SYS(newfstatat),
- SCMP_SYS(fstat),
- SCMP_SYS(fstat64),
- SCMP_SYS(fstatat64),
- SCMP_SYS(lstat),
- SCMP_SYS(lstat64),
- SCMP_SYS(stat),
- SCMP_SYS(stat64),
- SCMP_SYS(statx),
-
- /* Then the fd close func. */
- SCMP_SYS(close),
-
- /* Then fd open family of functions. */
- SCMP_SYS(open),
- SCMP_SYS(openat),
-
- /* Then the memory mapping functions. */
- SCMP_SYS(mmap),
- SCMP_SYS(mmap2),
- SCMP_SYS(munmap),
-
- /* Then the directory reading functions. */
- SCMP_SYS(getdents),
- SCMP_SYS(getdents64),
-
- /* Then the file reading functions. */
- SCMP_SYS(pread64),
- SCMP_SYS(read),
- SCMP_SYS(readv),
- SCMP_SYS(preadv),
-
- /* Then the fd manipulation functions. */
- SCMP_SYS(fcntl),
- SCMP_SYS(fcntl64),
-
- /* After this point, just sort the list alphabetically. */
- SCMP_SYS(access),
- SCMP_SYS(brk),
- SCMP_SYS(capget),
- SCMP_SYS(chdir),
- SCMP_SYS(dup),
- SCMP_SYS(dup2),
- SCMP_SYS(dup3),
- SCMP_SYS(exit),
- SCMP_SYS(exit_group),
- SCMP_SYS(faccessat),
- SCMP_SYS(fchdir),
- SCMP_SYS(getpid),
- SCMP_SYS(gettid),
- SCMP_SYS(ioctl),
- SCMP_SYS(lseek),
- SCMP_SYS(_llseek),
- SCMP_SYS(mprotect),
-
- /* Syscalls listed because of compiler settings. */
- SCMP_SYS(futex),
-
- /* Syscalls listed because of sandbox. */
- SCMP_SYS(readlink),
- SCMP_SYS(readlinkat),
- SCMP_SYS(getcwd),
- #ifndef __SNR_faccessat2
- /* faccessat2 is not yet defiled in latest libseccomp-2.5.1 */
- # define __SNR_faccessat2 __NR_faccessat2
- #endif
- SCMP_SYS(faccessat2),
-
- /* Syscalls listed because of fakeroot. */
- SCMP_SYS(msgget),
- SCMP_SYS(msgrcv),
- SCMP_SYS(msgsnd),
- SCMP_SYS(semget),
- SCMP_SYS(semop),
- SCMP_SYS(semtimedop),
- /*
- * Some targets like ppc and i386 implement the above
- * syscall as subcalls via ipc() syscall.
- * https://bugs.gentoo.org/675378
- */
- SCMP_SYS(ipc),
- };
- int fork_syscalls[] = {
- SCMP_SYS(clone),
- SCMP_SYS(execve),
- SCMP_SYS(fork),
- SCMP_SYS(rt_sigaction),
- SCMP_SYS(rt_sigprocmask),
- SCMP_SYS(unshare),
- SCMP_SYS(vfork),
- SCMP_SYS(wait4),
- SCMP_SYS(waitid),
- SCMP_SYS(waitpid),
- };
- scmp_filter_ctx ctx = seccomp_init(USE_DEBUG ? SCMP_ACT_TRAP : SCMP_ACT_KILL);
- if (!ctx) {
- warnp("seccomp_init failed");
- return;
- }
-
- if (pax_seccomp_rules_add(ctx, base_syscalls) < 0)
- goto done;
-
- if (allow_forking)
- if (pax_seccomp_rules_add(ctx, fork_syscalls) < 0)
- goto done;
-
- /* We already called prctl. */
- seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0);
-
- if (USE_DEBUG)
- pax_seccomp_signal_init();
-
-#ifndef __SANITIZE_ADDRESS__
- /* ASAN does some weird stuff. */
- if (seccomp_load(ctx) < 0) {
- /* We have to assume that EINVAL == CONFIG_SECCOMP is disabled. */
- if (errno != EINVAL)
- warnp("seccomp_load failed");
- }
-#endif
-
- done:
- seccomp_release(ctx);
-}
-
-#else
-# define pax_seccomp_init(allow_forking)
+#ifndef SECCOMP_BPF_AVAILABLE
+# undef WANT_SECCOMP
#endif
static int ns_unshare(int flags)
@@ -308,7 +130,19 @@ void security_init(bool allow_forking)
_exit(0);
}
- pax_seccomp_init(allow_forking);
+#ifdef WANT_SECCOMP
+ {
+ int ret;
+
+ if (allow_forking)
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &seccomp_bpf_program_fork);
+ else
+ ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &seccomp_bpf_program_base);
+
+ if (ret)
+ warn("enabling seccomp failed");
+ }
+#endif
}
#endif