Learn R Programming

RAppArmor (version 0.6.0)

eval.secure: Secure evaluation

Description

Evaluate in a sandboxed environment.

Usage

eval.secure(..., uid, gid, priority, profile,
    timeout = 60, silent = FALSE, verbose = TRUE,
    RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA,
    RLIMIT_FSIZE, RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE,
    RLIMIT_NICE, RLIMIT_NOFILE, RLIMIT_NPROC,
    RLIMIT_RTPRIO, RLIMIT_RTTIME, RLIMIT_SIGPENDING,
    RLIMIT_STACK)

Arguments

...
arguments passed on to eval(...)
uid
integer or name of linux user.
gid
integer or name of linux group.
priority
priority. Value between -20 and 20.
profile
AppArmor security profile. Has to be preloaded by Linux.
timeout
timeout in seconds.
silent
suppress output on stdout. See mcparallel().
verbose
print some C output (TRUE/FALSE)
RLIMIT_AS
hard limit passed on to rlimit_as()
RLIMIT_CORE
hard limit passed on to rlimit_core()
RLIMIT_CPU
hard limit passed on to rlimit_cpu()
RLIMIT_DATA
hard limit passed on to rlimit_data()
RLIMIT_FSIZE
hard limit passed on to rlimit_fsize()
RLIMIT_MEMLOCK
hard limit passed on to rlimit_memlock()
RLIMIT_MSGQUEUE
hard limit passed on to rlimit_msgqueue()
RLIMIT_NICE
hard limit passed on to rlimit_nice()
RLIMIT_NOFILE
hard limit passed on to rlimit_nofile()
RLIMIT_NPROC
hard limit passed on to rlimit_nproc()
RLIMIT_RTPRIO
hard limit passed on to rlimit_rtprio()
RLIMIT_RTTIME
hard limit passed on to rlimit_rttime()
RLIMIT_SIGPENDING
hard limit passed on to rlimit_sigpending()
RLIMIT_STACK
hard limit passed on to rlimit_stack()

Details

This function creates a fork, and then sets any rlimits, uid, gid, priority, apparmor profile where specified, and then evaluates the expression inside the fork. After evaluation returns, the fork is killed. If the timeout is reached the fork is also killed and an error is thrown.

Evaluation of an expression through secure.eval should never have any side effects on the current R session. This also means that if the code does e.g. assignments to the global environment, sets options(), these will get lost, as we explicitly want to prevent this. However, if the expression saves any files (where allowed by apparmor), these will still be available after the evaluation finishes.

Note that if the initial process does not have superuser rights, rlimits can only be decreased and setuid/setgid might not work. In this case, specifying an RLIMIT higher than the current value will result in an error. Some of the rlimits can also be specified inside of the apparmor profile. When a rlimit is set both in the profile and through R, the more restrictive one will be effective.

Examples

Run this code
## Restricting file access ##
eval.secure(list.files("/"))
eval.secure(list.files("/"), profile="r-base")

eval.secure(system("ls /", intern=TRUE))
eval.secure(system("ls /", intern=TRUE), profile="r-base")

## Limiting CPU time ##
cputest <- function(){
	A <- matrix(rnorm(1e7), 1e3);
	B <- svd(A);
}

## setTimeLimit doesn't always work:
setTimeLimit(5);
cputest();
setTimeLimit();

#timeout does work:
eval.secure(cputest(), timeout=5)

## Limiting memory ##
A <- matrix(rnorm(1e8), 1e4);
B <- eval.secure(matrix(rnorm(1e8), 1e4), RLIMIT_AS = 100*1024*1024)

## Limiting procs ##
forkbomb <- function(){
	repeat{
		parallel::mcparallel(forkbomb());
	}
}

## Forkbomb is mitigated ##
eval.secure(forkbomb(), RLIMIT_NPROC=10)

Run the code above in your browser using DataLab