NetBSD Problem Report #59387

From www@netbsd.org  Fri May  2 22:47:21 2025
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)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
	 client-signature RSA-PSS (2048 bits) client-digest SHA256)
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 8F4231A9239
	for <gnats-bugs@gnats.NetBSD.org>; Fri,  2 May 2025 22:47:21 +0000 (UTC)
Message-Id: <20250502224719.BEF021A923C@mollari.NetBSD.org>
Date: Fri,  2 May 2025 22:47:19 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: ld.elf_so: needlessly includes libc/gen/sysctl.c user.* data
X-Send-Pr-Version: www-1.0

>Number:         59387
>Category:       lib
>Synopsis:       ld.elf_so: needlessly includes libc/gen/sysctl.c user.* data
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          needs-pullups
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 02 22:50:00 +0000 2025
>Closed-Date:    
>Last-Modified:  Sat May 03 01:08:14 +0000 2025
>Originator:     Taylor R Campbell
>Release:        current
>Organization:
The RtldBloaatD Foundation
>Environment:
>Description:
ld.elf_so calls the libc sysctl() function to query sysctl kern.ostype, kern.osrelease, and hw.machine_arch for expanding $OSNAME, $OSREL, and $PLATFORM in, e.g., DT_RPATH entries:

     91 	case 3:	/* OSNAME */
     92 	case 4:	/* OSREL */
     93 	case 5:	/* PLATFORM */
     94 		len = sizeof(name);
 =>  95 		if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) {
     96 			xwarn("sysctl");
     97 			return 0;
     98 		}
     99 		ep = (p = name) + len - 1;
    100 		break;

https://nxr.netbsd.org/xref/src/libexec/ld.elf_so/expand.c?r=1.7#91

The libc sysctl() function is not just the syscall stub, though -- it is a wrapper that implements the user.* sysctl nodes:

     72 int
     73 sysctl(const int *name, unsigned int namelen,
     74 	void *oldp, size_t *oldlenp,
     75 	const void *newp, size_t newlen)
     76 {
     77 	size_t oldlen, savelen;
     78 	int error;
     79 
     80 	if (name[0] != CTL_USER)
     81 		return (__sysctl(name, namelen, oldp, oldlenp,
     82 				 newp, newlen));
     83 
     84 	oldlen = (oldlenp == NULL) ? 0 : *oldlenp;
     85 	savelen = oldlen;
     86 	error = user_sysctl(name + 1, namelen - 1, oldp, &oldlen, newp, newlen);
...
    104 static int
    105 user_sysctl(const int *name, unsigned int namelen,
    106 	void *oldp, size_t *oldlenp,
    107 	const void *newp, size_t newlen)
    108 {
    109 #define _INT(s, n, v, d) {					\
    110 	.sysctl_flags = CTLFLAG_IMMEDIATE|CTLFLAG_PERMANENT|	\
    111 			CTLTYPE_INT|SYSCTL_VERSION,		\
    112 	.sysctl_size = sizeof(int),				\
    113 	.sysctl_name = (s),					\
    114 	.sysctl_num = (n),					\
    115 	.sysctl_un.scu_idata = (v),				\
    116 	.sysctl_desc = (d),					\
    117 	}
    118 
    119 	/*
    120 	 * the nodes under the "user" node
    121 	 */
    122 	static const struct sysctlnode sysctl_usermib[] = {
    123 		{
    124 			.sysctl_flags = SYSCTL_VERSION|CTLFLAG_PERMANENT|
    125 				CTLTYPE_STRING,
    126 			.sysctl_size = sizeof(_PATH_STDPATH),
    127 			.sysctl_name = "cs_path",
    128 			.sysctl_num = USER_CS_PATH,
    129 			.sysctl_data = __UNCONST(_PATH_STDPATH),
    130 			.sysctl_desc = __UNCONST(
    131 				"A value for the PATH environment variable "
    132 				"that finds all the standard utilities"),
    133 		},
    134 		_INT("bc_base_max", USER_BC_BASE_MAX, BC_BASE_MAX,
    135 		     "The maximum ibase/obase values in the bc(1) utility"),
    136 		_INT("bc_dim_max", USER_BC_DIM_MAX, BC_DIM_MAX,
    137 		     "The maximum array size in the bc(1) utility"),
...

https://nxr.netbsd.org/xref/src/lib/libc/gen/sysctl.c?r=1.38#72

This sysctl_usermib table weighs in at a couple kilobytes and dozens of R_*_RELATIVE relocations at load-time (e.g., netbsd-10 amd64):

$ readelf -s /libexec/ld.elf_so | grep usermib
    52: 0000000000210720  2016 OBJECT  LOCAL  DEFAULT   11 sysctl_usermib.0
$ readelf -r /libexec/ld.elf_so

Relocation section '.rela.dyn' at offset 0x530 contains 28 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000210750  000000000008 R_X86_64_RELATIVE                    d628  # <--
000000210778  000000000008 R_X86_64_RELATIVE                    d680
0000002107d8  000000000008 R_X86_64_RELATIVE                    d6d0
000000210838  000000000008 R_X86_64_RELATIVE                    d708
000000210898  000000000008 R_X86_64_RELATIVE                    d738
0000002108f8  000000000008 R_X86_64_RELATIVE                    d768
000000210958  000000000008 R_X86_64_RELATIVE                    d798
0000002109b8  000000000008 R_X86_64_RELATIVE                    d818
000000210a18  000000000008 R_X86_64_RELATIVE                    d878
000000210a78  000000000008 R_X86_64_RELATIVE                    d8c0
000000210ad8  000000000008 R_X86_64_RELATIVE                    d930
000000210b38  000000000008 R_X86_64_RELATIVE                    d978
000000210b98  000000000008 R_X86_64_RELATIVE                    d9d8
000000210bf8  000000000008 R_X86_64_RELATIVE                    da20
000000210c58  000000000008 R_X86_64_RELATIVE                    da90
000000210cb8  000000000008 R_X86_64_RELATIVE                    dad8
000000210d18  000000000008 R_X86_64_RELATIVE                    db20
000000210d78  000000000008 R_X86_64_RELATIVE                    db58
000000210dd8  000000000008 R_X86_64_RELATIVE                    dba0
000000210e38  000000000008 R_X86_64_RELATIVE                    dbe8
000000210e98  000000000008 R_X86_64_RELATIVE                    dc40
000000210ef8  000000000008 R_X86_64_RELATIVE                    dc90  # <--
000000210ff0  000000000008 R_X86_64_RELATIVE                    210f00
000000210ff8  000000000008 R_X86_64_RELATIVE                    211060
000000211048  000000000008 R_X86_64_RELATIVE                    211040
000000211058  000000000008 R_X86_64_RELATIVE                    211050
000000211088  000000000008 R_X86_64_RELATIVE                    d300
000000211090  000000000008 R_X86_64_RELATIVE                    d520

Relocations from the first `<--' comment to the second one are all for sysctl_usermib.

But ld.elf_so will never use the user.* sysctl nodes!  So the table and the logic to search it is useless in ld.elf_so.
>How-To-Repeat:
readelf -a /libexec/ld.elf_so
>Fix:
Use the __sysctl() syscall stub instead of the sysctl() wrapper.

>Release-Note:

>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/59387 CVS commit: src
Date: Fri, 2 May 2025 23:04:56 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Fri May  2 23:04:56 UTC 2025

 Modified Files:
 	src/lib/libc/misc: stack_protector.c
 	src/libexec/ld.elf_so: expand.c paths.c
 Added Files:
 	src/lib/libc/include: __sysctl.h

 Log Message:
 ld.elf_so: Use __sysctl() syscall stub rather than sysctl() wrapper.

 This avoids pulling in some unnecessary junk from libc, saving on a
 couple kilobytes of space and some relative relocations at runtime.

 PR lib/59387: ld.elf_so: needlessly includes libc/gen/sysctl.c user.*


 To generate a diff of this commit:
 cvs rdiff -u -r0 -r1.1 src/lib/libc/include/__sysctl.h
 cvs rdiff -u -r1.9 -r1.10 src/lib/libc/misc/stack_protector.c
 cvs rdiff -u -r1.7 -r1.8 src/libexec/ld.elf_so/expand.c
 cvs rdiff -u -r1.42 -r1.43 src/libexec/ld.elf_so/paths.c

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

State-Changed-From-To: open->needs-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Sat, 03 May 2025 01:08:14 +0000
State-Changed-Why:
fixed in HEAD, maybe worth pullup-10


>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.