Add support for sandboxing the executables

This relies on an lxc container
This commit is contained in:
Nicolas Setton
2018-07-09 14:28:42 -04:00
parent adbe60e7ec
commit e4c668a9c5
3 changed files with 74 additions and 2 deletions

View File

@@ -2,6 +2,13 @@
Prototype server for creating interactive "try SPARK / try Ada" webpages
## Requirements
In addition to Python, this system relies on LXC to sandbox
the run of executables. To do this, you need
- a container named "safecontainer"
- this container should have a non-admin user 'ubuntu'
## Getting started
To setup, do this:

View File

@@ -214,11 +214,16 @@ def run_program(request):
# Run the command(s) to check the program
commands = [
# Build the program
["gprbuild", "-q", "-P", "main"],
# TODO: implement a safe execute in a container
[os.path.join(tempd, main[:-4])],
# Launch the program via "safe_run", to sandbox it
["python",
os.path.join(os.path.dirname(__file__), 'safe_run.py'),
os.path.join(tempd, main[:-4])],
]
print commands
try:
p = process_handling.SeparateProcess(commands, tempd)
message = "running gnatprove"

View File

@@ -0,0 +1,60 @@
""" This is a standalone Python script that runs its argument
safely in a container.
At the moment it assumes that the container "safecontainer"
exists and is running.
"""
import os
import time
import sys
import subprocess
CONT = 'safecontainer'
DEBUG = False
def run(command):
if DEBUG:
print ">", " ".join(command)
output = subprocess.check_output(["lxc", "exec", CONT, "--"] + command)
if output:
output = output.rstrip()
if DEBUG:
print "<", output
return output
def safe_run(main):
# Make a temporary directory on the container
tmpdir = run(["mktemp", "-d"])
try:
run(["chown", "ubuntu", tmpdir])
# Push the executable to the container
subprocess.check_call(["lxc", "file", "push", main,
# This requires the dir to end with /
CONT + tmpdir + os.sep])
# TODO: rlimit?
# Run it, printint output to stdout as we go along
subprocess.call(["lxc", "exec", CONT, "--",
"su", "ubuntu", "-c",
os.path.join(tmpdir, os.path.basename(main))],
stdout=sys.stdout)
except E:
print sys.exc_info()
finally:
if tmpdir and tmpdir.startswith("/tmp"):
time.sleep(0.2) # Time for the filesystem to sync
run(["rm", "-rf", tmpdir])
if __name__ == '__main__':
# Do not perform any sanity checking on args - this is not meant to
# be launched interactively
main = sys.argv[1]
safe_run(main)