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