Escaping my own chroot...

Nick Craig-Wood nick at craig-wood.com
Fri Feb 13 17:31:56 CET 2009


Jean-Paul Calderone <exarkun at divmod.com> wrote:
>  On Wed, 11 Feb 2009 09:31:56 -0600, Nick Craig-Wood <nick at craig-wood.com> wrote:
> >r0g <aioe.org at technicalbloke.com> wrote:
> >>  I'm writing a linux remastering script in python where I need to chroot
> >>  into a folder, run some system commands and then come out and do some
> >>  tidying up, un-mounting proc & sys etc.
> >>
> >>  I got in there with os.chroot() and I tried using that to get back out
> >>  but that didn't work so... is my script trapped in there forever now or
> >>  is there an un-hacky way to escape?
> >
> >No!
> 
>  If you still have root in the chroot (and you need root to get in there, so
>  it's not implausible that you will), then you can get out.  Googling for
>  "escape chroot" turns up lots of hits.  This page contains a fairly simple,
>  explicit description of how to get out of a chroot:
> 
>     http://www.bpfh.net/simes/computing/chroot-break.html
> 
>  See the bulleted list in the "Breaking chroot()" section.  Since you also
>  control the process before the chroot happens, breaking out is even simpler
>  in your case (just open / before you chroot in the first place).  forking
>  before doing the chroot may still be a good idea, but it's not the only
>  solution.

I admit it can be done, but I'm not sure it isn't hacky!

#!/usr/bin/python

"""
Enter a chroot and escape again

Run as root
"""

import os
import sys

def ls(path):
    """List the path"""
    print "Directory listing of %r" % path
    for f in os.listdir(path):
        print ">>", f

def main():
    if len(sys.argv) < 2:
        print >>sys.stderr, "Need directory to chroot to as an argument"
        raise SystemExit(1)
    chroot_dir = sys.argv[1]
    print "Opening root"
    root = os.open("/", os.O_RDONLY)
    print "Before chroot"
    ls("/")
    print "Chrooting to %r" % chroot_dir
    os.chroot(chroot_dir)
    ls("/")
    print "Breaking the chroot"
    os.fchdir(root)
    for i in range(100):
        os.chdir("..")
    os.chroot(".")
    ls("/")
    os.close(root)

if __name__ == "__main__":
    main()


I ran this

$ mkdir chroot_test
$ touch chroot_test/in_the_chroot
$ sudo ./chroot_test.py chroot_test

And it produced this

Opening root
Before chroot
Directory listing of '/'
>> lost+found
>> home
>> bin
>> boot
>> proc
>> dev
>> etc
[snip]
Chrooting to 'chroot_test'
Directory listing of '/'
>> in_the_chroot
Breaking the chroot
Directory listing of '/'
>> lost+found
>> home
>> bin
>> boot
>> proc
>> dev
>> etc
[snip]


-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list