Add wrapper program to apply seccomp to user code #47
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #41 by creating a "sandbox" executable which is deployed to the Docker image for running user code, and using it as
exec-wrapperin GDB (or calling it directly as a wrapper when not debugging).Currently it bans syscalls (only
ptraceat the moment) by returningERFKILL- I'm definitely open to alternatives here (EPERMcomes to mind); I primarily pickedERFKILLso it's obviously weird when debugging the sandbox feature as opposed to ambiguous with a potentially "real"EPERM. (Alternatively we can just kill the child.)Modifies the Dockerfile to use a multi-stage build: uses the
gcc:10.2.0image to compile the sandbox program, then takes the compiled executable and copies it into the final cplayground Docker image. This lets us avoid installing any of the compilation garbage in the target image, although since we're installing build-essential anyway this may be less relevant. However, from what I can tell, this is the "right" way to make a Docker image for a C program. If we want to change the CFLAGS or whatnot used for the build of the sandbox, that will entail a Dockerfile tweak.The sandbox program itself is a fairly straightforward seccomp BPF program which blocklists ptrace and allows all other syscalls. Seccomp policies can be stacked, so we won't be overriding Docker's policy or anything. I haven't thoroughly examined this for security, but I imagine as long as the user code cannot coerce any of its parent processes to run code not affected by this policy, we should be fine. If we knew more about user programs, it might make more sense to only list allowed calls and block the rest, but considering we accept essentially arbitrary user programs, this is probably out of scope for this PR. If the sandbox program fails to apply its policy and exec the child, it returns status 100 +/- 1.
My biggest gripe at the moment is probably that the responsibility for ensuring the sandbox actually gets installed is split between
run.pyandcontainer.ts. I'm also not 100% happy with the ERFKILL return status, but I'm not sure what the right thing to do there is. Opening this PR for discussion and review.