Por que o chroot obtém o ENOENT em um arquivo existente?

3

; TL-DR - Resposta: porque o vinculador dinâmico ld-linux-x86-64.so.2 estava faltando.

Eu montei um sistema de arquivos squashfs (não importa) -ro,loop at /mnt/foo .

Ele contém, entre outras coisas, o seguinte ( /mnt/foo é o ponto de montagem):

-rwxr-xr-x 1 root    root     110088 jan 17  2013 /mnt/foo/bin/ls
-rw-r--r-- 1 root    root       5212 jul 23 09:35 /mnt/foo/etc/ld.so.cache
-rw-r--r-- 1 root    root          5 jul 23 09:35 /mnt/foo/etc/ld.so.conf
-rw-r--r-- 1 root    root      31168 maj 23  2013 /mnt/foo/lib/libacl.so.1
-rw-r--r-- 1 root    root      18624 maj 20  2013 /mnt/foo/lib/libattr.so.1
-rwxr-xr-x 1 root    root    1853400 okt 12  2013 /mnt/foo/lib/libc.so.6
-rw-r--r-- 1 root    root      14664 okt 12  2013 /mnt/foo/lib/libdl.so.2
-rw-r--r-- 1 root    root     256224 mar 11  2013 /mnt/foo/lib/libpcre.so.3
-rwxr-xr-x 1 root    root     135757 okt 12  2013 /mnt/foo/lib/libpthread.so.0
-rw-r--r-- 1 root    root      31760 okt 12  2013 /mnt/foo/lib/librt.so.1
-rw-r--r-- 1 root    root     134224 maj 23  2013 /mnt/foo/lib/libselinux.so.1

/mnt/foo/etc/ld.so.conf contém uma única linha (incluindo nova linha) com apenas /lib .

Antes de criar o sistema de arquivos, executei ldconfig -r ${TOPDIR} onde ${TOPDIR} resolvido para o local que agora está montado em /mnt/foo . Um strings on /mnt/foo/etc/ld.so.cache mostra que ele contém strings como /lib/libpcre.so.3 e assim por diante, então não acho que seja um problema com as bibliotecas compartilhadas.

Eu acho que deve ser algo bobo que eu estou negligenciando, mas eu não consigo entender por que um simples chroot /mnt/foo /bin/ls não funciona.

readelf -d /mnt/foo/bin/ls | grep NEEDED mostra essas bibliotecas conforme necessário:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Por fim, strace mostra isso:

chroot("/mnt/foo")                      = 0
chdir("/")                              = 0
execve("/bin/ls", ["/bin/ls"], [/* 32 vars */]) = -1 ENOENT (No such file or directory)

Este é o chroot de strace completo:

