From 2ace03e50511155aba891e01eab8d10b563db790 Mon Sep 17 00:00:00 2001 From: oneearedrabbit Date: Fri, 25 Jun 2021 18:06:30 -0400 Subject: [PATCH] Add support for compiler-based languages --- Dockerfile.sandbox | 107 +++-------------------- diggy-sandbox/config/sandbox.cfg | 135 +++++++++++++++++++++++++++--- diggy-sandbox/sandbox/__main__.py | 2 +- diggy-sandbox/sandbox/langs.py | 15 +++- diggy-sandbox/sandbox/nsjail.py | 23 +++-- userland_tpl/welcome/main.c | 7 ++ 6 files changed, 174 insertions(+), 115 deletions(-) create mode 100644 userland_tpl/welcome/main.c diff --git a/Dockerfile.sandbox b/Dockerfile.sandbox index a307301..29158fa 100644 --- a/Dockerfile.sandbox +++ b/Dockerfile.sandbox @@ -55,21 +55,6 @@ WORKDIR /sandbox # Pipenv installs to the default user site since PIP_USER is set. RUN pipenv install --deploy --system -# This must come after the first pipenv command! From the docs: -# All RUN instructions following an ARG instruction use the ARG variable -# implicitly (as an environment variable), thus can cause a cache miss. - -# TODO: refactor this, I don't like that pytest depends on a docker -# container - -# ARG DEV - -# Install numpy when in dev mode; one of the unit tests needs it. -# RUN if [ -n "${DEV}" ]; \ -# then \ -# pipenv install --deploy --system --dev \ -# && PYTHONUSERBASE=/opt/python/diggy pip install numpy~=1.20; \ -# fi # ------------------------------------------------------------------------------ FROM venv as sandbox @@ -79,96 +64,28 @@ RUN apt-get -y update \ && apt-get install -y \ curl \ gnupg2 \ - procps \ - # Conda dependencies, see below - # bzip2 \ - # ca-certificates \ - # libglib2.0-0 \ - # libsm6 \ - # libxext6 \ - # libxrender1 \ - # mercurial \ - # subversion \ - # wget \ - && rm -rf /var/lib/apt/lists/* - -# == Python - -# NOTE: I could not make conda work with nsjail, i.e. numpy fails with -# this error: Intel MKL FATAL ERROR: Cannot load . I am -# stuck, and if you manage to get it up and running, please let me -# know. - -# ARG CONDA_VERSION=py38_4.9.2 -# ARG CONDA_MD5=122c8c9beb51e124ab32a0fa6426c656 + procps -# ENV PATH /opt/conda/bin:$PATH +# 1. Python -# # Based on https://github.com/ContinuumIO/docker-images -# RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-${CONDA_VERSION}-Linux-x86_64.sh -O miniconda.sh && \ -# echo "${CONDA_MD5} miniconda.sh" > miniconda.md5 && \ -# if ! md5sum --status -c miniconda.md5; then exit 1; fi && \ -# mkdir -p /opt && \ -# sh miniconda.sh -b -p /opt/conda && \ -# rm miniconda.sh miniconda.md5 && \ -# ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \ -# echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \ -# echo "conda activate base" >> ~/.bashrc && \ -# find /opt/conda/ -follow -type f -name '*.a' -delete && \ -# find /opt/conda/ -follow -type f -name '*.js.map' -delete && \ -# /opt/conda/bin/conda clean -afy -# RUN conda config --add channels intel -# RUN conda create --name diggy intelpython3_core python=3.7 - -# Pre-install Python packages - -# SHELL ["conda", "run", "-n", "diggy", "/bin/bash", "-c"] - -# RUN yes | conda install numpy \ -# matplotlib - -# TODO: extract this to a post-install script, all additional packages +# TODO: Extract this to a post-install script, all additional packages # must be living outside of the Dockerfile. e.g. docker exec -it # -v $(pwd)/post-install.sh:/post-install.sh # /post-install.sh RUN PYTHONUSERBASE=/opt/python/diggy pip install matplotlib \ numpy -# == Ruby -# Based on https://github.com/ms-ati/docker-rvm/blob/master/Dockerfile -# I am not sure whether I like RVM approach more than a native Ruby -# package, but I am giving it a try. -ARG RVM_VERSION=stable -ENV RVM_VERSION=${RVM_VERSION} - -# 3.0.0-preview1 was the latest available binary at the time of -# writting this Dockerfile -ARG RVM_RUBY_VERSION="3.0.0-preview1" -ENV RVM_RUBY_VERSION=${RVM_RUBY_VERSION} -ENV RVM_RUBY_DEFAULT=${RVM_RUBY_VERSION} - -RUN mkdir ~/.gnupg \ - && chmod 700 ~/.gnupg \ - && echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \ - && gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 \ - 7D2BAF1CF37B13E2069D6956105BD0E739499BDB \ - && curl -sSL https://raw.githubusercontent.com/rvm/rvm/${RVM_VERSION}/binscripts/rvm-installer -o rvm-installer \ - && curl -sSL https://raw.githubusercontent.com/rvm/rvm/${RVM_VERSION}/binscripts/rvm-installer.asc -o rvm-installer.asc \ - && gpg2 --verify rvm-installer.asc rvm-installer \ - && bash rvm-installer \ - && rm rvm-installer rvm-installer.asc \ - && echo "rvm_autoupdate_flag=2" >> /etc/rvmrc \ - && echo "rvm_silence_path_mismatch_check_flag=1" >> /etc/rvmrc \ - && echo "install: --no-document" > /etc/gemrc +# 2. Ruby +RUN apt-get install -y \ + ruby ruby-dev -SHELL ["/bin/bash", "--login", "-c"] +# 3. C/C++ +RUN apt-get install -y \ + clang + +# Clean up +RUN rm -rf /var/lib/apt/lists/* -RUN echo "== docker-rvm: Installing ${RVM_RUBY_VERSION} ==" \ - && rvm install ${RVM_RUBY_VERSION} \ - && echo "== docker-rvm: Setting default ${RVM_RUBY_DEFAULT} ==" \ - && rvm use --default ${RVM_RUBY_DEFAULT} \ - && rvm cleanup all \ - && rm -rf /var/lib/apt/lists/* # ------------------------------------------------------------------------------ FROM sandbox diff --git a/diggy-sandbox/config/sandbox.cfg b/diggy-sandbox/config/sandbox.cfg index d4c2a46..f6f2608 100644 --- a/diggy-sandbox/config/sandbox.cfg +++ b/diggy-sandbox/config/sandbox.cfg @@ -36,7 +36,7 @@ gidmap { cgroup_mem_max: 52428800 cgroup_mem_mount: "/sys/fs/cgroup/memory" -cgroup_pids_max: 2 +cgroup_pids_max: 3 cgroup_pids_mount: "/sys/fs/cgroup/pids" iface_no_lo: true @@ -91,7 +91,9 @@ mount { rw: true } -# == Python +envar: "PATH=/usr/bin" + +# 1. Python envar: "PYTHONIOENCODING=utf-8:strict" envar: "PYTHONPATH=/opt/python/diggy/lib/python3.9/site-packages" envar: "OMP_NUM_THREADS=1" @@ -114,26 +116,139 @@ mount { rw: false } +# 2. Ruby mount { - src: "/usr/local/bin/python3" - dst: "/usr/local/bin/python3" + src: "/usr/bin/ruby" + dst: "/usr/bin/ruby" is_bind: true rw: false } +# 3. C/C++ + mount { - src: "/usr/local/bin/python3.9" - dst: "/usr/local/bin/python3.9" + src: "/usr/bin/gcc" + dst: "/usr/bin/gcc" is_bind: true rw: false } -# == Ruby -envar: "LD_LIBRARY_PATH=/usr/local/rvm/rubies/default/lib" +mount { + src: "/usr/include" + dst: "/usr/include" + is_bind: true + rw: false +} + +# everything from binutils +mount { + src: "/usr/bin/ld" + dst: "/usr/bin/ld" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/ld" + dst: "/usr/bin/ld" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/as" + dst: "/usr/bin/as" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/addr2line" + dst: "/usr/bin/addr2line" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/ar" + dst: "/usr/bin/ar" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/c++filt" + dst: "/usr/bin/c++filt" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/gold" + dst: "/usr/bin/gold" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/gprof" + dst: "/usr/bin/gprof" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/nm" + dst: "/usr/bin/nm" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/objcopy" + dst: "/usr/bin/objcopy" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/objdump" + dst: "/usr/bin/objdump" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/ranlib" + dst: "/usr/bin/ranlib" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/readelf" + dst: "/usr/bin/readelf" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/size" + dst: "/usr/bin/size" + is_bind: true + rw: false +} + +mount { + src: "/usr/bin/strings" + dst: "/usr/bin/strings" + is_bind: true + rw: false +} mount { - src: "/usr/local/rvm/rubies/default" - dst: "/usr/local/rvm/rubies/default" + src: "/usr/bin/strip" + dst: "/usr/bin/strip" is_bind: true rw: false } diff --git a/diggy-sandbox/sandbox/__main__.py b/diggy-sandbox/sandbox/__main__.py index adb3ef6..e1dfb79 100644 --- a/diggy-sandbox/sandbox/__main__.py +++ b/diggy-sandbox/sandbox/__main__.py @@ -25,7 +25,7 @@ def main() -> None: nsjail = NsJail(nsjail_config=NSJAIL_SYSTEM_CFG) result = nsjail.system(args.command.split(' ')) else: - nsjail = Nsjail() + nsjail = NsJail() result = nsjail.run(username=args.username, filename=args.filename) print(result.stdout) diff --git a/diggy-sandbox/sandbox/langs.py b/diggy-sandbox/sandbox/langs.py index caeaf64..b8696a8 100644 --- a/diggy-sandbox/sandbox/langs.py +++ b/diggy-sandbox/sandbox/langs.py @@ -1,8 +1,17 @@ langs = { - ".py": {"name": "Python", "path": "/usr/local/bin/python", "args": "-BSqu"}, + ".py": { + "name": "Python", + "run": "/usr/local/bin/python", + "run_args": ("-BSqu") + }, ".rb": { "name": "Ruby", - "path": "/usr/local/rvm/rubies/default/bin/ruby", - "args": "", + "run": "/usr/bin/ruby", }, + ".c": { + "name": "C", + "compile": "/usr/bin/gcc", + "compile_args": ("-Wall", "-Wextra"), + "run": "/userland/a.out", + } } diff --git a/diggy-sandbox/sandbox/nsjail.py b/diggy-sandbox/sandbox/nsjail.py index c459ddf..d3cf4cb 100644 --- a/diggy-sandbox/sandbox/nsjail.py +++ b/diggy-sandbox/sandbox/nsjail.py @@ -202,17 +202,28 @@ def run(self, filename: str, username: str) -> CompletedProcess: if lang is None: return CompletedProcess('', 0, "Language is not supported", None) - args = ( - lang["path"], - lang["args"], - userland_resolve(filename), - ) - compact_args = list(filter(None, args)) + fullname = userland_resolve(filename) nsjail_args = ( "--bindmount", f"{USERLAND_PATH}/{username}:{USERLAND_PATH}", ) + if lang.get("compile"): + compile_args = ( + lang["compile"], + *lang.get("compile_args", ()), + fullname, + ) + compact_compile_args = list(filter(None, compile_args)) + self.jail(args=compact_compile_args, nsjail_args=nsjail_args) + + args = ( + lang["run"], + *lang.get("args", ()), + fullname, + ) + compact_args = list(filter(None, args)) + return self.jail(args=compact_args, nsjail_args=nsjail_args) def jail( diff --git a/userland_tpl/welcome/main.c b/userland_tpl/welcome/main.c new file mode 100644 index 0000000..a5569f5 --- /dev/null +++ b/userland_tpl/welcome/main.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("Hello, world!"); + return 0; +}