Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .env.docker
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,11 @@ MAILPIT_UI_PORT=8025

# Auto-Judge Configuration
AUTOJUDGE_ENABLED=true
AUTOJUDGE_JAIL_PATH=/bocajail
AUTOJUDGE_SAFEEXEC_PATH=/usr/local/bin/safeexec
AUTOJUDGE_TIME_LIMIT=10
AUTOJUDGE_MEMORY_LIMIT=512
AUTOJUDGE_MAX_FILE_SIZE=100
AUTOJUDGE_OUTPUT_LIMIT=1024
AUTOJUDGE_COMPILE_TIMEOUT=30
AUTOJUDGE_USER=nobody
AUTOJUDGE_GROUP=nogroup

# Vite
VITE_APP_NAME="${APP_NAME}"
10 changes: 1 addition & 9 deletions Dockerfile.judge
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,7 @@ RUN addgroup -g 1000 -S judge && \
RUN mkdir -p /var/www/html/storage/app/judge \
&& mkdir -p /var/www/html/storage/app/problems \
&& mkdir -p /var/www/html/storage/app/runs \
&& mkdir -p /bocajail \
&& chown -R judge:judge /var/www/html \
&& chown -R judge:judge /bocajail

# Copy safeexec source and compile
COPY tools/safeexec.c /tmp/safeexec.c
RUN gcc -O2 -o /usr/local/bin/safeexec /tmp/safeexec.c 2>/dev/null || echo "safeexec not found, skipping" \
&& rm -f /tmp/safeexec.c \
&& chmod 4555 /usr/local/bin/safeexec 2>/dev/null || true
&& chown -R judge:judge /var/www/html

# Copy application files
COPY --chown=judge:judge . /var/www/html
Expand Down
32 changes: 2 additions & 30 deletions app/Services/AutoJudgeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
class AutoJudgeService
{
public string $workDir;
protected string $jailPath;
protected int $defaultTimeLimit;
protected int $defaultMemoryLimit;
protected string $safeExecPath;
protected string $bwrapPath;
protected bool $useBwrap;
protected array $sandboxPaths;
Expand All @@ -29,10 +27,8 @@ class AutoJudgeService
public function __construct()
{
$this->workDir = config('autojudge.work_dir', '/tmp/autojudge');
$this->jailPath = config('autojudge.jail_path', '/bocajail');
$this->defaultTimeLimit = config('autojudge.time_limit', 10);
$this->defaultMemoryLimit = config('autojudge.memory_limit', 512);
$this->safeExecPath = config('autojudge.safeexec_path', '/usr/bin/safeexec');
$this->bwrapPath = config('autojudge.bwrap_path', '/usr/bin/bwrap');
$this->useBwrap = config('autojudge.use_bwrap', true);
$this->sandboxPaths = config('autojudge.sandbox_paths', ['/usr', '/bin', '/sbin', '/lib', '/lib64', '/etc', '/opt', '/go']);
Expand Down Expand Up @@ -148,7 +144,8 @@ protected function roBindArgs(mixed $path): array
* Deliberately no `ulimit -v`: the JVM, Go and Rust runtimes reserve
* large virtual address ranges at startup and die under an address-space
* cap no matter how little they actually touch. Resident memory stays
* with safeexec (-m/-d) and the per-language {memory} flag.
* with the per-language {memory} flag (Java's -Xmx and friends); a
* real resident-memory cap needs cgroups, tracked in #86.
*/
protected function rlimitPrologue(array $options): string
{
Expand Down Expand Up @@ -417,18 +414,6 @@ protected function executeProgram(Run $run, string $runDir, string $inputFile, s
$command = $runCommand . " < {$inputFile} > {$outputFile} 2>&1";
}

// safeexec is a setuid-root helper: it escalates to root, then drops
// to the run directory's owner. bubblewrap mounts everything nosuid
// and sets no_new_privs by design, so inside the sandbox that
// escalation fails with EPERM and the run dies (exit 137, reported as
// TLE) regardless of what the submission does. The sandbox provides
// what safeexec was here for -- isolation, plus the rlimits applied
// in wrapWithBwrap -- so the two are mutually exclusive and safeexec
// only runs when the sandbox is off.
if (!$this->useBwrap && file_exists($this->safeExecPath)) {
$command = $this->wrapWithSafeExec($command, $timeLimit, $memoryLimit, $runDir);
}

// The test case input lives under storage/app/problems, i.e. inside
// the application root the sandbox does not mount. Bind this one
// file -- not the problems tree, which would hand submitted code
Expand Down Expand Up @@ -503,19 +488,6 @@ protected function executeProgram(Run $run, string $runDir, string $inputFile, s
];
}

protected function wrapWithSafeExec(string $command, int $timeLimit, int $memoryLimit, string $runDir): string
{
$memoryKb = $memoryLimit * 1024;

return "{$this->safeExecPath} " .
"-t {$timeLimit} " .
"-T " . ($timeLimit + 5) . " " .
"-m {$memoryKb} " .
"-d {$memoryKb} " .
"-f 10 " .
"-R {$runDir} " .
"-- {$command}";
}

protected function compareOutput(
string $expected,
Expand Down
37 changes: 0 additions & 37 deletions config/autojudge.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,7 @@

'enabled' => env('AUTOJUDGE_ENABLED', true),

/*
|--------------------------------------------------------------------------
| Jail Path
|--------------------------------------------------------------------------
|
| Path to the chroot jail for secure code execution.
| Set to null to run without jailing (not recommended for production).
|
*/
'jail_path' => env('AUTOJUDGE_JAIL_PATH', '/bocajail'),

/*
|--------------------------------------------------------------------------
| Safe Exec Path
|--------------------------------------------------------------------------
|
| Path to the safeexec binary for resource-limited execution.
|
*/
'safeexec_path' => env('AUTOJUDGE_SAFEEXEC_PATH', '/usr/bin/safeexec'),

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -80,25 +61,7 @@
*/
'compile_timeout' => env('AUTOJUDGE_COMPILE_TIMEOUT', 30),

/*
|--------------------------------------------------------------------------
| Judge User
|--------------------------------------------------------------------------
|
| System user to run submissions as for security.
|
*/
'judge_user' => env('AUTOJUDGE_USER', 'nobody'),

/*
|--------------------------------------------------------------------------
| Judge Group
|--------------------------------------------------------------------------
|
| System group to run submissions as for security.
|
*/
'judge_group' => env('AUTOJUDGE_GROUP', 'nogroup'),

/*
|--------------------------------------------------------------------------
Expand Down
Loading
Loading