def probe(self): # add custom entries into the probe dict d = Sandbox.probe(self, False) d['cpu'] = d['cpu_info'][0] d['mem'] = d['mem_info'][1] d['result_name'] = self.result_name(self.result) d['result'] = self.result return d
def probe(self): # add custom entries into the probe dict d = Sandbox.probe(self, False) d['cpu'] = d['cpu_info'][0] d['mem'] = d['mem_info'][1] d['result'] = ('PD', 'OK', 'RF', 'ML', 'OL', 'TL', 'RT', 'AT', 'IE', 'BP')[self.result] return d
def test_rlimit_cpu(self): s = Sandbox(self.task[6]) s.policy = AllowResLimitPolicy(s) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGXCPU, SI_KERNEL)) pass
def test_sigbus_adraln(self): s = Sandbox(self.task[0]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGBUS, BUS_ADRALN)) pass
def test_sigtrap_user(self): s = Sandbox(self.task[4]) s.policy = KillerPolicy(s, SIGTRAP) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGTRAP, SI_USER)) pass
def test_sigkill(self): s = Sandbox(self.task[4]) s.policy = KillerPolicy(s, SIGKILL) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'][0], SIGKILL) pass
def test_sigsegv_accerr(self): s = Sandbox(self.task[3]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGSEGV, SEGV_ACCERR)) pass
def test_sigfpe_intdiv(self): s = Sandbox(self.task[1]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGFPE, FPE_INTDIV)) pass
def test_int80_fork(self): # syscall #2: (fork, i686) vs (open, x86_64) s = Sandbox(self.task[1]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) self.assertEqual(d['syscall_info'], (2, 1)) pass
def test_ml_static(self): s = Sandbox(self.task[0], quota=dict(wallclock=60000, cpu=2000, memory=2 ** 24)) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_ML) d = s.probe(False) mem = d['mem_info'][1] * 1024 self.assertLess(s.quota[Sandbox.S_QUOTA_MEMORY], mem) pass
def test_kill_ppid(self): s = Sandbox(self.task[0]) s.policy = AllowSelfKillPolicy(s) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowSelfKillPolicy.SC_kill) pass
def test_exec_rf(self): # minimal policy forbids execve() s = Sandbox(self.task[:]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowExecOncePolicy.SC_execve) pass
def test_rlimit_fsz(self): s_wr = open(config.touch("rlimit_fsz.out"), "wb") s = Sandbox(self.task[5], stdout=s_wr) s.policy = AllowResLimitPolicy(s) s.run() s_wr.close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_OL) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGXFSZ, SI_USER)) pass
def test_int80_exit1(self): # syscall #1: (exit, i686) vs (write, x86_64) s = Sandbox(self.task[0]) s.policy = AllowExitPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_AT) d = s.probe(False) self.assertEqual(d['exitcode'], 1) self.assertEqual(d['syscall_info'], (1, 1)) pass
def test_exec_nested(self): # nested execve(): ./exec.exe ./exec.exe ./hello.exe s = Sandbox([self.task[0], ] + self.task[:]) s.policy = AllowExecOncePolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowExecOncePolicy.SC_execve) pass
def test_open_bogus(self): # dumping bad address should cause RT not BP/IE s = Sandbox(self.task[2]) s.policy = SelectiveOpenPolicy(s, set()) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in SelectiveOpenPolicy.SC_open) pass
def test_open_bogus(self): # dumping bad address should cause RT not BP/IE s = Sandbox(self.task[2]) s.policy = SelectiveOpenPolicy(s, set()) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) sc = d['syscall_info'] if machine( ) == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in SelectiveOpenPolicy.SC_open) pass
def test_tl_sleep(self): s = Sandbox(self.task[3], quota=dict(wallclock=1000, cpu=2000)) s.policy = AllowPauseSleepPolicy(s) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_TL) d = s.probe(False) elapsed = d['elapsed'] eps = config.MAX_WALLCLOCK_OVERRUN self.assertLess(s.quota[Sandbox.S_QUOTA_WALLCLOCK], elapsed) self.assertLess(elapsed - s.quota[Sandbox.S_QUOTA_WALLCLOCK], eps) pass
def test_exec_rf(self): # minimal policy forbids execve() s = Sandbox(self.task[:]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine( ) == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowExecOncePolicy.SC_execve) pass
def test_sigkill_io(self): s_rd, s_wr = os.pipe() s = Sandbox(self.task[7], stdin=s_rd) s.policy = KillerPolicy(s, SIGKILL) s.run() os.fdopen(s_rd, "rb").close() os.fdopen(s_wr, "wb").close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'][0], SIGKILL) pass
def test_tl_busy_loop_1s(self): s = Sandbox(self.task[0], quota=dict(wallclock=60000, cpu=1000)) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_TL) d = s.probe(False) cpu = d['cpu_info'][0] eps = config.MAX_CPU_OVERRUN self.assertLess(s.quota[Sandbox.S_QUOTA_CPU], cpu) self.assertLess(cpu - s.quota[Sandbox.S_QUOTA_CPU], eps) pass
def test_sigxfsz_user(self): s = Sandbox(self.task[4]) s.policy = KillerPolicy(s, SIGXFSZ) s.run() # this results in OL instead of RT because the way linux file systems # notify disk quota limitation is simply sending SIGXFSZ to the program # unfortunately the si_code is SI_USER making it not distinguishable # from a synthetic SIGXFSZ signal sent from third party self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_OL) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGXFSZ, SI_USER)) pass
def test_assert_rf(self): s_wr = open("/dev/null", "wb") s = Sandbox(self.task[1], stderr=s_wr) s.policy = MinimalPolicy() s.run() s_wr.close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowSelfKillPolicy.SC_rt_sigprocmask or sc in AllowSelfKillPolicy.SC_sigprocmask) pass
def test_assert(self): s_wr = open("/dev/null", "wb") s = Sandbox(self.task[1], stderr=s_wr) s.policy = AllowSelfKillPolicy(s) s.run() s_wr.close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RT) d = s.probe(False) self.assertEqual(d['signal_info'], (SIGABRT, SI_TKILL)) sc = d['syscall_info'] if machine() == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowSelfKillPolicy.SC_tgkill) pass
def test_ml_alloc(self): s_wr = open("/dev/null", "wb") s = Sandbox(self.task[1], quota=dict(wallclock=60000, cpu=2000, memory=2 ** 24), stderr=s_wr) s.policy = MinimalPolicy() s.run() s_wr.close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_ML) d = s.probe(False) mem = d['mem_info'][1] * 1024 self.assertLess(s.quota[Sandbox.S_QUOTA_MEMORY], mem) pass
def test_exit_group1(self): s = Sandbox(self.task[3]) s.policy = MinimalPolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_AT) # validate profiling d = s.probe(False) self.assertEqual(d['exitcode'], 1) cpu = d['cpu_info'][0] # cpu clock time mem = d['mem_info'][1] # peak vm size self.assertTrue(cpu >= 0) self.assertTrue(mem > 0) pass
def test_exec_nested(self): # nested execve(): ./exec.exe ./exec.exe ./hello.exe s = Sandbox([ self.task[0], ] + self.task[:]) s.policy = AllowExecOncePolicy() s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_RF) d = s.probe(False) sc = d['syscall_info'] if machine( ) == 'x86_64' else d['syscall_info'][0] self.assertTrue(sc in AllowExecOncePolicy.SC_execve) pass
def test_hello_world(self): s_wr = open("/dev/null", "wb") s = Sandbox(self.task[0], stdout=s_wr) s.run() s_wr.close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_OK) # validate profiling d = s.probe(False) self.assertEqual(d['exitcode'], 0) cpu = d['cpu_info'][0] # cpu clock time mem = d['mem_info'][1] # peak vm size self.assertTrue(cpu >= 0) self.assertTrue(mem > 0) pass
def test_tl_blocking_io(self): s_rd, s_wr = os.pipe() s = Sandbox(self.task[1], quota=dict(wallclock=1000, cpu=2000), stdin=s_rd) s.policy = MinimalPolicy() s.run() os.fdopen(s_rd, "rb").close() os.fdopen(s_wr, "wb").close() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_TL) d = s.probe(False) elapsed = d['elapsed'] eps = config.MAX_WALLCLOCK_OVERRUN self.assertLess(s.quota[Sandbox.S_QUOTA_WALLCLOCK], elapsed) self.assertLess(elapsed - s.quota[Sandbox.S_QUOTA_WALLCLOCK], eps) pass
def test_owner_group(self): nobody = getpwnam('nobody') s = Sandbox(self.task[0], owner=nobody.pw_uid, group=nobody.pw_gid) s.policy = SelectiveOpenPolicy(s, [(self.fout[0].encode(), O_WRONLY | O_CREAT | O_TRUNC), ]) self.assertEqual(s.owner, nobody.pw_uid) self.assertEqual(s.group, nobody.pw_gid) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_AT) d = s.probe(False) self.assertEqual(d['exitcode'], EACCES) # make sure file content is not changed with open(self.fout[0], "rb") as f: self.assertEqual(f.read(), self.secret) f.close() pass
def test_a_plus_b(self): p_rd, p_wr = os.pipe() p = Popen(["/bin/echo", "1", "2"], close_fds=True, stdout=p_wr) os.fdopen(p_wr, 'wb').close() s_rd, s_wr = os.pipe() s = Sandbox(self.task[1], stdin=p_rd, stdout=s_wr) s.run() self.assertEqual(s.status, Sandbox.S_STATUS_FIN) self.assertEqual(s.result, Sandbox.S_RESULT_OK) # validate result os.fdopen(s_wr, 'wb').close() with os.fdopen(s_rd, 'rb') as f: self.assertEqual(f.read(), b"3\n") f.close() # validate profiling d = s.probe(False) cpu = d['cpu_info'][0] # cpu clock time mem = d['mem_info'][1] # peak vm size self.assertTrue(cpu >= 0) self.assertTrue(mem > 0) pass