This patch reverts the following commits: commit fc2334ab32e04916832955301225a9785c36dac1 Author: H.J. Lu Date: Thu Dec 9 07:01:33 2021 -0800 Add a testcase to check alignment of PT_LOAD segment [BZ #28676] commit 718fdd87b1b98ef88e883a37d9c18867256fa5a4 Author: Rongwei Wang Date: Fri Dec 10 20:39:10 2021 +0800 elf: Properly align PT_LOAD segments [BZ #28676] When PT_LOAD segment alignment > the page size, allocate enough space to ensure that the segment can be properly aligned. This change helps code segments use huge pages become simple and available. This fixes [BZ #28676]. Signed-off-by: Xu Yu Signed-off-by: Rongwei Wang diff --git a/elf/Makefile b/elf/Makefile index fe42caeb0eec9a1b..d0bb0daa7e309157 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -207,7 +207,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-tls4 tst-tls5 \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ - tst-align tst-align2 tst-align3 \ + tst-align tst-align2 \ tst-dlmodcount tst-dlopenrpath tst-deep1 \ tst-dlmopen1 tst-dlmopen3 tst-dlmopen4 \ unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ @@ -241,9 +241,6 @@ tests-internal += loadtest unload unload2 circleload1 \ tests-container += tst-pldd tst-dlopen-tlsmodid-container \ tst-dlopen-self-container tst-preload-pthread-libc test-srcs = tst-pathopt -ifeq (yes,$(have-fpie)) -tests-pie += tst-align3 -endif selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) ifneq ($(selinux-enabled),1) tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog @@ -305,7 +302,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ circlemod3 circlemod3a \ reldep8mod1 reldep8mod2 reldep8mod3 \ reldep9mod1 reldep9mod2 reldep9mod3 \ - tst-alignmod tst-alignmod2 tst-alignmod3 \ + tst-alignmod tst-alignmod2 \ $(modules-execstack-$(have-z-execstack)) \ tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ tst-dlmopen1mod tst-auditmod1 \ @@ -1096,13 +1093,6 @@ CFLAGS-tst-alignmod.c += $(stack-align-test-flags) CFLAGS-tst-alignmod2.c += $(stack-align-test-flags) $(objpfx)tst-align.out: $(objpfx)tst-alignmod.so $(objpfx)tst-align2: $(objpfx)tst-alignmod2.so -$(objpfx)tst-align3: $(objpfx)tst-alignmod3.so -ifeq (yes,$(have-fpie)) -CFLAGS-tst-align3.c += $(PIE-ccflag) -endif -LDFLAGS-tst-align3 += -Wl,-z,max-page-size=0x200000 -LDFLAGS-tst-alignmod3.so += -Wl,-z,max-page-size=0x200000 -$(objpfx)tst-alignmod3.so: $(libsupport) $(objpfx)unload3.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \ $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so diff --git a/elf/dl-load.c b/elf/dl-load.c index 721593135e307f88..bf8957e73c32021a 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1,6 +1,5 @@ /* Map in a shared object's segments from the file. Copyright (C) 1995-2021 Free Software Foundation, Inc. - Copyright The GNU Toolchain Authors. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -1151,7 +1150,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize)); c->dataend = ph->p_vaddr + ph->p_filesz; c->allocend = ph->p_vaddr + ph->p_memsz; - c->mapalign = ph->p_align; c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize)); /* Determine whether there is a gap between the last segment diff --git a/elf/dl-load.h b/elf/dl-load.h index e6dabcb3368fd240..e329d49a813f2376 100644 --- a/elf/dl-load.h +++ b/elf/dl-load.h @@ -1,6 +1,5 @@ /* Map in a shared object's segments from the file. Copyright (C) 1995-2021 Free Software Foundation, Inc. - Copyright The GNU Toolchain Authors. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -75,7 +74,7 @@ ELF_PREFERRED_ADDRESS_DATA; Its details have been expanded out and converted. */ struct loadcmd { - ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign; + ElfW(Addr) mapstart, mapend, dataend, allocend; ElfW(Off) mapoff; int prot; /* PROT_* bits. */ }; diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h index 70a4c40695024028..f9fb110ee32ba8fd 100644 --- a/elf/dl-map-segments.h +++ b/elf/dl-map-segments.h @@ -1,6 +1,5 @@ /* Map in a shared object's segments. Generic version. Copyright (C) 1995-2021 Free Software Foundation, Inc. - Copyright The GNU Toolchain Authors. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,50 +18,6 @@ #include -/* Map a segment and align it properly. */ - -static __always_inline ElfW(Addr) -_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref, - const size_t maplength, int fd) -{ - if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize))) - return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot, - MAP_COPY|MAP_FILE, fd, c->mapoff); - - /* If the segment alignment > the page size, allocate enough space to - ensure that the segment can be properly aligned. */ - ElfW(Addr) maplen = (maplength >= c->mapalign - ? (maplength + c->mapalign) - : (2 * c->mapalign)); - ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen, - PROT_NONE, - MAP_ANONYMOUS|MAP_PRIVATE, - -1, 0); - if (__glibc_unlikely ((void *) map_start == MAP_FAILED)) - return map_start; - - ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign); - map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned, - maplength, c->prot, - MAP_COPY|MAP_FILE|MAP_FIXED, - fd, c->mapoff); - if (__glibc_unlikely ((void *) map_start_aligned == MAP_FAILED)) - __munmap ((void *) map_start, maplen); - else - { - /* Unmap the unused regions. */ - ElfW(Addr) delta = map_start_aligned - map_start; - if (delta) - __munmap ((void *) map_start, delta); - ElfW(Addr) map_end = map_start_aligned + maplength; - delta = map_start + maplen - map_end; - if (delta) - __munmap ((void *) map_end, delta); - } - - return map_start_aligned; -} - /* This implementation assumes (as does the corresponding implementation of _dl_unmap_segments, in dl-unmap-segments.h) that shared objects are always laid out with all segments contiguous (or with gaps @@ -98,7 +53,10 @@ _dl_map_segments (struct link_map *l, int fd, - MAP_BASE_ADDR (l)); /* Remember which part of the address space this object uses. */ - l->l_map_start = _dl_map_segment (c, mappref, maplength, fd); + l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength, + c->prot, + MAP_COPY|MAP_FILE, + fd, c->mapoff); if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED)) return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; diff --git a/elf/tst-align3.c b/elf/tst-align3.c deleted file mode 100644 index ac86d623a62f9e0f..0000000000000000 --- a/elf/tst-align3.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Check alignment of PT_LOAD segment in a shared library. - Copyright (C) 2021 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 - . */ - -#include -#include - -/* This should cover all possible page sizes we currently support. */ -#define ALIGN 0x200000 - -int bar __attribute__ ((aligned (ALIGN))) = 1; - -extern int do_load_test (void); - -static int -do_test (void) -{ - printf ("bar: %p\n", &bar); - TEST_VERIFY (is_aligned (&bar, ALIGN) == 0); - - return do_load_test (); -} - -#include diff --git a/elf/tst-alignmod3.c b/elf/tst-alignmod3.c deleted file mode 100644 index 0d33f2379d1c04aa..0000000000000000 --- a/elf/tst-alignmod3.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Check alignment of PT_LOAD segment in a shared library. - Copyright (C) 2021 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 - . */ - -#include -#include - -/* This should cover all possible page sizes we currently support. */ -#define ALIGN 0x200000 - -int foo __attribute__ ((aligned (ALIGN))) = 1; - -void -do_load_test (void) -{ - printf ("foo: %p\n", &foo); - TEST_VERIFY (is_aligned (&foo, ALIGN) == 0); -}