mailing list of musl libc
 help / color / mirror / code / Atom feed
* be able to break inheritance of LD_LIBRARY_PATH
@ 2014-03-28 10:42 u-igbb
  2014-03-28 12:18 ` orc
                   ` (4 more replies)
  0 siblings, 5 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 10:42 UTC (permalink / raw)
  To: musl

Hello,

I was aware of musl for some time and now consider deploying it as
a default library for new software builds, due to its very appealing
virtues.

Yet there is a small but important issue.

For our software setup it is crucial (quite useful otherwise in general)
to be able to specify the location of the dynamic libraries per binary/run
_without_ the unconditional inheritance imposed by LD_LIBRARY_PATH.

A very nice solution would be the ability to explicitely run a standalone
dynamic loader, as implemented in both glibc and uclibc. We are heavily
relying on this functionality.

I do not know how hard it would be to teach the musl loader
to be runnable standalone and which corner cases this might create.

As a simpler approach I might suggest simply being able to drop
LD_LIBRARY_PATH as soon as it has been read. An extra environment
variable as a flag would do.

Compared to a standalone loader this lacks the ability to run
a binary with a different version of the loader/musl but at least
makes it straightforward and safe to freely specify where to find other
libraries.

A naïve implementation might look as follows:

--- src/ldso/dynlink.c.ori      2014-03-28 10:37:34.821317811 +0100
+++ src/ldso/dynlink.c  2014-03-28 11:21:16.828047766 +0100
@@ -962,6 +962,7 @@
        size_t vdso_base;
        size_t *auxv;
        char **envp = argv+argc+1;
+       int forget_ld_library_path = 0;
 
        /* Find aux vector just past environ[] */
        for (i=argc+1; argv[i]; i++)
@@ -969,8 +970,19 @@
                        env_path = argv[i]+16;
                else if (!memcmp(argv[i], "LD_PRELOAD=", 11))
                        env_preload = argv[i]+11;
+               else if (!memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
+                       forget_ld_library_path = 1;
        auxv = (void *)(argv+i+1);
 
+       /* one _may_ wish to break the inheritance of LD_LIBRARY_PATH,
+        * the hack below only works if the corresponding memory is writable
+        * -- rl */
+       if (forget_ld_library_path)
+               for (i=argc+1; argv[i]; i++)
+                       if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16) ||
+                           !memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
+                               argv[i][0] = 'X';
+
        decode_vec(auxv, aux, AUX_CNT);
 
        /* Only trust user/env if kernel says we're not suid/sgid */


What do you think about this? Can this or something better be done?
I would love to be able to go with musl.

Regards,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
@ 2014-03-28 12:18 ` orc
  2014-03-28 12:52   ` u-igbb
  2014-03-28 12:27 ` Alexander Monakov
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 18+ messages in thread
From: orc @ 2014-03-28 12:18 UTC (permalink / raw)
  To: musl

28 марта 2014 г. 18:42:08 KRAT, u-igbb@aetey.se пишет:
>Hello,
>
>I was aware of musl for some time and now consider deploying it as
>a default library for new software builds, due to its very appealing
>virtues.
>
>Yet there is a small but important issue.
>
>For our software setup it is crucial (quite useful otherwise in
>general)
>to be able to specify the location of the dynamic libraries per
>binary/run
>_without_ the unconditional inheritance imposed by LD_LIBRARY_PATH.
>
>A very nice solution would be the ability to explicitely run a
>standalone
>dynamic loader, as implemented in both glibc and uclibc. We are heavily
>relying on this functionality.
>
>I do not know how hard it would be to teach the musl loader
>to be runnable standalone and which corner cases this might create.
>
>As a simpler approach I might suggest simply being able to drop
>LD_LIBRARY_PATH as soon as it has been read. An extra environment
>variable as a flag would do.
>
>Compared to a standalone loader this lacks the ability to run
>a binary with a different version of the loader/musl but at least
>makes it straightforward and safe to freely specify where to find other
>libraries.
>
>A naïve implementation might look as follows:
>
>--- src/ldso/dynlink.c.ori      2014-03-28 10:37:34.821317811 +0100
>+++ src/ldso/dynlink.c  2014-03-28 11:21:16.828047766 +0100
>@@ -962,6 +962,7 @@
>        size_t vdso_base;
>        size_t *auxv;
>        char **envp = argv+argc+1;
>+       int forget_ld_library_path = 0;
> 
>        /* Find aux vector just past environ[] */
>        for (i=argc+1; argv[i]; i++)
>@@ -969,8 +970,19 @@
>                        env_path = argv[i]+16;
>                else if (!memcmp(argv[i], "LD_PRELOAD=", 11))
>                        env_preload = argv[i]+11;
>+               else if (!memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=",
>23))
>+                       forget_ld_library_path = 1;
>        auxv = (void *)(argv+i+1);
> 
>+       /* one _may_ wish to break the inheritance of LD_LIBRARY_PATH,
>+        * the hack below only works if the corresponding memory is
>writable
>+        * -- rl */
>+       if (forget_ld_library_path)
>+               for (i=argc+1; argv[i]; i++)
>+                       if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16) ||
>+                           !memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=",
>23))
>+                               argv[i][0] = 'X';
>+
>        decode_vec(auxv, aux, AUX_CNT);
> 
>        /* Only trust user/env if kernel says we're not suid/sgid */
>
>
>What do you think about this? Can this or something better be done?
>I would love to be able to go with musl.
>
>Regards,
>Rune

Such change should be maintained locally by you probably. While LD_PRELOAD/LD_LIBRARY_PATH environment variables are "standard" enough (widely known), introduction of extra variables that control various aspects of dynamic linker internals is becoming a pain, especially for people writing security related software. For example, I already maintain such a local change that introduces LD_NORPATH (disables reading DT_RPATHs from executable, and forces it for all setuids).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
  2014-03-28 12:18 ` orc
