Giter Site home page Giter Site logo

jobe's Introduction

JOBE

Version: 1.8.0, 9 October 2023

Author: Richard Lobb, University of Canterbury, New Zealand

Contributors: Tim Hunt, Fedor Lyanguzov, Kai-Cheung Leung, Marcus Klang

Introduction

Jobe (short for Job Engine) is a server that supports running of small compile-and-run jobs in a variety of programming languages. It was developed as a remote sandbox for use by CodeRunner, a Moodle question-type plugin that asks students to write code to some relatively simple specification. However, Jobe servers could be useful in a variety of other contexts, particularly in education.

A job specifies a programming language, the source code, the standard input to the run and an optional list of additional files. Jobe compiles the source code (if compilation is appropriate in the specified language) and runs it with the given input data. It returns a run_result object containing various status information plus the output and error output from the run.

The interface is via a RESTful API, that is documented here.

The languages C, C++, Python3, Python2, Octave, Java, Pascal and PHP are all built-in. Other languages can be added fairly easily although if using Jobe from CodeRunner it is usually even easier to write a Python-based question type that scripts the execution of the required language. See the CodeRunner documentation for an example.

The Computer Science quiz server at the University of Canterbury switched to exclusive use of the Jobe sandbox in early July 2014. Since then it has run many hundreds of thousands of Python3, C, Java and Octave jobs unattended with only a few minor bug fixes and security refinements.

Implementation status

The current version of Jobe (Version 1.7.1, May 2023) implements a subset of the originally documented API, sufficient for use by CodeRunner. It has been used for many years at the University of Canterbury for several years, running many millions of submissions. Jobe is also used by over 600 other CodeRunner sites around the world. It can be considered stable and secure, though it should be run only on a separate appropriately-firewalled server.

With reference to the original API spec, only immediate-mode runs are supported, with run results being returned with the response to the POST of the run requests. Run results are not retained by the server (unless run_spec.debug is true; see the API), so get_run_status always returns 404 not found.

File PUTs are supported but not POSTs. When used by CodeRunner, file IDs are MD5 checksums of the file contents.

Since version 1.6, the Jobe server cleans the file cache whenever available disk space drops below 5% of the disk size. It simply deletes all files that haven't been used for 2 days or more, so the server must have enough free disk space to stay below 95% full for at least two whole days of running. For CodeRunner clients this should not be a problem unless question authors enable large classes of students to attach large files to their submissions. Support files attached by question authors are unlikely to be a problem; a Jobe server at the University of Canterbury serving a large Moodle client with many thousands of questions accumulated only 200 MB of support files over several years.

For sandboxing, Jobe uses the domjudge runguard program to run student jobs with restrictions on resource allocation (memory, processes, cpu time) as a low-privileged user. However it does not restrict any system calls.

Programs may write binary output but the results are returned to the caller JSON-encoded, which requires UTF-8 strings. To avoid crashing the json-encoder, the standard output and standard error output from the program are checked to see if they're valid utf-8. If so, they're returned unchanged. Otherwise, they're taken as 8-bit character streams; characters below '\x20' (the space character) and above '\x7E' are replaced by C-style hexadecimal encodings (e.g. '\x8E') except for newlines which are passed through directly, and tabs and returns which are replaced with '\t' and '\r' respectively.

If Jobe is to correctly handle utf-8 output from programs, the Apache LANG environment variable must be set to a UTF-8 compatible value. See the section Setting the locale below.

Jobe is implemented using Ellis Lab's codeigniter plus the RESTserver plugin originally written by Phil Sturgeon and now maintained by Chris Kacerguis.

Installation

WARNING Jobe is primarily intended for use on a server that is firewalled to allow connections from authorised client machines only. If you install it on a machine without such firewalling, and do not control access with API keys (see later), anyone will be able to connect to your machine and run their own code on it! CAVEAT EMPTOR!

NOTE: a video walkthrough of the process of setting up a Jobe server on a DigitalOcean droplet is here.

Installation on Ubuntu 22.04 systems should be straightforward but installation on other flavours of Linux or on systems with non-standard configurations may require Linux administrator skills.

An alternative approach, and probably the simplest way to get up and running, is to use the JobeInABox Docker image, which should be runnable with a single terminal command on any Linux system that has docker installed. Thanks to David Bowes for the initial work on this. Please be aware that while this Docker image has been around for a couple of years the developer has not himself used it in a production environment. Feedback is welcomed. The steps to fire up a Jobe Server on Digital Ocean using JobeInAbox are given below in section Setting up a JobeInAbox Digital Ocean server.

However, for security and performance reasons it it strongly recommended to run Jobe on a dedicated server, even when running it in a container.

