NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

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



>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:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 02 22:50:00 +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.



Home | Main Index | Thread Index | Old Index