@ 2014-03-28 12:27 ` Alexander Monakov
  2014-03-28 13:04   ` u-igbb
  2014-03-28 13:17 ` Szabolcs Nagy
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 18+ messages in thread
From: Alexander Monakov @ 2014-03-28 12:27 UTC (permalink / raw)
  To: musl

Instead of patching the dynamic loader, you can supply an LD_PRELOAD module
that would remove/modify LD_LIBRARY_PATH appropriately at startup:

#include <stdlib.h>

void __attribute__((constructor))
remove_ld_l_p(void)
{
  unsetenv("LD_LIBRARY_PATH");
  unsetenv("LD_PRELOAD");
}


HTH.
Alexander


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 12:18 ` orc
@ 2014-03-28 12:52   ` u-igbb
  0 siblings, 0 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 12:52 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 08:18:28PM +0800, orc wrote:
> >As a simpler approach I might suggest simply being able to drop
> >LD_LIBRARY_PATH as soon as it has been read. An extra environment
> >variable as a flag would do.

> Such change should be maintained locally by you probably.

It is what I'd very much like to avoid.

Local patches need to be maintained and make it painful to upgrade. The
functionality which I ask for is otherwise quite general and useful
(otherwise neither glibc nor uclibc would bother implementing it).

> While LD_PRELOAD/LD_LIBRARY_PATH environment variables are "standard"
> enough (widely known), introduction of extra variables that control
> various aspects of dynamic linker internals is becoming a pain, especially

Sure. I would prefer standalone execution. LD_LIBRARY_PATH is pretty much
broken by design anyway.

> maintain such a local change that introduces LD_NORPATH (disables reading
> DT_RPATHs from executable, and forces it for all setuids).

Yes, rpath is bad. My "locally patched" uclibc dynamic loader ignores it
unconditionally, as a precaution. Even though the decision to use rpath
(or not) should be on the one who compiles, it is virtually impossible
to cope with endless variations of build tools which either hardcode
rpath presence or even lie about "not using" rpath.

Regards,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 12:27 ` Alexander Monakov
@ 2014-03-28 13:04   ` u-igbb
  0 siblings, 0 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 13:04 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 04:27:05PM +0400, Alexander Monakov wrote:
> Instead of patching the dynamic loader, you can supply an LD_PRELOAD module
> that would remove/modify LD_LIBRARY_PATH appropriately at startup:

Thanks for the suggestion Alexander,

but I do not feel this would be "good enough". What you propose is to mix
together two otherwise distinct mechanisms. I like to keep things
orthogonal, to avoid keeping in mind unrelated constraints.

A separate flag variable is both easier and safer to use than
handling LD_PRELOAD depending on whether/how it is used for other
purposes at the same time.

This would neither cover a situation when the dynamic loader would look
for "LD_LIBRARY_PATH" again _after_ having run preload. This is afaik not
the case with musl now and probably will never be but yet the assumption
relies on looking at the internals - conceptually as bad/good as patching
in the first hand.

Regards,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
  2014-03-28 12:18 ` orc
  2014-03-28 12:27 ` Alexander Monakov
@ 2014-03-28 13:17 ` Szabolcs Nagy
  2014-03-28 14:00   ` u-igbb
  2014-03-28 16:34 ` be able to break inheritance of LD_LIBRARY_PATH Daniel Cegiełka
  2014-03-28 19:46 ` Rich Felker
  4 siblings, 1 reply; 18+ messages in thread
From: Szabolcs Nagy @ 2014-03-28 13:17 UTC (permalink / raw)
  To: musl

* u-igbb@aetey.se <u-igbb@aetey.se> [2014-03-28 10:42:08 +0000]:
> For our software setup it is crucial (quite useful otherwise in general)
> to be able to specify the location of the dynamic libraries per binary/run
> _without_ the unconditional inheritance imposed by LD_LIBRARY_PATH.

why do you use LD_LIBRARY_PATH then?

> A very nice solution would be the ability to explicitely run a standalone
> dynamic loader, as implemented in both glibc and uclibc. We are heavily
> relying on this functionality.

what is a standalone dynamic loader and how does it solve the lib path?

if you mean a separate binary from libc.so, that does not matter much
(the loader and libc.so are interdependent on each other's internals
anyway, they are one logical unit even if in two separate files)

if you mean you can run '/lib/ld-linux.so.2 binary' then musl can do the same

> As a simpler approach I might suggest simply being able to drop
> LD_LIBRARY_PATH as soon as it has been read. An extra environment
> variable as a flag would do.

if you dont control the environment you will have other issues
(eg with LD_PRELOAD)

if you do control the env then just unset LD_LIBRARY_PATH

> Compared to a standalone loader this lacks the ability to run
> a binary with a different version of the loader/musl but at least
> makes it straightforward and safe to freely specify where to find other
> libraries.

the loader is whatever the PT_INTERP says in the elf header of the
binary, so you can set it per binary, but in general you want it to
be the same everywhere so binaries are portable
(there ar no "different versions of the loader" in musl)

in case you do a lot of lib path hacks note that the path lookup is
different in glibc than in musl:

glibc:
	1) DT_RPATH if no DT_RUNPATH is present (transitive)
	2) LD_LIBRARY_PATH
	3) DT_RUNPATH (eg set with --enable-new-dtags) (non-transitive)
	4) /etc/ld.so.cache (except with -z nodefaultlib)
	5) /lib:/usr/lib (except with -z nodefaultlib)

musl:
	1) LD_LIBRARY_PATH
	2) DT_RPATH (transitive)
	3) {interp}/../etc/ld-musl-arch.path or /lib:/usr/local/lib:/usr/lib


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 13:17 ` Szabolcs Nagy
@ 2014-03-28 14:00   ` u-igbb
  2014-03-28 15:25     ` Szabolcs Nagy
  2014-03-28 16:02     ` PATCH (Re: [musl] be able to break inheritance of LD_LIBRARY_PATH) u-igbb
  0 siblings, 2 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 14:00 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 02:17:19PM +0100, Szabolcs Nagy wrote:
> * u-igbb@aetey.se <u-igbb@aetey.se> [2014-03-28 10:42:08 +0000]:
> > For our software setup it is crucial (quite useful otherwise in general)
> > to be able to specify the location of the dynamic libraries per binary/run
> > _without_ the unconditional inheritance imposed by LD_LIBRARY_PATH.
> 
> why do you use LD_LIBRARY_PATH then?

I "do not". I am using the --library-path argument to the dynamic loader.
(Unless LD_LIBRARY_PATH is forced upon myself by someone else;
then I need protection from its potentially detrimental side effects)

Otherwise relying on LD_LIBRARY_PATH would be the only option.
(A hardwired library reference makes it impossible to replace
libraries otherwise than "in place", which is bad for many reasons)

> > A very nice solution would be the ability to explicitely run a standalone
> > dynamic loader, as implemented in both glibc and uclibc. We are heavily
> > relying on this functionality.

> if you mean you can run '/lib/ld-linux.so.2 binary' then musl can do the same

Thanks for pointing me in the right direction.

I was thinking of a "cheap and dirty workaround" while the most
appropriate is of course to add the missing argument parsing.

> if you dont control the environment you will have other issues
> (eg with LD_PRELOAD)
> 
> if you do control the env then just unset LD_LIBRARY_PATH

This is kind of what I thought of doing, in the loader.

By the way, when you say this - LD_PRELOAD should be actually usable
in a non-inheritable way too. It brings otherwise the same problems
as LD_LIBRARY_PATH. It could deserve its own loader argument I guess,
like --preload.

> (there ar no "different versions of the loader" in musl)

Yes this is why I thought that a LD_LIBRARY_PATH removal would
be enough. Of course it is much better to do this properly, by
extending the behaviour of the loader when it is being used standalone.

This would cost just a few bytes I guess. I will look into proposing a patch.

> in case you do a lot of lib path hacks note that the path lookup is
> different in glibc than in musl:

Thanks, good to keep in mind - otherwise not crucial given that I
do my best to avoid rpath and the fallbacks.

Regards,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 14:00   ` u-igbb
@ 2014-03-28 15:25     ` Szabolcs Nagy
  2014-03-28 15:34       ` Alexander Monakov
  2014-03-28 16:02     ` PATCH (Re: [musl] be able to break inheritance of LD_LIBRARY_PATH) u-igbb
  1 sibling, 1 reply; 18+ messages in thread
From: Szabolcs Nagy @ 2014-03-28 15:25 UTC (permalink / raw)
  To: musl

* u-igbb@aetey.se <u-igbb@aetey.se> [2014-03-28 14:00:36 +0000]:
> On Fri, Mar 28, 2014 at 02:17:19PM +0100, Szabolcs Nagy wrote:
> > why do you use LD_LIBRARY_PATH then?
> 
> I "do not". I am using the --library-path argument to the dynamic loader.
> (Unless LD_LIBRARY_PATH is forced upon myself by someone else;
> then I need protection from its potentially detrimental side effects)
[..]
> > if you mean you can run '/lib/ld-linux.so.2 binary' then musl can do the same
> 
> Thanks for pointing me in the right direction.
> 
> I was thinking of a "cheap and dirty workaround" while the most
> appropriate is of course to add the missing argument parsing.
> 

i still don't get what you are trying to achieve

what is the difference between

	/lib/ld-linux.so.2 --library-path libpath binary

and

	LD_LIBRARY_PATH=libpath /lib/ld-linux.so.2 binary

?


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 15:25     ` Szabolcs Nagy
@ 2014-03-28 15:34       ` Alexander Monakov
  0 siblings, 0 replies; 18+ messages in thread
From: Alexander Monakov @ 2014-03-28 15:34 UTC (permalink / raw)
  To: musl

On Fri, 28 Mar 2014, Szabolcs Nagy wrote:
> i still don't get what you are trying to achieve
> 
> what is the difference between
> 
> 	/lib/ld-linux.so.2 --library-path libpath binary
> 
> and
> 
> 	LD_LIBRARY_PATH=libpath /lib/ld-linux.so.2 binary

In the former case a specific library path is used only for "binary", but not
its children.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* PATCH (Re: [musl] be able to break inheritance of LD_LIBRARY_PATH)
  2014-03-28 14:00   ` u-igbb
  2014-03-28 15:25     ` Szabolcs Nagy
@ 2014-03-28 16:02     ` u-igbb
  1 sibling, 0 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 16:02 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 794 bytes --]

