severity 731082 important
retitle 731082 ld.so.cache parsing code does not deal with mixed endianess 
multiarch, causing segfaults
reassign 731082 libc6
thanks

Michael Tokarev wrote...

> 01.12.2013 23:27, Marc Glisse wrote:
> []
> > I managed to run:
> > $ qemu-ppc-static /lib/powerpc-linux-gnu/libc.so.6
> > 
> > which prints the usual text, but so far that's the only program that
> > hasn't failed with:
> > 
> > $ qemu-ppc-static ./bin/true
> > Invalid data memory access: 0xb6d15008
> [...]
> 
> > Other people seem to have more luck, but I have mostly read posts about
> > debootstrap or chroots, not about multiarch setups.
> 
> I've never tried multiarch setup, never ever considered it.
> Only on second read of your bugreport I realized you're not
> running it in chroot but on real root with multiarch instead.
> 
> And now I realize that I don't even know how to do that.
> I don't really want to mess with my regular system (unless
> it is something easy, like just libc6), so it looks I'll
> have to try multiarch-within-chroot.
> 
> Can you provide some details about how this kind of multiarch
> system can be set up, pleae?
> 
> Note: I verified several arches from qemu-user-static in foreign
> chroots (using debootstrap --arch=powerpc in this case), and it
> works quite well.  But it never occured to me to test in a live
> system..
> 
> > According to strace, the segfault happens just after closing
> > /etc/ld.so.cache. On arm, that's followed by a second check for
> > /etc/ld.so.nohwcap and then looking everywhere for libc.so.6.
> 
> Might it be due to some differences within ld.so.cache?  I mean,
> when it has stuff from several architectures, does the runtime
> linker actually work right?  I dunno.

Quite close. The problem is not architectures per se, it's endianess:
powerpc is big endian, amd64 and armel/armhf are little endian. That's
why armhf was no problem for you.

The content of /etc/ld.so.cache is in the host architecture, probably
the one of ldconfig, for example:

amd64:
                                               vvvvvvvvvvv = 0x32e nlibs
00000000  6c 64 2e 73 6f 2d 31 2e  37 2e 30 00 2e 03 00 00  |ld.so-1.7.0.....|
00000010  03 03 00 00 80 4c 00 00  8d 4c 00 00 03 03 00 00  |.....L...L......|

powerpc:
                                               vvvvvvvvvvv = 0x90 nlibs
00000000  6c 64 2e 73 6f 2d 31 2e  37 2e 30 00 00 00 00 90  |ld.so-1.7.0.....|
00000010  00 00 00 03 00 00 0d 98  00 00 0d a2 00 00 00 03  |................|


However the loader code in elf/dl-cache.c always treats the content
in his own endianess, like in line 278 (content mapped to struct
cache_file *cache):

      cache_data = (const char *) &cache->libs[cache->nlibs];

which is likey the code line that causes the segfault due to a
ludicrous value of nlibs if read in the wrong endianess.


Fastest way to reproduce probably is

# dpkg --add-architecture <arch>
  where <arch> has different endianess
* Install qemu-user-static
* Run a program in the foreign architecture, using qemu-*-static

Debugging is eased a bit by setting LD_DEBUG=all btw, last messages
here were

    8273:     file=libselinux.so.1 [0];  needed by /usr/bin/<redacted> [0]
    8273:     find library=libselinux.so.1 [0]; searching
    8273:      search cache=/etc/ld.so.cache


No idea for a simple fix. Personally, I'd change ld.so.cache to
ld.so.cache.<triple> since I doubt mixing different archs' shared
objects makes any sense. If I'm wrong, split at least for endianess.
Worst approach: Guess the file's endianess from nlibs, and switch all
values when required.

(Re-assigning to libc)

    Christoph

Attachment: signature.asc
Description: Digital signature

Reply via email to