2

I am attempting to script the creation of a chroot jail (I know that there are tools for this, but I am in it for the experience, so please don't recommend a tool). I have a script which looks up commands that I wish to be runnable within the jail, looks up their dependencies, follows symbolic links, and then copies everything to the jail. Here is that script setup for python only.

executables="
python
"

for exe in $executables
do
        # move the executable
        echo Executable: $exe
        exe_path=`which $exe`
        echo READLINK -f $exe_path
        exe_true_path=`readlink -f $exe_path`
        exe_dir=`echo $exe_path | grep -o '/.*/'`
        mkdir -p $1$exe_dir
        cp -L $exe_true_path $1$exe_path

        # get the libs for this exe
        libs=`ldd $exe_true_path | grep -o '/[^()]*'`

        # move each lib
        for lib in $libs
        do
                echo Library: $lib
                lib_path=$lib
                lib_true_path=`readlink -f $lib_path`
                lib_dir=`echo $lib_path | grep -o '/.*/'`
                echo MKDIR $1$lib_path
                mkdir -p $1$lib_path
                echo CP $lib_true_path $1$lib_path
                cp -L $lib_true_path $1$lib_path
        done
done

It seems to work quite well...

$ tree .
.
+-- lib
¦   +-- x86_64-linux-gnu
¦       +-- libc.so.6
¦       ¦   +-- libc-2.13.so
¦       +-- libdl.so.2
¦       ¦   +-- libdl-2.13.so
¦       +-- libgcc_s.so.1
¦       ¦   +-- libgcc_s.so.1
¦       +-- libm.so.6
¦       ¦   +-- libm-2.13.so
¦       +-- libpthread.so.0
¦       ¦   +-- libpthread-2.13.so
¦       +-- libutil.so.1
¦       ¦   +-- libutil-2.13.so
¦       +-- libz.so.1
¦           +-- libz.so.1.2.7
+-- lib64
¦   +-- ld-linux-x86-64.so.2
¦       +-- ld-2.13.so
+-- usr
    +-- bin
        +-- python

However, when it comes to actually running python within this jail, I get a permissions error.

$ sudo chroot chroot12/ python --version
chroot: failed to run command `python': Permission denied

Even after I open up the permissions, I get the error.

$ chmod -R 777 chroot12/
$ sudo chroot chroot12/ python --version
chroot: failed to run command `python': Permission denied

Any ideas what might be causing this? I didn't start getting these errors until I introduced the link following, but I unfortunately don't have the older version of the script to compare with.

Thanks in advance!

strace output

$ sudo strace -f chroot chroot12 python --version
execve("/usr/sbin/chroot", ["chroot", "chroot12", "python", "--version"], [/* 14 vars */]) = 0
brk(0)                                  = 0x11f1000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f329f926000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26406, ...}) = 0
mmap(NULL, 26406, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f329f91f000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\360\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1599536, ...}) = 0
mmap(NULL, 3713144, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f329f37e000
mprotect(0x7f329f500000, 2093056, PROT_NONE) = 0
mmap(0x7f329f6ff000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x181000) = 0x7f329f6ff000
mmap(0x7f329f704000, 18552, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f329f704000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f329f91e000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f329f91d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f329f91c000
arch_prctl(ARCH_SET_FS, 0x7f329f91d700) = 0
mprotect(0x7f329f6ff000, 16384, PROT_READ) = 0
mprotect(0x607000, 4096, PROT_READ)     = 0
mprotect(0x7f329f928000, 4096, PROT_READ) = 0
munmap(0x7f329f91f000, 26406)           = 0
brk(0)                                  = 0x11f1000
brk(0x1212000)                          = 0x1212000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1534672, ...}) = 0
mmap(NULL, 1534672, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f329f7a5000
close(3)                                = 0
chroot("chroot12")                      = 0
chdir("/")                              = 0
execve("/usr/local/sbin/python", ["python", "--version"], [/* 14 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/bin/python", ["python", "--version"], [/* 14 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/sbin/python", ["python", "--version"], [/* 14 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/bin/python", ["python", "--version"], [/* 14 vars */]) = -1 EACCES (Permission denied)
execve("/sbin/python", ["python", "--version"], [/* 14 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/python", ["python", "--version"], [/* 14 vars */]) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/locale.alias", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "chroot: ", 8chroot: )                 = 8
write(2, "failed to run command `python'", 30failed to run command `python') = 30
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Permission denied", 19: Permission denied)     = 19
write(2, "\n", 1
)                       = 1
close(1)                                = 0
close(2)                                = 0
exit_group(126)                         = ?
Rip Leeb
  • 347
  • 1
    Maybe use strace to see what it's trying to access when it gets the error. – Barmar Oct 30 '14 at 18:48
  • python is not a valid shell. Try using bash then once in the changeroot, run python --version: chroot chroot12/ -s /bin/bash – eyoung100 Oct 30 '14 at 18:52
  • Have you run an ls -lAR on chroot12 and looked for "obvious" problems? (And maybe post the output?) Also, are you doing the link stuff just as a learning exercise? I think you could just cp $lib_path $1$lib_path and get the right result. – G-Man Says 'Reinstate Monica' Oct 30 '14 at 19:08
  • @Barmar like so? $ sudo chroot chroot12/ strace python --version chroot: failed to run command 'strace': Permission denied @eyoung100 bash seems to be blocked too: $ sudo chroot chroot12/ chroot: failed to run command '/bin/bash': Permission denied @G-Man I am not totally familiar with those options. Let me get back to you. – Rip Leeb Oct 30 '14 at 19:10
  • Put the strace outside the jail, like so: sudo strace -f chroot chroot12 python --version – Celada Oct 30 '14 at 19:12
  • Thanks for clarification @Celada. I added strace output to the post. – Rip Leeb Oct 30 '14 at 19:16
  • Strange. There are no EPERM errors in the trace, I don't see where that error is coming from. And even though you have chroot12/user/bin/python in your tree, it's reporting ENOENT for that path. – Barmar Oct 30 '14 at 19:23
  • @Barmar Take a closer look. execve(/usr/bin/python) fails with EACCES (Permission denied). – goldilocks Oct 30 '14 at 19:29
  • Oops, missed that. What are the permissions on chroot12/usr/bin/python? – Barmar Oct 30 '14 at 19:31
  • $ ls -l chroot12/usr/bin/python -rwxrwxrwx 1 admin admin 2884984 Oct 30 19:05 chroot12/usr/bin/python – Rip Leeb Oct 30 '14 at 19:33

1 Answers1

2

The only way I am able to reproduce the error:

execve("/usr/bin/python", ["python", "--version"], [/* 14 vars */]) = -1 EACCES (Permission denied)

...is by making the ELF dynamic loader non-executable.

This works:

$ ls -l chroot12/lib64/ld-linux-x86-64.so.2 
-rwxr-xr-x 1 root root 149280 Oct 30 16:22 chroot12/lib64/ld-linux-x86-64.so.2

This doesn't:

$ ls -l chroot12/lib64/ld-linux-x86-64.so.2 
-rw-r--r-- 1 root root 149280 Oct 30 16:22 chroot12/lib64/ld-linux-x86-64.so.2

Make sure chroot12/lib64/ld-linux-x86-64.so.2 has execute permission.

Celada
  • 44,132