Commit 8cee4ab7 authored by Colin Walters's avatar Colin Walters

Add seccomp and rules imported from xdg-app/Sandstorm.io

seccomp is disabled by default for backwards compatibility.

This "v0" version is a basic blacklist that turns off some of the
known historical attack surface, initially imported from xdg-app.

I added a note about code sharing - we should share rules among
container implementations.
parent 99a02e41
......@@ -17,9 +17,13 @@
bin_PROGRAMS += linux-user-chroot
linux_user_chroot_SOURCES = src/linux-user-chroot.c
linux_user_chroot_SOURCES = \
src/setup-seccomp.c \
src/linux-user-chroot.c \
$(NULL)
linux_user_chroot_CFLAGS = $(AM_CFLAGS)
linux_user_chroot_CFLAGS = $(AM_CFLAGS) $(LIBSECCOMP_CFLAGS)
linux_user_chroot_LDFLAGS = $(LIBSECCOMP_LIBS)
if BUILD_NEWNET_HELPER
bin_PROGRAMS += linux-user-chroot-newnet
......
* seccomp support
......@@ -24,6 +24,10 @@ AC_SUBST(WARN_CFLAGS)
LT_PREREQ([2.2.4])
LT_INIT([disable-static])
PKG_CHECK_MODULES(LIBSECCOMP, [libseccomp])
AC_SUBST(LIBSECCOMP_CFLAGS)
AC_SUBST(LIBSECCOMP_LIBS)
AC_ARG_ENABLE(documentation,
AC_HELP_STRING([--enable-documentation],
[build documentation]),,
......
......@@ -22,6 +22,7 @@ linux\-user\-chroot \- safely allow normal users to chroot
.RB [ --unshare-ipc ]
.RB [ --unshare-pid ]
.RB [ --unshare-net ]
.RB [ --seccomp-profile-version ]
.RB [ --mount-proc " \fIDIR\fR]
.RB [ --mount-readonly " \fIDIR\fR"]
.RB [ --mount-bind " \fISOURCE DEST\fR"]
......@@ -87,6 +88,17 @@ Add a bind mount while the command is executing.
After setting the new root directory for the command,
change the current working directory to be
.IR DIR .
.TP
.BI \-\-seccomp-profile-version " DIR"
Seccomp is a tool to restrict the system calls applications
can make. As linux-user-chroot is designed for build systems,
we do not need to expose the entire system to build processes;
things like profiling should not happen during builds.
This argument is an integer, where -1 means "no seccomp",
and "0" enables the first profile version. This is an
opt-in system to any future versions.
.IR DIR .
.SH "EXIT STATUS"
The exit status is the exit status of the executed command,
or 1 if
......
......@@ -27,6 +27,7 @@
#include "config.h"
/* Core libc/linux-headers stuff */
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
......@@ -44,6 +45,8 @@
#include <sys/wait.h>
#include <sched.h>
#include "setup-seccomp.h"
#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
#endif
......@@ -168,6 +171,7 @@ main (int argc,
int unshare_ipc = 0;
int unshare_net = 0;
int unshare_pid = 0;
int seccomp_profile_version = -1;
int clone_flags = 0;
int child_status = 0;
pid_t child;
......@@ -271,6 +275,14 @@ main (int argc,
chdir_target = argv[after_mount_arg_index+1];
after_mount_arg_index += 2;
}
else if (strcmp (arg, "--seccomp-profile-version") == 0)
{
if ((argc - after_mount_arg_index) < 2)
fatal ("--seccomp-profile-version takes one argument");
seccomp_profile_version = atoi(argv[after_mount_arg_index+1]);
after_mount_arg_index += 2;
}
else
break;
}
......@@ -411,6 +423,14 @@ main (int argc,
if (chdir (chdir_target) < 0)
fatal_errno ("chdir");
/* Add the seccomp filters just before we exec */
if (seccomp_profile_version == 0)
setup_seccomp_v0 ();
else if (seccomp_profile_version == -1)
;
else
fatal ("Unknown --seccomp-profile-version");
if (execvp (program, program_argv) < 0)
fatal_errno ("execv");
}
......
/* Seccomp rules, originally from xdg-app, which looks clearly influenced
* by sandstorm-io/sandstorm/src/standstorm/supervisor.c++
*
* Copyright (C) 2014 Alexander Larsson
* Copyright (C) 2015 Colin Walters <walters@verbum.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
/* Core libc/linux-headers stuff */
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/fsuid.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sched.h>
/* Seccomp */
#include <seccomp.h>
#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
#include "setup-seccomp.h"
static void
die_with_error (const char *format, ...)
{
va_list args;
int errsv;
errsv = errno;
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
fprintf (stderr, ": %s\n", strerror (errsv));
exit (1);
}
static void
die (const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
fprintf (stderr, "\n");
exit (1);
}
static void
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.
*/
void
setup_seccomp_v0 (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[] = {
/* Block dmesg */
{SCMP_SYS(syslog)},
/* Useless old syscall */
{SCMP_SYS(uselib)},
/* Don't allow you to switch to bsd emulation or whatnot */
{SCMP_SYS(personality)},
/* Don't allow disabling accounting */
{SCMP_SYS(acct)},
/* 16-bit code is unnecessary in the sandbox, and modify_ldt is a
historic source of interesting information leaks. */
{SCMP_SYS(modify_ldt)},
/* Don't allow reading current quota use */
{SCMP_SYS(quotactl)},
/* Scary VM/NUMA ops */
{SCMP_SYS(move_pages)},
{SCMP_SYS(mbind)},
{SCMP_SYS(get_mempolicy)},
{SCMP_SYS(set_mempolicy)},
{SCMP_SYS(migrate_pages)},
/* Don't allow subnamespace setups: */
{SCMP_SYS(unshare)},
{SCMP_SYS(mount)},
{SCMP_SYS(pivot_root)},
{SCMP_SYS(clone), &SCMP_A0(SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
/* Utterly terrifying profiling operations */
{SCMP_SYS(perf_event_open)}
};
/* Blacklist all but unix, inet, inet6 and netlink */
int socket_family_blacklist[] = {
AF_AX25,
AF_IPX,
AF_APPLETALK,
AF_NETROM,
AF_BRIDGE,
AF_ATMPVC,
AF_X25,
AF_ROSE,
AF_DECnet,
AF_NETBEUI,
AF_SECURITY,
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);
}
/* 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 family = socket_family_blacklist[i];
if (i == N_ELEMENTS (socket_family_blacklist) - 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));
if (r < 0)
die_with_error ("Failed to block socket family %d", family);
}
}
r = seccomp_load (seccomp);
if (r < 0)
die_with_error ("Failed to install seccomp audit filter: ");
seccomp_release (seccomp);
}
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil -*-
*
* linux-user-chroot: A setuid program that allows non-root users to safely chroot(2)
*
* Copyright 2015 Colin Walters <walters@verbum.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
void setup_seccomp_v0 (void);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment