summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leeming <andrew.leeming@codethink.co.uk>2016-10-14 12:28:55 +0100
committerAndrew Leeming <andrew.leeming@codethink.co.uk>2016-10-21 12:18:01 +0100
commitff7d57ba33c22ab2b20822a225dd7b1f3c991e85 (patch)
tree1647bc6775e8f3dd3a871d30776b8b5972af3bc7
parentefad18c41aea63c25826c7f0e0faa7644c3a9211 (diff)
downloadsandboxlib-leeming/bwrap-rebase.tar.gz
Bubblewrap is the default for executor_for_platform()leeming/bwrap-rebase
Previously executor_for_platform() would select linux-user-chroot if availble. New behaviour is to look for bubblewrap first, then linux-user-chroot, else falling back to chroot. To support this, a generic 'get_program()' function was added to both bubblewrap.py and linux_user_chroot.py for interfacing.
-rw-r--r--README.rst3
-rw-r--r--sandboxlib/__init__.py28
-rw-r--r--sandboxlib/bubblewrap.py30
-rw-r--r--sandboxlib/linux_user_chroot.py3
4 files changed, 40 insertions, 24 deletions
diff --git a/README.rst b/README.rst
index bb241c3..f19c415 100644
--- a/README.rst
+++ b/README.rst
@@ -35,18 +35,17 @@ Current backends
- chroot: any POSIX OS, requires 'root' priviliges
- linux-user-chroot_: Linux-only, does not require 'root', requires
``linux-user-chroot`` to be installed and setuid root
+- bubblewrap: Does not require 'root', requires ``bwrap`` to be installed.
Possible future backends
========================
-- Bubblewrap_
- Firejail_
- runC_
- `Security Enhanced Linux`_ (SELinux): see https://danwalsh.livejournal.com/28545.html
- systemd-nspawn_
- Warden_
-.. _Bubblewrap: https://github.com/alexlarsson/bubblewrap
.. _Firejail: https://github.com/netblue30/firejail/
.. _runC: http://runc.io/
.. _Security Enhanced Linux: http://selinuxproject.org/page/Main_Page
diff --git a/sandboxlib/__init__.py b/sandboxlib/__init__.py
index cdb2fb3..47aff9d 100644
--- a/sandboxlib/__init__.py
+++ b/sandboxlib/__init__.py
@@ -23,12 +23,14 @@ docstrings that describe the different parameters.
import logging
+import logging.config
import os
import platform
import pipes
import subprocess
import warnings
+logging.config.fileConfig(os.path.join(os.path.dirname(__file__), 'logger.conf'))
class ProgramNotFound(Exception):
pass
@@ -170,13 +172,19 @@ def executor_for_platform():
"value %s." % backend_name)
if backend is None and platform.uname()[0] == 'Linux':
- log.info("Linux detected, looking for 'linux-user-chroot'.")
- try:
- program = sandboxlib.linux_user_chroot.linux_user_chroot_program()
- log.info("Found %s, choosing 'linux_user_chroot' module.", program)
- backend = sandboxlib.linux_user_chroot
- except sandboxlib.ProgramNotFound as e:
- log.debug("Did not find 'linux-user-chroot': %s", e)
+ # Not all backends may exist, so try them one by one in order of preference
+ prefered_backends = ['bubblewrap', 'linux-user-chroot']
+ for backend_name in prefered_backends:
+
+ log.info("Linux detected, looking for '{}'.".format(backend_name))
+ try:
+ executor = get_executor(backend_name)
+ program = executor.get_program()
+ log.info("Found {}, choosing '{}' module.".format(program,backend_name))
+ backend = executor
+ break
+ except sandboxlib.ProgramNotFound as e:
+ log.warn("Did not find '{}': {}".format(backend_name, e))
if backend is None:
log.info("Choosing 'chroot' sandbox module.")
@@ -187,7 +195,7 @@ def executor_for_platform():
def validate_extra_mounts(extra_mounts):
'''Validate and fill in default values for 'extra_mounts' setting.'''
- if extra_mounts == None:
+ if extra_mounts is None:
return []
new_extra_mounts = []
@@ -220,7 +228,6 @@ def validate_extra_mounts(extra_mounts):
return new_extra_mounts
-
def argv_to_string(argv):
return ' '.join(map(pipes.quote, argv))
@@ -246,7 +253,8 @@ def _run_command(argv, stdout, stderr, cwd=None, env=None):
dev_null = None
log = logging.getLogger('sandboxlib')
- log.debug('Running: {}'.format(argv))
+ log.debug('Running: {} ENV: {}'.format(argv,env))
+ log.debug(cwd)
try:
process = subprocess.Popen(
diff --git a/sandboxlib/bubblewrap.py b/sandboxlib/bubblewrap.py
index a0c005e..e03b7a0 100644
--- a/sandboxlib/bubblewrap.py
+++ b/sandboxlib/bubblewrap.py
@@ -124,14 +124,15 @@ def run_sandbox(command, cwd=None, env=None,
bwrap_command += process_mounts(filesystem_root, extra_mounts,
filesystem_writable_paths)
-
+ # Set UID and GUI
+ bwrap_command.extend(['--unshare-user', '--uid', '0', '--gid', '0'])
argv = bwrap_command + command
- log.info("bubblewrap.run_command({}, stdou:{}, stderr:{}, env:{})"
+ log.info("bubblewrap.run_command({}, stdout:{}, stderr:{}, env:{})"
.format(" ".join(argv), stdout, stderr, env))
-
+
exit, out, err = sandboxlib._run_command(argv, stdout, stderr, env=env)
-
+
return exit, out, err
@@ -149,6 +150,9 @@ def run_sandbox_with_redirection(command, **sandbox_config):
# out and err will be None
return exit
+def get_program():
+ return bubblewrap_program()
+
# Non API methods below
@@ -204,12 +208,12 @@ def process_mounts(fs_root, mounts, writable_paths):
log.debug("process_mounts(fs_root={}, mounts={}, writable_paths={})".format(fs_root, mounts, writable_paths))
extra_args = []
fs_dict = {}
-
+
for ex_mnt in mounts:
mnt_src, mnt_target, mnt_type, mnt_options = ex_mnt
# TODO
# How to handle options? Can bwrap do this?
-
+
if mnt_target not in fs_dict.keys():
fs_dict[mnt_target] = {'src': mnt_src, 'type': mnt_type, 'options': mnt_options}
# already exists. should only upgrade some things
@@ -255,14 +259,16 @@ def process_mounts(fs_root, mounts, writable_paths):
# First is using the --dev option that mounts host /dev
# Second is using --dev-bind for moutning a [src] to [dest]
# while allowing device access.
- #
- # How do we diferentiate the two?
- # extra_args.extend(['--dev', mnt_target])
- # Experiment to see if --dev-bind fixes permissions errors
- log.info("Using --dev-bind instead")
- extra_args.extend(['--dev-bind', mnt_src, mnt_target])
+ # How do we diferentiate the two?
+ # Check if we are mounting host root to target
+ if "/" in fs_dict.keys() and fs_dict['/']['src'] == "/":
+ log.info("Using --dev to share host dev")
+ extra_args.extend(['--dev', mnt_target])
+ else:
+ log.info("Using --dev-bind for local dev")
+ extra_args.extend(['--dev-bind', mnt_src, mnt_target])
else:
if is_mount_writable(mnt_target, writable_paths):
extra_args.extend(['--bind', mnt_src, mnt_target])
diff --git a/sandboxlib/linux_user_chroot.py b/sandboxlib/linux_user_chroot.py
index cab5344..f427b33 100644
--- a/sandboxlib/linux_user_chroot.py
+++ b/sandboxlib/linux_user_chroot.py
@@ -279,6 +279,9 @@ def create_mount_points_if_missing(filesystem_root, mount_info_list):
os.makedirs(path)
+def get_program():
+ return linux_user_chroot_program()
+
def linux_user_chroot_program():
# Raises sandboxlib.ProgramNotFound if not found.
return sandboxlib.utils.find_program('linux-user-chroot')