Hi, My previous patch is incorrect : changing root to a path with a trailing slash produces an error.
me@localhost:~$ fakechroot fakeroot -i .fakeroot.state -s .fakeroot.state chroot mychroot1/ root@localhost:~/mychroot1# ls . ls: cannot access '.': No such file or directory root@localhost:~/mychroot1# printenv FAKECHROOT_BASE /home/me/mychroot1/ root@localhost:~/mychroot1# exit me@localhost:~$ fakechroot fakeroot -i .fakeroot.state -s .fakeroot.state chroot mychroot1 root@localhost:/# ls . bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@localhost:/# printenv FAKECHROOT_BASE /home/me/mychroot1 (correct behavior) The same error message occurs at chroot(2) invocation in a program with the unpatched version 2.18-1 of fakechroot : me@localhost:~$ fakechroot fakeroot -i .fakeroot.state -s .fakeroot.state chroot mychroot1/ root@localhost:/# cd home/me1/ root@localhost:/home/me1# ./chroot_test mychroot2/ ./chroot_test : changing root to mychroot2/ chroot : result=0 ls: cannot access '.': No such file or directory ls : result=512 root@localhost:/home/me1# ./chroot_test /home/me1/mychroot2/ ./chroot_test : changing root to /home/me1/mychroot2/ chroot : result=0 ls: cannot access '.': No such file or directory ls : result=512 root@localhost:/home/me1# ./chroot_test mychroot2 ./chroot_test : changing root to mychroot2 chroot : result=0 bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var ls : result=0 (correct behavior) Here are two revised patches in the attachment to recover the correct behavior in these use cases. Regards, JH Chatenet #-------------------8<--------- file chroot_test.c -------8<------------- #include <unistd.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[]) { int result = 0; if (argv[1] == NULL) return 1; printf("%s : changing root to %s\n", argv[0], argv[1]); result = chroot(argv[1]); printf("chroot : result=%i\n", result); result = system("cd / && ls ."); printf("ls : result=%i\n", result); return 0; } #-------------------8<-------------------------------------8<-------------
--- a/scripts/chroot.fakechroot.sh +++ b/scripts/chroot.fakechroot.sh @@ -39,6 +39,12 @@ fakechroot_chroot_base="$FAKECHROOT_BASE_ORIG" +# records the content of LD_LIBRARY_PATH at first chroot invocation +if [ -z "$fakechroot_chroot_base" -a -n "$LD_LIBRARY_PATH" ]; then + FAKECHROOT_LDLIBPATH="$LD_LIBRARY_PATH" + export FAKECHROOT_LDLIBPATH +fi + fakechroot_chroot_n=1 for fakechroot_chroot_opt in "$@"; do case "$fakechroot_chroot_opt" in @@ -46,36 +52,42 @@ continue ;; *) - fakechroot_chroot_newroot="$fakechroot_chroot_opt" + fakechroot_chroot_requested_newroot="$fakechroot_chroot_opt" break ;; esac fakechroot_chroot_n=$(($fakechroot_chroot_n + 1)) done +# absolute paths in fakechroot_chroot_opt are relative to FAKECHROOT_BASE_ORIG +if [ "${fakechroot_chroot_requested_newroot#/}" != "$fakechroot_chroot_requested_newroot" ]; then + fakechroot_chroot_newroot="${fakechroot_chroot_base}${fakechroot_chroot_requested_newroot}" +else + fakechroot_chroot_newroot="$fakechroot_chroot_requested_newroot" +fi if [ -d "$fakechroot_chroot_newroot" ]; then - fakechroot_chroot_newroot=`cd "$fakechroot_chroot_opt"; pwd -P` + fakechroot_chroot_newroot=`cd "$fakechroot_chroot_newroot"; pwd -P` fakechroot_chroot_paths= # append newroot to each directory from original LD_LIBRARY_PATH fakechroot_chroot_IFS_bak="$IFS" IFS=: - for fakechroot_chroot_d in $LD_LIBRARY_PATH; do - fakechroot_chroot_paths="${fakechroot_chroot_paths:+$fakechroot_chroot_paths:}$fakechroot_chroot_base$fakechroot_chroot_newroot/${fakechroot_chroot_d#/}" + for fakechroot_chroot_d in $FAKECHROOT_LDLIBPATH; do + fakechroot_chroot_paths="${fakechroot_chroot_paths:+$fakechroot_chroot_paths:}$fakechroot_chroot_newroot/${fakechroot_chroot_d#/}" done IFS="$fakechroot_chroot_IFS_bak" # append newroot to each directory from new /etc/ld.so.conf fakechroot_chroot_paths_ldsoconf="" if [ -f "$fakechroot_chroot_newroot/etc/ld.so.conf" ]; then - fakechroot_chroot_paths_ldsoconf=`fakechroot_chroot_load_ldsoconf "/etc/ld.so.conf" "$fakechroot_chroot_newroot" | while read fakechroot_chroot_line; do printf ":%s%s" "$fakechroot_chroot_base" "$fakechroot_chroot_line"; done` + fakechroot_chroot_paths_ldsoconf=`fakechroot_chroot_load_ldsoconf "/etc/ld.so.conf" "$fakechroot_chroot_newroot" | while read fakechroot_chroot_line; do printf ":%s" "$fakechroot_chroot_line"; done` elif [ -d "$fakechroot_chroot_newroot/etc/ld.so.conf.d" ]; then - fakechroot_chroot_paths_ldsoconf=`fakechroot_chroot_load_ldsoconf "/etc/ld.so.conf.d/*" "$fakechroot_chroot_newroot" | while read fakechroot_chroot_line; do printf ":%s%s" "$fakechroot_chroot_base" "$fakechroot_chroot_line"; done` + fakechroot_chroot_paths_ldsoconf=`fakechroot_chroot_load_ldsoconf "/etc/ld.so.conf.d/*" "$fakechroot_chroot_newroot" | while read fakechroot_chroot_line; do printf ":%s" "$fakechroot_chroot_line"; done` fi fakechroot_chroot_paths_ldsoconf="${fakechroot_chroot_paths_ldsoconf#:}" - fakechroot_chroot_paths="$fakechroot_chroot_paths${fakechroot_chroot_paths_ldsoconf:+:$fakechroot_chroot_paths_ldsoconf}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" + fakechroot_chroot_paths="$fakechroot_chroot_paths${fakechroot_chroot_paths_ldsoconf:+:$fakechroot_chroot_paths_ldsoconf}${FAKECHROOT_LDLIBPATH:+:$FAKECHROOT_LDLIBPATH}" fakechroot_chroot_paths="${fakechroot_chroot_paths#:}" fi --- a/src/libfakechroot.c +++ b/src/libfakechroot.c @@ -56,6 +56,7 @@ "FAKECHROOT_ELFLOADER", "FAKECHROOT_ELFLOADER_OPT_ARGV0", "FAKECHROOT_EXCLUDE_PATH", + "FAKECHROOT_LDLIBPATH", "FAKECHROOT_VERSION", "FAKEROOTKEY", "FAKED_MODE",
Fix chroot.c for absolute paths in case of a double chroot. --- a/src/chroot.c +++ b/src/chroot.c @@ -71,8 +71,11 @@ return -1; } - if (fakechroot_base != NULL && strstr(cwd, fakechroot_base) == fakechroot_base) { + if (fakechroot_base != NULL && strstr(cwd, fakechroot_base) == cwd) { expand_chroot_path(path); + strlcpy(tmp, path, FAKECHROOT_PATH_MAX); + dedotdot(tmpptr); + path = tmpptr; } else { if (*path == '/') { @@ -88,6 +91,11 @@ } } + /* Suppress a trailing slash */ + if ((strlen(tmpptr) > 1) && path[strlen(tmpptr) - 1] == '/') { + tmpptr[strlen(tmpptr) - 1] = '\0'; + } + if ((status = STAT(path, &sb)) != 0) { return status; }