On Fri, Mar 28, 2014 at 02:00:36PM +0000, u-igbb@aetey.se wrote:
> By the way, when you say this - LD_PRELOAD should be actually usable
> in a non-inheritable way too. It brings otherwise the same problems
> as LD_LIBRARY_PATH. It could deserve its own loader argument I guess,
> like --preload.
> 
> > (there ar no "different versions of the loader" in musl)
> 
> Yes this is why I thought that a LD_LIBRARY_PATH removal would
> be enough. Of course it is much better to do this properly, by
> extending the behaviour of the loader when it is being used standalone.
> 
> This would cost just a few bytes I guess. I will look into proposing a patch.

Attaching the patch. It seems to work, under some primitive testing.
Could this or similar be considered for applying upstream?

Regards,
Rune

[-- Attachment #2: add--library-path.patch --]
[-- Type: text/plain, Size: 1350 bytes --]

--- src/ldso/dynlink.c.ori	2014-03-28 10:37:34.821317811 +0100
+++ src/ldso/dynlink.c	2014-03-28 16:45:26.435994022 +0100
@@ -1041,12 +1041,34 @@
 		size_t l = strlen(ldname);
 		if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
 		*argv++ = (void *)-1;
-		if (argv[0] && !strcmp(argv[0], "--")) *argv++ = (void *)-1;
+		while (argv[0] && argv[0][0] == '-') {
+			if (argv[0][1] == '-' && argv[0][2] == 0) { /* "--" */
+				*argv++ = (void *)-1;
+				break;
+			}
+			/* care about someone making the dynamic loader
+			 * itself (!) setuid? (s)he has possibly good
+			 * reasons, who am I to interfere -- thus
+			 * no setuid checking here -- rl */
+			if (!strcmp(argv[0], "--library-path")) {
+				*argv++ = (void *)-1;
+				env_path = argv[0]; /* even if NULL */
+			} else if (!strcmp(argv[0], "--preload")) {
+				*argv++ = (void *)-1;
+				env_preload = argv[0]; /* even if NULL */
+			} else
+				/* any -<something-else> stops parsing */
+				break;
+			if (!argv[0])
+				/* missing argument? */
+				break;
+			*argv++ = (void *)-1;
+		}
 		if (!argv[0]) {
 			dprintf(2, "musl libc\n"
 				"Version %s\n"
 				"Dynamic Program Loader\n"
-				"Usage: %s [--] pathname%s\n",
+				"Usage: %s [--library-path path] [--preload path] [--] pathname%s\n",
 				__libc_get_version(), ldname,
 				ldd_mode ? "" : " [args]");
 			_exit(1);

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
                   ` (2 preceding siblings ...)
  2014-03-28 13:17 ` Szabolcs Nagy
@ 2014-03-28 16:34 ` Daniel Cegiełka
  2014-03-28 17:50   ` u-igbb
  2014-03-28 19:46 ` Rich Felker
  4 siblings, 1 reply; 18+ messages in thread
From: Daniel Cegiełka @ 2014-03-28 16:34 UTC (permalink / raw)
  To: musl

2014-03-28 11:42 GMT+01:00 <u-igbb@aetey.se>:

>
> A naïve implementation might look as follows:
>
> --- src/ldso/dynlink.c.ori      2014-03-28 10:37:34.821317811 +0100
> +++ src/ldso/dynlink.c  2014-03-28 11:21:16.828047766 +0100
> @@ -962,6 +962,7 @@
>         size_t vdso_base;
>         size_t *auxv;
>         char **envp = argv+argc+1;
> +       int forget_ld_library_path = 0;
>
>         /* Find aux vector just past environ[] */
>         for (i=argc+1; argv[i]; i++)
> @@ -969,8 +970,19 @@
>                         env_path = argv[i]+16;
>                 else if (!memcmp(argv[i], "LD_PRELOAD=", 11))
>                         env_preload = argv[i]+11;
> +               else if (!memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
> +                       forget_ld_library_path = 1;
>         auxv = (void *)(argv+i+1);
>
> +       /* one _may_ wish to break the inheritance of LD_LIBRARY_PATH,
> +        * the hack below only works if the corresponding memory is writable
> +        * -- rl */
> +       if (forget_ld_library_path)
> +               for (i=argc+1; argv[i]; i++)
> +                       if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16) ||
> +                           !memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
> +                               argv[i][0] = 'X';
> +
>         decode_vec(auxv, aux, AUX_CNT);
>
>         /* Only trust user/env if kernel says we're not suid/sgid */
>
>
> What do you think about this? Can this or something better be done?
> I would love to be able to go with musl.

Hi Rune,
I don't understand why you expect that users wants this functionality.
Is this raises the risk for SUID/SGID?

/* Only trust user/env if kernel says we're not suid/sgid */
if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
 || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]) {
env_path = 0;
env_preload = 0;
libc.secure = 1;
}

but where is hardering for forget_ld_library_path?

Daniel

>
> Regards,
> Rune
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 16:34 ` be able to break inheritance of LD_LIBRARY_PATH Daniel Cegiełka
@ 2014-03-28 17:50   ` u-igbb
  2014-03-28 18:03     ` Daniel Cegiełka
  0 siblings, 1 reply; 18+ messages in thread
From: u-igbb @ 2014-03-28 17:50 UTC (permalink / raw)
  To: musl

Hello Daniel,

On Fri, Mar 28, 2014 at 05:34:29PM +0100, Daniel Cegiełka wrote:
> > +                           !memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))

