From patchwork Sun Aug 2 04:07:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xi Ruoyao X-Patchwork-Id: 140406 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8FDC54BAE7C0 for ; Sun, 2 Aug 2026 04:08:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8FDC54BAE7C0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1785643733; bh=RzsfCNI+9vLZWTRj298icQEaHuZn5kDrGy2QTWYCmSI=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=o0yO4WkAORs+ce2SZR9WLusTi0VR/sOmA7GMhHLe/VJ3/x5WJWEOrcZuXzwoD7qYP U2dEOsAyuuFrxu4C9unShT+GoU2kathBb+7SLrv2PxIYy7owhuOgJ3eODlspfB34jM FWtKY3YA+vjm2S/UCmIERsSVy4y7H2MRYke/HCsw= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from xry111.site (xry111.site [89.208.246.23]) by sourceware.org (Postfix) with ESMTPS id 1E50F4BA9006 for ; Sun, 2 Aug 2026 04:08:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E50F4BA9006 ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1E50F4BA9006 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785643700; cv=none; b=F7GrTILMvAhiJA7X8UbU2JT9U52nb/eQ8wNBNik6l05wV8QMaRAimuqqxKxOG7VPBWRn7b+bisM6aLIVzLQ3yFtpSaB4lBUKQt07oMF2Vb7R0VPVxwWLGb1VIqecOY0eIbLrIlyaXZY7KbT4W11n+CVDPE/hkGhJCrNP9kj1BGI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785643700; c=relaxed/simple; bh=8YtkX2LEhmrS6oakKnfYCrGaL5DoA3uIXF/8904N5P4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=xYGYbrlRU9dMNVEQBlb8bq87TPU6iacXfnsGrxTloC0+fdq3SIADLq8LRRjh61ZEjmYT4V48DiyFwfWIPbFCPUG+Kxrtd/JUOhDWwt/EXzs4WhXpEmNzHHjLa2TlMETta8f9TT3kgGCydEIBf806ZtlWYHt3v/7bGSbtXZisrq0= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=xry111.site header.i=@xry111.site header.a=rsa-sha256 header.s=default header.b=Ft+IAMLp DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1E50F4BA9006 Received: from stargazer (unknown [IPv6:2408:824e:303:4921:c427:8c70:2426:b]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (Client did not present a certificate) (Authenticated sender: xry111@xry111.site) by xry111.site (Postfix) with ESMTPSA id 96CE865983; Sun, 2 Aug 2026 00:07:38 -0400 (EDT) To: binutils@sourceware.org Cc: Meng Qinggang , Nick Clifton , Mingcong Bai , Zixing Liu , WANG Xuerui , Yanjun Yang , Xi Ruoyao Subject: [PATCH] LoongArch: fix .got.plt dislocation in static PDE Date: Sun, 2 Aug 2026 12:07:18 +0800 Message-ID: <20260802040719.1136959-1-xry111@xry111.site> X-Mailer: git-send-email 2.55.0 MIME-Version: 1.0 X-Spam-Status: No, score=-9.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, LIKELY_SPAM_FROM, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Xi Ruoyao via Binutils From: Xi Ruoyao Reply-To: Xi Ruoyao Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org The code path handling R_LARCH_GOT{64*,{,_PC}_LO12} miscalculated the address of the .got.plt entry: it always counted the two .got.plt entries reserved for ld.so, but in static PDE those two entries do not exist (as in static PDE the PLT is solely for ifunc). Thus all .got.plt entries dislocated for two slots. Those affected relocations are practically always used together with the R_LARCH_GOT_{PC_,}HI20 relocation. In 2.46 and earlier releases, R_LARCH_GOT_{PC_,}HI20 set pointer_equality_needed, which caused the R_LARCH_GOT_* relocs resolved to a .got entry (targeting the PLT stub) instead of .got.plt in static PDE, thus the error was latent. But in the 2.47 release R_LARCH_GOT_{PC_,}HI20 no longer sets pointer_equality_needed so the error became exploitable. Fix the issue by factoring out the correct .got.plt entry addressing logic handling R_LARCH_GOT_{PC_,}HI20 into a subroutine and replace the incorrect logic for R_LARCH_GOT{64*,{,_PC}_LO12} with a call to the subroutine. Signed-off-by: Xi Ruoyao --- bfd/elfnn-loongarch.c | 46 ++++++------------- ld/testsuite/ld-loongarch-elf/ifunc.exp | 8 ++++ ld/testsuite/ld-loongarch-elf/static-ifunc.c | 27 +++++++++++ .../ld-loongarch-elf/static-ifunc.out | 1 + 4 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 ld/testsuite/ld-loongarch-elf/static-ifunc.c create mode 100644 ld/testsuite/ld-loongarch-elf/static-ifunc.out diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 4bdc3f26285..658c5b93e08 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -3513,6 +3513,19 @@ loongarch_resolve_pcrel_lo_relocs (loongarch_pcrel_relocs *p) return true; } +static bfd_vma +ifunc_got_off (struct elf_link_hash_table *htab, + struct elf_link_hash_entry *h) +{ + bfd_vma idx = + (h->plt.offset - (htab->splt ? PLT_HEADER_SIZE : 0)) / PLT_ENTRY_SIZE; + + return sec_addr (htab->sgotplt) + + (htab->splt ? GOTPLT_HEADER_SIZE : 0) + + (idx * GOT_ENTRY_SIZE) + - sec_addr (htab->sgot); +} + static int loongarch_elf_relocate_section (struct bfd_link_info *info, bfd *input_bfd, asection *input_section, @@ -4539,25 +4552,7 @@ loongarch_elf_relocate_section (struct bfd_link_info *info, /* Hidden symbol not has got entry, * only got.plt entry so it is (plt - got). */ if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) - { - bfd_vma idx; - if (htab->elf.splt != NULL) - { - idx = (h->plt.offset - PLT_HEADER_SIZE) - / PLT_ENTRY_SIZE; - got_off = sec_addr (htab->elf.sgotplt) - + GOTPLT_HEADER_SIZE - + (idx * GOT_ENTRY_SIZE) - - sec_addr (htab->elf.sgot); - } - else - { - idx = h->plt.offset / PLT_ENTRY_SIZE; - got_off = sec_addr (htab->elf.sgotplt) - + (idx * GOT_ENTRY_SIZE) - - sec_addr (htab->elf.sgot); - } - } + got_off = ifunc_got_off (&htab->elf, h); if ((h->got.offset & 1) == 0) { @@ -4638,18 +4633,7 @@ loongarch_elf_relocate_section (struct bfd_link_info *info, got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1); if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) - { - bfd_vma idx; - if (htab->elf.splt != NULL) - idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; - else - idx = h->plt.offset / PLT_ENTRY_SIZE; - - got_off = sec_addr (htab->elf.sgotplt) - + GOTPLT_HEADER_SIZE - + (idx * GOT_ENTRY_SIZE) - - sec_addr (htab->elf.sgot); - } + got_off = ifunc_got_off (&htab->elf, h); relocation = got_off + sec_addr (got); } diff --git a/ld/testsuite/ld-loongarch-elf/ifunc.exp b/ld/testsuite/ld-loongarch-elf/ifunc.exp index da33eeb8061..f6c97ae2019 100644 --- a/ld/testsuite/ld-loongarch-elf/ifunc.exp +++ b/ld/testsuite/ld-loongarch-elf/ifunc.exp @@ -30,5 +30,13 @@ if [istarget loongarch*-*-*] { "attr-ifunc-4" \ "attr-ifunc-4.out" \ ] \ + [list \ + "Run static-ifunc" \ + "-static" \ + "" \ + {static-ifunc.c} \ + "static-ifunc" \ + "static-ifunc.out" \ + ] \ ] } diff --git a/ld/testsuite/ld-loongarch-elf/static-ifunc.c b/ld/testsuite/ld-loongarch-elf/static-ifunc.c new file mode 100644 index 00000000000..c0b1788df7c --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/static-ifunc.c @@ -0,0 +1,27 @@ +int +f1 () +{ + return 42; +} +int +f2 () +{ + return 47; +} + +void * +fx () +{ + return f1; +} + +[[gnu::ifunc ("fx")]] int f (); + +int +main () +{ + int (*p) () = f; + asm ("# prevent optimization" : "+r"(p)); + __builtin_printf ("%d\n", p ()); + return 0; +} diff --git a/ld/testsuite/ld-loongarch-elf/static-ifunc.out b/ld/testsuite/ld-loongarch-elf/static-ifunc.out new file mode 100644 index 00000000000..d81cc0710eb --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/static-ifunc.out @@ -0,0 +1 @@ +42