From patchwork Tue Dec 21 21:49:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 49160 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 65A683858427 for ; Tue, 21 Dec 2021 21:50:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 65A683858427 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1640123414; bh=vzudlVICs35gnMSFQrpfR81AVXPAPeU/mcMd6Q1yirc=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=IkCa6SQqOpowpCTjXAh2yiYrmvoY2zCiI0DhknROutHPwxG9iHi3sw8vr2Pi0mOj2 BYJpCOQm6kn9SUogJ1IFOrQSARyz1JjDh5sO/yMhMjRQjI8mdtykZ68LEfn9rWso19 YzfzWj8PyY3PyMBlYcis1oyGbLcIJx3tzldsy6M8= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 455213858C2C for ; Tue, 21 Dec 2021 21:49:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 455213858C2C Received: by mail-pf1-x42b.google.com with SMTP id t123so428796pfc.13 for ; Tue, 21 Dec 2021 13:49:11 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=vzudlVICs35gnMSFQrpfR81AVXPAPeU/mcMd6Q1yirc=; b=B0ngCWA4qCTaR8oznsJ3hDWDGxVzKWw2WFsyYEzx0dezKCvc8g+YND20x7sEUPgkHz 5/heoHi4qPztC8bVp12NsGGXe4a2i02DvsPLlSzwofOIdXsGmuVWDtjgq7P1ApRBhO2y DQm7qUeIlXhdXhiXXasfQeV0AbDF3oZFM3iWWl0Bq0z2sx8KMMVad/OzTG0y31MCvD0i wbZM3oL4/jAOggORk5iCt+7Oro1tsQMIrTAGpPF2U350CygvOzvbdp+InJb11F9qIlLb 1V3gqBwU6Rk/TcewMAGBhJlrefSI/uMHwzyT64oPf/hibAjyaVgF6rtucrcEqzlg6ZSf 7hqg== X-Gm-Message-State: AOAM533ijlqNcuKmUUbOlQo0vgdXtY/rD2lUSB6haPri1vHBKAh2EqKo RzXMxOqld/l9bBrFArEuQuIip4dS284= X-Google-Smtp-Source: ABdhPJwoxFTfQsaxqZjRyXNlN+qaWzQJbRfLRJXdZAZMENt2kLLNtbFIRJsdZX81dy+CmFmKocNmwA== X-Received: by 2002:a05:6a00:15c2:b0:4bb:3ab:83ca with SMTP id o2-20020a056a0015c200b004bb03ab83camr26992pfu.18.1640123350218; Tue, 21 Dec 2021 13:49:10 -0800 (PST) Received: from gnu-tgl-3.localdomain ([172.58.35.133]) by smtp.gmail.com with ESMTPSA id c19sm3440713pjv.39.2021.12.21.13.49.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Dec 2021 13:49:09 -0800 (PST) Received: from gnu-tgl-2.localdomain (gnu-tgl-2 [192.168.1.42]) by gnu-tgl-3.localdomain (Postfix) with ESMTPS id 7C965C0192 for ; Tue, 21 Dec 2021 13:49:07 -0800 (PST) Received: from gnu-tgl-2.. (localhost [IPv6:::1]) by gnu-tgl-2.localdomain (Postfix) with ESMTP id 503513003DA for ; Tue, 21 Dec 2021 13:49:06 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH v6 1/2] elf: Properly align all PT_LOAD segments [BZ #28676] Date: Tue, 21 Dec 2021 13:49:05 -0800 Message-Id: <20211221214906.2105602-1-hjl.tools@gmail.com> X-Mailer: git-send-email 2.33.1 MIME-Version: 1.0 X-Spam-Status: No, score=-3029.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" 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 Date: Thu Oct 15 20:12:32 2020 -0700 fs/binfmt_elf: use PT_LOAD p_align values for suitable start address --- elf/dl-load.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index 721593135e..e61515771a 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -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 From patchwork Tue Dec 21 21:49:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 49159 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 397B33858429 for ; Tue, 21 Dec 2021 21:49:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 397B33858429 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1640123372; bh=oWpNhp/mxuFH3N6Bl84SnUPKRhTa6/kOdR2wGkFiGbo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Eg7NnrY5A9MS5dWTQwz0RKtR1t2hQZhqnTuJAaQ1p+dSjtSfDIFY+ke5N4Quqnz5x DkuYGE6ZAqcVciuQ6r4jMLMLWOKn2vEkfTVrrTm8qzUpRFJopoNQbmr9172tfBToej yD3mKbkCqo7uO9lJHRMgYR4fY/NTjZVVqLAjcIQQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by sourceware.org (Postfix) with ESMTPS id 907D83858C60 for ; Tue, 21 Dec 2021 21:49:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 907D83858C60 Received: by mail-pj1-x1029.google.com with SMTP id f18-20020a17090aa79200b001ad9cb23022so512549pjq.4 for ; Tue, 21 Dec 2021 13:49:10 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oWpNhp/mxuFH3N6Bl84SnUPKRhTa6/kOdR2wGkFiGbo=; b=5UbXuywSERJZFZ+zWiLFIVJp96wEbKPKid19sVn06kI883eTxo79U62liyakuf8ycb YlI8/+HTkWfECBRWIJ/zllWLFSvIeb42AxA7ihzhun2kVWFk2WAfVGeOpiiE4ERQDMpE jwBAlbgZWoOUGnyesQ9TPl2z35tlFg9YjKT4BksCq2PGfHBweeFqDJIO7/BYHp7WkYrO lqFa+b4tY9Gjybcnwv3qhEOCIU77b5cRNDN9Dc+kd4KZQu3s7ZlNC1MoZPdCDUfYmzFM dS1uNNzf0RiR7cpsRcw2oq9YfuSKywhDjTkUexzB7EMjokbMuDOaMVjmacm5zP/K7P0x CZUA== X-Gm-Message-State: AOAM533MbQMBYGX3NxqS0/qSgW2C90Ft8yKgZZ77ubqFZCKaIUtu3UNh z0iGZ5FQZ4KH2GzX90amXuaaxM6OsQM= X-Google-Smtp-Source: ABdhPJybNX8+3zOSy35z+6stsMTNIBI3oA/l7q8Rz5UJq5uXxhO4jbW4bDhGTgkxrO8DuQerPV+TTg== X-Received: by 2002:a17:902:ab04:b0:148:9284:d7c0 with SMTP id ik4-20020a170902ab0400b001489284d7c0mr182868plb.50.1640123349275; Tue, 21 Dec 2021 13:49:09 -0800 (PST) Received: from gnu-tgl-3.localdomain ([172.58.35.133]) by smtp.gmail.com with ESMTPSA id q22sm71540pfk.27.2021.12.21.13.49.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Dec 2021 13:49:08 -0800 (PST) Received: from gnu-tgl-2.localdomain (gnu-tgl-2 [192.168.1.42]) by gnu-tgl-3.localdomain (Postfix) with ESMTPS id 7F58CC0722 for ; Tue, 21 Dec 2021 13:49:07 -0800 (PST) Received: from gnu-tgl-2.. (localhost [IPv6:::1]) by gnu-tgl-2.localdomain (Postfix) with ESMTP id 5148D3003DB for ; Tue, 21 Dec 2021 13:49:06 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH v6 2/2] elf: Add a test for PT_LOAD segments with mixed p_align [BZ #28676] Date: Tue, 21 Dec 2021 13:49:06 -0800 Message-Id: <20211221214906.2105602-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211221214906.2105602-1-hjl.tools@gmail.com> References: <20211221214906.2105602-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3029.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Add tst-p_alignmod1-edit to edit the copy of tst-alignmod3.so to reduce p_align of the first PT_LOAD segment by half and verify that the shared library is mapped with the maximum p_align of all PT_LOAD segments. --- elf/Makefile | 18 ++++++ elf/tst-elf-edit.h | 126 +++++++++++++++++++++++++++++++++++++ elf/tst-p_align1.c | 27 ++++++++ elf/tst-p_alignmod1-edit.c | 34 ++++++++++ 4 files changed, 205 insertions(+) create mode 100644 elf/tst-elf-edit.h create mode 100644 elf/tst-p_align1.c create mode 100644 elf/tst-p_alignmod1-edit.c diff --git a/elf/Makefile b/elf/Makefile index fe42caeb0e..6435fb0022 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -378,6 +378,13 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-auditmod18 \ tst-audit18mod \ +ifeq (yes,$(build-shared)) +tests += \ + tst-p_alignmod1-edit \ + tst-p_align1 \ + +endif + # Most modules build with _ISOMAC defined, but those filtered out # depend on internal headers. modules-names-tests = $(filter-out ifuncmod% tst-tlsmod%,\ @@ -1995,3 +2002,14 @@ $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \ $(objpfx)tst-ro-dynamic-mod.os $(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig + +$(objpfx)tst-p_align1: $(objpfx)tst-p_alignmod1.so + +# Make a copy of tst-alignmod3.so and lower p_align of the first PT_LOAD +# segment. +$(objpfx)tst-p_alignmod1.so: $(objpfx)tst-p_alignmod1-edit \ + $(objpfx)tst-alignmod3.so + rm -f $@ + cp $(objpfx)tst-alignmod3.so $@ + $(test-wrapper-env) $(run-program-env) $(rtld-prefix) \ + $(objpfx)tst-p_alignmod1-edit $@ diff --git a/elf/tst-elf-edit.h b/elf/tst-elf-edit.h new file mode 100644 index 0000000000..ce98cf012c --- /dev/null +++ b/elf/tst-elf-edit.h @@ -0,0 +1,126 @@ +/* Update p_align of the first PT_LOAD segment. + 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 +#include +#include +#include +#include +#include +#include +#include + +const char *file_name; + +static size_t update_p_align (size_t); + +int +main (int argc, char ** argv) +{ + if (argc != 2) + { + printf ("Usage: %s: file\n", argv[0]); + return 0; + } + + file_name = argv[1]; + struct stat statbuf; + int errno_saved; + + if (stat (file_name, &statbuf) < 0) + error (1, errno, "%s: not exist", file_name); + + ElfW(Ehdr) *ehdr; + + if (statbuf.st_size < sizeof (*ehdr)) + error (1, 0, "%s: too small", file_name); + + int fd = open (file_name, O_RDWR); + if (fd < 0) + error (1, errno, "%s: can't open", file_name); + + /* Map in the whole file. */ + void *base = mmap (NULL, statbuf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (base == MAP_FAILED) + { + errno_saved = errno; + close (fd); + error (1, errno_saved, "%s: failed to map", file_name); + } + + ehdr = (ElfW(Ehdr) *) base; + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 + || ehdr->e_ident[EI_MAG1] != ELFMAG1 + || ehdr->e_ident[EI_MAG2] != ELFMAG2 + || ehdr->e_ident[EI_MAG3] != ELFMAG3) + { + close (fd); + error (1, 0, "%s: bad ELF header", file_name); + } + + if (ehdr->e_type != ET_DYN) + { + close (fd); + error (1, 0, "%s: not shared library", file_name); + } + + bool unsupported_class = true; + switch (ehdr->e_ident[EI_CLASS]) + { + default: + break; + + case ELFCLASS32: + unsupported_class = __ELF_NATIVE_CLASS != 32; + break; + + case ELFCLASS64: + unsupported_class = __ELF_NATIVE_CLASS != 64; + break; + } + + if (unsupported_class) + { + close (fd); + error (1, 0, "%s: unsupported ELF class: %d", + file_name, ehdr->e_ident[EI_CLASS]); + } + + size_t phdr_size = sizeof (ElfW(Phdr)) * ehdr->e_phentsize; + if (statbuf.st_size < (ehdr->e_phoff + phdr_size)) + { + close (fd); + error (1, 0, "%s: too small", file_name); + } + + ElfW(Phdr) *phdr = (ElfW(Phdr) *) (base + ehdr->e_phoff); + for (int i = 0; i < ehdr->e_phnum; i++, phdr++) + if (phdr->p_type == PT_LOAD) + { + /* Update p_align of the first PT_LOAD segment. */ + phdr->p_align = update_p_align (phdr->p_align); + break; + } + + munmap (base, statbuf.st_size); + close (fd); + + return 0; +} diff --git a/elf/tst-p_align1.c b/elf/tst-p_align1.c new file mode 100644 index 0000000000..cab9793220 --- /dev/null +++ b/elf/tst-p_align1.c @@ -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 + . */ + +extern int do_load_test (void); + +static int +do_test (void) +{ + return do_load_test (); +} + +#include diff --git a/elf/tst-p_alignmod1-edit.c b/elf/tst-p_alignmod1-edit.c new file mode 100644 index 0000000000..2aa0e7ccdd --- /dev/null +++ b/elf/tst-p_alignmod1-edit.c @@ -0,0 +1,34 @@ +/* Reduce p_align of the first PT_LOAD segment by half. + 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 "tst-elf-edit.h" + +/* Reduce p_align by half. */ + +static size_t +update_p_align (size_t p_align) +{ + size_t pagesize = sysconf (_SC_PAGESIZE); + size_t new_p_align = p_align >> 1; + + if (new_p_align < pagesize) + error (1, 0, "%s: new p_align (0x%zx) < page size (0x%zx)", + file_name, new_p_align, pagesize); + + return new_p_align; +}