Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 545006

Summary: sys-libs/musl: expand ldconfig support
Product: Gentoo Linux Reporter: Felix Janda <felix.janda>
Component: [OLD] Core systemAssignee: Anthony Basile <blueness>
Status: RESOLVED FIXED    
Severity: normal CC: lu_zero, toolchain, ttilley
Priority: Normal    
Version: unspecified   
Hardware: All   
OS: Linux   
Whiteboard:
Package list:
Runtime testing required: ---
Bug Depends on:    
Bug Blocks: 430702    
Attachments: Proposed patch against ldconfig-0.1
Proposed patch against ldconfig-0.1

Description Felix Janda 2015-03-29 22:54:55 UTC
musl libc has its own dynamic linker with different behavior than glibc's.

In particular, it builds its search path from /etc/ld-musl-$LDSO_ARCH.path
instead of /lib/ld.so.cache. Therefore musl based system need a different
ldconfig program to generate the path file from /lib/ld.so.conf.

There is a prototype program as sys-apps/ldconfig in the musl branch of
hardened-development. It is however not ready yet for being used.
Therefore currently users must be very careful when upgrading gcc.

This bug aims to track progress on creating a functional ldconfig.


Reproducible: Always
Comment 1 Felix Janda 2015-03-29 23:02:06 UTC
Created attachment 400100 [details, diff]
Proposed patch against ldconfig-0.1

