item2
Next»

contents

 

Introduction - 1

Background - 2

Deployment - 3

Starkits - 4

Tclkit - 5

Advanced topics - 6

Repositories - 7

Server apps - 8

Who uses this - 9

Examples - 10

Conclusion - 11

 

Acknowledgements

References

6.10 - Safekit and chroot jails

Sometimes you want to run Tcl scripts in a secure environment - that is, one where the underlying filesystem cannot be touched.

This can be achieved with careful use of the Tcl Safe Interpreter facility - which allows untrusted Tcl scripts to be run safely, and provides mediated access by such scripts to potentially dangerous functionality.

But there are times when you want to allow access to external files, but restricted within a defined areas of the filesystem (for example, in a CGI application).

This can be achieved on Unix using the chroot (change root) system call to block out all access to the local filesystem. Since Tclkit is a static executable and carries a complete runtime with it, there is no need to access the underlying filesystem.

To achieve this we use a small C wrapper called Safekit. This wrapper launches Tclkit after calling chroot() to limit access to the current filesystem subtree. This approach guarantees that scripts run within this context cannot access a file outside this environment, not even through external programs.

Safekit is just a small C program that must be installed “setuid root”. On startup, it does a chroot("."), and then reduces permissions to the current user’s normal ones. Then, Tclkit is launched, passing all arguments on to it.

    #include <unistd.h>
    #include <sys/types.h>

    int main(int argc, char** argv)
    {
        if (chroot(".") != 0)
            return 1;
        if (seteuid(getuid()) != 0)
            return 2;
        argv[0] = "/tclkit";
        if (execv(argv[0], argv) != 0)
            return 3;
        return 0;
    }

To use this sandbox you need to place all scripts and data that are needed in a single directory area, along with a copy of Tclkit and the Safekit wrapper. Nothing else is needed, provided that Tclkit and Safekit are both compiled as fully static executables. If extensions are to be dynamically loaded, you will also need to create a .../lib area with all necessary runtime shared libraries. For example, to run "myscript.tcl" safely, set up something similar to the following:

    safeplace
    |-- myscript.tcl
    |-- safekit
    |-- tclkit
    `lib

Then, change the permissions on Safekit to be setuid root:

    # chmod -rwx safekit
    # chown root safekit
    # chmod u+s go+x safekit

As an example, we’ll use the following myscript.tcl script:

    puts "pwd = [pwd]"
    catch { exec ls } err
    puts "exec ls -> [split $err \n]"
    puts "glob * -> [glob *]"
    cd ..

When run with a normal Tclkit, we see the following:

    $ ./tclkit myscript.tcl
    pwd = /home/steve/safeplace
    exec ls -> myscript.tcl safekit tclkit
    glob * -> safekit tclkit myscript.tcl
    pwd = /home/steve

However when run with the Safekit wrapper the script we see that we can’t get outside of the current directory and commands like ls are not available:

    $ ./safekit myscript.tcl
    pwd = /
    exec ls -> {couldn't execute "ls":
      no such file or directory}
    glob * -> safekit tclkit myscript.tcl
    pwd = /

see also

Starkit Home Page

Tclkit Home Page

Metakit Home Page

SDX Utility

Wikit Home Page

Tclers' Wiki

Author's Website

Updated paper, by Steve Landers, as presented at Tcl/Tk 2002 conference - see also original PDF.

Papers & Presentations