Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
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.