NetBSD Problem Report #57792

From www@netbsd.org  Sat Dec 23 16:36:30 2023
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 3E7D91A923C
	for <gnats-bugs@gnats.NetBSD.org>; Sat, 23 Dec 2023 16:36:30 +0000 (UTC)
Message-Id: <20231223163628.4669B1A9241@mollari.NetBSD.org>
Date: Sat, 23 Dec 2023 16:36:28 +0000 (UTC)
From: prlw1@cam.ac.uk
Reply-To: prlw1@cam.ac.uk
To: gnats-bugs@NetBSD.org
Subject: SIGSEGV in ld.elf_so / _rtld_call_ifunc
X-Send-Pr-Version: www-1.0

>Number:         57792
>Category:       lib
>Synopsis:       SIGSEGV in ld.elf_so / _rtld_call_ifunc
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    riastradh
>State:          analyzed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Dec 23 16:40:00 +0000 2023
>Closed-Date:    
>Last-Modified:  Fri Apr 18 20:55:01 +0000 2025
>Originator:     Patrick Welche
>Release:        NetBSD-10.99.10/amd64 / pkgsrc-current 2023-12-23
>Organization:
>Environment:
>Description:
Starting program: /tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/tmp-introspect31yl1w3c/Gdk-4.0 

Program received signal SIGSEGV, Segmentation fault.
_rtld_call_ifunc (obj=0x7f7ff7ee7400, mask=mask@entry=0x7f7fffffe4f0, 
    cur_objgen=cur_objgen@entry=1) at /usr/src/libexec/ld.elf_so/reloc.c:311
311                             *where = target;
(gdb) bt
#0  _rtld_call_ifunc (obj=0x7f7ff7ee7400, mask=mask@entry=0x7f7fffffe4f0, 
    cur_objgen=cur_objgen@entry=1) at /usr/src/libexec/ld.elf_so/reloc.c:311
#1  0x00007f7ff7ef3284 in _rtld_call_ifunc_functions (cur_objgen=1, 
    obj=<optimized out>, mask=0x7f7fffffe4f0)
    at /usr/src/libexec/ld.elf_so/rtld.c:280
#2  _rtld_call_init_functions (mask=mask@entry=0x7f7fffffe4f0)
    at /usr/src/libexec/ld.elf_so/rtld.c:304
#3  0x00007f7ff7ef3de5 in _rtld (sp=<optimized out>, relocbase=<optimized out>)
    at /usr/src/libexec/ld.elf_so/rtld.c:795
