Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/DMOJ/judge-server
Browse files Browse the repository at this point in the history
  • Loading branch information
hieplpvip committed Jun 6, 2024
2 parents a2f7218 + 8bc8bf3 commit b146260
Show file tree
Hide file tree
Showing 26 changed files with 110 additions and 29 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h1 align="center">
<img src="https://avatars2.githubusercontent.com/u/6934864?v=3&s=1000" width="120px">
<img src="https://github.com/DMOJ/online-judge/blob/master/logo.png?raw=true" width="120px">
<br>
DMOJ Judge
</h1>
Expand Down Expand Up @@ -56,6 +56,7 @@ Supported languages include:
The judge can also grade in the languages listed below:

* Ada
* Algol 68
* AWK
* Brain\*\*\*\*
* COBOL
Expand Down
2 changes: 1 addition & 1 deletion dmoj/cptbox/filesystem_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def _finalize_directory_rule(self, node: Dir, rule: Union[ExactDir, RecursiveDir

# `path` should be a normalized path
def check(self, path: str) -> bool:
assert os.path.abspath(path) == path, 'Must pass a normalized, absolute path to check'
assert os.path.abspath(path) == path, f'Must pass a normalized, absolute path to check: passed {path}'
components = [] if path == '/' else path.split('/')[1:]

node = self.root
Expand Down
24 changes: 15 additions & 9 deletions dmoj/cptbox/isolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,14 @@ def _access_check(self, debugger: Debugger, file: str, fs_jail: FilesystemPolicy

if normalized != real:
proc_dir = f'/proc/{debugger.tid}'
if real == proc_dir:
real = '/proc/self'
elif real.startswith(proc_dir):
real = os.path.join('/proc/self', os.path.relpath(real, proc_dir))
if real.startswith(proc_dir):
relpath = os.path.relpath(real, proc_dir)
if relpath == '.':
# Special-case the root /proc/self directory, otherwise the branch below generates '/proc/self/.'
# which will fail the FS jail check since abspath('/proc/self/.') = '/proc/self' != '/proc/self/.'.
real = '/proc/self'
else:
real = os.path.join('/proc/self', relpath)

if not fs_jail.check(real):
raise DeniedSyscall(ACCESS_EACCES, f'Denying {file}, real path {real}')
Expand Down Expand Up @@ -454,13 +458,15 @@ def get_full_path(self, debugger: Debugger, file: str, dirfd: int = AT_FDCWD) ->

def handle_kill(self, debugger: Debugger) -> None:
# Allow tgkill to execute as long as the target thread group is the debugged process
# libstdc++ seems to use this to signal itself, see <https://github.com/DMOJ/judge/issues/183>
if debugger.uarg0 != debugger.pid:
raise DeniedSyscall(ACCESS_EPERM, 'Cannot kill other processes')
# libstdc++ seems to use this to signal itself, see <https://github.com/DMOJ/judge/issues/18A3>
target = debugger.uarg0
if target != debugger.pid:
raise DeniedSyscall(ACCESS_EPERM, f'Cannot kill other processes (target={target}, self={debugger.pid})')

def handle_prlimit(self, debugger: Debugger) -> None:
if debugger.uarg0 not in (0, debugger.pid):
raise DeniedSyscall(ACCESS_EPERM, 'Cannot prlimit other processes')
target = debugger.uarg0
if target not in (0, debugger.pid):
raise DeniedSyscall(ACCESS_EPERM, f'Cannot prlimit other processes (target={target}, self={debugger.pid})')

def handle_prctl(self, debugger: Debugger) -> None:
PR_GET_DUMPABLE = 3
Expand Down
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ sys_mq_timedsend: int
sys_mq_timedsend_time64: int
sys_mq_unlink: int
sys_mremap: int
sys_mseal: int
sys_msgctl: int
sys_msgget: int
sys_msgrcv: int
Expand Down
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls/linux-arm.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,4 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls/linux-generic.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,4 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls/linux-generic32.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,4 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
2 changes: 2 additions & 0 deletions dmoj/cptbox/syscalls/linux-x32.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
450 set_mempolicy_home_node
451 cachestat
452 fchmodat2
453 map_shadow_stack
454 futex_wake
455 futex_wait
456 futex_requeue
Expand All @@ -323,6 +324,7 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
512 rt_sigaction
513 rt_sigreturn
514 ioctl
Expand Down
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls/linux-x64.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,4 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
1 change: 1 addition & 0 deletions dmoj/cptbox/syscalls/linux-x86.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,4 @@
459 lsm_get_self_attr
460 lsm_set_self_attr
461 lsm_list_modules
462 mseal
42 changes: 42 additions & 0 deletions dmoj/executors/ALGL68.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import List

from dmoj.cptbox.handlers import ACCESS_EACCES
from dmoj.executors.compiled_executor import CompiledExecutor


class Executor(CompiledExecutor):
ext = 'a'
command = 'a68g'

test_program = """
BEGIN
STRING input;
get(standin, input);
print((input, newline))
END
"""

data_grace = 131072
syscalls = [
('mkdir', ACCESS_EACCES),
('mkdirat', ACCESS_EACCES),
'alarm',
'setitimer',
]

def get_compile_args(self) -> List[str]:
command = self.get_command()
assert command is not None
assert self._code is not None
# This doesn't actually compile anything, but will generate useful
# output if the program is malformed.
return [command, '--norun', '--noportcheck', '--nopragmats', self._code]

def get_cmdline(self, **kwargs) -> List[str]:
command = self.get_command()
assert command is not None
assert self._code is not None
return [command, '--nowarnings', '--noportcheck', '--nopragmats', self._code]

def get_executable(self):
return self.get_command()
6 changes: 0 additions & 6 deletions dmoj/executors/GO.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import re
from typing import Dict, List

from dmoj.cptbox.filesystem_policies import ExactFile
from dmoj.error import CompileError
from dmoj.executors.base_executor import VersionFlags
from dmoj.executors.compiled_executor import CompiledExecutor
Expand All @@ -24,11 +23,6 @@ class Executor(CompiledExecutor):
command = 'go'
syscalls = ['mincore', 'mlock', 'setrlimit']
compiler_syscalls = ['copy_file_range', 'setrlimit']
fs = [
# Go will start without THP information, but has some tuning for when
# it is available -- so let's allow it to tell.
ExactFile('/sys/kernel/mm/transparent_hugepage/hpage_pmd_size'),
]
test_name = 'echo'
test_program = """\
package main
Expand Down
2 changes: 1 addition & 1 deletion dmoj/executors/HASK.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Executor(NullStdoutMixin, CompiledExecutor):
RecursiveDir('/proc/self/task'),
RecursiveDir('/var/lib/ghc'),
]
syscalls = ['timerfd_settime']
syscalls = ['pselect6', 'timerfd_settime']
nproc = -1

test_program = """\
Expand Down
1 change: 1 addition & 0 deletions dmoj/executors/PY2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
class Executor(PythonExecutor):
command = 'python'
command_paths = ['python2.7', 'python2', 'python']
pygments_traceback_lexer = 'py2tb'
test_program = """
import sys
if sys.version_info.major == 2:
Expand Down
1 change: 1 addition & 0 deletions dmoj/executors/PY3.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
class Executor(PythonExecutor):
command = 'python3'
command_paths = [f'python{i}' for i in ['3.6', '3.5', '3.4', '3.3', '3.2', '3.1', '3']]
pygments_traceback_lexer = 'py3tb'
test_program = """
import sys
if sys.version_info.major == 3:
Expand Down
1 change: 1 addition & 0 deletions dmoj/executors/PYPY.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class Executor(PythonExecutor):
command = 'pypy'
pygments_traceback_lexer = 'py2tb'
test_program = """
import sys
if sys.version_info.major == 2:
Expand Down
1 change: 1 addition & 0 deletions dmoj/executors/PYPY3.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

class Executor(PYPYExecutor):
command = 'pypy3'
pygments_traceback_lexer = 'py3tb'
test_program = """
import sys
if sys.version_info.major == 3:
Expand Down
5 changes: 1 addition & 4 deletions dmoj/executors/RKT.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
class Executor(CompiledExecutor):
ext = 'rkt'
fs = [RecursiveDir('/etc/racket'), ExactFile('/etc/passwd'), ExactDir('/')]
compiler_read_fs = [
RecursiveDir('/etc/racket'),
RecursiveDir('~/.local/share/racket'),
]
compiler_read_fs = [RecursiveDir('~/.local/share/racket')]

command = 'racket'

Expand Down
3 changes: 3 additions & 0 deletions dmoj/executors/base_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
ExactDir('/sys/devices/system/cpu'),
ExactFile('/sys/devices/system/cpu/online'),
ExactFile('/etc/selinux/config'),
ExactFile('/sys/kernel/mm/transparent_hugepage/enabled'),
ExactFile('/sys/kernel/mm/transparent_hugepage/hpage_pmd_size'),
ExactFile('/sys/kernel/mm/transparent_hugepage/shmem_enabled'),
]

if sys.platform.startswith('freebsd'):
Expand Down
18 changes: 17 additions & 1 deletion dmoj/executors/compiled_executor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import fcntl
import hashlib
import os
import pty
import struct
import tempfile
import termios
from typing import Any, Dict, IO, List, Optional, Tuple, Union


Expand Down Expand Up @@ -107,8 +110,16 @@ def get_compile_env(self) -> Optional[Dict[str, str]]:
def get_compile_popen_kwargs(self) -> Dict[str, Any]:
return {}

def get_compiler_read_fs(self) -> List[FilesystemAccessRule]:
return self.get_fs() + self.compiler_read_fs

def get_compiler_write_fs(self) -> List[FilesystemAccessRule]:
return self.get_write_fs() + self.compiler_write_fs

def get_compiler_security(self):
sec = CompilerIsolateTracer(tmpdir=self._dir, read_fs=self.compiler_read_fs, write_fs=self.compiler_write_fs)
sec = CompilerIsolateTracer(
tmpdir=self._dir, read_fs=self.get_compiler_read_fs(), write_fs=self.get_compiler_write_fs()
)
return self._add_syscalls(sec, self.compiler_syscalls)

def create_compile_process(self, args: List[str]) -> TracedPopen:
Expand All @@ -118,6 +129,11 @@ def create_compile_process(self, args: List[str]) -> TracedPopen:
#
# Emulate the streams of a process connected to a terminal: stdin, stdout, and stderr are all ptys.
_master, _slave = pty.openpty()

# Some runtimes helpfully try to word-wrap error messages by determining the width of the screen. Lie and say
# we're a 1024x1024 terminal, so they don't try wrapping to 1-column width.
fcntl.ioctl(_slave, termios.TIOCSWINSZ, struct.pack('HHHH', 1024, 1024, 0, 0))

# Some runtimes *cough cough* Swift *cough cough* actually check the environment variables too.
env = self.get_compile_env() or os.environ.copy()
env['TERM'] = 'xterm'
Expand Down
1 change: 0 additions & 1 deletion dmoj/executors/mono_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class MonoExecutor(CompiledExecutor):
data_grace = 65536
cptbox_popen_class = MonoTracedPopen
fs = [RecursiveDir('/etc/mono')]
compiler_read_fs = fs
# Mono sometimes forks during its crashdump procedure, but continues even if
# the call to fork fails.
syscalls = [
Expand Down
13 changes: 12 additions & 1 deletion dmoj/executors/python_executor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import builtins
import re
from collections import deque
from typing import Dict, List
from typing import Dict, List, Optional

from pygments import highlight
from pygments.formatters import Terminal256Formatter
from pygments.lexers import get_lexer_by_name

from dmoj.cptbox import TracedPopen
from dmoj.executors.base_executor import VersionFlags
Expand Down Expand Up @@ -29,6 +33,7 @@ class PythonExecutor(CompiledExecutor):
address_grace = 131072
data_grace = 2048
ext = 'py'
pygments_traceback_lexer: Optional[str] = None

def get_compile_args(self) -> List[str]:
command = self.get_command()
Expand All @@ -55,6 +60,12 @@ def get_env(self) -> Dict[str, str]:
env['PYTHONINTMAXSTRDIGITS'] = '0'
return env

def handle_compile_error(self, output: bytes) -> None:
if self.pygments_traceback_lexer:
lexer = get_lexer_by_name(self.pygments_traceback_lexer)
output = utf8bytes(highlight(utf8text(output), lexer, Terminal256Formatter()))
super().handle_compile_error(output)

def create_files(self, problem_id: str, source_code: bytes, *args, **kwargs) -> None:
super().create_files(problem_id, source_code, **kwargs)
self._loader = self._file('-loader.py')
Expand Down
2 changes: 1 addition & 1 deletion testsuite/check_memory_limit/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


def check(process_output: bytes, judge_output: bytes, *, result: Result, **kwargs) -> bool:
if result.max_memory > 16384:
if result.max_memory > 65536:
return False

return standard.check(process_output, judge_output, result=result, **kwargs)
2 changes: 1 addition & 1 deletion testsuite/check_memory_limit/tests/c_blank/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: C
time: 2
memory: 65536
memory: 262144
source: empty.c
expect: AC
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma GCC optimize "O0"

const int MN = 25 * 1024 * 1024;
const int MN = 100 * 1024 * 1024;
char arr[MN];

int main() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: CPP17
time: 2
memory: 65536
memory: 262144
source: bloat.cpp
expect: WA

0 comments on commit b146260

Please sign in to comment.