# strace -f chroot /mnt/foo /bin/ls
execve("/usr/sbin/chroot", ["chroot", "/mnt/foo", "/bin/ls"], [/* 32 vars */]) = 0
brk(0)                                  = 0x1985000
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) = 0x7fc115ac8000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=96457, ...}) = 0
mmap(NULL, 96457, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc115ab0000
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|O_CLOEXEC) = 3
read(3, "7ELF
-rwxr-xr-x 1 root    root     110088 jan 17  2013 /mnt/foo/bin/ls
-rw-r--r-- 1 root    root       5212 jul 23 09:35 /mnt/foo/etc/ld.so.cache
-rw-r--r-- 1 root    root          5 jul 23 09:35 /mnt/foo/etc/ld.so.conf
-rw-r--r-- 1 root    root      31168 maj 23  2013 /mnt/foo/lib/libacl.so.1
-rw-r--r-- 1 root    root      18624 maj 20  2013 /mnt/foo/lib/libattr.so.1
-rwxr-xr-x 1 root    root    1853400 okt 12  2013 /mnt/foo/lib/libc.so.6
-rw-r--r-- 1 root    root      14664 okt 12  2013 /mnt/foo/lib/libdl.so.2
-rw-r--r-- 1 root    root     256224 mar 11  2013 /mnt/foo/lib/libpcre.so.3
-rwxr-xr-x 1 root    root     135757 okt 12  2013 /mnt/foo/lib/libpthread.so.0
-rw-r--r-- 1 root    root      31760 okt 12  2013 /mnt/foo/lib/librt.so.1
-rw-r--r-- 1 root    root     134224 maj 23  2013 /mnt/foo/lib/libselinux.so.1
 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
chroot("/mnt/foo")                      = 0
chdir("/")                              = 0
execve("/bin/ls", ["/bin/ls"], [/* 32 vars */]) = -1 ENOENT (No such file or directory)
# strace -f chroot /mnt/foo /bin/ls
execve("/usr/sbin/chroot", ["chroot", "/mnt/foo", "/bin/ls"], [/* 32 vars */]) = 0
brk(0)                                  = 0x1985000
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) = 0x7fc115ac8000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=96457, ...}) = 0
mmap(NULL, 96457, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc115ab0000
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|O_CLOEXEC) = 3
read(3, "7ELF%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0%pre%%pre%%pre%%pre%%pre%"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1853400, ...}) = 0
mmap(NULL, 3961912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc1154e0000
mprotect(0x7fc11569d000, 2097152, PROT_NONE) = 0
mmap(0x7fc11589d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fc11589d000
mmap(0x7fc1158a3000, 17464, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc1158a3000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc115aaf000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc115aad000
arch_prctl(ARCH_SET_FS, 0x7fc115aad740) = 0
mprotect(0x7fc11589d000, 16384, PROT_READ) = 0
mprotect(0x606000, 4096, PROT_READ)     = 0
mprotect(0x7fc115aca000, 4096, PROT_READ) = 0
munmap(0x7fc115ab0000, 96457)           = 0
brk(0)                                  = 0x1985000
brk(0x19a6000)                          = 0x19a6000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=8463952, ...}) = 0
mmap(NULL, 8463952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc114ccd000
close(3)                                = 0
chroot("/mnt/foo")                      = 0
chdir("/")                              = 0
execve("/bin/ls", ["/bin/ls"], [/* 32 vars */]) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = -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/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory)
write(2, "chroot: ", 8chroot: )                 = 8
write(2, "failed to run command 200/bin/ls"..., 35failed to run command ‘/bin/ls’) = 35
open("/usr/share/locale/en_US/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)
open("/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": No such file or directory", 27: No such file or directory) = 27
write(2, "\n", 1
)                       = 1
close(1)                                = 0
close(2)                                = 0
exit_group(127)                         = ?
+++ exited with 127 +++
%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0%pre%%pre%%pre%%pre%%pre%"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1853400, ...}) = 0 mmap(NULL, 3961912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc1154e0000 mprotect(0x7fc11569d000, 2097152, PROT_NONE) = 0 mmap(0x7fc11589d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fc11589d000 mmap(0x7fc1158a3000, 17464, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc1158a3000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc115aaf000 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc115aad000 arch_prctl(ARCH_SET_FS, 0x7fc115aad740) = 0 mprotect(0x7fc11589d000, 16384, PROT_READ) = 0 mprotect(0x606000, 4096, PROT_READ) = 0 mprotect(0x7fc115aca000, 4096, PROT_READ) = 0 munmap(0x7fc115ab0000, 96457) = 0 brk(0) = 0x1985000 brk(0x19a6000) = 0x19a6000 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=8463952, ...}) = 0 mmap(NULL, 8463952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc114ccd000 close(3) = 0 chroot("/mnt/foo") = 0 chdir("/") = 0 execve("/bin/ls", ["/bin/ls"], [/* 32 vars */]) = -1 ENOENT (No such file or directory) open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = -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/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/lib/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory) write(2, "chroot: ", 8chroot: ) = 8 write(2, "failed to run command 200/bin/ls"..., 35failed to run command ‘/bin/ls’) = 35 open("/usr/share/locale/en_US/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) open("/usr/share/locale-langpack/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory) write(2, ": No such file or directory", 27: No such file or directory) = 27 write(2, "\n", 1 ) = 1 close(1) = 0 close(2) = 0 exit_group(127) = ? +++ exited with 127 +++

Então, isso é ENOENT enganoso?

YES - ENOENT é um pouco enganador. Para mim sempre significou "arquivo não encontrado".

Quando o vinculador dinâmico não pode ser encontrado, o execve () obtém ENOENT.

Quando o kernel de inicialização tenta carregar init (ou linuxrc ou qualquer outro), o erro que recebo é " Falha ao executar / linuxrc (erro -2). Tentando padrões ... " .

O problema aconteceu devido a um bug no meu script que criou esse ramdisk inicial. (omitiu bibliotecas não apontadas por "= >" por ldd ).

Duas perguntas bônus para ponderar créditos extras:

  • o que é linux-vdso.so.1 que ldd mostra sem um caminho?
  • por que ldd mostra ld-linux.so sem um " => "?
por MattBianco 23.07.2014 / 10:15

1 resposta

3

O problema é que /bin/ls não precisa apenas das bibliotecas compartilhadas que você forneceu. Também precisa do programa que os carrega; o carregador do linux.

Para resolver seu problema, você pode copiar o carregador de seu sistema (geralmente /lib/ld-linux.so.2 ) para o local do seu chroot ( /mnt/foo/lib/ld-linux.so.2 ).

    
por 23.07.2014 / 10:30