#4  0x00007f7ff7eed033 in rtld_start () from /usr/libexec/ld.elf_so
#5  0x0000000000000000 in ?? ()
(gdb) list
306                     _rtld_exclusive_enter(mask);
307     #ifdef __sparc__
308                     sparc_write_branch(where2 + 1, (void *)target);
309     #else
310                     if (*where != target)
311                             *where = target;
312     #endif
313             }
314
315             while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
(gdb) print target
$1 = 140187593839377 = 0x7F7FF7BB9311
(gdb) print where
$2 = (Elf64_Addr *) 0x7f7ff7ed64c8 <*ABS*@got.plt>
(gdb) print *where
$3 = 140187589897974 = 0x7F7FF77F6EF6
(gdb) x 0x7F7FF7BB9311
0x7f7ff7bb9311 <float_to_half_f16c>:    0x8e0fd285
(gdb) x 0x7f7ff7ed64c8
0x7f7ff7ed64c8 <*ABS*@got.plt>: 0xf77f6ef6
(gdb) x 0x7F7FF77F6EF6
0x7f7ff77f6ef6 <*ABS*+0x46f2a0@plt+6>:  0x00088268
(gdb) frame 2
#2  _rtld_call_init_functions (mask=mask@entry=0x7f7fffffe4f0) at /usr/src/libexec/ld.elf_so/rtld.c:304
304                     if (_rtld_call_ifunc_functions(mask, elm->obj, cur_objgen)) {
(gdb) list
299             SIMPLEQ_INIT(&initlist);
300             _rtld_initlist_tsort(&initlist, 0);
301
302             /* First pass: objects with IRELATIVE relocations. */
303             SIMPLEQ_FOREACH(elm, &initlist, link) {
304                     if (_rtld_call_ifunc_functions(mask, elm->obj, cur_objgen)) {
305                             dbg(("restarting init iteration"));
306                             _rtld_objlist_clear(&initlist);
307                             goto restart;
308                     }
(gdb) print *elm->obj
$11 = {next = 0x7f7ff7ee7800, 
  path = 0x7f7ff7ee8080 "/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/gtk/libgtk-4.so.1", refcount = 1, 
  dl_refcount = 0, mapbase = 0x7f7ff774a000 "\177ELF\002\001\001\003", mapsize = 7966720, textsize = 675840, 
  vaddrbase = 0, relocbase = 0x7f7ff774a000 "\177ELF\002\001\001\003", dynamic = 0x7f7ff7ed2168, entry = 0x0, 
  phdr = 0x7f7ff774a040, phsize = 504, pltgot = 0x7f7ff7ed2548, rel = 0x0, rellim = 0x0, rela = 0x7f7ff77b4b38, 
  relalim = 0x7f7ff77e1ec8, pltrel = 0x0, pltrellim = 0x0, pltrela = 0x7f7ff77e1ec8, pltrelalim = 0x7f7ff77eeb40, 
  symtab = 0x7f7ff7755568, strtab = 0x7f7ff77807f8 "", strsize = 198980, buckets = 0x7f7ff774a240, unused1 = 0, 
  chains = 0x7f7ff774e24c, nchains = 7366, rpaths = 0x7f7ff7ee59c0, needed = 0x7f7ff7ee55c0, 
  init = 0x7f7ff77ef000 <_init>, fini = 0x7f7ff7bba460 <_fini>, mainprog = 0, rtld = 0, textrel = 0, 
  symbolic = 1, printed = 0, isdynamic = 1, mainref = 1, globalref = 0, init_done = 1, init_called = 0, 
  fini_called = 0, z_now = 1, z_nodelete = 0, z_initfirst = 0, z_noopen = 0, phdr_loaded = 1, tls_static = 1, 
  tls_dynamic = 0, ref_nodel = 0, sysv_hash = 1, gnu_hash = 0, linkmap = {
    l_addr = 0x7f7ff774a000 "\177ELF\002\001\001\003", 
    l_name = 0x7f7ff7ee8080 "/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/gtk/libgtk-4.so.1", 
    l_ld = 0x7f7ff7ed2168, l_next = 0x7f7ff7ee7908, l_prev = 0x7f7ff7ee7108}, interp = 0x0, dldags = {
    sqh_first = 0x0, sqh_last = 0x7f7ff7ee7538}, dagmembers = {sqh_first = 0x0, sqh_last = 0x7f7ff7ee7548}, 
  dev = 43778, ino = 82350959332080029, ehdr = 0x7f7ff7ee3000, nbuckets = 4099, nbuckets_m = 4288680445, 
  nbuckets_s1 = 1 '\001', nbuckets_s2 = 12 '\f', buckets_gnu = 0x0, nbuckets_gnu = 0, nbuckets_m_gnu = 0, 
  nbuckets_s1_gnu = 0 '\000', nbuckets_s2_gnu = 0 '\000', chains_gnu = 0x0, bloom_gnu = 0x0, symndx_gnu = 0, 
  mask_bm_gnu = 0, shift2_gnu = 0, pathlen = 68, names = {sqh_first = 0x7f7ff7ee6040, sqh_last = 0x7f7ff7ee6040}, 
  tlsindex = 0, tlsinit = 0x0, tlsinitsize = 0, tlssize = 0, tlsoffset = 0, tlsalign = 0, 
  relro_page = 0x7f7ff7eb8840, relro_size = 124864, verneed = 0x7f7ff77b4ac8, verneednum = 3, verdef = 0x0, 
  verdefnum = 0, versyms = 0x7f7ff77b113c, vertab = 0x7f7ff63f3000, vertabnum = 6, init_array = 0x7f7ff7eb8840, 
  init_arraysz = 3, fini_array = 0x0, fini_arraysz = 0, ifunc_remaining = 2, ifunc_remaining_nonplt = 0, 
  cxa_refcount = 0}

>How-To-Repeat:
On NetBSD-current/amd64, HAVE_GCC=12 (probably not necessary), with pkgsrc-current, set 'export GI_SCANNER_DEBUG="save-temps"' and try to build x11/gtk4. The environment variable will stop unlinking the evidence.

It will fail with
Command '['/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/tmp-introspect31yl1w3c/Gdk-4.0', '--introspect-dump=/tmp/pkgsrc/
x11/gtk4/work.x86_64/gtk-4.12.4/output/tmp-introspect31yl1w3c/functions.txt,/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output
/tmp-introspect31yl1w3c/dump.xml']' died with <Signals.SIGSEGV: 11>.

# file Gdk-4.0
Gdk-4.0: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /usr/libexec/ld.elf_so, for
NetBSD 10.99.10, with debug_info, not stripped
# file ../gtk/libgtk-4.so.1.1200.4
libgtk-4.so.1.1200.4: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, for NetBSD 10.99.10, with debug_info, not stripped

# env LD_LIBRARY_PATH=/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/gtk ./Gdk-4.0
[1]   Segmentation fault (core dumped) env LD_LIBRARY_PATH=/tmp/pkgsrc/x11/gtk4/work.x86_64/gtk-4.12.4/output/gtk ./Gdk-4.0

Gdk-4.0 is built by the gnome module of mesonbuild. Apparently simply running kills ld.so_elf as it tries to load the freshly built libgtk?!
>Fix:

>Release-Note:

>Audit-Trail:
From: Patrick Welche <prlw1@talktalk.net>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc
Date: Sun, 24 Dec 2023 17:17:59 -0600

 Just repeated the experiment with LD_DEBUG:
 sp = 0x7f7fffffe6c0, argc = 1, argv = 0x7f7fffffe6d8 <./Gdk-4.0> relocbase 0x7f7ff7ee8000
 ...
 headers: digesting PT_DYNAMIC at 0x7f7ff7efdba0
   d_tag 16 at 0x7f7ff7efdba0
   d_tag 4 at 0x7f7ff7efdbb0
   d_tag 5 at 0x7f7ff7efdbc0
   d_tag 6 at 0x7f7ff7efdbd0
   d_tag 10 at 0x7f7ff7efdbe0
   d_tag 11 at 0x7f7ff7efdbf0
   d_tag 7 at 0x7f7ff7efdc00
   d_tag 8 at 0x7f7ff7efdc10
   d_tag 9 at 0x7f7ff7efdc20
   d_tag 1879048185 at 0x7f7ff7efdc30
  added path "/usr/lib"

 Does that last d_tag look strangely large?

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc
Date: Tue, 26 Dec 2023 23:51:11 +0000 (UTC)

 On Mon, 25 Dec 2023, Patrick Welche wrote:

 > Just repeated the experiment with LD_DEBUG:
 > sp = 0x7f7fffffe6c0, argc = 1, argv = 0x7f7fffffe6d8 <./Gdk-4.0> relocbase 0x7f7ff7ee8000
 > ...
 > headers: digesting PT_DYNAMIC at 0x7f7ff7efdba0
 >   d_tag 16 at 0x7f7ff7efdba0
 >   d_tag 4 at 0x7f7ff7efdbb0
 >   d_tag 5 at 0x7f7ff7efdbc0
 >   d_tag 6 at 0x7f7ff7efdbd0
 >   d_tag 10 at 0x7f7ff7efdbe0
 >   d_tag 11 at 0x7f7ff7efdbf0
 >   d_tag 7 at 0x7f7ff7efdc00
 >   d_tag 8 at 0x7f7ff7efdc10
 >   d_tag 9 at 0x7f7ff7efdc20
 >   d_tag 1879048185 at 0x7f7ff7efdc30
 >  added path "/usr/lib"
 >
 > Does that last d_tag look strangely large?
 >

 That's `DT_RELACOUNT':

 ```
 $ fgrep DT_RELACOUNT /usr/src/external/bsd/elftoolchain/
 /usr/src/external/bsd/elftoolchain/dist/common/sys/elfconstants.m4:_(`DT_RELACOUNT',        0x6FFFFFF9UL,
 $
 ```

 I think what's happening here is the dynamic linker _not_ doing a
 mprotect(PROT_WRITE) before it goes to patch the ifunc addresses
 in an _executable_ (shared libs seem fine) built with RELRO+NOW:

 ```
 $ cat i.c
 #include <stdio.h>

 #define MAGIC 0xdeadbeefLL

 static long long ifunc_helper(void) {
          return MAGIC;
 }

 static void* resolve_ifunc(void) {
          return ifunc_helper;
 }

 static long long ifunc(void) __attribute__((ifunc ("resolve_ifunc")));

 int main(void) {
          printf("calling ifunc\n");
          fflush(stdout);
          return ifunc() != MAGIC;
 }

 $ gcc -Wall -Wextra -Wconversion -o i i.c -Wl,-z,now
 $ ./i || echo FAIL
 calling ifunc		# only -z now works

 $ gcc -Wall -Wextra -Wconversion -o i i.c -Wl,-z,relro
 $ ./i || echo FAIL
 calling ifunc		# only -z relro also works

 $ gcc -Wall -Wextra -Wconversion -o i i.c -Wl,-z,now,-z,relro
 $ ./i || echo FAIL
 Segmentation fault (core dumped)
 FAIL			# -z relro + -z now fails!

 $
 ```

 Unfortunately, src/tests/libexec/ld.elf_so/t_ifunc.c doesn't test
 with RELRO + NOW, otherwise this would've been caught long ago.

 Try compiling the package without `-z now'.

 -RVP

From: "Patrick Welche" <prlw1@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57792 CVS commit: pkgsrc/x11/gtk4
Date: Tue, 16 Jan 2024 10:00:16 +0000

 Module Name:	pkgsrc
 Committed By:	prlw1
 Date:		Tue Jan 16 10:00:16 UTC 2024

 Modified Files:
 	pkgsrc/x11/gtk4: Makefile distinfo
 Added Files:
 	pkgsrc/x11/gtk4/patches: patch-meson.build

 Log Message:
 gtk4: build workaround for NetBSD with gcc 12

 NetBSD ld.elf_so dumps core with a shlib built with gcc 12 and
 both -z,relro and -z,now. c.f., PR lib/57792

 gtk4 adds both of these flags by default, and fails on either a
 system with a base HAVE_GCC=12, or with GCC_REQD=12.

 With the patch, it can be caused to fail again by setting
 PKGSRC_USE_RELRO=full

 Thank you to RVP for the analysis


 To generate a diff of this commit:
 cvs rdiff -u -r1.39 -r1.40 pkgsrc/x11/gtk4/Makefile
 cvs rdiff -u -r1.17 -r1.18 pkgsrc/x11/gtk4/distinfo
 cvs rdiff -u -r0 -r1.5 pkgsrc/x11/gtk4/patches/patch-meson.build

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57792 CVS commit: src
Date: Sun, 7 Jul 2024 17:37:33 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Sun Jul  7 17:37:33 UTC 2024

 Modified Files:
 	src/distrib/sets/lists/debug: mi
 	src/distrib/sets/lists/tests: mi
 	src/tests/libexec/ld.elf_so: Makefile

 Log Message:
 t_ifunc: Test with all combinations of {relro, bindnow}.

 PR lib/57792


 To generate a diff of this commit:
 cvs rdiff -u -r1.436 -r1.437 src/distrib/sets/lists/debug/mi
 cvs rdiff -u -r1.1325 -r1.1326 src/distrib/sets/lists/tests/mi
 cvs rdiff -u -r1.21 -r1.22 src/tests/libexec/ld.elf_so/Makefile

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Taylor R Campbell <riastradh@NetBSD.org>
To: Patrick Welche <prlw1@cam.ac.uk>, RVP <rvp@SDF.ORG>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org, joerg@NetBSD.org,
	skrll@NetBSD.org, mrg@NetBSD.org
Subject: Re: lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc
Date: Mon, 15 Jul 2024 16:08:56 +0000

 The following test cases now exhibit the difference:

 /usr/tests/libexec/ld.elf_so/t_ifunc (relro, bind lazily)
 /usr/tests/libexec/ld.elf_so/t_ifunc_now (relro, bind now)

 t_ifunc works; t_ifunc_now crashes.

 Setting a breakpoint on

 https://nxr.netbsd.org/xref/src/libexec/ld.elf_so/reloc.c?r=3D1.118#311

 where t_ifunc_now crashes reveals:

 [t_ifunc]     where =3D  0x55c03018 <*ABS*@got.plt>
 [t_ifunc_now] where =3D 0x1b5e02f10 <*ABS*@got.plt>

 The high-order parts of the addresses -- 0x55c0...., 0x1b5e0.... --
 are ASLR red herrings; it's the low-order parts that are relevant.

 Examining /proc/<pid>/maps reveals:

 0000000055c02000-0000000055c03000 r--p 0000000000002000 2bd:13ede 679572   =
                           /home/riastradh/netbsd/10/obj.amd64/destdir.amd64=
 /usr/tests/libexec/ld.elf_so/t_ifunc
 0000000055c03000-0000000055c04000 rw-p 0000000000000000 00:00 0

 00000001b5e02000-00000001b5e03000 r--p 0000000000002000 2bd:13ede 679575   =
                           /home/riastradh/netbsd/10/obj.amd64/destdir.amd64=
 /usr/tests/libexec/ld.elf_so/t_ifunc_now
 00000001b5e03000-00000001b5e04000 rw-p 0000000000000000 00:00 0

 In both cases, relative to the base address (0x55c00000, 0x1b5e00000),
 page 0x2000 is mapped read-only and page 0x3000 is mapped read/write.

 - In the working case (t_ifunc), the ifunc relocation is in the
   read/write page at 0x3018.

 - In the broken case (t_ifunc_now), the ifunc relocation is in the
   read-only page at 0x2f10.

 readelf shows the following headers and segments:

 $ readelf -a t_ifunc
 ...
  0x0000000000000003 (PLTGOT)             0x3fe8
 ...
 Program Headers:
   Type           Offset             VirtAddr           PhysAddr
                  FileSiz            MemSiz              Flags  Align
   PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                  0x0000000000000230 0x0000000000000230  R      0x8
   INTERP         0x0000000000000270 0x0000000000000270 0x0000000000000270
                  0x0000000000000017 0x0000000000000017  R      0x1
       [Requesting program interpreter: /usr/libexec/ld.elf_so]
   LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                  0x0000000000000c90 0x0000000000000c90  R      0x1000
   LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                  0x0000000000000c6e 0x0000000000000c6e  R E    0x1000
   LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                  0x000000000000052c 0x000000000000052c  R      0x1000
   LOAD           0x0000000000002d38 0x0000000000003d38 0x0000000000003d38
                  0x00000000000003e2 0x0000000000000450  RW     0x1000
 ...
    04     .rodata .eh_frame_hdr .eh_frame=20
    05     .ctors .dtors .jcr .data.rel.ro .dynamic .got .got.plt .data .bss=
 =20
 ...

 $ readelf -a t_ifunc_now
 ...
  0x0000000000000003 (PLTGOT)             0x3ef8
 ...
 Program Headers:
   Type           Offset             VirtAddr           PhysAddr
                  FileSiz            MemSiz              Flags  Align
   PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                  0x0000000000000230 0x0000000000000230  R      0x8
   INTERP         0x0000000000000270 0x0000000000000270 0x0000000000000270
                  0x0000000000000017 0x0000000000000017  R      0x1
       [Requesting program interpreter: /usr/libexec/ld.elf_so]
   LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                  0x0000000000000c90 0x0000000000000c90  R      0x1000
   LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                  0x0000000000000c6e 0x0000000000000c6e  R E    0x1000
   LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                  0x000000000000052c 0x000000000000052c  R      0x1000
   LOAD           0x0000000000002c78 0x0000000000003c78 0x0000000000003c78
                  0x00000000000003da 0x0000000000000450  RW     0x1000
 ...
    04     .rodata .eh_frame_hdr .eh_frame=20
    05     .ctors .dtors .jcr .data.rel.ro .dynamic .got .data .bss=20
 ...

 Someone who has more details of linkers and gots and plts may be able
 to pursue this thread more efficiently than I can at this point.

Responsible-Changed-From-To: lib-bug-people->riastradh
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Fri, 18 Apr 2025 02:04:37 +0000
Responsible-Changed-Why:
mine


State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Fri, 18 Apr 2025 02:04:37 +0000
State-Changed-Why:
patch posted


From: Taylor R Campbell <riastradh@NetBSD.org>
To: prlw1@cam.ac.uk
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc
Date: Fri, 18 Apr 2025 02:00:25 +0000

 This is a multi-part message in MIME format.
 --=_rhGMeJlKcnVU63TmxERqST609Awrm+9s

 The attached patch should resolve the underlying issue -- both fixing
 the t_ifunc_now test, and fixing the gtk4 issue.  Details in the
 commit message.

 --=_rhGMeJlKcnVU63TmxERqST609Awrm+9s
 Content-Type: text/plain; charset="ISO-8859-1"; name="pr57792-ldelfsodefereagerrelro"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment; filename="pr57792-ldelfsodefereagerrelro.patch"

 # HG changeset patch
 # User Taylor R Campbell <riastradh@NetBSD.org>
 # Date 1744941415 0
 #      Fri Apr 18 01:56:55 2025 +0000
 # Branch trunk
 # Node ID f0c0c2d90c130d5e6e06ac9f5a230a3902d23412
 # Parent  438b14ea036dd2bd2e1109f5e08f7d74109e6fae
 # EXP-Topic riastradh-pr57792-relrorounding
 ld.elf_so(1): Defer RELRO a bit for eagerly-bound (-z now) programs.

 GNU binutils links programs a little differently if they're eagerly
 bound with -Wl,-z,now.  In particular, the part of the .got relocated
 for ifuncs is covered by the RELRO region in eagerly-bound programs
 (-z now), but not in lazily-bound programs (default).

 Presumably this is done under the premise that eagerly-bound programs
 will resolve all ifuncs at startup _before_ mprotecting the main
 object's RELRO region.  But ld.elf_so was mprotecting it first, in
 _rtld_do_copy_relocations, and then resolving ifuncs -- at which the
 memory locations where it tries to write the resolutions will be
 mapped read-only.

 (In contrast, for lazily bound programs, ifuncs may also be resolved
 lazily, so the locations they relocate are _not_ covered by the RELRO
 region and we don't run into any trouble)

 To avoid this trouble, for eagerly-bound programs, we defer the RELRO
 mprotect of the main object by a little bit -- we move it from
 _rtld_do_copy_relocations to just after _rtld_call_init_functions.

 PR lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc

 diff -r 438b14ea036d -r f0c0c2d90c13 libexec/ld.elf_so/reloc.c
 --- a/libexec/ld.elf_so/reloc.c	Thu Apr 17 13:43:59 2025 +0000
 +++ b/libexec/ld.elf_so/reloc.c	Fri Apr 18 01:56:55 2025 +0000
 @@ -154,7 +154,22 @@ int
  		}
  	}
  #ifdef GNU_RELRO
 -	if (_rtld_relro(dstobj, true) =3D=3D -1)
 +	/*
 +	 * If the main program is lazily bound (default -- whether or
 +	 * not LD_BINDNOW is set in the calling environment), we are
 +	 * now done writing to anything covered by RELRO and we can
 +	 * safely make it read-only.  There may still be ifunc
 +	 * resolution to do later; it will happen in a read/write
 +	 * segment and will not be made read-only.
 +	 *
 +	 * But if the main program is eagerly bound (i.e., the object
 +	 * has DF_1_NOW set in DT_FLAGS_1, whether or not LD_BIND_NOW
 +	 * is set in the calling environment), we delay protecting the
 +	 * RELRO region as read-only until we have resolved ifuncs --
 +	 * at which point we will make the ifunc resolution read-only
 +	 * too.
 +	 */
 +	if (!dstobj->z_now && _rtld_relro(dstobj, true) =3D=3D -1)
  		return -1;
  #endif
  #endif /* RTLD_INHIBIT_COPY_RELOCS */
 diff -r 438b14ea036d -r f0c0c2d90c13 libexec/ld.elf_so/rtld.c
 --- a/libexec/ld.elf_so/rtld.c	Thu Apr 17 13:43:59 2025 +0000
 +++ b/libexec/ld.elf_so/rtld.c	Fri Apr 18 01:56:55 2025 +0000
 @@ -806,6 +806,27 @@ Elf_Addr
 =20
  	_rtld_exclusive_exit(&mask);
 =20
 +#ifdef GNU_RELRO
 +	/*
 +	 * If the main program is lazily bound (default -- whether or
 +	 * not LD_BINDNOW is set in the calling environment), its RELRO
 +	 * region has already been mapped read-only in
 +	 * _rtld_do_copy_relocations.  The ifunc resolutions lie
 +	 * outside this region, so future lazy ifunc resolution is
 +	 * unaffected by the RELRO region's being read-only.
 +	 *
 +	 * If the main program is eagerly bound (i.e., the object has
 +	 * DF_1_NOW set in DT_FLAGS_1, whether or not LD_BIND_NOW is
 +	 * set in the calling environment), we deferred that from
 +	 * _rtld_do_copy_relocations so that the ifunc resolution, we
 +	 * have now resolved all ifuncs in it, so we can commit the
 +	 * RELRO region to be read-only -- and that means ifunc
 +	 * resolutions are read-only too.
 +	 */
 +	if (_rtld_objmain->z_now && _rtld_relro(_rtld_objmain, true) =3D=3D -1)
 +		return -1;
 +#endif
 +
  	/*
  	 * Return with the entry point and the exit procedure in at the top
  	 * of stack.

 --=_rhGMeJlKcnVU63TmxERqST609Awrm+9s--

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57792 CVS commit: src/libexec/ld.elf_so
Date: Fri, 18 Apr 2025 02:16:16 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Fri Apr 18 02:16:16 UTC 2025

 Modified Files:
 	src/libexec/ld.elf_so: reloc.c rtld.c

 Log Message:
 ld.elf_so(1): Defer RELRO a bit for eagerly-bound (-z now) programs.

 GNU binutils links programs a little differently if they're eagerly
 bound with -Wl,-z,now.  In particular, the part of the .got relocated
 for ifuncs is covered by the RELRO region in eagerly-bound programs
 (-z now), but not in lazily-bound programs (default).

 Presumably this is done under the premise that eagerly-bound programs
 will resolve all ifuncs at startup _before_ mprotecting the main
 object's RELRO region.  But ld.elf_so was mprotecting it first, in
 _rtld_do_copy_relocations, and then resolving ifuncs -- at which the
 memory locations where it tries to write the resolutions will be
 mapped read-only.

 (In contrast, for lazily bound programs, ifuncs may also be resolved
 lazily, so the locations they relocate are _not_ covered by the RELRO
 region and we don't run into any trouble)

 To avoid this trouble, for eagerly-bound programs, we defer the RELRO
 mprotect of the main object by a little bit -- we move it from
 _rtld_do_copy_relocations to just after _rtld_call_init_functions.

 PR lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc


 To generate a diff of this commit:
 cvs rdiff -u -r1.118 -r1.119 src/libexec/ld.elf_so/reloc.c
 cvs rdiff -u -r1.218 -r1.219 src/libexec/ld.elf_so/rtld.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57792 CVS commit: src/libexec/ld.elf_so
Date: Fri, 18 Apr 2025 20:51:31 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Fri Apr 18 20:51:31 UTC 2025

 Modified Files:
 	src/libexec/ld.elf_so: rtld.c

 Log Message:
 ld.elf_so: Call _rtld_die if relro fails; don't return -1.

 Returning -1 was a pasto from where the original _rtld_relro call
 came from, in _rtld_do_copy_relocations.

 PR lib/57792: SIGSEGV in ld.elf_so / _rtld_call_ifunc


 To generate a diff of this commit:
 cvs rdiff -u -r1.219 -r1.220 src/libexec/ld.elf_so/rtld.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.