diff options
| author | 2021-12-26 18:40:11 +0000 | |
|---|---|---|
| committer | 2021-12-26 18:40:11 +0000 | |
| commit | e5c07edcb90018ac14787048e87f13c1384faf9f (patch) | |
| tree | c2a2f478e2a27093c18fef5db49a645e87d9ee41 | |
| parent | Excluded the snekbox/config_pb2.py from coverage (#130) (diff) | |
| parent | CI: disable setup-python action on self-hosted runner (diff) | |
Merge pull request #127 from python-discord/feat/nsjail/102/cgroupv2
| -rw-r--r-- | .github/workflows/lint-test-build-push.yaml | 26 | ||||
| -rw-r--r-- | Dockerfile | 12 | ||||
| -rw-r--r-- | Pipfile | 3 | ||||
| -rw-r--r-- | config/snekbox.cfg | 1 | ||||
| -rw-r--r-- | snekbox/config_pb2.py | 1017 | ||||
| -rw-r--r-- | snekbox/nsjail.py | 83 | ||||
| -rw-r--r-- | snekbox/utils/__init__.py | 3 | ||||
| -rw-r--r-- | snekbox/utils/cgroup.py | 102 | ||||
| -rw-r--r-- | snekbox/utils/swap.py | 62 | ||||
| -rw-r--r-- | tests/api/__init__.py | 3 | ||||
| -rw-r--r-- | tests/gunicorn_utils.py | 80 | ||||
| -rw-r--r-- | tests/test_integration.py | 43 | ||||
| -rw-r--r-- | tests/test_nsjail.py | 3 | 
13 files changed, 378 insertions, 1060 deletions
diff --git a/.github/workflows/lint-test-build-push.yaml b/.github/workflows/lint-test-build-push.yaml index 87fc5d5..020b2a5 100644 --- a/.github/workflows/lint-test-build-push.yaml +++ b/.github/workflows/lint-test-build-push.yaml @@ -9,7 +9,16 @@ on:  jobs:    lint-test-build-push: -    runs-on: ubuntu-latest +    runs-on: ${{ matrix.os }} +    strategy: +      matrix: +        os: [ubuntu-20.04, self-hosted] +        include: +          - os: ubuntu-20.04 +            full: true +          - os: self-hosted +            full: false # Only run tests. +      env:        # Determine whether or not we should build the        # final production image and push it to GHCR. @@ -88,6 +97,7 @@ jobs:        # Required by pre-commit.        - name: Install git +        if: matrix.full          run: >-            docker exec snekbox_dev /bin/bash -c            'apt-get -y update && apt-get install -y git=1:2.20.*' @@ -96,12 +106,13 @@ jobs:        # Skip the flake8 hook because the following step will run it.        - name: Run pre-commit hooks          id: run-pre-commit-hooks +        if: matrix.full          run: >-            docker exec snekbox_dev /bin/bash -c            'PIP_USER=0 SKIP=flake8 pre-commit run --all-files'        - name: Show pre-commit logs -        if: always() && steps.run-pre-commit-hooks.outcome != 'success' +        if: matrix.full && always() && steps.run-pre-commit-hooks.outcome != 'success'          run: >-            docker exec snekbox_dev /bin/bash -c            'cat /root/.cache/pre-commit/pre-commit.log' @@ -112,6 +123,7 @@ jobs:        # up on this output to generate nice annotations to indicate what went        # wrong where.        - name: Run linter +        if: matrix.full          run: >-            docker exec snekbox_dev /bin/bash -c            'flake8 --format @@ -136,7 +148,7 @@ jobs:        # Note: This step runs even if the test step failed to make        # sure we process the coverage reports.        - name: Setup python -        if: always() && steps.run_tests.outputs.started == 'true' +        if: matrix.os != 'self-hosted' && always() && steps.run_tests.outputs.started == 'true'          id: python          uses: actions/setup-python@v2          with: @@ -166,7 +178,7 @@ jobs:        # both with the short commit SHA and 'latest'. This step should use        # the local build cache of the current run.        - name: Build final image -        if: env.production_build == 'true' +        if: matrix.full && env.production_build == 'true'          uses: docker/build-push-action@v2          with:            context: . @@ -185,7 +197,7 @@ jobs:        # Deploy to Kubernetes        - name: Authenticate with Kubernetes -        if: env.production_build == 'true' +        if: matrix.full && env.production_build == 'true'          uses: azure/k8s-set-context@v1          with:            method: kubeconfig @@ -202,7 +214,7 @@ jobs:        # Push the base image to GHCR, with an inline cache manifest        - name: Push base image -        if: env.production_build == 'true' +        if: matrix.full && env.production_build == 'true'          uses: docker/build-push-action@v2          with:            context: . @@ -216,7 +228,7 @@ jobs:        # Push the venv image to GHCR, with an inline cache manifest        - name: Push venv image -        if: env.production_build == 'true' +        if: matrix.full && env.production_build == 'true'          uses: docker/build-push-action@v2          with:            context: . @@ -1,4 +1,7 @@  FROM python:3.10-slim-buster as builder + +WORKDIR /nsjail +  RUN apt-get -y update \      && apt-get install -y \          bison=2:3.3.* \ @@ -11,12 +14,8 @@ RUN apt-get -y update \          make=4.2.* \          pkg-config=0.29-6 \          protobuf-compiler=3.6.* -RUN git clone \ -    -b '2.9' \ -    --single-branch \ -    --depth 1 \ -    https://github.com/google/nsjail.git /nsjail -WORKDIR /nsjail +RUN git clone -b master --single-branch https://github.com/google/nsjail.git . \ +    && git checkout dccf911fd2659e7b08ce9507c25b2b38ec2c5800  RUN make  # ------------------------------------------------------------------------------ @@ -25,6 +24,7 @@ FROM python:3.10-slim-buster as base  # Everything will be a user install to allow snekbox's dependencies to be kept  # separate from the packages exposed during eval.  ENV PATH=/root/.local/bin:$PATH \ +    PIP_DISABLE_PIP_VERSION_CHECK=1 \      PIP_NO_CACHE_DIR=false \      PIP_USER=1 \      PIPENV_DONT_USE_PYENV=1 \ @@ -40,9 +40,10 @@ precommit = "pre-commit install"  # Testing  report = "coverage report"  # Fix ownership of the coverage file even if tests fail & preserve exit code +# Install numpy because a test checks if it's importable  test = """      docker-compose run --entrypoint /bin/bash --rm snekbox -c \ -    'coverage run -m unittest; e=$?; chown --reference=. .coverage; exit $e' +    'env PYTHONUSERBASE=/snekbox/user_base pip install numpy && coverage run -m unittest; e=$?; chown --reference=. .coverage; exit $e'  """  # Docker diff --git a/config/snekbox.cfg b/config/snekbox.cfg index 3a4cc67..a1caf68 100644 --- a/config/snekbox.cfg +++ b/config/snekbox.cfg @@ -105,6 +105,7 @@ mount {  }  cgroup_mem_max: 52428800 +cgroup_mem_swap_max: 0  cgroup_mem_mount: "/sys/fs/cgroup/memory"  cgroup_pids_max: 5 diff --git a/snekbox/config_pb2.py b/snekbox/config_pb2.py index 35d6a8f..bd4e112 100644 --- a/snekbox/config_pb2.py +++ b/snekbox/config_pb2.py @@ -1,14 +1,13 @@ +# -*- coding: utf-8 -*-  # Generated by the protocol buffer compiler.  DO NOT EDIT!  # source: config.proto - -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +"""Generated protocol buffer code."""  from google.protobuf.internal import enum_type_wrapper  from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool  from google.protobuf import message as _message  from google.protobuf import reflection as _reflection  from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2  # @@protoc_insertion_point(imports)  _sym_db = _symbol_database.Default() @@ -16,109 +15,13 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor.FileDescriptor( -  name='config.proto', -  package='nsjail', -  serialized_pb=_b('\n\x0c\x63onfig.proto\x12\x06nsjail\"a\n\x05IdMap\x12\x13\n\tinside_id\x18\x01 \x01(\t:\x00\x12\x14\n\noutside_id\x18\x02 \x01(\t:\x00\x12\x10\n\x05\x63ount\x18\x03 \x01(\r:\x01\x31\x12\x1b\n\x0cuse_newidmap\x18\x04 \x01(\x08:\x05\x66\x61lse\"\xca\x02\n\x07MountPt\x12\r\n\x03src\x18\x01 \x01(\t:\x00\x12\x18\n\x0eprefix_src_env\x18\x02 \x01(\t:\x00\x12\x15\n\x0bsrc_content\x18\x03 \x01(\x0c:\x00\x12\r\n\x03\x64st\x18\x04 \x02(\t:\x00\x12\x18\n\x0eprefix_dst_env\x18\x05 \x01(\t:\x00\x12\x10\n\x06\x66stype\x18\x06 \x01(\t:\x00\x12\x11\n\x07options\x18\x07 \x01(\t:\x00\x12\x16\n\x07is_bind\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\x11\n\x02rw\x18\t \x01(\x08:\x05\x66\x61lse\x12\x0e\n\x06is_dir\x18\n \x01(\x08\x12\x17\n\tmandatory\x18\x0b \x01(\x08:\x04true\x12\x19\n\nis_symlink\x18\x0c \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06nosuid\x18\r \x01(\x08:\x05\x66\x61lse\x12\x14\n\x05nodev\x18\x0e \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06noexec\x18\x0f \x01(\x08:\x05\x66\x61lse\"F\n\x03\x45xe\x12\x0c\n\x04path\x18\x01 \x02(\t\x12\x0b\n\x03\x61rg\x18\x02 \x03(\t\x12\x0c\n\x04\x61rg0\x18\x03 \x01(\t\x12\x16\n\x07\x65xec_fd\x18\x04 \x01(\x08:\x05\x66\x61lse\"\x81\x14\n\x0cNsJailConfig\x12\x0e\n\x04name\x18\x01 \x01(\t:\x00\x12\x13\n\x0b\x64\x65scription\x18\x02 \x03(\t\x12 \n\x04mode\x18\x03 \x01(\x0e\x32\x0c.nsjail.Mode:\x04ONCE\x12\x16\n\nchroot_dir\x18\x04 \x01(\tB\x02\x18\x01\x12\x1d\n\nis_root_rw\x18\x05 \x01(\x08:\x05\x66\x61lseB\x02\x18\x01\x12\x18\n\x08hostname\x18\x08 \x01(\t:\x06NSJAIL\x12\x0e\n\x03\x63wd\x18\t \x01(\t:\x01/\x12\x0f\n\x04port\x18\n \x01(\r:\x01\x30\x12\x14\n\x08\x62indhost\x18\x0b \x01(\t:\x02::\x12\x1b\n\x10max_conns_per_ip\x18\x0c \x01(\r:\x01\x30\x12\x17\n\ntime_limit\x18\r \x01(\r:\x03\x36\x30\x30\x12\x15\n\x06\x64\x61\x65mon\x18\x0e \x01(\x08:\x05\x66\x61lse\x12\x13\n\x08max_cpus\x18\x0f \x01(\r:\x01\x30\x12\x0e\n\x06log_fd\x18\x10 \x01(\x05\x12\x10\n\x08log_file\x18\x11 \x01(\t\x12#\n\tlog_level\x18\x12 \x01(\x0e\x32\x10.nsjail.LogLevel\x12\x17\n\x08keep_env\x18\x13 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05\x65nvar\x18\x14 \x03(\t\x12\x18\n\tkeep_caps\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x0b\n\x03\x63\x61p\x18\x16 \x03(\t\x12\x15\n\x06silent\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bskip_setsid\x18\x18 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0estderr_to_null\x18\x19 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07pass_fd\x18\x1a \x03(\x05\x12#\n\x14\x64isable_no_new_privs\x18\x1b \x01(\x08:\x05\x66\x61lse\x12\x17\n\trlimit_as\x18\x1c \x01(\x04:\x04\x34\x30\x39\x36\x12-\n\x0erlimit_as_type\x18\x1d \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x16\n\x0brlimit_core\x18\x1e \x01(\x04:\x01\x30\x12/\n\x10rlimit_core_type\x18\x1f \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x17\n\nrlimit_cpu\x18  \x01(\x04:\x03\x36\x30\x30\x12.\n\x0frlimit_cpu_type\x18! \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x17\n\x0crlimit_fsize\x18\" \x01(\x04:\x01\x31\x12\x30\n\x11rlimit_fsize_type\x18# \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x19\n\rrlimit_nofile\x18$ \x01(\x04:\x02\x33\x32\x12\x31\n\x12rlimit_nofile_type\x18% \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x1a\n\x0crlimit_nproc\x18& \x01(\x04:\x04\x31\x30\x32\x34\x12/\n\x11rlimit_nproc_type\x18\' \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x1d\n\x0crlimit_stack\x18( \x01(\x04:\x07\x31\x30\x34\x38\x35\x37\x36\x12/\n\x11rlimit_stack_type\x18) \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x19\n\ndisable_rl\x18T \x01(\x08:\x05\x66\x61lse\x12)\n\x1apersona_addr_compat_layout\x18* \x01(\x08:\x05\x66\x61lse\x12%\n\x16persona_mmap_page_zero\x18+ \x01(\x08:\x05\x66\x61lse\x12(\n\x19persona_read_implies_exec\x18, \x01(\x08:\x05\x66\x61lse\x12%\n\x16persona_addr_limit_3gb\x18- \x01(\x08:\x05\x66\x61lse\x12(\n\x19persona_addr_no_randomize\x18. \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0c\x63lone_newnet\x18/ \x01(\x08:\x04true\x12\x1b\n\rclone_newuser\x18\x30 \x01(\x08:\x04true\x12\x19\n\x0b\x63lone_newns\x18\x31 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newpid\x18\x32 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newipc\x18\x33 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newuts\x18\x34 \x01(\x08:\x04true\x12\x1d\n\x0f\x63lone_newcgroup\x18\x35 \x01(\x08:\x04true\x12\x1d\n\x06uidmap\x18\x36 \x03(\x0b\x32\r.nsjail.IdMap\x12\x1d\n\x06gidmap\x18\x37 \x03(\x0b\x32\r.nsjail.IdMap\x12\x19\n\nmount_proc\x18\x38 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x05mount\x18\x39 \x03(\x0b\x32\x0f.nsjail.MountPt\x12\x1b\n\x13seccomp_policy_file\x18: \x01(\t\x12\x16\n\x0eseccomp_string\x18; \x03(\t\x12\x1a\n\x0bseccomp_log\x18< \x01(\x08:\x05\x66\x61lse\x12\x19\n\x0e\x63group_mem_max\x18= \x01(\x04:\x01\x30\x12/\n\x10\x63group_mem_mount\x18> \x01(\t:\x15/sys/fs/cgroup/memory\x12!\n\x11\x63group_mem_parent\x18? \x01(\t:\x06NSJAIL\x12\x1a\n\x0f\x63group_pids_max\x18@ \x01(\x04:\x01\x30\x12.\n\x11\x63group_pids_mount\x18\x41 \x01(\t:\x13/sys/fs/cgroup/pids\x12\"\n\x12\x63group_pids_parent\x18\x42 \x01(\t:\x06NSJAIL\x12!\n\x16\x63group_net_cls_classid\x18\x43 \x01(\r:\x01\x30\x12\x34\n\x14\x63group_net_cls_mount\x18\x44 \x01(\t:\x16/sys/fs/cgroup/net_cls\x12%\n\x15\x63group_net_cls_parent\x18\x45 \x01(\t:\x06NSJAIL\x12 \n\x15\x63group_cpu_ms_per_sec\x18\x46 \x01(\r:\x01\x30\x12,\n\x10\x63group_cpu_mount\x18G \x01(\t:\x12/sys/fs/cgroup/cpu\x12!\n\x11\x63group_cpu_parent\x18H \x01(\t:\x06NSJAIL\x12\x1a\n\x0biface_no_lo\x18I \x01(\x08:\x05\x66\x61lse\x12\x11\n\tiface_own\x18J \x03(\t\x12\x15\n\rmacvlan_iface\x18K \x01(\t\x12\"\n\rmacvlan_vs_ip\x18L \x01(\t:\x0b\x31\x39\x32.168.0.2\x12$\n\rmacvlan_vs_nm\x18M \x01(\t:\r255.255.255.0\x12\"\n\rmacvlan_vs_gw\x18N \x01(\t:\x0b\x31\x39\x32.168.0.1\x12\x17\n\rmacvlan_vs_ma\x18O \x01(\t:\x00\x12\x16\n\nnice_level\x18P \x01(\x05:\x02\x31\x39\x12\x1d\n\x08\x65xec_bin\x18Q \x01(\x0b\x32\x0b.nsjail.Exe\x12&\n\x0e\x63groupv2_mount\x18R \x01(\t:\x0e/sys/fs/cgroup\x12\x1b\n\x0cuse_cgroupv2\x18S \x01(\x08:\x05\x66\x61lse*3\n\x04Mode\x12\n\n\x06LISTEN\x10\x00\x12\x08\n\x04ONCE\x10\x01\x12\t\n\x05RERUN\x10\x02\x12\n\n\x06\x45XECVE\x10\x03*B\n\x08LogLevel\x12\t\n\x05\x44\x45\x42UG\x10\x00\x12\x08\n\x04INFO\x10\x01\x12\x0b\n\x07WARNING\x10\x02\x12\t\n\x05\x45RROR\x10\x03\x12\t\n\x05\x46\x41TAL\x10\x04*0\n\x06RLimit\x12\t\n\x05VALUE\x10\x00\x12\x08\n\x04SOFT\x10\x01\x12\x08\n\x04HARD\x10\x02\x12\x07\n\x03INF\x10\x03') -) -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -_MODE = _descriptor.EnumDescriptor( -  name='Mode', -  full_name='nsjail.Mode', -  filename=None, -  file=DESCRIPTOR, -  values=[ -    _descriptor.EnumValueDescriptor( -      name='LISTEN', index=0, number=0, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='ONCE', index=1, number=1, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='RERUN', index=2, number=2, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='EXECVE', index=3, number=3, -      options=None, -      type=None), -  ], -  containing_type=None, -  options=None, -  serialized_start=3092, -  serialized_end=3143, -) -_sym_db.RegisterEnumDescriptor(_MODE) +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x63onfig.proto\x12\x06nsjail\"a\n\x05IdMap\x12\x13\n\tinside_id\x18\x01 \x01(\t:\x00\x12\x14\n\noutside_id\x18\x02 \x01(\t:\x00\x12\x10\n\x05\x63ount\x18\x03 \x01(\r:\x01\x31\x12\x1b\n\x0cuse_newidmap\x18\x04 \x01(\x08:\x05\x66\x61lse\"\xca\x02\n\x07MountPt\x12\r\n\x03src\x18\x01 \x01(\t:\x00\x12\x18\n\x0eprefix_src_env\x18\x02 \x01(\t:\x00\x12\x15\n\x0bsrc_content\x18\x03 \x01(\x0c:\x00\x12\r\n\x03\x64st\x18\x04 \x02(\t:\x00\x12\x18\n\x0eprefix_dst_env\x18\x05 \x01(\t:\x00\x12\x10\n\x06\x66stype\x18\x06 \x01(\t:\x00\x12\x11\n\x07options\x18\x07 \x01(\t:\x00\x12\x16\n\x07is_bind\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\x11\n\x02rw\x18\t \x01(\x08:\x05\x66\x61lse\x12\x0e\n\x06is_dir\x18\n \x01(\x08\x12\x17\n\tmandatory\x18\x0b \x01(\x08:\x04true\x12\x19\n\nis_symlink\x18\x0c \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06nosuid\x18\r \x01(\x08:\x05\x66\x61lse\x12\x14\n\x05nodev\x18\x0e \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06noexec\x18\x0f \x01(\x08:\x05\x66\x61lse\"F\n\x03\x45xe\x12\x0c\n\x04path\x18\x01 \x02(\t\x12\x0b\n\x03\x61rg\x18\x02 \x03(\t\x12\x0c\n\x04\x61rg0\x18\x03 \x01(\t\x12\x16\n\x07\x65xec_fd\x18\x04 \x01(\x08:\x05\x66\x61lse\"\xe5\x16\n\x0cNsJailConfig\x12\x0e\n\x04name\x18\x01 \x01(\t:\x00\x12\x13\n\x0b\x64\x65scription\x18\x02 \x03(\t\x12 \n\x04mode\x18\x03 \x01(\x0e\x32\x0c.nsjail.Mode:\x04ONCE\x12\x18\n\x08hostname\x18\x04 \x01(\t:\x06NSJAIL\x12\x0e\n\x03\x63wd\x18\x05 \x01(\t:\x01/\x12\x1b\n\x0cno_pivotroot\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x04port\x18\x07 \x01(\r:\x01\x30\x12\x14\n\x08\x62indhost\x18\x08 \x01(\t:\x02::\x12\x14\n\tmax_conns\x18\t \x01(\r:\x01\x30\x12\x1b\n\x10max_conns_per_ip\x18\n \x01(\r:\x01\x30\x12\x17\n\ntime_limit\x18\x0b \x01(\r:\x03\x36\x30\x30\x12\x15\n\x06\x64\x61\x65mon\x18\x0c \x01(\x08:\x05\x66\x61lse\x12\x13\n\x08max_cpus\x18\r \x01(\r:\x01\x30\x12\x0e\n\x06log_fd\x18\x0e \x01(\x05\x12\x10\n\x08log_file\x18\x0f \x01(\t\x12#\n\tlog_level\x18\x10 \x01(\x0e\x32\x10.nsjail.LogLevel\x12\x17\n\x08keep_env\x18\x11 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05\x65nvar\x18\x12 \x03(\t\x12\x18\n\tkeep_caps\x18\x13 \x01(\x08:\x05\x66\x61lse\x12\x0b\n\x03\x63\x61p\x18\x14 \x03(\t\x12\x15\n\x06silent\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bskip_setsid\x18\x16 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0estderr_to_null\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07pass_fd\x18\x18 \x03(\x05\x12#\n\x14\x64isable_no_new_privs\x18\x19 \x01(\x08:\x05\x66\x61lse\x12\x17\n\trlimit_as\x18\x1a \x01(\x04:\x04\x34\x30\x39\x36\x12-\n\x0erlimit_as_type\x18\x1b \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x16\n\x0brlimit_core\x18\x1c \x01(\x04:\x01\x30\x12/\n\x10rlimit_core_type\x18\x1d \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x17\n\nrlimit_cpu\x18\x1e \x01(\x04:\x03\x36\x30\x30\x12.\n\x0frlimit_cpu_type\x18\x1f \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x17\n\x0crlimit_fsize\x18  \x01(\x04:\x01\x31\x12\x30\n\x11rlimit_fsize_type\x18! \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x19\n\rrlimit_nofile\x18\" \x01(\x04:\x02\x33\x32\x12\x31\n\x12rlimit_nofile_type\x18# \x01(\x0e\x32\x0e.nsjail.RLimit:\x05VALUE\x12\x1a\n\x0crlimit_nproc\x18$ \x01(\x04:\x04\x31\x30\x32\x34\x12/\n\x11rlimit_nproc_type\x18% \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x17\n\x0crlimit_stack\x18& \x01(\x04:\x01\x38\x12/\n\x11rlimit_stack_type\x18\' \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x1a\n\x0erlimit_memlock\x18( \x01(\x04:\x02\x36\x34\x12\x31\n\x13rlimit_memlock_type\x18) \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x18\n\rrlimit_rtprio\x18* \x01(\x04:\x01\x30\x12\x30\n\x12rlimit_rtprio_type\x18+ \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x1d\n\x0frlimit_msgqueue\x18, \x01(\x04:\x04\x31\x30\x32\x34\x12\x32\n\x14rlimit_msgqueue_type\x18- \x01(\x0e\x32\x0e.nsjail.RLimit:\x04SOFT\x12\x19\n\ndisable_rl\x18. \x01(\x08:\x05\x66\x61lse\x12)\n\x1apersona_addr_compat_layout\x18/ \x01(\x08:\x05\x66\x61lse\x12%\n\x16persona_mmap_page_zero\x18\x30 \x01(\x08:\x05\x66\x61lse\x12(\n\x19persona_read_implies_exec\x18\x31 \x01(\x08:\x05\x66\x61lse\x12%\n\x16persona_addr_limit_3gb\x18\x32 \x01(\x08:\x05\x66\x61lse\x12(\n\x19persona_addr_no_randomize\x18\x33 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0c\x63lone_newnet\x18\x34 \x01(\x08:\x04true\x12\x1b\n\rclone_newuser\x18\x35 \x01(\x08:\x04true\x12\x19\n\x0b\x63lone_newns\x18\x36 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newpid\x18\x37 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newipc\x18\x38 \x01(\x08:\x04true\x12\x1a\n\x0c\x63lone_newuts\x18\x39 \x01(\x08:\x04true\x12\x1d\n\x0f\x63lone_newcgroup\x18: \x01(\x08:\x04true\x12\x1c\n\rclone_newtime\x18; \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x06uidmap\x18< \x03(\x0b\x32\r.nsjail.IdMap\x12\x1d\n\x06gidmap\x18= \x03(\x0b\x32\r.nsjail.IdMap\x12\x19\n\nmount_proc\x18> \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x05mount\x18? \x03(\x0b\x32\x0f.nsjail.MountPt\x12\x1b\n\x13seccomp_policy_file\x18@ \x01(\t\x12\x16\n\x0eseccomp_string\x18\x41 \x03(\t\x12\x1a\n\x0bseccomp_log\x18\x42 \x01(\x08:\x05\x66\x61lse\x12\x19\n\x0e\x63group_mem_max\x18\x43 \x01(\x04:\x01\x30\x12\x1f\n\x14\x63group_mem_memsw_max\x18[ \x01(\x04:\x01\x30\x12\x1f\n\x13\x63group_mem_swap_max\x18\\ \x01(\x03:\x02-1\x12/\n\x10\x63group_mem_mount\x18\x44 \x01(\t:\x15/sys/fs/cgroup/memory\x12!\n\x11\x63group_mem_parent\x18\x45 \x01(\t:\x06NSJAIL\x12\x1a\n\x0f\x63group_pids_max\x18\x46 \x01(\x04:\x01\x30\x12.\n\x11\x63group_pids_mount\x18G \x01(\t:\x13/sys/fs/cgroup/pids\x12\"\n\x12\x63group_pids_parent\x18H \x01(\t:\x06NSJAIL\x12!\n\x16\x63group_net_cls_classid\x18I \x01(\r:\x01\x30\x12\x34\n\x14\x63group_net_cls_mount\x18J \x01(\t:\x16/sys/fs/cgroup/net_cls\x12%\n\x15\x63group_net_cls_parent\x18K \x01(\t:\x06NSJAIL\x12 \n\x15\x63group_cpu_ms_per_sec\x18L \x01(\r:\x01\x30\x12,\n\x10\x63group_cpu_mount\x18M \x01(\t:\x12/sys/fs/cgroup/cpu\x12!\n\x11\x63group_cpu_parent\x18N \x01(\t:\x06NSJAIL\x12&\n\x0e\x63groupv2_mount\x18O \x01(\t:\x0e/sys/fs/cgroup\x12\x1b\n\x0cuse_cgroupv2\x18P \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0biface_no_lo\x18Q \x01(\x08:\x05\x66\x61lse\x12\x11\n\tiface_own\x18R \x03(\t\x12\x15\n\rmacvlan_iface\x18S \x01(\t\x12\"\n\rmacvlan_vs_ip\x18T \x01(\t:\x0b\x31\x39\x32.168.0.2\x12$\n\rmacvlan_vs_nm\x18U \x01(\t:\r255.255.255.0\x12\"\n\rmacvlan_vs_gw\x18V \x01(\t:\x0b\x31\x39\x32.168.0.1\x12\x17\n\rmacvlan_vs_ma\x18W \x01(\t:\x00\x12\x1e\n\rmacvlan_vs_mo\x18X \x01(\t:\x07private\x12\x16\n\nnice_level\x18Y \x01(\x05:\x02\x31\x39\x12\x1d\n\x08\x65xec_bin\x18Z \x01(\x0b\x32\x0b.nsjail.Exe*3\n\x04Mode\x12\n\n\x06LISTEN\x10\x00\x12\x08\n\x04ONCE\x10\x01\x12\t\n\x05RERUN\x10\x02\x12\n\n\x06\x45XECVE\x10\x03*B\n\x08LogLevel\x12\t\n\x05\x44\x45\x42UG\x10\x00\x12\x08\n\x04INFO\x10\x01\x12\x0b\n\x07WARNING\x10\x02\x12\t\n\x05\x45RROR\x10\x03\x12\t\n\x05\x46\x41TAL\x10\x04*0\n\x06RLimit\x12\t\n\x05VALUE\x10\x00\x12\x08\n\x04SOFT\x10\x01\x12\x08\n\x04HARD\x10\x02\x12\x07\n\x03INF\x10\x03') +_MODE = DESCRIPTOR.enum_types_by_name['Mode']  Mode = enum_type_wrapper.EnumTypeWrapper(_MODE) -_LOGLEVEL = _descriptor.EnumDescriptor( -  name='LogLevel', -  full_name='nsjail.LogLevel', -  filename=None, -  file=DESCRIPTOR, -  values=[ -    _descriptor.EnumValueDescriptor( -      name='DEBUG', index=0, number=0, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='INFO', index=1, number=1, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='WARNING', index=2, number=2, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='ERROR', index=3, number=3, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='FATAL', index=4, number=4, -      options=None, -      type=None), -  ], -  containing_type=None, -  options=None, -  serialized_start=3145, -  serialized_end=3211, -) -_sym_db.RegisterEnumDescriptor(_LOGLEVEL) - +_LOGLEVEL = DESCRIPTOR.enum_types_by_name['LogLevel']  LogLevel = enum_type_wrapper.EnumTypeWrapper(_LOGLEVEL) -_RLIMIT = _descriptor.EnumDescriptor( -  name='RLimit', -  full_name='nsjail.RLimit', -  filename=None, -  file=DESCRIPTOR, -  values=[ -    _descriptor.EnumValueDescriptor( -      name='VALUE', index=0, number=0, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='SOFT', index=1, number=1, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='HARD', index=2, number=2, -      options=None, -      type=None), -    _descriptor.EnumValueDescriptor( -      name='INF', index=3, number=3, -      options=None, -      type=None), -  ], -  containing_type=None, -  options=None, -  serialized_start=3213, -  serialized_end=3261, -) -_sym_db.RegisterEnumDescriptor(_RLIMIT) - +_RLIMIT = DESCRIPTOR.enum_types_by_name['RLimit']  RLimit = enum_type_wrapper.EnumTypeWrapper(_RLIMIT)  LISTEN = 0  ONCE = 1 @@ -135,885 +38,53 @@ HARD = 2  INF = 3 - -_IDMAP = _descriptor.Descriptor( -  name='IdMap', -  full_name='nsjail.IdMap', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    _descriptor.FieldDescriptor( -      name='inside_id', full_name='nsjail.IdMap.inside_id', index=0, -      number=1, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='outside_id', full_name='nsjail.IdMap.outside_id', index=1, -      number=2, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='count', full_name='nsjail.IdMap.count', index=2, -      number=3, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='use_newidmap', full_name='nsjail.IdMap.use_newidmap', index=3, -      number=4, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  oneofs=[ -  ], -  serialized_start=24, -  serialized_end=121, -) - - -_MOUNTPT = _descriptor.Descriptor( -  name='MountPt', -  full_name='nsjail.MountPt', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    _descriptor.FieldDescriptor( -      name='src', full_name='nsjail.MountPt.src', index=0, -      number=1, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='prefix_src_env', full_name='nsjail.MountPt.prefix_src_env', index=1, -      number=2, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='src_content', full_name='nsjail.MountPt.src_content', index=2, -      number=3, type=12, cpp_type=9, label=1, -      has_default_value=True, default_value=_b(""), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='dst', full_name='nsjail.MountPt.dst', index=3, -      number=4, type=9, cpp_type=9, label=2, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='prefix_dst_env', full_name='nsjail.MountPt.prefix_dst_env', index=4, -      number=5, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='fstype', full_name='nsjail.MountPt.fstype', index=5, -      number=6, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='options', full_name='nsjail.MountPt.options', index=6, -      number=7, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='is_bind', full_name='nsjail.MountPt.is_bind', index=7, -      number=8, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rw', full_name='nsjail.MountPt.rw', index=8, -      number=9, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='is_dir', full_name='nsjail.MountPt.is_dir', index=9, -      number=10, type=8, cpp_type=7, label=1, -      has_default_value=False, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='mandatory', full_name='nsjail.MountPt.mandatory', index=10, -      number=11, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='is_symlink', full_name='nsjail.MountPt.is_symlink', index=11, -      number=12, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='nosuid', full_name='nsjail.MountPt.nosuid', index=12, -      number=13, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='nodev', full_name='nsjail.MountPt.nodev', index=13, -      number=14, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='noexec', full_name='nsjail.MountPt.noexec', index=14, -      number=15, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  oneofs=[ -  ], -  serialized_start=124, -  serialized_end=454, -) - - -_EXE = _descriptor.Descriptor( -  name='Exe', -  full_name='nsjail.Exe', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    _descriptor.FieldDescriptor( -      name='path', full_name='nsjail.Exe.path', index=0, -      number=1, type=9, cpp_type=9, label=2, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='arg', full_name='nsjail.Exe.arg', index=1, -      number=2, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='arg0', full_name='nsjail.Exe.arg0', index=2, -      number=3, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='exec_fd', full_name='nsjail.Exe.exec_fd', index=3, -      number=4, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  oneofs=[ -  ], -  serialized_start=456, -  serialized_end=526, -) - - -_NSJAILCONFIG = _descriptor.Descriptor( -  name='NsJailConfig', -  full_name='nsjail.NsJailConfig', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    _descriptor.FieldDescriptor( -      name='name', full_name='nsjail.NsJailConfig.name', index=0, -      number=1, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='description', full_name='nsjail.NsJailConfig.description', index=1, -      number=2, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='mode', full_name='nsjail.NsJailConfig.mode', index=2, -      number=3, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='chroot_dir', full_name='nsjail.NsJailConfig.chroot_dir', index=3, -      number=4, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=_descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\030\001'))), -    _descriptor.FieldDescriptor( -      name='is_root_rw', full_name='nsjail.NsJailConfig.is_root_rw', index=4, -      number=5, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=_descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\030\001'))), -    _descriptor.FieldDescriptor( -      name='hostname', full_name='nsjail.NsJailConfig.hostname', index=5, -      number=8, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("NSJAIL").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cwd', full_name='nsjail.NsJailConfig.cwd', index=6, -      number=9, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='port', full_name='nsjail.NsJailConfig.port', index=7, -      number=10, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='bindhost', full_name='nsjail.NsJailConfig.bindhost', index=8, -      number=11, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("::").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='max_conns_per_ip', full_name='nsjail.NsJailConfig.max_conns_per_ip', index=9, -      number=12, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='time_limit', full_name='nsjail.NsJailConfig.time_limit', index=10, -      number=13, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=600, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='daemon', full_name='nsjail.NsJailConfig.daemon', index=11, -      number=14, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='max_cpus', full_name='nsjail.NsJailConfig.max_cpus', index=12, -      number=15, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='log_fd', full_name='nsjail.NsJailConfig.log_fd', index=13, -      number=16, type=5, cpp_type=1, label=1, -      has_default_value=False, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='log_file', full_name='nsjail.NsJailConfig.log_file', index=14, -      number=17, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='log_level', full_name='nsjail.NsJailConfig.log_level', index=15, -      number=18, type=14, cpp_type=8, label=1, -      has_default_value=False, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='keep_env', full_name='nsjail.NsJailConfig.keep_env', index=16, -      number=19, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='envar', full_name='nsjail.NsJailConfig.envar', index=17, -      number=20, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='keep_caps', full_name='nsjail.NsJailConfig.keep_caps', index=18, -      number=21, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cap', full_name='nsjail.NsJailConfig.cap', index=19, -      number=22, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='silent', full_name='nsjail.NsJailConfig.silent', index=20, -      number=23, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='skip_setsid', full_name='nsjail.NsJailConfig.skip_setsid', index=21, -      number=24, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='stderr_to_null', full_name='nsjail.NsJailConfig.stderr_to_null', index=22, -      number=25, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='pass_fd', full_name='nsjail.NsJailConfig.pass_fd', index=23, -      number=26, type=5, cpp_type=1, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='disable_no_new_privs', full_name='nsjail.NsJailConfig.disable_no_new_privs', index=24, -      number=27, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_as', full_name='nsjail.NsJailConfig.rlimit_as', index=25, -      number=28, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=4096, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_as_type', full_name='nsjail.NsJailConfig.rlimit_as_type', index=26, -      number=29, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_core', full_name='nsjail.NsJailConfig.rlimit_core', index=27, -      number=30, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_core_type', full_name='nsjail.NsJailConfig.rlimit_core_type', index=28, -      number=31, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_cpu', full_name='nsjail.NsJailConfig.rlimit_cpu', index=29, -      number=32, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=600, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_cpu_type', full_name='nsjail.NsJailConfig.rlimit_cpu_type', index=30, -      number=33, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_fsize', full_name='nsjail.NsJailConfig.rlimit_fsize', index=31, -      number=34, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_fsize_type', full_name='nsjail.NsJailConfig.rlimit_fsize_type', index=32, -      number=35, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_nofile', full_name='nsjail.NsJailConfig.rlimit_nofile', index=33, -      number=36, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=32, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_nofile_type', full_name='nsjail.NsJailConfig.rlimit_nofile_type', index=34, -      number=37, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_nproc', full_name='nsjail.NsJailConfig.rlimit_nproc', index=35, -      number=38, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=1024, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_nproc_type', full_name='nsjail.NsJailConfig.rlimit_nproc_type', index=36, -      number=39, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_stack', full_name='nsjail.NsJailConfig.rlimit_stack', index=37, -      number=40, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=1048576, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='rlimit_stack_type', full_name='nsjail.NsJailConfig.rlimit_stack_type', index=38, -      number=41, type=14, cpp_type=8, label=1, -      has_default_value=True, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='disable_rl', full_name='nsjail.NsJailConfig.disable_rl', index=39, -      number=84, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='persona_addr_compat_layout', full_name='nsjail.NsJailConfig.persona_addr_compat_layout', index=40, -      number=42, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='persona_mmap_page_zero', full_name='nsjail.NsJailConfig.persona_mmap_page_zero', index=41, -      number=43, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='persona_read_implies_exec', full_name='nsjail.NsJailConfig.persona_read_implies_exec', index=42, -      number=44, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='persona_addr_limit_3gb', full_name='nsjail.NsJailConfig.persona_addr_limit_3gb', index=43, -      number=45, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='persona_addr_no_randomize', full_name='nsjail.NsJailConfig.persona_addr_no_randomize', index=44, -      number=46, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newnet', full_name='nsjail.NsJailConfig.clone_newnet', index=45, -      number=47, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newuser', full_name='nsjail.NsJailConfig.clone_newuser', index=46, -      number=48, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newns', full_name='nsjail.NsJailConfig.clone_newns', index=47, -      number=49, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newpid', full_name='nsjail.NsJailConfig.clone_newpid', index=48, -      number=50, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newipc', full_name='nsjail.NsJailConfig.clone_newipc', index=49, -      number=51, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newuts', full_name='nsjail.NsJailConfig.clone_newuts', index=50, -      number=52, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='clone_newcgroup', full_name='nsjail.NsJailConfig.clone_newcgroup', index=51, -      number=53, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=True, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='uidmap', full_name='nsjail.NsJailConfig.uidmap', index=52, -      number=54, type=11, cpp_type=10, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='gidmap', full_name='nsjail.NsJailConfig.gidmap', index=53, -      number=55, type=11, cpp_type=10, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='mount_proc', full_name='nsjail.NsJailConfig.mount_proc', index=54, -      number=56, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='mount', full_name='nsjail.NsJailConfig.mount', index=55, -      number=57, type=11, cpp_type=10, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='seccomp_policy_file', full_name='nsjail.NsJailConfig.seccomp_policy_file', index=56, -      number=58, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='seccomp_string', full_name='nsjail.NsJailConfig.seccomp_string', index=57, -      number=59, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='seccomp_log', full_name='nsjail.NsJailConfig.seccomp_log', index=58, -      number=60, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_mem_max', full_name='nsjail.NsJailConfig.cgroup_mem_max', index=59, -      number=61, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_mem_mount', full_name='nsjail.NsJailConfig.cgroup_mem_mount', index=60, -      number=62, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/sys/fs/cgroup/memory").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_mem_parent', full_name='nsjail.NsJailConfig.cgroup_mem_parent', index=61, -      number=63, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("NSJAIL").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_pids_max', full_name='nsjail.NsJailConfig.cgroup_pids_max', index=62, -      number=64, type=4, cpp_type=4, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_pids_mount', full_name='nsjail.NsJailConfig.cgroup_pids_mount', index=63, -      number=65, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/sys/fs/cgroup/pids").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_pids_parent', full_name='nsjail.NsJailConfig.cgroup_pids_parent', index=64, -      number=66, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("NSJAIL").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_net_cls_classid', full_name='nsjail.NsJailConfig.cgroup_net_cls_classid', index=65, -      number=67, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_net_cls_mount', full_name='nsjail.NsJailConfig.cgroup_net_cls_mount', index=66, -      number=68, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/sys/fs/cgroup/net_cls").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_net_cls_parent', full_name='nsjail.NsJailConfig.cgroup_net_cls_parent', index=67, -      number=69, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("NSJAIL").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_cpu_ms_per_sec', full_name='nsjail.NsJailConfig.cgroup_cpu_ms_per_sec', index=68, -      number=70, type=13, cpp_type=3, label=1, -      has_default_value=True, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_cpu_mount', full_name='nsjail.NsJailConfig.cgroup_cpu_mount', index=69, -      number=71, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/sys/fs/cgroup/cpu").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroup_cpu_parent', full_name='nsjail.NsJailConfig.cgroup_cpu_parent', index=70, -      number=72, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("NSJAIL").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='iface_no_lo', full_name='nsjail.NsJailConfig.iface_no_lo', index=71, -      number=73, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='iface_own', full_name='nsjail.NsJailConfig.iface_own', index=72, -      number=74, type=9, cpp_type=9, label=3, -      has_default_value=False, default_value=[], -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='macvlan_iface', full_name='nsjail.NsJailConfig.macvlan_iface', index=73, -      number=75, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='macvlan_vs_ip', full_name='nsjail.NsJailConfig.macvlan_vs_ip', index=74, -      number=76, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("192.168.0.2").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='macvlan_vs_nm', full_name='nsjail.NsJailConfig.macvlan_vs_nm', index=75, -      number=77, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("255.255.255.0").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='macvlan_vs_gw', full_name='nsjail.NsJailConfig.macvlan_vs_gw', index=76, -      number=78, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("192.168.0.1").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='macvlan_vs_ma', full_name='nsjail.NsJailConfig.macvlan_vs_ma', index=77, -      number=79, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='nice_level', full_name='nsjail.NsJailConfig.nice_level', index=78, -      number=80, type=5, cpp_type=1, label=1, -      has_default_value=True, default_value=19, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='exec_bin', full_name='nsjail.NsJailConfig.exec_bin', index=79, -      number=81, type=11, cpp_type=10, label=1, -      has_default_value=False, default_value=None, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='cgroupv2_mount', full_name='nsjail.NsJailConfig.cgroupv2_mount', index=80, -      number=82, type=9, cpp_type=9, label=1, -      has_default_value=True, default_value=_b("/sys/fs/cgroup").decode('utf-8'), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    _descriptor.FieldDescriptor( -      name='use_cgroupv2', full_name='nsjail.NsJailConfig.use_cgroupv2', index=81, -      number=83, type=8, cpp_type=7, label=1, -      has_default_value=True, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  oneofs=[ -  ], -  serialized_start=529, -  serialized_end=3090, -) - -_NSJAILCONFIG.fields_by_name['mode'].enum_type = _MODE -_NSJAILCONFIG.fields_by_name['log_level'].enum_type = _LOGLEVEL -_NSJAILCONFIG.fields_by_name['rlimit_as_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_core_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_cpu_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_fsize_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_nofile_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_nproc_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['rlimit_stack_type'].enum_type = _RLIMIT -_NSJAILCONFIG.fields_by_name['uidmap'].message_type = _IDMAP -_NSJAILCONFIG.fields_by_name['gidmap'].message_type = _IDMAP -_NSJAILCONFIG.fields_by_name['mount'].message_type = _MOUNTPT -_NSJAILCONFIG.fields_by_name['exec_bin'].message_type = _EXE -DESCRIPTOR.message_types_by_name['IdMap'] = _IDMAP -DESCRIPTOR.message_types_by_name['MountPt'] = _MOUNTPT -DESCRIPTOR.message_types_by_name['Exe'] = _EXE -DESCRIPTOR.message_types_by_name['NsJailConfig'] = _NSJAILCONFIG -DESCRIPTOR.enum_types_by_name['Mode'] = _MODE -DESCRIPTOR.enum_types_by_name['LogLevel'] = _LOGLEVEL -DESCRIPTOR.enum_types_by_name['RLimit'] = _RLIMIT - -IdMap = _reflection.GeneratedProtocolMessageType('IdMap', (_message.Message,), dict( -  DESCRIPTOR = _IDMAP, -  __module__ = 'config_pb2' +_IDMAP = DESCRIPTOR.message_types_by_name['IdMap'] +_MOUNTPT = DESCRIPTOR.message_types_by_name['MountPt'] +_EXE = DESCRIPTOR.message_types_by_name['Exe'] +_NSJAILCONFIG = DESCRIPTOR.message_types_by_name['NsJailConfig'] +IdMap = _reflection.GeneratedProtocolMessageType('IdMap', (_message.Message,), { +  'DESCRIPTOR' : _IDMAP, +  '__module__' : 'config_pb2'    # @@protoc_insertion_point(class_scope:nsjail.IdMap) -  )) +  })  _sym_db.RegisterMessage(IdMap) -MountPt = _reflection.GeneratedProtocolMessageType('MountPt', (_message.Message,), dict( -  DESCRIPTOR = _MOUNTPT, -  __module__ = 'config_pb2' +MountPt = _reflection.GeneratedProtocolMessageType('MountPt', (_message.Message,), { +  'DESCRIPTOR' : _MOUNTPT, +  '__module__' : 'config_pb2'    # @@protoc_insertion_point(class_scope:nsjail.MountPt) -  )) +  })  _sym_db.RegisterMessage(MountPt) -Exe = _reflection.GeneratedProtocolMessageType('Exe', (_message.Message,), dict( -  DESCRIPTOR = _EXE, -  __module__ = 'config_pb2' +Exe = _reflection.GeneratedProtocolMessageType('Exe', (_message.Message,), { +  'DESCRIPTOR' : _EXE, +  '__module__' : 'config_pb2'    # @@protoc_insertion_point(class_scope:nsjail.Exe) -  )) +  })  _sym_db.RegisterMessage(Exe) -NsJailConfig = _reflection.GeneratedProtocolMessageType('NsJailConfig', (_message.Message,), dict( -  DESCRIPTOR = _NSJAILCONFIG, -  __module__ = 'config_pb2' +NsJailConfig = _reflection.GeneratedProtocolMessageType('NsJailConfig', (_message.Message,), { +  'DESCRIPTOR' : _NSJAILCONFIG, +  '__module__' : 'config_pb2'    # @@protoc_insertion_point(class_scope:nsjail.NsJailConfig) -  )) +  })  _sym_db.RegisterMessage(NsJailConfig) - -_NSJAILCONFIG.fields_by_name['chroot_dir'].has_options = True -_NSJAILCONFIG.fields_by_name['chroot_dir']._options = _descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\030\001')) -_NSJAILCONFIG.fields_by_name['is_root_rw'].has_options = True -_NSJAILCONFIG.fields_by_name['is_root_rw']._options = _descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\030\001')) +if _descriptor._USE_C_DESCRIPTORS == False: + +  DESCRIPTOR._options = None +  _MODE._serialized_start=3448 +  _MODE._serialized_end=3499 +  _LOGLEVEL._serialized_start=3501 +  _LOGLEVEL._serialized_end=3567 +  _RLIMIT._serialized_start=3569 +  _RLIMIT._serialized_end=3617 +  _IDMAP._serialized_start=24 +  _IDMAP._serialized_end=121 +  _MOUNTPT._serialized_start=124 +  _MOUNTPT._serialized_end=454 +  _EXE._serialized_start=456 +  _EXE._serialized_end=526 +  _NSJAILCONFIG._serialized_start=529 +  _NSJAILCONFIG._serialized_end=3446  # @@protoc_insertion_point(module_scope) diff --git a/snekbox/nsjail.py b/snekbox/nsjail.py index a1092cf..ac36551 100644 --- a/snekbox/nsjail.py +++ b/snekbox/nsjail.py @@ -4,15 +4,13 @@ import re  import subprocess  import sys  import textwrap -import uuid -from pathlib import Path  from subprocess import CompletedProcess  from tempfile import NamedTemporaryFile  from typing import Iterable  from google.protobuf import text_format -from snekbox import DEBUG +from snekbox import DEBUG, utils  from snekbox.config_pb2 import NsJailConfig  log = logging.getLogger(__name__) @@ -26,9 +24,6 @@ LOG_BLACKLIST = ("Process will be ",)  NSJAIL_PATH = os.getenv("NSJAIL_PATH", "/usr/sbin/nsjail")  NSJAIL_CFG = os.getenv("NSJAIL_CFG", "./config/snekbox.cfg") -# If this file is present, cgroupv2 should be enabled -CGROUPV2_PROBE_PATH = Path("/sys/fs/cgroup/cgroup.controllers") -  # Limit of stdout bytes we consume before terminating nsjail  OUTPUT_MAX = 1_000_000  # 1 MB  READ_CHUNK_SIZE = 10_000  # chars @@ -44,19 +39,10 @@ class NsJail:      def __init__(self, nsjail_binary: str = NSJAIL_PATH):          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"Cgroups version: {self._probe_cgroup_version()}") - -    @staticmethod -    def _probe_cgroup_version() -> int: -        """Poll the filesystem and return the guessed cgroup version.""" -        # Right now we check whenever the controller path exists -        version = 2 if CGROUPV2_PROBE_PATH.exists() else 1 - -        if DEBUG: -            log.info(f"Guessed cgroups version: {version}") - -        return version +        log.info(f"Assuming cgroup version {self.cgroup_version}.")      @staticmethod      def _read_config() -> NsJailConfig: @@ -81,49 +67,6 @@ class NsJail:          return config -    def _create_dynamic_cgroups(self) -> str: -        """ -        Create a PID and memory cgroup for NsJail to use as the parent cgroup. - -        Returns the name of the cgroup, located in the cgroup root. - -        NsJail doesn't do this automatically because it requires privileges NsJail usually doesn't -        have. - -        Disables memory swapping. -        """ -        # Pick a name for the cgroup -        cgroup = "snekbox-" + str(uuid.uuid4()) - -        pids = Path(self.config.cgroup_pids_mount, cgroup) -        mem = Path(self.config.cgroup_mem_mount, cgroup) -        mem_max = str(self.config.cgroup_mem_max) - -        pids.mkdir(parents=True, exist_ok=True) -        mem.mkdir(parents=True, exist_ok=True) - -        # Swap limit cannot be set to a value lower than memory.limit_in_bytes. -        # Therefore, this must be set before the swap limit. -        # -        # Since child cgroups are dynamically created, the swap limit has to be set on the parent -        # instead so that children inherit it. Given the swap's dependency on the memory limit, -        # the memory limit must also be set on the parent. NsJail only sets the memory limit for -        # child cgroups, not the parent. -        (mem / "memory.limit_in_bytes").write_text(mem_max, encoding="utf-8") - -        try: -            # Swap limit is specified as the sum of the memory and swap limits. -            # Therefore, setting it equal to the memory limit effectively disables swapping. -            (mem / "memory.memsw.limit_in_bytes").write_text(mem_max, encoding="utf-8") -        except PermissionError: -            log.warning( -                "Failed to set the memory swap limit for the cgroup. " -                "This is probably because CONFIG_MEMCG_SWAP or CONFIG_MEMCG_SWAP_ENABLED is unset. " -                "Please ensure swap memory is disabled on the system." -            ) - -        return cgroup -      @staticmethod      def _parse_log(log_lines: Iterable[str]) -> None:          """Parse and log NsJail's log messages.""" @@ -203,19 +146,19 @@ class NsJail:          `py_args` are arguments to pass to the Python subprocess before the code,          which is the last argument. By default, it's "-c", which executes the code given.          """ -        cgroup = self._create_dynamic_cgroups() +        if self.cgroup_version == 2: +            nsjail_args = ("--use_cgroupv2", *nsjail_args) -        with NamedTemporaryFile() as nsj_log: -            if self._probe_cgroup_version() == 2: -                nsjail_args = (["--use_cgroupv2"]).extend(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,                  "--config", NSJAIL_CFG,                  "--log", nsj_log.name, -                # Set our dynamically created parent cgroups -                "--cgroup_mem_parent", cgroup, -                "--cgroup_pids_parent", cgroup,                  *nsjail_args,                  "--",                  self.config.exec_bin.path, *self.config.exec_bin.arg, *py_args, code @@ -260,8 +203,4 @@ class NsJail:          log.info(f"nsjail return code: {returncode}") -        # Remove the dynamically created cgroups once we're done -        Path(self.config.cgroup_mem_mount, cgroup).rmdir() -        Path(self.config.cgroup_pids_mount, cgroup).rmdir() -          return CompletedProcess(args, returncode, output, None) diff --git a/snekbox/utils/__init__.py b/snekbox/utils/__init__.py new file mode 100644 index 0000000..5a7b632 --- /dev/null +++ b/snekbox/utils/__init__.py @@ -0,0 +1,3 @@ +from . import cgroup, swap + +__all__ = ("cgroup", "swap") diff --git a/snekbox/utils/cgroup.py b/snekbox/utils/cgroup.py new file mode 100644 index 0000000..3e12406 --- /dev/null +++ b/snekbox/utils/cgroup.py @@ -0,0 +1,102 @@ +import logging +from pathlib import Path + +from snekbox.config_pb2 import NsJailConfig + +log = logging.getLogger(__name__) + + +def get_version(config: NsJailConfig) -> int: +    """ +    Examine the filesystem and return the guessed cgroup version. + +    Fall back to use_cgroupv2 in the NsJail config if either both v1 and v2 seem to be enabled, +    or neither seem to be enabled. +    """ +    cgroup_mounts = ( +        config.cgroup_mem_mount, +        config.cgroup_pids_mount, +        config.cgroup_net_cls_mount, +        config.cgroup_cpu_mount +    ) +    v1_exists = any(Path(mount).exists() for mount in cgroup_mounts) + +    controllers_path = Path(config.cgroupv2_mount, "cgroup.controllers") +    v2_exists = controllers_path.exists() + +    config_version = 2 if config.use_cgroupv2 else 1 + +    if v1_exists and v2_exists: +        # Probably hybrid mode. Use whatever is set in the config. +        return config_version +    elif v1_exists: +        if config_version == 2: +            log.warning( +                "NsJail is configured to use cgroupv2, but only cgroupv1 was detected on the " +                "system. Either use_cgroupv2 or cgroupv2_mount is incorrect. Snekbox is unable " +                "to override use_cgroupv2. If NsJail has been configured to use cgroups, then " +                "it will fail. In such case, please correct the config manually." +            ) +        return 1 +    elif v2_exists: +        return 2 +    else: +        log.warning( +            f"Neither the cgroupv1 controller mounts, nor {str(controllers_path)!r} exists. " +            "Either cgroup_xxx_mount and cgroupv2_mount are misconfigured, or all " +            "corresponding v1 controllers are disabled on the system. " +            "Falling back to the use_cgroupv2 NsJail setting." +        ) +        return config_version + + +def init(config: NsJailConfig) -> int: +    """Determine the cgroup version, initialise the cgroups for NsJail, and return the version.""" +    version = get_version(config) +    if version == 1: +        init_v1(config) +    else: +        init_v2(config) + +    return version + + +def init_v1(config: NsJailConfig) -> None: +    """ +    Create a PID and memory cgroup for NsJail to use as the parent cgroup for each controller. + +    NsJail doesn't do this automatically because it requires privileges NsJail usually doesn't +    have. +    """ +    pids = Path(config.cgroup_pids_mount, config.cgroup_pids_parent) +    mem = Path(config.cgroup_mem_mount, config.cgroup_mem_parent) + +    pids.mkdir(parents=True, exist_ok=True) +    mem.mkdir(parents=True, exist_ok=True) + + +def init_v2(config: NsJailConfig) -> None: +    """Ensure cgroupv2 children have controllers enabled.""" +    cgroup_mount = Path(config.cgroupv2_mount) + +    # If the root's subtree_control already has some controllers enabled, +    # no further action is necessary. +    if (cgroup_mount / "cgroup.subtree_control").read_text().strip(): +        return + +    # Move all processes from the cgroupv2 mount to a child cgroup. +    # This is necessary to be able to write to subtree_control in the parent later. +    # Otherwise, a write operation would yield a "device or resource busy" error. +    init_cgroup = cgroup_mount / "init" +    init_cgroup.mkdir(parents=True, exist_ok=True) + +    procs = (cgroup_mount / "cgroup.procs").read_text().split() +    for proc in procs: +        (init_cgroup / "cgroup.procs").write_text(proc) + +    # Enable all available controllers for child cgroups. +    # This also retroactively enables controllers for children that already exist, +    # including the "init" child created just before. +    controllers = (cgroup_mount / "cgroup.controllers").read_text().split() +    for controller in controllers: +        (cgroup_mount / "cgroup.subtree_control").write_text(f"+{controller}") 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 diff --git a/tests/api/__init__.py b/tests/api/__init__.py index dcee5b5..a900316 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -1,3 +1,4 @@ +import logging  from subprocess import CompletedProcess  from unittest import mock @@ -20,4 +21,6 @@ class SnekAPITestCase(testing.TestCase):          )          self.addCleanup(self.patcher.stop) +        logging.getLogger("snekbox.nsjail").setLevel(logging.WARNING) +          self.app = SnekAPI() diff --git a/tests/gunicorn_utils.py b/tests/gunicorn_utils.py new file mode 100644 index 0000000..f2d9b6d --- /dev/null +++ b/tests/gunicorn_utils.py @@ -0,0 +1,80 @@ +import concurrent.futures +import contextlib +import multiprocessing +from typing import Iterator + +from gunicorn.app.base import Application + + +class _StandaloneApplication(Application): +    def __init__(self, config_path: str = None, **kwargs): +        self.config_path = config_path +        self.options = kwargs + +        super().__init__() + +    def init(self, parser, opts, args): +        pass + +    def load(self): +        from snekbox.api.app import application +        return application + +    def load_config(self): +        for key, value in self.options.items(): +            if key in self.cfg.settings and value is not None: +                self.cfg.set(key.lower(), value) + +        if self.config_path: +            self.load_config_from_file(self.config_path) + + +def _proc_target(config_path: str, event: multiprocessing.Event, **kwargs) -> None: +    """Run a Gunicorn app with the given config and set `event` when Gunicorn is ready.""" +    def when_ready(_): +        event.set() + +    app = _StandaloneApplication(config_path, when_ready=when_ready, **kwargs) + +    import logging +    logging.disable(logging.INFO) + +    app.run() + + +def run_gunicorn(config_path: str = "config/gunicorn.conf.py", **kwargs) -> Iterator[None]: +    """ +    Run the Snekbox app through separate Gunicorn process. Use as a context manager. + +    `config_path` is the path to the Gunicorn config to use. +    Additional kwargs are interpreted as Gunicorn settings. + +    Raise RuntimeError if Gunicorn terminates before it is ready. +    Raise TimeoutError if Gunicorn isn't ready after 60 seconds. +    """ +    event = multiprocessing.Event() +    proc = multiprocessing.Process(target=_proc_target, args=(config_path, event), kwargs=kwargs) + +    try: +        proc.start() + +        # Wait 60 seconds for Gunicorn to be ready, but exit early if Gunicorn fails. +        executor = concurrent.futures.ThreadPoolExecutor(max_workers=2) +        concurrent.futures.wait( +            [executor.submit(proc.join), executor.submit(event.wait)], +            timeout=60, +            return_when=concurrent.futures.FIRST_COMPLETED +        ) +        # Can't use the context manager cause wait=False needs to be set. +        executor.shutdown(wait=False, cancel_futures=True) + +        if proc.is_alive(): +            if not event.is_set(): +                raise TimeoutError("Timed out waiting for Gunicorn to be ready.") +        else: +            raise RuntimeError(f"Gunicorn terminated unexpectedly with code {proc.exitcode}.") + +        yield +    finally: +        proc.terminate() diff --git a/tests/test_integration.py b/tests/test_integration.py new file mode 100644 index 0000000..b76b005 --- /dev/null +++ b/tests/test_integration.py @@ -0,0 +1,43 @@ +import json +import unittest +import urllib.request +from multiprocessing.dummy import Pool + +from tests.gunicorn_utils import run_gunicorn + + +def run_code_in_snekbox(code: str) -> tuple[str, int]: +    body = {"input": code} +    json_data = json.dumps(body).encode("utf-8") + +    req = urllib.request.Request("http://localhost:8060/eval") +    req.add_header("Content-Type", "application/json; charset=utf-8") +    req.add_header("Content-Length", str(len(json_data))) + +    with urllib.request.urlopen(req, json_data, timeout=30) as response: +        response_data = response.read().decode("utf-8") + +    return response_data, response.status + + +class IntegrationTests(unittest.TestCase): + +    def test_memory_limit_separate_per_process(self): +        """ +        Each NsJail process should have its own memory limit. + +        The memory used by one process should not contribute to the memory cap of other processes. +        See https://github.com/python-discord/snekbox/issues/83 +        """ +        with run_gunicorn(): +            code = "import time; ' ' * 33000000; time.sleep(0.1)" +            processes = 3 + +            args = [code] * processes +            with Pool(processes) as p: +                results = p.map(run_code_in_snekbox, args) + +            responses, statuses = zip(*results) + +            self.assertTrue(all(status == 200 for status in statuses)) +            self.assertTrue(all(json.loads(response)["returncode"] == 0 for response in responses)) diff --git a/tests/test_nsjail.py b/tests/test_nsjail.py index c0ed96b..989cc31 100644 --- a/tests/test_nsjail.py +++ b/tests/test_nsjail.py @@ -259,7 +259,8 @@ class NsJailTests(unittest.TestCase):          args = ("foo", "bar")          result = self.nsjail.python3("", nsjail_args=args) -        self.assertEqual(result.args[9:11], args) +        end = result.args.index("--") +        self.assertEqual(result.args[end - len(args):end], args)      def test_py_args(self):          args = ("-m", "timeit")  |