summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2016-01-20 12:27:10 -0500
committerColin Walters <walters@verbum.org>2016-01-20 12:27:10 -0500
commit3981d30f44f550d6680fa9aef4c74fbb83c3770f (patch)
tree22be9b8cae3ffc3283521bc7941aa0dbfcd40ec3
parent3d1efb1cb5ee18937cc4cda82fad735dde0a7f0d (diff)
downloadlinux-user-chroot-walters-seccomp-profile-v1.tar.gz
seccomp: Add version 1 that blocks `keyctl` due to CVE-2016-0728walters-seccomp-profile-v1
This entailed actually refactoring the code now so we can have versioned profiles. There's some code motion, but it's all relatively straightforward.
-rw-r--r--src/linux-user-chroot.c4
-rw-r--r--src/setup-seccomp.c197
-rw-r--r--src/setup-seccomp.h4
3 files changed, 126 insertions, 79 deletions
diff --git a/src/linux-user-chroot.c b/src/linux-user-chroot.c
index 4c9dbbb..29d9035 100644
--- a/src/linux-user-chroot.c
+++ b/src/linux-user-chroot.c
@@ -447,8 +447,8 @@ main (int argc,
fatal_errno ("chdir");
/* Add the seccomp filters just before we exec */
- if (seccomp_profile_version == 0)
- setup_seccomp_v0 ();
+ if (seccomp_profile_version >= 0 && seccomp_profile_version <= MAX_SECCOMP_PROFILE_VERSION)
+ setup_seccomp (seccomp_profile_version);
else if (seccomp_profile_version == -1)
;
else
diff --git a/src/setup-seccomp.c b/src/setup-seccomp.c
index fc00227..19d2396 100644
--- a/src/setup-seccomp.c
+++ b/src/setup-seccomp.c
@@ -85,48 +85,95 @@ die_oom (void)
die ("Out of memory");
}
-/*
- * We're calling this filter "v0" - any future additions or changes
- * should become new versions. This helps ensure backwards
- * compatibility for build systems.
+typedef struct {
+ int scall;
+ struct scmp_arg_cmp *arg;
+} SyscallBlackListEntry;
+
+
+/**** BEGIN NOTE ON CODE SHARING
+ *
+ * There are today a number of different Linux container
+ * implementations. That will likely continue for long into the
+ * future. But we can still try to share code, and it's important
+ * to do so because it affects what library and application writers
+ * can do, and we should support code portability between different
+ * container tools.
+ *
+ * This syscall blacklist is copied from xdg-app, which was in turn
+ * clearly influenced by the Sandstorm.io blacklist.
+ *
+ * If you make any changes here, I suggest sending the changes along
+ * to other sandbox maintainers. Using the libseccomp list is also
+ * an appropriate venue:
+ * https://groups.google.com/forum/#!topic/libseccomp
+ *
+ * A non-exhaustive list of links to container tooling that might
+ * want to share this blacklist:
+ *
+ * https://github.com/sandstorm-io/sandstorm
+ * in src/sandstorm/supervisor.c++
+ * http://cgit.freedesktop.org/xdg-app/xdg-app/
+ * in lib/xdg-app-helper.c
+ * https://git.gnome.org/browse/linux-user-chroot
+ * in src/setup-seccomp.c
+ *
+ **** END NOTE ON CODE SHARING
*/
-void
-setup_seccomp_v0 (void)
+
+static scmp_filter_ctx
+prepare_seccomp (void)
{
scmp_filter_ctx seccomp;
- /**** BEGIN NOTE ON CODE SHARING
- *
- * There are today a number of different Linux container
- * implementations. That will likely continue for long into the
- * future. But we can still try to share code, and it's important
- * to do so because it affects what library and application writers
- * can do, and we should support code portability between different
- * container tools.
- *
- * This syscall blacklist is copied from xdg-app, which was in turn
- * clearly influenced by the Sandstorm.io blacklist.
- *
- * If you make any changes here, I suggest sending the changes along
- * to other sandbox maintainers. Using the libseccomp list is also
- * an appropriate venue:
- * https://groups.google.com/forum/#!topic/libseccomp
- *
- * A non-exhaustive list of links to container tooling that might
- * want to share this blacklist:
- *
- * https://github.com/sandstorm-io/sandstorm
- * in src/sandstorm/supervisor.c++
- * http://cgit.freedesktop.org/xdg-app/xdg-app/
- * in lib/xdg-app-helper.c
- * https://git.gnome.org/browse/linux-user-chroot
- * in src/setup-seccomp.c
- *
- **** END NOTE ON CODE SHARING
- */
- struct {
- int scall;
- struct scmp_arg_cmp *arg;
- } syscall_blacklist[] = {
+ int r;
+
+ seccomp = seccomp_init (SCMP_ACT_ALLOW);
+ if (!seccomp)
+ die_oom ();
+
+ /* Add in all possible secondary archs we are aware of that
+ * this kernel might support. */
+#if defined(__i386__) || defined(__x86_64__)
+ r = seccomp_arch_add (seccomp, SCMP_ARCH_X86);
+ if (r < 0 && r != -EEXIST)
+ die_with_error ("Failed to add x86 architecture to seccomp filter");
+
+ r = seccomp_arch_add (seccomp, SCMP_ARCH_X86_64);
+ if (r < 0 && r != -EEXIST)
+ die_with_error ("Failed to add x86_64 architecture to seccomp filter");
+
+ r = seccomp_arch_add (seccomp, SCMP_ARCH_X32);
+ if (r < 0 && r != -EEXIST)
+ die_with_error ("Failed to add x32 architecture to seccomp filter");
+#endif
+
+ return seccomp;
+}
+
+static void
+add_syscall_blacklist (scmp_filter_ctx seccomp,
+ const SyscallBlackListEntry *syscall_blacklist,
+ unsigned int n_entries)
+{
+ int i, r;
+ for (i = 0; i < n_entries; i++)
+ {
+ int scall = syscall_blacklist[i].scall;
+ if (syscall_blacklist[i].arg)
+ r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 1, *syscall_blacklist[i].arg);
+ else
+ r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 0);
+ if (r < 0 && r == -EFAULT /* unknown syscall */)
+ die_with_error ("Failed to block syscall %d", scall);
+ }
+}
+
+static void
+add_seccomp_v0 (scmp_filter_ctx seccomp)
+{
+ struct utsname uts;
+
+ const SyscallBlackListEntry syscall_blacklist_v0[] = {
/* Block dmesg */
{SCMP_SYS(syslog)},
/* Useless old syscall */
@@ -160,8 +207,9 @@ setup_seccomp_v0 (void)
{SCMP_SYS(perf_event_open)},
{SCMP_SYS(ptrace)}
};
+
/* Blacklist all but unix, inet, inet6 and netlink */
- int socket_family_blacklist[] = {
+ static const int socket_family_blacklist_v0[] = {
AF_AX25,
AF_IPX,
AF_APPLETALK,
@@ -176,52 +224,21 @@ setup_seccomp_v0 (void)
AF_KEY,
AF_NETLINK + 1, /* Last gets CMP_GE, so order is important */
};
- int i, r;
- struct utsname uts;
-
- seccomp = seccomp_init(SCMP_ACT_ALLOW);
- if (!seccomp)
- return die_oom ();
-
- /* Add in all possible secondary archs we are aware of that
- * this kernel might support. */
-#if defined(__i386__) || defined(__x86_64__)
- r = seccomp_arch_add (seccomp, SCMP_ARCH_X86);
- if (r < 0 && r != -EEXIST)
- die_with_error ("Failed to add x86 architecture to seccomp filter");
-
- r = seccomp_arch_add (seccomp, SCMP_ARCH_X86_64);
- if (r < 0 && r != -EEXIST)
- die_with_error ("Failed to add x86_64 architecture to seccomp filter");
-
- r = seccomp_arch_add (seccomp, SCMP_ARCH_X32);
- if (r < 0 && r != -EEXIST)
- die_with_error ("Failed to add x32 architecture to seccomp filter");
-#endif
/* TODO: Should we filter the kernel keyring syscalls in some way?
* We do want them to be used by desktop apps, but they could also perhaps
* leak system stuff or secrets from other apps.
*/
-
- for (i = 0; i < N_ELEMENTS (syscall_blacklist); i++)
- {
- int scall = syscall_blacklist[i].scall;
- if (syscall_blacklist[i].arg)
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 1, *syscall_blacklist[i].arg);
- else
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EPERM), scall, 0);
- if (r < 0 && r == -EFAULT /* unknown syscall */)
- die_with_error ("Failed to block syscall %d", scall);
- }
+ add_syscall_blacklist (seccomp, syscall_blacklist_v0, N_ELEMENTS (syscall_blacklist_v0));
/* Socket filtering doesn't work on x86 */
if (uname (&uts) == 0 && strcmp (uts.machine, "i686") != 0)
{
- for (i = 0; i < N_ELEMENTS (socket_family_blacklist); i++)
+ int i, r;
+ for (i = 0; i < N_ELEMENTS (socket_family_blacklist_v0); i++)
{
- int family = socket_family_blacklist[i];
- if (i == N_ELEMENTS (socket_family_blacklist) - 1)
+ int family = socket_family_blacklist_v0[i];
+ if (i == N_ELEMENTS (socket_family_blacklist_v0) - 1)
r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_GE, family));
else
r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, family));
@@ -229,6 +246,34 @@ setup_seccomp_v0 (void)
die_with_error ("Failed to block socket family %d", family);
}
}
+}
+
+/*
+ * Any future additions or changes should become new versions. This
+ * helps ensure backwards compatibility for build systems.
+ */
+void
+setup_seccomp (unsigned int profile_version)
+{
+ int r;
+ scmp_filter_ctx seccomp;
+
+ assert (profile_version >= 0 && profile_version <= MAX_SECCOMP_PROFILE_VERSION);
+
+ seccomp = prepare_seccomp ();
+
+ add_seccomp_v0 (seccomp);
+
+ if (profile_version > 0)
+ {
+ static const SyscallBlackListEntry v1_blacklist[] = {
+
+ /* CVE-2016-0728 - https://lwn.net/Articles/672405/ */
+ { SCMP_SYS(keyctl) }
+
+ };
+ add_syscall_blacklist (seccomp, v1_blacklist, N_ELEMENTS (v1_blacklist));
+ }
r = seccomp_load (seccomp);
if (r < 0)
diff --git a/src/setup-seccomp.h b/src/setup-seccomp.h
index 1d96578..9be73c5 100644
--- a/src/setup-seccomp.h
+++ b/src/setup-seccomp.h
@@ -21,4 +21,6 @@
#pragma once
-void setup_seccomp_v0 (void);
+#define MAX_SECCOMP_PROFILE_VERSION 1
+
+void setup_seccomp (unsigned int profile_version);