idea: chroot :: FilePath -> IO a -> IO a

David Roundy droundy@abridgegame.org
Mon, 21 Apr 2003 10:12:11 -0400


I have the idea that we ought to be able to implement the equivalent of a
unix chroot command, but all within the haskell IO monad.

So the idea would be that if I want to do some operation that only requires
access to, say /var/cache/test, but involves user-provided input which I
don't trust (and if I don't want to trust the security of my parsing of the
possibly malicious input), I could run:

chroot "/var/cache/test" $ complicated_function "/" scary_user_input

which would be the equivalent of

complicated_function "/var/cache/test" scary_user_input

except that every file and directory access (read or write or stat or
whatever) would be forced to be in a subdirectory of /var/cache/test.
Moreover, calls such as system would not be allowed (that is, they'd throw
an isChrootError exception), since such calls of course could not be
verified to touch no file outside of /var/cache/test (at least not using
only haskell).

Actually, there are two ways this could be done.  One is the one mentioned
above, which is roughly equivalent to a unix chroot.  Another (now that I
think about it, probably more elegant) would be to implement a
restrict_access type of function, which wouldn't change the meaning of any
file paths as a chroot does, but would simply cause any access outside of
the specified directory to fail.  This would have the advantage of being
transparent to the writer of complicated_function--and might be extended to
allow access to more than one directory (e.g. for a webserver of only
static pages maybe /var/www and /etc/myserver/).

As I see it, implementing such a function would require support in the IO
monad (some of which may already be there?), since it would need to know
for each primitive operation which arguments are file paths, plus whether
that operation is even legal in a chroot environment.  Or perhaps it's the
other way around, and every primitive operation would need to support
chroot...

I know I would find such a function exceedingly comforting, since I wonder
from time to time what would happen if users stick weird filenames in the
wrong places, or make symlinks to things they should not have access to.
And the cool thing is that with haskell's monadic IO, I think it could be
done in a very elegant manner, and in such a way that it is natural (and
simple) to wrap a chroot around individual operations, giving finer grained
control than I can imagine doing any other way.

Any ideas whether such a feat would be possible, and if so how hard it
would be?
-- 
David Roundy
http://www.abridgegame.org