There are 2 bugs here: When we use ldconfig with -r option like usual user we use absolute path to aux-cache file without any changes according to the new root. When we use ldconfig with -r option like usual user we do not check if the symbolic link in our new root points outside of our root and we need "normalize" the name according to -r option. (We have a link to /lib/ourlib and stat this link instead of /our_new_root/lib/ourlib) I am proposing the patch against 2.11.1 here: --- orig/glibc-2.11.1/elf/ldconfig.c 2009-12-08 22:10:20.000000000 +0200 +++ patch/glibc-2.11.1/elf/ldconfig.c 2010-01-08 18:10:32.000000000 +0200 @@ -118,6 +118,9 @@ /* Cache file to use. */ static char *cache_file; +/* Aux cache file to use. */ +static char *aux_cache_file; + /* Configuration file. */ static const char *config_file; @@ -790,6 +793,34 @@ lstat_buf.st_ino = stat_buf.st_ino; lstat_buf.st_size = stat_buf.st_size; lstat_buf.st_ctime = stat_buf.st_ctime; + + /* We need to check if it is link outside of new root + and stat returns to us different info than real chroot. */ + if (opt_chroot) + { + char *real_name = chroot_canon (opt_chroot, file_name); + if (real_name == NULL) + { + if (strstr (file_name, ".so") == NULL) + error (0, 0, _("Input file %s not found.\n"), file_name); + continue; + } + if (__builtin_expect (stat64 (real_name, &stat_buf), 0)) + { + error (0, errno, _("Cannot stat %s"), real_name); + continue; + } + if (lstat_buf.st_dev != stat_buf.st_dev + || lstat_buf.st_ino != stat_buf.st_ino + || lstat_buf.st_size != stat_buf.st_size + || lstat_buf.st_ctime != stat_buf.st_ctime) + { + lstat_buf.st_dev = stat_buf.st_dev; + lstat_buf.st_ino = stat_buf.st_ino; + lstat_buf.st_size = stat_buf.st_size; + lstat_buf.st_ctime = stat_buf.st_ctime; + } + } } else is_dir = S_ISDIR (lstat_buf.st_mode); @@ -1346,8 +1377,39 @@ add_system_dir (LIBDIR); } + if (aux_cache_file == NULL) + { + aux_cache_file = alloca (strlen (_PATH_LDCONFIG_AUX_CACHE) + 1); + strcpy (aux_cache_file, _PATH_LDCONFIG_AUX_CACHE); + } + + if (opt_chroot) + { + /* Canonicalize the directory name of aux_cache_file, not aux_cache_file, + because we'll rename a temporary aux cache file to it. */ + char *p = strrchr (aux_cache_file, '/'); + char *canon = chroot_canon (opt_chroot, + p ? (*p = '\0', aux_cache_file) : "/"); + + if (canon == NULL) + { + error (EXIT_FAILURE, errno, + _("Can't open aux cache file directory %s\n"), + p ? aux_cache_file : "/"); + } + + if (p) + ++p; + else + p = aux_cache_file; + + aux_cache_file = alloca (strlen (canon) + strlen (p) + 2); + sprintf (aux_cache_file, "%s/%s", canon, p); + free (canon); + } + if (! opt_ignore_aux_cache) - load_aux_cache (_PATH_LDCONFIG_AUX_CACHE); + load_aux_cache (aux_cache_file); else init_aux_cache (); @@ -1356,7 +1418,7 @@ if (opt_build_cache) { save_cache (cache_file); - save_aux_cache (_PATH_LDCONFIG_AUX_CACHE); + save_aux_cache (aux_cache_file); } return 0; I checked the newest 2.12, we still have it.
I agree with the aux cache file setting (although I used a simpler patch). You will have to explain the second part. Describe the setup you think creates a problem.
I use maemo SDK+. It does not use chroot. I launch ldconfig -r /our_new_root. It finds link to /lib/ourlib inside /our_new_root and tries to stat /lib/ourlib. But we specify -r /our_new_root. So it shall stat /our_new_root/lib/ourlib according to -r options. My patch provides this functionality. Thank you.
(In reply to comment #2) > I use maemo SDK+. It does not use chroot. I launch ldconfig -r /our_new_root. It > finds link to /lib/ourlib inside /our_new_root and tries to stat /lib/ourlib. Explain exactly where the link is located etc. I need to be able to reproduce this here.
#pwd /lib #ls -la somelib somelib.ln -> somelib #pwd ~/our_new_root/lib #ls -la somelib somelib.ln -> somelib ldconfig searchs it in aux cache (search_aux_cache), does not find, tries to add (add_to_aux_cache) and aborts when tries to insert. Please, ask me if it is not enough. Thank you.
(In reply to comment #4) > Please, ask me if it is not enough. Thank you. It isn't enough. First, files named somelib are ignored because they don't look like libraries. I asked for the exact situation, not some general idea. Second, even if I'm using a real library with its real name and then a link I see no accesses outside the chroot: I copied libc.so in a chroot tree and added libc.so.6 as a symlink. The only accesses to libc.so of ldconfig -r $PWD/testroot are: lstat("$PWD/testroot/lib64/libc.so", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 open("$PWD/testroot/lib64/libc.so", O_RDONLY) = 4 stat("$PWD/testroot/lib64/libc.so.6", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 lstat("$PWD/testroot/lib64/libc.so.6", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0 readlink("$PWD/testroot/lib64/libc.so.6", "libc.so", 4096) = 7 lstat("$PWD/testroot/lib64/libc.so", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 lstat("$PWD/testroot/lib64/libc.so.6", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0 lstat("$PWD/testroot/lib64/libc.so.6", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0 readlink("$PWD/testroot/lib64/libc.so.6", "libc.so", 4096) = 7 lstat("$PWD/testroot/lib64/libc.so", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 stat("$PWD/testroot/lib64/libc.so", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 lstat("$PWD/testroot/lib64/libc.so", {st_mode=S_IFREG|0775, st_size=9166760, ...}) = 0 write(3, "libc.so.6\0/lib64/libc.so.6\0", 27) = 27 I have of course replace the real path with $PWD in the output. But as you can see there is no access outside the chroot. Either provide _exact_ instructions for how to show the problem or close the bug. And make sure you're using current sources.
I am sorry. I built glibc-2.11.1 on top of my ubuntu jaunty. There are minimum settings: # pwd /home/user/testroot # find . ./lib ./lib/libBrokenLocale.so.1 ./lib/libBrokenLocale-2.8.so ./etc ./etc/ld.so.conf ./var ./var/cache ./usr ./usr/lib ./usr/lib/libBrokenLocale.so # pwd /home/user/testroot/lib # ls -l -rw-r--r-- 1 user user 5484 2010-02-23 15:55 libBrokenLocale-2.8.so lrwxrwxrwx 1 user user 22 2010-04-12 20:27 libBrokenLocale.so.1 -> libBrokenLocale-2.8.so # pwd /home/user/testroot/usr/lib # ls -l lrwxrwxrwx 1 user user 25 2010-04-12 20:26 libBrokenLocale.so -> /lib/libBrokenLocale.so.1 And when I launch ldconfig it is aborted: # ./ldconfig -r /home/user/testroot/ Aborted It shall be enough. It was three months ago, I am sorry again.
OK, I fixed it now. The patch differes from yours.
Thanks a lot. Could you provide version number where can I verify it, please. Thank you.
Version 2.12 should have the fix, as well as 2.11.2.
I checked glibc-2.11.2. It is still aborted. Will continue soon. Many thanks.
Excuse me. It works fine. It was my mistake. Thanks a lot. Verified.
Unfortunately, the aux_cache change introduced a bug - normally, ldconfig -r never cares if the auxiliary cache is not available and that is not a fatal problem, however this is not the case in case of ldconfig -r when executed as non-root. In that case, ldconfig -r fails hard unless var/cache/ldconfig/ exists within the chroot. Patch to follow.
Created attachment 4825 [details] proposed patch
This has long since been fixed.