> I don't understand why you expect that users wants this functionality.

In my job as a system administrator I routinely get reports of breakage
because of third party software packages which [have/choose to] use
LD_LIBRARY_PATH - it ends up being applied to the child processes which
happen to be incompatible with the given libraries. The effects may
be either spectacular or subtle, the latter being more dangerous.

Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 17:50   ` u-igbb
@ 2014-03-28 18:03     ` Daniel Cegiełka
  2014-03-28 18:21       ` u-igbb
  0 siblings, 1 reply; 18+ messages in thread
From: Daniel Cegiełka @ 2014-03-28 18:03 UTC (permalink / raw)
  To: musl

FORGET_LD_LIBRARY_PATH is not a standard. I'm guessing that Rich will
not be a fan of this :)

Daniel


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 18:03     ` Daniel Cegiełka
@ 2014-03-28 18:21       ` u-igbb
  0 siblings, 0 replies; 18+ messages in thread
From: u-igbb @ 2014-03-28 18:21 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 07:03:32PM +0100, Daniel Cegiełka wrote:
> FORGET_LD_LIBRARY_PATH is not a standard. I'm guessing that Rich will
> not be a fan of this :)

Hope he will read the whole thread before taking a stance :)

No I do not expect the mentioned dirty hack to be welcomed by anyone,
myself included.

Cheers,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
                   ` (3 preceding siblings ...)
  2014-03-28 16:34 ` be able to break inheritance of LD_LIBRARY_PATH Daniel Cegiełka
@ 2014-03-28 19:46 ` Rich Felker
  2014-03-28 21:07   ` u-igbb
  4 siblings, 1 reply; 18+ messages in thread
From: Rich Felker @ 2014-03-28 19:46 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 10:42:08AM +0000, u-igbb@aetey.se wrote:
> Hello,
> 
> I was aware of musl for some time and now consider deploying it as
> a default library for new software builds, due to its very appealing
> virtues.
> 
> Yet there is a small but important issue.
> 
> For our software setup it is crucial (quite useful otherwise in general)
> to be able to specify the location of the dynamic libraries per binary/run
> _without_ the unconditional inheritance imposed by LD_LIBRARY_PATH.

Why aren't you using RPATH, possibly with a $ORIGIN base? This is a
lot cleaner/saner than environment variables or invoking the dynamic
linker explicitly with arguments.

> A very nice solution would be the ability to explicitely run a standalone
> dynamic loader, as implemented in both glibc and uclibc. We are heavily
> relying on this functionality.

As others have said, this is already possible, and it's already setup
to be able to handle option arguments before the command (if you're
not sure the command name won't begin with a "-", you're supposed to
put "--" before the command). So it's just a matter of adding the
options. I haven't checked your patch yet, but the big things to
consider are:

- not breaking the current handling of "--"

- whether --library-path and --preload should override/replace the
  values obtained from the environment or supplement them, and if the
  latter, whether they should have higher or lower priority

> I do not know how hard it would be to teach the musl loader
> to be runnable standalone and which corner cases this might create.
> 
> As a simpler approach I might suggest simply being able to drop
> LD_LIBRARY_PATH as soon as it has been read. An extra environment
> variable as a flag would do.
> 
> Compared to a standalone loader this lacks the ability to run
> a binary with a different version of the loader/musl but at least
> makes it straightforward and safe to freely specify where to find other
> libraries.
> 
> A naïve implementation might look as follows:
> ...
> +               else if (!memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
> +                       forget_ld_library_path = 1;

Adding new environment variables that are processed by libc outside of
those specified by the standard and/or overwhelming real-world
practice is not acceptable. If nothing else, this would be a security
bug because there's no way applications can know they would need to
unset this variable to keep it from taking effect.

>         auxv = (void *)(argv+i+1);
>  
> +       /* one _may_ wish to break the inheritance of LD_LIBRARY_PATH,
> +        * the hack below only works if the corresponding memory is writable
> +        * -- rl */
> +       if (forget_ld_library_path)
> +               for (i=argc+1; argv[i]; i++)
> +                       if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16) ||
> +                           !memcmp(argv[i], "FORGET_LD_LIBRARY_PATH=", 23))
> +                               argv[i][0] = 'X';

As written this possibly corrupts the environment (e.g. leading to TWO
definitions of XD_LIBRARY_PATH in the environment). In any case this
is the wrong approach. If you _really_ want to remove these vars once
they're processed, you can use the LD_PRELOAD approach that calls
unsetenv on them, but I think that's one of the worst solutions to the
problem you're trying to solve (and RPATH/$ORIGIN is the best
solution).

Rich


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 19:46 ` Rich Felker
@ 2014-03-28 21:07   ` u-igbb
  2014-03-28 21:48     ` Rich Felker
  0 siblings, 1 reply; 18+ messages in thread
From: u-igbb @ 2014-03-28 21:07 UTC (permalink / raw)
  To: musl

Hello Rich,

Thanks for your answer.

On Fri, Mar 28, 2014 at 03:46:38PM -0400, Rich Felker wrote:
> Why aren't you using RPATH, possibly with a $ORIGIN base? This is a
> lot cleaner/saner than environment variables or invoking the dynamic
> linker explicitly with arguments.

Any hardcoded references make it impossible to update libraries in other
way than "substituting in place" which affects all binaries containing
the hardcoded reference. It is important to be able to run a certain
binary with a certain library without rewriting/replacing either the
former or the latter (both can be needed and used by other parties who
potentially do not expect/agree to any change!).

> > A very nice solution would be the ability to explicitely run a standalone
> > dynamic loader, as implemented in both glibc and uclibc. We are heavily
> > relying on this functionality.
> 
> As others have said, this is already possible, and it's already setup
> to be able to handle option arguments before the command (if you're
> not sure the command name won't begin with a "-", you're supposed to
> put "--" before the command). So it's just a matter of adding the
> options. I haven't checked your patch yet, but the big things to
> consider are:
> 
> - not breaking the current handling of "--"
> 
> - whether --library-path and --preload should override/replace the
>   values obtained from the environment or supplement them, and if the
>   latter, whether they should have higher or lower priority

Sure I am aware of these issues. As much as I can tell I followed
the behaviour of both glibc and uclibc (ignoring LD_LIBRARY_PATH
when --library-path is present).
(--preload is not present in those libraries but I feel it should
behave the same way as --library-path).

> Adding new environment variables that are processed by libc outside of
 ...
> As written this possibly corrupts the environment (e.g. leading to TWO

Sorry for presenting such an ugly example code. The purpose was merely
to explain what I had in mind (which also was wrong per se as I didn't
notice the possibility of adding the loader arguments).

I hope you are more positive to the latter patch (which I consider
being of acceptable quality).

> problem you're trying to solve (and RPATH/$ORIGIN is the best
> solution).

We are certainly thinking about different goals.

Hardcoded references (and even references read from files like
/etc/something if the path to the file is hardcoded into the binary
to be run) make it impossible to perform safe/limited (i.e. with a
constrained impact on the multiple resource consumers) changes in the
bindings between binaries and libraries. In this context RPATH
is hardly a suitable tool, even if combined with $ORIGIN.

Regards,
Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 21:07   ` u-igbb
@ 2014-03-28 21:48     ` Rich Felker
  2014-03-29  7:25       ` u-igbb
  0 siblings, 1 reply; 18+ messages in thread
From: Rich Felker @ 2014-03-28 21:48 UTC (permalink / raw)
  To: musl

On Fri, Mar 28, 2014 at 09:07:08PM +0000, u-igbb@aetey.se wrote:
> Hello Rich,
> 
> Thanks for your answer.
> 
> On Fri, Mar 28, 2014 at 03:46:38PM -0400, Rich Felker wrote:
> > Why aren't you using RPATH, possibly with a $ORIGIN base? This is a
> > lot cleaner/saner than environment variables or invoking the dynamic
> > linker explicitly with arguments.
> 
> Any hardcoded references make it impossible to update libraries in other
> way than "substituting in place" which affects all binaries containing
> the hardcoded reference.

This is exactly the problem $ORIGIN exists to solve. Used in RPATH,
'$ORIGIN' or '${ORIGIN}' expands to the directory component of the
pathname of the executable or library the RPATH tag resides in. So you
can use things like RPATH=$ORIGIN/../lib or RPATH=$ORIGIN or similar.

> > - whether --library-path and --preload should override/replace the
> >   values obtained from the environment or supplement them, and if the
> >   latter, whether they should have higher or lower priority
> 
> Sure I am aware of these issues. As much as I can tell I followed
> the behaviour of both glibc and uclibc (ignoring LD_LIBRARY_PATH
> when --library-path is present).
> (--preload is not present in those libraries but I feel it should
> behave the same way as --library-path).

I'm definitely fine with adding --library-path. The intent was always
to add options compatible with or at least similar to those used by
other dynamic loaders; that's why I added the "--" handling early on
so that adding options would not be a feature regression (breaking the
ability to run programs whose names start with "-".

As for --preload, I don't have any real objection but we should at
least stop a bit to consider adding nonstandard options that don't
have precedent in other implementations. Once we've added something
it's not really appropriate to remove it later. So I'd like to do just
--library-path for now if it will solve your problem and keep
--preload as a future idea.

> I hope you are more positive to the latter patch (which I consider
> being of acceptable quality).

Yes, at first glance it looked right but I want to review it a bit
more. The comment about suid isn't needed; making the dynamic loader
suid is about the only thing stupider than making a shell suid. :-)

Rich


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: be able to break inheritance of LD_LIBRARY_PATH
  2014-03-28 21:48     ` Rich Felker
