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;
     }

Reply via email to