mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-07 13:28:05 +08:00
elf: Add glibc.rtld.execstack
The new tunable can be used to control whether executable stacks are allowed from either the main program or dependencies. The default is to allow executable stacks. The executable stacks default permission is checked agains the one provided by the PT_GNU_STACK from program headers (if present). The tunable also disables the stack permission change if any dependency requires an executable stack at loading time. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. Reviewed-by: Florian Weimer <fweimer@redhat.com>
This commit is contained in:
parent
c9540704ac
commit
58272284b6
5
NEWS
5
NEWS
@ -62,6 +62,11 @@ Major new features:
|
||||
asinf, asinhf, atanf, atan2f, atanhf, coshf, sinhf, and tanhf from CORE-MATH
|
||||
project <https://core-math.gitlabpages.inria.fr/>.
|
||||
|
||||
* A new tunable, glibc.rtld.execstack, can be used to control whether a
|
||||
executable stacks is allowed from the main program, either implicitly due
|
||||
to a mising GNU_STACK ELF header or explicit explicitly because of the
|
||||
executable bit in GNU_STACK. The default is to allow executable stacks.
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
* The big-endian ARC port (arceb-linux-gnu) has been removed.
|
||||
|
44
elf/Makefile
44
elf/Makefile
@ -570,6 +570,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
|
||||
endif
|
||||
ifeq ($(have-depaudit),yes)
|
||||
@ -666,6 +673,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))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += \
|
||||
$(objpfx)tst-ldconfig-X.out \
|
||||
@ -1989,6 +1997,42 @@ CFLAGS-tst-execstack-mod.c += -Wno-trampolines
|
||||
|
||||
LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack
|
||||
CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines
|
||||
|
||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
||||
tst-execstack-prog-noexecstack-msg = "Fatal glibc error: executable stack is not allowed$$"
|
||||
else
|
||||
tst-execstack-prog-noexecstack-msg = "error while loading shared libraries:.*cannot enable executable stack as shared object requires:"
|
||||
endif
|
||||
|
||||
$(objpfx)tst-execstack-prog-noexecstack.out: $(objpfx)tst-execstack-prog
|
||||
$(test-program-cmd-before-env) \
|
||||
$(run-program-env) \
|
||||
GLIBC_TUNABLES=glibc.rtld.execstack=0 \
|
||||
$(test-program-cmd-after-env) $< \
|
||||
> $@ 2>&1; echo "status: $$?" >> $@; \
|
||||
grep -q $(tst-execstack-prog-noexecstack-msg) $@ \
|
||||
&& grep -q '^status: 127$$' $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-execstack-needed-noexecstack.out: $(objpfx)tst-execstack-needed
|
||||
$(test-program-cmd-before-env) \
|
||||
$(run-program-env) \
|
||||
GLIBC_TUNABLES=glibc.rtld.execstack=0 \
|
||||
$(test-program-cmd-after-env) $< \
|
||||
> $@ 2>&1; echo "status: $$?" >> $@; \
|
||||
grep -q 'error while loading shared libraries:.*cannot enable executable stack as shared object requires:' $@ \
|
||||
&& grep -q '^status: 127$$' $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-execstack-prog-static-noexecstack.out: $(objpfx)tst-execstack-prog-static
|
||||
$(test-program-cmd-before-env) \
|
||||
$(run-program-env) \
|
||||
GLIBC_TUNABLES=glibc.rtld.execstack=0 \
|
||||
$< \
|
||||
> $@ 2>&1; echo "status: $$?" >> $@; \
|
||||
grep -q 'Fatal glibc error: executable stack is not allowed$$' $@ \
|
||||
&& grep -q '^status: 127$$' $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
LDFLAGS-tst-array2 = -Wl,--no-as-needed
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <dl-tunables.h>
|
||||
|
||||
/* Type for the buffer we put the ELF header and hopefully the program
|
||||
header. This buffer does not really have to be too large. In most
|
||||
@ -1317,7 +1318,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
/* The stack is presently not executable, but this module
|
||||
requires that it be executable. Only tries to change the
|
||||
stack protection during process startup. */
|
||||
if ((mode & __RTLD_DLOPEN) == 0)
|
||||
if ((mode & __RTLD_DLOPEN) == 0
|
||||
&& TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 1)
|
||||
errval = _dl_make_stack_executable (stack_endp);
|
||||
else
|
||||
errval = EINVAL;
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <dl-find_object.h>
|
||||
#include <array_length.h>
|
||||
#include <dl-symbol-redir-ifunc.h>
|
||||
#include <dl-tunables.h>
|
||||
|
||||
extern char *__progname;
|
||||
char **_dl_argv = &__progname; /* This is checked for some error messages. */
|
||||
@ -331,6 +332,10 @@ _dl_non_dynamic_init (void)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
|
||||
&& TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
|
||||
_dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n");
|
||||
|
||||
call_function_static_weak (_dl_find_object_init);
|
||||
|
||||
/* Setup relro on the binary itself. */
|
||||
|
@ -135,6 +135,12 @@ glibc {
|
||||
maxval: 1
|
||||
default: 0
|
||||
}
|
||||
execstack {
|
||||
type: INT_32
|
||||
minval: 0
|
||||
maxval: 1
|
||||
default: 1
|
||||
}
|
||||
}
|
||||
|
||||
mem {
|
||||
|
@ -1645,6 +1645,10 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
bool has_interp = rtld_setup_main_map (main_map);
|
||||
|
||||
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
|
||||
&& TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
|
||||
_dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n");
|
||||
|
||||
/* If the current libname is different from the SONAME, add the
|
||||
latter as well. */
|
||||
if (_dl_rtld_map.l_info[DT_SONAME] != NULL
|
||||
|
@ -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]+)
|
||||
|
@ -355,6 +355,34 @@ 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 requires an executable stack the loader will
|
||||
change the main stack permission if kernel starts with a non-executable stack.
|
||||
|
||||
The @code{glibc.rtld.execstack} can be used to control whether an executable
|
||||
stack is allowed from the main program. Setting the value to @code{0} disables
|
||||
the ABI auto-negotiation (meaning no executable stacks even if the ABI or ELF
|
||||
header requires it), while @code{1} enables auto-negotiation (although the
|
||||
program might not need an executable stack).
|
||||
|
||||
When executable stacks are not allowed, and if the main program requires it,
|
||||
the loader will fail with an error message.
|
||||
|
||||
Some systems do not have separate page protection flags at the hardware
|
||||
level for read access and execute access (sometimes called read-implies-exec).
|
||||
This mode can also be enabled on certain systems where the hardware supports
|
||||
separate protection flags. The @theglibc{} tunable configuration is independent
|
||||
of hardware capabilities and kernel configuration.
|
||||
|
||||
@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
|
||||
main program does not require an executable stack at loading time. This
|
||||
is enforced regardless of the tunable value.
|
||||
@end deftp
|
||||
|
||||
@node Elision Tunables
|
||||
@section Elision Tunables
|
||||
@cindex elision tunables
|
||||
|
Loading…
Reference in New Issue
Block a user