diff --git a/etc/nsjail/execute.cfg b/etc/nsjail/execute.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f8a6c0bbda8916c5b3bc290c55b1c24dfaab2339 --- /dev/null +++ b/etc/nsjail/execute.cfg @@ -0,0 +1,118 @@ +name: "compiler explorer compiler execution sandbox" + +mode: ONCE +hostname: "ce" + +time_limit: 0 +max_cpus: 1 + +log_level: FATAL + +rlimit_as_type: SOFT +rlimit_cpu_type: SOFT +rlimit_fsize_type: SOFT + +uidmap { + inside_id: "0" +} + +gidmap { + inside_id: "0" +} + +# must run following as root during system startup +# cgcreate -a ubuntu:ubuntu -g memory,pids,cpu,net_cls:ce-compile +cgroup_mem_parent: "ce-compile" +cgroup_pids_parent: "ce-compile" +cgroup_net_cls_parent: "ce-compile" +cgroup_cpu_parent: "ce-compile" + +cgroup_mem_max: 1342177280 # 1.25GB +cgroup_pids_max: 4 +# TODO decide (probably not?) +#cgroup_cpu_ms_per_sec: 500 + +mount { + src: "/lib" + dst: "/lib" + is_bind: true +} + +mount { + src: "/usr/lib" + dst: "/usr/lib" + is_bind: true +} + +mount { + src: "/lib64" + dst: "/lib64" + is_bind: true + mandatory: false +} + +mount { + src: "/lib32" + dst: "/lib32" + is_bind: true + mandatory: false +} + +mount { + dst: "/tmp" + fstype: "tmpfs" + options: "size=20971520,nr_inodes=100" # 20 MiB + rw: true + noexec: true + nodev: true + nosuid: true +} + +mount { + dst: "/dev" + fstype: "tmpfs" +} + +mount { + src: "/dev/null" + dst: "/dev/null" + rw: true + is_bind: true +} + +mount { + src: "/dev/zero" + dst: "/dev/zero" + is_bind: true +} + +mount { + src: "/dev/urandom" + dst: "/dev/random" + is_bind: true +} + +mount { + src: "/dev/urandom" + dst: "/dev/urandom" + is_bind: true +} + +mount { + dst: "/proc" + fstype: "proc" +} + +mount { + src: "/opt/compiler-explorer" + dst: "/opt/compiler-explorer" + is_bind: true +} + +mount { + src: "/opt/intel" + dst: "/opt/intel" + is_bind: true +} + +# TODO: seccomp? diff --git a/etc/nsjail/sandbox.cfg b/etc/nsjail/sandbox.cfg index 396f7b9421aa690d42c59e9b2a5f7a173f0f4a80..084acdc1a45e4f32e70c648d28aebeb8e60104f8 100644 --- a/etc/nsjail/sandbox.cfg +++ b/etc/nsjail/sandbox.cfg @@ -8,7 +8,7 @@ max_cpus: 1 log_level: FATAL -rlimit_as: 102400 # 100 GiB +rlimit_as_type: SOFT rlimit_cpu_type: SOFT rlimit_fsize: 16 # 16 MiB rlimit_nofile: 10 diff --git a/lib/exec.js b/lib/exec.js index 7b88cc3961c45957f08db3d29fae210ccd970366..78f083c1ca6ba50682d95c16f56d045ba3a4d8bb 100644 --- a/lib/exec.js +++ b/lib/exec.js @@ -158,7 +158,7 @@ function sandboxNsjail(command, args, options) { const jailingOptions = withNsjailTimeout([ '--config', 'etc/nsjail/sandbox.cfg', '--cwd', '/app', - '--bindmount', `${execPath}:/app`, + '--bindmount', `${execPath}:/app` ]); if (options.ldPath) { @@ -403,6 +403,35 @@ function executeFirejail(command, args, options) { return executeDirect(firejail, baseOptions.concat(args), options, filenameTransform); } +function executeNsjail(command, args, options) { + if (needsWine(command)) { + throw new Error('WINE not supported'); + } + options = options || {}; + + const nsjail = execProps("nsjail"); + const baseOptions = withNsjailTimeout([], options); + + logger.debug("Regular execution via firejail", {command, args}); + baseOptions.push('--config'); + baseOptions.push('etc/nsjail/execute.cfg'); + let filenameTransform; + if (options.customCwd) { + baseOptions.push('--bindmount'); + const privateDir = '/compilation'; + baseOptions.push(`${options.customCwd}:${privateDir}`); + const replacement = options.customCwd; + filenameTransform = opt => opt.replace(replacement, privateDir); + args = args.map(filenameTransform); + delete options.customCwd; + baseOptions.push('--cwd'); + baseOptions.push(privateDir); + } + baseOptions.push('--'); + baseOptions.push(command); + return executeDirect(nsjail, baseOptions.concat(args), options, filenameTransform); +} + function executeNone(command, args, options) { if (needsWine(command)) { return executeWineDirect(command, args, options); @@ -412,7 +441,8 @@ function executeNone(command, args, options) { const executeDispatchTable = { none: executeNone, - firejail: executeFirejail + firejail: executeFirejail, + nsjail: executeNsjail }; function execute(command, args, options) {