- Let ldconfig also read files in /lib/ld.so.conf.d/*
- Give /etc/ld-musl-$LDSO_ARCH.path the right permissions
- If there are multiple /lib/ld-musl-*.so.1 create a path file for any of them
- There should not be comments in /etc/ld-musl-$LDSO_PATH.path
- Don't error out for the unimplemented options (This needs some more thought.)

The patched ldconfig creates a functional path file at least on my system.
Comment 2 Anthony Basile gentoo-dev 2015-03-30 22:48:05 UTC
(In reply to Felix Janda from comment #1)
> Created attachment 400100 [details, diff] [details, diff]
> Proposed patch against ldconfig-0.1
> 
> - Let ldconfig also read files in /lib/ld.so.conf.d/*
> - Give /etc/ld-musl-$LDSO_ARCH.path the right permissions
> - If there are multiple /lib/ld-musl-*.so.1 create a path file for any of
> them
> - There should not be comments in /etc/ld-musl-$LDSO_PATH.path
> - Don't error out for the unimplemented options (This needs some more
> thought.)
> 
> The patched ldconfig creates a functional path file at least on my system.

Does this fix the issue I was having, namely that my ldconfig would break a system?  (I thought of something like this but ran out of time to work on it.)  If so, I'm wondering if we shouldn't just bundle this with the musl ebuild.  I'm going to push out musl-1.1.8 without ldconfig to build the stage tarballs.  I'll then test and if this works, I'll push out 1.1.8-r1 ~arch with this.  Comments?

+	X=$(mktemp --tmpdir=/tmp ${LDSO_NAME}.XXXXXX)
+	for d in $drs; do
+		echo $d >> $X
+	done
+	mv $X $ETC_LDSO_PATH
+	chmod 644 $ETC_LDSO_PATH
Comment 3 Felix Janda 2015-03-31 10:33:01 UTC
Yes, without explicitely setting the permissions, they would be 600 and dynamic linking breaks for all non-root users. Actually, I now think it's better to set the right permissions before moving in order to have an atomic upgrade.

In addition, in order to get the path for libgcc, parsing the files in /etc/ld.conf.d/  is necessary.

Please test!
Comment 4 Anthony Basile gentoo-dev 2015-04-02 16:51:37 UTC
(In reply to Felix Janda from comment #3)
> Yes, without explicitely setting the permissions, they would be 600 and
> dynamic linking breaks for all non-root users. Actually, I now think it's
> better to set the right permissions before moving in order to have an atomic
> upgrade.

I'm not sure the permissions was everything because I was doing this as root in a chroot env.  But I could have been missing something.

> 
> In addition, in order to get the path for libgcc, parsing the files in
> /etc/ld.conf.d/  is necessary.

Yes

> 
> Please test!

musl 1.1.8 brings in a servious fix so I think we need more time to test this in the wild before I begin bundling it with the musl ebuild.
Comment 5 Felix Janda 2015-04-03 16:17:11 UTC
Created attachment 400488 [details, diff]
Proposed patch against ldconfig-0.1

A new version with a shorter diff against ldconfig-0.1:
* Don't complete ignore -f option
* Read from /etc/ld.so.conf.d/*
* Get correct dynamic linker from /bin/bash using readelf.
* Set correct permissions for the temporary file before moving it

It is safe to assume that bash is dynamically linker against musl?
Comment 6 Anthony Basile gentoo-dev 2015-04-04 21:26:05 UTC
(In reply to Felix Janda from comment #5)
> Created attachment 400488 [details, diff] [details, diff]
> Proposed patch against ldconfig-0.1
> 
> A new version with a shorter diff against ldconfig-0.1:
> * Don't complete ignore -f option
> * Read from /etc/ld.so.conf.d/*
> * Get correct dynamic linker from /bin/bash using readelf.
> * Set correct permissions for the temporary file before moving it
> 
> It is safe to assume that bash is dynamically linker against musl?


LDSO_PATH=$(readelf -l /bin/bash | grep -o '\/lib\/ld-musl-.*\.so\.1')

1) The system may not have bash.  In all likelihood it will, but it might be the case that some POSIX purest wants just dash for instance.  

2) We can't use /bin/sh since it might be a sym link to a busybox which might be statically linked.  In this case $LDSO_PATH will be an empty variable and badness will ensue.

3) This approache creates a dependency on binutils which is probably okay, but you might want to be carefull.  Sometimes I build little images where i eventually remove binutils/gcc (among other stuff).  Of course when you do you might say, no need to run ldconfig after that, but it'll still be on the system and will produce an empty $LDSO_PATH variable again.

I'm still feeling safer with my original LDSO_PATH=$(ls /lib/ld-musl-*.so.1)
Comment 7 Anthony Basile gentoo-dev 2015-04-04 22:37:15 UTC
(In reply to Anthony Basile from comment #6).
> 
> I'm still feeling safer with my original LDSO_PATH=$(ls /lib/ld-musl-*.so.1)

Okay I pushed this without bump.  I did switch to LDSO_PATH=$(ls /lib/ld-musl-*.so.1) but I also have LDSO_PATH=$(readelf -l /bin/bash | grep -o '\/lib\/ld-musl-.*\.so\.1') in there but commented out, for testing.

I'm going to do a full rebuild of @system in a chroot on amd64 to see how this goes.
Comment 8 Anthony Basile gentoo-dev 2015-04-04 23:01:16 UTC
(In reply to Felix Janda from comment #5)

> * Read from /etc/ld.so.conf.d/*

Actually my original script had that with expanded().  This is redundant:

for f in $LDSO_CONF.d/*; do
        drs="$drs $(read_ldso_conf "$f")"
done

I'm testing that now.
Comment 9 Anthony Basile gentoo-dev 2015-04-05 11:29:05 UTC
Another point to note is that effectively this script is `ldconfig -X` since it does not update sym links to the most recent .so's, and of course doesn't deal with -N + -X logic.  This is sufficient for portage, but it may not be what the user expects.  So i'm going to change the getopts to print out an warning if -X is missing, not if its present.
Comment 10 Felix Janda 2015-04-05 14:27:32 UTC
(In reply to Anthony Basile from comment #8)
> (In reply to Felix Janda from comment #5)
> 
> > * Read from /etc/ld.so.conf.d/*
> 
> Actually my original script had that with expanded().  This is redundant:
> 
> for f in $LDSO_CONF.d/*; do
>         drs="$drs $(read_ldso_conf "$f")"
> done
> 
> I'm testing that now.

If you remove this, hell will break loose because libgcc_s.so will not be found anymore. (Unless I understand you wrong.) This is very likely exactly the problem you had with the original script.
Comment 11 Felix Janda 2015-04-05 14:53:25 UTC
Also, when including an ldconfig with the musl ebuild we make it
tailored for the $LDSO_ARCH.
Comment 12 Anthony Basile gentoo-dev 2015-04-06 00:19:02 UTC
(In reply to Felix Janda from comment #10)
> (In reply to Anthony Basile from comment #8)
> > (In reply to Felix Janda from comment #5)
> > 
> > > * Read from /etc/ld.so.conf.d/*
> > 
> > Actually my original script had that with expanded().  This is redundant:
> > 
> > for f in $LDSO_CONF.d/*; do
> >         drs="$drs $(read_ldso_conf "$f")"
> > done
> > 
> > I'm testing that now.
> 
> If you remove this, hell will break loose because libgcc_s.so will not be
> found anymore. (Unless I understand you wrong.) This is very likely exactly
> the problem you had with the original script.

The problem is that env-update is not including a line that looks like

include ld.so.conf.d/*.conf

when generating the ld.so.conf file.  This is the problem, not the ldconfig script as written.  Notice what this does:

		next=0
		for l in $line; do
			if [[ $next == 1 ]]; then
				next=0
				drs=$(expand $l $drs)
			elif [[ $l == "include" ]]; then
				next=1
			else
				if [[ -d $l ]]; then
					repeated $l $drs && continue
					drs+=" $l "
				fi
			fi
		done


When "include" is encountered, it skips it and set 'next=1' and then on the next token runs expand() which reads ld.so.conf.d/*.conf.  If that line were in the ld.so.conf file, it would work but right now env-update is not adding it.  So this tells me something needs to be fixed in env-update, not the ldconfig script.

Here's what happens when you run it manually:

yellow ~ # cat /etc/ld.so.confy
/lib
/usr/lib
/usr/local/lib
include ld.so.conf.d/*.conf
yellow ~ # ls /etc/ld.so.conf.d/
05binutils.conf  05gcc-x86_64-gentoo-linux-musl.conf
yellow ~ # ldconfig 
yellow ~ # cat /etc/ld-musl-x86_64.path
/lib
/usr/lib
/usr/local/lib
/usr/x86_64-gentoo-linux-musl/lib
/usr/lib/gcc/x86_64-gentoo-linux-musl/4.8.4

as expected.  However, if you run env-update, here's what the ld.so.conf file looks like:

yellow ~ # env-update 
>>> Regenerating /etc/ld.so.cache...
yellow ~ # cat /etc/ld.so.conf
# ld.so.conf autogenerated by env-update; make all changes to
# contents of /etc/env.d directory
/lib
/usr/lib
/usr/local/lib

Note the include ld.so.conf.d/*.conf was removed.  Running ldconfig now misses stuff the stuff from ld.so.conf.d/*.conf and we get the failure.

Adding 

for f in $LDSO_CONF.d/*; do
        drs="$drs $(read_ldso_conf "$f")"
done

is wrong because the include line point to something other than $LDSO_CONF.d/*.  We must reproduce the original ldconfig as best possible so that we don't break standards and confuse users.
Comment 13 Anthony Basile gentoo-dev 2015-04-06 00:21:42 UTC
(In reply to Anthony Basile from comment #12)

> is wrong because the include line point to something other than
> $LDSO_CONF.d/*.  We must reproduce the original ldconfig as best possible so
> that we don't break standards and confuse users.

sorry that should read "the include line *may* point to something other than"
Comment 14 Felix Janda 2015-04-06 06:52:42 UTC
Thanks for explaining. (I somehow had the impression /etc/ld.so.conf.d
was standard.)

I agree that this seems to be a problem of env-update. Usually there
is 00glibc generated by sys-libs/glibc/files/eblits/src_install.eblit
with the line 'LDPATH="include ld.so.conf.d/*.conf'" but other tools
like gcc-config also assume that ld.so.conf.d/*.conf are included. So
the 'LDPATH="include ld.so.conf.d/*.conf'" should better be in 00basic.
Comment 15 SpanKY gentoo-dev 2015-04-06 07:23:29 UTC
(In reply to Felix Janda from comment #14)

not every C library supports ld.so.conf.d, so each C lib has to opt into it.  putting it into 00basic would be wrong.

gcc-config & binutils-config are explicitly designed to support both the dir and the flat file.  if the dir exists, they assume the system supports it.  this isn't a bug on their part.
Comment 16 Felix Janda 2015-04-06 08:19:12 UTC
I see, e.g. uclibc's ldconfig does not support include statements.

So we should create an /etc/env.d/00musl.
(Or rip out the include statement handling to be more like uclibc...)
Comment 17 Felix Janda 2015-04-06 14:44:18 UTC
Small fix:

--- a/ldconfig-0.1	2015-04-06 16:35:30.000000000 -0200
+++ b/ldconfig-0.1	2015-04-06 16:35:39.217604221 -0200
@@ -29,7 +29,7 @@
 			echo "Invalid option: -$opt" >&2
 			exit 1
 			;;
-		n|N|X|C)
+		n|N|X|C|p)
 			echo "Unimplemented option: -$opt" >&2
 			exit 1
 			;;
Comment 18 Anthony Basile gentoo-dev 2015-04-08 00:28:18 UTC
(In reply to Felix Janda from comment #16)
> I see, e.g. uclibc's ldconfig does not support include statements.
> 
> So we should create an /etc/env.d/00musl.
> (Or rip out the include statement handling to be more like uclibc...)

I went with this option.  I like the include option.
Comment 19 Anthony Basile gentoo-dev 2015-04-15 23:13:14 UTC
This is now in the tree with 1.1.8-r1 and 9999.  I also coalesced sys-app/getent with musl.  I think it was a bad idea to break it out into its own packages.

Please test and reopen this bug if there's some issue.
Comment 20 SpanKY gentoo-dev 2015-04-16 02:57:43 UTC
(In reply to Anthony Basile from comment #19)

getent is also a dedicated script in uClibc.  we could think about creating a common project on github or something for it.
Comment 21 Anthony Basile gentoo-dev 2015-04-16 21:49:35 UTC
(In reply to SpanKY from comment #20)
> (In reply to Anthony Basile from comment #19)
> 
> getent is also a dedicated script in uClibc.  we could think about creating
> a common project on github or something for it.

yep that's where i stole i from.  i did break out a copy which i'm hosting on my dev space so moving it to github might be a good idea, to give it more public exposure now that its being used in two libc's.

i still think keeping it as a separate package on the gentoo tree is excessive.  its a whole package for one file.  so in musl-1.1.8-r1 its being distributed in ${FILESDIR} and i plan to eventually mask/remove sys-apps/getent.  if we do put it on github, we can just add the url to the SRC_URI.

unless you think keeping it a separate package is a good idea, I'll eventually remove sys-apps/getent.
Comment 22 SpanKY gentoo-dev 2015-04-17 04:48:27 UTC
(In reply to Anthony Basile from comment #21)

i just worry about forking.  maybe fetch it directly from uClibc's git ?
Comment 23 Anthony Basile gentoo-dev 2015-04-17 16:17:44 UTC
(In reply to SpanKY from comment #22)
> (In reply to Anthony Basile from comment #21)
> 
> i just worry about forking.  maybe fetch it directly from uClibc's git ?

yeah i agree about the forking.  i'll come up with something where we stay in sync with uclibc automatically.