def test_changing_vmem_limit(self): # Up the limit, it will succeed. set_limit('VMEM', 80000000) res = jailpy(code="print len(bytearray(40000000))") self.assertEqual(res.stderr, "") self.assertEqual(res.stdout, "40000000\n") self.assertEqual(res.status, 0)
def test_disabling_vmem_limit(self): # Disable the limit, it will succeed. set_limit('VMEM', 0) res = jailpy(code="print len(bytearray(50000000))") self.assertEqual(res.stderr, "") self.assertEqual(res.stdout, "50000000\n") self.assertEqual(res.status, 0)
def test_cant_use_too_much_memory(self): # This will fail after setting the limit to 30Mb. set_limit('VMEM', 30000000) res = jailpy(code="print len(bytearray(40000000))") self.assertEqual(res.stdout, "") self.assertIn("MemoryError", res.stderr) self.assertEqual(res.status, 1)
def test_we_can_remove_tmp_files(self): # This test is meant to create a tmp file in a temp folder as the # sandbox user that the application user can't delete. # This is because the sandbox user has the ability to delete # any toplevel files in the tmp directory but not the abilty # to delete files in folders that are only owned by the sandbox # user, such as the temp directory created below. set_limit('FSIZE', 1000) res = jailpy( code="""\ import os, shutil, tempfile temp_dir = tempfile.mkdtemp() with open("{}/myfile.txt".format(temp_dir), "w") as f: f.write("This is my file!") shutil.move("{}/myfile.txt".format(temp_dir), "{}/overthere.txt".format(temp_dir)) with open("{}/overthere.txt".format(temp_dir)) as f: print f.read() with open("{}/.myfile.txt".format(temp_dir), "w") as f: f.write("This is my dot file!") # Now make it secret! os.chmod("{}/overthere.txt".format(temp_dir), 0) print os.listdir(temp_dir) """) self.assertResultOk(res) self.assertEqual( res.stdout, "This is my file!\n['overthere.txt', '.myfile.txt']\n" )
def enable_codejail(self, codejail_config): """ Enable codejail for the process. codejail_config is a dict like this: { "name": "python", "bin_path": "/path/to/python", "user": "******", "limits": { "CPU": 1, ... } } limits are optional user defaults to the current user """ name = codejail_config["name"] bin_path = codejail_config['bin_path'] user = codejail_config.get('user', getpass.getuser()) jail_code.configure(name, bin_path, user=user) limits = codejail_config.get("limits", {}) for name, value in limits.items(): jail_code.set_limit(name, value) self.log.info("configured codejail -> %s %s %s", name, bin_path, user) return name
def test_importing_lots_of_crap(self): set_limit('REALTIME', 10) globs = {} self.safe_exec(textwrap.dedent("""\ from numpy import * a = 1723 """), globs) self.assertEqual(globs['a'], 1723)
def test_cant_use_too_much_time(self, log_log): # Default time limit is 1 second. Sleep for 1.5 seconds. set_limit('CPU', 100) res = jailpy(code="import time; time.sleep(1.5); print 'Done!'") self.assertEqual(res.stdout, "") self.assertEqual(res.status, -signal.SIGKILL) # -9 # Make sure we log that we are killing the process. log_text = text_of_logs(log_log.mock_calls) self.assertRegexpMatches(log_text, r"WARNING: Killing process \d+")
def test_disabling_vmem_limit(self): # Disable the limit, it will succeed. set_limit('VMEM', 0) res = jailpy(code=""" from __future__ import print_function print(len(bytearray(50000000))) """) self.assertEqual(res.stderr, b"") self.assertEqual(res.stdout, b"50000000\n") self.assertEqual(res.status, 0)
def test_cant_use_too_much_memory(self): # This will fail after setting the limit to 30Mb. set_limit('VMEM', 80000000) res = jailpy(code=""" from __future__ import print_function print(len(bytearray(100000000))) """) self.assertEqual(res.stdout, b"") self.assertIn(b"MemoryError", res.stderr) self.assertEqual(res.status, 1)
def test_disabling_realtime_limit(self): # Disable the time limit, sleeping for 1.5 will be fine. set_limit('REALTIME', 0) res = jailpy(code=""" from __future__ import print_function import time time.sleep(1.5) print('Done!') """) self.assertResultOk(res) self.assertEqual(res.stdout, b"Done!\n")
def test_cant_use_too_much_cpu(self): set_limit('CPU', 1) set_limit('REALTIME', 10) res = jailpy(code=""" from __future__ import print_function from six.moves import range print(sum(range(2**31-1))) """) self.assertEqual(res.stdout, b"") self.assertEqual(res.stderr, b"") self.assertEqual(res.status, -signal.SIGXCPU) # 137
def test_argv(self): set_limit('REALTIME', 2) res = jailpy( code=""" from __future__ import print_function import sys print(':'.join(sys.argv[1:])) """, argv=["Hello", "world", "-x"], slug="a/useful/slug", ) self.assertResultOk(res) self.assertEqual(res.stdout, b"Hello:world:-x\n")
def test_can_write_temp_files(self): set_limit('FSIZE', 1000) res = jailpy(code="""\ import os, tempfile print "Trying mkstemp" f, path = tempfile.mkstemp() os.close(f) with open(path, "w") as f1: f1.write("hello") with open(path) as f2: print "Got this:", f2.read() """) self.assertResultOk(res) self.assertEqual(res.stdout, "Trying mkstemp\nGot this: hello\n")
def test_cant_write_large_temp_files(self): set_limit('FSIZE', 1000) res = jailpy(code="""\ import os, tempfile print "Trying mkstemp" f, path = tempfile.mkstemp() os.close(f) with open(path, "w") as f1: f1.write("hello"*250) with open(path) as f2: print "Got this:", f2.read() """) self.assertNotEqual(res.status, 0) self.assertEqual(res.stdout, "Trying mkstemp\n") self.assertIn("IOError", res.stderr)
def test_cant_fork(self): set_limit('NPROC', 1) res = jailpy(code="""\ from __future__ import print_function import os print("Forking") child_ppid = os.fork() print(child_ppid) """) # stdout should only contain the first print statement self.assertEqual(res.stdout, b"Forking\n") if six.PY2: self.assertIn(b"OSError", res.stderr) else: self.assertIn(b'BlockingIOError', res.stderr) self.assertNotEqual(res.status, 0)
def test_cant_use_too_much_time(self, log_log): # Default time limit is 1 second. Sleep for 1.5 seconds. set_limit('CPU', 100) set_limit('REALTIME', 1) res = jailpy( code=""" from __future__ import print_function import time time.sleep(1.5) print('Done!') """ ) self.assertEqual(res.stdout, b"") self.assertEqual(res.status, -signal.SIGKILL) # -9 # Make sure we log that we are killing the process. log_text = text_of_logs(log_log.mock_calls) self.assertRegex(log_text, r"WARNING: Killing process \d+")
def test_cant_write_large_temp_files(self): set_limit('FSIZE', 1000) res = jailpy(code="""\ import os, tempfile print "Trying mkstemp" f, path = tempfile.mkstemp() os.close(f) with open(path, "w") as f1: try: f1.write(".".join("%05d" % i for i in xrange(1000))) except IOError as e: print "Expected exception: %s" % e else: with open(path) as f2: print "Got this:", f2.read() """) self.assertResultOk(res) self.assertIn("Expected exception", res.stdout)
def test_cant_write_many_small_temp_files(self): # We would like this to fail, but there's nothing that checks total # file size written, so the sandbox does not prevent it yet. raise SkipTest("There's nothing checking total file size yet.") set_limit('FSIZE', 1000) res = jailpy(code="""\ import os, tempfile print "Trying mkstemp 250" for i in range(250): f, path = tempfile.mkstemp() os.close(f) with open(path, "w") as f1: f1.write("hello") with open(path) as f2: assert f2.read() == "hello" print "Finished 250" """) self.assertNotEqual(res.status, 0) self.assertEqual(res.stdout, "Trying mkstemp 250\n") self.assertIn("IOError", res.stderr)
def test_cant_write_large_temp_files(self): set_limit('FSIZE', 1000) res = jailpy(code="""\ from __future__ import print_function import os, tempfile from six.moves import range print("Trying mkstemp") f, path = tempfile.mkstemp() os.close(f) with open(path, "w") as f1: try: f1.write(".".join("%05d" % i for i in range(1000))) except IOError as e: print("Expected exception: %s" % e) else: with open(path) as f2: print("Got this:", f2.read()) """) if six.PY2: self.assertResultOk(res) self.assertIn(b"Expected exception", res.stdout) else: self.assertIn(b"OSError", res.stderr) self.assertIn(b"File too large", res.stderr)
def test_cant_use_too_much_time(self): # Default time limit is 1 second. Sleep for 1.5 seconds. set_limit('CPU', 100) res = jailpy(code="import time; time.sleep(1.5); print 'Done!'") self.assertEqual(res.stdout, "") self.assertEqual(res.status, -signal.SIGKILL) # -9
# part of the Pythontutor project # https://github.com/vpavlenko/pythontutor-ru from json import dumps, loads from os.path import dirname from sys import stderr from codejail.jail_code import configure, jail_code, set_limit from evaldontevil.config import * configure('python', VENV_PYTHON + '/bin/python', user=USER) set_limit('CPU', CPUTIME_LIMIT) set_limit('REALTIME', REALTIME_LIMIT) set_limit('MEM', MEM_LIMIT) set_limit('FSIZE', FSIZE_LIMIT) class ExecuteResult: def __init__(self, jailres): self.result = 'ok' self.stdout = '' self.stderr = '' if jailres.status & 128 != 0: self.result = 'realtime_limited' return
def test_disabling_realtime_limit(self): # Disable the time limit, sleeping for 1.5 will be fine. set_limit('REALTIME', 0) res = jailpy(code="import time; time.sleep(1.5); print 'Done!'") self.assertResultOk(res) self.assertEqual(res.stdout, "Done!\n")
def test_changing_realtime_limit(self): # Change time limit to 2 seconds, sleeping for 1.5 will be fine. set_limit('REALTIME', 2) res = jailpy(code="import time; time.sleep(1.5); print 'Done!'") self.assertResultOk(res) self.assertEqual(res.stdout, "Done!\n")
with open(sys.argv[7], "r") as f: source_code = f.read() print "Source code len: %d" % len(source_code) stdin_contents = '' with open(sys.argv[6], "r") as f: stdin_contents = f.read() output_file = sys.argv[8] print "Output file: %s" % output_file unit_test_code = None if len(sys.argv) >= 10: with open(sys.argv[9], "r") as f: unit_test_code = f.read() print "Unit test code len: %d" % len(unit_test_code) jail_code.configure('python', python_path, sandbox_user) jail_code.set_limit('CPU', max_cpu) jail_code.set_limit('VMEM', max_memory) jail_code.set_limit('REALTIME', max_real_time) result = jail_code.jail_code('python', source_code, \ None, None, stdin_contents, "codemarathon", unit_test_code) cpu_time = result.res_data.ru_utime + result.res_data.ru_stime memory_usage = result.res_data.ru_maxrss * resource.getpagesize() / 1024 status = result.status error_message = result.stderr with open(output_file, "w") as f: f.write(result.stdout) with open("stat", "w") as f: f.write("Time: %f\n" % cpu_time)
def tearDown(self): for name, value in self.old_limits.items(): set_limit(name, value) super(TestLimits, self).tearDown()
def test_cant_use_too_much_cpu(self): set_limit('CPU', 1) set_limit('REALTIME', 100) res = jailpy(code="print sum(xrange(2**31-1))") self.assertEqual(res.stdout, "") self.assertEqual(res.status, 128+signal.SIGXCPU) # 137
# evaldontevil # (eval, don't evil) # part of the Pythontutor project # https://github.com/vpavlenko/pythontutor-ru from json import dumps, loads from os.path import dirname from sys import stderr from codejail.jail_code import configure, jail_code, set_limit from evaldontevil.config import * configure('python', VENV_PYTHON + '/bin/python', user=USER) set_limit('CPU', CPUTIME_LIMIT) set_limit('REALTIME', REALTIME_LIMIT) set_limit('MEM', MEM_LIMIT) set_limit('FSIZE', FSIZE_LIMIT) class ExecuteResult: def __init__(self, jailres): self.result = 'ok' self.stdout = '' self.stderr = '' if jailres.status & 128 != 0: self.result = 'realtime_limited' return