Skip to content

Instantly share code, notes, and snippets.

@iondune
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save iondune/d11db3291f1816dfb5fc to your computer and use it in GitHub Desktop.

Select an option

Save iondune/d11db3291f1816dfb5fc to your computer and use it in GitHub Desktop.
SafeRun docs

SafeRun

Name

SafeRun - Run an executable, providing pty I/O, security against output overruns, excess runtimes, and process runaways

Usage

SafeRun [options] test_subject

Description

SafeRun is a test harness for running a "test subject" Unix executable that has a text I/O interface. SafeRun provides the following

Better Recording of Redirected Ouput in the Presence of Faults

Text I/O programs are often tested with redirected input and output, but if they fail during the run, much or all of their output may be lost due to buffering that automatically occurs when stdout is redirected. A program might generate dozens of lines prior to a runtime fault when run directly on screen, but show no output at all when redirected to a file. SafeRun arranges input and output "piping" via ptys, so even in the presence of a fault, the output it generates looks like what you'd see on screen, despite being redirected.

Runtime fault messages, e.g. "Seg fault core dumped", are made directly to screen, and not to the error stream. SafeRun, however, creates and prints to the error stream a message reporting the fault.

Restraint of Runaway Output

Simple redirection invites huge output files from programs with runaway output. SafeRun places a byte limit on redirected data, and simply drops all output exceeding that limit, printing to stderr a message telling how many bytes were dropped.

Termination of Endless Loops

SafeRun measures both the wallclock and CPU time of the test subject, and terminates it if either exceeds some limit.

Security against Process Runaways

SafeRun limits the number of simultanously running descendant processes created by the test subject, by limiting process count through Unix resource controls. SafeRun generates and reports a fault if this limit is exceeded.

Security against Lingering Descendant Processes

SafeRun detects and kills lingering descendant processes of the test subject, and it reports via stderr a count of such processes.

It does this by one of two means. In a non-rooted configuration, it places the test subject under a new session id, and detects and kills all lingering processes running under that session id. Sufficiently malfeasant processes can defeat this by shifting session ids, but this is unlikely.

If SafeRun is run under root privilege, and is given the name of a user, it will run the test subject under that user, and kill all lingering processes running under that user, on the entire system.

Chroot Jailing

SafeRun can run the test subject and its descendant processes in a chroot jail, to thwart test subjects that "explore" their environment, or attempt to corrupt it. Chroot jailing requires root privilege for SafeRun.

Detection of Unread Input

SafeRun determines whether the test subject left input unread, and reports this as an error, unless otherwise configured.

Options

SafeRun accepts the following options. Each is expressed with a '-', the option letter, and any configuration information without spaces, e.g. "-T1000". Most have a default value used if no option is given.

T

Wallclock time limit in mS. The option "-T1000" results in a wallclock time limit of 1s. Default value: 1000000

t

CPU time limit, per process or child process, in mS. The option -t1000 results in a per process CPU limit of 1s. Default value: 10000

p

Max number of descendant processes. -p10 limits simultanous active test subject descendant processes to 10, using Unix resource limits. (Note this does not preclude an infinite number of children if each spawns another and then dies.) Default value: 10

o

Max number of output bytes allowed in stdout or stderr (both limited independently). -o1000 limits output to 1000 stdout and 1000 stderr bytes. Default value: 1000000

u

Username for test subject. Requires that SafeRun run with root privilege. -uGuest runs test subject as user Guest. Presuming Guest is not root privileged, this means all descendant processes will also be Guest, and SafeRun's termination of all lingering Guest processes will block even malfeasant users from creating runaway processes. Default is no username, which means that lingering process cleanup will be done by session id, which is less reliable.

r

Chroot flag. Requires SafeRun have root privilege. -r turns on chroot behavior; test subject and all descendant processes will run in a clean chroot jail in the current directory. SafeRun does not populate the chroot jail with any dynamic libraries, so any test subject must be statically linked. Default behavior: no chroot jail.

i

Input control flag. Its presence makes unread input permissible. The flag alone makes any unread input, including no unread input, OK; the flag followed by a number requires exactly that many bytes of unread input, with any other amount resulting in an error message to stderr.

b

Flag for accommodation of binary input. SafeRun normally sends input to the test subject via a pty, as described above. If input is binary, the presence of control-characters in the binary data makes this problematic. A -b flag causes SafeRun to use a standard pipe for input to the test subject, though it still uses the pty for output. This handles binary input properly, at the expense of losing the ability to detect unread input, since piped input is usually grabbed by the test subject in large buffersfull, even if it ends up unused.

Exit Code

SafeRun reports error situations on stderr, but it also returns a program result code for use in scripting. (The code can be determined by running echo $? immediately after a hand-run of SafeRun, per usual.) The result code is one of the following, in descending order of priority:

Any internal SafeRun error

180 Fork call failed

181 Error setting up parameters

182 Wait call for test subject failed

183 Chroot failed, perhaps because SafeRun lacked root privilege

184 Execution of test subject failed, perhaps using chroot with nonstatically linked executable

185 Attempt to run test subject under another user via -u option failed

186 Unexpected error running "select" system call

187 Interrupted by control-C or control-\

188-191 Reserved for later errors

Absent internal SafeRun errors, any of these faults by the test subject

Result code is 192 plus an or of one or more of these values. E.g. a result code of 197 indicates excess runtime plus nonterminated child processes.

1 Excess runtime, due either to slow implementation or endless loop
2 Excessively long output, again probably due to endless loop
4 Child processes not terminated and waited for
8 Runtime fault of some sort, e.g. segmentation fault
16 Failure to read all supplied input.

32 Reserved for later errors

Absent other errors, the Test Subject result code

Note that this may be at most 179 without interference with the other possible values above. But, this is not a significant limit for many applications. And the only way to obtain a 0 result code from SafeRun is for no other failures to occur and for the test subject to return a 0 result code.

Note that this means shell scripts checking for nonzero result codes will be sensitive to the result code of the test subject itself, if no other error has occured. If you get weird result codes from SafeRun, check to be sure your code is returning a valid result code, not leaving it to random chance.

SafeRun will print any nonzero result code to stderr.

Notes on SafeRun Debugging

Exit code 127

In some instances where SafeRun is not in the PATH, an exit code of 127 may be seen instead of the usual shell command not found complaint. This appears to happen most often when redirecting stderr to stdout via 2>&1. The exit code does not come from SafeRun or the test subject; it's set by the shell.

Input EOF

SafeRun is meant to be run with redirected input. It can also be run with hand-entered input, but remember that you must end your input with an EOF indication (i.e. control-D) or SafeRun will wait indefinitely, even if the test subject has long since terminated. SafeRun detects input not read by the test subject, and if you have "more to say" after the test subject has ended, it needs to know this so it can report an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment