diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-06-09 12:21:26 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-06-09 12:21:26 +0100 |
commit | ccc25d0bee354f3b905e809cca10bb88d5e58b29 (patch) | |
tree | be8e65a09a6f0083f876d5f7a03be3512ff267bb | |
parent | b502a569b4f5c1b16b97b9813df1983c9e776a65 (diff) | |
download | sandboxlib-ccc25d0bee354f3b905e809cca10bb88d5e58b29.tar.gz |
Replace maximum_possible_isolation() with degrade_config_for_capabilities()
The goal is to be useful for apps which want to be flexible about which
backend they use, taking into account that not all backends are capable
of the same thing.
My idea for degrade_config_for_capabilities() is that the app first
defines the sandboxing config they would like to use, and then passes it
through degrade_config_for_capabilities(). Any changes made are warned
about, because probably the user needs to know if certain security
features are being disabled.
This commit also adds a CAPABILITIES dict to each backend.
-rw-r--r-- | sandboxlib/__init__.py | 30 | ||||
-rw-r--r-- | sandboxlib/chroot.py | 44 | ||||
-rw-r--r-- | sandboxlib/linux_user_chroot.py | 19 |
3 files changed, 51 insertions, 42 deletions
diff --git a/sandboxlib/__init__.py b/sandboxlib/__init__.py index c568357..30cb71e 100644 --- a/sandboxlib/__init__.py +++ b/sandboxlib/__init__.py @@ -33,30 +33,18 @@ class ProgramNotFound(Exception): pass -def maximum_possible_isolation(): - '''Describe the 'tightest' isolation possible with a specific backend. +def degrade_config_for_capabilities(in_config, warn=True): + '''Alter settings in 'in_config' that a given backend doesn't support. - This function returns a dict, with the following keys: + This function is provided for users who want to be flexible about which + sandbox implementation they use, and who don't mind if not all of the + isolation that they requested is actually possible. - - mounts - - network + This is not a general purpose 'check your config' function. Any unexpected + keys or values in ``in_config`` will just be ignored. - Each key maps to a parameter of the run_sandbox() function, and each - value is a valid value for that parameter. - - Example result: - - { - 'mounts': 'undefined' - 'network': 'isolated' - } - - You can pass the result directly to a run_sandbox() function directly, - using the `**` operator to turn it into keyword arguments as in the - following example: - - isolation_settings = maximum_possible_isolation() - run_sandbox(root_path, ['echo', 'hello'], **isolation_settings) + If 'warn' is True, each change the function makes is logged using + warnings.warn(). ''' raise NotImplementedError() diff --git a/sandboxlib/chroot.py b/sandboxlib/chroot.py index 9f7b16a..e224ec0 100644 --- a/sandboxlib/chroot.py +++ b/sandboxlib/chroot.py @@ -24,10 +24,6 @@ syscall, which is likely to require 'root' priviliges. If any 'extra_mounts' are specified, there must be a working 'mount' binary in the host system. -Supported mounts settings: 'undefined'. - -Supported network settings: 'undefined'. - The code would be simpler if we just used the 'chroot' program, but it's not always practical to do that. First, it may not be installed. Second, we can't set the working directory of the program inside the chroot, unless we assume @@ -46,17 +42,41 @@ import warnings import sandboxlib -def maximum_possible_isolation(): - return { - 'mounts': 'undefined', - 'network': 'undefined', - } +CAPABILITIES = { + 'network': ['undefined'], + 'mounts': ['undefined'], + 'writable_paths': ['all'], +} -def process_mount_config(mounts, extra_mounts): - supported_values = ['undefined', 'isolated'] +def degrade_config_for_capabilities(in_config, warn=True): + # Currently this is all done manually... it may make sense to add something + # in utils.py that automatically checks the config against CAPABILITIES. + out_config = in_config.copy() + backend = 'chroot' + + def degrade_and_warn(name, allowed_value): + out_config[name] = allowed_value + if warn: + msg = ( + 'Unable to set %(name)s=%(value)s in a %(backend)s sandbox, ' + 'falling back to %(name)s=%(allowed_value)s'.format(locals())) + warnings.warn(msg) + + if out_config.get('mounts', 'undefined') != 'undefined': + degrade_and_warn('mounts', 'undefined') - assert mounts in supported_values, \ + if out_config.get('network', 'undefined') != 'undefined': + degrade_and_warn('network', 'undefined') + + if out_config.get('filesystem_writable_paths', 'all') != 'all': + degrade_and_warn('network', 'all') + + return out_config + + +def process_mount_config(mounts, extra_mounts): + assert mounts == 'undefined', \ "'%s' is an unsupported value for 'mounts' in the 'chroot' " \ "Mount sharing cannot be configured in this backend." % mounts diff --git a/sandboxlib/linux_user_chroot.py b/sandboxlib/linux_user_chroot.py index 3397a1a..755e70e 100644 --- a/sandboxlib/linux_user_chroot.py +++ b/sandboxlib/linux_user_chroot.py @@ -27,10 +27,6 @@ implementation here also uses 'unshare --mount', which can only be run as linux-user-chroot to handle creating the new mount namespace and processing any extra mounts would be a useful fix. -Supported mounts settings: 'undefined', 'isolated'. - -Supported network settings: 'undefined', 'isolated'. - Much of this code is adapted from Morph, from the Baserock project, from code written by Joe Burmeister, Richard Maw, Lars Wirzenius and others. @@ -45,11 +41,16 @@ import tempfile import sandboxlib -def maximum_possible_isolation(): - return { - 'mounts': 'isolated', - 'network': 'isolated', - } +CAPABILITIES = { + 'network': ['isolated', 'undefined'], + 'mounts': ['isolated', 'undefined'], + 'writable_paths': ['all', 'any'], +} + + +def degrade_config_for_capabilities(in_config, warn=True): + # This backend has the most features, right now! + return in_config def tmpfs_for_user(): |