elf: Properly align all PT_LOAD segments [BZ #28676]
Checks
Context |
Check |
Description |
dj/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
dj/TryBot-32bit |
success
|
Build for i686
|
Commit Message
Linker may set p_align of a PT_LOAD segment larger than p_align of the
first PT_LOAD segment to satisfy a section alignment:
Elf file type is DYN (Shared object file)
Entry point 0x0
There are 10 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000834 0x0000000000000834 R E 0x1000
LOAD 0x0000000000000e00 0x0000000000001e00 0x0000000000001e00
0x0000000000000230 0x0000000000000230 RW 0x1000
LOAD 0x0000000000400000 0x0000000000400000 0x0000000000400000
0x0000000000000004 0x0000000000000008 RW 0x400000
...
Section to Segment mapping:
Segment Sections...
00 .note.gnu.property .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
01 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt
02 .data .bss
We should align the first PT_LOAD segment to the maximum p_align of all
PT_LOAD segments, similar to the kernel commit:
commit ce81bb256a224259ab686742a6284930cbe4f1fa
Author: Chris Kennelly <ckennelly@google.com>
Date: Thu Oct 15 20:12:32 2020 -0700
fs/binfmt_elf: use PT_LOAD p_align values for suitable start addres
This patch includes a test with an x86-64 shared library binary created
by the linker patch:
https://sourceware.org/pipermail/binutils/2021-December/118893.html
to verify that shared libraries with such PT_LOAD segments are mapped
properly.
---
elf/dl-load.c | 9 +++++++-
sysdeps/x86_64/64/Makefile | 9 ++++++++
sysdeps/x86_64/64/tst-p_align1.c | 27 ++++++++++++++++++++++++
sysdeps/x86_64/64/tst-p_alignmod1.so.xz | Bin 0 -> 2212 bytes
4 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 sysdeps/x86_64/64/Makefile
create mode 100644 sysdeps/x86_64/64/tst-p_align1.c
create mode 100755 sysdeps/x86_64/64/tst-p_alignmod1.so.xz
GIT binary patch
literal 2212
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
literal 0
HcmV?d00001
@@ -1101,6 +1101,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
size_t nloadcmds = 0;
bool has_holes = false;
bool empty_dynamic = false;
+ ElfW(Addr) p_align_max = 0;
/* The struct is initialized to zero so this is not necessary:
l->l_ld = 0;
@@ -1151,7 +1152,9 @@ _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;
+ /* Remember the maximum p_align. */
+ if (ph->p_align > p_align_max)
+ p_align_max = ph->p_align;
c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
/* Determine whether there is a gap between the last segment
@@ -1226,6 +1229,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
goto lose;
}
+ /* Align all PT_LOAD segments to the maximum p_align. */
+ for (size_t i = 0; i < nloadcmds; i++)
+ loadcmds[i].mapalign = p_align_max;
+
/* 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
new file mode 100644
@@ -0,0 +1,9 @@
+ifeq ($(subdir),elf)
+tests += tst-p_align1
+
+$(objpfx)tst-p_align1: $(objpfx)tst-p_alignmod1.so
+
+$(objpfx)tst-p_alignmod1.so: $(..)sysdeps/x86_64/64/tst-p_alignmod1.so.xz
+ cp -f $< $(objpfx)
+ unxz -f $(objpfx)tst-p_alignmod1.so.xz
+endif
new file mode 100644
@@ -0,0 +1,27 @@
+/* Check different alignments of PT_LOAD segments 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
+ <https://www.gnu.org/licenses/>. */
+
+extern int do_load_test (void);
+
+static int
+do_test (void)
+{
+ return do_load_test ();
+}
+
+#include <support/test-driver.c>
new file mode 100755