Jobe runs only on Linux, which must have the Apache web server installed and running. PHP must have been compiled with the System V Semaphone and shared-memory functions enabled (see here)[http://www.php.net/manual/en/sem.setup.php], but that's the norm. Access Control Lists (ACLs) must be enabled; they normally are but if the /home/jobe directory lands up on a mounted volume, you may need to explicitly enable ACLs in the mount command or in /etc/fstab. The Python3 and the C development system must also be installed.

Installing the necessary dependencies

On Ubuntu-22.04, the commands to set up all the necessary web tools plus all currently-supported languages is the following:

sudo apt-get install apache2 php libapache2-mod-php php-cli\
    php-mbstring nodejs git python3 build-essential default-jdk\
    python3-pip fp-compiler acl sudo sqlite3

sudo apt-get install --no-install-suggests --no-install-recommends  octave

Octave and fp are required only if you need to run Octave or Pascal programs respectively.

If you wish to use API-authentication, which is generally pointless when setting up a private Jobe server, you also need the following:

sudo apt install mysql-server php-mysql

Similar commands should work on other Debian-based Linux distributions, although some differences are inevitable (e.g.: acl is preinstalled in Ubuntu, whereas in debian it must be installed).

A Raspberry Pi user reports that they additionally had to use the command

apt-get install --fix-missing

which may help with broken installs on other systems, too.

Setting up pylint (if you want it)

Firstly, install pylint for your required version of python (assumed here to be python3) with the command:

sudo -H python3 -m pip install pylint

You also need to build the /etc/pylintrc file to set the default options with one of the following commands, which must be run as root (don't just try prefixing the command with sudo, as the output redirection will fail).

Firstly try the command:

pylint --reports=no --score=n --generate-rcfile > /etc/pylintrc

If that gives you an error "no such option: --score" (which happens with older versions of pylint), try instead

pylint --reports=no --generate-rcfile > /etc/pylintrc

Installing Jobe

Clone the Jobe project in the web root directory WEBROOT (usually /var/www/html). Do not clone it elsewhere and attempt to add it to web root with symbolic links. That breaks this installer. In what follows, replace WEBROOT with either /var/www or /var/www/html as appropriate.

To clone Jobe:

cd WEBROOT
sudo git clone https://github.com/trampgeek/jobe.git

Installation is performed by the install script, which must be run as root so that it can add the required jobe run users (jobe00, jobe01, etc) and set-up a jobe-sudoers file in /etc/sudoers.d that allows the web server to execute the runguard program as root and to kill any residual jobe processes from the run.

Before running the install script, you might wish to edit the file

/var/www/html/jobe/application/config/config.php

Find the line

$config['jobe_max_users'] = 8;

and decide if that value, which sets the maximum number of jobs that can be run at once, is appropriate for your hardware set up. A rule of thumb is to set this to the number of cores on your machine, but if you plan on running lots of partially-I/O-bound jobs, you could consider larger numbers.

Having set that value to your satisfaction:

cd WEBROOT/jobe
sudo ./install

On Centos6 systems (and possibly early Centos7 releases) you should also comment out the line

Defaults requiretty

in /etc/sudoers. This was (reported as a bug)[https://bugzilla.redhat.com/show_bug.cgi?id=1196451] and was fixed in later RHEL releases.

Setting the locale

By default, Apache is configured to use the C locale. This means that programs generating, say, UTF-8 output will fail with an error

UnicodeEncodeError: 'ascii' codec can't encode character ...

If you wish to run UTF-8 code (recommended) you should find the line in the Apache envvars file (on Ubuntu systems this is to be found at /etc/apache2/envvars)

export LANG=C

and change it to either C.UTF-8 (which changes the charset to UTF-8 but leaves other locale settings unchanged) or to the required standard locale value, e.g.

export LANG=en_NZ.UTF-8

Make sure that whatever locale you use is installed on the Jobe server.

Then restart apache with the command

sudo service apache2 restart

Note:

  1. The comment in the Apache envvars file suggesting the use of the default locale probably won't work, as this will also just give you ASCII text.

  2. To take advantage of the UTF-8 capabilities in CodeRunner you will need to use Version 3.3 or later.

Setting up a JobeInAbox Digital Ocean server

For people wanting to get a Jobe server up in hurry, the following is probably the simplest approach. This uses a minimal Digital Ocean virtual machine, to run the Docker JobeInAbox image; you should increase memory and core for production servers. Other cloud servers, such as Amazon ECS, can of course also be used.

  1. Set yourself up with an account on Digital Ocean.
  2. Create new Droplet: Ubuntu 22.04. x64, minimal config (1GB CPI, 25GB disk)
  3. Connect to the server with an SSH client.
  4. Install docker (see https://phoenixnap.com/kb/how-to-install-docker-on-ubuntu-18-04): sudo apt update; sudo apt install docker.io
  5. Launch JobeInABox with Docker: sudo docker run -d -p 80:80 --name jobe trampgeek/jobeinabox:latest

At this point you have a running Jobe server. You can check it's working by browsing to

http://<hostname>/jobe/index.php/restapi/languages

You should get presented with a JSON list of installed languages.

And you can connect your CodeRunner plugin to it by setting the new JobeServer IP number in the Admin panel of the plugin. You're in business!

All that remains is to firewall your new server so that only your Moodle server can use it, and so it can't itself open outgoing connections. For example:

sudo apt install ufw
sudo ufw default reject outgoing
sudo sudo ufw allow in 22/tcp
sudo ufw allow in proto tcp to any port 80 from <your moodle server IP>
sudo ufw enable

Testing the install

The program testsubmit.py allows you to test your jobe server. For information on how to use it run this command on the Jobe server:

python3 testsubmit.py --help

Testing general correctness

To test the installation, first try running the tester with the command

python3 testsubmit.py

The first time you run this command, the initial step of obtaining all the different versions of all language is slow, as it has to test-drive all compilers and interpreters. Be patient. Results are cached in a file in /tmp so subsequent runs will be much faster, at least until the next reboot, when the list is rebuilt.

All going well, you should then be able to copy the testsubmit.py file to any client machine that is allowed to access the jobe server and rerun the command with a line of the form

python3 testsubmit.py --host='jobe.somehow.somewhere' --port=4000

where the host and port are set to reference the jobe server.

Testing performance

To test the performance of your new Jobe server, run the testsubmit program on your client machine again, this time with a --perf command line argument, e.g.

python3 testsubmit.py --perf --host='jobe.somehow.somewhere' --port=4000

The test will print information on the maximum burst of C compile-and-run submissions the server can handle in isolation and the sustained rate of submissions over a 30 second window by default. The figures you get are upper bounds, since the program being used for testing is a minimal 'hello world' program. It's also possible that the Moodle server cannot deliver jobs to the Jobe server at the maximum rate.

Languages like C, PHP and nodejs have similar performance since the communication and server overheads dominate the performance. For slower languages like C++ and particularly Java however, you will much lower throughput. To test Java, for example, type add the argument 'java' to the above command, i.e.

python3 testsubmit.py --perf --host='jobe.somehow.somewhere' --port=4000 java

WARNING: you should not run the performance test on a live production server, as it repeatedly pushes the server into overload, which will result in other users' jobs also receiving server-overload errors.

Using Jobe

Usually Jobe is used as a server for Moodle CodeRunner questions. So once jobe has been installed and tested with testsubmit.py it can be used by CodeRunner questions by plugging the Jobe server hostname into the CodeRunner administrator settings, replacing the default value of jobe2.cosc.canterbury.ac.nz.

However, Jobe can also be used standalone. The simpletest.py program shows how it can be invoked from a Python client.

Note that the POST request payload must a JSON object with a run_spec attribute as specified in the document restapi.pdf. For example, the following POST data runs the classic C "Hello World" program:

{"run_spec": {"language_id": "c", "sourcefilename": "test.c", "sourcecode": "\n#include <stdio.h>\n\nint main() {\n    printf(\"Hello world\\n\");\n}\n"}}

The POST request must have the header

Content-type: application/json; charset-utf-8

and should be sent to a URL like

localhost/jobe/index.php/restapi/runs

For example, the following Linux curl command runs the C Hello World program:

curl -d '{"run_spec": {"language_id": "c", "sourcefilename": "test.c", "sourcecode": "\n#include <stdio.h>\n\nint main() {\n    printf(\"Hello world\\n\");\n}\n"}}' -H "Content-type: application/json; charset-utf-8"  localhost/jobe/index.php/restapi/runs

Updating Jobe

If you wish to update an existing version of Jobe to a new one, first put the the client Moodle server into maintenance mode. Reboot the Jobe server. Then cd into the Jobe directory, do a git pull to update the code, then run the installer with the --purge option, i.e.

sudo ./install --purge

Check that all is well by testing as in the section "Testing the install" above. Lastly take the Moodle server out of maintenance mode again.

Debugging

If you have problems installing Jobe, here are some things to check.

If the install script fails, check the error message. You should be able to read through the script and figure out what went wrong. Otherwise ...

  1. Check the install went OK:

  2. Make sure your webserver has read access to the entire jobe subtree.

  3. Make sure your webserver has write access to jobe/files

  4. Make sure there exist users jobe and jobe00 through jobe09.

  5. Make sure there is a directory /home/jobe/runs owned by jobe and writeable by the webserver. It should not be readable or writeable by all.

  6. Make sure there is a directory /var/log/jobe.

If the install appears OK but testsubmit.py fails:

  1. If you get messages "Bad result object", something is fundamentally broken. Start by rebooting your server, and make sure Apache is running, e.g. by browsing to http://<jobehost>.

  2. Try pointing your browser at http://<jobehost>/jobe/index.php/restapi/languages This should return a JSON list of languages. If not, you may at least get a readable error message.

  3. You are running testsubmit.py with Python3, right?

  4. Check the apache error log.

  5. If something unexpected happened with the actual run of a program, find the run in /home/jobe/runs and try executing the program manually. [The run directory contains the source file, the bash command used to run it, plus the compile output and (if it ran) the stderr and stdout outputs.

  6. Check for any error messages in /var/log/jobe/*.

  7. Turn on debug level of logging in jobe/application/config/config.php by setting the log_threshold to 2 (around line 183). You should now get screeds of log info in the directory /var/log/jobe. Most of this comes from the framework; look for lines beginning jobe. These are all issued by restapi.php in application/controllers, which is the top level handler for all http requests.

  8. If you are getting Overloaded errors, then you can display the in-memory locks on the Jobe users with this PHP one-liner:

      ("/var/www/html/jobe/application/libraries/LanguageTask.php", "j")), 1));```

If you still can't figure it out, email me (Richard Lobb; my gmail name is trampgeek).

An optional extra installation step

[For paranoid sysadmins only].

Submitted jobs can generally write files only into the temporary directory created for their run within the '/home/jobe/runs' directory. Exceptions to this rule are the /tmp, /var/tmp, /var/crash and /run/lock directories all of which conventionally can be written into by any Linux process.

The temporary working directory and any files in the writable directories mentioned above are deleted on the termination of the run. However, depending on the size of the various partitions and the allowed maximum run time, it might in principle be possible for a rogue process, or a deliberate attacker, to run the system out of disk space in a particular partition (probably /tmp, which is usually relatively small), before the job terminates. That could in turn impact upon other jobs in progress.

This possibility is considered very remote under normal circumstances. With typical run times of a few seconds, jobs time out long before they can fill up a main partition such as that housing /home/jobe. Filling up /tmp is easier but jobs shouldn't generally be using that directory, so a rogue process that fills it up shouldn't affect other users. In either case, the space is freed as soon as the job terminates. Certainly this is not a problem we have ever observed in practice. However, it should be possible to protect against such an outcome by setting disk quotas for the users jobe00, jobe01, ... jobe09 [The number of such user accounts is defined by the parameter jobe_max_users in application/config/config.php. The default value is 8.] Instructions for installing the quota management system and setting quotas are given in various places on the web, e.g. here. The precise details will vary from system to system according to how the disk partitions are set up; quotas should be set for all jobe users on whatever partitions contain /home/jobe, /tmp, /var/tmp, /var/crash and /run/lock.

Securing the site

Securing by means of a firewall

By default, Jobe is expected to run on an Intranet server that is firewalled to permit access only from specific authorised hosts. In this mode, the client is assumed to be trusted and does not need to provide any form of authorisation or authentication. It is also important to prevent the jobe server from opening connections to other machines, so that a student program cannot do nasty things like port-scanning within your Intranet.

Using ufw (Uncomplicated Firewall) a possible command sequence that will restrict outgoing traffic to just a single nominated host ("some useful ip") on ports 80 and 443, allow ssh access (port 22) from anywhere and web access to jobe (assumed to be on port 80) from just one specified client is the following:

ufw default reject outgoing
ufw allow out proto tcp to <some_useful_ip> port 80,443
ufw allow in 22/tcp
ufw allow in proto tcp to any port 80 from <your_client_ip>
ufw enable

In the above, <your_client_ip> is the host that is permitted to send jobs to Jobe (e.g. a Moodle server with CodeRunner). <some_useful_ip> is any server to which Jobe might need to connect in order to run/grade student code. In the absence of such a server, that line should be omitted.

Securing with API keys (rarely useful)

If you wish Jobe to serve multiple clients and do not wish to open a specific port for each one you will need to configure the firewall to allow incoming connections from anywhere but you should then also configure the rest-server to require some form of authentication and authorisation. The various ways of achieving this are discussed in the documentation of the rest-server plugin.

The simplest authorisation approach is to provide an API key on each request. The client must then provide the key with each request in an X-API-Key header of the form

X-API-KEY: <key>

To set up Jobe to run in this way, proceed as follows:

  1. Make sure you installed the additional dependencies for API-key authentication given in the section "Installing the necessary dependencies". You need to be running a PHP version prior to PHP 7.2 (like that on Ubuntu 16.04 for example).

  2. Create a database called jobe and define a user with full access to it.

  3. Edit application/config/database.php to access your mysql server and the jobe database with the user credentials you defined in the previous step.

  4. Edit the file application/config/rest.php and set the configuration parameter rest_enable_keys to 1.

  5. Set up tables keys and limits as explained in rest.php. Populate the keys table with one or more API keys, which must then be used by any requests to the Jobe server.

If running in API-Key mode, you should still firewall the Jobe server to prevent it opening any sockets to other machines.

Other security mechanisms

If serving multiple clients, you may wish to restrict the use made of the server by one or more clients. This can be done by setting the rest_enable_limits parameter in application/config/rest.php to non-zero. Jobe will then limit the number of requests made with any given key to the values set in application/config/per_method_limits.php.

For this to work, the jobe database must contain an additional table limits, defined with an SQL command like

CREATE TABLE `limits` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uri` varchar(255) NOT NULL,
  `count` int(10) NOT NULL,
  `hour_started` int(11) NOT NULL,
  `api_key` varchar(40) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

You can turn off limit checking on a key-by-key basis by setting the ignore_limits to TRUE (1) in the keys table.

You should read the REST-server plugin documentation and the file application/config/rest.php for other features available.

Run_spec parameters

The Jobe REST API specification document defines the format of a so-called run_spec, which is the record/object that is encoded within a POST request or a run request to specify the job details. It includes the language_id, the source code, the source file name, any standard input data, a list of required files and a set of job parameters. The job parameters are not defined by the REST API as they are implementation dependent. This section defines the format of the parameters field of a run_spec in this implementation.

The allowable attributes of the parameters field, plus their global default values in parentheses, are:

  1. disklimit (20): the maximum number of megabytes that can be written to disk file(s) before the job is aborted
  2. streamsize (2): the maximum number of megabytes of standard output before the job is aborted.
  3. cputime (5): the maximum number of seconds of CPU time before the job is aborted
  4. memorylimit (default 400 but raised for some languages, e.g. 1000 for Python3): the maximum number of megabytes of memory the task can consume. This value is used to set the Linux RLIMIT_STACK, RLIMIT_DATA and RLIMIT_AS via the setrlimit system call. If the value is exceeded the job is not aborted but malloc and/or mmap calls will fail to allocate more memory with somewhat unpredictable results, although a segmentation fault is the most likely outcome.
  5. numprocs (20): the maximum number of processes the task is allowed. If this is exceeded the fork system call will fail with, again, somewhat unpredictable outcomes.
  6. compileargs ([]): a list of string option values to pass to the compiler, such as ["-Wall", "-std=c99"] for the C compiler. Meaningful only for compiled languages. These arguments precede the name of the file to be compiled.
  7. linkargs ([]): a list of string option values to pass to the compiler, such as ["-lm"] for the C compiler. These arguments follow the name of the file to be compiled. Meaningful only for some compiled languages, notably C and C++.
  8. interpreterargs ([]): a list of string option values to pass to the language interpreter or Java VM etc when the program is executed. Meaningful only for languages like Python, PHP and Java where the output from the compiler is not pure executable machine code.
  9. runargs ([]): a list of string option values to pass to the executed program, e.g. to set argc and argv for a C program. Not generally useful from CodeRunner as there is no way to set parameters on a per-test-case basis.

Individual languages will usually set their own default values for compileargs and interpreterargs.

If any of the above attributes are defined within the run_spec parameters field, the latter is used and the defaults are ignored.

The default values of compileargs and interpreterargs for the currently-implemented languages are as follows. An empty default means the global default is used.

language_idlanguagecompileargsinterpreterargs
cC["-Wall", "-Werror", "-std=c99", "-x c"]
cppC++["-Wall", "-Werror"]
python2Python2["-BESs"]
python3Python3["-BE"]
javaJava["-Xrs", "-Xss8m", "-Xmx200m"]
nodejsJavaScript (nodejs)["--use_strict"]
octaveOctave (matlab variant)["--norc", "--no-window-system", "--silent", "-H"]
phpPHP["--no-php-ini"]
pascalFree Pascal["-vew", "-Se"]

Configuration

This version of jobe is configured for use by Moodle Coderunner. When using Jobe from CodeRunner the various language compile and run options can be changed via the sandbox Parameters field in the question authoring form (using the advanced customisation capabilities) of either the question prototype or within a particular question as suggested by the previous section. For example, if the sandbox Parameters field is set to

    { "compileargs": ["-Wall", "-Werror", "-std=c89"] }

for a C question, the code will be compiled with all warnings enabled, aborting if any warnings are issued and will need to be C89 compliant.

If you wish to change the existing default options within Jobe, or you wish to add new languages, you must edit the source code as follows.

The folder application/libraries contains all the code that executes submitted jobs. The file LanguageTask.php defines an abstract class Task that contains default configuration parameters for things like memory limit, maximum cpu run time, maximum disk output, etc. For each supported language, a subclass with a name of the form <Language>_Task resides in a file named <language>_task.php. For example, c_task.php contains all the parameters specific to running C tasks, octave_task.php contains parameters for running Octave tasks, etc. To add a new language to Jobe you just drop in a new <language>_task.php file; its presence is autodetected by the Restapi constructor and the language will be available immediately.

Each subclass of LanguageTask typically defines at least the following three methods:

  1. __construct(). This is the constructor. It should generally call the parent constructor then set any language-specific default compile and/or interpret and/or run options.

  2. getVersion(). This returns a string defining what version of the language, compiler etc is supported. It's not actually used by CodeRunner but is available via the rest API.

  3. compile(). Calling this method must result in the file named $this->sourceFileName being compiled, with an executable output file being placed in the current working directory. If compilation succeeds the name of the executable must be returned in $this->executableFileName; alternatively $this->cmpinfo should be set to an appropriate error message; any non-empty string is taken as a compile error. Interpreted languages might do nothing or might copy the program.

  4. getRunCommand(). This method must return an array of strings that, when joined with a space separator, make a bash command to execute the program resulting from the compile(). Execution parameters like the Java heap size are set in this function. The output from this function is passed to the RunguardSandbox, after addition of standard I/O redirection plus other sandbox parameters (see getParam below).

Additionally the subclass may define:

  1. filteredStderr(). This takes $this->stderr and returns a filtered version, which might be necessary in some languages to remove extraneous text or remove special characters like form-feed or tab in order to make the result more appropriate for subsequent use, e.g. for display to students in a CodeRunner result table.

  2. filteredStdout(). This performs the same task as filteredStderr() except it filters stdout, available to the function as $this->stdout.

Some typical (?) performance figures

The following performance measurements were made on a physical 8-core 16GB Intel i5 CPU @1.60GHz Jobe server.

Burst sizes are measured by sending a burst of submissions as fast as possible to the server and then observing whether or not they all run successfully. If so, the burst size is doubled and the test repeated. Thus burst sizes might be low by a factor of 2. Apart from that, however, all figures should be regarded as upper-bounds on performance since the test jobs are of minimal size with minimal communication overhead.

Performance figures on 8-core virtualised servers on enterprise server systems could be 2 or more times higher, depending on the server infrastructure.

Language Language id Max burst size (jobs) Max sustained throughput (jobs/sec)
C c 128 18
Python3 python3 128 18
JavaScript nodejs 64 13
C++ cpp 32 5
Java java 16 2

Change Log

Version 1.2

Fixed bug with Java when correct source file name supplied in the request (rename of file to itself was failing). Thanks Paul Denny. Replaced uses of Moodle coding_exception with generic exception. Again thanks Paul Denny.

Fixed bug in C++ task - invalid language type being passed to compiler.

Updated CodeIgniter Rest Server to latest version.

Added code to load limit data from a config file "per_method_limits.php" to support per-API-key limits on the number of calls that can be made to the restapi's POST and PUT entry points per hour. Updated the documentation to explain how to turn on API-key authorisation and per-method limits.

Version 1.2.2

Added code to support CORS (Cross Origin Resource Sharing), i.e., in-browser JavaScript requests from arbitrary domains.

Version 1.2.3

Fixed bug in how Java class names (and hence source file names) were inferred from the source code (main classes that implemented an interface or extended a subclass were not handled correctly). Also the filename field in the REST API runspec is now optional; if provided, it is trusted and used as-is, but if not supplied or if an empty string is supplied, Jobe now calls a language-specific function to provide a filename from the sourcecode. [Usually this is just something generic like prog.cpp, prog.py etc]

Version 1.2.4

Fixed issue with runguard that prevented use of pthreads library in C programs.,

Version 1.3

Pascal support added by Fedor Lyanguzov (thanks Fedor)

Good luck!

Version 1.3.1

Minor patches to ensure PHP7 compability. Install instruction in readme.md still relate to PHP5, however.

Version 1.3.2

Change Java config parameters to allow Java 8 to run (more memory and more processes).

Version 1.3.3

Remove inline declaration of readoptarg in runguard.c (causing compile errors with most recent gcc versions). Documentation tweaks.

Version 1.3.4

Fix serious security flaw in runguard + my use of it.

Version 1.3.5

  1. Fix broken caching of language versions (wasting time on each submission).
  2. Improve identification of language versions; 'Unknown' is now given as the language version if a language get-version command runs but produces output in an unexpected format. Formerly such languages were deemed invalid.
  3. Change Java task so supplied memlimit is ignored, leaving JVM to manage its own memory.
  4. Add 'getLanguages' to simpletest.py and testsubmit.py.

Version 1.3.5+ 16 June 2017

  1. Improve installer to handle installation on servers with less permissive access rights than Ubuntu 16.04.
  2. Delete any files created in /tmp, /var/tmp, /run/lock and /var/crash on completion of a run.
  3. Limit maximum CPU time for any one Jobe to 30 secs (config constant).

Thanks Kai-Cheung Leung for the first two of those additions.

Version 1.3.6 21 June 2017

  1. Minimum PHP version is now required to be 5.5. (This is now checked in the installer.)
  2. Compilation of the Student's code is now also done in the runguard sandbox. This provides an additional layer of security.

Thanks Tim Hunt for most of the work in this addition.

1.3.6+

  1. Tune retry count for better performance under overload.
  2. Documentation updates
  3. Tweak installer for Centos detection of web server

1.4.0

  1. Tweaks to allow full utf-8 output to be returned, provided Apache's LANG variable is set to a UTF-8 compatible value.

1.4.1

  1. Merged in switch to pylint3/python3 completely (thanks Garth Williamson)

1.4.2

  1. Bug fix: Jobe server overload was being incorrectly reported as a Runguard error ("No user jobe-1").

1.4.3

  1. Fix bug in testsubmit.php when used with latest pylint3.
  2. Document dependency script for Ubuntu 18.04 plus limitations due to missing mcrypt.

1.5.0

  1. Move to latest versions of CodeIgniter and RestServer frameworks, primarily to fix bug with PHP versions > 7.1 no longer supporting mcrypt library, but also for improved security and error handling.

1.6.0

  1. Change file cache directory from /var/www/html/jobe/files to /home/jobe/files
  2. Change file cache to use a 3 level hierarchy, using the first 4 chars of the MD5 file-id (2 pairs of 2) for the directory names to improve lookup performance when there are many files.
  3. Implement a simple cache clean mechanism that deletes all files that haven't been used for 2 or more days whenever less than 5% of the disk space is free.
  4. Document in restapi that use of check_file to confirm existence of a required file before a run is unsafe, as the file might be removed by the cache cleaner between the two runs.

1.6.0+ (5 December 2019)

  1. Correct bad JSON in documentation (was using single quoted strings).

1.6.1 (14 April 2020)

  1. Tweak handling of timeouts to kill jobs after a wall-clock time in excess of twice the given max_cpu_time
  2. Document issue with handling of resource limits. Jobe is inappropriately applying the compile resource limits even for non-compile tasks. However, fixing this might break existing questions and it's not a serious problem.
  3. Correct bad JSON in documentation that used single-quoted strings.
  4. Add /var/lock to the list of directories to be cleaned on task exit. While it's usually a symbolic link to /run/lock, apparently that's not always the case.
  5. Accept Java programs that use "static public" in main() declaration rather than the more usual "public static".
  6. Fix deprecation warning with PHP 7.4 (and possibly earlier) resulting from loading the JSON-encoded language cache file into an object rather than an associative array.

1.6.2 (16 May 2020)

  1. Increase memory limit for Python3 to 600 MB. Document.

1.6.2+ (24 May 2020)

  1. Change install instructions to install non-GUI Octave.

1.6.3 (20 November 2020)

  1. Prevent privilege escalation attacks via cputime parameter, issue #39.
  2. Change the invalid nodejs program in testsubmit.py to be even more invalid, so it fails to run with all versions of nodejs.

1.6.4 (22 January 2021)

  1. Workaround for bug in py_compile (https://bugs.python.org/issue38731) that results in multiple error messages when a python syntax check fails.

1.6.5 (31 January 2021)

  1. Prevent privilege escalation attacks via sourcefilename issue #46.
  2. Add a load tester (ad hoc, experimental), loadtester.py.

1.6.6 (21 July 2021)

  1. Add a config parameter to determine which python3 executable to use if there are multiple versions installed.
  2. Remove the temporary workaround for a bug in the python3 py_compile module (now fixed).

1.6.7 (15 June 2022)

  1. Tweak RestServer code to handle PHP 8
  2. Tweak testsubmit.py to handle larger default memory limits and possible increases in the user-configured maxcputime.

1.6.8 (20 September 2022)

  1. Bug fix - the Python3 syntax check, using py_compile, was using the default installed Python3 version, not a customised one (if set).

1.7.0 (27 December 2022)

  1. Add a configuration parameter to config.php to allow users to adjust the maximum time Jobe will wait for a free worker thread before aborting the execution and returning a server-overload response.

  2. Alter the testsubmit program to workaround differences in the way RedHat servers handle process limits, particularly in containerised versions of Jobe.

  3. Add performance measurement code to the testsubmit program.

  4. Add several command-line arguments to make the testsubmit.py program more user-friendly.

1.7.1 (15 May 2023)

  1. Increase memory allocation for Python as jobs continue to grow in memory demand.

  2. Add HTTP return code to the error message on invalid sourcefilename.

  3. Ensure PHP 8.2 compatibility by allowing dynamic properties in the CodeIgniter core and by adding property declarations to Jobe classes.

  4. Increase the backoff from 1 sec to 5 secs when starting the sustained load testing. Otherwise, the first test could fail.

1.7.2 (4 June 2023)

  1. Fix long-standing bug that always applied a compile parameter setting if this was greater than the requested value, even when it wasn't a compile. Hopefully won't break anyone's code (they'd have to have been using very low parameter values).

  2. Bug fix: purge fails if num_jobe_users has been reduced in the config file since the install was run.

  3. Upgrade install to include option to set range of UIDs for Jobe and workers. This should provide a workaround for JobeInABox installs on systems running nginx, which resulted in a UID conflict with the host. Also include a --uninstall option.

1.8.0 (9 October 2023)

  1. Add various tuning parameters for Java to config file. Thanks Marcus Klang.

  2. Ensure that install updates runguard config to allow for a large number of Jobe users (> 20). Thanks Marcus Klang.

  3. Add a main_class parameter to Java task. Thanks Peter Seibel.

  4. Increase default per-run memory allocation from 200 MB to 400 MB. Needed for NodeJS in particular but everything is getting greedier.

jobe's People

Contributors

fedor-lyanguzov avatar gigamonkey avatar kcleung avatar kiliansinger avatar lszeremeta avatar marcusklang avatar myyxl avatar spetzreborn avatar timhunt avatar trampgeek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jobe's Issues

Privilege escalation using cputime parameter and runguard

Hello,
i have found a bug that can lead to a privilege escalation.
Most of the input which the user can control is escaped using escapeshellarg but using the cputime parameter which is not escaped you can create a command injection which leads to a privilege escalation.
Here you can see that cputime is not escaped and is directly set into the sandox command which is executed by the user www-data.
Once you have access to the webroot you can patch runguard to accept root as a valid user and execute commands as root.
I have also a proof-of-concept script but I won't upload it here for security reasons.
If there are any further questions, I'll be happy to help.

Sincerely,
Marlon

Matlab is crashing (segmentation violation detected)

Hello,
I'm trying to run questions for Matlab. The question type is python3 and template is as follows:

""" The template for a question type that runs a student-submitted
    matlab function.
"""

import subprocess, sys

# Write the test and student code to a file student_code.m
test_code = """{{ TEST.testcode }}

"""

student_answer = """{{ STUDENT_ANSWER }}"""
with open("student_code.m", "w") as src:
    print(test_code, file=src)
    print(student_answer, file=src)


# Run the code. Since this is a per-test template,
# stdin is already set up for the stdin text specified in the test case,
# so we can run the compiled program directly.
try:
    output = subprocess.check_output(["matlab", "-batch", "student_code"], universal_newlines=True)
    print(output)
except subprocess.CalledProcessError as e:
    print("Task failed with signal", -e.returncode, file=sys.stderr)
    print("** Further testing aborted **", file=sys.stderr)

But Matlab is crashing when running the question with the following error (I added strace for debugging):

***Error***
execve("/usr/local/bin/matlab", ["matlab", "-batch", "student_code"], 0x7fff2d0d3cc0 /* 5 vars */) = 0
brk(NULL)                               = 0x55d0eee27000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffefdb9f050) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=36065, ...}) = 0
mmap(NULL, 36065, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2da6e4f000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\364\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=191480, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2da6e4d000
mmap(NULL, 190832, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2da6e1e000
mmap(0x7f2da6e2c000, 57344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe000) = 0x7f2da6e2c000
mmap(0x7f2da6e3a000, 57344, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c000) = 0x7f2da6e3a000
mmap(0x7f2da6e48000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x29000) = 0x7f2da6e48000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\"\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=37240, ...}) = 0
mmap(NULL, 24688, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2da6e17000
mmap(0x7f2da6e19000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f2da6e19000
mmap(0x7f2da6e1b000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f2da6e1b000
mmap(0x7f2da6e1c000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f2da6e1c000
mmap(0x7f2da6e1d000, 112, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2da6e1d000
close(3)                                = 0
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \203\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0J\177\263t\t\177\271'\373\223\323^\371\213\250\222"..., 68, 880) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=3222048, ...}) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 1876640, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2da6c4c000
mprotect(0x7f2da6c72000, 1683456, PROT_NONE) = 0
mmap(0x7f2da6c72000, 1372160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7f2da6c72000
mmap(0x7f2da6dc1000, 307200, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x175000) = 0x7f2da6dc1000
mmap(0x7f2da6e0d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f2da6e0d000
mmap(0x7f2da6e13000, 12960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2da6e13000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2da6c49000
arch_prctl(ARCH_SET_FS, 0x7f2da6c49740) = 0
mprotect(0x7f2da6e0d000, 12288, PROT_READ) = 0
mprotect(0x7f2da6e1c000, 4096, PROT_READ) = 0
mprotect(0x7f2da6e48000, 16384, PROT_READ) = 0
mprotect(0x55d0ee6b0000, 16384, PROT_READ) = 0
mprotect(0x7f2da6e83000, 4096, PROT_READ) = 0
munmap(0x7f2da6e4f000, 36065)           = 0
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = -1 ENXIO (No such device or address)
ioctl(0, TCGETS, 0x7ffefdb9ec90)        = -1 ENOTTY (Inappropriate ioctl for device)
brk(NULL)                               = 0x55d0eee27000
brk(0x5 ...snip... FDIR|0755, st_size=4096, ...}) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [PIPE CHLD TSTP WINCH], 8) = 0
clone(child_stack=0x7f6e44e53d70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tid=[33873], tls=0x7f6e44e54640, child_tidptr=0x7f6e44e54910) = 33873
rt_sigprocmask(SIG_SETMASK, [PIPE CHLD TSTP WINCH], NULL, 8) = 0
futex(0x1db47f0, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x1db4868, FUTEX_WAIT_PRIVATE, 0, NULL
--------------------------------------------------------------------------------
          Segmentation violation detected at 2021-03-26 16:14:13 +0100
--------------------------------------------------------------------------------

Configuration:
  Crash Decoding           : Disabled - No sandbox or build area path
  Crash Mode               : continue (default)
  Default Encoding         : UTF-8
  GNU C Library            : 2.32 stable
  MATLAB Architecture      : glnxa64
  MATLAB Root              : /opt/Matlab/R2020b
  MATLAB Version           : 9.9.0.1467703 (R2020b)
  Operating System         : Linux 5.10.23-200.fc33.x86_64 #1 SMP Thu Mar 11 22:18:30 UTC 2021 x86_64
  Process ID               : 33771
  Processor ID             : x86 Family 6 Model 86 Stepping 3, GenuineIntel
  Session Key              : c2fd9afe-4421-466c-872f-a63646d54ad4
  Static TLS mitigation    : Disabled: Unnecessary

Fault Count: 1


Abnormal termination:
Segmentation violation

Current Thread: 'MCR 0 interpret' id 140111152932416

Register State (from fault):
  RAX = 0000000000000000  RBX = 00007f6e2b7fd120
  RCX = 00007f6e4d0701d7  RDX = 000000007fffffff
  RSP = 00007f6e2b7fd018  RBP = 00007f6e2b7fd080
  RSI = 0000000000000081  RDI = 0000000000000000

   R8 = 0000000000000000   R9 = 0000000000000001
  R10 = 0000000000000000  R11 = 0000000000000246
  R12 = 00007f6e2b7fd140  R13 = 00007f6e2b7fd100
  R14 = 00007f6e2b7fd140  R15 = 00007f6e3e7802a1

  RIP = 00007f6e49602050  EFL = 0000000000010246

   CS = 0033   FS = 0000   GS = 0000

Stack Trace (from fault):
[  0] 0x00007f6e49602050 /opt/Matlab/R2020b/bin/glnxa64/libmwsettingscore.so+01814608 _ZNK8settings4core8Settings28isConnectedToTheSettingsTreeEv+00000000
[  1] 0x00007f6e3e6bc276         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+00680566
[  2] 0x00007f6e3e6fdea5         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+00949925
[  3] 0x00007f6e3e711b55         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+01030997
[  4] 0x00007f6e3e6e8f9a         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+00864154 _ZNSt17_Function_handlerIFSt10unique_ptrINSt13__future_base12_Result_baseENS2_8_DeleterEEvENS1_12_Task_setterIS0_INS1_7_ResultIvEES3_EZNS1_11_Task_stateISt8functionIFvvEESaIiESC_E6_M_runEvEUlvE_vEEE9_M_invokeERKSt9_Any_data+00000042
[  5] 0x00007f6e4d3215ff    /opt/Matlab/R2020b/bin/glnxa64/libmwservices.so+02717183 _ZNSt13__future_base13_State_baseV29_M_do_setEPSt8functionIFSt10unique_ptrINS_12_Result_baseENS3_8_DeleterEEvEEPb+00000031
[  6] 0x00007f6e4d0701af                             /lib64/libpthread.so.0+00070063
[  7] 0x00007f6e4b128306      /opt/Matlab/R2020b/bin/glnxa64/libmwmlutil.so+08098566 _ZSt9call_onceIMNSt13__future_base13_State_baseV2EFvPSt8functionIFSt10unique_ptrINS0_12_Result_baseENS4_8_DeleterEEvEEPbEJPS1_S9_SA_EEvRSt9once_flagOT_DpOT0_+00000102
[  8] 0x00007f6e3e6e8484         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+00861316
[  9] 0x00007f6e3e6e8727         /opt/Matlab/R2020b/bin/glnxa64/libmwmcr.so+00861991
[ 10] 0x00007f6e4c25f482 /opt/Matlab/R2020b/bin/glnxa64/libmwboost_thread.so.1.70.0+00062594
[ 11] 0x00007f6e4d0683f9                             /lib64/libpthread.so.0+00037881
[ 12] 0x00007f6e4c9f8b53                                   /lib64/libc.so.6+01055571 clone+00000067

** This crash report has been saved to disk as /tmp/matlab_crash_dump.33771-1 **



MATLAB is exiting because of fatal error
) = ?
+++ killed by SIGKILL +++
Task failed with signal 9
** Further testing aborted **

I'm guessing, that there is some problem with the sandboxing, because I can run the subprocess.check_output(["matlab", "-batch", "student_code"], universal_newlines=True) command interactively as normal user without any problems.

Do you have some idea how to solve this?

Thank you

testsubmit "Memory limit exceeded in C (seg faults)"

Hi,

I have updated Jobe to version 1.6.6 on an up to date Debian 10 server. When I launch python3 ./testsubmit.py to test the install the test "Memory limit exceeded in C (seg faults)" fails since the requested malloc call succeeds. After investigating it seems to me that the new default memory limit for C tasks is 500MB. If I edit testsubmit.py and change the #define CHUNKSIZE 500000000 line to for example #define CHUNKSIZE 550000000 the malloc fails as expected and the test succeeds. It would be nice if you could patch the code accordingly.

Best regards,
Jean-Pierre

Privilege escalation using sourcefilename

Hi Richard,
I have found another privilege escalation but this time using the sourcefilename. When adding "../../" before the actual file name you can store the file in another directory. If you store the file into the web directory you can execute php code by doing a request to the website. After this you can patch runguard and gain root.
Here is the affected line in the source code: Link

Sincerely,
Marlon

how can i install jobe in Nginx?

how can i install jobe in Nginx?
Nginx is insalled as my httpserver, how can i install jobe in a Nginx server instead of apacher?

Testing instructions on README.md wrongly mention --port=4000

On README.md you include the following instructions to test a Jobe server from a client machine:

python3 testsubmit.py --host='jobe.somehow.somewhere' --port=4000

However, as far as I can tell, the Jobe server is listening on port 80, right?

web server unable to access contents of /var/www/html/jobe/ and therefore can't run

I cloned jobe onto /var/www/html, changed into /var/www/html/jobe, and run:

sudo ./install

./install only changed ownership of the directory "files" to jobe:www-data (files needs to be written by jobe), but the rest of the contents are still root:root, with access of directories such as application, nbproject, runguard and system remain as rwxr-xr--

As a result, the web server cannot read the directories application, nbproject and runguard, and therefore cannot run jobs.

Therefore should install change group ownership of all contents to www-data, to ensure www-data can read the necessary files? Or should install make everything world-readable and all directories world-executable?

How to add SQL support?

This is a good sandbox without the SQL support. Unfortunately, SQL is a most teacher technic in our school.

It's is possible to add SQL support?

Thanks

Module 'xmlrpc'

Hy;
i have an error , coderunner didn't knew python3 anymore
in /vag/log/jobe i have :
ERROR - 2019-07-10 11:22:21 --> Severity: Core Warning --> Module 'xmlrpc' already loaded Unknown 0

Issues with JobeInaBox

The following error runs up whenever I try to run the test script for jobeinabox by running sudo docker exec -t jobe /usr/bin/python3 /var/www/html/jobe/testsubmit.py

The error:

    c: 9.3.0
    cpp: 9.3.0
    java: 14.0.2
    nodejs: 10.19.0
    octave: 5.2.0
    pascal: 3.0.4
    php: 7.4.3
    python3: 3.8.10


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Valid Python3
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Python3 with stdin
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************

Syntactically invalid Python3 OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Python3 runtime error
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Python3 file I/O
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Testing use of interpreter args with Python3
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Testing use of runargs args with Python3
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Python3 program with customised timeout
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Python3 program with support files
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Valid Python3/pylint program
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Invalid Python3/pylint program
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
UTF-8 output from Python3 (will fail unless Jobe set up for UTF-8)
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Test good C hello world
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************

Test compile error C hello world OK
Test use of compileargs with C OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Test runtime error C hello world
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Test timelimit on C
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Test outputlimit on C
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Memory limit exceeded in C (seg faults)
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Infinite recursion (stack error) on C
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
C program controlled forking
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
A C program with ASCII non-UTF-8-compatible output
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 12, 'cmpinfo': '', 'stdout': '', 'stderr': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n"}
Valid Octave
Jobe result: Runtime error

No output

Error output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.


************************************************


***************** FAILED TEST ******************

{'run_id': None, 'outcome': 12, 'cmpinfo': '', 'stdout': '', 'stderr': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n"}
octave with stdin
Jobe result: Runtime error

No output

Error output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.


************************************************

Syntactically invalid Octave (treated as runtime error) OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 12, 'cmpinfo': '', 'stdout': '', 'stderr': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n"}
Syntactically valid Nodejs hello world
Jobe result: Runtime error

No output

Error output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.


************************************************

Syntactically invalid Nodejs OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Correct Php program 
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************

Syntactically incorrect Php program  OK
Syntactically incorrect Php program  OK
Correct Java program  OK
Correct Java program without supplied sourcefilename  OK
Syntactically incorrect Java program  OK
Java program with a support class (.java) OK
Java program with Unicode output (will fail unless Jobe set up for UTF-8)  OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
Test good C++ hello world
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************

Test compile error C++ hello world OK

***************** HTTP ERROR ******************

 Response: 200 OK 

<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

<h4>A PHP Error was encountered</h4>

<p>Severity: Warning</p>
<p>Message:  file_get_contents(prog.pas.err): failed to open stream: No such file or directory</p>
<p>Filename: libraries/pascal_task.php</p>
<p>Line Number: 36</p>


	<p>Backtrace:</p>
	
		
	
		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/pascal_task.php<br />
			Line: 36<br />
			Function: file_get_contents			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/controllers/Restapi.php<br />
			Line: 221<br />
			Function: compile			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/REST_Controller.php<br />
			Line: 793<br />
			Function: runs_post			</p>

		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/index.php<br />
			Line: 315<br />
			Function: require_once			</p>

		
	

</div>
<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

<h4>A PHP Error was encountered</h4>

<p>Severity: Notice</p>
<p>Message:  Undefined property: Pascal_Task::$executableFileName</p>
<p>Filename: libraries/pascal_task.php</p>
<p>Line Number: 51</p>


	<p>Backtrace:</p>
	
		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/pascal_task.php<br />
			Line: 51<br />
			Function: _error_handler			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/LanguageTask.php<br />
			Line: 395<br />
			Function: getExecutablePath			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/LanguageTask.php<br />
			Line: 159<br />
			Function: getRunCommand			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/controllers/Restapi.php<br />
			Line: 225<br />
			Function: execute			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/REST_Controller.php<br />
			Line: 793<br />
			Function: runs_post			</p>

		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/index.php<br />
			Line: 315<br />
			Function: require_once			</p>

		
	

</div>{"run_id":null,"outcome":12,"cmpinfo":false,"stdout":"","stderr":"\/var\/www\/html\/jobe\/application\/libraries\/..\/..\/runguard\/runguard: cannot start `sh': Resource temporarily unavailable\nTry `\/var\/www\/html\/jobe\/application\/libraries\/..\/..\/runguard\/runguard --help' for more information.\n"}

***************** HTTP ERROR ******************

 Response: 200 OK 

<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

<h4>A PHP Error was encountered</h4>

<p>Severity: Warning</p>
<p>Message:  file_get_contents(prog.pas.err): failed to open stream: No such file or directory</p>
<p>Filename: libraries/pascal_task.php</p>
<p>Line Number: 36</p>


	<p>Backtrace:</p>
	
		
	
		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/pascal_task.php<br />
			Line: 36<br />
			Function: file_get_contents			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/controllers/Restapi.php<br />
			Line: 221<br />
			Function: compile			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/REST_Controller.php<br />
			Line: 793<br />
			Function: runs_post			</p>

		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/index.php<br />
			Line: 315<br />
			Function: require_once			</p>

		
	

</div>
<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

<h4>A PHP Error was encountered</h4>

<p>Severity: Notice</p>
<p>Message:  Undefined property: Pascal_Task::$executableFileName</p>
<p>Filename: libraries/pascal_task.php</p>
<p>Line Number: 51</p>


	<p>Backtrace:</p>
	
		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/pascal_task.php<br />
			Line: 51<br />
			Function: _error_handler			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/LanguageTask.php<br />
			Line: 395<br />
			Function: getExecutablePath			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/LanguageTask.php<br />
			Line: 159<br />
			Function: getRunCommand			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/controllers/Restapi.php<br />
			Line: 225<br />
			Function: execute			</p>

		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/application/libraries/REST_Controller.php<br />
			Line: 793<br />
			Function: runs_post			</p>

		
	
		
	
		
			<p style="margin-left:10px">
			File: /var/www/html/jobe/index.php<br />
			Line: 315<br />
			Function: require_once			</p>

		
	

</div>{"run_id":null,"outcome":12,"cmpinfo":false,"stdout":"","stderr":"\/var\/www\/html\/jobe\/application\/libraries\/..\/..\/runguard\/runguard: cannot start `sh': Resource temporarily unavailable\nTry `\/var\/www\/html\/jobe\/application\/libraries\/..\/..\/runguard\/runguard --help' for more information.\n"}

39 tests, 13 passed, 24 failed, 2 exceptions

Checking parallel submissions
Doing child 0
Doing child 1
Doing child 2
Doing child 3
Doing child 4
Doing child 5
Doing child 6
Doing child 7
Doing child 8
Doing child 9

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 11, 'cmpinfo': "/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable\nTry `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.\n", 'stdout': '', 'stderr': ''}
C program to check parallel submissions
Jobe result: Compile error

Compiler output:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable
Try `/var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.



************************************************

C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
C program to check parallel submissions OK
All done

Testing a submission with an excessive cputime parameter
OK

Used the latest docker image: trampgeek/jobeinabox:latest
Linux kernel: 5.15.0
Docker version: `20.10.12

Please let me know if I can provide more details to help fix this.

syntax error

An error occurred when the test failed and I take a look to Apache log :
PHP Parse error: syntax error, unexpected 'finally' (T_STRING), expecting catch (T_CATCH) in /var/www/html/jobe/application/controllers/restapi.php on line 228
System: CentOS 7
Installed:
apache
php
libapache2-mod-php
php-mcrypt
mysql-server
php-cli
octave
nodejs
git
python3
openjdk-9-jre
python3-pip
fp-compiler
pylint3

Directory permission problems under umask 0007

The standard VM created by my institution has a default umask of 0007. As a result:

/var/www/html/jobe/system$ ls -lh
total 12K
drwxr-xr-- 2 root root 320 Apr 11 09:21 core
drwxr-xr-- 3 root root 182 Apr 11 09:21 database
drwxr-xr-- 2 root root 40 Apr 11 09:21 fonts
drwxr-xr-- 2 root root 4.0K Apr 11 09:21 helpers
-rw-r--r-- 1 root root 114 Apr 11 09:21 index.html
drwxr-xr-- 3 root root 39 Apr 11 09:21 language
drwxr-xr-- 4 root root 4.0K Apr 11 09:21 libraries

many directories are not readable by the user www-data after I run install.sh, thus rendering the jobe unusable.

So install.sh somehow needs to ensure all directories are world-executable

Also, when I check out jobe onto /var/www/html/jobe, this is the permission I get for the files inside:

:/var/www/html/jobe$ ls -lh
total 220K
drwxr-x--- 15 root root 232 Apr 11 09:34 application
-rw-r----- 1 root root 1.5K Apr 11 09:34 checkcorsaccess.html
-rw-r----- 1 root root 6.5K Apr 11 09:34 index.php
-rwxr-x--- 1 root root 6.5K Apr 11 09:34 install
-rw-r----- 1 root root 2.5K Apr 11 09:34 license.txt
drwxr-x--- 3 root root 66 Apr 11 09:34 nbproject
-rw-r----- 1 root root 21K Apr 11 09:34 README.md
-rw-r----- 1 root root 44K Apr 11 09:34 restapi.odt
-rw-r----- 1 root root 91K Apr 11 09:34 restapi.pdf
drwxr-x--- 2 root root 97 Apr 11 09:34 runguard
-rw-r----- 1 root root 4.4K Apr 11 09:34 simpletest.py
drwxr-x--- 8 root root 130 Apr 11 09:34 system
-rwxr-x--- 1 root root 25K Apr 11 09:34 testsubmit.py

I guess the install.sh also needs to fix this too. Should all files be world-readable, and all directories be world-executable?

Adding jail / proot support

This is perhaps not an issue so much as a query - it would be useful to have a chroot'd jail for the applications, but this is typically a pain to implement.

For another system where I execute arbitrary code from students (our computer systems class), I recently retrofitted the server to use "proot" ( http://proot.me/ ). This turned out to be very easy.

The setup code was something like this (create /tmp/jailXYZZY directory)
$jail = tempdir( CLEANUP => 1 );
system("/bin/mkdir $jail/bin") == 0
or log_die("unable to create proot $jail/bin");
system("/bin/mkdir $jail/tmp") == 0
or log_die("unable to create proot $jail/tmp");
system("/bin/cp $BINDIR/bufbomb $jail/bin") == 0
or log_die("unable to copy bufbomb to proot jail");

this makes /tmp/jail/tmp, and /tmp/jail/bin. The binary is then coped it i/tmp/jail/bin

and then the execution is something like:

proot -r $jail $prootlibs bufbomb

where prootlibs is $PROOT_LIBS="-b /etc/ld.so.cache -b /lib/ld-linux.so.2 -b /lib32/libc.so.6 -w /bin ";
in other words, the files that should be mapped into the proot jail.

My situation was much simpler because I only needed specific files mapped in (the ones above), but proot can also handle standard jail tasks w/o sudo.

jobe-created accounts automatically deleted by central management system such as puppet

I have just tried to install jobe into a VM that is centrally managed using puppet by our ITS. However, the accounts created by jobe were deleted by puppet, because these automatically-created accounts.

To solve this problem, I have added the argument '-r' in useradd called by the installer script "install" to make all jobe users as system users, thus will not be touched by central management systems.

I will create a pull request that will fix this issue.

Bad Result Object { }

testsubmit.py results in
Bad result object{} for every test

http://my_ip_address/jobe/index.php/restapi/languages
returns
[["c","7.3.0"],["cpp","7.3.0"],["java","1.8.0_181"],["php","7.2.7"],["python2","2.7.15"],["python3","3.6.5"]]

Working in Ubuntu 18.04 LTS

How to get the code execution time and the memory consumed by the code

Thank you very much for providing such a great plug-in,I not only care about the results of the student code, but also want to know the execution efficiency of the code.I noticed that the maximum CPU running time and maximum execution memory parameters can be set. Is there any way for Moodle to get the code execution time and the memory consumed by the code, or does it need to modify the configuration of the jobe server? If so, what should I do? Can you give me some tips,thanks

Install has a problem

An error occurred when I executed my order :
# sudo ./install
File "./install", line 48
names = {ps_line.split(' ')[0] for ps_line in ps_lines}
^
SyntaxError: invalid syntax

runguard/runguard: cannot start ` sh': Resource temporarily unavailable

Hello, when I try to run ' python3 testsubmit.py', I obtain 28 error messages like :

/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `                                                                                                                                                             sh': Resource temporarily unavailable

I run it in a Lxc container in proxmox , et the container is 'ubuntu 18.04' type.

Thank's a lot,

PHP8 compatibility

As PHP7.4 is becoming unsupported later this year, can Jobe be updated to work with php8 ?

Here is the error we get for each call (including testsubmit.py) :

Message: strtolower(): Passing null to parameter #1 ($string) of type string is deprecated

Filename: libraries/REST_Controller.php

Line Number: 1050

Inline function readoptarg: undefined reference in gcc 5

Inline function readoptarg(), defined in .c file(asaik, it's a good practice to define inline functions in headers), causes undefined reference with newer gcc 5+, because it switched from -std=gnu89 to -std=c11 by default

runguard.c:(.text+0x13cd): undefined reference to `readoptarg'
runguard.c:(.text+0x1432): undefined reference to `readoptarg'
runguard.c:(.text+0x1497): undefined reference to `readoptarg'
runguard.c:(.text+0x1538): undefined reference to `readoptarg'
collect2: error: ld returned 1 exit status

Workaround: set -std=gnu89 manually.

Tighten security around the LANGUAGE_CACHE_FILE

because this file lives in tmp, it is theorietically possisble that another user on the Jobe server could tamper with it. Therefore, when we load it, it would be a good idea to verify the contents before they are used.

I am about to do a patch for this.

Security problem with Jobe

Language selected: Python3
source code:

a = eval(input())
print(a)

payload:
__import__('os').popen('ls /').read()

This will show up root directory

`sh': Resource temporarily unavailable

Hello, well we have two installations of the jobe server as a docker container.

One on a Hyper-V Server (with Ubuntu 18.04), that runs perfect and
another on a ProxMox Hypervisor (with Ubuntu 20.4) here I've got the error:

"/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start `sh': Resource temporarily unavailable"`

Any idea or solution what is going wrong?

best regars

jtuttas

Permissions/ownership of /home/jobe/runs/jobe_xxxxxx test directories

I'm testing the https://hub.docker.com/r/trampgeek/jobeinabox docker container in Ubuntu 18.04, and the /jobe/index.php/restapi/languages test returns the expected JSON output. However, when I run testsubmit.py inside the container I get a lot of test failures due to permission errors, for example:

{'run_id': '/home/jobe/runs/jobe_1ZYE4V', 'outcome': 11, 'cmpinfo': '/usr/bin/ld: cannot open output file 
test.c.exe: Permission denied\ncollect2: error: ld returned 1 exit status\n', 'stdout': '', 'stderr': ''}
C program to check parallel submissions
Jobe result: Compile error

Compiler output:
/usr/bin/ld: cannot open output file test.c.exe: Permission denied
collect2: error: ld returned 1 exit status

So I enabled debugging and tried running the command in the jobe_1ZYE4V subdirectory that was created in /home/jobe/runs, with the same outcome. But I noticed that the permissions of all the jobe_xxxxxx subdirectories are, for example:

drwxr-xr-x  2 www-data www-data  4096 Oct 24 02:50 jobe_1ZYE4V

However, these commands all seem to be run by one of the 'jobexx' users (in the 'jobe' group), so it's understandable why the output files can't be written.

Are the jobe_xxxxxx subdirectories supposed to be created with different permissions? The parent directory, /home/jobe/runs has these permissions:

drwxrwx--x 51 jobe www-data 36864 Oct 24 02:50 runs

Thanks,
Tony.

jobe fails to delete data stored in /tmp after the job finishes

jobe fails to delete temporary data stored in /tmp after the job finishes. In many VM systems, storage space in /tmp is very limited, so this bug causes the /tmp to fill up quickly, and making the VM unusable.

The script needs to ensure temporary data of a job is immediately deleted after the job ends and data is returned to the moodle

Jobeserver fails with 3 Python3 tests under debian stretch

Under debian stretch:
"Python3 file io" test fails and two other file io related python3 tests.
Reported error: PermissionError: [Errno 13] Permission denied: 'testoutput.txt'
When compared to ubuntu 16.04LTS jobeserver creates folder in /home/jobe/runs/ with access
right 755 (debian) instead of 765 (ubuntu).
Other possible cause:
when calling as www-data this works in both debian and ubuntu:
su - www-data -s /bin/bash -c 'cd /home/jobe/runs/jobe_PYTHONIO_ID && python3 /home/jobe/runs/jobe_PYTHONIO_ID/test.py
but this only works in ubuntu:
su - jobe00 -s /bin/bash -c 'cd /home/jobe/runs/jobe_PYTHONIO_ID && python3 /home/jobe/runs/jobe_PYTHONIO_ID/test.py

Reason for using debian stretch is use of grsecurity, which is offically supported in backports and soon hopefully in stable releases. Also debian jessie fails with many errors that language 'c' and 'java' are unknown.
I guess it is a version problem, which I do not see any reason to fix.

PS: debugging and verbose mode was enabled.

Lack of support of link arguments in C and C++ languages

In C and C++ programs that requires external libraries, the link arguments must be inserted after the output file argument, e.g.:

g++ -g -W -Wall foo.cpp -o foo -lGl -Glu

or otherwise the linker will not be able to load the requested libraries, yet the current jobe version only supports "compileargs".

To fix this problem, I have added the parameter "linkargs" in run_spec to allow specification of link arguments. The fix is in:
https://github.com/UoA-CompSci/jobe

and I have already submitted a pull request. Please have a look.

testsubmit.py fails 1 test "15, 'cmpinfo'"

I have just cloned/installed the current version of jobe (as at about 1 hour ago) from the git repo onto an Ubuntu 18.04 server.

(I have set the Apache envvars value of LANG to: C.UTF-8, if that is relevant.)

When running python3 testsubmit.py, all tests appear to be successful apart from one.
Is this anything to be concerned about?

Thanks, David.

$ python3 testsubmit.py

Supported languages:
c: 7.3.0
cpp: 7.3.0
java: 10.0.1
nodejs: 8.10.0
octave: 4.2.2
pascal: 3.0.4
php: 7.2.7
python3: 3.6.5

Valid Python3 OK
Python3 with stdin OK
Syntactically invalid Python3 OK
Python3 runtime error OK
Python3 file I/O OK
Testing use of interpreter args with Python3 OK
Testing use of runargs args with Python3 OK
Python3 program with customised timeout OK
Python3 program with support files OK

***************** FAILED TEST ******************

{'run_id': None, 'outcome': 15, 'cmpinfo': '', 'stdout': '------------------------------------\n', 'stderr': ''}
Valid Python3/pylint program
Jobe result: Successful run

Output:


Invalid Python3/pylint program OK
UTF-8 output from Python3 (will fail unless Jobe set up for UTF-8) OK

[...tests continue OK...]

allow testing of PHP5 or PHP 7 code from students?

currently the docs state that language_id 'php' is for PHP5
please could system by upgraded, so that PHP7 code can also be run/unit tested?
I believe your codebase has been refactored for PHP7 so am hoping this is pretty straightforward

I see Python has python2 and python3
since php is already in use, then perhaps 'php' would be for php5 and 'php7' would be for php 7?

many thanks if this is possible

I was going to write my own PHP Moodle quiz system, but am hoping CodeRunner will meet my requirements - but I've upgraded all my teaching to PHP7 so support for that is pretty important

CodeRunner looks like it really fills a need for code assessments via Moodle - I've high hopes from reading your docs so far

regards, .. matt ..

Suggestion: have c and cpp templates remove $this->src before execution

Some very clever students determined the test cases to their quiz questions by using popen to then cat prog.cpp and get a copy of the template source. I added unlink($this->src) to fix this for C/C++, but for many languages there is no work around (e.g. python2/3) that I can think of.

Dependencies problem

Hello, Richard.

Thank you for your great work. I am constructing a test system for my school and encountered some problems.

There is at least 2 problems with installing Jobe:

  1. libapache2-mod-auth-mysql package is missing in Debian 8 Jessie (stable). Apache2 had changed API or something, so all modules should be rebuilt considering changes. Unfortunately, this one is not built yet. Solution is to use oldstable Debian 7.8 Wheezy. I am trying this right now.
  2. nodejs is not in Debian repos, it should be installed manually with
apt-get install curl
curl --silent --location https://deb.nodesource.com/setup_0.12 | bash -
apt-get install --yes nodejs

When i am done with installing, i will try to add Pascal prototype question to CodeRunner (this looks pretty simple), and Pascal support to Jobe (not so easy). Would you like to see this features merged to your repository?

Sincerely yours,
Fedor.

/home/jobe path explicitly coded in LanguageTakss.php

On line 65 of LanguageTasks, the /home/jobe path is explicitly coded into the application. For various reasons (our /home is typically an auto-mounted mess) I specified a homedir of /local/jobe.

The failure mode was a little perplexing - jobe directories were in /tmp and readable by all other jobe submissions, which our pesky students quickly exploited.

Perhaps the documentation should indicate you need to use /home (or change the file) or it should be auto configured from the config file.

* Time limit exceeded * when running python3 scripts with numpy

We have a debian installation of jobe, that gets time limit exceeded when importing numpy.

lsb_release -a

No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm

free -m

           total        used        free      shared  buff/cache   available

Mem: 8902 583 8239 7 342 8319
Swap: 1955 0 1955

We have 16 processors on this VM.

We have tired to raise the limits of memory to 2000 for python, and CPU runtime with no other result that the tests take longer to respond.

According to debugging in README.md:

"
If something unexpected happened with the actual run of a program, find the run in /home/jobe/runs and try executing the program manually. [The run directory contains the source file, the bash command used to run it, plus the compile output and (if it ran) the stderr and stdout outputs.
"

We have tried to catch the program and run them in CLI on the server:
while :;do time python3 jobe_/__test ;echo $?; sleep 1;done

Output from out program:
Test [420/8991]
[1, 3, 5, 7, 9, 2, 4, 6, 8, 10]

real 0m0.166s
user 0m0.931s
sys 0m0.883s
0

Where the program is:
"
import numpy as np
def task12(param1, param2):
print("Test")
return [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
"

testsubmit.py is only complaining on c, witch does not seem relevant to our case.

***************** FAILED TEST ****************** (8 results) [3360/8998]

{'run_id': None, 'outcome': 11, 'cmpinfo': 'prog.c: In function ‘silly’:\nprog.c:4:6: error: infinite rec
ursion detected [-Werror=infinite-recursion]\n 4 | void silly(int i) {\n | ^~~~~\nprog.c:7:9
: note: recursive call\n 7 | silly(j);\n | ^~~~~~~~\nprog.c:9:9: note: recursive
call\n 9 | silly(j + 1);\n | ^~~~~~~~~~~~\ncc1: all warnings being treated as err
ors\n', 'stdout': '', 'stderr': ''}
Infinite recursion (stack error) on C
Jobe result: Compile error

Compiler output:
prog.c: In function ‘silly’:
prog.c:4:6: error: infinite recursion detected [-Werror=infinite-recursion]
4 | void silly(int i) {
| ^~~~~
prog.c:7:9: note: recursive call
7 | silly(j);
| ^~~~~~~~
prog.c:9:9: note: recursive call
9 | silly(j + 1);
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors


We don't understand why it completes quickly in CLI, but times out in moodle.
Any suggestions or tips?

Regards
Björn and Sebastian
DSV
Stockholm university

Runguard error

signal-2023-05-19-172804_002
Encountering the following error when running Jobe in a Docker container hosted locally:
/var/www/html/jobe/application/libraries/../../runguard/runguard: cannot start sh': Resource temporarily unavailable Try /var/www/html/jobe/application/libraries/../../runguard/runguard --help' for more information.

Limit reached

Hello

I saw error bellow yesterday. What would you recommend?

"Failed to run tests
Sandbox submission limit reached"

Issue with runguard

I have been using CodeRunner with C++ programs. I was trying to overcome the problem of CodeRunner failing to execute further tests when a test causes a program crash, hence I tried to changed the template so that a subprocess is created using fork() per each test case.

It does not work and I believe the reason has to do with the way runguard works. Consider the following program.

#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

void doit(int x) {
  pid_t pid = fork();
  if (pid == 0) {
    printf("SON %d %d\n", x, getpid());
    exit(0);
  } else if (pid > 0) {
    waitpid(pid, 0, 0);
    printf("PARENT %d %d\n", x, getpid());
  } else {
    printf("FAIL %d\n", x);
  }
}
int main() {
  puts("A");
  doit(0);
  puts("B");
  doit(1);
  puts("C");
  doit(2);
}

During a normal execution of the program I get (as expected) something like:

A
SON 0 1963
PARENT 0 1962
B
SON 1 1964
PARENT 1 1962
C
SON 2 1965
PARENT 2 1962

When I execute the program through run_guard I get surprising output - I believe fork() behaves differently:

A
SON 0 2070
A
PARENT 0 2069
B
SON 1 2071
A
PARENT 0 2069
B
PARENT 1 2069
C
SON 2 2072
A
PARENT 0 2069
B
PARENT 1 2069
C
PARENT 2 2069

Is there a way to fix this behavior through CR configuration options passed on to Jobe?

Thanks

Https?

Hi!

I just set up Jobe for use in our programming education, and everything works perfectly. However, it doesn't seem like HTTPS is supported when communicating between the jobe server and the client?

I haven't looked very closely at this apart from noting that jobe seems to break when I set up a redirect from http to https and/or I point my moodle server to https://my.server.example instead of my.server.example.

Am I right in concluding that jobe (and/or coderunner?) doesn't support HTTPS at the moment? Are there any plans on changing that? I could probably produce a patch if there is interest (and I get the time).

How to support the SQL?

This is a best sandbox server. I already used these application.
and I want to know how to enable the SQL support?

Making loaded files writable

Hello,

I'm using Jobe as a code sandbox for my own LMS.

One change I'm trying to make is making files loaded in the workdir writable. I tried a few things but none worked.

First thing I tried: in LanguageTask.php, function prepare_execution_environment, I changed this line:

exec("setfacl -m u:{$this->user}:rwX {$this->workdir}")

to

 exec("setfacl -Rmd u:{$this->user}:rwX {$this->workdir}")

expecting that the rule would apply recursively to all files in the folder, including ones generated in the future. However, for some reason, what ends up happening is that I am not able to execute the executable file after compiling: for example, with a C task, I get

/usr/bin/ld: cannot open output file prog.c.exe: Permission denied
collect2: error: ld returned 1 exit status

Second thing I tried: in the function load_files in LanguageTask.php, after creating each file with file_put_contents, I added:

chown($destPath, $this->user)

However, this fails because it can only be used as root user, which is not the user under which Jobe runs.

How can I make the loaded files writable? Maybe I don't have a deep enough understanding of how Jobe works yet to find a solution, so any help is welcome.

octave wants many xserver and gnome dependencies on Ubuntu 20.04

I'm trying to build a new Jobe server (for testing) on Ubuntu 20.04.

octave now seems to want many xserver and gnome dependencies (which I don't think it did by default previously?).

Do you know if there is a way to install a more minimal non-gui version of Octave, as it seems unnecessary (and undesirable) to bring in the whole windowing system when it is only going to be used programmatically on an otherwise 'headless' server? Possibly it might be worth liaising with the Ubuntu octave packagers about this?

Octave will not run

Hi,

I'm getting the following error when trying to run an Octave problem with the RESTAPI

/usr/bin/octave-cli: error while loading shared libraries: libopenblas.so.0: failed to map segment from shared object

If I shell in to the server I can run octave-cli with no problems. I've even tried runguard octave-cli and that also works.

Any ideas on where I should go from here?

preloading jobe (or jobeinabox maybe) with some files

Hi, hope this is an okay place to ask this kind of question.

I'm looking it using jobe to run Java programs for a web-based programming environment. If there are certain jar files that I know I'm going to want to make available to javac and java is there a standard way to preload them into the environment other than having the client upload them into the filecache via the REST API?

Hope that question actually makes sense; I've only been poking around and reading docs for a day or so so I obviously may have missed something obvious or misunderstood something. Cheers!

num_jobe_users=multiprocessing.cpu_count() clobber

Howdy, it's Michael from University of Wollongong, Australia

In amongst our process to get ready for Exams Period, we spotted an issue in v1.6 that capped performance in the jump from 8 to 16 vCPUs. Thankfully, this was already spotted and corrected in v1.7 however, just flagging that commit 6bcf49f has rolled back the num_jobe_users from number of cpu's back to number in the config file only in origin/master potentially by accident?

how can i install jobe in Nginx?

how can i install jobe in Nginx?
Nginx is insalled as my httpserver, how can i install jobe in a Nginx server instead of apacher?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.