[PATCH v5 4/4] elf: Add glibc.rtld.execstack
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Dec 3 17:25:40 GMT 2024
On 29/11/24 17:01, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/Makefile b/elf/Makefile
>> index bdd169f4e8..6dd15c63d9 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -556,6 +556,13 @@ tests-execstack-yes = \
>> tests-execstack-static-yes = \
>> tst-execstack-prog-static
>> # tests-execstack-static-yes
>> +ifeq (yes,$(run-built-tests))
>> +tests-execstack-special-yes = \
>> + $(objpfx)tst-execstack-needed-noexecstack.out \
>> + $(objpfx)tst-execstack-prog-noexecstack.out \
>> + $(objpfx)tst-execstack-prog-static-noexecstack.out \
>> + # tests-execstack-special-yes
>> +endif # $(run-built-tests)
>> endif
>> ifeq ($(have-depaudit),yes)
>> tests += \
>> @@ -651,6 +658,7 @@ $(objpfx)tst-rtld-dash-dash.out: tst-rtld-dash-dash.sh $(objpfx)ld.so
>>
>> tests += $(tests-execstack-$(have-z-execstack))
>> tests-static+= $(tests-execstack-static-$(have-z-execstack))
>> +tests-special += $(tests-execstack-special-$(have-z-execstack))
>
> Should this be guarded by $(run-built-tests)?
I don't think it is necessary, since tests-execstack-special-yes will only be non-empty
if $(run-built-tests) is 'yes' (in fact I fixed it from v4, where I saw the tests were
failing on Hurd due the missing $(run-built-tests) check).
>
>> diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
>> index db0e1c86e9..9f5990f340 100644
>> --- a/elf/tst-rtld-list-tunables.exp
>> +++ b/elf/tst-rtld-list-tunables.exp
>> @@ -13,5 +13,6 @@ glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0x[f]+)
>> glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
>> glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
>> glibc.rtld.enable_secure: 0 (min: 0, max: 1)
>> +glibc.rtld.execstack: 1 (min: 0, max: 1)
>> glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
>> glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
>> diff --git a/manual/tunables.texi b/manual/tunables.texi
>> index 0b1b2898c0..c3e894f4fe 100644
>> --- a/manual/tunables.texi
>> +++ b/manual/tunables.texi
>> @@ -355,6 +355,25 @@ tests for @code{AT_SECURE} programs and not meant to be a security feature.
>> The default value of this tunable is @samp{0}.
>> @end deftp
>>
>> +@deftp Tunable glibc.rtld.execstack
>> +@theglibc{} will use either the default architecture ABI flags (that might
>> +contain the executable bit) or the value of @code{PT_GNU_STACK} (if present)
>> +to define whether to mark the stack non-executable, and if the program or
>> +any shared library dependency require an executable stack the loader will
>> +change the main stack permission if kernel starts with a non executable stack.
>> +
>> +The @code{glibc.rtld.execstack} tunable allows the user to control how
>> +to proceed regarding the stack execution bit. Setting its value to @code{0}
>> +disables executable stacks, where @code{1} enables it. The default value
>> +is @code{1}.
>
> This is ambiguous because 1 enables automatic handling. Executable
> stacks will still be disabled in most cases.
I think we can phrase this better:
The @code{glibc.rtld.execstack} tunable allows the user to control how
to proceed regarding the stack execution support. Setting its value to @code{0}
disables executable stacks, even if the program or direct dependencies require
it. The value @code{1} will follow the program and dependencies requirement,
where glibc might turn the initial and subsequent thread stack executable,
if required. The default value is @code{1}.
>
>> +When executable stacks are not allowed, and if the main program requires an
>> +executable stack, the loader will fail with an error message.
>> +@strong{NB:} Trying to load a dynamic shared library with @code{dlopen} or
>> +@code{dlmopen} that requires an executable stack will always fail if the
>> +default flags does not contain the executable bit.
>> +@end deftp
>
> This paragraph seems to have some sort of formatting glitch.
Hum, which kind of glitch? On libc.pdf I see that 'NB:' is correctly rendered
on same line of the 'When executable stack...'.
>
> Could we get a couple more modes?
>
> fully disabled, load/dlopen will fail
> fully disabled, but load/dlopen will proceed (useful with setarch -X)
> auto-enable, dlopen might fail (the default)
> auto-enable, dlopen will silently proceed instead of failing
> always enabled (useful for legacy applications that need dlopen)
I am not sure if all these modes do make sense:
1. 'fully disabled, but load/dlopen will proceed (useful with setarch -X)' -
means that either we will need to reinstate the code to make the thread
executable again, or loading a module that requires executable stack
without actually making all the thread stack executable.
2. 'auto-enable, dlopen will silently proceed instead of failing' -
same for 1, it will put the program in an inconsistent wrt stack
execution requirements.
3. 'always enabled (useful for legacy applications that need dlopen)' -
same for 1 wrt reinstate code.
I really don't think it would be good to way to just override the security
hardening this patchset it aiming to fix with a tunable. I think
if a program or any of its dependencies do require executable stack,
it should be well defined during *program loading*, which can be easily
verifiable without the need to run the program.
More information about the Libc-alpha
mailing list