| Message ID | CAMe9rOqP44oi5pxb7LNsEPK0+owjjdWdQW_f6Qp5Zb8o-WTE+Q@mail.gmail.com |
|---|---|
| State | New |
| Headers |
Return-Path: <binutils-bounces~patchwork=sourceware.org@sourceware.org> 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 57F5F385840C for <patchwork@sourceware.org>; Tue, 23 Sep 2025 02:25:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 57F5F385840C Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=A7+F1grO X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-yb1-xb2a.google.com (mail-yb1-xb2a.google.com [IPv6:2607:f8b0:4864:20::b2a]) by sourceware.org (Postfix) with ESMTPS id F16A13858D1E for <binutils@sourceware.org>; Tue, 23 Sep 2025 02:24:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F16A13858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F16A13858D1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::b2a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758594263; cv=none; b=bSNklH68VDrR+46EFmamlOug8iD6Q69slpz2GCAXV4ZOzhUuAmA5Qj9H9lJNhO0zXTGzrvUKuUzfeREl5jRDUra8h/V6QPDobcr3myKREaztLO+MTdt8ONwe6ovsFET4Hipp4DY8hIab7yIaNQvvYYQimbcFKIHotVSNWPbbixA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758594263; c=relaxed/simple; bh=dYkcvtvHrvTMkvZTGO9hVZPYzpkObxD0z12bHQVyarE=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=SNqT9Xh4y1IHdvOZ+9kvIWQKp4LNKBKXAfC7ifRaMJpx8NJ5h2/NazjxJ9gSjFESJwCk9D6NQNRuVIl67x0WmAEbJkTM1UbwuUPS4j+wsZnwfjnX9jIvDwlHCTm+kgfyzNNeBj56T7q3Gg/B3ZsZJUuaqrGDe6GnhdO0hhk0//o= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F16A13858D1E Received: by mail-yb1-xb2a.google.com with SMTP id 3f1490d57ef6-e94d678e116so5526513276.2 for <binutils@sourceware.org>; Mon, 22 Sep 2025 19:24:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1758594262; x=1759199062; darn=sourceware.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=ClIfko1S/HPs2AjJCDqrAzbPNOOdmUnsNu1gvjanUrs=; b=A7+F1grOox2STb0T7RtNQcqwg68BVMqVYFdpK55pHXBRkj4zGtisgeG8z6qNJOyEqg m52gURfZuuqWuytWl2Va9sMbqXE76Xc9OUFcjqoYoA9cLTXmgSeb+7RHN/olCVutAEjl O/wwjDa/ZJ8vudyR8mxc8530t8aH+f1ygSPYeJq0vCHcqP62v3aHTby755eniICCiTBO L00ZnxaBR7QXYNcocYtD7Xgk301m6+GdKuiGmEKArPavMx8e6hbvMiJ2PRcEM3fFoops FLxFMovgjyhk9cI4Uwmy6bzIGx+93Yz/LFofsyNrt9sYzKJB7SWukJVTkiKSy/C0jkxg 7LBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758594262; x=1759199062; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=ClIfko1S/HPs2AjJCDqrAzbPNOOdmUnsNu1gvjanUrs=; b=Y2TTnPzY+RHyUyou09BLj7UOGvmixWgqdktz0RVMjoyVzBapmip46UvSlt3BgqyB5Y /hZOXH3wCbh6assiAsH0kX84b19M3gOYrqp1vwR9v8k2ek7au0moNW0OZ4y8rZAcvR3j CFBPrwF5OYlIV60GyuqnjfCuVqQVRXRdT7pos31UWCPK+YLY6j5nzR8Si34jtfoH+t+d oz6sQpALpwl0p0nJmBUgLJgq00xgp2U0d4DLwkyfAhIMeTBbD70LVi5UaUO2kkZRw8JH tLuDQ/g5QGbPoFTmAdxT4FY3uyi4Y9ZxsvTfM+vxBPv6+gykhtn0CIcDkFeVmJ3RaoWS pbQQ== X-Gm-Message-State: AOJu0YzcQDbCtP/fCdct/TthXmyAohxy4oUl/GGfEddtkFV4ssJW158H mGm1pEbaqmvwP0vADaQfzyDd8vwAd5bc7I7qwSuyym9TcOYJp0AHxtlFVpBV7+BmBO2HE/BMEGu i44W48TFP7SyOC8wB/gWTpa28NJ0BLy794C7Lf64= X-Gm-Gg: ASbGncuOKWuTu+94MICF/ltXkWPZJg6/BNASa/dJMVKDtH3o59li19gZzq9DMbxOn7z /IXTgnIiA1D/gM/N9EWqCDBwY7PXXkla1XAIYFhketdopaaNVOIyhhi/2FKU0DcA62D6YZRq+gm 2B3PbE9kzz5hu9svAatKU1Ym2ZbbRxkLMvL03/egJwg4PLFYfO1IL/q1860h5fFqbyW6uVVxBTw Mvd5yI+ X-Google-Smtp-Source: AGHT+IFlT8YWq7pauiR97ePM/pMckuNiEguq9vjvk4mQ5kj8MmAsi7BWJPje41IKF0rQcz/r4htZqAUpLMNdIjtvVOU= X-Received: by 2002:a05:690e:2452:b0:635:4ecf:bdc6 with SMTP id 956f58d0204a3-6360464a990mr619385d50.40.1758594262139; Mon, 22 Sep 2025 19:24:22 -0700 (PDT) MIME-Version: 1.0 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Tue, 23 Sep 2025 10:23:45 +0800 X-Gm-Features: AS18NWBqJiGJOsfO1dLQUmcGB5218BgQfxDHM3oSoQSosKsgfezOh5R6rMV9_eQ Message-ID: <CAMe9rOqP44oi5pxb7LNsEPK0+owjjdWdQW_f6Qp5Zb8o-WTE+Q@mail.gmail.com> Subject: [PATCH 3/4] elf: Avoid linker crash on corrupt .eh_frame section To: Binutils <binutils@sourceware.org>, Alan Modra <amodra@gmail.com>, Nick Clifton <nickc@redhat.com>, Jan Beulich <JBeulich@suse.com> Content-Type: multipart/mixed; boundary="0000000000004cf23c063f6ea28e" X-Spam-Status: No, score=-3012.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list <binutils.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/binutils>, <mailto:binutils-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/binutils/> List-Post: <mailto:binutils@sourceware.org> List-Help: <mailto:binutils-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/binutils>, <mailto:binutils-request@sourceware.org?subject=subscribe> Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org |
| Series |
[1/4] elf: Disallow the empty symbol name
|
|
Commit Message
H.J. Lu
Sept. 23, 2025, 2:23 a.m. UTC
Return false on corrupt .eh_frame section. Cap the .eh_frame section alignment to the larger of the section size and the pointer size. PR ld/33453 * elf-bfd.h (ABI_64_P): New. * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false on corrupt .eh_frame section. * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section alignment. * elfxx-mips.c (ABI_64_P): Removed. * elfxx-sparc.c (ABI_64_P): Likewise. * elfxx-tilegx.c (ABI_64_P): Likewise. * elfxx-x86.h (ABI_64_P): Likewise.
Comments
On Tue, Sep 23, 2025 at 10:23:45AM +0800, H.J. Lu wrote: > Return false on corrupt .eh_frame section. Cap the .eh_frame section > alignment to the larger of the section size and the pointer size. > > PR ld/33453 > * elf-bfd.h (ABI_64_P): New. > * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false > on corrupt .eh_frame section. > * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section > alignment. > * elfxx-mips.c (ABI_64_P): Removed. > * elfxx-sparc.c (ABI_64_P): Likewise. > * elfxx-tilegx.c (ABI_64_P): Likewise. > * elfxx-x86.h (ABI_64_P): Likewise. > > -- > H.J. > From dc96baa76c046ed34b05926a6401c6ebd0d1eb03 Mon Sep 17 00:00:00 2001 > From: "H.J. Lu" <hjl.tools@gmail.com> > Date: Tue, 23 Sep 2025 08:25:49 +0800 > Subject: [PATCH 3/4] elf: Avoid linker crash on corrupt .eh_frame section > > Return false on corrupt .eh_frame section. Cap the .eh_frame section > alignment to the larger of the section size and the pointer size. > > PR ld/33453 > * elf-bfd.h (ABI_64_P): New. > * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false > on corrupt .eh_frame section. > * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section > alignment. > * elfxx-mips.c (ABI_64_P): Removed. > * elfxx-sparc.c (ABI_64_P): Likewise. > * elfxx-tilegx.c (ABI_64_P): Likewise. > * elfxx-x86.h (ABI_64_P): Likewise. > > Signed-off-by: H.J. Lu <hjl.tools@gmail.com> > --- > bfd/elf-bfd.h | 3 +++ > bfd/elf-eh-frame.c | 5 +++++ > bfd/elf.c | 21 +++++++++++++++++++-- > bfd/elfxx-mips.c | 4 ---- > bfd/elfxx-sparc.c | 3 --- > bfd/elfxx-tilegx.c | 3 --- > bfd/elfxx-x86.h | 3 --- > 7 files changed, 27 insertions(+), 15 deletions(-) > > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > index 51e6ae7bb78..5a131d735ff 100644 > --- a/bfd/elf-bfd.h > +++ b/bfd/elf-bfd.h > @@ -1919,6 +1919,9 @@ struct bfd_elf_section_data > #define get_elf_backend_data(abfd) \ > xvec_get_elf_backend_data ((abfd)->xvec) > > +#define ABI_64_P(abfd) \ > + (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > + > /* The least object attributes (within an attributes subsection) known > for any target. Some code assumes that the value 0 is not used and > the field for that attribute can instead be used as a marker to > diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c > index 30bb313489c..93d412b38f0 100644 > --- a/bfd/elf-eh-frame.c > +++ b/bfd/elf-eh-frame.c > @@ -2126,6 +2126,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, > > /* Skip length. */ > cie = ent->u.fde.cie_inf; > + if (cie == NULL) > + { > + _bfd_error_handler (_("corrupt .eh_frame section")); > + return false; > + } > buf += 4; > value = ((ent->new_offset + sec->output_offset + 4) > - (cie->new_offset + cie->u.cie.u.sec->output_offset)); > diff --git a/bfd/elf.c b/bfd/elf.c > index 6ef60301091..07428cb91f9 100644 > --- a/bfd/elf.c > +++ b/bfd/elf.c > @@ -981,10 +981,27 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, > } > } > > + bfd_size_type alignment = hdr->sh_addralign; > + if (streq (name, ".eh_frame")) > + { > + bfd_size_type eh_alignment = ABI_64_P (abfd) ? 8 : 4; > + if (hdr->sh_size > eh_alignment) > + eh_alignment = 1 << bfd_log2 (hdr->sh_size); sh_size?? > + if (alignment > eh_alignment) > + { > + _bfd_error_handler > + /* xgettext:c-format */ > + (_("%pB: warning: ignore .eh_frame section alignment (%ld), limit it to %ld"), > + abfd, (unsigned long) alignment, > + (unsigned long) eh_alignment); > + alignment = eh_alignment; > + } > + } > + > if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb) > || !bfd_set_section_size (newsect, hdr->sh_size) > - || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign > - & -hdr->sh_addralign))) > + || !bfd_set_section_alignment (newsect, bfd_log2 (alignment > + & -alignment))) > return false; > > /* As a GNU extension, if the name begins with .gnu.linkonce, we > diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c > index bf3fd7df805..181f9f5e9fc 100644 > --- a/bfd/elfxx-mips.c > +++ b/bfd/elfxx-mips.c > @@ -816,10 +816,6 @@ static bfd *reldyn_sorting_bfd; > #define ABI_N32_P(abfd) \ > ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) > > -/* Nonzero if ABFD is using the N64 ABI. */ > -#define ABI_64_P(abfd) \ > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > - > /* Nonzero if ABFD is using NewABI conventions. */ > #define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd)) > > diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c > index bbaa7829132..1f3b9d831d8 100644 > --- a/bfd/elfxx-sparc.c > +++ b/bfd/elfxx-sparc.c > @@ -37,9 +37,6 @@ > /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ > #define MINUS_ONE (~ (bfd_vma) 0) > > -#define ABI_64_P(abfd) \ > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > - > /* The relocation "howto" table. */ > > /* Utility for performing the standard initial work of an instruction > diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c > index 79358e6b204..577d259a3b8 100644 > --- a/bfd/elfxx-tilegx.c > +++ b/bfd/elfxx-tilegx.c > @@ -27,9 +27,6 @@ > #include "libiberty.h" > #include "elfxx-tilegx.h" > > -#define ABI_64_P(abfd) \ > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > - > #define TILEGX_ELF_WORD_BYTES(htab) \ > ((htab)->bytes_per_word) > > diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h > index 1ebc9d2f2e5..902592a3cf0 100644 > --- a/bfd/elfxx-x86.h > +++ b/bfd/elfxx-x86.h > @@ -102,9 +102,6 @@ > header. */ > #define PLT_SFRAME_FDE_START_OFFSET sizeof (sframe_header) > > -#define ABI_64_P(abfd) \ > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > - > /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid > copying dynamic variables from a shared lib into an app's dynbss > section, and instead use a dynamic relocation to point into the > -- > 2.51.0 >
On 23.09.2025 04:23, H.J. Lu wrote: > Return false on corrupt .eh_frame section. Cap the .eh_frame section > alignment to the larger of the section size and the pointer size. Like for patch 2, I'm unconvinced of it being a good idea to build in heuristics like this. What if someone feels a need to align .eh_frame to, say, a page boundary? Also, please format unsigned long-s using %lu or (here) %lx. Especially when values get large, imo printing them as decimal is unhelpful. Finally - why would .eh_frame be special in this regard? What about, say, .sframe? Jan
On Tue, Sep 23, 2025 at 7:58 PM Alan Modra <amodra@gmail.com> wrote: > > On Tue, Sep 23, 2025 at 10:23:45AM +0800, H.J. Lu wrote: > > Return false on corrupt .eh_frame section. Cap the .eh_frame section > > alignment to the larger of the section size and the pointer size. > > > > PR ld/33453 > > * elf-bfd.h (ABI_64_P): New. > > * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false > > on corrupt .eh_frame section. > > * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section > > alignment. > > * elfxx-mips.c (ABI_64_P): Removed. > > * elfxx-sparc.c (ABI_64_P): Likewise. > > * elfxx-tilegx.c (ABI_64_P): Likewise. > > * elfxx-x86.h (ABI_64_P): Likewise. > > > > -- > > H.J. > > > From dc96baa76c046ed34b05926a6401c6ebd0d1eb03 Mon Sep 17 00:00:00 2001 > > From: "H.J. Lu" <hjl.tools@gmail.com> > > Date: Tue, 23 Sep 2025 08:25:49 +0800 > > Subject: [PATCH 3/4] elf: Avoid linker crash on corrupt .eh_frame section > > > > Return false on corrupt .eh_frame section. Cap the .eh_frame section > > alignment to the larger of the section size and the pointer size. > > > > PR ld/33453 > > * elf-bfd.h (ABI_64_P): New. > > * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false > > on corrupt .eh_frame section. > > * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section > > alignment. > > * elfxx-mips.c (ABI_64_P): Removed. > > * elfxx-sparc.c (ABI_64_P): Likewise. > > * elfxx-tilegx.c (ABI_64_P): Likewise. > > * elfxx-x86.h (ABI_64_P): Likewise. > > > > Signed-off-by: H.J. Lu <hjl.tools@gmail.com> > > --- > > bfd/elf-bfd.h | 3 +++ > > bfd/elf-eh-frame.c | 5 +++++ > > bfd/elf.c | 21 +++++++++++++++++++-- > > bfd/elfxx-mips.c | 4 ---- > > bfd/elfxx-sparc.c | 3 --- > > bfd/elfxx-tilegx.c | 3 --- > > bfd/elfxx-x86.h | 3 --- > > 7 files changed, 27 insertions(+), 15 deletions(-) > > > > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > > index 51e6ae7bb78..5a131d735ff 100644 > > --- a/bfd/elf-bfd.h > > +++ b/bfd/elf-bfd.h > > @@ -1919,6 +1919,9 @@ struct bfd_elf_section_data > > #define get_elf_backend_data(abfd) \ > > xvec_get_elf_backend_data ((abfd)->xvec) > > > > +#define ABI_64_P(abfd) \ > > + (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > > + > > /* The least object attributes (within an attributes subsection) known > > for any target. Some code assumes that the value 0 is not used and > > the field for that attribute can instead be used as a marker to > > diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c > > index 30bb313489c..93d412b38f0 100644 > > --- a/bfd/elf-eh-frame.c > > +++ b/bfd/elf-eh-frame.c > > @@ -2126,6 +2126,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, > > > > /* Skip length. */ > > cie = ent->u.fde.cie_inf; > > + if (cie == NULL) > > + { > > + _bfd_error_handler (_("corrupt .eh_frame section")); > > + return false; > > + } > > buf += 4; > > value = ((ent->new_offset + sec->output_offset + 4) > > - (cie->new_offset + cie->u.cie.u.sec->output_offset)); > > diff --git a/bfd/elf.c b/bfd/elf.c > > index 6ef60301091..07428cb91f9 100644 > > --- a/bfd/elf.c > > +++ b/bfd/elf.c > > @@ -981,10 +981,27 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, > > } > > } > > > > + bfd_size_type alignment = hdr->sh_addralign; > > + if (streq (name, ".eh_frame")) > > + { > > + bfd_size_type eh_alignment = ABI_64_P (abfd) ? 8 : 4; > > + if (hdr->sh_size > eh_alignment) > > + eh_alignment = 1 << bfd_log2 (hdr->sh_size); > > sh_size?? Normally, .eh_frame section is aligned to 8 or 4 bytes, depending on ELF class. But a larger alignment is possible. Without eh_alignment = 1 << bfd_log2 (hdr->sh_size); I got: ./ld-new: tmpdir/eh3.o: warning: ignore .eh_frame section alignment (16), limit it to 8 FAIL: ld-elf/eh3 /export/build/gnu/tools-build/binutils-gitlab-test/build-x86_64-linux/ld/../binutils/objdump: tmpdir/dump: warning: ignore .eh_frame section alignment (8), limit it to 4 FAIL: ld-x86-64/pr18160 ./ld-new: tmpdir/simple-x32.o: warning: ignore .eh_frame section alignment (8), limit it to 4 FAIL: X32 DSO from x86-64 object The section size is a reasonable upper bound. > > + if (alignment > eh_alignment) > > + { > > + _bfd_error_handler > > + /* xgettext:c-format */ > > + (_("%pB: warning: ignore .eh_frame section alignment (%ld), limit it to %ld"), > > + abfd, (unsigned long) alignment, > > + (unsigned long) eh_alignment); > > + alignment = eh_alignment; > > + } > > + } > > + > > if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb) > > || !bfd_set_section_size (newsect, hdr->sh_size) > > - || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign > > - & -hdr->sh_addralign))) > > + || !bfd_set_section_alignment (newsect, bfd_log2 (alignment > > + & -alignment))) > > return false; > > > > /* As a GNU extension, if the name begins with .gnu.linkonce, we > > diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c > > index bf3fd7df805..181f9f5e9fc 100644 > > --- a/bfd/elfxx-mips.c > > +++ b/bfd/elfxx-mips.c > > @@ -816,10 +816,6 @@ static bfd *reldyn_sorting_bfd; > > #define ABI_N32_P(abfd) \ > > ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) > > > > -/* Nonzero if ABFD is using the N64 ABI. */ > > -#define ABI_64_P(abfd) \ > > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > > - > > /* Nonzero if ABFD is using NewABI conventions. */ > > #define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd)) > > > > diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c > > index bbaa7829132..1f3b9d831d8 100644 > > --- a/bfd/elfxx-sparc.c > > +++ b/bfd/elfxx-sparc.c > > @@ -37,9 +37,6 @@ > > /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ > > #define MINUS_ONE (~ (bfd_vma) 0) > > > > -#define ABI_64_P(abfd) \ > > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > > - > > /* The relocation "howto" table. */ > > > > /* Utility for performing the standard initial work of an instruction > > diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c > > index 79358e6b204..577d259a3b8 100644 > > --- a/bfd/elfxx-tilegx.c > > +++ b/bfd/elfxx-tilegx.c > > @@ -27,9 +27,6 @@ > > #include "libiberty.h" > > #include "elfxx-tilegx.h" > > > > -#define ABI_64_P(abfd) \ > > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > > - > > #define TILEGX_ELF_WORD_BYTES(htab) \ > > ((htab)->bytes_per_word) > > > > diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h > > index 1ebc9d2f2e5..902592a3cf0 100644 > > --- a/bfd/elfxx-x86.h > > +++ b/bfd/elfxx-x86.h > > @@ -102,9 +102,6 @@ > > header. */ > > #define PLT_SFRAME_FDE_START_OFFSET sizeof (sframe_header) > > > > -#define ABI_64_P(abfd) \ > > - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) > > - > > /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid > > copying dynamic variables from a shared lib into an app's dynbss > > section, and instead use a dynamic relocation to point into the > > -- > > 2.51.0 > > > > > -- > Alan Modra
On Tue, Sep 23, 2025 at 10:50 PM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.09.2025 04:23, H.J. Lu wrote: > > Return false on corrupt .eh_frame section. Cap the .eh_frame section > > alignment to the larger of the section size and the pointer size. > > Like for patch 2, I'm unconvinced of it being a good idea to build in > heuristics like this. What if someone feels a need to align .eh_frame > to, say, a page boundary? .eh_frame section is special: eh_alignment = ((1 << o->alignment_power) * bfd_octets_per_byte (output_bfd, o)); /* Skip over zero terminator, and prevent empty sections from adding alignment padding at the end. */ for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) if (i->size == 0) i->flags |= SEC_EXCLUDE; else if (i->size > 4) break; /* The last non-empty eh_frame section doesn't need padding. */ if (i != NULL) i = i->map_tail.s; /* Any prior sections must pad the last FDE out to the output section alignment. Otherwise we might have zero padding between sections, which would be seen as a terminator. */ for (; i != NULL; i = i->map_tail.s) if (i->size == 4) /* All but the last zero terminator should have been removed. */ BFD_FAIL (); else { bfd_size_type size = (i->size + eh_alignment - 1) & -eh_alignment; If .eh_frame section alignment is larger than the section size, we will get buffer overflow. if (i->size != size) { i->size = size; changed = 1; eh_changed = 1; } } > Also, please format unsigned long-s using %lu or (here) %lx. Especially > when values get large, imo printing them as decimal is unhelpful. Will do. > Finally - why would .eh_frame be special in this regard? What about, > say, .sframe? > .sframe section doesn't do the code above.
On 23.09.2025 22:46, H.J. Lu wrote: > On Tue, Sep 23, 2025 at 10:50 PM Jan Beulich <jbeulich@suse.com> wrote: >> >> On 23.09.2025 04:23, H.J. Lu wrote: >>> Return false on corrupt .eh_frame section. Cap the .eh_frame section >>> alignment to the larger of the section size and the pointer size. >> >> Like for patch 2, I'm unconvinced of it being a good idea to build in >> heuristics like this. What if someone feels a need to align .eh_frame >> to, say, a page boundary? > > .eh_frame section is special: > > eh_alignment = ((1 << o->alignment_power) > * bfd_octets_per_byte (output_bfd, o)); > /* Skip over zero terminator, and prevent empty sections from > adding alignment padding at the end. */ > for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) > if (i->size == 0) > i->flags |= SEC_EXCLUDE; > else if (i->size > 4) > break; > /* The last non-empty eh_frame section doesn't need padding. */ > if (i != NULL) > i = i->map_tail.s; > /* Any prior sections must pad the last FDE out to the output > section alignment. Otherwise we might have zero padding > between sections, which would be seen as a terminator. */ > for (; i != NULL; i = i->map_tail.s) > if (i->size == 4) > /* All but the last zero terminator should have been removed. */ > BFD_FAIL (); > else > { > bfd_size_type size > = (i->size + eh_alignment - 1) & -eh_alignment; > > If .eh_frame section alignment is larger than the section size, > we will get buffer overflow. > > if (i->size != size) > { > i->size = size; > changed = 1; > eh_changed = 1; > } > } > >> Also, please format unsigned long-s using %lu or (here) %lx. Especially >> when values get large, imo printing them as decimal is unhelpful. > > Will do. > >> Finally - why would .eh_frame be special in this regard? What about, >> say, .sframe? >> > > .sframe section doesn't do the code above. I understand that, but I hoped you would also understand that I'm merely trying to give examples. In all of your reply you didn't address my question "What if someone feels a need to align .eh_frame to, say, a page boundary?" If someone doing so resulted in a buffer overflow, that would indeed want fixing. But not by preventing them to use that kind of alignment. Jan
On Thu, Sep 25, 2025 at 2:06 PM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.09.2025 22:46, H.J. Lu wrote: > > On Tue, Sep 23, 2025 at 10:50 PM Jan Beulich <jbeulich@suse.com> wrote: > >> > >> On 23.09.2025 04:23, H.J. Lu wrote: > >>> Return false on corrupt .eh_frame section. Cap the .eh_frame section > >>> alignment to the larger of the section size and the pointer size. > >> > >> Like for patch 2, I'm unconvinced of it being a good idea to build in > >> heuristics like this. What if someone feels a need to align .eh_frame > >> to, say, a page boundary? > > > > .eh_frame section is special: > > > > eh_alignment = ((1 << o->alignment_power) > > * bfd_octets_per_byte (output_bfd, o)); > > /* Skip over zero terminator, and prevent empty sections from > > adding alignment padding at the end. */ > > for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) > > if (i->size == 0) > > i->flags |= SEC_EXCLUDE; > > else if (i->size > 4) > > break; > > /* The last non-empty eh_frame section doesn't need padding. */ > > if (i != NULL) > > i = i->map_tail.s; > > /* Any prior sections must pad the last FDE out to the output > > section alignment. Otherwise we might have zero padding > > between sections, which would be seen as a terminator. */ > > for (; i != NULL; i = i->map_tail.s) > > if (i->size == 4) > > /* All but the last zero terminator should have been removed. */ > > BFD_FAIL (); > > else > > { > > bfd_size_type size > > = (i->size + eh_alignment - 1) & -eh_alignment; > > > > If .eh_frame section alignment is larger than the section size, > > we will get buffer overflow. > > > > if (i->size != size) > > { > > i->size = size; > > changed = 1; > > eh_changed = 1; > > } > > } > > > >> Also, please format unsigned long-s using %lu or (here) %lx. Especially > >> when values get large, imo printing them as decimal is unhelpful. > > > > Will do. > > > >> Finally - why would .eh_frame be special in this regard? What about, > >> say, .sframe? > >> > > > > .sframe section doesn't do the code above. > > I understand that, but I hoped you would also understand that I'm merely > trying to give examples. In all of your reply you didn't address my question > "What if someone feels a need to align .eh_frame to, say, a page boundary?" > If someone doing so resulted in a buffer overflow, that would indeed want > fixing. But not by preventing them to use that kind of alignment. > > Jan So far, we don't have any request for large .eh_frame section alignment. My patch simply changes the linker crash to a linker error. If people do need large .eh_frame section alignments in the future, we can work with them to resolve their issues.
On 25.09.2025 08:32, H.J. Lu wrote: > On Thu, Sep 25, 2025 at 2:06 PM Jan Beulich <jbeulich@suse.com> wrote: >> >> On 23.09.2025 22:46, H.J. Lu wrote: >>> On Tue, Sep 23, 2025 at 10:50 PM Jan Beulich <jbeulich@suse.com> wrote: >>>> >>>> On 23.09.2025 04:23, H.J. Lu wrote: >>>>> Return false on corrupt .eh_frame section. Cap the .eh_frame section >>>>> alignment to the larger of the section size and the pointer size. >>>> >>>> Like for patch 2, I'm unconvinced of it being a good idea to build in >>>> heuristics like this. What if someone feels a need to align .eh_frame >>>> to, say, a page boundary? >>> >>> .eh_frame section is special: >>> >>> eh_alignment = ((1 << o->alignment_power) >>> * bfd_octets_per_byte (output_bfd, o)); >>> /* Skip over zero terminator, and prevent empty sections from >>> adding alignment padding at the end. */ >>> for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) >>> if (i->size == 0) >>> i->flags |= SEC_EXCLUDE; >>> else if (i->size > 4) >>> break; >>> /* The last non-empty eh_frame section doesn't need padding. */ >>> if (i != NULL) >>> i = i->map_tail.s; >>> /* Any prior sections must pad the last FDE out to the output >>> section alignment. Otherwise we might have zero padding >>> between sections, which would be seen as a terminator. */ >>> for (; i != NULL; i = i->map_tail.s) >>> if (i->size == 4) >>> /* All but the last zero terminator should have been removed. */ >>> BFD_FAIL (); >>> else >>> { >>> bfd_size_type size >>> = (i->size + eh_alignment - 1) & -eh_alignment; >>> >>> If .eh_frame section alignment is larger than the section size, >>> we will get buffer overflow. >>> >>> if (i->size != size) >>> { >>> i->size = size; >>> changed = 1; >>> eh_changed = 1; >>> } >>> } >>> >>>> Also, please format unsigned long-s using %lu or (here) %lx. Especially >>>> when values get large, imo printing them as decimal is unhelpful. >>> >>> Will do. >>> >>>> Finally - why would .eh_frame be special in this regard? What about, >>>> say, .sframe? >>>> >>> >>> .sframe section doesn't do the code above. >> >> I understand that, but I hoped you would also understand that I'm merely >> trying to give examples. In all of your reply you didn't address my question >> "What if someone feels a need to align .eh_frame to, say, a page boundary?" >> If someone doing so resulted in a buffer overflow, that would indeed want >> fixing. But not by preventing them to use that kind of alignment. > > So far, we don't have any request for large .eh_frame section alignment. > My patch simply changes the linker crash to a linker error. If people > do need large .eh_frame section alignments in the future, we can work > with them to resolve their issues. That's not how I look at things, sorry. If Alan or Nick want to approve this patch, I'm not going to stand in the way, but I won't (and I object to you putting it in without approval, ftaod). Jan
Hi Guys, >>>>>> Return false on corrupt .eh_frame section. Cap the .eh_frame section >>>>>> alignment to the larger of the section size and the pointer size. >>>>> >>>>> Like for patch 2, I'm unconvinced of it being a good idea to build in >>>>> heuristics like this. What if someone feels a need to align .eh_frame >>>>> to, say, a page boundary? >> So far, we don't have any request for large .eh_frame section alignment. >> My patch simply changes the linker crash to a linker error. If people >> do need large .eh_frame section alignments in the future, we can work >> with them to resolve their issues. > > That's not how I look at things, sorry. If Alan or Nick want to approve this > patch, I'm not going to stand in the way, but I won't (and I object to you > putting it in without approval, ftaod). I am with Jan here. If we are going to implement a cap on the .eh_frame section size then we need to a) document it and b) inform the user if the cap is ever exceeded, oh and c) not break if it happens. Setting an arbitrary limit of max(pointer size, section size) makes sense from a practical point of view, but we must be ready to revisit this decision if it turns out that there are real world situations where a larger alignment (eg page boundary) is desired. So either the code must support any (power of two) alignment, or it must be friendly to the user and let them know if a limit is reached. Cheers Nick
From dc96baa76c046ed34b05926a6401c6ebd0d1eb03 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Tue, 23 Sep 2025 08:25:49 +0800 Subject: [PATCH 3/4] elf: Avoid linker crash on corrupt .eh_frame section Return false on corrupt .eh_frame section. Cap the .eh_frame section alignment to the larger of the section size and the pointer size. PR ld/33453 * elf-bfd.h (ABI_64_P): New. * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Return false on corrupt .eh_frame section. * elf.c (_bfd_elf_make_section_from_shdr): Limit .eh_frame section alignment. * elfxx-mips.c (ABI_64_P): Removed. * elfxx-sparc.c (ABI_64_P): Likewise. * elfxx-tilegx.c (ABI_64_P): Likewise. * elfxx-x86.h (ABI_64_P): Likewise. Signed-off-by: H.J. Lu <hjl.tools@gmail.com> --- bfd/elf-bfd.h | 3 +++ bfd/elf-eh-frame.c | 5 +++++ bfd/elf.c | 21 +++++++++++++++++++-- bfd/elfxx-mips.c | 4 ---- bfd/elfxx-sparc.c | 3 --- bfd/elfxx-tilegx.c | 3 --- bfd/elfxx-x86.h | 3 --- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 51e6ae7bb78..5a131d735ff 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1919,6 +1919,9 @@ struct bfd_elf_section_data #define get_elf_backend_data(abfd) \ xvec_get_elf_backend_data ((abfd)->xvec) +#define ABI_64_P(abfd) \ + (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) + /* The least object attributes (within an attributes subsection) known for any target. Some code assumes that the value 0 is not used and the field for that attribute can instead be used as a marker to diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 30bb313489c..93d412b38f0 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -2126,6 +2126,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, /* Skip length. */ cie = ent->u.fde.cie_inf; + if (cie == NULL) + { + _bfd_error_handler (_("corrupt .eh_frame section")); + return false; + } buf += 4; value = ((ent->new_offset + sec->output_offset + 4) - (cie->new_offset + cie->u.cie.u.sec->output_offset)); diff --git a/bfd/elf.c b/bfd/elf.c index 6ef60301091..07428cb91f9 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -981,10 +981,27 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, } } + bfd_size_type alignment = hdr->sh_addralign; + if (streq (name, ".eh_frame")) + { + bfd_size_type eh_alignment = ABI_64_P (abfd) ? 8 : 4; + if (hdr->sh_size > eh_alignment) + eh_alignment = 1 << bfd_log2 (hdr->sh_size); + if (alignment > eh_alignment) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: warning: ignore .eh_frame section alignment (%ld), limit it to %ld"), + abfd, (unsigned long) alignment, + (unsigned long) eh_alignment); + alignment = eh_alignment; + } + } + if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb) || !bfd_set_section_size (newsect, hdr->sh_size) - || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign - & -hdr->sh_addralign))) + || !bfd_set_section_alignment (newsect, bfd_log2 (alignment + & -alignment))) return false; /* As a GNU extension, if the name begins with .gnu.linkonce, we diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index bf3fd7df805..181f9f5e9fc 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -816,10 +816,6 @@ static bfd *reldyn_sorting_bfd; #define ABI_N32_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) -/* Nonzero if ABFD is using the N64 ABI. */ -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) - /* Nonzero if ABFD is using NewABI conventions. */ #define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd)) diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index bbaa7829132..1f3b9d831d8 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -37,9 +37,6 @@ /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) - /* The relocation "howto" table. */ /* Utility for performing the standard initial work of an instruction diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c index 79358e6b204..577d259a3b8 100644 --- a/bfd/elfxx-tilegx.c +++ b/bfd/elfxx-tilegx.c @@ -27,9 +27,6 @@ #include "libiberty.h" #include "elfxx-tilegx.h" -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) - #define TILEGX_ELF_WORD_BYTES(htab) \ ((htab)->bytes_per_word) diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 1ebc9d2f2e5..902592a3cf0 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -102,9 +102,6 @@ header. */ #define PLT_SFRAME_FDE_START_OFFSET sizeof (sframe_header) -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) - /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid copying dynamic variables from a shared lib into an app's dynbss section, and instead use a dynamic relocation to point into the -- 2.51.0