diff options
-rwxr-xr-x | run-sandbox | 7 | ||||
-rw-r--r-- | sandboxlib/chroot.py | 22 | ||||
-rw-r--r-- | sandboxlib/linux_user_chroot.py | 35 |
3 files changed, 61 insertions, 3 deletions
diff --git a/run-sandbox b/run-sandbox index 2bea1d4..356d9f6 100755 --- a/run-sandbox +++ b/run-sandbox @@ -91,7 +91,12 @@ def run(): extra_env['AC_APP_NAME'] = manifest['name'] - executor.run_sandbox(rootfs_path, command, cwd=cwd, extra_env=extra_env) + sharing_config = executor.maximum_possible_isolation() + + executor.run_sandbox( + rootfs_path, command, cwd=cwd, extra_env=extra_env, + **sharing_config) + else: # We should at minimum handle filesystem trees as well. raise RuntimeError( diff --git a/sandboxlib/chroot.py b/sandboxlib/chroot.py index 8495df1..7c79f5c 100644 --- a/sandboxlib/chroot.py +++ b/sandboxlib/chroot.py @@ -31,12 +31,32 @@ import sys import sandboxlib -def run_sandbox(rootfs_path, command, cwd=None, extra_env=None): +def maximum_possible_isolation(): + return { + 'network': 'undefined' + } + + +def process_network_config(network): + # It'd be possible to implement network isolation on Linux using the + # clone() syscall. However, I prefer to have the 'chroot' backend behave + # the same on all platforms, and have separate Linux-specific backends to + # do Linux-specific stuff. + + assert network == 'undefined', \ + "'%s' is an unsupported value for 'network' in the 'chroot' backend. " \ + "Network sharing cannot be be configured in this backend." % network + + +def run_sandbox(rootfs_path, command, cwd=None, extra_env=None, + network='undefined'): if type(command) == str: command = [command] env = sandboxlib.environment_vars(extra_env) + process_network_config(network) + pid = os.fork() if pid == 0: # Child process. It's a bit messy that we create a child process and diff --git a/sandboxlib/linux_user_chroot.py b/sandboxlib/linux_user_chroot.py index 7af7608..cbd15d3 100644 --- a/sandboxlib/linux_user_chroot.py +++ b/sandboxlib/linux_user_chroot.py @@ -21,7 +21,38 @@ import subprocess import sandboxlib -def run_sandbox(rootfs_path, command, cwd=None, extra_env=None): +def maximum_possible_isolation(): + return { + 'network': 'isolated', + } + + +def process_network_config(network): + # Network isolation is pretty easy, we 'unshare' the network namespace, and + # nothing can access the network. + + # Network 'sharing' is a lot harder to tie down: does it just mean 'not + # blocked'? Or does it mean 'working, with /etc/resolv.conf correctly set + # up'? So that's not handled yet. + + supported_values = ['undefined', 'isolated'] + + assert network in supported_values, \ + "'%s' is an unsupported value for 'network' in the " \ + "'linux-user-chroot' backend. Supported values: %s" \ + % (network, ', '.join(supported_values)) + + if network == 'isolated': + # This is all we need to do for network isolation + extra_linux_user_chroot_args = ['--unshare-net'] + else: + extra_linux_user_chroot_args = [] + + return extra_linux_user_chroot_args + + +def run_sandbox(rootfs_path, command, cwd=None, extra_env=None, + network='undefined'): if type(command) == str: command = [command] @@ -29,6 +60,8 @@ def run_sandbox(rootfs_path, command, cwd=None, extra_env=None): linux_user_chroot_args = [] + linux_user_chroot_args += process_network_config(network) + if cwd is not None: linux_user_chroot_args.extend(['--chdir', cwd]) |