feat(nsjail): make python/ansible rlimit_as configurable per worker (GIT-921) (#10138)

nsjail caps a jailed job's virtual address space at rlimit_as (4096 MiB for
python3 and ansible). JIT runtimes (Bun/JavaScriptCore, the JVM) reserve large
virtual ranges up front, so a subprocess spawned from a jailed Python/Ansible
job can crash against this cap even when its physical memory use is modest
(e.g. the Bun-compiled claude CLI hitting JSC/pthread allocation failures).

Most other language protos already run with disable_rl: true (unlimited);
python3 and ansible are the outliers with an explicit rlimit_as. This exposes
that cap via a per-language env var (NSJAIL_PY_RLIMIT_AS_MB,
NSJAIL_ANSIBLE_RLIMIT_AS_MB) so operators can raise or lift it on a dedicated
worker pool without a source patch/rebuild and without weakening the
mount/PID/user-namespace isolation that provides the real security boundary.
Only the address-space limit changes; cpu/fsize/nofile rlimits are untouched.

Value is in MiB, or unlimited/none/inf/0 to uncap (rlimit_as_type: INF). Unset
keeps the historical 4096 default.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-07-15 17:52:39 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent f7eb5c460d
commit 17872018cc
6 changed files with 110 additions and 10 deletions
+10 -5
View File
@@ -155,16 +155,17 @@ use windmill_object_store::OBJECT_STORE_SETTINGS;
use crate::{
common::{
build_command_with_isolation, create_args_and_out_file, get_reserved_variables, read_file,
read_result, resolve_nsjail_timeout, resolve_nsjail_tmp_mount_block, start_child_process,
OccupancyMetrics, StreamNotifier, DEV_CONF_NSJAIL,
read_result, render_nsjail_rlimit_as, resolve_nsjail_timeout,
resolve_nsjail_tmp_mount_block, start_child_process, OccupancyMetrics, StreamNotifier,
DEV_CONF_NSJAIL,
},
get_proxy_envs_for_lang,
handle_child::handle_child,
is_sandboxing_enabled, read_ee_registry_with_workspace_override,
worker_utils::ping_job_status,
PyV, DISABLE_NUSER, HOME_ENV, NSJAIL_AVAILABLE, NSJAIL_PATH, PATH_ENV, PIP_EXTRA_INDEX_URL,
PIP_INDEX_URL, PROXY_ENVS, PY_INSTALL_DIR, TRACING_PROXY_CA_CERT_PATH, TZ_ENV, UV_CACHE_DIR,
UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, UV_PYTHON_INSTALL_MIRROR,
PyV, DISABLE_NUSER, HOME_ENV, NSJAIL_AVAILABLE, NSJAIL_PATH, NSJAIL_PY_RLIMIT_AS_MB, PATH_ENV,
PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, PROXY_ENVS, PY_INSTALL_DIR, TRACING_PROXY_CA_CERT_PATH,
TZ_ENV, UV_CACHE_DIR, UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, UV_PYTHON_INSTALL_MIRROR,
};
use windmill_common::client::AuthedClient;
@@ -1077,6 +1078,10 @@ mount {{
job_dir,
"run.config.proto",
&NSJAIL_CONFIG_RUN_PYTHON3_CONTENT
.replace(
"{RLIMIT_AS}",
&render_nsjail_rlimit_as(NSJAIL_PY_RLIMIT_AS_MB.as_deref(), 4096),
)
.replace("{JOB_DIR}", job_dir)
.replace("{PY_INSTALL_DIR}", &*PY_INSTALL_DIR)
.replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string())