Compare commits

...

7 Commits

Author SHA1 Message Date
Thomas Hobson 37141e87f6
Merge pull request #624 from Brikaa/fix-job-cleanup-evasion-vulnerability
Fix job cleanup evasion vulnerability, improve job execution error handling
2023-10-09 10:49:47 +13:00
Thomas Hobson fb658e1921
Merge pull request #627 from Brikaa/improve-containers-stopping-performance
Improve containers stopping performance by handling SIGTERM (95% improvement)
2023-10-09 10:48:48 +13:00
Omar Brikaa 016a8c086f exec comment 2023-10-03 15:21:48 +03:00
Omar Brikaa fef00b96f1 Improve containers stopping performance by handling SIGTERM 2023-10-03 13:59:23 +03:00
Omar Brikaa 6a47869578 Comments explaining the try-catch flow 2023-09-16 21:37:09 +03:00
Omar Brikaa 040e19fdc2 Interactive execution: run job cleanup regardless of errors 2023-09-15 20:39:15 +03:00
Omar Brikaa fe2fc374aa Improve normal execution error handling
- Properly differentiate between bad requests and internal server errors
- Avoid clean up evasion by putting the cleanup in the finally block
2023-09-15 20:26:10 +03:00
6 changed files with 67 additions and 23 deletions

View File

@ -210,20 +210,27 @@ router.ws('/connect', async (ws, req) => {
if (job === null) {
job = await get_job(msg);
await job.prime();
try {
await job.prime();
ws.send(
JSON.stringify({
type: 'runtime',
language: job.runtime.language,
version: job.runtime.version.raw,
})
);
ws.send(
JSON.stringify({
type: 'runtime',
language: job.runtime.language,
version: job.runtime.version.raw,
})
);
await job.execute(event_bus);
await job.cleanup();
ws.close(4999, 'Job Completed');
await job.execute(event_bus);
} catch (error) {
logger.error(
`Error cleaning up job: ${job.uuid}:\n${error}`
);
throw error;
} finally {
await job.cleanup();
}
ws.close(4999, 'Job Completed'); // Will not execute if an error is thrown above
} else {
ws.close(4000, 'Already Initialized');
}
@ -265,9 +272,13 @@ router.ws('/connect', async (ws, req) => {
});
router.post('/execute', async (req, res) => {
let job;
try {
job = await get_job(req.body);
} catch (error) {
return res.status(400).json(error);
}
try {
const job = await get_job(req.body);
await job.prime();
let result = await job.execute();
@ -276,11 +287,17 @@ router.post('/execute', async (req, res) => {
result.run = result.compile;
}
await job.cleanup();
return res.status(200).send(result);
} catch (error) {
return res.status(400).json(error);
logger.error(`Error executing job: ${job.uuid}:\n${error}`);
return res.status(500).send();
} finally {
try {
await job.cleanup(); // This gets executed before the returns in try/catch
} catch (error) {
logger.error(`Error cleaning up job: ${job.uuid}:\n${error}`);
return res.status(500).send(); // On error, this replaces the return in the outer try-catch
}
}
});

View File

@ -35,7 +35,10 @@ expressWs(app);
}
}
});
fss.chmodSync(path.join(config.data_directory, globals.data_directories.jobs), 0o711)
fss.chmodSync(
path.join(config.data_directory, globals.data_directories.jobs),
0o711
);
logger.info('Loading packages');
const pkgdir = path.join(
@ -92,7 +95,12 @@ expressWs(app);
logger.debug('Calling app.listen');
const [address, port] = config.bind_address.split(':');
app.listen(port, address, () => {
const server = app.listen(port, address, () => {
logger.info('API server started on', config.bind_address);
});
process.on('SIGTERM', () => {
server.close();
process.exit(0)
});
})();

0
packages/bash/5.2.0/build.sh vendored Normal file → Executable file
View File

View File

@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y unzip autoconf build-essential libssl-d
rm -rf /var/lib/apt/lists/* && \
update-alternatives --install /usr/bin/python python /usr/bin/python3.7 2
ADD entrypoint.sh mkindex.sh /
ADD entrypoint.sh mkindex.sh serve.py /
ENTRYPOINT ["bash","/entrypoint.sh"]
CMD ["--no-build"]

View File

@ -27,7 +27,7 @@ do
echo "Done with package $pkg"
elif [[ $CI -eq 1 ]]; then
echo "Commit SHA: $pkg"
cd ..
echo "Changed files:"
git diff --name-only $pkg^1 $pkg
@ -52,8 +52,9 @@ echo "Index created"
if [[ $SERVER -eq 1 ]]; then
echo "Starting index server.."
python3 -m http.server
# We want the child process to replace the shell to handle signals
exec python3 /serve.py
else
echo "Skipping starting index server"
fi
exit 0
exit 0

18
repo/serve.py Normal file
View File

@ -0,0 +1,18 @@
import signal
import sys
import http.server
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
def signal_handler(sig, frame):
sys.exit(0)
signal.signal(signal.SIGTERM, signal_handler)
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()