v3 - Remove the use of unshare + privileged mode and instead (#195)

use seccomp to filter for socket syscalls
This commit is contained in:
Victor Frazao 2021-04-06 20:31:30 -04:00 committed by GitHub
parent f6a4e67d5f
commit 552fb91c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 10 deletions

View File

@ -70,7 +70,7 @@ jobs:
runner_uid_max: 1500 runner_uid_max: 1500
runner_gid_min: 1100 runner_gid_min: 1100
runner_gid_max: 1500 runner_gid_max: 1500
enable_unshare: false disable_networking: false
output_max_size: 1024 output_max_size: 1024
max_process_count: 64 max_process_count: 64
max_open_files: 2048 max_open_files: 2048

View File

@ -10,7 +10,7 @@ RUN for i in $(seq 1001 1500); do \
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y libxml2 gnupg tar coreutils util-linux libc6-dev \ apt-get install -y libxml2 gnupg tar coreutils util-linux libc6-dev \
binutils build-essential locales libpcre3-dev libevent-dev libgmp3-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/* rm -rf /var/lib/apt/lists/*
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen 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 RUN npm i
COPY ./src ./src COPY ./src ./src
RUN make -C ./src/nosocket/ all && make -C ./src/nosocket/ install
CMD [ "node", "src", "-m", "-c", "/piston/config.yaml"] CMD [ "node", "src", "-m", "-c", "/piston/config.yaml"]
EXPOSE 2000/tcp EXPOSE 2000/tcp

View File

@ -79,8 +79,8 @@ const options = [
validators: [] validators: []
}, },
{ {
key: 'enable_unshare', key: 'disable_networking',
desc: 'Enable using unshare to disable networking', desc: 'Set to true to disable networking',
default: true, default: true,
validators: [] validators: []
}, },

View File

@ -70,7 +70,7 @@ class Job {
async safe_call(file, args, timeout) { async safe_call(file, args, timeout) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const unshare = config.enable_unshare ? ['unshare','-n','-r'] : []; const nonetwork = config.disable_networking ? ['nosocket'] : [];
const prlimit = [ const prlimit = [
'prlimit', 'prlimit',
@ -80,7 +80,7 @@ class Job {
const proc_call = [ const proc_call = [
...prlimit, ...prlimit,
...unshare, ...nonetwork,
'bash',file, 'bash',file,
...args ...args
]; ];

19
api/src/nosocket/Makefile Normal file
View File

@ -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)

View File

@ -0,0 +1,46 @@
/*
nosocket.c
Disables access to the `socket` syscall and runs a program provided as the first
commandline argument.
*/
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <seccomp.h>
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 <program name> <arguments>\n", argv[0], argv[0]);
return 1;
}
seccomp_load(ctx);
execvp(argv[1], argv + 1);
return 1;
}

View File

@ -3,12 +3,10 @@ version: '2.7'
services: services:
piston_api: piston_api:
build: api build: api
cap_add:
- CAP_SYS_ADMIN
restart: always restart: always
ports: ports:
- 2000:2000 - 2000:2000
volumes: volumes:
- ./data/piston:/piston - ./data/piston:/piston
tmpfs: tmpfs:
- /piston/jobs:exec - /piston/jobs:exec

View File

@ -1,5 +1,5 @@
FROM debian:buster-slim 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 && \ 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 && \ ln -sf /bin/bash /bin/sh && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \