[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-hackers
Subject: Re: LD_PRELOADed code before or after exec - different behavior after 6.x
From: John Hein <jhein () symmetricom ! com>
Date: 2012-08-24 17:25:06
Message-ID: 20535.47346.913434.799005 () gromit ! timing ! com
[Download RAW message or body]
Answers inline...
Konstantin Belousov wrote at 19:23 +0300 on Aug 24, 2012:
> On Fri, Aug 24, 2012 at 09:17:22AM -0600, John Hein wrote:
> >
> > head sl.cc pe.c
> > ==> sl.cc <==
> > #include <cstdio>
> > #include <cstdlib>
> > class C
> > {
> > public:
> > C(){
> > printf("C\n");
> > unsetenv("XXX");
> > }
> > };
> > static C c;
> >
> > ==> pe.c <==
> > #include <stdio.h>
> > #include <stdlib.h>
> > int
> > main()
> > {
> > char *p=getenv("XXX");
> > if (p != NULL)
> > printf("XXX=%s\n",p);
> > return 0;
> > }
> >
> >
> > % g++ -fpic -shared sl.cc -o sl.so
> > % gcc pe.c -o pe
> >
> > 7.x & 8.x ...
> > % sh -c 'XXX=1 LD_PRELOAD=$(pwd)/sl.so pe'
> > C
> > XXX=1
> >
> > 6.x & 4.x ...
> > % sh -c 'XXX=1 LD_PRELOAD=$(pwd)/sl.so pe'
> > C
> >
> >
> > In 6.x and earlier (fedora 16, too), the unsetenv clears the XXX env
> > var apparently in time to affect the exec'd process. In 8.x & 9.x, it
> > seems the environment is set and passed to the exec'd process and the
> > LD_PRELOADed code does not affect that despite its best efforts.
> >
> > It seems to me that 6.x behavior is more correct, but I'm seeking
> > opinions before contemplating if / how to put together a fix.
> >
> I suppose that this is a fallback from the POSIXification of putenv().
> The libc image of the environment block is now referenced through
> the environ var. Since csu always reinitialize the environ, effect
> of the changes made by preloaded dso is cleared.
>
> At the end of the message is the patch for HEAD which seems to fix the
> issue. It is not applicable to stable/9 or 8. You could try to change
> lib/csu/<arch>/crt1.c to replace unconditional
> environ = env;
> assignment with
> if (environ == NULL)
> environ = env;
> .
Thanks. This fixes my reported problem - tested on 8.x.
> Unfortunately, because csu is linked to the binary, you have to relink
> the binary after applying the patch and rebuilding the world. In other
> words, old binaries cannot be fixed.
>
> Committing this requires secteam@ review, AFAIR.
Indeed this could be a sec issue if someone relies on preloaded
code clearing something in the environment. secteam CC'd
> diff --git a/lib/csu/amd64/crt1.c b/lib/csu/amd64/crt1.c
> index f33aad6..3740e73 100644
> --- a/lib/csu/amd64/crt1.c
> +++ b/lib/csu/amd64/crt1.c
> @@ -61,9 +61,7 @@ _start(char **ap, void (*cleanup)(void))
> argc = *(long *)(void *)ap;
> argv = ap + 1;
> env = ap + 2 + argc;
> - environ = env;
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (&_DYNAMIC != NULL)
> atexit(cleanup);
> diff --git a/lib/csu/arm/crt1.c b/lib/csu/arm/crt1.c
> index 127c28d..e3529b8 100644
> --- a/lib/csu/arm/crt1.c
> +++ b/lib/csu/arm/crt1.c
> @@ -98,10 +98,7 @@ __start(int argc, char **argv, char **env, struct ps_strings *ps_strings,
> const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void))
> {
>
> - environ = env;
> -
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (ps_strings != (struct ps_strings *)0)
> __ps_strings = ps_strings;
> diff --git a/lib/csu/common/ignore_init.c b/lib/csu/common/ignore_init.c
> index e3d2441..89b3734 100644
> --- a/lib/csu/common/ignore_init.c
> +++ b/lib/csu/common/ignore_init.c
> @@ -87,14 +87,18 @@ handle_static_init(int argc, char **argv, char **env)
> }
>
> static inline void
> -handle_progname(const char *v)
> +handle_argv(int argc, char *argv[], char **env)
> {
> const char *s;
>
> - __progname = v;
> - for (s = __progname; *s != '\0'; s++) {
> - if (*s == '/')
> - __progname = s + 1;
> + if (environ == NULL)
> + environ = env;
> + if (argc > 0 && argv[0] != NULL) {
> + __progname = argv[0];
> + for (s = __progname; *s != '\0'; s++) {
> + if (*s == '/')
> + __progname = s + 1;
> + }
> }
> }
>
> diff --git a/lib/csu/i386-elf/crt1_c.c b/lib/csu/i386-elf/crt1_c.c
> index 3249069..65de04c 100644
> --- a/lib/csu/i386-elf/crt1_c.c
> +++ b/lib/csu/i386-elf/crt1_c.c
> @@ -61,10 +61,7 @@ _start1(fptr cleanup, int argc, char *argv[])
> char **env;
>
> env = argv + argc + 1;
> - environ = env;
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> -
> + handle_argv(argc, argv, env);
> if (&_DYNAMIC != NULL)
> atexit(cleanup);
> else
> diff --git a/lib/csu/mips/crt1.c b/lib/csu/mips/crt1.c
> index 1968f06..95348b7 100644
> --- a/lib/csu/mips/crt1.c
> +++ b/lib/csu/mips/crt1.c
> @@ -71,9 +71,7 @@ __start(char **ap,
> argc = * (long *) ap;
> argv = ap + 1;
> env = ap + 2 + argc;
> - environ = env;
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (&_DYNAMIC != NULL)
> atexit(cleanup);
> diff --git a/lib/csu/powerpc/crt1.c b/lib/csu/powerpc/crt1.c
> index c3be90d..d1a3ea0 100644
> --- a/lib/csu/powerpc/crt1.c
> +++ b/lib/csu/powerpc/crt1.c
> @@ -81,10 +81,8 @@ _start(int argc, char **argv, char **env,
> struct ps_strings *ps_strings)
> {
>
> - environ = env;
>
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (ps_strings != (struct ps_strings *)0)
> __ps_strings = ps_strings;
> diff --git a/lib/csu/powerpc64/crt1.c b/lib/csu/powerpc64/crt1.c
> index a7c3581..35c5a6e 100644
> --- a/lib/csu/powerpc64/crt1.c
> +++ b/lib/csu/powerpc64/crt1.c
> @@ -81,10 +81,7 @@ _start(int argc, char **argv, char **env,
> struct ps_strings *ps_strings)
> {
>
> - environ = env;
> -
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (ps_strings != (struct ps_strings *)0)
> __ps_strings = ps_strings;
> diff --git a/lib/csu/sparc64/crt1.c b/lib/csu/sparc64/crt1.c
> index 3b3ecc2..e11ae39 100644
> --- a/lib/csu/sparc64/crt1.c
> +++ b/lib/csu/sparc64/crt1.c
> @@ -85,9 +85,7 @@ _start(char **ap, void (*cleanup)(void), struct Struct_Obj_Entry *obj __unused,
> argc = *(long *)(void *)ap;
> argv = ap + 1;
> env = ap + 2 + argc;
> - environ = env;
> - if (argc > 0 && argv[0] != NULL)
> - handle_progname(argv[0]);
> + handle_argv(argc, argv, env);
>
> if (&_DYNAMIC != NULL)
> atexit(cleanup);
> [DELETED ATTACHMENT <no suggested filename>, application/pgp-signature]
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic