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