Re: Running Untrusted Code in a Restricted Process

From: David A. Wagner (daw@cs.berkeley.edu)
Date: Fri Jun 09 2000 - 22:04:23 EST


As others have noted, you can use ptrace() to selectively deny syscalls.
See http://www.cs.berkeley.edu/~daw/janus/ for an implementation that used
this idea in a more general context.

In general, I suggest to place the policy decisions in user-space code,
and only the minimal mechanism in the kernel.

sendmsg() and recvmsg() are probably ok as long as you take care in which
open fd's are passed across the fork(). brk() can be more easily restricted
by using setrusage() and relying on the kernel to do the checks, rather
than re-implementing those checks yourself.

Make sure to audit the interface between the untrusted process and the
trusted one real well -- that's where a lot of bugs can creep in, if the
two processes can interact in complex ways. BTW, why are you using IPC
and shared memory rather than pipe(2) and read()/write()? Shared memory
in particular sounds like asking for trouble.

You'll also want to take great care about what privileges, etc., you pass
across the fork(). The following code snippet is not exhaustive, but might
be useful as a starting point:

    /* If we're root, give it up */
    if (!geteuid()) setuid(NOBODY); // #define NOBODY appropriately

    /* Set the umask */
    umask(077);

    /* No core files */
    rl.rlim_cur = rl.rlim_max = 0;
    setrlimit(RLIMIT_CORE, &rl);

    /* No huge files */
    rl.rlim_cur = rl.rlim_max = 5 * 1024 * 1024;
    setrlimit(RLIMIT_FSIZE, &rl);

    /* 20MB virtual memory */
    rl.rlim_cur = rl.rlim_max = 18 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rl);
    rl.rlim_cur = rl.rlim_max = 2 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rl);

    if (!interactive)
    {
        /* Close stdin/out/err */
        close(0);
        close(1);
        close(2);

        /* Get a /dev/null handle and make stdin/out/err it */
        devnull = open("/dev/null", O_RDWR);
        if (devnull >= 0)
        {
            dup2(devnull, 0);
            dup2(devnull, 1);
            dup2(devnull, 2);
        }
    }

    /* Close all remaining fds */
    if (getrlimit(RLIMIT_NOFILE, &rl)) rl.rlim_max = 1024;

    for(fd=3;fd<rl.rlim_max;++fd)
    {
        close(fd);
    }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:20 EST