diff options
| author | 2021-12-21 20:42:14 -0800 | |
|---|---|---|
| committer | 2021-12-21 20:42:14 -0800 | |
| commit | 777189097bb96a48789916023fd269bd3794ff4b (patch) | |
| tree | 3e7133357c5a3d4fce0aa75545a6f5c1ecdd5c51 | |
| parent | Remove dynamic cgroupv1 creation (diff) | |
Ignore swap limits if the swap controller is disabled
Fix NsJail failing to set the swap limit because it tries to write to
a file that doesn't exist.
Log a warning if swap is on, the swap controller is disabled, and the
NsJail config is attempting to limit swap memory.
| -rw-r--r-- | snekbox/nsjail.py | 6 | ||||
| -rw-r--r-- | snekbox/utils/__init__.py | 4 | ||||
| -rw-r--r-- | snekbox/utils/swap.py | 62 | 
3 files changed, 70 insertions, 2 deletions
diff --git a/snekbox/nsjail.py b/snekbox/nsjail.py index 79d33ba..ac36551 100644 --- a/snekbox/nsjail.py +++ b/snekbox/nsjail.py @@ -40,6 +40,7 @@ class NsJail:          self.nsjail_binary = nsjail_binary          self.config = self._read_config()          self.cgroup_version = utils.cgroup.init(self.config) +        self.ignore_swap_limits = utils.swap.should_ignore_limit(self.config, self.cgroup_version)          log.info(f"Assuming cgroup version {self.cgroup_version}.") @@ -148,6 +149,11 @@ class NsJail:          if self.cgroup_version == 2:              nsjail_args = ("--use_cgroupv2", *nsjail_args) +        if self.ignore_swap_limits: +            nsjail_args = ( +                "--cgroup_mem_memsw_max", "0", "--cgroup_mem_swap_max", "-1", *nsjail_args +            ) +          with NamedTemporaryFile() as nsj_log:              args = (                  self.nsjail_binary, diff --git a/snekbox/utils/__init__.py b/snekbox/utils/__init__.py index 22ece40..5a7b632 100644 --- a/snekbox/utils/__init__.py +++ b/snekbox/utils/__init__.py @@ -1,3 +1,3 @@ -from . import cgroup +from . import cgroup, swap -__all__ = ("cgroup",) +__all__ = ("cgroup", "swap") diff --git a/snekbox/utils/swap.py b/snekbox/utils/swap.py new file mode 100644 index 0000000..3e0d0aa --- /dev/null +++ b/snekbox/utils/swap.py @@ -0,0 +1,62 @@ +import logging +import uuid +from pathlib import Path + +from snekbox.config_pb2 import NsJailConfig + +log = logging.getLogger(__name__) + + +def controller_exists(config: NsJailConfig, cgroup_version: int) -> bool: +    """Return True if the swap memory cgroup controller is enabled.""" +    if cgroup_version == 1: +        return Path(config.cgroup_mem_mount, "memory.memsw.max_usage_in_bytes").exists() +    else: +        # Create a child cgroup because memory.swap isn't available in the root cgroup. +        child = Path(config.cgroupv2_mount, f"snekbox-temp-{uuid.uuid4()}") +        child.mkdir() +        swap_controller_exists = (child / "memory.swap.max").exists() +        child.rmdir() + +        return swap_controller_exists + + +def is_enabled() -> bool: +    """Return True if the total size of swap memory is greater than 0.""" +    with open("/proc/meminfo", "rb") as f: +        for line in f: +            name, value, *_ = line.split() +            if name == b"SwapTotal:": +                return value != b"0" + +    log.warning("Couldn't determine if swap is on or off. Assuming it's off.") +    return False + + +def should_ignore_limit(config: NsJailConfig, cgroup_version: int) -> bool: +    """ +    Return True if a swap limit should not be configured for NsJail. + +    If the swap controller doesn't exist, then NsJail would fail when trying to limit the swap. +    It would attempt to write to a file that doesn't exist. In such case, the swap limit arguments +    should be set to their default values, so NsJail will avoid setting a swap limit. + +    Log a warning if swap is enabled but the swap controller isn't enabled. +    """ +    if config.cgroup_mem_max <= 0: +        return False + +    if config.cgroup_mem_memsw_max <= 0 and config.cgroup_mem_swap_max < 0: +        log.warning("Memory is being limited, but swap memory is unlimited.") +        return False + +    controller_missing = not controller_exists(config, cgroup_version) +    if is_enabled() and controller_missing: +        log.warning( +            "Swap memory is available, but the swap memory controller is not enabled. This is " +            "probably due to the CONFIG_MEMCG_SWAP or CONFIG_MEMCG_SWAP_ENABLED kernel " +            "parameters not being set. NsJail will not be able to limit memory effectively. " +            "Please turn off swap memory on the system, or enable the swap memory controller." +        ) + +    return controller_missing  |