+2019-06-18 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24323]
+ * include/elf.h (DT_1_SUPPORTED_MASK): Include DF_1_PIE.
+ * elf/dl-load.c (_dl_map_object_from_fd): Check for DF_1_PIE and
+ fail when called from dlopen.
+ * elf/Makefile [have-fpie && build-shared] (tests): Add
+ tst-dlopen-pie.
+ (tst-dlopen-pie): Link with -ldl.
+ (tst-dlopen-pie.out): Add run-time dependency on tst-pie1.
+ * elf/tst-dlopen-pie.c (do_test): New file.
+
2019-06-17 Rafal Luzynski <digitalfreak@lingonborough.com>
[BZ #24614]
endif
ifeq (yesyes,$(have-fpie)$(build-shared))
modules-names += tst-piemod1
-tests += tst-pie1 tst-pie2
+tests += tst-pie1 tst-pie2 tst-dlopen-pie
tests-pie += tst-pie1 tst-pie2
ifeq (yes,$(have-protected-data))
tests += vismain
$(objpfx)tst-piemod1.so: $(libsupport)
$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
+$(objpfx)tst-dlopen-pie: $(libdl)
+$(objpfx)tst-dlopen-pie.out: $(objpfx)tst-pie1
ifeq (yes,$(build-shared))
# NB: Please keep cet-built-dso in sysdeps/x86/Makefile in sync with
goto call_lose;
}
+ /* dlopen of an executable is not valid because it is not possible
+ to perform proper relocations, handle static TLS, or run the
+ ELF constructors. For PIE, the check needs the dynamic
+ section, so there is another check below. */
if (__glibc_unlikely (type != ET_DYN)
&& __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))
{
elf_get_dynamic_info (l, NULL);
/* Make sure we are not dlopen'ing an object that has the
- DF_1_NOOPEN flag set. */
- if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
- && (mode & __RTLD_DLOPEN))
+ DF_1_NOOPEN flag set, or a PIE object. */
+ if ((__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
+ && (mode & __RTLD_DLOPEN))
+ || (__glibc_unlikely (l->l_flags_1 & DF_1_PIE)
+ && __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0)))
{
/* We are not supposed to load this object. Free all resources. */
_dl_unmap_segments (l);
if (l->l_phdr_allocated)
free ((void *) l->l_phdr);
- errstring = N_("shared object cannot be dlopen()ed");
+ if (l->l_flags_1 & DF_1_PIE)
+ errstring
+ = N_("cannot dynamically load position-independent executable");
+ else
+ errstring = N_("shared object cannot be dlopen()ed");
goto call_lose;
}
--- /dev/null
+/* dlopen test for PIE objects.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test attempts to open the (otherwise unrelated) PIE test
+ program elf/tst-pie1 and expects the attempt to fail. */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static void
+test_mode (int mode)
+{
+ char *pie_path = xasprintf ("%s/elf/tst-pie1", support_objdir_root);
+ if (dlopen (pie_path, mode) != NULL)
+ FAIL_EXIT1 ("dlopen succeeded unexpectedly (%d)", mode);
+ const char *message = dlerror ();
+ const char *expected
+ = "cannot dynamically load position-independent executable";
+ if (strstr (message, expected) == NULL)
+ FAIL_EXIT1 ("unexpected error message (mode %d): %s", mode, message);
+}
+
+static int
+do_test (void)
+{
+ test_mode (RTLD_LAZY);
+ test_mode (RTLD_NOW);
+ return 0;
+}
+
+#include <support/test-driver.c>
# endif
# define DT_1_SUPPORTED_MASK \
(DF_1_NOW | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \
- | DF_1_ORIGIN | DF_1_NODEFLIB)
+ | DF_1_ORIGIN | DF_1_NODEFLIB | DF_1_PIE)
#endif /* !_ISOMAC */
#endif /* elf.h */