@ 2014-03-29  7:25       ` u-igbb
  0 siblings, 0 replies; 18+ messages in thread
From: u-igbb @ 2014-03-29  7:25 UTC (permalink / raw)
  To: musl

Hello Rich,

On Fri, Mar 28, 2014 at 05:48:44PM -0400, Rich Felker wrote:
> > Any hardcoded references make it impossible to update libraries in other
> > way than "substituting in place" which affects all binaries containing
> > the hardcoded reference.
> 
> This is exactly the problem $ORIGIN exists to solve. Used in RPATH,
> '$ORIGIN' or '${ORIGIN}' expands to the directory component of the
> pathname of the executable or library the RPATH tag resides in. So you
> can use things like RPATH=$ORIGIN/../lib or RPATH=$ORIGIN or similar.

Unfortunately it does not help as everybody running the binary will
pick up the same library/ies. I am supporting large and multiple groups
of users running the same binary instances with potentially different
libraries and vice versa.

$ORIGIN helps if you are willing to copy the binary to somewhere
else (and make corresponding copies or symlinks of the necessary libraries).
This is possible but from my perspective quite impractical.

Generally speaking, the approach of looking for resources relative to the
binary's location is both insufficient and error-prone - it can (and does
in practice) accidentally hit resources not meant to. With other words,
you can not choose a place for a binary without "looking around" depending
on what is designated inside it as its "nearby area of interest".

Instead, I am using a straightforward framework where a tiny wrapper
makes a freely configurable point-of-run for a binary and a set
of library instances, wherever they happen to be located.
This way I do not have any artificial constraints on the relative or
absolute placement of the binaries and the libraries.

> > As much as I can tell I followed
> > the behaviour of both glibc and uclibc (ignoring LD_LIBRARY_PATH
> > when --library-path is present).
> > (--preload is not present in those libraries but I feel it should
> > behave the same way as --library-path).
> 
> I'm definitely fine with adding --library-path. The intent was always
> to add options compatible with or at least similar to those used by
> other dynamic loaders; that's why I added the "--" handling early on
> so that adding options would not be a feature regression (breaking the
> ability to run programs whose names start with "-".

Yes it looked like a preparation step. Appreciated.

> As for --preload, I don't have any real objection but we should at
> least stop a bit to consider adding nonstandard options that don't
> have precedent in other implementations. Once we've added something
> it's not really appropriate to remove it later. So I'd like to do just
> --library-path for now if it will solve your problem and keep
> --preload as a future idea.

I would like to be able to specify preload per binary, not per process tree
as LD_PRELOAD does.

In the same way as LD_LIBRARY_PATH,
LD_PRELOAD is dangerous on any "non-monolithic" system
(i.e. when different application use different libraries).
Even on a homogenous system a certain preload can be necessary for one
application and totally unacceptable for another one in a child process.

On certain hardware I used to use v4l1compat preload.
Then when an application starts a child process using different libraries
I remember occasions of getting error messages about preload failing. (I
am routinely using in production a mix of applications linked to several
different versions of glibc, uclibc and now musl). This was a mere
annoyance but potentially could lead to harm.

> > I hope you are more positive to the latter patch (which I consider
> > being of acceptable quality).
> 
> Yes, at first glance it looked right but I want to review it a bit
> more. The comment about suid isn't needed; making the dynamic loader
> suid is about the only thing stupider than making a shell suid. :-)

:) Sure.

Rune



^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-03-29  7:25 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-28 10:42 be able to break inheritance of LD_LIBRARY_PATH u-igbb
2014-03-28 12:18 ` orc
2014-03-28 12:52   ` u-igbb
2014-03-28 12:27 ` Alexander Monakov
2014-03-28 13:04   ` u-igbb
2014-03-28 13:17 ` Szabolcs Nagy
2014-03-28 14:00   ` u-igbb
2014-03-28 15:25     ` Szabolcs Nagy
2014-03-28 15:34       ` Alexander Monakov
2014-03-28 16:02     ` PATCH (Re: [musl] be able to break inheritance of LD_LIBRARY_PATH) u-igbb
2014-03-28 16:34 ` be able to break inheritance of LD_LIBRARY_PATH Daniel Cegiełka
2014-03-28 17:50   ` u-igbb
2014-03-28 18:03     ` Daniel Cegiełka
2014-03-28 18:21       ` u-igbb
2014-03-28 19:46 ` Rich Felker
2014-03-28 21:07   ` u-igbb
2014-03-28 21:48     ` Rich Felker
2014-03-29  7:25       ` u-igbb

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).