Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Node.js executor for DMOJ #1143

Merged
merged 1 commit into from
Jan 22, 2024
Merged

Add Node.js executor for DMOJ #1143

merged 1 commit into from
Jan 22, 2024

Conversation

pxpeterxu
Copy link
Contributor

@pxpeterxu pxpeterxu commented Dec 21, 2023

Thanks again for maintaining DMOJ! It's a great project with a really solid security foundation.

Motivation

We wanted to use DMOJ for internal company events, and since our company's primary language is Javascript (using Node.js), we wanted to implement a version that used Node directly rather than using https://github.com/DMOJ/v8dmoj

This resolves issue #1136

Changes

  • Add a judge executor that will execute code written in Node.js
    • This was based on the Coffeescript executor, except with some newer syscalls added (e.g., io_uring)

Related PRs on other repositories

Testing

Deployed a judge server with this with the following Dockerfile:

FROM dmoj/runtimes-tier3

# Install Node from nodesource based on https://github.com/nodesource/distributions/tree/69a4558#installation-instructions
RUN apt-get install -y ca-certificates curl gnupg && mkdir -p /etc/apt/keyrings && { curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; } && { echo 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main' > /etc/apt/sources.list.d/nodesource.list; } && apt-get update && apt-get install -y nodejs

# The remainder of this file is copied from
# https://github.com/DMOJ/judge-server/blob/master/.docker/tier3/Dockerfile
RUN mkdir /judge /problems && cd /judge && \
	curl -L https://github.com/wanderlog/judge-server/archive/master.tar.gz | tar -xz --strip-components=1 && \
    python3 -m venv --prompt=DMOJ /env && \
	/env/bin/pip3 install cython && \
	/env/bin/pip3 install -e . && \
	/env/bin/python3 setup.py develop && \
	HOME=~judge . ~judge/.profile && \
	runuser -u judge -w PATH -- /env/bin/dmoj-autoconf -V > /judge-runtime-paths.yml && \
	echo '  crt_x86_in_lib32: true' >> /judge-runtime-paths.yml

Verified that test runs using this Dockerfile worked properly:

Screen capture

@dmoj-build
Copy link
Collaborator

Can one of the admins verify this patch?

@quantum5
Copy link
Member

Your code looks fairly good, but I have to ask: what's the point of this? If you look at your submission for the A Plus B problem, you'll note that you are doing a lot of I/O boilerplate, mostly because node.js is designed for stream-based I/O and not so much for line-based I/O. You also won't be able to use npm modules on the judge.

The V8JS runtime is the exact same JS engine except it comes with a bunch of line-based I/O functions that requires a lot less boilerplate to use.

@pxpeterxu
Copy link
Contributor Author

pxpeterxu commented Dec 21, 2023

Your code looks fairly good, but I have to ask: what's the point of this? If you look at your submission for the A Plus B problem, you'll note that you are doing a lot of I/O boilerplate, mostly because node.js is designed for stream-based I/O and not so much for line-based I/O. You also won't be able to use npm modules on the judge.

Good point -- I think the main goal of this was for our engineers to run the code they submit locally on their machines without having to install the https://github.com/DMOJ/v8dmoj client locally, since Node.js is already preinstalled on their machines and is pretty widely used! It does require somewhat more boilerplate in code, though we often provide this with the problem.

I'd understand if this is too different from the goals of the main DMOJ site though; let me know what might be helpful.

Copy link
Member

@quantum5 quantum5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some discussion, we've decided that Node.js is an okay addition after all.

dmoj/executors/NODEJS.py Outdated Show resolved Hide resolved
Comment on lines 11 to 19
# Start syscalls copied from COFFEE.py
'capget',
'eventfd2',
'newselect',
'sched_yield',
'select',
'setrlimit',
'statx',
# End syscalls copied from COFFEE.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we try trimming down this list? Also the comment is not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I ran /judge/.docker/entry test | grep NODEJS multiple times while commenting out these, and it seems like we only need capget and eventfd2. I left these two (and shutdown) in.

dmoj/executors/NODEJS.py Outdated Show resolved Hide resolved
dmoj/executors/NODEJS.py Outdated Show resolved Hide resolved
@pxpeterxu
Copy link
Contributor Author

@quantum5 Thanks again for the review and happy new year! I think I've addressed all comments; can you please take a look?

Also, if you can check the associated PRs, that'd be great too:

README.md Outdated Show resolved Hide resolved
@Xyene
Copy link
Member

Xyene commented Jan 7, 2024

It looks like lint failed, but otherwise this looks good to me.

Once you've resolved that, could you please rebase and squash your commits? After that we should be good to merge.

@murtadha
Copy link

I'm eagerly waiting for this PR to be merged as our community has also been asking for the ability to run JS code via Node.js for exactly the same reason @pxpeterxu mentioned.

Please let me know if there is anything I can do to help get this merged ASAP 🙏

dmoj/executors/NODEJS.py Outdated Show resolved Hide resolved
dmoj/executors/NODEJS.py Outdated Show resolved Hide resolved
@pxpeterxu
Copy link
Contributor Author

@int-y1 I fixed the lint errors! Hopefully this is ready to merge now, but let me know if there are any other changes (sorry, it's been a busy few weeks!)

@Xyene
Copy link
Member

Xyene commented Jan 22, 2024

Thanks, could you please rebase and squash your commits into one?

@pxpeterxu pxpeterxu force-pushed the master branch 2 times, most recently from 8c44618 to 7bfc8c0 Compare January 22, 2024 05:11
@pxpeterxu
Copy link
Contributor Author

Thanks, could you please rebase and squash your commits into one?

Just done! Also, I didn't realize this project started at Don Mills C.I. -- I went there way back too! (Graduated 2010)

@Xyene
Copy link
Member

Xyene commented Jan 22, 2024

Wow, small world!

@codecov-commenter
Copy link

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (c70e803) 82.91% compared to head (7bfc8c0) 82.14%.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1143      +/-   ##
==========================================
- Coverage   82.91%   82.14%   -0.78%     
==========================================
  Files         141      142       +1     
  Lines        5373     5392      +19     
==========================================
- Hits         4455     4429      -26     
- Misses        918      963      +45     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Xyene
Copy link
Member

Xyene commented Jan 22, 2024

Looks like this failed CI because of

WARNING:dmoj.cptbox:Protection fault on: 330 (sys_pkey_alloc)
WARNING:dmoj.cptbox:Arg0: 0x0000000000000000
WARNING:dmoj.cptbox:Arg1: 0x0000000000000001
WARNING:dmoj.cptbox:Arg2: 0x0000000000000001
WARNING:dmoj.cptbox:Arg3: 0x0000150daed57188
WARNING:dmoj.cptbox:Arg4: 0x0000000000000000
WARNING:dmoj.cptbox:Arg5: 0x0000000000000000

We should be able to just allow it, seems like it's part of some CFI protection in V8:

@pxpeterxu
Copy link
Contributor Author

Looks like this failed CI because of

WARNING:dmoj.cptbox:Protection fault on: 330 (sys_pkey_alloc)
WARNING:dmoj.cptbox:Arg0: 0x0000000000000000
WARNING:dmoj.cptbox:Arg1: 0x0000000000000001
WARNING:dmoj.cptbox:Arg2: 0x0000000000000001
WARNING:dmoj.cptbox:Arg3: 0x0000150daed57188
WARNING:dmoj.cptbox:Arg4: 0x0000000000000000
WARNING:dmoj.cptbox:Arg5: 0x0000000000000000

We should be able to just allow it, seems like it's part of some CFI protection in V8:

* https://man7.org/linux/man-pages/man7/pkeys.7.html

* https://docs.google.com/document/d/1O2jwK4dxI3nRcOJuPYkonhTkNQfbmwdvxQMyXgeaRHo/edit#heading=h.bvaojj9fu6hc

I added a whitelist here, and it seems to be working: https://github.com/wanderlog/judge-server/actions/runs/7618060649

Force-pushed an update to this branch too

Copy link
Member

@Xyene Xyene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@Xyene Xyene merged commit f276790 into DMOJ:master Jan 22, 2024
9 checks passed
@Xyene Xyene mentioned this pull request Jan 22, 2024
@yanngv29
Copy link

yanngv29 commented Jan 27, 2024

not sure if this is the same problem than 5 day ago but i have got error today with dmoj-autoconf:

Auto-configuring NODEJS: Protection fault on: 331 (sys_pkey_free)
Arg0: 0x0000000000000001
Arg1: 0x0000000000000001
Arg2: 0x0000000000000008
Arg3: 0xe74cfd037f6ee7e7
Arg4: 0x0000000000000007
Arg5: 0x000055555563db90

Adding 'pkey_free' to the white list do the tricks for me.

@Xyene
Copy link
Member

Xyene commented Jan 28, 2024

Thanks for the report, I've put together #1164.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants