def comp_cxx(self, callback): '''GCC, Clang compile. Args: callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' callback(stat['detect_error']) with StackContext(Privilege.fileaccess): compile_path = self.chal_path + '/compile' os.mkdir(compile_path, mode=0o770) shutil.copyfile(self.code_path, compile_path + '/test.cpp', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(compile_path, self.compile_uid, self.compile_gid) if self.comp_typ == 'g++': compiler = '/usr/bin/g++' elif self.comp_typ == 'clang++': compiler = '/usr/bin/clang++' task_id = PyExt.create_task(compiler, \ [ '-O2', '-std=c++14', '-o', './a.out', './test.cpp', ], \ [ 'PATH=/usr/bin', 'TMPDIR=/home/%d/compile'%self.uniqid, ], \ StdChal.null_fd, StdChal.null_fd, StdChal.null_fd, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 256 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(-1) else: PyExt.start_task(task_id, _done_cb)
def __init__(self, *args): Privilege.init() PyExt.init() StdChal.init() IOLoop.configure(EvIOLoop) Server.init_socket_server() super().__init__(*args)
def main(): '''Main function.''' Privilege.init() PyExt.init() StdChal.init() IOLoop.configure(EvIOLoop) init_websocket_server() IOLoop.instance().start()
def main(): '''Main function.''' Privilege.init() PyExt.init() StdChal.init() IOLoop.configure(EvIOLoop) init_socket_server() IOLoop.instance().start()
def comp_make(self, callback=None): '''Makefile compile. Args: callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' callback((stat['detect_error'], '')) make_path = self.chal_path + '/compile' FileUtils.copydir(self.res_path + '/make', make_path) with StackContext(Privilege.fileaccess): shutil.copyfile(self.code_path, make_path + '/main.cpp', \ follow_symlinks=False) FileUtils.setperm(make_path, self.compile_uid, self.compile_gid) with StackContext(Privilege.fullaccess): os.chmod(make_path, mode=0o770) task_id = PyExt.create_task('/usr/bin/make', \ [], \ [ 'PATH=/usr/bin:/bin', 'TMPDIR=/home/%d/compile'%self.uniqid, 'OUT=./a.out', ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, }, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback((PyExt.DETECT_INTERNALERR, '')) else: PyExt.start_task(task_id, _done_cb)
def comp_make(self, callback=None): '''Makefile compile. Args: callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' callback((stat['detect_error'], '')) make_path = self.chal_path + '/compile' FileUtils.copydir(self.res_path + '/make', make_path) with StackContext(Privilege.fileaccess): shutil.copyfile(self.code_path, make_path + '/main.cpp', \ follow_symlinks=False) FileUtils.setperm(make_path, self.compile_uid, self.compile_gid) with StackContext(Privilege.fullaccess): os.chmod(make_path, mode=0o770) task_id = PyExt.create_task('/usr/bin/make', \ [], \ [ 'PATH=/usr/bin:/bin', 'TMPDIR=/home/%d/compile'%self.uniqid, 'OUT=./a.out', ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, }, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(PyExt.DETECT_INTERNALERR) else: PyExt.start_task(task_id, _done_cb)
def comp_python(self, callback): '''Python3.4 compile. Args: callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' callback(stat['detect_error']) with StackContext(Privilege.fileaccess): compile_path = self.chal_path + '/compile' os.mkdir(compile_path, mode=0o770) shutil.copyfile(self.code_path, compile_path + '/test.py', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(compile_path, self.compile_uid, self.compile_gid) task_id = PyExt.create_task('/usr/bin/python3.4', \ [ '-m', 'py_compile', './test.py' ], \ [ 'HOME=/home/%d/compile'%self.uniqid, 'LANG=en_US.UTF-8' ], \ StdChal.null_fd, StdChal.null_fd, StdChal.null_fd, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 256 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(-1) else: PyExt.start_task(task_id, _done_cb)
def main(): '''Main function.''' Privilege.init() PyExt.init() StdChal.init() IOLoop.configure(EvIOLoop) app = Application([ (r'/judge', JudgeHandler), ]) app.listen(2501) IOLoop.instance().start()
def __init__(self, *args): Privilege.init() PyExt.init() StdChal.init() super().__init__(*args)
def build(self, build_ugid, res_path, callback=None): '''Build environment. Args: build_ugid ((int, int)): Build UID/GID. res_path (string): Resource path. callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' if stat['detect_error'] == PyExt.DETECT_NONE: callback(True) else: callback(False) build_uid, build_gid = build_ugid # Prepare build environment. FileUtils.copydir(res_path + '/check', self.build_path) FileUtils.setperm(self.build_path, build_uid, build_gid) with StackContext(Privilege.fullaccess): os.chmod(self.build_path, mode=0o770) with StackContext(Privilege.fileaccess): if not os.path.isfile(self.build_path + '/build'): callback(True) return # Make the build file executable. with StackContext(Privilege.fullaccess): os.chmod(self.build_path + '/build', mode=0o770) # Build. task_id = PyExt.create_task(self.build_relpath + '/build', \ [], \ [ 'PATH=/usr/bin:/bin', 'TMPDIR=%s'%self.build_relpath, 'HOME=%s'%self.build_relpath, 'LANG=en_US.UTF-8' ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, }, \ self.build_relpath, 'container/standard', \ build_uid, build_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(False) else: PyExt.start_task(task_id, _done_cb)
def judge(self, src_path, exe_relpath, argv, envp, check_ugid, test_ugid, \ test_relpath, test_param, metadata, callback=None): '''I/O redirect special judge. Args: src_path (string): Executable source path. exe_relpath (string): Executable or interpreter path in the sandbox. argv ([string]): List of arguments. envp ([string]): List of environment variables. check_ugid (int, int): Check UID/GID. test_ugid (int, int): Test UID/GID. test_relpath (string): Test relative path. test_param (dict): Test parameters. metadata (dict): Metadata. callback (function): Callback of return_future. Returns: None ''' def _check_started_cb(task_id): '''Check started callback. Close unused file descriptors after the check is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal inpipe_fd nonlocal outpipe_fd nonlocal ansfile_fd nonlocal check_infile_fd os.close(inpipe_fd[1]) os.close(outpipe_fd[0]) if ansfile_fd is not None: os.close(ansfile_fd) if check_infile_fd is not None: os.close(check_infile_fd) def _test_started_cb(task_id): '''Test started callback. Close unused file descriptors after the test is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal inpipe_fd nonlocal outpipe_fd nonlocal outfile_fd nonlocal test_infile_fd os.close(inpipe_fd[0]) os.close(outpipe_fd[1]) os.close(outfile_fd) if test_infile_fd is not None: os.close(test_infile_fd) def _done_cb(): '''Done callback.''' nonlocal result_stat nonlocal result_pass if result_pass is not None and result_stat is not None: callback((result_pass, result_stat)) return def _check_done_cb(task_id, stat): '''Check done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_pass if stat['detect_error'] == PyExt.DETECT_NONE: result_pass = True else: result_pass = False _done_cb() def _test_done_cb(task_id, stat): '''Test done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_stat result_stat = (stat['utime'], stat['peakmem'], stat['detect_error']) _done_cb() result_stat = None result_pass = None in_path = test_param['in'] ans_path = test_param['ans'] timelimit = test_param['timelimit'] memlimit = test_param['memlimit'] check_uid, check_gid = check_ugid test_uid, test_gid = test_ugid test_path = self.container_path + test_relpath output_relpath = test_relpath + '/output.txt' output_path = self.container_path + output_relpath verdict_relpath = test_relpath + '/verdict.txt' verdict_path = self.container_path + verdict_relpath # Prepare test environment. with StackContext(Privilege.fileaccess): os.mkdir(test_path, mode=0o771) shutil.copyfile(src_path, test_path + '/a.out', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(test_path + '/a.out', test_uid, test_gid) os.chmod(test_path + '/a.out', 0o500) # Prepare I/O. with StackContext(Privilege.fileaccess): try: check_infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) test_infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) except FileNotFoundError: check_infile_fd = None test_infile_fd = None try: ansfile_fd = os.open(ans_path, os.O_RDONLY | os.O_CLOEXEC) except FileNotFoundError: ansfile_fd = None outfile_fd = os.open(output_path, \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o400) os.close(os.open(verdict_path, \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o400)) with StackContext(Privilege.fullaccess): os.chown(output_path, check_uid, check_gid) os.chown(verdict_path, check_uid, check_gid) inpipe_fd = os.pipe2(os.O_CLOEXEC) outpipe_fd = os.pipe2(os.O_CLOEXEC) # Set file descriptor mapping. check_fdmap = { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, } test_fdmap = { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, } if check_infile_fd is not None: check_fdmap[metadata['redir_check']['testin']] = check_infile_fd if ansfile_fd is not None: check_fdmap[metadata['redir_check']['ansin']] = ansfile_fd check_fdmap[metadata['redir_check']['pipein']] = inpipe_fd[1] check_fdmap[metadata['redir_check']['pipeout']] = outpipe_fd[0] try: del check_fdmap[-1] except KeyError: pass if test_infile_fd is not None: test_fdmap[metadata['redir_test']['testin']] = test_infile_fd test_fdmap[metadata['redir_test']['testout']] = outfile_fd test_fdmap[metadata['redir_test']['pipein']] = inpipe_fd[0] test_fdmap[metadata['redir_test']['pipeout']] = outpipe_fd[1] try: del test_fdmap[-1] except KeyError: pass check_task_id = PyExt.create_task(self.build_relpath + '/check', \ [], \ [ 'PATH=/usr/bin:/bin', 'HOME=%s'%self.build_relpath, 'LANG=en_US.UTF-8', 'OUTPUT=%s'%output_relpath, 'VERDICT=%s'%verdict_relpath, ], \ check_fdmap, \ self.build_relpath, self.container_path, \ check_uid, check_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if check_task_id is None: callback((False, (0, 0, PyExt.DETECT_INTERNALERR))) return PyExt.start_task(check_task_id, _check_done_cb, _check_started_cb) test_task_id = PyExt.create_task(exe_relpath, argv, envp, \ test_fdmap, \ test_relpath, self.container_path, \ test_uid, test_gid, timelimit, memlimit, \ PyExt.RESTRICT_LEVEL_HIGH) if test_task_id is None: callback((False, (0, 0, PyExt.DETECT_INTERNALERR))) return PyExt.start_task(test_task_id, _test_done_cb, _test_started_cb)
def build(self, build_ugid, res_path, callback=None): '''Build environment. Args: build_ugid ((int, int)): Build UID/GID. res_path (string): Resource path. callback (function): Callback of return_future. Returns: None ''' def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' if stat['detect_error'] == PyExt.DETECT_NONE: callback(True) else: callback(False) build_uid, build_gid = build_ugid # Prepare build environment. FileUtils.copydir(res_path + '/check', self.build_path) FileUtils.setperm(self.build_path, build_uid, build_gid) with StackContext(Privilege.fullaccess): os.chmod(self.build_path, mode=0o770) with StackContext(Privilege.fileaccess): if not os.path.isfile(self.build_path + '/build'): callback(True) return # Build. task_id = PyExt.create_task(self.build_relpath + '/build', \ [], \ [ 'PATH=/usr/bin:/bin', 'TMPDIR=%s'%self.build_relpath, 'HOME=%s'%self.build_relpath, 'LANG=en_US.UTF-8' ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, }, \ self.build_relpath, 'container/standard', \ build_uid, build_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(False) else: PyExt.start_task(task_id, _done_cb)
def comp_python(self, callback=None): '''Python3.4 compile. Args: callback (function): Callback of return_future. Returns: None ''' def _started_cb(task_id): '''Started callback. Close unused file descriptors after the task is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal errpipe_fd os.close(errpipe_fd) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal compile_path with StackContext(Privilege.fileaccess): verfile = open(compile_path + '/verdict.txt', 'r') verdict = verfile.read(140) verfile.close() callback((stat['detect_error'], verdict)) compile_path = self.chal_path + '/compile' with StackContext(Privilege.fileaccess): os.mkdir(compile_path, mode=0o770) shutil.copyfile(self.code_path, compile_path + '/test.py', \ follow_symlinks=False) FileUtils.setperm(compile_path, self.compile_uid, self.compile_gid) with StackContext(Privilege.fileaccess): errpipe_fd = os.open(compile_path + '/verdict.txt', \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o440) task_id = PyExt.create_task('/usr/bin/python3.4', \ [ '-m', 'py_compile', './test.py' ], \ [ 'HOME=/home/%d/compile'%self.uniqid, 'LANG=en_US.UTF-8' ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: errpipe_fd, }, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: os.close(errpipe_fd) callback((PyExt.DETECT_INTERNALERR, '')) return PyExt.start_task(task_id, _done_cb, _started_cb)
def comp_make(self, callback): '''Makefile compile. Args: callback (function): Callback of return_future. Returns: None ''' def _copy_fn(src, dst, follow_symlinks=True): '''Copytree helper function. Args: src (string): Source path. dst (string): Destination path. follow_symlinks: Follow symbolic link or not. Returns: None ''' shutil.copy(src, dst, follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(dst, self.compile_uid, self.compile_gid) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' callback(stat['detect_error']) with StackContext(Privilege.fileaccess): make_path = self.chal_path + '/compile' shutil.copytree(self.res_path + '/make', make_path, symlinks=True, \ copy_function=_copy_fn) shutil.copyfile(self.code_path, make_path + '/main.cpp', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(make_path, self.compile_uid, self.compile_gid) os.chmod(make_path, mode=0o770) task_id = PyExt.create_task('/usr/bin/make', \ [], \ [ 'PATH=/usr/bin', 'TMPDIR=/home/%d/compile'%self.uniqid, 'OUT=./a.out', ], \ StdChal.null_fd, StdChal.null_fd, StdChal.null_fd, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 256 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: callback(-1) else: PyExt.start_task(task_id, _done_cb)
def judge(self, src_path, exe_relpath, argv, envp, check_ugid, test_ugid, \ test_relpath, test_param, metadata, callback=None): '''I/O redirect special judge. Args: src_path (string): Executable source path. exe_relpath (string): Executable or interpreter path in the sandbox. argv ([string]): List of arguments. envp ([string]): List of environment variables. check_ugid (int, int): Check UID/GID. test_ugid (int, int): Test UID/GID. test_relpath (string): Test relative path. test_param (dict): Test parameters. metadata (dict): Metadata. callback (function): Callback of return_future. Returns: None ''' def _check_started_cb(task_id): '''Check started callback. Close unused file descriptors after the check is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal inpipe_fd nonlocal outpipe_fd nonlocal ansfile_fd nonlocal check_infile_fd os.close(inpipe_fd[1]) os.close(outpipe_fd[0]) if ansfile_fd is not None: os.close(ansfile_fd) if check_infile_fd is not None: os.close(check_infile_fd) def _test_started_cb(task_id): '''Test started callback. Close unused file descriptors after the test is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal inpipe_fd nonlocal outpipe_fd nonlocal outfile_fd nonlocal test_infile_fd os.close(inpipe_fd[0]) os.close(outpipe_fd[1]) os.close(outfile_fd) if test_infile_fd is not None: os.close(test_infile_fd) def _done_cb(): '''Done callback.''' nonlocal result_stat nonlocal result_pass nonlocal verdict_path if result_pass is not None and result_stat is not None: with StackContext(Privilege.fileaccess): verfile = open(verdict_path, 'r') verdict = verfile.read(140) verfile.close() callback((result_pass, result_stat, verdict)) return def _check_done_cb(task_id, stat): '''Check done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_pass if stat['detect_error'] == PyExt.DETECT_NONE: result_pass = True else: result_pass = False _done_cb() def _test_done_cb(task_id, stat): '''Test done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_stat result_stat = (stat['utime'], stat['peakmem'], stat['detect_error']) _done_cb() result_stat = None result_pass = None in_path = test_param['in'] ans_path = test_param['ans'] timelimit = test_param['timelimit'] memlimit = test_param['memlimit'] check_uid, check_gid = check_ugid test_uid, test_gid = test_ugid test_path = self.container_path + test_relpath output_relpath = test_relpath + '/output.txt' output_path = self.container_path + output_relpath verdict_relpath = test_relpath + '/verdict.txt' verdict_path = self.container_path + verdict_relpath # Prepare test environment. with StackContext(Privilege.fileaccess): os.mkdir(test_path, mode=0o771) shutil.copyfile(src_path, test_path + '/a.out', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(test_path + '/a.out', test_uid, test_gid) os.chmod(test_path + '/a.out', 0o500) # Prepare I/O. with StackContext(Privilege.fileaccess): try: check_infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) test_infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) except (FileNotFoundError, TypeError): check_infile_fd = None test_infile_fd = None try: ansfile_fd = os.open(ans_path, os.O_RDONLY | os.O_CLOEXEC) except (FileNotFoundError, TypeError): ansfile_fd = None outfile_fd = os.open(output_path, \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o400) os.close(os.open(verdict_path, os.O_CREAT | os.O_CLOEXEC, mode=0o640)) with StackContext(Privilege.fullaccess): os.chown(output_path, check_uid, check_gid) os.chown(verdict_path, check_uid, check_gid) inpipe_fd = os.pipe2(os.O_CLOEXEC) outpipe_fd = os.pipe2(os.O_CLOEXEC) # Set file descriptor mapping. check_fdmap = { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, } test_fdmap = { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: StdChal.null_fd, } if check_infile_fd is not None: check_fdmap[metadata['redir_check']['testin']] = check_infile_fd if ansfile_fd is not None: check_fdmap[metadata['redir_check']['ansin']] = ansfile_fd check_fdmap[metadata['redir_check']['pipein']] = inpipe_fd[1] check_fdmap[metadata['redir_check']['pipeout']] = outpipe_fd[0] try: del check_fdmap[-1] except KeyError: pass if test_infile_fd is not None: test_fdmap[metadata['redir_test']['testin']] = test_infile_fd test_fdmap[metadata['redir_test']['testout']] = outfile_fd test_fdmap[metadata['redir_test']['pipein']] = inpipe_fd[0] test_fdmap[metadata['redir_test']['pipeout']] = outpipe_fd[1] try: del test_fdmap[-1] except KeyError: pass check_task_id = PyExt.create_task(self.build_relpath + '/check', \ [], \ [ 'PATH=/usr/bin:/bin', 'HOME=%s'%self.build_relpath, 'LANG=en_US.UTF-8', 'OUTPUT=%s'%output_relpath, 'VERDICT=%s'%verdict_relpath, ], \ check_fdmap, \ self.build_relpath, self.container_path, \ check_uid, check_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if check_task_id is None: callback((False, (0, 0, PyExt.DETECT_INTERNALERR), '')) return PyExt.start_task(check_task_id, _check_done_cb, _check_started_cb) test_task_id = PyExt.create_task(exe_relpath, argv, envp, \ test_fdmap, \ test_relpath, self.container_path, \ test_uid, test_gid, timelimit, memlimit, \ PyExt.RESTRICT_LEVEL_HIGH) if test_task_id is None: callback((False, (0, 0, PyExt.DETECT_INTERNALERR), '')) return PyExt.start_task(test_task_id, _test_done_cb, _test_started_cb)
def comp_cxx(self, callback=None): '''GCC, Clang compile. Args: callback (function): Callback of return_future. Returns: None ''' def _started_cb(task_id): '''Started callback. Close unused file descriptors after the task is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal errpipe_fd os.close(errpipe_fd) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal compile_path with StackContext(Privilege.fileaccess): verfile = open(compile_path + '/verdict.txt', 'rb') # To fix decoding error. # Force convert the binary string to string temporarily. verdict = ''.join(chr(c) for c in verfile.read(140)) verfile.close() callback((stat['detect_error'], verdict)) compile_path = self.chal_path + '/compile' with StackContext(Privilege.fileaccess): os.mkdir(compile_path, mode=0o770) shutil.copyfile(self.code_path, compile_path + '/test.cpp', \ follow_symlinks=False) FileUtils.setperm(compile_path, self.compile_uid, self.compile_gid) with StackContext(Privilege.fileaccess): errpipe_fd = os.open(compile_path + '/verdict.txt', \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o440) if self.comp_typ == 'g++': compiler = '/usr/bin/g++' elif self.comp_typ == 'clang++': compiler = '/usr/bin/clang++' task_id = PyExt.create_task(compiler, \ [ '-O2', '-std=c++14', '-o', './a.out', './test.cpp', ], \ [ 'PATH=/usr/bin:/bin', 'TMPDIR=/home/%d/compile'%self.uniqid, ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: errpipe_fd, }, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: os.close(errpipe_fd) callback((PyExt.DETECT_INTERNALERR, '')) return PyExt.start_task(task_id, _done_cb, _started_cb)
def comp_python(self, callback=None): '''Python3.4 compile. Args: callback (function): Callback of return_future. Returns: None ''' def _started_cb(task_id): '''Started callback. Close unused file descriptors after the task is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal errpipe_fd os.close(errpipe_fd) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal compile_path with StackContext(Privilege.fileaccess): verfile = open(compile_path + '/verdict.txt', 'r') verdict = verfile.read(140) verfile.close() callback((stat['detect_error'], verdict)) compile_path = self.chal_path + '/compile' with StackContext(Privilege.fileaccess): os.mkdir(compile_path, mode=0o770) shutil.copyfile(self.code_path, compile_path + '/test.py', \ follow_symlinks=False) FileUtils.setperm(compile_path, self.compile_uid, self.compile_gid) with StackContext(Privilege.fileaccess): errpipe_fd = os.open(compile_path + '/verdict.txt', \ os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC, mode=0o440) task_id = PyExt.create_task('/usr/bin/python3.4', \ [ '-m', 'py_compile', './test.py' ], \ [ 'HOME=/home/%d/compile'%self.uniqid, 'LANG=en_US.UTF-8' ], \ { 0: StdChal.null_fd, 1: StdChal.null_fd, 2: errpipe_fd, }, \ '/home/%d/compile'%self.uniqid, 'container/standard', \ self.compile_uid, self.compile_gid, 60000, 1024 * 1024 * 1024, \ PyExt.RESTRICT_LEVEL_LOW) if task_id is None: os.close(errpipe_fd) callback(PyExt.DETECT_INTERNALERR) return PyExt.start_task(task_id, _done_cb, _started_cb)
def initialize(self, **kwargs): '''Initialize.''' super().initialize(impl=PyExt.EvPoll(), **kwargs)
def judge_diff(self, src_path, exe_path, argv, envp, in_path, ans_path, \ timelimit, memlimit, callback=None): '''Diff judge. Args: src_path (string): Executable source path. exe_path (string): Executable or interpreter path in the sandbox. argv ([string]): List of arguments. envp ([string]): List of environment variables. in_path (string): Input file path. ans_path (string): Answer file path. timelimit (int): Timelimit. memlimit (int): Memlimit. callback (function): Callback of return_future. Returns: None ''' def _started_cb(task_id): '''Started callback. Close unused file descriptors after the task is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal infile_fd nonlocal outpipe_fd os.close(infile_fd) os.close(outpipe_fd[1]) IOLoop.instance().add_handler(outpipe_fd[0], _diff_out, \ IOLoop.READ | IOLoop.ERROR) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_stat nonlocal result_pass result_stat = (stat['utime'], stat['peakmem'], stat['detect_error']) if result_pass is not None: callback((result_pass, result_stat)) def _diff_out(evfd, events): '''Diff the output of the task. Args: evfd (int): Event file descriptor. events (int): Event flags. Returns: None ''' nonlocal outpipe_fd nonlocal ansfile nonlocal result_stat nonlocal result_pass end_flag = False if events & IOLoop.READ: while True: try: data = os.read(outpipe_fd[0], 65536) except BlockingIOError: break ansdata = ansfile.read(len(data)) if data != ansdata: result_pass = False end_flag = True break if len(ansdata) == 0: if len(ansfile.read(1)) == 0: result_pass = True else: result_pass = False end_flag = True break if (events & IOLoop.ERROR) or end_flag: if result_pass is None: if len(ansfile.read(1)) == 0: result_pass = True else: result_pass = False IOLoop.instance().remove_handler(evfd) os.close(outpipe_fd[0]) ansfile.close() if result_stat is not None: callback((result_pass, result_stat)) judge_uid, judge_gid = StdChal.get_restrict_ugid() # Prepare I/O and stat. with StackContext(Privilege.fileaccess): infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) ansfile = open(ans_path, 'rb') outpipe_fd = os.pipe2(os.O_CLOEXEC) fcntl.fcntl(outpipe_fd[0], fcntl.F_SETFL, os.O_NONBLOCK) result_stat = None result_pass = None # Prepare judge environment. with StackContext(Privilege.fileaccess): judge_path = self.chal_path + '/run_%d'%judge_uid os.mkdir(judge_path, mode=0o771) shutil.copyfile(src_path, judge_path + '/a.out', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(judge_path + '/a.out', judge_uid, judge_gid) os.chmod(judge_path + '/a.out', 0o500) task_id = PyExt.create_task(exe_path, argv, envp, \ { 0: infile_fd, 1: outpipe_fd[1], 2: outpipe_fd[1], }, \ '/home/%d/run_%d'%(self.uniqid, judge_uid), 'container/standard', \ judge_uid, judge_gid, timelimit, memlimit, \ PyExt.RESTRICT_LEVEL_HIGH) if task_id is None: os.close(infile_fd) os.close(outpipe_fd[0]) os.close(outpipe_fd[1]) ansfile.close() callback((False, (0, 0, PyExt.DETECT_INTERNALERR))) else: PyExt.start_task(task_id, _done_cb, _started_cb)
def judge_diff(self, src_path, exe_path, argv, envp, in_path, ans_path, \ timelimit, memlimit, callback): '''Diff judge. Args: src_path (string): Executable source path. exe_path (string): Executable or interpreter path in the sandbox. argv ([string]): List of arguments. envp ([string]): List of environment variables. in_path (string): Input file path. ans_path (string): Answer file path. timelimit (int): Timelimit. memlimit (int): Memlimit. callback (function): Callback of return_future. Returns: None ''' with StackContext(Privilege.fileaccess): infile_fd = os.open(in_path, os.O_RDONLY | os.O_CLOEXEC) ansfile = open(ans_path, 'rb') outpipe_fd = os.pipe2(os.O_CLOEXEC) fcntl.fcntl(outpipe_fd[0], fcntl.F_SETFL, os.O_NONBLOCK) result_stat = None result_pass = None def _started_cb(task_id): '''Started callback. Close unused file descriptor after the task is started. Args: task_id (int): Task ID. Returns: None ''' nonlocal infile_fd nonlocal outpipe_fd os.close(infile_fd) os.close(outpipe_fd[1]) def _done_cb(task_id, stat): '''Done callback. Args: task_id (int): Task ID. stat (dict): Task result. Returns: None ''' nonlocal result_stat nonlocal result_pass result_stat = (stat['utime'], stat['peakmem'], stat['detect_error']) if result_pass is not None: callback((result_pass, result_stat)) def _diff_out(evfd, events): '''Diff the output of the task. Args: evfd (int): Event file descriptor. events (int): Event flags. Returns: None ''' nonlocal outpipe_fd nonlocal ansfile nonlocal result_stat nonlocal result_pass end_flag = False if events & IOLoop.READ: while True: try: data = os.read(outpipe_fd[0], 65536) except BlockingIOError: break ansdata = ansfile.read(len(data)) if data != ansdata: result_pass = False end_flag = True break if len(ansdata) == 0: if len(ansfile.read(1)) == 0: result_pass = True else: result_pass = False end_flag = True break if (events & IOLoop.ERROR) or end_flag: if result_pass is None: if len(ansfile.read(1)) == 0: result_pass = True else: result_pass = False IOLoop.instance().remove_handler(evfd) os.close(outpipe_fd[0]) ansfile.close() if result_stat is not None: callback((result_pass, result_stat)) StdChal.last_judge_uid += 1 judge_uid = StdChal.last_judge_uid judge_gid = judge_uid with StackContext(Privilege.fileaccess): judge_path = self.chal_path + '/run_%d' % judge_uid os.mkdir(judge_path, mode=0o771) shutil.copyfile(src_path, judge_path + '/a.out', \ follow_symlinks=False) with StackContext(Privilege.fullaccess): os.chown(judge_path + '/a.out', judge_uid, judge_gid) os.chmod(judge_path + '/a.out', 0o500) IOLoop.instance().add_handler(outpipe_fd[0], _diff_out, \ IOLoop.READ | IOLoop.ERROR) task_id = PyExt.create_task(exe_path, argv, envp, \ infile_fd, outpipe_fd[1], outpipe_fd[1], \ '/home/%d/run_%d'%(self.uniqid, judge_uid), 'container/standard', \ judge_uid, judge_gid, timelimit, memlimit, \ PyExt.RESTRICT_LEVEL_HIGH) if task_id is None: callback((False, (0, 0, PyExt.DETECT_INTERNALERR))) PyExt.start_task(task_id, _done_cb, _started_cb)