|
Message-ID: <20200715023432.GC14669@brightrain.aerifal.cx> Date: Tue, 14 Jul 2020 22:34:32 -0400 From: Rich Felker <dalias@...c.org> To: Simon <simonhf@...il.com> Cc: musl@...ts.openwall.com Subject: Re: musl attribute constructor does not pass argc and argv as expected? On Tue, Jul 14, 2020 at 05:32:42PM -0700, Simon wrote: > Hello! > > I tried compiling the test.c snippet here [1] with glibc and musl under > Alpine 3.12 and get the following results: > > $ gcc -std=c99 -o test test.c # glibc > $ ldd ./test > linux-vdso.so.1 (0x00007ffd0bfc9000) > libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd1e9363000) > /lib64/ld-linux-x86-64.so.2 (0x00007fd1e9572000) > $ ./test arg1 arg2 > stuff: argv[0] = './test' > stuff: argv[1] = 'arg1' > stuff: argv[2] = 'arg2' > main: argv[0] = './test' > main: argv[1] = 'arg1' > main: argv[2] = 'arg2' > > $ gcc -static -std=c99 -o test test.c # musl > $ ldd ./test > statically linked > $ ./test arg1 arg2 > Segmentation fault (core dumped) > $ ./test arg1 arg2 > main: argv[0] = './test' > main: argv[1] = 'arg1' > main: argv[2] = 'arg2' > > Very infrequently when I run the musl compiled code then I get the seg > fault. And the rest of the time only main() is run. > > If I compile without static then same thing: > > $ gcc -std=c99 -o test test.c # musl > $ ldd ./test > linux-vdso.so.1 (0x00007ffed4193000) > libc.musl-x86_64.so.1 => not found > $ ./test arg1 arg2 > main: argv[0] = './test' > main: argv[1] = 'arg1' > main: argv[2] = 'arg2' > $ ./test arg1 arg2 > Segmentation fault (core dumped) > > If I add the following line of code both functions and recompile with musl > under Alpine: > > printf("- argc=%d\n", argc); > > Then the it seems that argc is being passed but the wrong value: > > $ ./test arg1 arg2 > - argc=-1988853488 > - argc=3 > main: argv[0] = './test' > main: argv[1] = 'arg1' > main: argv[2] = 'arg2' > $ ./test arg1 arg2 > - argc=1409286416 > Segmentation fault (core dumped) > > Seems like a bug in musl, or what am I doing wrong? > > Thanks in advance! This is intentional. Relying on the glibc-specific behavior here is not portable. The ELF spec does not define arguments being passed to init_array functions, and other (non-glibc) implementations don't do it either. Aside from trying to discourage nonportable things (musl was pretty aggressive about this early on, a bit less so now), this particular behavior is one where failing hard seems to have been a better choice. The main case we found of software trying to use the ctor arguments was in an attempt to relocate argv/environ prior to program entry in order to make space to do a "setproctitle" operation. This is highly unsafe, as the dynamic linker and/or __libc_start_main entry-point code have already saved pointers to some things found there, and will break in subtle but potentially dangerous ways that might not be noticed until long after deployment. Crashing immediately in the ctor trying to poke at them, on the other hand, caused the bad code to be found and fixed. > [1] https://stackoverflow.com/a/37012337/1547069 BTW the comments on that answer noted this is not guaranteed at all and musl doesn't do it. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.