diff --git a/.github/workflows/package-pr.yaml b/.github/workflows/package-pr.yaml index 1fda6be..7b200aa 100644 --- a/.github/workflows/package-pr.yaml +++ b/.github/workflows/package-pr.yaml @@ -70,7 +70,7 @@ jobs: runner_uid_max: 1500 runner_gid_min: 1100 runner_gid_max: 1500 - enable_unshare: false + disable_networking: false output_max_size: 1024 max_process_count: 64 max_open_files: 2048 diff --git a/api/Dockerfile b/api/Dockerfile index 8f61d16..395e414 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -10,7 +10,7 @@ RUN for i in $(seq 1001 1500); do \ RUN apt-get update && \ apt-get install -y libxml2 gnupg tar coreutils util-linux libc6-dev \ binutils build-essential locales libpcre3-dev libevent-dev libgmp3-dev \ - libncurses6 libncurses5 libedit-dev && \ + libncurses6 libncurses5 libedit-dev libseccomp-dev && \ rm -rf /var/lib/apt/lists/* RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen @@ -22,5 +22,7 @@ COPY ["package.json", "package-lock.json", "./"] RUN npm i COPY ./src ./src +RUN make -C ./src/nosocket/ all && make -C ./src/nosocket/ install + CMD [ "node", "src", "-m", "-c", "/piston/config.yaml"] EXPOSE 2000/tcp diff --git a/api/src/config.js b/api/src/config.js index 023cc8e..d98a4b4 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -79,8 +79,8 @@ const options = [ validators: [] }, { - key: 'enable_unshare', - desc: 'Enable using unshare to disable networking', + key: 'disable_networking', + desc: 'Set to true to disable networking', default: true, validators: [] }, diff --git a/api/src/executor/job.js b/api/src/executor/job.js index 445c73a..77ecbfe 100644 --- a/api/src/executor/job.js +++ b/api/src/executor/job.js @@ -70,7 +70,7 @@ class Job { async safe_call(file, args, timeout) { return new Promise((resolve, reject) => { - const unshare = config.enable_unshare ? ['unshare','-n','-r'] : []; + const nonetwork = config.disable_networking ? ['nosocket'] : []; const prlimit = [ 'prlimit', @@ -80,7 +80,7 @@ class Job { const proc_call = [ ...prlimit, - ...unshare, + ...nonetwork, 'bash',file, ...args ]; diff --git a/api/src/nosocket/Makefile b/api/src/nosocket/Makefile new file mode 100644 index 0000000..a86a8f5 --- /dev/null +++ b/api/src/nosocket/Makefile @@ -0,0 +1,19 @@ +CC = gcc +CFLAGS = -O2 -Wall -lseccomp +TARGET = nosocket +BUILD_PATH = ./ +INSTALL_PATH = /usr/local/bin/ +SOURCE = nosocket.c + +all: $(TARGET) + +$(TARGET): $(SOURCE) + $(CC) $(BUILD_PATH)$(SOURCE) $(CFLAGS) -o $(TARGET) + +install: + mv $(TARGET) $(INSTALL_PATH) + +clean: + $(RM) $(TARGET) + $(RM) $(INSTALL_PATH)$(TARGET) + diff --git a/api/src/nosocket/nosocket.c b/api/src/nosocket/nosocket.c new file mode 100644 index 0000000..03909ee --- /dev/null +++ b/api/src/nosocket/nosocket.c @@ -0,0 +1,46 @@ +/* +nosocket.c + +Disables access to the `socket` syscall and runs a program provided as the first +commandline argument. +*/ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + // Disallow any new capabilities from being added + prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + + // SCMP_ACT_ALLOW lets the filter have no effect on syscalls not matching a + // configured filter rule (allow all by default) + scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW); + if (!ctx) + { + fprintf(stderr, "Unable to initialize seccomp filter context\n"); + return 1; + } + + // Add a seccomp rule to the syscall blacklist - blacklist the socket syscall + if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 0) < 0) + { + fprintf(stderr, "Unable to add seccomp rule to context\n"); + return 1; + } + +#ifdef DEBUG + seccomp_export_pfc(ctx, 0); +#endif + + if (argc < 2) + { + fprintf(stderr, "Usage %s: %s \n", argv[0], argv[0]); + return 1; + } + seccomp_load(ctx); + execvp(argv[1], argv + 1); + return 1; +} diff --git a/docker-compose.yaml b/docker-compose.yaml index 82ec45a..76cf319 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,12 +3,10 @@ version: '2.7' services: piston_api: build: api - cap_add: - - CAP_SYS_ADMIN restart: always ports: - 2000:2000 volumes: - ./data/piston:/piston tmpfs: - - /piston/jobs:exec \ No newline at end of file + - /piston/jobs:exec diff --git a/repo/Dockerfile b/repo/Dockerfile index debbd0b..4c85179 100644 --- a/repo/Dockerfile +++ b/repo/Dockerfile @@ -1,5 +1,5 @@ FROM debian:buster-slim - +ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && apt-get install -y unzip autoconf build-essential libssl-dev pkg-config zlib1g-dev libargon2-dev libsodium-dev libcurl4-openssl-dev sqlite3 libsqlite3-dev libonig-dev libxml2 libxml2-dev bc curl git linux-headers-amd64 perl xz-utils python3 python3-pip gnupg jq zlib1g-dev cmake cmake-doc extra-cmake-modules build-essential gcc binutils bash coreutils util-linux pciutils usbutils coreutils binutils findutils grep libncurses5-dev libncursesw5-dev python3-pip libgmp-dev libmpfr-dev python2 && \ ln -sf /bin/bash /bin/sh && \ rm -rf /var/lib/apt/lists/* && \