;TL-DR - Answer: because the dynamic linker ld-linux-x86-64.so.2 was missing.
I have mounted a squashfs (shouldn't matter) filesystem -ro,loop
at /mnt/foo
.
It contains among other things the following (/mnt/foo
is the mount point):
-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
contains a single row (including newline) with just /lib
on it.
Before creating the file system, I ran ldconfig -r ${TOPDIR}
where ${TOPDIR}
resolved to the place that is now mounted at /mnt/foo
.
A strings
on /mnt/foo/etc/ld.so.cache
shows it contains strings like /lib/libpcre.so.3
and so on, so I don't think it is a problem with the shared libraries.
I figure it must be something silly I'm overlooking, but I cannot figure out myself why a simple chroot /mnt/foo /bin/ls
doesn't work.
readelf -d /mnt/foo/bin/ls | grep NEEDED
shows these libraries as needed:
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]
Finally, strace
shows this:
chroot("/mnt/foo") = 0 chdir("/") = 0 execve("/bin/ls", ["/bin/ls"], [/* 32 vars */]) = -1 ENOENT (No such file or directory)
This is the full strace chroot:
# 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, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\36\2\0\0\0\0\0"..., 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 \342\200\230/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 +++
So, is this ENOENT
misleading?
YES - ENOENT is a bit misleading. To me it has always meant "file not found".
When the dynamic linker cannot be found, execve() gets ENOENT.
When the booting kernel tries to load init
(or linuxrc or whatever), the error I get is "Failed to execute /linuxrc (error -2). Attempting defaults...".
The problem happened due to a bug in my script that created this initial ramdisk. (it omitted libraries not pointed out by "=>" by ldd
).
Two bonus questions to ponder for extra credits:
- what is
linux-vdso.so.1
thatldd
shows without a path? - why does
ldd
show ld-linux.so without a "=>
"?
ld-linux
!strace -s 1024
to get the full message ofstrace
.-s 1024
only shows more of the libc.so.6 contents.-s 0
? some lines likeexecve("/bin/ls", ["/bin/ls"], [/* 32 vars */])
is not printed enough.