mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
129
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4f51887c4 | ||
|
|
30950ce64d | ||
|
|
0b4e41fc51 | ||
|
|
5c479454d1 | ||
|
|
93606c5c1d | ||
|
|
2d5421ffca | ||
|
|
8587edfc96 | ||
|
|
3258c3fd91 | ||
|
|
890f1c13f0 | ||
|
|
ca54198dec | ||
|
|
cb61572ea3 | ||
|
|
6f9b2bfa50 | ||
|
|
63b53df549 | ||
|
|
9c48b91ee3 | ||
|
|
ae9225d559 | ||
|
|
d6ff274313 | ||
|
|
afd131806b | ||
|
|
16be151849 | ||
|
|
11ac3d78fc | ||
|
|
65d35639a9 | ||
|
|
7cc7a3a4fb | ||
|
|
89da37bb6e | ||
|
|
eacd9cced9 | ||
|
|
9e1b1ef77c | ||
|
|
4662c4675d | ||
|
|
26b9cc42a0 | ||
|
|
10e3ce8a57 | ||
|
|
f34027b27f | ||
|
|
fc36411946 | ||
|
|
f7beb24f3a | ||
|
|
45b8a13c48 | ||
|
|
5d1e923ed7 | ||
|
|
fec2a9c676 | ||
|
|
58da792d8a | ||
|
|
9bcb85688e | ||
|
|
0b58f5d80d | ||
|
|
7cba77790f | ||
|
|
c045fc61e8 | ||
|
|
0b05bc1422 | ||
|
|
1bd7965106 | ||
|
|
5e5ddf5798 | ||
|
|
c3a3a9808a | ||
|
|
50245c56a6 | ||
|
|
bc92b40b15 | ||
|
|
5961de5588 | ||
|
|
12726491af | ||
|
|
ffaa52a30e | ||
|
|
015e8ef482 | ||
|
|
0f731d92cd | ||
|
|
e9996c743d | ||
|
|
b9bd146ad1 | ||
|
|
3f3229739e | ||
|
|
a5aa0df24a | ||
|
|
623279d52a | ||
|
|
0d61a81612 | ||
|
|
7ace114369 | ||
|
|
a36971bebe | ||
|
|
b2d4136341 | ||
|
|
a8e580f6a0 | ||
|
|
6b29e74c73 | ||
|
|
249639137e | ||
|
|
a29c483d3c | ||
|
|
5c47592adb | ||
|
|
70685abb80 | ||
|
|
18f97e140d | ||
|
|
49d25edb76 | ||
|
|
2678adc8eb | ||
|
|
82a0bf8d33 | ||
|
|
c82b609596 | ||
|
|
af51ed63d0 | ||
|
|
ea50bcc538 | ||
|
|
e03cefb56b | ||
|
|
81ae821113 | ||
|
|
cdfa80fad3 | ||
|
|
e2cefe16c3 | ||
|
|
2324aa7aa8 | ||
|
|
69b0bacd72 | ||
|
|
a3d4ff18c5 | ||
|
|
202b4f794a | ||
|
|
aafc0024b3 | ||
|
|
b8985facc9 | ||
|
|
1c0531af67 | ||
|
|
098e6c969c | ||
|
|
3a9c4dbe30 | ||
|
|
93d68cfbeb | ||
|
|
f1c94392d9 | ||
|
|
4e971f5558 | ||
|
|
3d3cd10c4e | ||
|
|
5396eb7045 | ||
|
|
980089ebab | ||
|
|
20b13fa08b | ||
|
|
617376a04b | ||
|
|
b5eecf35d9 | ||
|
|
d70dd7d722 | ||
|
|
b416f91801 | ||
|
|
3e3146fd86 | ||
|
|
28c3a25bc2 | ||
|
|
1d95a42ead | ||
|
|
0f61d77aef | ||
|
|
db59f39646 | ||
|
|
59cb960a22 | ||
|
|
df0669d41d | ||
|
|
d692a3444e | ||
|
|
d109f366ce | ||
|
|
c6ce3bed6d | ||
|
|
800ab3e463 | ||
|
|
568e673fa9 | ||
|
|
6f1d069804 | ||
|
|
b4a0ea4a2c | ||
|
|
b9476fa9aa | ||
|
|
5bba5e06e0 | ||
|
|
f2e3dacbff | ||
|
|
2077c0e385 | ||
|
|
70dd422b6f | ||
|
|
1ab0003872 | ||
|
|
2b13da5e0e | ||
|
|
19e158b7f0 | ||
|
|
b6804fb36e | ||
|
|
ef1cb97f69 | ||
|
|
7cac99621e | ||
|
|
e80612e596 | ||
|
|
3c779ab155 | ||
|
|
84c3993f1f | ||
|
|
45267197ff | ||
|
|
fae194043a | ||
|
|
fcea66cd46 | ||
|
|
9a953f9a48 | ||
|
|
b9957a70b8 | ||
|
|
e24269f74b |
@@ -0,0 +1,2 @@
|
||||
For the GNU C Library Security Advisories, see the git master branch:
|
||||
https://sourceware.org/git/?p=glibc.git;a=tree;f=advisories;hb=HEAD
|
||||
File diff suppressed because it is too large
Load Diff
@@ -480,7 +480,7 @@ build the GNU C Library:
|
||||
GCC 12.1 or higher is required. In general it is recommended to
|
||||
use the newest version of the compiler that is known to work for
|
||||
building the GNU C Library, as newer compilers usually produce
|
||||
better code. As of release time, GCC 15.2.1 is the newest compiler
|
||||
better code. As of release time, GCC 16.1.1 is the newest compiler
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
For multi-arch support it is recommended to use a GCC which has
|
||||
@@ -502,7 +502,7 @@ build the GNU C Library:
|
||||
|
||||
You must use GNU 'binutils' (as and ld) to build the GNU C Library.
|
||||
No other assembler or linker has the necessary functionality at the
|
||||
moment. As of release time, GNU 'binutils' 2.45.1 is the newest
|
||||
moment. As of release time, GNU 'binutils' 2.46.1 is the newest
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
* GNU 'texinfo' 4.7 or later
|
||||
@@ -511,7 +511,7 @@ build the GNU C Library:
|
||||
need this version of the 'texinfo' package. Earlier versions do
|
||||
not understand all the tags used in the document, and the
|
||||
installation mechanism for the info files is not present or works
|
||||
differently. As of release time, 'texinfo' 7.2 is the newest
|
||||
differently. As of release time, 'texinfo' 7.3 is the newest
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
* GNU 'awk' 3.1.2, or higher
|
||||
@@ -519,7 +519,7 @@ build the GNU C Library:
|
||||
'awk' is used in several places to generate files. Some 'gawk'
|
||||
extensions are used, including the 'asorti' function, which was
|
||||
introduced in version 3.1.2 of 'gawk'. As of release time, 'gawk'
|
||||
version 5.3.2 is the newest verified to work to build the GNU C
|
||||
version 5.4.1 is the newest verified to work to build the GNU C
|
||||
Library.
|
||||
|
||||
Testing the GNU C Library requires 'gawk' to be compiled with
|
||||
@@ -536,19 +536,19 @@ build the GNU C Library:
|
||||
|
||||
Perl is not required, but if present it is used in some tests and
|
||||
the 'mtrace' program, to build the GNU C Library manual. As of
|
||||
release time 'perl' version 5.42.0 is the newest verified to work
|
||||
release time 'perl' version 5.44.0 is the newest verified to work
|
||||
to build the GNU C Library.
|
||||
|
||||
* GNU 'sed' 3.02 or newer
|
||||
|
||||
'Sed' is used in several places to generate files. Most scripts
|
||||
work with any version of 'sed'. As of release time, 'sed' version
|
||||
4.9 is the newest verified to work to build the GNU C Library.
|
||||
4.10 is the newest verified to work to build the GNU C Library.
|
||||
|
||||
* Python 3.4 or later
|
||||
|
||||
Python is required to build the GNU C Library. As of release time,
|
||||
Python 3.14.0 is the newest verified to work for building and
|
||||
Python 3.14.6 is the newest verified to work for building and
|
||||
testing the GNU C Library.
|
||||
|
||||
* PExpect 4.0
|
||||
@@ -634,7 +634,7 @@ components of the GNU C Library installation to be in '/lib' and some in
|
||||
Library with '--prefix=/usr'. If you set some other prefix or allow it
|
||||
to default to '/usr/local', then all the components are installed there.
|
||||
|
||||
As of release time, Linux version 6.12 is the newest stable version
|
||||
As of release time, Linux version 7.1 is the newest stable version
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
Reporting Bugs
|
||||
|
||||
+17
@@ -782,6 +782,14 @@ run-built-tests = yes
|
||||
endif
|
||||
endif
|
||||
|
||||
# Whether the timing-sensitive test runs are serialized: each is run with
|
||||
# .NOTPARALLEL and, at the top level, ordered after the rest of the test run.
|
||||
# This is the default; 'make check-parallel' clears it to run every test
|
||||
# concurrently.
|
||||
ifndef serialize-tests
|
||||
serialize-tests = yes
|
||||
endif
|
||||
|
||||
# Whether to build the static math tests
|
||||
ifndef build-math-static-tests
|
||||
build-math-static-tests = no
|
||||
@@ -815,8 +823,15 @@ $(subst $(empty) ,:,$(strip $(patsubst -Wl$(comma)-rpath-link=%, %,\
|
||||
run-via-rtld-prefix = \
|
||||
$(if $(strip $(filter $(notdir $(built-program-file)), \
|
||||
$(tests-static) $(xtests-static))),, $(rtld-prefix))
|
||||
# $(container-via-rtld-prefix) is like $(run-via-rtld-prefix), but for the
|
||||
# support/test-container helper, which is always dynamically linked even
|
||||
# when the test it launches is static. It must therefore always run
|
||||
# through the newly built loader, unlike $(run-via-rtld-prefix) which is
|
||||
# empty for tests listed in tests-static or xtests-static.
|
||||
container-via-rtld-prefix = $(rtld-prefix)
|
||||
else
|
||||
run-via-rtld-prefix =
|
||||
container-via-rtld-prefix =
|
||||
endif
|
||||
# $(run-program-env) is the default environment variable settings to
|
||||
# use when running a program built with the newly built library.
|
||||
@@ -883,6 +898,7 @@ endif
|
||||
|
||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
||||
test-via-rtld-prefix =
|
||||
test-container-via-rtld-prefix =
|
||||
test-program-prefix-before-env = $(test-wrapper-env)
|
||||
test-program-prefix-after-env =
|
||||
test-program-prefix = $(test-program-prefix-before-env) $(run-program-env) \
|
||||
@@ -894,6 +910,7 @@ test-program-cmd = $(test-program-cmd-before-env) $(run-program-env) \
|
||||
host-test-program-cmd = $(built-program-file)
|
||||
else
|
||||
test-via-rtld-prefix = $(run-via-rtld-prefix)
|
||||
test-container-via-rtld-prefix = $(container-via-rtld-prefix)
|
||||
test-program-prefix-before-env = $(run-program-prefix-before-env)
|
||||
test-program-prefix-after-env = $(run-program-prefix-after-env)
|
||||
test-program-prefix = $(run-program-prefix)
|
||||
|
||||
@@ -54,9 +54,6 @@ configure: configure.ac aclocal.m4; $(autoconf-it)
|
||||
endif # $(AUTOCONF) = no
|
||||
|
||||
|
||||
# We don't want to run anything here in parallel.
|
||||
.NOTPARALLEL:
|
||||
|
||||
# These are the targets that are made by making them in each subdirectory.
|
||||
+subdir_targets := subdir_lib objects objs others subdir_mostlyclean \
|
||||
subdir_clean subdir_distclean subdir_realclean \
|
||||
@@ -129,6 +126,13 @@ lib-noranlib: subdir_lib
|
||||
ifeq (yes,$(build-shared))
|
||||
# Build the shared object from the PIC object library.
|
||||
lib: $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so
|
||||
ifdef libc.so-version
|
||||
# Every program linked in the others pass lists the versioned name
|
||||
# (through link-libc-between-gnulib) as a prerequisite, and the rule
|
||||
# creating the symbolic link is visible in every sub-make. Build it
|
||||
# here once so the concurrent sub-makes do not race to create it.
|
||||
lib: $(common-objpfx)libc.so$(libc.so-version)
|
||||
endif
|
||||
endif # $(build-shared)
|
||||
|
||||
# Used to build testrun.sh.
|
||||
@@ -490,6 +494,159 @@ subdir=$(@D)$(if $($(@D)-srcdir),\
|
||||
endef
|
||||
|
||||
.PHONY: $(+subdir_targets) $(all-subdirs-targets)
|
||||
|
||||
# Encode the topological ordering computed by scripts/gen-sorted.awk as
|
||||
# explicit dependencies between the per-subdirectory targets, so that
|
||||
# independent subdirectories build concurrently. In summary:
|
||||
#
|
||||
# * Every subdirectory depends on the first sorted one (csu, or mach on
|
||||
# Hurd): its sub-make also materializes the shared generated files in
|
||||
# $(common-objpfx) (abi-versions.h, sysd-syscalls, before-compile
|
||||
# headers, ...) that concurrent sub-makes would otherwise race to
|
||||
# create.
|
||||
#
|
||||
# * The edges requested by the Depend files (emitted by gen-sorted.awk
|
||||
# as subdir-deps-*) are preserved.
|
||||
#
|
||||
# * elf stays last for the object-building classes, as in the sorted
|
||||
# list: its rtld link consumes $(common-objpfx)libc_pic.a, which
|
||||
# aggregates every other subdirectory's objects, and its rtld-Rules
|
||||
# recursion compiles into the other subdirectories' object
|
||||
# directories. The others/tests/xtests classes have no such
|
||||
# dependency (the pass barriers below provide everything they need),
|
||||
# so elf is unordered there.
|
||||
#
|
||||
# * Only target classes without cross-directory file conflicts use this
|
||||
# sparse ordering; everything else (install, clean, abi, stubs) keeps
|
||||
# the previous total order via a serial chain.
|
||||
|
||||
+elf_last_subdir_targets := \
|
||||
subdir_lib objects \
|
||||
objs \
|
||||
subdir_objs \
|
||||
# +elf_last_subdir_targets
|
||||
+parallel_subdir_targets := \
|
||||
$(+elf_last_subdir_targets) \
|
||||
others \
|
||||
tests \
|
||||
xtests \
|
||||
# +parallel_subdir_targets
|
||||
+serial_subdir_targets := $(filter-out $(+parallel_subdir_targets),\
|
||||
$(+subdir_targets))
|
||||
|
||||
# The tests and xtests classes run, rather than build, the per-directory
|
||||
# test programs; once the 'others' pass barrier below has built the tree
|
||||
# they are mutually independent and carry no cross-directory ordering.
|
||||
# Keeping them out of the generated-file and Depend edges below is what
|
||||
# lets 'make subdir/tests' run only that subdirectory's tests.
|
||||
+barrier_only_subdir_targets := tests xtests
|
||||
+ordered_parallel_subdir_targets := \
|
||||
$(filter-out $(+barrier_only_subdir_targets),$(+parallel_subdir_targets))
|
||||
|
||||
# The subdirectories that generate shared files in $(common-objpfx)
|
||||
# consumed by the rest of the build without explicit dependencies: csu
|
||||
# provides the gen-as-const headers, and on Hurd the mach and hurd
|
||||
# directories generate the MiG RPC headers (every other subdirectory
|
||||
# otherwise runs a nested make in hurd/ to create them, racing under
|
||||
# parallel recursion; see sysdeps/mach/hurd/Makefile). Run them serially,
|
||||
# in their sorted order (mach, hurd, csu).
|
||||
+subdir-pregen := $(filter mach hurd csu,$(subdirs))
|
||||
+subdir-rest := $(filter-out $(+subdir-pregen),$(subdirs))
|
||||
|
||||
$(foreach t,$(+ordered_parallel_subdir_targets),$(eval \
|
||||
$(addsuffix /$(t),$(+subdir-rest)): $(addsuffix /$(t),$(+subdir-pregen))))
|
||||
+subdir-pregen-prev :=
|
||||
$(foreach d,$(+subdir-pregen),$(foreach t,$(+ordered_parallel_subdir_targets),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(+subdir-pregen-prev))))\
|
||||
$(eval +subdir-pregen-prev := $(d)))
|
||||
# For the classes where elf is forced last, edges pointing to elf are
|
||||
# dropped: the sorted list always overrides such Depend requests today
|
||||
# (e.g. support/Depend), and the elf-last edges below would otherwise
|
||||
# create a cycle. The remaining classes honor them.
|
||||
$(foreach t,$(+elf_last_subdir_targets),$(foreach d,$(+subdir-rest),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),\
|
||||
$(filter-out elf,$(filter $(subdirs),$(subdir-deps-$(d))))))))
|
||||
$(foreach t,$(filter-out $(+elf_last_subdir_targets),\
|
||||
$(+ordered_parallel_subdir_targets)),\
|
||||
$(foreach d,$(+subdir-rest),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(filter $(subdirs),$(subdir-deps-$(d)))))))
|
||||
ifneq (,$(filter elf,$(subdirs)))
|
||||
$(foreach t,$(+elf_last_subdir_targets),$(eval \
|
||||
elf/$(t): $(addsuffix /$(t),$(filter-out elf,$(subdirs)))))
|
||||
endif
|
||||
|
||||
# The archive rules in Makerules list every stamp file as a
|
||||
# prerequisite of libc_pic.a, which the elf sub-make evaluates for the
|
||||
# librtld.map link, but a sub-make can only create its own directory's
|
||||
# stamps. Create the top-level ones before the fan-out.
|
||||
$(foreach t,$(+elf_last_subdir_targets),$(eval \
|
||||
$(addsuffix /$(t),$(subdirs)): \
|
||||
$(foreach o,$(object-suffixes-for-libc),$(common-objpfx)stamp$(o))))
|
||||
|
||||
# Pass barriers: a subdirectory 'others' build links programs against
|
||||
# the libraries, so the 'lib' pass (including the top-level libc.so
|
||||
# link) must have completed.
|
||||
# 'tests' and 'xtests' additionally require the 'others' pass. The
|
||||
# testroot used by the container tests performs a full installation in
|
||||
# its recipe, which must not run concurrently with the build passes.
|
||||
$(addsuffix /others,$(subdirs)): lib
|
||||
$(addsuffix /tests,$(subdirs)) $(addsuffix /xtests,$(subdirs)): others
|
||||
$(objpfx)testroot.pristine/install.stamp: | others
|
||||
|
||||
# Timing-sensitive test runs: the threading tests (nptl/htl) and the realtime
|
||||
# tests (rt) are perturbed by the machine load, so run them after the rest of
|
||||
# the test run has finished and one group at a time. Those subdirectories
|
||||
# also serialize their own tests (.NOTPARALLEL in their Makefiles).
|
||||
#
|
||||
# This only orders a full-suite run ('make check'/'tests'); a targeted
|
||||
# 'make subdir/tests' is left alone. And it only orders the test run
|
||||
# (run-built-tests=yes); the "build the tests" pass (run-built-tests=no)
|
||||
# is left fully parallel, so every test program still builds concurrently.
|
||||
# serialize-tests=no ('make check-parallel') drops the ordering entirely.
|
||||
ifeq ($(run-built-tests),yes)
|
||||
ifeq (yes,$(serialize-tests))
|
||||
ifneq (,$(filter tests xtests check xcheck,$(MAKECMDGOALS)))
|
||||
+late-test-subdirs := $(filter nptl htl,$(subdirs)) $(filter rt,$(subdirs))
|
||||
+test-run-prev := \
|
||||
$(addsuffix /tests,$(filter-out $(+late-test-subdirs),$(subdirs)))
|
||||
$(foreach d,$(+late-test-subdirs),\
|
||||
$(eval $(d)/tests: $(+test-run-prev))\
|
||||
$(eval +test-run-prev += $(d)/tests))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
# The top-level libc.so and linkobj/libc_pic.a rules list these
|
||||
# subdirectory-built files as prerequisites, but no rule at this level
|
||||
# builds them. The explicit empty recipe (';') is required, a
|
||||
# prerequisite-only rule would send make on an implicitrule search and
|
||||
# have this level compile them itself with the wrong context.
|
||||
ifneq (,$(filter elf,$(subdirs)))
|
||||
$(elf-objpfx)ld.so $(elf-objpfx)sofini.os $(elf-objpfx)interp.os: \
|
||||
| elf/subdir_lib ;
|
||||
endif
|
||||
ifneq (,$(filter sunrpc,$(subdirs)))
|
||||
# Makerules explicit adds librpc_compat_pic.a as a dependency of
|
||||
# libc_pic.a.
|
||||
$(common-objpfx)sunrpc/librpc_compat_pic.a: | sunrpc/subdir_lib ;
|
||||
endif
|
||||
# Hurd sysdedp Makeilfe links libc.so against the lib*user-link.so
|
||||
# objects, built by the %-link.so: %_pic.a pattern rule from archives
|
||||
# that only the mach and hurd sub-makes create.
|
||||
ifneq (,$(filter mach,$(subdirs)))
|
||||
$(common-objpfx)mach/libmachuser_pic.a: | mach/subdir_lib ;
|
||||
endif
|
||||
ifneq (,$(filter hurd,$(subdirs)))
|
||||
$(common-objpfx)hurd/libhurduser_pic.a: | hurd/subdir_lib ;
|
||||
endif
|
||||
endif
|
||||
|
||||
# The remaining target classes keep the old total order.
|
||||
+subdir-chain-prev :=
|
||||
$(foreach d,$(subdirs),$(foreach t,$(+serial_subdir_targets),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(+subdir-chain-prev))))\
|
||||
$(eval +subdir-chain-prev := $(d)))
|
||||
|
||||
# Targets to clean things up to various degrees.
|
||||
|
||||
@@ -540,26 +697,41 @@ $(objpfx)check-local-headers.out: scripts/check-local-headers.sh
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(headers)" ""
|
||||
# Special test of all the installed headers in this directory.
|
||||
# Special test of all the installed headers in this directory. See
|
||||
# Rules for the per-header split rationale.
|
||||
tests-special += $(objpfx)check-installed-headers-c.out
|
||||
libof-check-installed-headers-c := testsuite
|
||||
$(objpfx)check-installed-headers-c.out: \
|
||||
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
|
||||
scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-c.out: $(+cih-c-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-c-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(CXX)" ""
|
||||
tests-special += $(objpfx)check-installed-headers-cxx.out
|
||||
libof-check-installed-headers-cxx := testsuite
|
||||
$(objpfx)check-installed-headers-cxx.out: \
|
||||
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
|
||||
scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-cxx.out: $(+cih-cxx-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-cxx-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
endif # $(CXX)
|
||||
|
||||
@@ -648,8 +820,13 @@ else
|
||||
LINKS_DSO_PROGRAM = links-dso-program
|
||||
endif
|
||||
|
||||
# The testroot is only used by the container tests, which are not run
|
||||
# when run-built-tests is no; skip the installation entirely in that
|
||||
# case.
|
||||
ifeq ($(run-built-tests),yes)
|
||||
$(tests-container) $(addsuffix /tests,$(subdirs)) : \
|
||||
$(objpfx)testroot.pristine/install.stamp
|
||||
endif
|
||||
$(objpfx)testroot.pristine/install.stamp :
|
||||
test -d $(objpfx)testroot.pristine || \
|
||||
mkdir $(objpfx)testroot.pristine
|
||||
@@ -700,7 +877,11 @@ endif
|
||||
touch $(objpfx)testroot.pristine/install.stamp
|
||||
|
||||
tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
|
||||
# The build-only first pass of the two-pass 'make check' (see Makerules)
|
||||
# passes tests-summary=no: the merge and summary are left to the second
|
||||
# pass, which folds in this pass's $(tests-special) results.
|
||||
tests: $(tests-special)
|
||||
ifneq ($(tests-summary),no)
|
||||
$(..)scripts/merge-test-results.sh -s $(objpfx) "" \
|
||||
$(sort $(tests-special-notdir:.out=)) \
|
||||
> $(objpfx)subdir-tests.sum
|
||||
@@ -708,11 +889,14 @@ tests: $(tests-special)
|
||||
$(sort $(subdirs) .) \
|
||||
> $(objpfx)tests.sum
|
||||
$(call summarize-tests,tests.sum)
|
||||
endif
|
||||
xtests:
|
||||
ifneq ($(tests-summary),no)
|
||||
$(..)scripts/merge-test-results.sh -t $(objpfx) subdir-xtests.sum \
|
||||
$(sort $(subdirs)) \
|
||||
> $(objpfx)xtests.sum
|
||||
$(call summarize-tests,xtests.sum, for extra tests)
|
||||
endif
|
||||
|
||||
# The realclean target is just like distclean for the parent, but we want
|
||||
# the subdirs to know the difference in case they care.
|
||||
|
||||
@@ -259,7 +259,17 @@ endif # gen-py-const-headers
|
||||
ifdef gen-as-const-headers
|
||||
# Generating headers for assembly constants.
|
||||
# We need this defined early to get into before-compile before
|
||||
# it's used in sysd-rules, below.
|
||||
# it's used in sysd-rules, below. The gen-as-const-headers is evaluated
|
||||
# per subdirectory, so the before-compile dependency below only orders
|
||||
# the generated header before the compiles of the subdirectory whose
|
||||
# Makefile adds the .sym directive.
|
||||
# The parallel subdirectory recursion does not order sibling subdirectories,
|
||||
# so a .sym must be added in the subdirectory that compiles its consumers,
|
||||
# or in csu (which runs before the parallel) when it has consumers in
|
||||
# several subdirectories.
|
||||
# It must not add the same .sym in several subdirectories though: their
|
||||
# concurrent sub-makes would race generating the header through the fixed
|
||||
# temporary files below.
|
||||
# Define GEN_AS_CONST_HEADERS to avoid circular dependency [BZ #22792].
|
||||
# NB: <tcb-offsets.h> is generated from tcb-offsets.sym to define
|
||||
# offsets and sizes of types in <tls.h> and maybe <pthread.h> which
|
||||
@@ -302,7 +312,12 @@ lib-names-h-abi = gnu/lib-names-$(default-abi).h
|
||||
lib-names-stmp-abi = gnu/lib-names-$(default-abi).stmp
|
||||
before-compile += $(common-objpfx)$(lib-names-h-abi)
|
||||
common-generated += gnu/lib-names.h
|
||||
# The $(inst_includedir)/%.h install rules are defined only where $(headers)
|
||||
# is non-empty, and with parallel subdir recursion a subdir without headers
|
||||
# (e.g. csu) may run before the top level has installed the header.
|
||||
ifndef subdir
|
||||
install-others-nosubdir: $(inst_includedir)/$(lib-names-h-abi)
|
||||
endif
|
||||
$(common-objpfx)gnu/lib-names.h:
|
||||
$(make-target-directory)
|
||||
{ \
|
||||
@@ -743,10 +758,20 @@ all-dt-files := $(foreach o,$(object-suffixes-for-libc),$(+depfiles:.d=$o.dt))
|
||||
$(wildcard $(all-dt-files:.dt=.d))
|
||||
|
||||
# This is a funny rule in that it removes its input file.
|
||||
#
|
||||
# More than one make can convert the .dt files of a single object
|
||||
# directory: the elf rtld-Rules recursion runs a sub-make over every
|
||||
# $(rtld-subdirs) directory, concurrently with that directory's own
|
||||
# sub-make under the parallel subdir recursion. Add the PID of the
|
||||
# shell to the temporary name and claim the input with a rename: only
|
||||
# the run that wins converts and installs the target.
|
||||
%.d: %.dt
|
||||
@sed $(sed-remove-objpfx) $< > $(@:.d=.T) && \
|
||||
mv -f $(@:.d=.T) $@ && \
|
||||
rm -f $<
|
||||
@dt=$(@:.d=.T)$$$$; \
|
||||
if mv -f $< $$dt 2>/dev/null; then \
|
||||
sed $(sed-remove-objpfx) $$dt > $$dt.new && \
|
||||
mv -f $$dt.new $@ && \
|
||||
rm -f $$dt; \
|
||||
fi
|
||||
|
||||
# Avoid the .h.d files for any .sym files whose .h files don't exist yet.
|
||||
# They will be generated when they're needed, and trying too early won't work.
|
||||
@@ -1184,12 +1209,55 @@ ALL_BUILD_CFLAGS = $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -D_GNU_SOURCE \
|
||||
-DIS_IN_build -include $(common-objpfx)config.h
|
||||
|
||||
# Support the GNU standard name for this target.
|
||||
.PHONY: check
|
||||
# Special target xcheck runs tests which cannot be run unconditionally;
|
||||
# maintainers should use this target.
|
||||
.PHONY: check xcheck
|
||||
|
||||
# Building and running a subdirectory's tests are fused in its sub-make,
|
||||
# and run-built-tests is fixed for a make instance, so the only way to
|
||||
# build every test program with the recursion fully parallel while the
|
||||
# run still honors the per-subdirectory .NOTPARALLEL (nptl/htl/rt) and the
|
||||
# run-time ordering is to use two passes. At the top level, 'make check'
|
||||
# therefore builds the test programs (run-built-tests=no, recursion fully
|
||||
# parallel) and then runs them (run-built-tests=yes). 'make tests' and a
|
||||
# subdirectory's own 'check' stay single-pass.
|
||||
# The first pass still runs the static checks ($(tests-special): abi,
|
||||
# conformtest, installed headers, ...), so tests-summary=no makes it skip
|
||||
# the results merge and summary: an unexpected FAIL there would otherwise
|
||||
# abort 'check' before the second pass runs any built test, and even a
|
||||
# clean run would print a misleading partial summary. The .test-result
|
||||
# files persist, so the second pass folds those results into the one
|
||||
# complete summary at the end.
|
||||
check-twopass :=
|
||||
ifndef subdir
|
||||
ifeq (yes,$(run-built-tests))
|
||||
check-twopass := yes
|
||||
endif
|
||||
endif
|
||||
ifeq (yes,$(check-twopass))
|
||||
check:
|
||||
$(MAKE) run-built-tests=no tests-summary=no tests
|
||||
$(MAKE) run-built-tests=yes tests
|
||||
xcheck:
|
||||
$(MAKE) run-built-tests=no tests-summary=no xtests
|
||||
$(MAKE) run-built-tests=yes xtests
|
||||
else
|
||||
check: tests
|
||||
# Special target to run tests which cannot be run unconditionally.
|
||||
# Maintainers should use this target.
|
||||
.PHONY: xcheck
|
||||
xcheck: xtests
|
||||
endif
|
||||
|
||||
# 'make check-parallel' runs the whole suite with maximum concurrency:
|
||||
# serialize-tests=no drops the per-subdirectory .NOTPARALLEL and the run-time
|
||||
# ordering, so every test builds and runs in parallel. A single pass suffices
|
||||
# (there is no .NOTPARALLEL to work around, so the test programs already build
|
||||
# concurrently).
|
||||
# This is faster on an idle machine, at the cost of possible flakiness in the
|
||||
# timing-sensitive tests under the heavier load.
|
||||
.PHONY: check-parallel xcheck-parallel
|
||||
check-parallel:
|
||||
$(MAKE) serialize-tests=no tests
|
||||
xcheck-parallel:
|
||||
$(MAKE) serialize-tests=no xtests
|
||||
|
||||
# Also handle test inputs in sysdeps.
|
||||
vpath %.input $(sysdirs)
|
||||
@@ -1375,7 +1443,7 @@ endef
|
||||
# Also remove the dependencies and generated source files.
|
||||
common-clean: common-mostlyclean
|
||||
-rm -f $(addprefix $(objpfx),$(generated))
|
||||
-rm -f $(objpfx)*.d $(objpfx)*.dt
|
||||
-rm -f $(objpfx)*.d $(objpfx)*.dt $(objpfx)*.T[0-9]*
|
||||
-rm -fr $(addprefix $(objpfx),$(generated-dirs))
|
||||
-rm -f $(addprefix $(common-objpfx),$(common-generated))
|
||||
-rm -f $(gen-as-const-headers:%.sym=$(common-objpfx)%.h)
|
||||
|
||||
@@ -5,48 +5,92 @@ See the end for copying conditions.
|
||||
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.44.1
|
||||
|
||||
The following bugs are resolved with this release:
|
||||
|
||||
[34338] libc: Cancellable syscall wrappers are missing from backtraces
|
||||
because they tail-call __syscall_cancel
|
||||
[34438] build: non reproducible build failure: sigaltstack-offsets.h:
|
||||
No such file or directory
|
||||
[34439] build: parallel make install fails on multi-ABI targets: no
|
||||
rule to make $(inst_includedir)/gnu/lib-names-$(abi).h in csu
|
||||
[34441] math: math: sinh() returns wrong results for some inputs with
|
||||
|x| > 36.736801
|
||||
[34465] math: math: x86_64 tanh ifunc selection wrong
|
||||
[34507] nptl: Pretty-printer tests FAIL instead of UNSUPPORTED when
|
||||
cross-testing without python3 on target
|
||||
[34509] libc: [m68k] Regression: Perl locks up after upgrading glibc
|
||||
to 2.43
|
||||
|
||||
Version 2.44
|
||||
|
||||
Major new features:
|
||||
|
||||
* System-wide tunables can be applied using /etc/tunables.conf and
|
||||
running ldconfig. Specific tunable settings and the
|
||||
/etc/tunables.conf file format and path are not part of the stable
|
||||
library interfaces and may change between releases.
|
||||
|
||||
* A new tunable, glibc.elf.thp, is added to map read-only segments with
|
||||
Transparent Huge Pages (THP) if THP isn't disable in kernel. When
|
||||
Transparent Huge Pages (THP) if THP is not disabled in the kernel. When
|
||||
glibc.elf.thp is set to 1, malloc uses the actual kernel THP mode
|
||||
instead of defaulting to madvise mode and madvise_thp will stop issuing
|
||||
MADV_HUGEPAGE if kernel THP mode is always.
|
||||
|
||||
* THP page size in malloc is capped to MAX_THP_PAGESIZE. If THP page
|
||||
size is above MAX_THP_PAGESIZE, THP in malloc is disabled.
|
||||
* The THP page size in malloc is capped to MAX_THP_PAGESIZE. If the THP
|
||||
page size is above MAX_THP_PAGESIZE, THP in malloc is disabled.
|
||||
|
||||
* Additional optimized and correctly rounded mathematical functions have
|
||||
been imported from the CORE-MATH project, in particular cosh, sinh, and
|
||||
tanh.
|
||||
|
||||
* The SVID handling for cosh and sinh were moved to compat symbols, allowing
|
||||
improvements in performance.
|
||||
* Many additional improvements to existing functions have been synchronized
|
||||
from the CORE-MATH project.
|
||||
|
||||
* New locale added: hrx_BR (Hunsrik language spoken in Brazil).
|
||||
* For C++26, the assert macro is now variadic, allowing more complex
|
||||
arguments containing commas (which however still must evaluate to a single
|
||||
value).
|
||||
|
||||
* The SVID error handling for cosh and sinh was moved to compatibility
|
||||
symbols, allowing improvements in performance.
|
||||
|
||||
* Static PIE is now supported for arm-*-linux-gnueabi. It requires toolchain
|
||||
support to correctly set the expected linker options.
|
||||
|
||||
* On AArch64 targets that support Guarded Control Stack extension all GCS
|
||||
* On AArch64 targets that support the Guarded Control Stack extension all GCS
|
||||
operations (including status, write on shadow stack, and push to shadow
|
||||
stack) are locked after enabling GCS with ENFORCED or OVERRIDE GCS policy.
|
||||
When a GCS operation is locked, a program cannot change this operation
|
||||
status via prctl syscall. This prevents disabling or corrupting GCS
|
||||
shadow stack during runtime.
|
||||
status via the prctl syscall. This prevents disabling or corrupting the
|
||||
GCS shadow stack during runtime.
|
||||
|
||||
* On AArch64 targets, log, exp, sin, cas, sinh, cosh, asinh, acosh, atanh
|
||||
single and double precision special cases have been vectorized for SVE and
|
||||
AdvSIMD, and vector variants of powr have been added.
|
||||
|
||||
* On RISC-V targets, vector extension optimized variants of memcmp, memccpy,
|
||||
memchr, memcpy, memmove, stpncpy, strcmp, strchr, strcpy, strncmp, strncpy,
|
||||
strlen, and strrchr have been added.
|
||||
|
||||
* On PowerPC, memchr optimized for Power10 has been re-added.
|
||||
|
||||
* Support for LoongArch32 has been added.
|
||||
|
||||
* Pre-built ld.so.cache files can be installed with ldconfig.
|
||||
|
||||
* A new locale has been added: hrx_BR (Hunsrik language spoken in Brazil).
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
* Although malloc and related functions currently return pointers
|
||||
aligned to alignof (max_align_t), the documentation now says future
|
||||
versions of glibc may relax alignment requirements for small allocations.
|
||||
For example, a future malloc (1) might return a pointer with odd
|
||||
For example, a future malloc(1) might return a pointer with odd
|
||||
alignment, because no object of size 1 can have a fundamental
|
||||
alignment greater than 1.
|
||||
|
||||
* The s390-linux-gnu (31bit) configuration is no longer supported.
|
||||
* The s390-linux-gnu (31bit) configuration is no longer supported.
|
||||
|
||||
* The --enable-memory-tagging configure option has been removed.
|
||||
The corresponding AArch64-specific functionality that was previously
|
||||
@@ -57,10 +101,6 @@ Deprecated and removed features, and other changes affecting compatibility:
|
||||
remaining behavior was to suppress the link-time warnings on the NSS
|
||||
interface functions in libc.a, which are now emitted unconditionally.
|
||||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
[Add changes to build and runtime requirements here]
|
||||
|
||||
Security related changes:
|
||||
|
||||
The following CVEs were fixed in this release, details of which can be
|
||||
@@ -80,8 +120,114 @@ found in the advisories directory of the release tarball:
|
||||
|
||||
The following bugs were resolved with this release:
|
||||
|
||||
[The release manager will add the list generated by
|
||||
scripts/list-fixed-bugs.py just before the release.]
|
||||
[2363] libc: EOPNOTSUPP and ENOTSUP in errno.h must be different,
|
||||
according to SUSv3
|
||||
[3794] manual: iconv: //TRANSLIT and //IGNORE feature not documented
|
||||
[15792] dynamic-link: [arm] ARM dynamic linker should save/restore
|
||||
coprocessor registers
|
||||
[20331] libc: fts ignores errors from readdir()
|
||||
[20680] dynamic-link: ifunc resolver cannot access the thread pointer
|
||||
with static linking
|
||||
[22944] libc: fts cannot traverse paths which have a length longer
|
||||
than USHRT_MAX
|
||||
[25257] libc: sotruss: fix error message for '--f' argument
|
||||
[25770] locale: newlocale memory leak in LOCPATH parsing and on error
|
||||
paths
|
||||
[27582] libc: x86_64: IFUNC in static user programs may crash when
|
||||
built with -fstack-protector-all
|
||||
[28218] dynamic-link: ld.so: ifunc resolver calls a lazy PLT. When
|
||||
does it work?
|
||||
[28817] libc: static-pie ifunc resolver tls failure
|
||||
[28940] nss: __nss_database_get doesn't check for allocation failure
|
||||
[30136] manual: Please document behaviour of iconv(3) when input is
|
||||
untranslatable
|
||||
[30304] nptl: nptl/tst-pthread-gdb-attach test fails with new libc
|
||||
shared library version
|
||||
[30769] malloc: malloc_trim is not working correctly for arenas other
|
||||
than arena 0
|
||||
[30976] dynamic-link: rtld: resolve ifunc relocations after
|
||||
JUMP_SLOT/GLOB_DAT/etc
|
||||
[30992] libc: alpha: setrlimit() with negative values besides
|
||||
RLIM_INFINITY returns EPERM
|
||||
[31901] libc: elf/tst-glibc-hwcaps-prepend-cache fails on i686
|
||||
[33226] math: math-vector-fortran.h vs not ffast-math
|
||||
[33626] libc: execvpe should skip inaccessible $PATH components
|
||||
[33650] build: abilist.awk doesn't handle unversioned defined symbols
|
||||
[33785] stdio: New streams are linked into global list before they are
|
||||
fully initialized
|
||||
[33848] build: Build fails at openat2.h, redefinition of 'struct
|
||||
open_how'
|
||||
[33882] libc: Recursion in nftw() causes stack overflow(CWE-674)
|
||||
[33904] build: error: '__vasprintf_chk' undeclared here
|
||||
[33921] build: Building with Linux-7.0-rc1 errors on OPEN_TREE_CLONE
|
||||
[33935] stdio: _IO_wfile_doallocate not linked correctly when linking
|
||||
glibc statically
|
||||
[33980] locale: iconv: ibm139x trigger assertion error when converting
|
||||
to internal while lack enough room (CVE-2026-4046)
|
||||
[33985] build: ld: cannot find -lgcc_s: No such file or directory
|
||||
[33999] stdio: libio: potential dangling _IO_save_base or memory leak
|
||||
in wgenops.c
|
||||
[34006] stdio: libio: inconsistent fmemopen_write behavior on last \0
|
||||
[34008] stdio: stdio-common: scanf %mc pattern will cause heap
|
||||
overflow when width > 1024
|
||||
[34014] nss: gethostbyaddr and gethostbyaddr_r may incorrectly handle
|
||||
DNS response
|
||||
[34015] nss: gethostbyaddr and gethostbyaddr_r return invalid DNS
|
||||
hostnames
|
||||
[34019] stdio: libio: undefined behavior when setbuf on open_memstream
|
||||
[34033] network: resolv/ns_print.c: ns_sprintrrf TSIG path bypasses
|
||||
buflen and can overflow caller buffer
|
||||
[34064] dynamic-link: The unnecessary PT_NOTE check in when loading a
|
||||
binary
|
||||
[34069] network: Buffer overread in ns_sprintrrf with corrupted RDATA
|
||||
field (CVE-2026-6238)
|
||||
[34070] hurd: Calling open ("/dev/tty/", O_RDONLY) causes the program
|
||||
to segfault
|
||||
[34073] regex: regexec can mistakenly match with backrefs and the $
|
||||
anchor
|
||||
[34079] dynamic-link: THP segment load aligns all PT_LOAD segments to
|
||||
THP page size
|
||||
[34080] dynamic-link: Support THP segment load with THP enabled with
|
||||
madvise
|
||||
[34083] dynamic-link: __get_thp_mode and __get_thp_size are called
|
||||
twice
|
||||
[34090] libc: wordexp WRDE_APPEND rollback restores stale we_wordv,
|
||||
leading to invalid free in wordfree
|
||||
[34098] libc: Missing SUPPORT_STATIC_PIE in arm32
|
||||
[34129] string: x86: Non-temporal memset unreachable on AMD Zen 3/4/5
|
||||
[34144] libc: ld.so clobbers VFP registers during runtime linking
|
||||
[34154] network: Segfault in sock_eq after res_init() returns -1, due
|
||||
to stale _u._ext.nscount in __res_iclose
|
||||
[34156] dynamic-link: dlsym(RTLD_DEFAULT, ...) from a constructor
|
||||
SIGSEGVs when tail-called
|
||||
[34164] dynamic-link: elf: IFUNC resolvers do not see static TLS
|
||||
initialization
|
||||
[34170] dynamic-link: elf: IFUNC resolver reading global-
|
||||
dynamic/TLSDESC __thread variable crashes inside __tls_get_addr
|
||||
[34183] math: fma produces wrong results
|
||||
[34192] nptl: pthread_setname_np opens /proc/<tid>/comm with O_RDWR
|
||||
instead of O_WRONLY|O_CLOEXEC
|
||||
[34196] libc: elf: static dlopen: pointer guard of the loaded
|
||||
ld.so/libc.so is left uninitialized
|
||||
[34197] dynamic-link: elf: Stack canary and pointer guard are
|
||||
recoverable from AT_RANDOM (getauxval)
|
||||
[34205] libc: aarch64: SIGSEGV in tunable_strcmp in static-pie
|
||||
binaries run with a string tunable
|
||||
[34208] stdio: scanf not pushback after matching failure
|
||||
[34210] libc: elf/tst-glibc-hwcaps-prepend-cache fails on
|
||||
armv7a-unknown-linux-gnueabihf
|
||||
[34236] locale: Non-representable transliteration still causes iconv
|
||||
to exit with 1 if //TRANSLIT is specified
|
||||
[34289] network: ns_sprintrrf uses p_class, p_type internally
|
||||
[34311] build: THP tests failed to link
|
||||
[34347] libc: Incorrect trailing bitfield word of struct tcp_info
|
||||
[34348] dynamic-link: FAIL: elf/tst-thp-1 if THP is disabled in kernel
|
||||
[34351] build: Random test failures
|
||||
[34355] build: [2.44 Regression] "make check -j7 subdirs=stdio-common"
|
||||
no longer works
|
||||
[34396] libc: sparc64-unknown-linux-gnu , Gentoo: >200 test failures,
|
||||
SIGILL in many binaries
|
||||
[34398] string: Truncated strncpy on s390x z900 ifunc variant
|
||||
|
||||
Version 2.43
|
||||
|
||||
|
||||
@@ -80,15 +80,24 @@ common-generated += dummy.o dummy.c
|
||||
|
||||
ifneq "$(headers)" ""
|
||||
# Test that all of the headers installed by this directory can be compiled
|
||||
# in isolation.
|
||||
# in isolation. Each header gets its own intermediate target so that the
|
||||
# it can run concurrently under -j; the .out target concatenates the per-header
|
||||
# results in the original $(headers) order.
|
||||
tests-special += $(objpfx)check-installed-headers-c.out
|
||||
libof-check-installed-headers-c := testsuite
|
||||
$(objpfx)check-installed-headers-c.out: \
|
||||
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
|
||||
$(..)scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-c.out: $(+cih-c-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-c-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(CXX)" ""
|
||||
@@ -96,12 +105,19 @@ ifneq "$(CXX)" ""
|
||||
# in isolation as C++.
|
||||
tests-special += $(objpfx)check-installed-headers-cxx.out
|
||||
libof-check-installed-headers-cxx := testsuite
|
||||
$(objpfx)check-installed-headers-cxx.out: \
|
||||
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
|
||||
$(..)scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-cxx.out: $(+cih-cxx-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-cxx-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
endif # $(CXX)
|
||||
|
||||
@@ -413,7 +429,7 @@ $(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence.
|
||||
# and pid namespaces) in which to run, should be added to
|
||||
# tests-container.
|
||||
$(tests-container:%=$(objpfx)%.out): $(objpfx)%.out : $(if $(wildcard $(objpfx)%.files),$(objpfx)%.files,/dev/null) $(objpfx)%
|
||||
$(test-wrapper-env) $(run-program-env) $(test-via-rtld-prefix) \
|
||||
$(test-wrapper-env) $(run-program-env) $(test-container-via-rtld-prefix) \
|
||||
$(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) $(test-tunables) \
|
||||
$(host-test-program-cmd) $($*-ARGS) > $@; \
|
||||
$(evaluate-test)
|
||||
@@ -451,8 +467,9 @@ py-env := PYTHONPATH=$(py-const-dir):$(..)scripts:$${PYTHONPATH}
|
||||
# The pretty printer files and test_common_printers.py must be present for all.
|
||||
$(tests-printers-out): $(objpfx)%.out: $(objpfx)% %.py %.c $(pretty-printers) \
|
||||
$(..)scripts/test_printers_common.py
|
||||
$(test-wrapper-env) $(py-env) \
|
||||
$(PYTHON) $*.py $*.c $(objpfx)$* $(pretty-printers) > $@; \
|
||||
$(test-wrapper-env) $(py-env) sh -c \
|
||||
'command -v $(firstword $(PYTHON)) > /dev/null 2>&1 || exit 77; \
|
||||
exec $(PYTHON) $*.py $*.c $(objpfx)$* $(pretty-printers)' > $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ core-math:
|
||||
sysdeps/ieee754/dbl-64/s_erf.c
|
||||
# src/binary64/erfc/erfc.c, revision 55e9869e
|
||||
sysdeps/ieee754/dbl-64/s_erfc.c
|
||||
# src/binary64/tanh/tanh.c, revision 8ea8ea35
|
||||
# src/binary64/tanh/tanh.c, revision cf237fa0
|
||||
sysdeps/ieee754/dbl-64/s_tanh.c
|
||||
# src/binary32/acos/acosf.c, revision 56dd347
|
||||
sysdeps/ieee754/flt-32/e_acosf.c
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
printf: incorrect output for integers with thousands separator and width field
|
||||
|
||||
When the printf family of functions is called with a format specifier
|
||||
that uses an <apostrophe> (enable grouping) and a minimum width
|
||||
specifier, the resulting output could be larger than reasonably expected
|
||||
by a caller that computed a tight bound on the buffer size. The
|
||||
resulting larger than expected output could result in a buffer overflow
|
||||
in the printf family of functions.
|
||||
|
||||
CVE-Id: CVE-2023-25139
|
||||
Public-Date: 2023-02-02
|
||||
Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37)
|
||||
Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38)
|
||||
Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4)
|
||||
@@ -1,15 +0,0 @@
|
||||
getaddrinfo: Stack read overflow in no-aaaa mode
|
||||
|
||||
If the system is configured in no-aaaa mode via /etc/resolv.conf,
|
||||
getaddrinfo is called for the AF_UNSPEC address family, and a DNS
|
||||
response is received over TCP that is larger than 2048 bytes,
|
||||
getaddrinfo may potentially disclose stack contents via the returned
|
||||
address data, or crash.
|
||||
|
||||
CVE-Id: CVE-2023-4527
|
||||
Public-Date: 2023-09-12
|
||||
Vulnerable-Commit: f282cdbe7f436c75864e5640a409a10485e9abb2 (2.36)
|
||||
Fix-Commit: bd77dd7e73e3530203be1c52c8a29d08270cb25d (2.39)
|
||||
Fix-Commit: 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f (2.36-113)
|
||||
Fix-Commit: b7529346025a130fee483d42178b5c118da971bb (2.37-38)
|
||||
Fix-Commit: b25508dd774b617f99419bdc3cf2ace4560cd2d6 (2.38-19)
|
||||
@@ -1,15 +0,0 @@
|
||||
getaddrinfo: Potential use-after-free
|
||||
|
||||
When an NSS plugin only implements the _gethostbyname2_r and
|
||||
_getcanonname_r callbacks, getaddrinfo could use memory that was freed
|
||||
during buffer resizing, potentially causing a crash or read or write to
|
||||
arbitrary memory.
|
||||
|
||||
CVE-Id: CVE-2023-4806
|
||||
Public-Date: 2023-09-12
|
||||
Fix-Commit: 973fe93a5675c42798b2161c6f29c01b0e243994 (2.39)
|
||||
Fix-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
|
||||
Fix-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
|
||||
Fix-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
|
||||
Fix-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
|
||||
Fix-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
|
||||
@@ -1,16 +0,0 @@
|
||||
tunables: local privilege escalation through buffer overflow
|
||||
|
||||
If a tunable of the form NAME=NAME=VAL is passed in the environment of a
|
||||
setuid program and NAME is valid, it may result in a buffer overflow,
|
||||
which could be exploited to achieve escalated privileges. This flaw was
|
||||
introduced in glibc 2.34.
|
||||
|
||||
CVE-Id: CVE-2023-4911
|
||||
Public-Date: 2023-10-03
|
||||
Vulnerable-Commit: 2ed18c5b534d9e92fc006202a5af0df6b72e7aca (2.34)
|
||||
Fix-Commit: 1056e5b4c3f2d90ed2b4a55f96add28da2f4c8fa (2.39)
|
||||
Fix-Commit: dcc367f148bc92e7f3778a125f7a416b093964d9 (2.34-423)
|
||||
Fix-Commit: c84018a05aec80f5ee6f682db0da1130b0196aef (2.35-274)
|
||||
Fix-Commit: 22955ad85186ee05834e47e665056148ca07699c (2.36-118)
|
||||
Fix-Commit: b4e23c75aea756b4bddc4abcf27a1c6dca8b6bd3 (2.37-45)
|
||||
Fix-Commit: 750a45a783906a19591fb8ff6b7841470f1f5701 (2.38-27)
|
||||
@@ -1,18 +0,0 @@
|
||||
getaddrinfo: DoS due to memory leak
|
||||
|
||||
The fix for CVE-2023-4806 introduced a memory leak when an application
|
||||
calls getaddrinfo for AF_INET6 with AI_CANONNAME, AI_ALL and AI_V4MAPPED
|
||||
flags set.
|
||||
|
||||
CVE-Id: CVE-2023-5156
|
||||
Public-Date: 2023-09-25
|
||||
Vulnerable-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
|
||||
Vulnerable-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
|
||||
Vulnerable-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
|
||||
Vulnerable-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
|
||||
Vulnerable-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
|
||||
Fix-Commit: 8006457ab7e1cd556b919f477348a96fe88f2e49 (2.34-421)
|
||||
Fix-Commit: 17092c0311f954e6f3c010f73ce3a78c24ac279a (2.35-272)
|
||||
Fix-Commit: 856bac55f98dc840e7c27cfa82262b933385de90 (2.36-116)
|
||||
Fix-Commit: 4473d1b87d04b25cdd0e0354814eeaa421328268 (2.37-42)
|
||||
Fix-Commit: 5ee59ca371b99984232d7584fe2b1a758b4421d3 (2.38-24)
|
||||
@@ -1,15 +0,0 @@
|
||||
syslog: Heap buffer overflow in __vsyslog_internal
|
||||
|
||||
__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER
|
||||
containing a long program name failed to update the required buffer
|
||||
size, leading to the allocation and overflow of a too-small buffer on
|
||||
the heap.
|
||||
|
||||
CVE-Id: CVE-2023-6246
|
||||
Public-Date: 2024-01-30
|
||||
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
|
||||
Fix-Commit: 6bd0e4efcc78f3c0115e5ea9739a1642807450da (2.39)
|
||||
Fix-Commit: 23514c72b780f3da097ecf33a793b7ba9c2070d2 (2.38-42)
|
||||
Fix-Commit: 97a4292aa4a2642e251472b878d0ec4c46a0e59a (2.37-57)
|
||||
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
|
||||
Fix-Commit: d1a83b6767f68b3cb5b4b4ea2617254acd040c82 (2.36-126)
|
||||
@@ -1,15 +0,0 @@
|
||||
syslog: Heap buffer overflow in __vsyslog_internal
|
||||
|
||||
__vsyslog_internal used the return value of snprintf/vsnprintf to
|
||||
calculate buffer sizes for memory allocation. If these functions (for
|
||||
any reason) failed and returned -1, the resulting buffer would be too
|
||||
small to hold output.
|
||||
|
||||
CVE-Id: CVE-2023-6779
|
||||
Public-Date: 2024-01-30
|
||||
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
|
||||
Fix-Commit: 7e5a0c286da33159d47d0122007aac016f3e02cd (2.39)
|
||||
Fix-Commit: d0338312aace5bbfef85e03055e1212dd0e49578 (2.38-43)
|
||||
Fix-Commit: 67062eccd9a65d7fda9976a56aeaaf6c25a80214 (2.37-58)
|
||||
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
|
||||
Fix-Commit: 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 (2.36-127)
|
||||
@@ -1,13 +0,0 @@
|
||||
syslog: Integer overflow in __vsyslog_internal
|
||||
|
||||
__vsyslog_internal calculated a buffer size by adding two integers, but
|
||||
did not first check if the addition would overflow.
|
||||
|
||||
CVE-Id: CVE-2023-6780
|
||||
Public-Date: 2024-01-30
|
||||
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
|
||||
Fix-Commit: ddf542da94caf97ff43cc2875c88749880b7259b (2.39)
|
||||
Fix-Commit: d37c2b20a4787463d192b32041c3406c2bd91de0 (2.38-44)
|
||||
Fix-Commit: 2b58cba076e912961ceaa5fa58588e4b10f791c0 (2.37-59)
|
||||
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
|
||||
Fix-Commit: b9b7d6a27aa0632f334352fa400771115b3c69b7 (2.36-128)
|
||||
@@ -1,28 +0,0 @@
|
||||
ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence
|
||||
|
||||
The iconv() function in the GNU C Library versions 2.39 and older may
|
||||
overflow the output buffer passed to it by up to 4 bytes when converting
|
||||
strings to the ISO-2022-CN-EXT character set, which may be used to
|
||||
crash an application or overwrite a neighbouring variable.
|
||||
|
||||
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
|
||||
(as specified by RFC 1922). While the SOdesignation has the expected
|
||||
bounds checks, neither SS2designation nor SS3designation have its;
|
||||
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
|
||||
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
|
||||
|
||||
CVE-Id: CVE-2024-2961
|
||||
Public-Date: 2024-04-17
|
||||
Vulnerable-Commit: 755104edc75c53f4a0e7440334e944ad3c6b32fc (2.1.93-169)
|
||||
Fix-Commit: f9dc609e06b1136bb0408be9605ce7973a767ada (2.40)
|
||||
Fix-Commit: 31da30f23cddd36db29d5b6a1c7619361b271fb4 (2.39-31)
|
||||
Fix-Commit: e1135387deded5d73924f6ca20c72a35dc8e1bda (2.38-66)
|
||||
Fix-Commit: 89ce64b269a897a7780e4c73a7412016381c6ecf (2.37-89)
|
||||
Fix-Commit: 4ed98540a7fd19f458287e783ae59c41e64df7b5 (2.36-164)
|
||||
Fix-Commit: 36280d1ce5e245aabefb877fe4d3c6cff95dabfa (2.35-315)
|
||||
Fix-Commit: a8b0561db4b9847ebfbfec20075697d5492a363c (2.34-459)
|
||||
Fix-Commit: ed4f16ff6bed3037266f1fa682ebd32a18fce29c (2.33-263)
|
||||
Fix-Commit: 682ad4c8623e611a971839990ceef00346289cc9 (2.32-140)
|
||||
Fix-Commit: 3703c32a8d304c1ee12126134ce69be965f38000 (2.31-154)
|
||||
|
||||
Reported-By: Charles Fol
|
||||
@@ -1,22 +0,0 @@
|
||||
nscd: Stack-based buffer overflow in netgroup cache
|
||||
|
||||
If the Name Service Cache Daemon's (nscd) fixed size cache is exhausted
|
||||
by client requests then a subsequent client request for netgroup data
|
||||
may result in a stack-based buffer overflow. This flaw was introduced
|
||||
in glibc 2.15 when the cache was added to nscd.
|
||||
|
||||
This vulnerability is only present in the nscd binary.
|
||||
|
||||
CVE-Id: CVE-2024-33599
|
||||
Public-Date: 2024-04-23
|
||||
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
|
||||
Fix-Commit: 69c58d5ef9f584ea198bd00f7964d364d0e6b921 (2.31-155)
|
||||
Fix-Commit: a77064893bfe8a701770e2f53a4d33805bc47a5a (2.32-141)
|
||||
Fix-Commit: 5c75001a96abcd50cbdb74df24c3f013188d076e (2.33-264)
|
||||
Fix-Commit: 52f73e5c4e29b14e79167272297977f360ae1e97 (2.34-460)
|
||||
Fix-Commit: 7a95873543ce225376faf13bb71c43dea6d24f86 (2.35-316)
|
||||
Fix-Commit: caa3151ca460bdd9330adeedd68c3112d97bffe4 (2.36-165)
|
||||
Fix-Commit: f75c298e747b2b8b41b1c2f551c011a52c41bfd1 (2.37-91)
|
||||
Fix-Commit: 5968aebb86164034b8f8421b4abab2f837a5bdaf (2.38-72)
|
||||
Fix-Commit: 1263d583d2e28afb8be53f8d6922f0842036f35d (2.39-35)
|
||||
Fix-Commit: 87801a8fd06db1d654eea3e4f7626ff476a9bdaa (2.40)
|
||||
@@ -1,32 +0,0 @@
|
||||
nscd: Null pointer crash after notfound response
|
||||
|
||||
If the Name Service Cache Daemon's (nscd) cache fails to add a not-found
|
||||
netgroup response to the cache, the client request can result in a null
|
||||
pointer dereference. This flaw was introduced in glibc 2.15 when the
|
||||
cache was added to nscd.
|
||||
|
||||
This vulnerability is only present in the nscd binary.
|
||||
|
||||
CVE-Id: CVE-2024-33600
|
||||
Public-Date: 2024-04-24
|
||||
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
|
||||
Fix-Commit: b048a482f088e53144d26a61c390bed0210f49f2 (2.40)
|
||||
Fix-Commit: 7835b00dbce53c3c87bbbb1754a95fb5e58187aa (2.40)
|
||||
Fix-Commit: c99f886de54446cd4447db6b44be93dabbdc2f8b (2.39-37)
|
||||
Fix-Commit: 5a508e0b508c8ad53bd0d2fb48fd71b242626341 (2.39-36)
|
||||
Fix-Commit: 2ae9446c1b7a3064743b4a51c0bbae668ee43e4c (2.38-74)
|
||||
Fix-Commit: 541ea5172aa658c4bd5c6c6d6fd13903c3d5bb0a (2.38-73)
|
||||
Fix-Commit: a8070b31043c7585c36ba68a74298c4f7af075c3 (2.37-93)
|
||||
Fix-Commit: 5eea50c4402e39588de98aa1d4469a79774703d4 (2.37-92)
|
||||
Fix-Commit: f205b3af56740e3b014915b1bd3b162afe3407ef (2.36-167)
|
||||
Fix-Commit: c34f470a615b136170abd16142da5dd0c024f7d1 (2.36-166)
|
||||
Fix-Commit: bafadc589fbe21ae330e8c2af74db9da44a17660 (2.35-318)
|
||||
Fix-Commit: 4370bef52b0f3f3652c6aa13d7a9bb3ac079746d (2.35-317)
|
||||
Fix-Commit: 1f94122289a9bf7dba573f5d60327aaa2b85cf2e (2.34-462)
|
||||
Fix-Commit: 966d6ac9e40222b84bb21674cc4f83c8d72a5a26 (2.34-461)
|
||||
Fix-Commit: e3eef1b8fbdd3a7917af466ca9c4b7477251ca79 (2.33-266)
|
||||
Fix-Commit: f20a8d696b13c6261b52a6434899121f8b19d5a7 (2.33-265)
|
||||
Fix-Commit: be602180146de37582a3da3a0caa4b719645de9c (2.32-143)
|
||||
Fix-Commit: 394eae338199078b7961b051c191539870742d7b (2.32-142)
|
||||
Fix-Commit: 8d7949183760170c61e55def723c1d8050187874 (2.31-157)
|
||||
Fix-Commit: 304ce5fe466c4762b21b36c26926a4657b59b53e (2.31-156)
|
||||
@@ -1,28 +0,0 @@
|
||||
nscd: netgroup cache may terminate daemon on memory allocation failure
|
||||
|
||||
The Name Service Cache Daemon's (nscd) netgroup cache uses xmalloc or
|
||||
xrealloc and these functions may terminate the process due to a memory
|
||||
allocation failure resulting in a denial of service to the clients. The
|
||||
flaw was introduced in glibc 2.15 when the cache was added to nscd.
|
||||
|
||||
This vulnerability is only present in the nscd binary.
|
||||
|
||||
Subsequent refactoring of the netgroup cache only added more uses of
|
||||
xmalloc and xrealloc. Uses of xmalloc and xrealloc in other parts of
|
||||
nscd only occur during startup of the daemon and so are not affected by
|
||||
client requests that could trigger an out of memory followed by
|
||||
termination.
|
||||
|
||||
CVE-Id: CVE-2024-33601
|
||||
Public-Date: 2024-04-24
|
||||
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
|
||||
Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40)
|
||||
Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38)
|
||||
Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75)
|
||||
Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94)
|
||||
Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168)
|
||||
Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319)
|
||||
Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463)
|
||||
Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267)
|
||||
Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144)
|
||||
Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158)
|
||||
@@ -1,26 +0,0 @@
|
||||
nscd: netgroup cache assumes NSS callback uses in-buffer strings
|
||||
|
||||
The Name Service Cache Daemon's (nscd) netgroup cache can corrupt memory
|
||||
when the NSS callback does not store all strings in the provided buffer.
|
||||
The flaw was introduced in glibc 2.15 when the cache was added to nscd.
|
||||
|
||||
This vulnerability is only present in the nscd binary.
|
||||
|
||||
There is no guarantee from the NSS callback API that the returned
|
||||
strings are all within the buffer. However, the netgroup cache code
|
||||
assumes that the NSS callback uses in-buffer strings and if it doesn't
|
||||
the buffer resizing logic could lead to potential memory corruption.
|
||||
|
||||
CVE-Id: CVE-2024-33602
|
||||
Public-Date: 2024-04-24
|
||||
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
|
||||
Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40)
|
||||
Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38)
|
||||
Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75)
|
||||
Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94)
|
||||
Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168)
|
||||
Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319)
|
||||
Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463)
|
||||
Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267)
|
||||
Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144)
|
||||
Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158)
|
||||
@@ -1,40 +0,0 @@
|
||||
assert: Buffer overflow when printing assertion failure message
|
||||
|
||||
When the assert() function fails, it does not allocate enough space for the
|
||||
assertion failure message string and size information, which may lead to a
|
||||
buffer overflow if the message string size aligns to page size.
|
||||
|
||||
This bug can be triggered when an assertion in a program fails. The assertion
|
||||
failure message is allocated to allow developers to see this failure in core
|
||||
dumps and it typically includes, in addition to the invariant assertion
|
||||
string and function name, the name of the program. If the name of the failing
|
||||
program is user controlled, for example on a local system, this could allow an
|
||||
attacker to control the assertion failure to trigger this buffer overflow.
|
||||
|
||||
The only viable vector for exploitation of this bug is local, if a setuid
|
||||
program exists that has an existing bug that results in an assertion failure.
|
||||
No such program has been discovered at the time of publishing this advisory,
|
||||
but the presence of custom setuid programs, although strongly discouraged as a
|
||||
security practice, cannot be discounted.
|
||||
|
||||
CVE-Id: CVE-2025-0395
|
||||
Public-Date: 2025-01-22
|
||||
Vulnerable-Commit: f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 (2.13-175)
|
||||
Fix-Commit: 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578 (2.41)
|
||||
Fix-Commit: cdb9ba84191ce72e86346fb8b1d906e7cd930ea2 (2.42)
|
||||
Fix-Commit: 69fda28279b497bd405fdd442a6d8e4d3d5f681b (2.41-7)
|
||||
Fix-Commit: 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c (2.40-66)
|
||||
Fix-Commit: d6c156c326999f144cb5b73d29982108d549ad8a (2.40-71)
|
||||
Fix-Commit: 808a84a8b81468b517a4d721fdc62069cb8c211f (2.39-146)
|
||||
Fix-Commit: f6d48470aef9264d2d56f4c4533eb76db7f9c2e4 (2.39-150)
|
||||
Fix-Commit: c32fd59314c343db88c3ea4a203870481d33c3d2 (2.38-122)
|
||||
Fix-Commit: f984e2d7e8299726891a1a497a3c36cd5542a0bf (2.38-124)
|
||||
Fix-Commit: a3d7865b098a3a67c44f7812208d9ce4718873ba (2.37-143)
|
||||
Fix-Commit: b989519fe1683c204ac24ec92830e3fe3bfaccad (2.37-146)
|
||||
Fix-Commit: 7971add7ee4171fdd8dfd17e7c04c4ed77a18845 (2.36-216)
|
||||
Fix-Commit: 0487893d5c5bc6710d83d7c3152d888a0339559e (2.36-219)
|
||||
Fix-Commit: 8b5d4be762419c4f6176261c6fea40ac559b88dc (2.35-370)
|
||||
Fix-Commit: 8b3d09dc0d350191985f9d291cc30ce96f034b49 (2.35-373)
|
||||
Fix-Commit: df4e1f4a5096b385c9bcc94424cf2eaa227b3761 (2.34-500)
|
||||
Fix-Commit: 31eb872cb21449832ab47ad5db83281d240e1d03 (2.34-503)
|
||||
Reported-By: Qualys Security Advisory
|
||||
@@ -1,23 +0,0 @@
|
||||
elf: static setuid binary dlopen may incorrectly search LD_LIBRARY_PATH
|
||||
|
||||
A statically linked setuid binary that calls dlopen (including internal
|
||||
dlopen calls after setlocale or calls to NSS functions such as getaddrinfo)
|
||||
may incorrectly search LD_LIBRARY_PATH to determine which library to load,
|
||||
leading to the execution of library code that is attacker controlled.
|
||||
|
||||
The only viable vector for exploitation of this bug is local, if a static
|
||||
setuid program exists, and that program calls dlopen, then it may search
|
||||
LD_LIBRARY_PATH to locate the SONAME to load. No such program has been
|
||||
discovered at the time of publishing this advisory, but the presence of
|
||||
custom setuid programs, although strongly discouraged as a security
|
||||
practice, cannot be discounted.
|
||||
|
||||
CVE-Id: CVE-2025-4802
|
||||
Public-Date: 2025-05-16
|
||||
Vulnerable-Commit: 10e93d968716ab82931d593bada121c17c0a4b93 (2.27)
|
||||
Fix-Commit: 5451fa962cd0a90a0e2ec1d8910a559ace02bba0 (2.39)
|
||||
Fix-Commit: 3be3728df2f1912c80abd3288bc6e3a25ad679e4 (2.38-132)
|
||||
Fix-Commit: 7403ede2d7752e59e0c47d5d33d73c2bf850e7be (2.37-154)
|
||||
Fix-Commit: 2ef7850279b2931caf6d6d6743ebaa91839e1cf7 (2.36-227)
|
||||
Fix-Commit: 621c65ccf12ddd415ceeb2234423bd1acd0fabb3 (2.35-387)
|
||||
Fix-Commit: 35018c0fd20eac9ceaf60060fed2745b3177359d (2.34-517)
|
||||
@@ -1,30 +0,0 @@
|
||||
power10: strcmp fails to save and restore nonvolatile vector registers
|
||||
|
||||
The Power 10 implementation of strcmp in
|
||||
sysdeps/powerpc/powerpc64/le/power10/strcmp.S failed to save/restore
|
||||
nonvolatile vector registers in the 32-byte aligned loop path. This
|
||||
results in callers reading content from those registers in a different
|
||||
context, potentially altering program logic.
|
||||
|
||||
There could be a program context where a user controlled string could
|
||||
leak through strcmp into program code, thus altering its logic. There
|
||||
is also a potential for sensitive strings passed into strcmp leaking
|
||||
through the clobbered registers into parts of the calling program that
|
||||
should otherwise not have had access to those strings.
|
||||
|
||||
The impact of this flaw is limited to applications running on Power 10
|
||||
hardware that use the nonvolatile vector registers, i.e. v20 to v31
|
||||
assuming that they have been treated in accordance with the OpenPower
|
||||
psABI. It is possible to work around the issue for those specific
|
||||
applications by setting the glibc.cpu.hwcaps tunable to "-arch_3_1" like
|
||||
so:
|
||||
|
||||
export GLIBC_TUNABLES=glibc.cpu.hwcaps=-arch_3_1
|
||||
|
||||
CVE-Id: CVE-2025-5702
|
||||
Public-Date: 2025-06-04
|
||||
Vulnerable-Commit: 3367d8e180848030d1646f088759f02b8dfe0d6f (2.39)
|
||||
Fix-Commit: 15808c77b35319e67ee0dc8f984a9a1a434701bc (2.42)
|
||||
Fix-Commit: 0c76c951620f9e12df2a89b2c684878b55bb6795 (2.41-60)
|
||||
Fix-Commit: 7e12550b8e3a11764a4a9090ce6bd3fc23fc8a8e (2.40-139)
|
||||
Fix-Commit: 06a70769fd0b2e1f2a3085ad50ab620282bd77b3 (2.39-209)
|
||||
@@ -1,29 +0,0 @@
|
||||
power10: strncmp fails to save and restore nonvolatile vector registers
|
||||
|
||||
The Power 10 implementation of strncmp in
|
||||
sysdeps/powerpc/powerpc64/le/power10/strncmp.S failed to save/restore
|
||||
nonvolatile vector registers in the 32-byte aligned loop path. This
|
||||
results in callers reading content from those registers in a different
|
||||
context, potentially altering program logic.
|
||||
|
||||
There could be a program context where a user controlled string could
|
||||
leak through strncmp into program code, thus altering its logic. There
|
||||
is also a potential for sensitive strings passed into strncmp leaking
|
||||
through the clobbered registers into parts of the calling program that
|
||||
should otherwise not have had access to those strings.
|
||||
|
||||
The impact of this flaw is limited to applications running on Power 10
|
||||
hardware that use the nonvolatile vector registers, i.e. v20 to v31
|
||||
assuming that they have been treated in accordance with the OpenPower
|
||||
psABI. It is possible to work around the issue for those specific
|
||||
applications by setting the glibc.cpu.hwcaps tunable to "-arch_3_1" like
|
||||
so:
|
||||
|
||||
export GLIBC_TUNABLES=glibc.cpu.hwcaps=-arch_3_1
|
||||
|
||||
CVE-Id: CVE-2025-5745
|
||||
Public-Date: 2025-06-05
|
||||
Vulnerable-Commit: 23f0d81608d0ca6379894ef81670cf30af7fd081 (2.40)
|
||||
Fix-Commit: 63c60101ce7c5eac42be90f698ba02099b41b965 (2.42)
|
||||
Fix-Commit: 84bdbf8a6f2fdafd3661489dbb7f79835a52da82 (2.41-57)
|
||||
Fix-Commit: 42a5a940c974d02540c8da26d6374c744d148cb9 (2.40-136)
|
||||
@@ -1,14 +0,0 @@
|
||||
posix: Fix double-free after allocation failure in regcomp
|
||||
|
||||
The regcomp function in the GNU C library version from 2.4 to 2.41 is
|
||||
subject to a double free if some previous allocation fails. It can be
|
||||
accomplished either by a malloc failure or by using an interposed
|
||||
malloc that injects random malloc failures. The double free can allow
|
||||
buffer manipulation depending of how the regex is constructed.
|
||||
This issue affects all architectures and ABIs supported by the GNU C
|
||||
library.
|
||||
|
||||
CVE-Id: CVE-2025-8058
|
||||
Public-Date: 2025-07-22
|
||||
Vulnerable-Commit: 963d8d782fc98fb6dc3a66f0068795f9920c269d (2.3.3-1596)
|
||||
Fix-Commit: 7ea06e994093fa0bcca0d0ee2c1db271d8d7885d (2.42)
|
||||
@@ -1,41 +0,0 @@
|
||||
Integer overflow in memalign leads to heap corruption
|
||||
|
||||
Passing too large an alignment to the memalign suite of functions
|
||||
(memalign, posix_memalign, aligned_alloc) in the GNU C Library version
|
||||
2.30 to 2.42 may result in an integer overflow, which could consequently
|
||||
result in a heap corruption.
|
||||
|
||||
Note that the attacker must have control over both, the size as well as
|
||||
the alignment arguments of the memalign function to be able to exploit
|
||||
this. The size parameter must be close enough to PTRDIFF_MAX so as to
|
||||
overflow size_t along with the large alignment argument. This limits
|
||||
the malicious inputs for the alignment for memalign to the range [1<<62
|
||||
+ 1, 1<<63] and exactly 1<<63 for posix_memalign and aligned_alloc.
|
||||
|
||||
Typically the alignment argument passed to such functions is a known
|
||||
constrained quantity (e.g. page size, block size, struct sizes) and is
|
||||
not attacker controlled, because of which this may not be easily
|
||||
exploitable in practice. An application bug could potentially result in
|
||||
the input alignment being too large, e.g. due to a different buffer
|
||||
overflow or integer overflow in the application or its dependent
|
||||
libraries, but that is again an uncommon usage pattern given typical
|
||||
sources of alignments.
|
||||
|
||||
CVE-Id: CVE-2026-0861
|
||||
Public-Date: 2026-01-14
|
||||
Vulnerable-Commit: 9bf8e29ca136094f73f69f725f15c51facc97206 (2.30)
|
||||
Fix-Commit: c9188d333717d3ceb7e3020011651f424f749f93 (2.43)
|
||||
Fix-Commit: 7f19ef14fbce095d4c77395e258320cad2ea2b28 (2.30-153)
|
||||
Fix-Commit: f18446d7b4a423090ee5e328c36b3c2a0f26041c (2.31-166)
|
||||
Fix-Commit: 8aef9e7a7af9565c0324b4ecb38b30dfa3782fd8 (2.32-151)
|
||||
Fix-Commit: 011293b4fd748cdd6f95874ba2b6aba9a3df8bff (2.33-275)
|
||||
Fix-Commit: 2c77e52108a58956c9f674b36e1f59a4e3fdcf4d (2.34-525)
|
||||
Fix-Commit: 499d1ccafccfe64df1b88deea2fa84d8180e8e8f (2.35-399)
|
||||
Fix-Commit: fb6b8822175769b5794fb6ea04f2895483a29b61 (2.36-244)
|
||||
Fix-Commit: 7b913d41a07836def826f2164c52541a9835f324 (2.37-172)
|
||||
Fix-Commit: 744b63026a29f7eedbbc8e3a01a7f48a6eb0a085 (2.38-212)
|
||||
Fix-Commit: fb22fd3f5b415dd4cd6f7b5741c2f0412374e242 (2.39-286)
|
||||
Fix-Commit: bfc4dd9e526eacf3017dd8864ba0848e9d045dd4 (2.40-216)
|
||||
Fix-Commit: 1e2c1ea4307197ccece0cda574bcfebf9080894c (2.41-121)
|
||||
Fix-Commit: b0ec8fb689df862171f0f78994a3bdeb51313545 (2.42-49)
|
||||
Reported-by: Igor Morgenstern, Aisle Research
|
||||
@@ -1,36 +0,0 @@
|
||||
getnetbyaddr and getnetbyaddr_r leak stack contents to DNS resovler
|
||||
|
||||
Calling getnetbyaddr or getnetbyaddr_r with a configured nsswitch.conf
|
||||
that specifies the library's DNS backend for networks and queries for a
|
||||
zero-valued network in the GNU C Library version 2.0 to version 2.42
|
||||
can leak stack contents to the configured DNS resolver.
|
||||
|
||||
A defect in the _nss_dns_getnetbyaddr_r function which implements
|
||||
getnetbyaddr and getnetbyaddr_r in the dns-based network database can
|
||||
pass stack contents unmodified to the configured DNS resolver as part of
|
||||
the network DNS query when the network queried is the default network
|
||||
i.e. net == 0x0. This stack contents leaking in the query is considered
|
||||
a loss of confidentiality for the host making the query. Typically it
|
||||
is rare to call these APIs with a net value of zero, and if an attacker
|
||||
can control the net value it can only leak adjacent stack, and so loss
|
||||
of confidentiality is spatially limited. The leak might be used to
|
||||
accelerate an ASLR bypass by knowing pointer values, but also requires
|
||||
network adjacent access to snoop between the application and the
|
||||
DNS server; making the attack complexity higher.
|
||||
|
||||
CVE-Id: CVE-2026-0915
|
||||
Public-Date: 2026-01-15
|
||||
Vulnerable-Commit: 5f0e6fc702296840d2daa39f83f6cb1e40073d58 (1.92-1)
|
||||
Fix-Commit: e56ff82d5034ec66c6a78f517af6faa427f65b0b (2.43)
|
||||
Fix-Commit: 453e6b8dbab935257eb0802b0c97bca6b67ba30e (2.42-50)
|
||||
Fix-Commit: 15c9839a0b853f552b4ed9047841b6223f3c104d (2.41-122)
|
||||
Fix-Commit: 329c775788b2c9ff3da774ccf59fba7b6b8ff08e (2.40-217)
|
||||
Fix-Commit: 831f63b94ceb92fb14c0d1a7ddad35a0d1404c71 (2.39-287)
|
||||
Fix-Commit: 49125ffc8e1674dc2a100dfdc5b78796f22e16f2 (2.38-213)
|
||||
Fix-Commit: ddcaed5dfb05b2c1a6ea842fd6b643501365450a (2.37-173)
|
||||
Fix-Commit: a6bf47887f24b2b394acb301a3189fda04bd4d4d (2.36-245)
|
||||
Fix-Commit: 66f0cb057c9b4fb1249a5fec6ef4a63511a37899 (2.35-400)
|
||||
Fix-Commit: 96863dee262225cfb79f9fe45e06fd188319c7b8 (2.34-526)
|
||||
Fix-Commit: d210011f1536c8322157cbb4fe4229b35c834c08 (2.33-276)
|
||||
Fix-Commit: 1bc1832cfc74c2a601220969f36e789a5e9f0ebe (2.32-152)
|
||||
Reported-by: Igor Morgenstern, Aisle Research
|
||||
@@ -1,36 +0,0 @@
|
||||
wordexp with WRDE_REUSE and WRDE_APPEND may return uninitialized memory
|
||||
|
||||
Calling wordexp with WRDE_REUSE in conjunction with WRDE_APPEND in the
|
||||
GNU C Library version 2.0 to version 2.42 may cause the interface to
|
||||
return uninitialized memory in the we_wordv member, which on subsequent
|
||||
calls to wordfree may abort the process.
|
||||
|
||||
The implementation of WRDE_REUSE in conjunction with WRDE_APPEND fails
|
||||
to clear the we_wordc member of the structure, and as such, when new
|
||||
words are added internally, a leading we_wordc count number of entries
|
||||
are skipped since they are assumed initialized. These skipped entries
|
||||
are not initialized, but are the contents of a realloc-expanded array of
|
||||
pointers. If the caller inspects the we_wordv array, it will
|
||||
dereference invalid pointers and crash. If the caller calls wordfree,
|
||||
the malloc implementation may detect the invalid pointers and abort the
|
||||
process. Calls to wordexp using WRDE_REUSE and WRDE_APPEND have never
|
||||
worked correctly and thus the existence of applications that make use of
|
||||
this feature is unlikely.
|
||||
|
||||
CVE-Id: CVE-2025-15281
|
||||
Public-Date: 2026-01-20
|
||||
Vulnerable-Commit: 8f2ece695d8822e9ecc63ecd157e90bf17a6fe65 (1.93-260)
|
||||
Fix-Commit: 80cc58ea2de214f85b0a1d902a3b668ad2ecb302 (2.43)
|
||||
Fix-Commit: cbf39c26b25801e9bc88499b4fd361ac172d4125 (2.42-51)
|
||||
Fix-Commit: fb4db64a04ad6c96cd1fbb7e02eb59323b1f2ac2 (2.41-123)
|
||||
Fix-Commit: 9fe8576664d43b87ca19401fb6a975e217e47623 (2.40-218)
|
||||
Fix-Commit: ce65d944e38a20cb70af2a48a4b8aa5d8fabe1cc (2.39-288)
|
||||
Fix-Commit: d5409a1be010699794264162c551ba60f05ee6c3 (2.38-214)
|
||||
Fix-Commit: ff2b172803f6bbd897755d2ce83ec4323a1a15b3 (2.37-174)
|
||||
Fix-Commit: e97cfe2293ed097eb3d0b4c18274d22855e65130 (2.36-246)
|
||||
Fix-Commit: bb59339d02faebac534a87eea50c83c948f35b77 (2.35-401)
|
||||
Fix-Commit: 2b656ff94d72f93c84d8da2e7c76456c1994f02e (2.34-527)
|
||||
Fix-Commit: 1d8ed2067a8a5d162a07670d0d063429679f17a0 (2.33-277)
|
||||
Fix-Commit: 3a56c4ee4ea49b8f2391a2d8d6220013c4160a79 (2.32-153)
|
||||
Fix-Commit: 28eb5caf895ced5d895cb02757e109004a2d33e5 (2.31-167)
|
||||
Reported-by: Vitaly Simonovich
|
||||
@@ -1,30 +0,0 @@
|
||||
nscd client crash on x86_64 under high nscd load
|
||||
|
||||
Calling NSS-backed functions that support caching via nscd may call the
|
||||
nscd client side code and in the GNU C Library version 2.36 under high
|
||||
load on x86_64 systems, the client may call memcmp on inputs that are
|
||||
concurrently modified by other processes or threads and crash.
|
||||
|
||||
The nscd client in the GNU C Library uses the memcmp function with
|
||||
inputs that may be concurrently modified by another thread, potentially
|
||||
resulting in spurious cache misses, which in itself is not a security
|
||||
issue. However in the GNU C Library version 2.36 an optimized
|
||||
implementation of memcmp was introduced for x86_64 which could crash
|
||||
when invoked with such undefined behaviour, turning this into a
|
||||
potential crash of the nscd client and the application that uses it.
|
||||
This implementation was backported to the 2.35 branch, making the nscd
|
||||
client in that branch vulnerable as well. Subsequently, the fix for
|
||||
this issue was backported to all vulnerable branches in the GNU C
|
||||
Library repository.
|
||||
|
||||
It is advised that distributions that may have cherry-picked the memcpy
|
||||
SSE2 optimization in their copy of the GNU C Library, also apply the fix
|
||||
to avoid the potential crash in the nscd client.
|
||||
|
||||
CVE-Id: CVE-2026-3904
|
||||
Public-Date: 2026-03-11
|
||||
Vulnerable-Commit: 8804157ad9da39631703b92315460808eac86b0c (2.36)
|
||||
Vulnerable-Commit: 5a8df6485c584e2b0e957ec6b9070437a724911a (2.35-89)
|
||||
Fix-Commit: b712be52645282c706a5faa038242504feb06db5 (2.37)
|
||||
Fix-Commit: 93967a2a7bbdcedb73e0b246713580c7c84d001e (2.36-84)
|
||||
Fix-Commit: 6bcd5d8e3668d52388a6e0580611749f93e6871f (2.35-230)
|
||||
@@ -1,37 +0,0 @@
|
||||
gethostbyaddr and gethostbyaddr_r may incorrectly handle DNS response
|
||||
|
||||
Calling gethostbyaddr or gethostbyaddr_r with a configured nsswitch.conf
|
||||
that specifies the library's DNS backend in the GNU C Library version
|
||||
2.34 to version 2.43 could, with a crafted response from the configured
|
||||
DNS server, result in a violation of the DNS specification that causes
|
||||
the application to treat a non-answer section of the DNS response as a
|
||||
valid answer.
|
||||
|
||||
A defect in the getanswer_ptr function, which implements the iteration
|
||||
and extraction of the answer from the DNS response, can cause it to
|
||||
incorrectly transition from the answer section to the next section while
|
||||
still treating it as an answer to the question. This can happen when
|
||||
the answer contains only skipped records, and the subsequent section
|
||||
contains a semantically invalid T_PTR record. This is considered a
|
||||
security issue because it is a violation of the DNS specification that
|
||||
leads to incorrect behaviour that could result in the wrong hostname
|
||||
being returned to the caller. At the time of publication, no known
|
||||
affected DNS server returns results that would be incorrectly
|
||||
interpreted by the library. An attacker would either need to be network
|
||||
adjacent or have compromised the DNS server to use this defect to hide
|
||||
returned reverse DNS results from intrusion detection systems. Even
|
||||
then, the inbound connection from the attacker, or the outbound
|
||||
connection from the application, would be visible to the intrusion
|
||||
detection system. At best, the defect can be used to obfuscate and
|
||||
delay analysis of the evolving threat.
|
||||
|
||||
CVE-Id: CVE-2026-4437
|
||||
Public-Date: 2026-03-20
|
||||
Vulnerable-Commit: 32e5db37684ffcbc6ae34fcc6cdcf28670506baa (2.34-323)
|
||||
Vulnerable-Commit: def97e7f71a07517810f7263213d607e08ad21f1 (2.35-188)
|
||||
Vulnerable-Commit: 77f523c473878ec0051582ef15161c6982879095 (2.36-30)
|
||||
Vulnerable-Commit: e32547d661a43da63368e488b6cfa9c53b4dcf92 (2.37)
|
||||
Fix-Commit: 5c6fca0c62ce5bd6e68e259f138097756cbafd4d (2.43-16)
|
||||
Fix-Commit: 9f5f18aab40ec6b61fa49a007615e6077e9a979b (2.44)
|
||||
Reported-by: Antonio Maini (0rbitingZer0) - 0rbitingZer0@proton.me
|
||||
Reported-by: Kevin Farrell
|
||||
@@ -1,27 +0,0 @@
|
||||
gethostbyaddr and gethostbyaddr_r return invalid DNS hostnames
|
||||
|
||||
Calling gethostbyaddr or gethostbyaddr_r with a configured nsswitch.conf
|
||||
that specifies the library's DNS backend in the GNU C library version
|
||||
2.34 to version 2.43 could result in an invalid DNS hostname being
|
||||
returned to the caller in violation of the DNS specification.
|
||||
|
||||
A defect in the getanswer_ptr function, which implements the iteration
|
||||
and extraction of the answer from a DNS response, can cause it to accept
|
||||
an invalid DNS hostname that can contain shell metacharacters. An
|
||||
application that uses the returned hostname in a shell, without guarding
|
||||
for shell expansion, may be subject to shell injection attacks. At the
|
||||
time of publication, no known affected DNS server returns results with
|
||||
shell metacharacters in the results. An attacker would either need to
|
||||
be network adjacent or have compromised the DNS server to use this
|
||||
defect for shell injection. No known vulnerable application has been
|
||||
identified.
|
||||
|
||||
CVE-Id: CVE-2026-4438
|
||||
Public-Date: 2026-03-20
|
||||
Vulnerable-Commit: 32e5db37684ffcbc6ae34fcc6cdcf28670506baa (2.34-323)
|
||||
Vulnerable-Commit: def97e7f71a07517810f7263213d607e08ad21f1 (2.35-188)
|
||||
Vulnerable-Commit: 77f523c473878ec0051582ef15161c6982879095 (2.36-30)
|
||||
Vulnerable-Commit: e32547d661a43da63368e488b6cfa9c53b4dcf92 (2.37)
|
||||
Fix-Commit: dd9945c0ba40d2dbc9eb7c99291ba6b69bd66718 (2.43-17)
|
||||
Fix-Commit: e10977481f4db4b2a3ce34fa4c3a1e26651ae312 (2.44)
|
||||
Reported-by: Antonio Maini (0rbitingZer0) - 0rbitingZer0@proton.me
|
||||
@@ -1,15 +0,0 @@
|
||||
iconv crash due to assertion failure with untrusted input
|
||||
|
||||
The iconv() function in the GNU C Library versions 2.43 and earlier may
|
||||
crash due to an assertion failure when converting inputs from the
|
||||
IBM1390 or IBM1399 character sets, which may be used to remotely crash
|
||||
an application.
|
||||
|
||||
This vulnerability can be trivially mitigated by removing the IBM1390
|
||||
and IBM1399 character sets from systems that do not need them.
|
||||
|
||||
CVE-Id: CVE-2026-4046
|
||||
Public-Date: 2026-03-12
|
||||
Vulnerable-Commit: 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (2.3.3-1501)
|
||||
Fix-Commit: d6f08d1cf027f4eb2ba289a6cc66853722d4badc (2.44)
|
||||
Reported-by: Rocket Ma
|
||||
@@ -1,22 +0,0 @@
|
||||
REJECTED: Static buffer overflow in deprecated nis_local_principal
|
||||
|
||||
REJECTED: CVE-2026-5358 is rejected for two reasons. Firstly it has been
|
||||
discovered that no NIS+ client or server was ever released for any
|
||||
Linux-based OS distributions and as such this makes the API provisional
|
||||
and unused. Secondly it has been discovered that the NIS+ cold start
|
||||
cache (/var/nis/NIS_COLD_START) cannot be bypassed and as such the API
|
||||
can only be called with a trusted server from the pre-populated cache.
|
||||
The use of a trusted server means no trust boundary is crossed and this
|
||||
is therefore considered a normal bug.
|
||||
|
||||
NIS+ support in the GNU C Library was never officially supported even
|
||||
though an incomplete implementation of the APIs was made pulibc. To the
|
||||
best knowledge of the glibc security team no open-source NIS+ server
|
||||
implementations were ever released for use with this API. Applications
|
||||
should not use any of the NIS+ APIs and should move to modern identity
|
||||
and access management services.
|
||||
|
||||
CVE-Id: CVE-2026-5358
|
||||
Public-Date: 2026-04-10
|
||||
Rejected-Date: 2026-04-33
|
||||
Reported-by: Rahul Hoysala
|
||||
@@ -1,23 +0,0 @@
|
||||
scanf %mc off-by-one heap buffer overflow
|
||||
|
||||
Calling the scanf family of functions with a %mc (malloc'd character
|
||||
match) in the GNU C Library version 2.7 to version 2.43 with a format
|
||||
width specifier with an explicit width greater than 1024 could result in
|
||||
a one byte heap buffer overflow.
|
||||
|
||||
The bug is in the buffer growth formula in __vfscanf_internal, which
|
||||
under-allocates by one byte during realloc expansion, allowing a
|
||||
controlled single-byte overwrite past the end of the heap buffer.
|
||||
|
||||
The impact is limited by the fact that to execute the overwrite you need
|
||||
both user controlled input data and a specific choice of maximum width
|
||||
that yields a smaller than needed allocation. The latter point has to
|
||||
take into account malloc's particular chunk size rounding process. The
|
||||
"%[width]mc" format specifier does not appear to have notable use in
|
||||
major Linux-based OS distributions, due to which the real world impact
|
||||
may be limited to bespoke use cases.
|
||||
|
||||
CVE-Id: CVE-2026-5450
|
||||
Public-Date: 2026-03-19
|
||||
Vulnerable-Commit: 874aa52349cc111d1f6ea5dff24bb14c306714e0 (2.7)
|
||||
Reported-by: Rocket Ma
|
||||
@@ -1,24 +0,0 @@
|
||||
Potential buffer under-read in ungetwc
|
||||
|
||||
Calling the ungetwc function on a FILE stream with wide characters
|
||||
encoded in a character set that has overlaps between its single byte and
|
||||
multi-byte character encodings, in the GNU C Library version 2.43 or
|
||||
earlier, may result in an attempt to read bytes before an allocated
|
||||
buffer, potentially resulting in unintentional disclosure of neighboring
|
||||
data in the heap, or a program crash.
|
||||
|
||||
A bug in the wide character pushback implementation
|
||||
(_IO_wdefault_pbackfail in libio/wgenops.c) causes ungetwc() to operate
|
||||
on the regular character buffer (fp->_IO_read_ptr) instead of the actual
|
||||
wide-stream read pointer (fp->_wide_data->_IO_read_ptr). The program
|
||||
crash may happen in cases where fp->_IO_read_ptr is not initialized and
|
||||
hence points to NULL. The buffer under-read requires a special situation
|
||||
where the input character encoding is such that there are overlaps
|
||||
between single byte representations and multibyte representations in
|
||||
that encoding, resulting in spurious matches. The spurious match case
|
||||
is not possible in the standard Unicode character sets.
|
||||
|
||||
CVE-Id: CVE-2026-5928
|
||||
Public-Date: 2026-03-17
|
||||
Reported-by: Rocket Ma
|
||||
Vulnerable-Commit: d64b6ad07585b8a37e5fecc9a47fcee766d52ede (2.1.1-89)
|
||||
@@ -1,24 +0,0 @@
|
||||
Potential buffer overflow in ns_sprintrrf TSIG handling path
|
||||
|
||||
The deprecated functions ns_printrrf, ns_printrr and fp_nquery in the
|
||||
GNU C Library version 2.2 and newer fail to enforce the caller-supplied
|
||||
buffer length, and can result in an out-of-bounds write when printing
|
||||
TSIG records.
|
||||
|
||||
A defect in the TSIG case handling within ns_sprintrrf performs a
|
||||
formatted write using sprintf without checking the remaining buffer
|
||||
length, and may write up to 6 bytes past the end of the buffer. If the
|
||||
library is compiled with assertions, and the out-of-bounds write doesn't
|
||||
terminate the process, then a subsequent check for "len <= *buflen" will
|
||||
trigger an assertion failure.
|
||||
|
||||
These functions are for application debugging only and hence not in the
|
||||
path of code executed by the DNS resolver. Further, they have been
|
||||
deprecated since version 2.34 (2021-08-02) and should not be used by any
|
||||
new applications. Applications should consider porting away from these
|
||||
interfaces since they may be removed in future versions.
|
||||
|
||||
CVE-Id: CVE-2026-5435
|
||||
Public-Date: 2026-04-02
|
||||
Vulnerable-Commit: b43b13ac2544b11f35be301d1589b51a8473e32b (2.2)
|
||||
Reported-by: shinobu
|
||||
@@ -1,18 +0,0 @@
|
||||
Buffer overread in ns_printrrf with corrupted RDATA field
|
||||
|
||||
The deprecated functions ns_printrrf, ns_printrr and fp_nquery in the
|
||||
GNU C Library version 2.0.1 to version 2.43 fail to validate the RDATA
|
||||
content against the RDATA length in a DNS response when processing A6,
|
||||
CERT, LOC, TKEY or TSIG records, which may allow an attacker to craft a
|
||||
DNS response, causing a target application to crash or read
|
||||
uninitialized memory.
|
||||
|
||||
These functions are for application debugging only and hence not in the
|
||||
path of code executed by the DNS resolver. Further, they have been
|
||||
deprecated since version 2.34 and should not be used by any new
|
||||
applications. Applications should consider porting away from these
|
||||
interfaces since they may be removed in future versions.
|
||||
|
||||
CVE-Id: CVE-2026-6238
|
||||
Public-Date: 2026-04-11
|
||||
Vulnerable-Commit: ee188d555b8c32ad9704a7440cab400af967292f (1.90)
|
||||
@@ -1,20 +0,0 @@
|
||||
Potential stack-based buffer clash during tilde expansion in wordexp
|
||||
|
||||
Calling wordexp with a tilde (~) followed by an overly long username
|
||||
in the GNU C Library version 2.2.3 to 2.43 may lead to a stack buffer
|
||||
clash.
|
||||
|
||||
When expanding paths that begin with a tilde (~) followed by a username, the
|
||||
internal parse_tilde function extracts the username to determine the user's
|
||||
home directory. The implementation allocates memory for this username directly
|
||||
on the stack using the strndupa macro. Because the size of this allocation
|
||||
was determined by the length of the user-supplied input without any bounds
|
||||
checks, passing an excessively long username e.g. thousands of characters,
|
||||
forces the thread to exhaust its stack space. Thus if an application passes
|
||||
untrusted, attacker-controlled input to the wordexp function, an attacker
|
||||
can trigger a stack clash.
|
||||
|
||||
CVE-Id: CVE-2026-6791
|
||||
Public-Date: 2026-06-22
|
||||
Vulnerable-Commit: 344af000e1d6e9c7882b9bc48e71cb3f1b5fc03c (2.2.3-114)
|
||||
Reported-by: storm
|
||||
@@ -1,92 +0,0 @@
|
||||
GNU C Library Security Advisory Format
|
||||
======================================
|
||||
|
||||
Security advisories in this directory follow a simple git commit log
|
||||
format, with a heading and free-format description augmented with tags
|
||||
to allow parsing key information. References to code changes are
|
||||
specific to the glibc repository and follow a specific format:
|
||||
|
||||
Tag-name: <commit-ref> (release-version)
|
||||
|
||||
The <commit-ref> indicates a specific commit in the repository. The
|
||||
release-version indicates the publicly consumable release in which this
|
||||
commit is known to exist. The release-version is derived from the
|
||||
git-describe format, (i.e. stripped out from glibc-2.34.NNN-gxxxx) and
|
||||
is of the form 2.34-NNN. If the -NNN suffix is absent, it means that
|
||||
the change is in that release tarball, otherwise the change is on the
|
||||
release/2.YY/master branch and not in any released tarball.
|
||||
|
||||
The following tags are currently being used:
|
||||
|
||||
CVE-Id:
|
||||
This is the CVE-Id assigned under the CVE Program
|
||||
(https://www.cve.org/).
|
||||
|
||||
Public-Date:
|
||||
The date this issue became publicly known.
|
||||
|
||||
Rejected-Date:
|
||||
The most recent date the assigned advisory was rejected. If the advisory
|
||||
is ever published again the Rejected-Date tag should be removed.
|
||||
|
||||
Vulnerable-Commit:
|
||||
The commit that introduced this vulnerability. There could be multiple
|
||||
entries, one for each release branch in the glibc repository; the
|
||||
release-version portion of this tag should tell you which branch this is
|
||||
on.
|
||||
|
||||
Fix-Commit:
|
||||
The commit that fixed this vulnerability. There could be multiple
|
||||
entries for each release branch in the glibc repository, indicating that
|
||||
all of those commits contributed to fixing that issue in each of those
|
||||
branches.
|
||||
|
||||
Reported-By:
|
||||
The entity that reported this issue. There could be multiple entries, one for
|
||||
each reporter.
|
||||
|
||||
Adding an Advisory
|
||||
------------------
|
||||
|
||||
An advisory for a CVE needs to be added on the master branch in two steps:
|
||||
|
||||
1. Add the text of the advisory without any Fix-Commit tags along with
|
||||
the fix for the CVE. Add the Vulnerable-Commit tag, if applicable.
|
||||
The advisories directory does not exist in release branches, so keep
|
||||
the advisory text commit distinct from the code changes, to ease
|
||||
backports. Ask for the GLIBC-SA advisory number from the security
|
||||
team.
|
||||
|
||||
2. Finish all backports on release branches and then back on the msater
|
||||
branch, add all commit refs to the advisory using the Fix-Commit
|
||||
tags. Don't bother adding the release-version subscript since the
|
||||
next step will overwrite it.
|
||||
|
||||
3. Run the process-advisories.sh script in the scripts directory on the
|
||||
advisory:
|
||||
|
||||
scripts/process-advisories.sh update GLIBC-SA-YYYY-NNNN
|
||||
|
||||
(replace YYYY-NNNN with the actual advisory number).
|
||||
|
||||
4. Verify the updated advisory and push the result.
|
||||
|
||||
Rejecting an Advisory
|
||||
---------------------
|
||||
|
||||
Rejecting an advisory on the master branch can be done in one step:
|
||||
|
||||
1. Mark the advisory as rejected. Add the text "REJECTED: " as a prefix
|
||||
to any short-form description. Add a new paragraph that starts with
|
||||
"REJECTED: " and explains the reason for the rejection including
|
||||
justification for why it no longer has security impact. Lastly add
|
||||
a Rejected-Date tag to the advisory.
|
||||
|
||||
Getting a NEWS snippet from advisories
|
||||
--------------------------------------
|
||||
|
||||
Run:
|
||||
|
||||
scripts/process-advisories.sh news
|
||||
|
||||
and copy the content into the NEWS file.
|
||||
+25
-3
@@ -409,9 +409,9 @@ $(addprefix $(objpfx)bench-,calloc-thread): $(libm-benchtests)
|
||||
# Rules to build and execute the benchmarks. Do not put any benchmark
|
||||
# parameters beyond this point.
|
||||
|
||||
# We don't want the benchmark programs to run in parallel since that could
|
||||
# affect their performance.
|
||||
.NOTPARALLEL:
|
||||
# Benchmark programs must not run concurrently, however building them is
|
||||
# safe in parallel. So '.NOTPARALLEL:' is used only when benchmarks run
|
||||
# or when more than one group is going to run.
|
||||
|
||||
bench-extra-objs = json-lib.o
|
||||
|
||||
@@ -622,8 +622,30 @@ $(bench-link-targets): %: %.o $(objpfx)json-lib.o \
|
||||
$(bench-link-targets): LDFLAGS += $(link-bench-bind-now)
|
||||
|
||||
$(objpfx)bench-%.c: %-inputs $(bench-deps)
|
||||
$(make-target-directory)
|
||||
{ if [ -n "$($*-INCLUDE)" ]; then \
|
||||
cat $($*-INCLUDE); \
|
||||
fi; \
|
||||
$(PYTHON) scripts/bench.py $(patsubst %-inputs,%,$<); } > $@-tmp
|
||||
mv -f $@-tmp $@
|
||||
|
||||
# Serialize the benchmark runs so their timing is not perturbed by a
|
||||
# concurrent workload, while still building every benchmark program in parallel.
|
||||
# Ordering is only needed when more than one benchmark group run: the combined
|
||||
# 'bench' goal runs all three groups, and the bench* goals can also be combined
|
||||
# on a single command line. A lone group needs no ordering -- make builds its
|
||||
# programs in parallel and then runs its single recipe, which cannot overlap a
|
||||
# compile.
|
||||
ifneq (,$(filter bench,$(MAKECMDGOALS)))
|
||||
bench-run-active := bench-set bench-func bench-malloc
|
||||
else
|
||||
bench-run-active := $(filter bench-set bench-func bench-malloc,$(MAKECMDGOALS))
|
||||
endif
|
||||
|
||||
ifneq (,$(word 2,$(bench-run-active)))
|
||||
# Hold every active run until all benchmark programs have been built.
|
||||
$(bench-run-active): | bench-build
|
||||
# And then run the active groups strictly one at a time.
|
||||
bench-func: | $(filter bench-set,$(bench-run-active))
|
||||
bench-malloc: | $(filter bench-set bench-func,$(bench-run-active))
|
||||
endif
|
||||
|
||||
+3006
-2405
File diff suppressed because it is too large
Load Diff
+3006
-4911
File diff suppressed because it is too large
Load Diff
+2004
-3446
File diff suppressed because it is too large
Load Diff
+11
-3
@@ -60,6 +60,14 @@ vpath %.c ../locale/programs
|
||||
|
||||
include ../Rules
|
||||
|
||||
# The catalog-generation tests below run gencat under specific locales,
|
||||
# and tst-catgets reads the resulting catalog, so the build must wait for
|
||||
# those locales to be generated. Without this dependency a parallel build
|
||||
# races catgets against localedata and gencat can run before the locale
|
||||
# exists (it then falls back to C and the test fails).
|
||||
LOCALES := de_DE.ISO-8859-1 hr_HR.ISO-8859-2 ja_JP.SJIS
|
||||
include ../gen-locales.mk
|
||||
|
||||
$(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o)
|
||||
|
||||
catgets-CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:$(localedir)/%l/%N:$(localedir)/%l/LC_MESSAGES/%N:"'
|
||||
@@ -95,7 +103,7 @@ tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de \
|
||||
ifeq ($(run-built-tests),yes)
|
||||
# This test just checks whether the program produces any error or not.
|
||||
# The result is not tested.
|
||||
$(objpfx)test1.cat: test1.msg $(objpfx)gencat
|
||||
$(objpfx)test1.cat: test1.msg $(objpfx)gencat $(gen-locales)
|
||||
$(built-program-cmd-before-env) \
|
||||
$(run-program-env) LC_ALL=hr_HR.ISO-8859-2 \
|
||||
$(built-program-cmd-after-env) -H $(objpfx)test1.h $@ $<; \
|
||||
@@ -103,7 +111,7 @@ $(objpfx)test1.cat: test1.msg $(objpfx)gencat
|
||||
$(objpfx)test2.cat: test2.msg $(objpfx)gencat
|
||||
$(built-program-cmd) -H $(objpfx)test2.h $@ $<; \
|
||||
$(evaluate-test)
|
||||
$(objpfx)de/libc.cat: $(objpfx)de.msg $(objpfx)gencat
|
||||
$(objpfx)de/libc.cat: $(objpfx)de.msg $(objpfx)gencat $(gen-locales)
|
||||
$(make-target-directory)
|
||||
$(built-program-cmd-before-env) \
|
||||
$(run-program-env) LC_ALL=de_DE.ISO-8859-1 \
|
||||
@@ -116,7 +124,7 @@ $(objpfx)de.msg: xopen-msg.awk $(..)po/de.po
|
||||
LC_ALL=C $(AWK) -f $^ $< > $@
|
||||
|
||||
$(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
|
||||
$(objpfx)sample.SJIS.cat
|
||||
$(objpfx)sample.SJIS.cat $(gen-locales)
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-cmd-before-env)' \
|
||||
'$(run-program-env)' '$(test-program-cmd-after-env)'; \
|
||||
$(evaluate-test)
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
_dl_aux_init (auxvec);
|
||||
# endif
|
||||
|
||||
__tunables_init (__environ);
|
||||
__tunables_init (__environ, argv);
|
||||
|
||||
ARCH_INIT_CPU_FEATURES ();
|
||||
|
||||
|
||||
+21
-11
@@ -36,10 +36,15 @@
|
||||
trampoline, read, 3 * fn, and do_test. */
|
||||
#define NUM_FUNCTIONS 7
|
||||
|
||||
/* Avoid the read wrapper frame truncation on targets that add extra frames
|
||||
between it and handle_signal (the cancellable syscall wrappers
|
||||
__syscall_cancel*, or the i686 __kernel_vsyscall entry). */
|
||||
#define MAX_FUNCTIONS 64
|
||||
|
||||
void
|
||||
handle_signal (int signum)
|
||||
{
|
||||
void *addresses[NUM_FUNCTIONS];
|
||||
void *addresses[MAX_FUNCTIONS];
|
||||
char **symbols;
|
||||
int n;
|
||||
int i;
|
||||
@@ -70,23 +75,28 @@ handle_signal (int signum)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do not check name for signal trampoline or cancellable syscall
|
||||
wrappers (__syscall_cancel*). */
|
||||
for (; i < n - 1; i++)
|
||||
/* Skip the signal trampoline and any cancellable syscall wrapper frames
|
||||
(__syscall_cancel*) and require the read syscall wrapper to be
|
||||
present. */
|
||||
for (i = 1; i < n; i++)
|
||||
if (match (symbols[i], "read"))
|
||||
break;
|
||||
if (i == n - 1)
|
||||
if (i == n)
|
||||
{
|
||||
FAIL ();
|
||||
return;
|
||||
}
|
||||
|
||||
for (; i < n - 1; i++)
|
||||
if (!match (symbols[i], "fn"))
|
||||
{
|
||||
FAIL ();
|
||||
return;
|
||||
}
|
||||
/* The read wrapper must be followed by the three fn recursion frames. */
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
i++;
|
||||
if (i == n || !match (symbols[i], "fn"))
|
||||
{
|
||||
FAIL ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Symbol names are not available for static functions, so we do not
|
||||
check do_test. */
|
||||
|
||||
|
||||
+67
-1
@@ -225,6 +225,7 @@ ldconfig-modules := \
|
||||
readlib \
|
||||
static-stubs \
|
||||
stringtable \
|
||||
tunconf \
|
||||
xmalloc \
|
||||
xstrdup \
|
||||
# ldconfig-modules
|
||||
@@ -335,6 +336,7 @@ tests-internal := \
|
||||
$(tests-static-internal) \
|
||||
tst-tls1 \
|
||||
tst-tls_tp_offset \
|
||||
tst-tunconf1 \
|
||||
# tests-internal
|
||||
|
||||
tests-static := $(tests-static-normal) $(tests-static-internal)
|
||||
@@ -345,6 +347,17 @@ tests-static += \
|
||||
tst-tls9-static \
|
||||
# tests-static
|
||||
|
||||
tst-tunconf1-TUNABLES-only = \
|
||||
glibc.malloc.tcache_count=5 \
|
||||
glibc.malloc.perturb=41 \
|
||||
glibc.malloc.mmap_threshold=10002 \
|
||||
glibc.malloc.trim_threshold=10002 \
|
||||
glibc.malloc.arena_max=300
|
||||
tst-tunconf1-ENV = \
|
||||
MALLOC_MMAP_MAX_=200 \
|
||||
MALLOC_TOP_PAD_=200 \
|
||||
MALLOC_ARENA_MAX=400
|
||||
|
||||
static-dlopen-environment = \
|
||||
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
|
||||
tst-tls9-static-ENV = $(static-dlopen-environment)
|
||||
@@ -577,10 +590,12 @@ endif
|
||||
tests-container += \
|
||||
tst-dlopen-self-container \
|
||||
tst-dlopen-tlsmodid-container \
|
||||
tst-ldconfig-cache \
|
||||
tst-pldd \
|
||||
tst-preload-pthread-libc \
|
||||
tst-ptrguard-static-dlopen \
|
||||
tst-rootdir \
|
||||
tst-tunconf1 \
|
||||
# tests-container
|
||||
|
||||
test-srcs = \
|
||||
@@ -712,6 +727,7 @@ tests-special += $(tests-execstack-special-$(have-z-execstack))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += \
|
||||
$(objpfx)tst-ldconfig-X.out \
|
||||
$(objpfx)tst-ldconfig-install.out \
|
||||
$(objpfx)tst-ldconfig-p.out \
|
||||
$(objpfx)tst-ldconfig-soname.out \
|
||||
$(objpfx)tst-rtld-help.out \
|
||||
@@ -734,6 +750,9 @@ one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
|
||||
0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x)
|
||||
tst-tls-many-dynamic-modules := \
|
||||
$(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod)
|
||||
tst-ldconfig-cache-modules := \
|
||||
$(foreach n,01 02 03 04 05,tst-tls-manydynamic$(n)mod)
|
||||
$(objpfx)tst-ldconfig-cache.out: $(tst-ldconfig-cache-modules:%=$(objpfx)%.so)
|
||||
tst-tls-many-dynamic-modules-dep-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 \
|
||||
14 15 16 17 18 19
|
||||
tst-tls-many-dynamic-modules-dep = \
|
||||
@@ -1377,6 +1396,13 @@ modules-names += \
|
||||
tst-ifunc-tls-write-lib \
|
||||
tst-tls-tdata-reloc-lib \
|
||||
# modules-names
|
||||
ifeq (yes,$(have-gcc-ifunc))
|
||||
tests += \
|
||||
tst-ifunc-fault-dep-bindnow \
|
||||
tst-ifunc-fault-dep-lazy \
|
||||
# tests
|
||||
modules-names += tst-ifunc-fault-mod
|
||||
endif
|
||||
ifneq (no,$(have-test-mtls-descriptor))
|
||||
tests += tst-ifunc-tls-init-tlsdesc
|
||||
modules-names += tst-ifunc-tls-init-tlsdesc-lib
|
||||
@@ -1406,6 +1432,7 @@ tests-special += \
|
||||
$(objpfx)check-execstack.out \
|
||||
$(objpfx)check-initfini.out \
|
||||
$(objpfx)check-localplt.out \
|
||||
$(objpfx)check-symbol-version.out \
|
||||
$(objpfx)check-textrel.out \
|
||||
$(objpfx)check-wx-segment.out \
|
||||
# tests-special
|
||||
@@ -1441,6 +1468,7 @@ ifndef avoid-generated
|
||||
# Makefile fragment to be included.
|
||||
define include_dsosort_tests
|
||||
$(objpfx)$(1).generated-makefile: $(1)
|
||||
$$(make-target-directory)
|
||||
$(PYTHON) $(..)scripts/dso-ordering-test.py \
|
||||
--description-file $$< --objpfx $(objpfx) --output-makefile $$@T
|
||||
mv $$@T $$@
|
||||
@@ -1449,6 +1477,7 @@ endef
|
||||
# Likewise, where the .def file itself is generated.
|
||||
define include_dsosort_tests_objpfx
|
||||
$(objpfx)$(1).generated-makefile: $(objpfx)$(1)
|
||||
$$(make-target-directory)
|
||||
$(PYTHON) $(..)scripts/dso-ordering-test.py \
|
||||
--description-file $$< --objpfx $(objpfx) --output-makefile $$@T
|
||||
mv $$@T $$@
|
||||
@@ -1467,12 +1496,15 @@ $(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
|
||||
$(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
|
||||
|
||||
$(objpfx)dso-sort-tests-all2.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 2 > $@
|
||||
|
||||
$(objpfx)dso-sort-tests-all3.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 3 > $@
|
||||
|
||||
$(objpfx)dso-sort-tests-all4.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 4 > $@
|
||||
|
||||
$(eval $(call include_dsosort_tests_objpfx,dso-sort-tests-all2.def))
|
||||
@@ -1550,7 +1582,9 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
|
||||
# when compiled for libc.
|
||||
rtld-stubbed-symbols = \
|
||||
__libc_assert_fail \
|
||||
__syscall_cancel \
|
||||
__libc_single_threaded_internal \
|
||||
__syscall_cancel_arch \
|
||||
__syscall_do_cancel \
|
||||
calloc \
|
||||
free \
|
||||
malloc \
|
||||
@@ -2344,6 +2378,12 @@ $(objpfx)check-initfini.out: $(..)scripts/check-initfini.awk \
|
||||
$(evaluate-test)
|
||||
generated += check-initfini.out
|
||||
|
||||
$(objpfx)check-symbol-version.out: $(..)scripts/check-symbol-version.awk \
|
||||
$(all-built-dso:=.dynsym)
|
||||
LC_ALL=C $(AWK) -f $^ > $@; \
|
||||
$(evaluate-test)
|
||||
generated += check-symbol-version.out
|
||||
|
||||
$(objpfx)tst-dlopenrpath: $(objpfx)tst-dlopenrpathmod.so
|
||||
CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\"
|
||||
LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir
|
||||
@@ -2521,6 +2561,27 @@ $(objpfx)tst-ifunc-fault-bindnow.out: $(objpfx)tst-ifunc-fault-bindnow \
|
||||
$(objpfx)ld.so
|
||||
$(tst-ifunc-fault-script)
|
||||
|
||||
LDFLAGS-tst-ifunc-fault-dep-lazy = -Wl,-z,lazy
|
||||
LDFLAGS-tst-ifunc-fault-dep-bindnow = -Wl,-z,now
|
||||
define tst-ifunc-fault-dep-script
|
||||
( $(test-wrapper) $(rtld-prefix) --verify $< \
|
||||
&& $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 $(rtld-prefix) $< \
|
||||
&& $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 LD_DEBUG=unused \
|
||||
$(rtld-prefix) $< \
|
||||
&& $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 LD_WARN=yes LD_BIND_NOW=1 \
|
||||
$(rtld-prefix) $< \
|
||||
) > $@; $(evaluate-test)
|
||||
endef
|
||||
$(objpfx)tst-ifunc-fault-dep-lazy: $(objpfx)tst-ifunc-fault-mod.so
|
||||
$(objpfx)tst-ifunc-fault-dep-bindnow: $(objpfx)tst-ifunc-fault-mod.so
|
||||
$(objpfx)tst-ifunc-fault-dep-lazy.out: $(objpfx)tst-ifunc-fault-dep-lazy \
|
||||
$(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
|
||||
$(tst-ifunc-fault-dep-script)
|
||||
$(objpfx)tst-ifunc-fault-dep-bindnow.out: \
|
||||
$(objpfx)tst-ifunc-fault-dep-bindnow \
|
||||
$(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
|
||||
$(tst-ifunc-fault-dep-script)
|
||||
|
||||
LDFLAGS-tst-ifunc-plt-lib.so = -Wl,-z,lazy
|
||||
|
||||
tst-ifunc-plt-bindnow-ENV = LD_BIND_NOW=1
|
||||
@@ -2824,6 +2885,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-ldconfig-install.out : tst-ldconfig-install.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-ldconfig-p.out : tst-ldconfig-p.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(sysconfdir)' '$(test-wrapper-env)' \
|
||||
'$(run-program-env)' > $@; \
|
||||
|
||||
+106
-2
@@ -36,6 +36,7 @@
|
||||
#include <dl-cache.h>
|
||||
#include <version.h>
|
||||
#include <stringtable.h>
|
||||
#include <tunconf.h>
|
||||
|
||||
/* Used to store library names, paths, and other strings. */
|
||||
static struct stringtable strings;
|
||||
@@ -275,7 +276,8 @@ check_new_cache (struct cache_file_new *cache)
|
||||
|
||||
/* Print the extension information in *EXT. */
|
||||
static void
|
||||
print_extensions (struct cache_extension_all_loaded *ext)
|
||||
print_extensions (struct cache_extension_all_loaded *ext,
|
||||
const char *cache_data)
|
||||
{
|
||||
if (ext->sections[cache_extension_tag_generator].base != NULL)
|
||||
{
|
||||
@@ -284,6 +286,65 @@ print_extensions (struct cache_extension_all_loaded *ext)
|
||||
ext->sections[cache_extension_tag_generator].size, stdout);
|
||||
putchar ('\n');
|
||||
}
|
||||
if (ext->sections[cache_extension_tag_tunables].base != NULL)
|
||||
{
|
||||
struct tunable_header_cached *thc;
|
||||
struct tunable_entry_cached *tec;
|
||||
int i, count;
|
||||
|
||||
thc = (struct tunable_header_cached *)
|
||||
ext->sections[cache_extension_tag_tunables].base;
|
||||
tec = thc->tunables;
|
||||
count = thc->num_tunables;
|
||||
printf("tunables sig 0x%08x ver 0x%08x count %u\n",
|
||||
thc->signature, thc->version, thc->num_tunables);
|
||||
/* Check that COUNT won't overflow our data block. */
|
||||
assert (ext->sections[cache_extension_tag_tunables].base
|
||||
+ ext->sections[cache_extension_tag_tunables].size
|
||||
== (void *) & tec[count]);
|
||||
for (i = 0; i < count; ++ i)
|
||||
{
|
||||
printf (" [%d] %s = %s [flags 0x%08x (",
|
||||
i,
|
||||
cache_data + tec[i].name_offset,
|
||||
cache_data + tec[i].value_offset,
|
||||
tec[i].flags);
|
||||
if (tec[i].flags & TUNCONF_FLAG_PARSED)
|
||||
printf ("parsed,");
|
||||
if (tec[i].flags & TUNCONF_FLAG_NEGATIVE)
|
||||
printf ("negative,");
|
||||
if ((tec[i].flags & TUNCONF_FLAG_OVERRIDABLE)
|
||||
== TUNCONF_OVERRIDE_ALLOW)
|
||||
printf ("overridable");
|
||||
else
|
||||
printf ("nonoverridable");
|
||||
switch (tec[i].flags & (TUNCONF_EXCLUDE_SECURE
|
||||
| TUNCONF_EXCLUDE_UNSECURE))
|
||||
{
|
||||
case TUNCONF_EXCLUDE_SECURE:
|
||||
printf(",nonsecure");
|
||||
break;
|
||||
case TUNCONF_EXCLUDE_UNSECURE:
|
||||
printf(",onlysecure");
|
||||
break;
|
||||
case TUNCONF_EXCLUDE_SECURE | TUNCONF_EXCLUDE_UNSECURE:
|
||||
printf(",ignore");
|
||||
break;
|
||||
case 0:
|
||||
printf(",anysecure");
|
||||
break;
|
||||
}
|
||||
switch (tec[i].flags & TUNCONF_FLAG_FILTER)
|
||||
{
|
||||
case TUNCONF_FILTER_PERPROC:
|
||||
printf(",[proc]");
|
||||
break;
|
||||
}
|
||||
if (tec[i].flag_offset != 0)
|
||||
printf (",'%s'", cache_data + tec[i].flag_offset);
|
||||
printf (")]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the whole cache file, if a file contains the new cache format
|
||||
@@ -394,7 +455,7 @@ print_cache (const char *cache_name)
|
||||
cache_new->libs[i].hwcap, hwcaps_string,
|
||||
cache_data + cache_new->libs[i].value);
|
||||
}
|
||||
print_extensions (&ext);
|
||||
print_extensions (&ext, cache_data);
|
||||
}
|
||||
/* Cleanup. */
|
||||
munmap (cache, cache_size);
|
||||
@@ -466,6 +527,18 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
if (p->used)
|
||||
hwcaps_array[p->section_index] = str_offset + p->name->offset;
|
||||
|
||||
struct tunable_header_cached *tunable_data;
|
||||
size_t tunable_size;
|
||||
size_t tunable_aligner = 0;
|
||||
|
||||
tunable_data = get_tunconf_ext (str_offset);
|
||||
|
||||
if (tunable_data == NULL)
|
||||
{
|
||||
/* There is no section for tunables data. */
|
||||
hwcaps_offset -= sizeof (struct cache_extension_section);
|
||||
}
|
||||
|
||||
/* This is the offset of the generator string. */
|
||||
uint32_t generator_offset = hwcaps_offset;
|
||||
if (hwcaps_count == 0)
|
||||
@@ -498,6 +571,23 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
ext->sections[xid].size = hwcaps_size;
|
||||
}
|
||||
|
||||
if (tunable_data != NULL)
|
||||
{
|
||||
uint32_t tunable_offset_ua;
|
||||
uint32_t tunable_offset;
|
||||
|
||||
tunable_size = TUNCONF_SIZE (tunable_data);
|
||||
tunable_offset_ua = generator_offset + strlen (generator);
|
||||
tunable_offset = ALIGN_UP (tunable_offset_ua, 8);
|
||||
tunable_aligner = tunable_offset - tunable_offset_ua;
|
||||
|
||||
++xid;
|
||||
ext->sections[xid].tag = cache_extension_tag_tunables;
|
||||
ext->sections[xid].flags = 0;
|
||||
ext->sections[xid].offset = tunable_offset;
|
||||
ext->sections[xid].size = tunable_size;
|
||||
}
|
||||
|
||||
++xid;
|
||||
ext->count = xid;
|
||||
assert (xid <= cache_extension_count);
|
||||
@@ -509,6 +599,14 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
|| write (fd, generator, strlen (generator)) != strlen (generator))
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
|
||||
|
||||
if (tunable_data)
|
||||
{
|
||||
if (write (fd, " ", tunable_aligner) != tunable_aligner
|
||||
|| write (fd, tunable_data, tunable_size) != tunable_size)
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache tunable data failed"));
|
||||
free (tunable_data);
|
||||
}
|
||||
|
||||
free (hwcaps_array);
|
||||
free (ext);
|
||||
}
|
||||
@@ -1106,3 +1204,9 @@ out_fail:
|
||||
free (temp_name);
|
||||
free (file_entries);
|
||||
}
|
||||
|
||||
struct stringtable_entry *
|
||||
cache_store_string (const char *string)
|
||||
{
|
||||
return stringtable_add (&strings, string);
|
||||
}
|
||||
|
||||
+239
-90
@@ -17,6 +17,7 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <intprops.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -26,11 +27,22 @@
|
||||
#include <_itoa.h>
|
||||
#include <dl-hwcaps.h>
|
||||
#include <dl-isa-level.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "tunconf.h"
|
||||
|
||||
/* This is the starting address and the size of the mmap()ed file. */
|
||||
static struct cache_file *cache;
|
||||
static struct cache_file_new *cache_new;
|
||||
static size_t cachesize;
|
||||
static struct cache_extension_all_loaded ext;
|
||||
|
||||
static struct {
|
||||
typeof ((*(struct __stat64_t64 *)0).st_mtime) mtime;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_ino) ino;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_size) size;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_dev) dev;
|
||||
} cache_file_time, new_cache_file_time;
|
||||
|
||||
#ifdef SHARED
|
||||
/* This is used to cache the priorities of glibc-hwcaps
|
||||
@@ -53,6 +65,7 @@ glibc_hwcaps_priorities_free (void)
|
||||
free (glibc_hwcaps_priorities);
|
||||
glibc_hwcaps_priorities = NULL;
|
||||
glibc_hwcaps_priorities_allocated = 0;
|
||||
glibc_hwcaps_priorities_length = 0;
|
||||
}
|
||||
|
||||
/* Ordered comparison of a hwcaps string from the cache on the left
|
||||
@@ -84,10 +97,6 @@ glibc_hwcaps_compare (uint32_t left_index, struct dl_hwcaps_priority *right)
|
||||
static void
|
||||
glibc_hwcaps_priorities_init (void)
|
||||
{
|
||||
struct cache_extension_all_loaded ext;
|
||||
if (!cache_extension_load (cache_new, cache, cachesize, &ext))
|
||||
return;
|
||||
|
||||
uint32_t length = (ext.sections[cache_extension_tag_glibc_hwcaps].size
|
||||
/ sizeof (uint32_t));
|
||||
if (length > glibc_hwcaps_priorities_allocated)
|
||||
@@ -374,6 +383,168 @@ _dl_cache_libcmp (const char *p1, const char *p2)
|
||||
return *p1 - *p2;
|
||||
}
|
||||
|
||||
/* Set the cache back to the "no cache" state, which may include
|
||||
cleaning up a loaded cache. */
|
||||
static void
|
||||
_dl_maybe_unload_ldsocache (void)
|
||||
{
|
||||
if (cache != NULL)
|
||||
__munmap (cache, cachesize);
|
||||
|
||||
cache = NULL;
|
||||
cache_new = NULL;
|
||||
cachesize = 0;
|
||||
|
||||
#ifdef SHARED
|
||||
glibc_hwcaps_priorities_free ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns TRUE if for any reason the cache needs to be reloaded
|
||||
(including, the first time, loaded). */
|
||||
static bool
|
||||
_dl_check_ldsocache_needs_loading (void)
|
||||
{
|
||||
int rv;
|
||||
static bool copy_old_time = 0;
|
||||
struct __stat64_t64 new_cache_file_stat;
|
||||
|
||||
/* Save the previous stat every time. We only care when this
|
||||
changes, and we only stat it here, so we can get away with doing
|
||||
the copy now instead of at every single return statement in this
|
||||
function. However, we only need to copy it if the previous stat
|
||||
succeeded. The only way this could be subverted is if the admin
|
||||
moves the file aside, then moves it back, but CACHE would be set
|
||||
to NULL in the interim so that would be detected. */
|
||||
if (copy_old_time)
|
||||
cache_file_time = new_cache_file_time;
|
||||
rv = __fstatat64_time64 (AT_FDCWD, LD_SO_CACHE, &new_cache_file_stat, 0);
|
||||
copy_old_time = (rv >= 0);
|
||||
|
||||
/* No file to load, but there used to be. Assume user intentionally
|
||||
deleted the cache and act accordingly. */
|
||||
if (rv < 0 && cache != NULL)
|
||||
{
|
||||
_dl_maybe_unload_ldsocache ();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No file to load and no loaded cache, so nothing to do. */
|
||||
if (rv < 0)
|
||||
return false;
|
||||
|
||||
/* Store the fields we check, in order they're likely to differ. We
|
||||
must do this even for the first load (CACHE == NULL below), so that
|
||||
the next call copies an accurate NEW_CACHE_FILE_TIME into
|
||||
CACHE_FILE_TIME and does not spuriously reload the unchanged cache. */
|
||||
new_cache_file_time.mtime = new_cache_file_stat.st_mtime;
|
||||
new_cache_file_time.ino = new_cache_file_stat.st_ino;
|
||||
new_cache_file_time.size = new_cache_file_stat.st_size;
|
||||
new_cache_file_time.dev = new_cache_file_stat.st_dev;
|
||||
|
||||
/* Any file is better than no file (likely the first time
|
||||
through). */
|
||||
if (cache == NULL)
|
||||
return true;
|
||||
|
||||
/* At this point, NEW_CACHE_FILE_TIME is valid as well as
|
||||
CACHE_FILE_TIME, so we compare them. */
|
||||
return (memcmp (&new_cache_file_time, &cache_file_time,
|
||||
sizeof(new_cache_file_time)));
|
||||
}
|
||||
|
||||
/* Attempts to load and validate the cache. On return, CACHE is either
|
||||
unchanged (still loaded or still not loaded) or valid. */
|
||||
static void
|
||||
_dl_maybe_load_ldsocache (void)
|
||||
{
|
||||
struct cache_file *tmp_cache = NULL;
|
||||
struct cache_file_new *tmp_cache_new = NULL;
|
||||
size_t tmp_cachesize = 0;
|
||||
|
||||
/* Read the contents of the file. */
|
||||
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &tmp_cachesize,
|
||||
PROT_READ);
|
||||
|
||||
/* We can handle three different cache file formats here:
|
||||
- only the new format
|
||||
- the old libc5/glibc2.0/2.1 format
|
||||
- the old format with the new format in it
|
||||
The following checks if the cache contains any of these formats. */
|
||||
if (file != MAP_FAILED && tmp_cachesize > sizeof *cache_new
|
||||
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((tmp_cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||
>= ((struct cache_file_new *) file)->nlibs))
|
||||
{
|
||||
if (! cache_file_new_matches_endian (file))
|
||||
{
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
tmp_cache_new = file;
|
||||
tmp_cache = file;
|
||||
}
|
||||
else if (file != MAP_FAILED && tmp_cachesize > sizeof *cache
|
||||
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((tmp_cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||
>= ((struct cache_file *) file)->nlibs))
|
||||
{
|
||||
size_t offset;
|
||||
/* Looks ok. */
|
||||
tmp_cache = file;
|
||||
|
||||
/* Check for new version. */
|
||||
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||
+ tmp_cache->nlibs * sizeof (struct file_entry));
|
||||
|
||||
tmp_cache_new = (struct cache_file_new *) ((void *) tmp_cache + offset);
|
||||
if (tmp_cachesize < (offset + sizeof (struct cache_file_new))
|
||||
|| memcmp (tmp_cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||
tmp_cache_new = NULL;
|
||||
else
|
||||
{
|
||||
if (! cache_file_new_matches_endian (tmp_cache_new))
|
||||
/* The old-format part of the cache is bogus as well
|
||||
if the endianness does not match. (But it is
|
||||
unclear how the new header can be located if the
|
||||
endianness does not match.) */
|
||||
{
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != MAP_FAILED)
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
struct cache_extension_all_loaded tmp_ext;
|
||||
if (!cache_extension_load (tmp_cache_new, tmp_cache, tmp_cachesize, &tmp_ext))
|
||||
{
|
||||
/* The extension is corrupt, so the cache is corrupt. */
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we've gotten here, the loaded cache is good and we need to
|
||||
save it. */
|
||||
_dl_maybe_unload_ldsocache ();
|
||||
cache = tmp_cache;
|
||||
cache_new = tmp_cache_new;
|
||||
cachesize = tmp_cachesize;
|
||||
ext = tmp_ext;
|
||||
|
||||
assert (cache != NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there, or null
|
||||
if none is found. The cache is loaded if it was not already. If loading
|
||||
@@ -389,81 +560,14 @@ _dl_load_cache_lookup (const char *name)
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
||||
_dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
|
||||
|
||||
if (_dl_check_ldsocache_needs_loading ())
|
||||
_dl_maybe_load_ldsocache ();
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
/* Read the contents of the file. */
|
||||
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
|
||||
PROT_READ);
|
||||
|
||||
/* We can handle three different cache file formats here:
|
||||
- only the new format
|
||||
- the old libc5/glibc2.0/2.1 format
|
||||
- the old format with the new format in it
|
||||
The following checks if the cache contains any of these formats. */
|
||||
if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
||||
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||
>= ((struct cache_file_new *) file)->nlibs))
|
||||
{
|
||||
if (! cache_file_new_matches_endian (file))
|
||||
{
|
||||
__munmap (file, cachesize);
|
||||
file = (void *) -1;
|
||||
}
|
||||
cache_new = file;
|
||||
cache = file;
|
||||
}
|
||||
else if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||
>= ((struct cache_file *) file)->nlibs))
|
||||
{
|
||||
size_t offset;
|
||||
/* Looks ok. */
|
||||
cache = file;
|
||||
|
||||
/* Check for new version. */
|
||||
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||
+ cache->nlibs * sizeof (struct file_entry));
|
||||
|
||||
cache_new = (struct cache_file_new *) ((void *) cache + offset);
|
||||
if (cachesize < (offset + sizeof (struct cache_file_new))
|
||||
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||
cache_new = (void *) -1;
|
||||
else
|
||||
{
|
||||
if (! cache_file_new_matches_endian (cache_new))
|
||||
{
|
||||
/* The old-format part of the cache is bogus as well
|
||||
if the endianness does not match. (But it is
|
||||
unclear how the new header can be located if the
|
||||
endianness does not match.) */
|
||||
cache = (void *) -1;
|
||||
cache_new = (void *) -1;
|
||||
__munmap (file, cachesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != MAP_FAILED)
|
||||
__munmap (file, cachesize);
|
||||
cache = (void *) -1;
|
||||
}
|
||||
|
||||
assert (cache != NULL);
|
||||
}
|
||||
|
||||
if (cache == (void *) -1)
|
||||
/* Previously looked for the cache file and didn't find it. */
|
||||
return NULL;
|
||||
|
||||
const char *best;
|
||||
if (cache_new != (void *) -1)
|
||||
if (cache_new != NULL)
|
||||
{
|
||||
const char *string_table = (const char *) cache_new;
|
||||
best = search_cache (string_table, cachesize,
|
||||
@@ -502,22 +606,67 @@ _dl_load_cache_lookup (const char *name)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef MAP_COPY
|
||||
/* If the system does not support MAP_COPY we cannot leave the file open
|
||||
all the time since this would create problems when the file is replaced.
|
||||
Therefore we provide this function to close the file and open it again
|
||||
once needed. */
|
||||
void
|
||||
_dl_unload_cache (void)
|
||||
const struct tunable_header_cached *
|
||||
_dl_load_cache_tunables (const char **data)
|
||||
{
|
||||
if (cache != NULL && cache != (struct cache_file *) -1)
|
||||
struct cache_extension_all_loaded ext;
|
||||
struct tunable_header_cached *thc;
|
||||
struct tunable_entry_cached *tec;
|
||||
int i, count;
|
||||
|
||||
if (_dl_check_ldsocache_needs_loading ())
|
||||
_dl_maybe_load_ldsocache ();
|
||||
|
||||
if (cache_new)
|
||||
*data = (const char *) cache_new;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
if (!cache_extension_load (cache_new, cache, cachesize, &ext))
|
||||
return NULL;
|
||||
|
||||
/* Validate length/contents here. */
|
||||
if (ext.sections[cache_extension_tag_tunables].size
|
||||
< sizeof(struct tunable_header_cached))
|
||||
return NULL;
|
||||
|
||||
thc = (struct tunable_header_cached *)
|
||||
ext.sections[cache_extension_tag_tunables].base;
|
||||
|
||||
/* Reject data produced by a different tunable cache format. */
|
||||
if (thc->signature != TUNCONF_SIGNATURE || thc->version != TUNCONF_VERSION)
|
||||
return NULL;
|
||||
|
||||
tec = thc->tunables;
|
||||
count = thc->num_tunables;
|
||||
|
||||
if (ext.sections[cache_extension_tag_tunables].base
|
||||
+ ext.sections[cache_extension_tag_tunables].size
|
||||
!= (void *) & tec[count])
|
||||
return NULL;
|
||||
|
||||
/* Validate each entry. The string table lies between the file entries
|
||||
and the end of the mapping; clamp its end to CACHESIZE so that a bogus
|
||||
len_strings cannot make an offset point outside the mapped file. */
|
||||
size_t s_start = (const char *) (&cache_new->libs[cache_new->nlibs]) - *data;
|
||||
size_t s_end;
|
||||
if (s_start >= cachesize
|
||||
|| INT_ADD_WRAPV (s_start, cache_new->len_strings, &s_end))
|
||||
return NULL;
|
||||
if (s_end > cachesize)
|
||||
s_end = cachesize;
|
||||
for (i = 0; i < count; i ++)
|
||||
{
|
||||
__munmap (cache, cachesize);
|
||||
cache = NULL;
|
||||
if (thc->tunables[i].name_offset < s_start
|
||||
|| thc->tunables[i].name_offset >= s_end
|
||||
|| thc->tunables[i].value_offset < s_start
|
||||
|| thc->tunables[i].value_offset >= s_end)
|
||||
return NULL;
|
||||
if (thc->tunables[i].flag_offset != 0
|
||||
&& (thc->tunables[i].flag_offset < s_start
|
||||
|| thc->tunables[i].flag_offset >= s_end))
|
||||
return NULL;
|
||||
}
|
||||
#ifdef SHARED
|
||||
/* This marks the glibc_hwcaps_priorities array as out-of-date. */
|
||||
glibc_hwcaps_priorities_length = 0;
|
||||
#endif
|
||||
|
||||
return thc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -898,11 +898,6 @@ no more namespaces available for dlmopen()"));
|
||||
struct dl_exception exception;
|
||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||
|
||||
#if defined USE_LDCONFIG && !defined MAP_COPY
|
||||
/* We must unmap the cache file. */
|
||||
_dl_unload_cache ();
|
||||
#endif
|
||||
|
||||
/* Do this for both the error and success cases. The old value has
|
||||
only been determined if the namespace ID was assigned (i.e., it
|
||||
is not __LM_ID_CALLER). In the success case, we actually may
|
||||
|
||||
@@ -80,7 +80,7 @@ _dl_relocate_static_pie (void)
|
||||
|
||||
/* Relocate ourselves so we can do normal function calls and data access
|
||||
using the global offset table. IRELATIVE entries are deferred. */
|
||||
ELF_DYNAMIC_RELOCATE_NOIFUNC (main_map, NULL, 0, 0);
|
||||
ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, main_map, NULL, 0, 0, 0);
|
||||
|
||||
/* Initialize _r_debug_extended. */
|
||||
struct r_debug *r = _dl_debug_initialize (0, LM_ID_BASE);
|
||||
@@ -98,7 +98,7 @@ void
|
||||
_dl_relocate_static_pie_ifunc (void)
|
||||
{
|
||||
struct link_map *main_map = _dl_get_dl_main_map ();
|
||||
ELF_DYNAMIC_RELOCATE_IFUNC (main_map, NULL, 0, 0);
|
||||
ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, main_map, NULL, 0, 0, 0);
|
||||
main_map->l_relocated = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
+4
-2
@@ -278,7 +278,8 @@ _dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
|
||||
IFUNC resolvers. Without this, a resolver would see the unrelocated
|
||||
initialiser bytes that were placed into the slot by the early
|
||||
_dl_allocate_tls_init. */
|
||||
ELF_DYNAMIC_RELOCATE_NOIFUNC (l, scope, lazy, consider_profiling);
|
||||
ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, l, scope, lazy,
|
||||
consider_profiling, skip_ifunc);
|
||||
|
||||
#ifdef SHARED
|
||||
/* Re-initialise the static TLS slot with the .tdata so the IRELATIVE
|
||||
@@ -291,7 +292,8 @@ _dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
|
||||
_dl_init_static_tls (l);
|
||||
#endif
|
||||
|
||||
ELF_DYNAMIC_RELOCATE_IFUNC (l, scope, lazy, skip_ifunc);
|
||||
ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, l, scope, lazy,
|
||||
0, skip_ifunc);
|
||||
|
||||
if ((consider_profiling || consider_symbind)
|
||||
&& l->l_info[DT_PLTRELSZ] != NULL)
|
||||
|
||||
+2
-14
@@ -42,20 +42,6 @@ typedef struct
|
||||
tunable_num_t max;
|
||||
} tunable_type_t;
|
||||
|
||||
/* Security level for tunables. This decides what to do with individual
|
||||
tunables for AT_SECURE binaries. */
|
||||
typedef enum
|
||||
{
|
||||
/* Erase the tunable for AT_SECURE binaries so that child processes don't
|
||||
read it. */
|
||||
TUNABLE_SECLEVEL_SXID_ERASE = 0,
|
||||
/* Ignore the tunable for AT_SECURE binaries, but don't erase it, so that
|
||||
child processes can read it. */
|
||||
TUNABLE_SECLEVEL_SXID_IGNORE = 1,
|
||||
/* Read the tunable. */
|
||||
TUNABLE_SECLEVEL_NONE = 2,
|
||||
} tunable_seclevel_t;
|
||||
|
||||
/* A tunable. */
|
||||
struct _tunable
|
||||
{
|
||||
@@ -65,6 +51,8 @@ struct _tunable
|
||||
tunable_val_t val; /* The value. */
|
||||
bool initialized; /* Flag to indicate that the tunable is
|
||||
initialized. */
|
||||
bool locked; /* If set, modifications are not
|
||||
allowed. */
|
||||
/* Compatibility elements. */
|
||||
const char env_alias[TUNABLE_ALIAS_MAX]; /* The compatibility environment
|
||||
variable name. */
|
||||
|
||||
+172
-3
@@ -37,6 +37,7 @@
|
||||
|
||||
#define TUNABLES_INTERNAL 1
|
||||
#include "dl-tunables.h"
|
||||
#include "tunconf.h"
|
||||
|
||||
static char **
|
||||
get_next_env (char **envp, char **name, char **val, char ***prev_envp)
|
||||
@@ -71,6 +72,9 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
|
||||
{
|
||||
tunable_num_t val, min, max;
|
||||
|
||||
if (cur->locked)
|
||||
return;
|
||||
|
||||
switch (cur->type.type_code)
|
||||
{
|
||||
case TUNABLE_TYPE_STRING:
|
||||
@@ -175,6 +179,14 @@ struct tunable_toset_t
|
||||
|
||||
enum { tunables_list_size = array_length (tunable_list) };
|
||||
|
||||
/* Records tunables that were set from GLIBC_TUNABLES during this call, so
|
||||
that a legacy environment-variable alias does not override them (the
|
||||
canonical GLIBC_TUNABLES form takes precedence over the aliases).
|
||||
A tunable that was set only from the system-wide cache is deliberately not
|
||||
recorded here, so an alias may still override an overridable cache default;
|
||||
a nonoverridable one remains protected by tunable_t::locked. */
|
||||
static bool tunable_set_by_env[tunables_list_size];
|
||||
|
||||
/* Parse the tunable string VALSTRING and set TUNABLES with the found tunables
|
||||
and their respective values. The VALSTRING is parsed in place, with the
|
||||
tunable start and size recorded in TUNABLES.
|
||||
@@ -284,6 +296,10 @@ parse_tunables (const char *valstring)
|
||||
if (!tunable_initialize (tunables[i].t, tunables[i].value,
|
||||
tunables[i].len))
|
||||
parse_tunable_print_error (&tunables[i]);
|
||||
else
|
||||
/* GLIBC_TUNABLES set this tunable; a legacy alias must not
|
||||
override it. */
|
||||
tunable_set_by_env[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +307,7 @@ parse_tunables (const char *valstring)
|
||||
ENV_ALIAS to find values. Later we will also use the tunable names to find
|
||||
values. */
|
||||
void
|
||||
__tunables_init (char **envp)
|
||||
__tunables_init (char **envp, char **argv)
|
||||
{
|
||||
char *envname = NULL;
|
||||
char *envval = NULL;
|
||||
@@ -302,6 +318,155 @@ __tunables_init (char **envp)
|
||||
if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
|
||||
TUNABLE_SET (glibc, malloc, hugetlb, 1);
|
||||
|
||||
#if defined(SHARED) && defined (USE_LDCONFIG)
|
||||
const char *prog_name = (argv && argv[0]) ? argv[0] : "";
|
||||
int prog_name_len = -1;
|
||||
const char *base_name = NULL;
|
||||
#ifdef PATH_MAX
|
||||
char exebuf[PATH_MAX];
|
||||
#else
|
||||
char exebuf[256];
|
||||
#endif
|
||||
const struct tunable_header_cached *thc;
|
||||
const char *td;
|
||||
|
||||
thc = _dl_load_cache_tunables (&td);
|
||||
if (thc != NULL)
|
||||
{
|
||||
for (int t = 0; t < thc->num_tunables; ++ t)
|
||||
{
|
||||
const struct tunable_entry_cached *tec = &( thc->tunables[t] );
|
||||
int tid = tec->tunable_id;
|
||||
const char *name = td + tec->name_offset;
|
||||
const char *value = td + tec->value_offset;
|
||||
|
||||
/* Check that we have the correct tunable, and search by
|
||||
name if needed. We rely on order of operations here to
|
||||
avoid mis-indexing tunables[]. */
|
||||
if (tid < 0 || tid >= tunables_list_size
|
||||
|| strcmp (name, tunable_list[tid].name) != 0)
|
||||
{
|
||||
/* It does not, search by name instead. */
|
||||
tid = -1;
|
||||
for (int i = 0; i < tunables_list_size; i++)
|
||||
{
|
||||
if (strcmp (name, tunable_list[i].name) == 0)
|
||||
{
|
||||
tid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tid == -1)
|
||||
continue;
|
||||
}
|
||||
/* At this point, TID is valid for the tunable we want. */
|
||||
|
||||
if (tec->flags & TUNCONF_EXCLUDE_SECURE && __libc_enable_secure)
|
||||
goto skip_due_to_filter;
|
||||
if (tec->flags & TUNCONF_EXCLUDE_UNSECURE && !__libc_enable_secure)
|
||||
goto skip_due_to_filter;
|
||||
|
||||
/* Apply selected filter, if any. */
|
||||
switch (tec->flags & TUNCONF_FLAG_FILTER) {
|
||||
case TUNCONF_FILTER_NONE:
|
||||
break;
|
||||
case TUNCONF_FILTER_PERPROC:
|
||||
/* Perform one-time calculations that aren't needed if we
|
||||
don't use this filter. */
|
||||
if (prog_name_len == -1)
|
||||
{
|
||||
ssize_t n = readlink ("/proc/self/exe",
|
||||
exebuf, sizeof (exebuf) - 1);
|
||||
if (n > 0 && n < sizeof(exebuf)-1)
|
||||
{
|
||||
/* If /proc/self/exe exists and we can read it,
|
||||
it's more reliable than argv[] so use it. */
|
||||
exebuf[n] = '\0';
|
||||
prog_name = exebuf;
|
||||
}
|
||||
else if (__libc_enable_secure)
|
||||
prog_name = NULL;
|
||||
if (prog_name != NULL)
|
||||
{
|
||||
const char *slash = NULL, *cp;
|
||||
for (cp = prog_name; *cp; ++ cp)
|
||||
if (*cp == '/')
|
||||
slash = cp;
|
||||
if (slash)
|
||||
base_name = slash + 1;
|
||||
else
|
||||
base_name = prog_name;
|
||||
prog_name_len = strlen (prog_name);
|
||||
}
|
||||
}
|
||||
/* prog_name and the cached string are both NUL terminated. */
|
||||
if (prog_name)
|
||||
{
|
||||
if (((const char *)(td + tec->flag_offset))[0] == '/')
|
||||
{
|
||||
if (strcmp (prog_name, td + tec->flag_offset) != 0)
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp (base_name, td + tec->flag_offset) != 0)
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Program is AT_SECURE but the only source of program
|
||||
name is argv[0], which is not secure, so we do not
|
||||
match any name-based filter. */
|
||||
goto skip_due_to_filter;
|
||||
break;
|
||||
default:
|
||||
/* Unknown filter. */
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
|
||||
/* If the tunable is set here, any previously set
|
||||
overridability flag is discarded. We need to reset the
|
||||
overridability flag here so we can change the tunable,
|
||||
and may set it later if this tunable also locks it. */
|
||||
tunable_list[tid].locked = false;
|
||||
|
||||
/* See if the parsed type matches the desired type. */
|
||||
if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING)
|
||||
{
|
||||
/* This is a memory leak but there's no easy way around
|
||||
it, as the mapping will go away if the disk file is
|
||||
updated and the cache is reloaded. */
|
||||
tunable_list[tid].val.strval.str = __strdup (value);
|
||||
tunable_list[tid].val.strval.len = strlen (value);
|
||||
tunable_list[tid].initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tunable_val_t tval;
|
||||
if (tec->flags & TUNCONF_FLAG_PARSED)
|
||||
{
|
||||
tval.numval = tec->parsed_value;
|
||||
do_tunable_update_val (& tunable_list[tid],
|
||||
&tval, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
tunable_initialize (& tunable_list[tid],
|
||||
value, strlen (value));
|
||||
}
|
||||
}
|
||||
|
||||
/* The overriability flag only applies to tunables
|
||||
which aren't filtered out. */
|
||||
if ((tec->flags & TUNCONF_FLAG_OVERRIDABLE)
|
||||
== TUNCONF_OVERRIDE_DENY)
|
||||
tunable_list[tid].locked = true;
|
||||
|
||||
skip_due_to_filter:;
|
||||
}
|
||||
}
|
||||
#endif /* defined(SHARED) && defined (USE_LDCONFIG) */
|
||||
|
||||
/* Ignore tunables for AT_SECURE programs. */
|
||||
if (__libc_enable_secure)
|
||||
return;
|
||||
@@ -345,9 +510,13 @@ __tunables_init (char **envp)
|
||||
|
||||
for (int i = 0; i < tunable_num_env_alias; i++)
|
||||
{
|
||||
/* Skip over tunables that have either been set or already initialized. */
|
||||
/* Skip aliases whose tunable was already set through GLIBC_TUNABLES,
|
||||
which takes precedence over the alias. A value coming only from the
|
||||
system-wide cache does not block the alias here: an overridable cache
|
||||
default may still be overridden, while a nonoverridable one is
|
||||
protected by tunable_t::locked. */
|
||||
if (tunables_env_alias[i].t == NULL
|
||||
|| tunables_env_alias[i].t->initialized)
|
||||
|| tunable_set_by_env[tunable_env_alias_list[i]])
|
||||
continue;
|
||||
|
||||
if (!tunable_initialize (tunables_env_alias[i].t,
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
|
||||
|
||||
#include "dl-tunable-list.h"
|
||||
|
||||
extern void __tunables_init (char **);
|
||||
extern void __tunables_init (char **, char **);
|
||||
extern void __tunables_print (void);
|
||||
extern bool __tunable_is_initialized (tunable_id_t);
|
||||
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
|
||||
|
||||
+23
-9
@@ -45,7 +45,13 @@ elf_dynamic_is_Rel_irelative (const ElfW(Rel) *reloc, const ElfW(Sym) *sym)
|
||||
return ((sym != NULL
|
||||
&& ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC
|
||||
&& sym->st_shndx != SHN_UNDEF)
|
||||
|| r_type == ELF_MACHINE_IRELATIVE);
|
||||
|| r_type == ELF_MACHINE_IRELATIVE
|
||||
# ifdef ELF_MACHINE_IRELATIVE_PLT
|
||||
/* Some ports resolve an IFUNC PLT slot for a local resolver with a
|
||||
dedicated reloc that carries no symboli. */
|
||||
|| r_type == ELF_MACHINE_IRELATIVE_PLT
|
||||
# endif
|
||||
);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@@ -73,17 +79,23 @@ elf_dynamic_Rel_audit_symbind (struct link_map *map,
|
||||
/* Perform the relocations in MAP on the running program image as specified
|
||||
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
|
||||
relocations; they should be set up to call _dl_runtime_resolve, rather
|
||||
than fully resolved now.
|
||||
than fully resolved now. If SKIP_IFUNC is nonzero no IFUNC resolver is
|
||||
called; this is required for the trace modes (ldd -u / ldd -r), which
|
||||
relocate objects.
|
||||
|
||||
IRELATIVE entries are always skipped (non-bootstrap); they are handled
|
||||
IRELATIVE entries and relocations against an STT_GNU_IFUNC symbol defined
|
||||
in MAP itself are always skipped (non-bootstrap); they are handled
|
||||
separately by elf_dynamic_do_Rel_irelative after all other relocations
|
||||
for both .rel.dyn and .rel.plt have been processed. */
|
||||
for both .rel.dyn and .rel.plt have been processed. Relocations against
|
||||
an IFUNC symbol defined in *another* object are not deferred, since the
|
||||
IFUNC symbol is only known after symbol resolution, and the defining object
|
||||
has already been relocated at this point. */
|
||||
|
||||
static inline void __attribute__ ((always_inline))
|
||||
elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
ElfW(Addr) reladdr, ElfW(Addr) relsize,
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
|
||||
int lazy)
|
||||
int lazy, int skip_ifunc)
|
||||
{
|
||||
const ElfW(Rel) *relative = (const void *) reladdr;
|
||||
const ElfW(Rel) *r = relative + nrelative;
|
||||
@@ -105,7 +117,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
|
||||
const struct r_found_version *rversion = &map->l_versions[ndx];
|
||||
|
||||
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, 0);
|
||||
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, skip_ifunc);
|
||||
}
|
||||
#else /* !RTLD_BOOTSTRAP */
|
||||
#if !defined DO_RELA || !defined ELF_MACHINE_PLT_REL
|
||||
@@ -120,7 +132,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
const ElfW (Sym) *sym = &symtab[ELFW (R_SYM) (r->r_info)];
|
||||
if (elf_dynamic_is_Rel_irelative (r, sym))
|
||||
continue;
|
||||
elf_machine_lazy_rel (map, scope, l_addr, r, 0);
|
||||
elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -152,7 +164,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
if (elf_dynamic_is_Rel_irelative (r, sym))
|
||||
continue;
|
||||
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, 0);
|
||||
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
|
||||
skip_ifunc);
|
||||
elf_dynamic_Rel_audit_symbind (map, scope, r, sym, rversion,
|
||||
r_addr_arg);
|
||||
}
|
||||
@@ -166,7 +179,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
if (elf_dynamic_is_Rel_irelative (r, sym))
|
||||
continue;
|
||||
elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg, 0);
|
||||
elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
|
||||
skip_ifunc);
|
||||
elf_dynamic_Rel_audit_symbind (map, scope, r, sym, NULL,
|
||||
r_addr_arg);
|
||||
}
|
||||
|
||||
+52
-65
@@ -78,18 +78,23 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
|
||||
are completely separate and there is a gap between them. */
|
||||
|
||||
/* This controls which sub-passes _ELF_DYNAMIC_DO_RELOC runs. Used to
|
||||
interleave TLS / stack-protector setup between the two passes so IFUNC
|
||||
resolvers see a fully-initialised TCB. */
|
||||
enum elf_dynamic_reloc_phase
|
||||
/* Selects which relocations a pass processes. Splitting them allows the
|
||||
caller to interleave TLS / stack-protector setup between the two passes,
|
||||
so IFUNC resolvers see a fully-initialised TCB.
|
||||
|
||||
This is orthogonal to the skip_ifunc argument, which says whether an IFUNC
|
||||
resolver may be run at all and is honoured by every pass. In particular
|
||||
DL_RELOC_NORMAL also runs IFUNC resolvers, for relocations against an
|
||||
IFUNC symbol defined in another object. */
|
||||
enum elf_dynamic_reloc_pass
|
||||
{
|
||||
DL_RELOC_BOTH = 0, /* Non-IRELATIVE pass then IRELATIVE pass. */
|
||||
DL_RELOC_NOIFUNC = 1, /* Non-IRELATIVE pass only. */
|
||||
DL_RELOC_IFUNC = 2, /* IRELATIVE pass only. */
|
||||
DL_RELOC_ALL = 0, /* Non-IRELATIVE relocations, then IRELATIVE. */
|
||||
DL_RELOC_NORMAL = 1, /* Non-IRELATIVE relocations only. */
|
||||
DL_RELOC_IRELATIVE = 2, /* IRELATIVE relocations only. */
|
||||
};
|
||||
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, \
|
||||
test_rel, phase) \
|
||||
test_rel, pass) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; \
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
|
||||
@@ -136,14 +141,15 @@ enum elf_dynamic_reloc_phase
|
||||
by the linker. */ \
|
||||
if (!DO_RTLD_BOOTSTRAP) \
|
||||
{ \
|
||||
if ((phase) != DL_RELOC_IFUNC) \
|
||||
if ((pass) != DL_RELOC_IRELATIVE) \
|
||||
for (int ranges_index = 0; ranges_index < 2; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc ((map), scope, \
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].nrelative, \
|
||||
ranges[ranges_index].lazy); \
|
||||
if ((phase) != DL_RELOC_NOIFUNC) \
|
||||
ranges[ranges_index].lazy, \
|
||||
skip_ifunc); \
|
||||
if ((pass) != DL_RELOC_NORMAL) \
|
||||
for (int ranges_index = 0; ranges_index < 2; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc##_irelative ((map), scope, \
|
||||
ranges[ranges_index].start, \
|
||||
@@ -158,7 +164,8 @@ enum elf_dynamic_reloc_phase
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].nrelative, \
|
||||
ranges[ranges_index].lazy); \
|
||||
ranges[ranges_index].lazy, \
|
||||
skip_ifunc); \
|
||||
} while (0)
|
||||
|
||||
# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
|
||||
@@ -169,37 +176,21 @@ enum elf_dynamic_reloc_phase
|
||||
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc, pass) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, \
|
||||
_ELF_CHECK_REL, DL_RELOC_BOTH)
|
||||
# define ELF_DYNAMIC_DO_REL_NOIFUNC(map, scope, lazy) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, 0, \
|
||||
_ELF_CHECK_REL, DL_RELOC_NOIFUNC)
|
||||
# define ELF_DYNAMIC_DO_REL_IFUNCONLY(map, scope, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, \
|
||||
_ELF_CHECK_REL, DL_RELOC_IFUNC)
|
||||
_ELF_CHECK_REL, pass)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_REL_NOIFUNC(map, scope, lazy) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_REL_IFUNCONLY(map, scope, lazy, skip_ifunc) /* Nothing. */
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc, pass) /* Nothing. */
|
||||
# endif
|
||||
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
# define DO_RELA
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc, pass) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, \
|
||||
_ELF_CHECK_REL, DL_RELOC_BOTH)
|
||||
# define ELF_DYNAMIC_DO_RELA_NOIFUNC(map, scope, lazy) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, 0, \
|
||||
_ELF_CHECK_REL, DL_RELOC_NOIFUNC)
|
||||
# define ELF_DYNAMIC_DO_RELA_IFUNCONLY(map, scope, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, \
|
||||
_ELF_CHECK_REL, DL_RELOC_IFUNC)
|
||||
_ELF_CHECK_REL, pass)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_RELA_NOIFUNC(map, scope, lazy) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_RELA_IFUNCONLY(map, scope, lazy, skip_ifunc) /* Nothing. */
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc, pass) /* Nothing. */
|
||||
# endif
|
||||
|
||||
# define ELF_DYNAMIC_DO_RELR(map) \
|
||||
@@ -240,37 +231,33 @@ enum elf_dynamic_reloc_phase
|
||||
# else
|
||||
# define DO_RTLD_BOOTSTRAP 0
|
||||
# endif
|
||||
/* Perform one relocation pass over MAP. PASS selects which relocations are
|
||||
processed. It is orthogonal to SKIP_IFUNC, which suppresses running IFUNC
|
||||
resolvers in whichever pass is selected.
|
||||
|
||||
Unless PASS is DL_RELOC_IRELATIVE, this also performs the machine-specific
|
||||
PLT/GOT setup, the DT_RELR relocations, and the ELF_DYNAMIC_AFTER_RELOC
|
||||
hook. */
|
||||
# define ELF_DYNAMIC_RELOCATE_PASS(pass, map, scope, lazy, consider_profile, \
|
||||
skip_ifunc) \
|
||||
do { \
|
||||
int edr_lazy = (lazy); \
|
||||
if ((pass) != DL_RELOC_IRELATIVE) \
|
||||
{ \
|
||||
edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
|
||||
(consider_profile)); \
|
||||
if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP) \
|
||||
ELF_DYNAMIC_DO_RELR (map); \
|
||||
} \
|
||||
ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc, (pass)); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc, (pass)); \
|
||||
if ((pass) != DL_RELOC_IRELATIVE) \
|
||||
ELF_DYNAMIC_AFTER_RELOC ((map), edr_lazy); \
|
||||
} while (0)
|
||||
|
||||
/* Run both passes back to back, for callers with nothing to interleave. */
|
||||
# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
|
||||
do { \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
|
||||
(consider_profile)); \
|
||||
if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP) \
|
||||
ELF_DYNAMIC_DO_RELR (map); \
|
||||
ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_AFTER_RELOC ((map), (edr_lazy)); \
|
||||
} while (0)
|
||||
|
||||
/* Like ELF_DYNAMIC_RELOCATE but only processes the non-IRELATIVE pass.
|
||||
The IRELATIVE pass must be completed later via ELF_DYNAMIC_RELOCATE_IFUNC.
|
||||
Used by the static-pie startup so the TCB and stack-protector canary can
|
||||
be initialised between the two passes. */
|
||||
# define ELF_DYNAMIC_RELOCATE_NOIFUNC(map, scope, lazy, consider_profile) \
|
||||
do { \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
|
||||
(consider_profile)); \
|
||||
if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP) \
|
||||
ELF_DYNAMIC_DO_RELR (map); \
|
||||
ELF_DYNAMIC_DO_REL_NOIFUNC ((map), (scope), edr_lazy); \
|
||||
ELF_DYNAMIC_DO_RELA_NOIFUNC ((map), (scope), edr_lazy); \
|
||||
ELF_DYNAMIC_AFTER_RELOC ((map), (edr_lazy)); \
|
||||
} while (0)
|
||||
|
||||
/* IRELATIVE-only companion to ELF_DYNAMIC_RELOCATE_NOIFUNC. */
|
||||
# define ELF_DYNAMIC_RELOCATE_IFUNC(map, scope, lazy, skip_ifunc) \
|
||||
do { \
|
||||
ELF_DYNAMIC_DO_REL_IFUNCONLY ((map), (scope), (lazy), skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_RELA_IFUNCONLY ((map), (scope), (lazy), skip_ifunc); \
|
||||
} while (0)
|
||||
ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_ALL, (map), (scope), (lazy), \
|
||||
(consider_profile), skip_ifunc)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -847,6 +847,7 @@ typedef struct
|
||||
#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
|
||||
#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
|
||||
address control */
|
||||
#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
|
||||
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
|
||||
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
|
||||
status registers. */
|
||||
|
||||
@@ -47,8 +47,10 @@ ldconfig_parse_config_1 (const char *filename, bool do_chroot,
|
||||
|
||||
opt_chroot - If non-NULL, all paths are relative to this.
|
||||
|
||||
callback - for each non-blank line in the file, this function is called
|
||||
with the line and it's location.
|
||||
callback - for each non-blank line in the file, this function is
|
||||
called with the line and it's location. Will also be called
|
||||
with a NULL line at the start and end of each file, for
|
||||
file-scoped config items.
|
||||
*/
|
||||
|
||||
void
|
||||
|
||||
+183
-5
@@ -44,12 +44,17 @@
|
||||
#include <dl-cache.h>
|
||||
#include <dl-hwcaps.h>
|
||||
#include <dl-is_dso.h>
|
||||
#include "tunconf.h"
|
||||
|
||||
|
||||
#ifndef LD_SO_CONF
|
||||
# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
|
||||
#endif
|
||||
|
||||
#ifndef TUNABLES_CONF
|
||||
# define TUNABLES_CONF SYSCONFDIR "/tunables.conf"
|
||||
#endif
|
||||
|
||||
/* Get libc version number. */
|
||||
#include <version.h>
|
||||
|
||||
@@ -104,12 +109,18 @@ static int opt_manual_link;
|
||||
/* Should we ignore an old auxiliary cache file? */
|
||||
static int opt_ignore_aux_cache;
|
||||
|
||||
/* Install a pre-existing cache file instead of generating a new one. */
|
||||
static int opt_install;
|
||||
|
||||
/* Cache file to use. */
|
||||
static char *cache_file;
|
||||
|
||||
/* Configuration file. */
|
||||
/* Configuration file for libraries. */
|
||||
static const char *config_file;
|
||||
|
||||
/* Configuration file for tunables. */
|
||||
static const char *tunconfig_file;
|
||||
|
||||
/* Name and version of program. */
|
||||
static void print_version (FILE *stream, struct argp_state *state);
|
||||
void (*argp_program_version_hook) (FILE *, struct argp_state *)
|
||||
@@ -127,11 +138,13 @@ static const struct argp_option options[] =
|
||||
{ NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0},
|
||||
{ NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
|
||||
{ NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
|
||||
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
|
||||
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file for libraries"), 0},
|
||||
{ NULL, 't', N_("TUNCONF"), 0, N_("Use TUNCONF as configuration file for tunables"), 0},
|
||||
{ NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
|
||||
{ NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
|
||||
{ "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0},
|
||||
{ "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
|
||||
{ "install", 'I', NULL, 0, N_("Install pre-existing cache file"), 0},
|
||||
{ NULL, 0, NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -164,6 +177,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case 'f':
|
||||
config_file = arg;
|
||||
break;
|
||||
case 't':
|
||||
tunconfig_file = arg;
|
||||
break;
|
||||
case 'i':
|
||||
opt_ignore_aux_cache = 1;
|
||||
break;
|
||||
@@ -197,6 +213,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
else if (strcmp (arg, "new") == 0)
|
||||
opt_format = opt_format_new;
|
||||
break;
|
||||
case 'I':
|
||||
opt_install = 1;
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
@@ -421,8 +440,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||
}
|
||||
|
||||
static void
|
||||
add_dir_callback (const char *line, const char *from_file, int from_line)
|
||||
add_dir_callback (char *line, const char *from_file, int from_line)
|
||||
{
|
||||
/* Denotes file boundaries. Not needed here. */
|
||||
if (line == NULL)
|
||||
return;
|
||||
if (!strncasecmp (line, "hwcap", 5) && isblank (line[5]))
|
||||
error (0, 0, _("%s:%u: hwcap directive ignored"), from_file, from_line);
|
||||
else
|
||||
@@ -1026,6 +1048,155 @@ search_dirs (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
install_cache_file (const char *source_arg)
|
||||
{
|
||||
int e;
|
||||
|
||||
if (source_arg == NULL)
|
||||
error (EXIT_FAILURE, 0, _("Missing source file name"));
|
||||
|
||||
const char *source = (opt_chroot
|
||||
? chroot_canon (opt_chroot, source_arg)
|
||||
: source_arg);
|
||||
if (source == NULL)
|
||||
error (EXIT_FAILURE, errno, _("Can't find %s"), source_arg);
|
||||
|
||||
int src_fd = open (source, O_RDONLY);
|
||||
if (src_fd < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't open %s"), source);
|
||||
|
||||
char *dest = xmalloc (strlen (cache_file) + 1 + 1);
|
||||
|
||||
/* This matches the temp file created by cache.c, and should be
|
||||
on the same filesystem as the cache file. */
|
||||
sprintf (dest, "%s~", cache_file);
|
||||
int dest_fd;
|
||||
|
||||
struct stat st;
|
||||
if (fstat (src_fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't stat %s"), source);
|
||||
|
||||
char buf[512];
|
||||
ssize_t r, w = 0, sz = 0;
|
||||
char *bp = buf;
|
||||
|
||||
/* Read the first part of the file and verify it looks
|
||||
reasonable. */
|
||||
while (sz < sizeof (buf)
|
||||
&& (r = read (src_fd, bp, sizeof (buf) - sz)) > 0)
|
||||
{
|
||||
sz += r;
|
||||
bp += r;
|
||||
}
|
||||
if (r < 0)
|
||||
error (EXIT_FAILURE, errno, _("Error reading file %s"), source);
|
||||
|
||||
if (! ((sz >= sizeof (CACHEMAGIC)
|
||||
&& memcmp (buf, CACHEMAGIC,
|
||||
sizeof (CACHEMAGIC) - 1) == 0)
|
||||
|| (sz >= sizeof (CACHEMAGIC_NEW)
|
||||
&& memcmp (buf, CACHEMAGIC_NEW,
|
||||
sizeof (CACHEMAGIC_NEW) - 1) == 0)))
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("File %s does not look like an ld.so.cache file"),
|
||||
source);
|
||||
}
|
||||
|
||||
/* Now write that first part out. */
|
||||
dest_fd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
|
||||
S_IRUSR|S_IWUSR);
|
||||
if (dest_fd < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't create %s"), dest);
|
||||
|
||||
r = sz;
|
||||
bp = buf;
|
||||
while (r > 0 && (w = write (dest_fd, bp, r)) > 0)
|
||||
{
|
||||
r -= w;
|
||||
bp += w;
|
||||
}
|
||||
if (w < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error writing file %s"), dest);
|
||||
}
|
||||
|
||||
/* At this point, sz contains the number of bytes copied so far.
|
||||
Copy the rest of the file. */
|
||||
while ((r = read (src_fd, buf, sizeof(buf))) > 0)
|
||||
{
|
||||
bp = buf;
|
||||
while (r > 0 && (w = write (dest_fd, bp, r)) > 0)
|
||||
{
|
||||
bp += w;
|
||||
r -= w;
|
||||
sz += w;
|
||||
}
|
||||
if (w <= 0)
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error reading file %s"), source);
|
||||
}
|
||||
if (w < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error writing file %s"), dest);
|
||||
}
|
||||
|
||||
close (src_fd);
|
||||
|
||||
/* Make sure we copied it all. */
|
||||
if (sz < st.st_size)
|
||||
{
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, 0, _("Unable to copy file %s to %s"),
|
||||
source, dest);
|
||||
}
|
||||
|
||||
/* Make sure user can always read the cache file */
|
||||
if (fchmod (dest_fd, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e,
|
||||
_("Changing access rights of %s to %#o failed"), dest,
|
||||
S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
|
||||
}
|
||||
|
||||
if (fsync (dest_fd) != 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Writing to %s failed"), dest);
|
||||
}
|
||||
|
||||
if (rename (dest, cache_file) < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Can't rename %s to %s"),
|
||||
dest, cache_file);
|
||||
}
|
||||
|
||||
if (close (dest_fd) != 0)
|
||||
error (EXIT_FAILURE, errno, _("Writing to %s failed"), dest);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@@ -1045,8 +1216,8 @@ main (int argc, char **argv)
|
||||
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
|
||||
|
||||
/* Remaining arguments are additional directories if opt_manual_link
|
||||
is not set. */
|
||||
if (remaining != argc && !opt_manual_link)
|
||||
and opt_install are not set. */
|
||||
if (remaining != argc && !opt_manual_link && !opt_install)
|
||||
{
|
||||
int i;
|
||||
for (i = remaining; i < argc; ++i)
|
||||
@@ -1089,6 +1260,9 @@ main (int argc, char **argv)
|
||||
if (config_file == NULL)
|
||||
config_file = LD_SO_CONF;
|
||||
|
||||
if (tunconfig_file == NULL)
|
||||
tunconfig_file = TUNABLES_CONF;
|
||||
|
||||
if (opt_print_cache)
|
||||
{
|
||||
if (opt_chroot != NULL)
|
||||
@@ -1139,6 +1313,8 @@ main (int argc, char **argv)
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if (opt_install)
|
||||
install_cache_file (argv[remaining]);
|
||||
|
||||
if (opt_build_cache)
|
||||
init_cache ();
|
||||
@@ -1164,6 +1340,8 @@ main (int argc, char **argv)
|
||||
|
||||
search_dirs ();
|
||||
|
||||
parse_tunconf (tunconfig_file, opt_chroot);
|
||||
|
||||
if (opt_build_cache)
|
||||
{
|
||||
save_cache (cache_file);
|
||||
|
||||
@@ -2371,11 +2371,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Auditing checkpoint: we have added all objects. */
|
||||
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
|
||||
|
||||
#if defined USE_LDCONFIG && !defined MAP_COPY
|
||||
/* We must munmap() the cache file. */
|
||||
_dl_unload_cache ();
|
||||
#endif
|
||||
|
||||
/* Once we return, _dl_sysdep_start will invoke
|
||||
the DT_INIT functions and then *USER_ENTRY. */
|
||||
}
|
||||
|
||||
+3
-8
@@ -1,5 +1,5 @@
|
||||
/* Symbol rediretion for loader/static initialization code.
|
||||
Copyright (C) 2022-2026 Free Software Foundation, Inc.
|
||||
/* Program calling an IFUNC defined in a dependency. BIND_NOW variant.
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -16,9 +16,4 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _DL_IFUNC_GENERIC_H
|
||||
#define _DL_IFUNC_GENERIC_H
|
||||
|
||||
asm ("memset = __memset_ultra1");
|
||||
|
||||
#endif
|
||||
#include "tst-ifunc-fault-dep-lazy.c"
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Definitions for ifunc resolvers for malloc: aarch64 version.
|
||||
/* Program calling an IFUNC defined in a dependency (BZ 34428).
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _AARCH64_MALLOC_IFUNCS_H
|
||||
#define _AARCH64_MALLOC_IFUNCS_H
|
||||
extern void magic (void);
|
||||
|
||||
#define USE_MULTIARCH_MALLOC 1
|
||||
|
||||
#endif /* _AARCH64_MALLOC_IFUNCS_H */
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
/* JMP_SLOT relocation against an undefined symbol. */
|
||||
magic ();
|
||||
return 1;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Definitions for ifunc resolvers for malloc: generic version.
|
||||
/* Shared object exporting an IFUNC symbol with a resolver which crashes.
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@@ -16,21 +16,23 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GENERIC_MALLOC_IFUNCS_H
|
||||
#define _GENERIC_MALLOC_IFUNCS_H
|
||||
#include <stddef.h>
|
||||
|
||||
/* Targets that support GNU ifuncs should define this macro
|
||||
if they provide ifuncs for malloc functions.
|
||||
static void
|
||||
implementation (void)
|
||||
{
|
||||
/* Produce a crash, without depending on any relocations. */
|
||||
volatile char *volatile p = NULL;
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
When USE_MULTIARCH_MALLOC is defined as 1, the following
|
||||
functions should be implemented via ifuncs:
|
||||
static __typeof__ (implementation) *
|
||||
resolver (void)
|
||||
{
|
||||
/* Produce a crash, without depending on any relocations. */
|
||||
volatile char *volatile p = NULL;
|
||||
*p = 0;
|
||||
return implementation;
|
||||
}
|
||||
|
||||
malloc, calloc, free, realloc
|
||||
memalign, valloc, pvalloc
|
||||
posix_memalign
|
||||
malloc_usable_size
|
||||
aligned_alloc, free_sized, free_aligned_sized
|
||||
*/
|
||||
#define USE_MULTIARCH_MALLOC 0
|
||||
|
||||
#endif /* _GENERIC_MALLOC_IFUNCS_H */
|
||||
void magic (void) __attribute__ ((ifunc ("resolver")));
|
||||
@@ -0,0 +1,137 @@
|
||||
/* Test ldconfig cache is correctly used when changed.
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* What we're testing for: We initially load ld.so.cache at startup
|
||||
and remember it. If we detect that ld.so.cache has changed, and we
|
||||
can load it successfully, we replace our remember it. If it
|
||||
doesn't change, or if the new version is corrupted, we continue
|
||||
using the old remembered copy. */
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <support/support.h>
|
||||
#include <support/check.h>
|
||||
|
||||
#include <support/xstdio.h>
|
||||
#include <support/xstdlib.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
|
||||
/* Verify that we can (or can't) load one of our test objects. */
|
||||
static void
|
||||
try (int i, int invert)
|
||||
{
|
||||
char dlname[100];
|
||||
char symname[100];
|
||||
int (*proc)(int);
|
||||
void *dl;
|
||||
|
||||
/* These match the objects copied by tst-ldconfig-cache.script,
|
||||
copied from tst-tls-manydynamic*.so. */
|
||||
sprintf (dlname, "libcache%d.so", i);
|
||||
sprintf (symname, "set_value_%02d", i);
|
||||
|
||||
dl = dlopen (dlname, RTLD_NOW);
|
||||
|
||||
if (invert)
|
||||
{
|
||||
/* This is a negative test; if the object doesn't load the test
|
||||
passes. */
|
||||
TEST_VERIFY (dl == NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a positive test; if the object doesn't load the test
|
||||
fails. */
|
||||
if (dl == NULL)
|
||||
FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ());
|
||||
}
|
||||
|
||||
proc = xdlsym (dl, symname);
|
||||
/* We don't need to call the symbol, just make sure it exists. */
|
||||
TEST_VERIFY (proc != NULL);
|
||||
|
||||
xdlclose (dl);
|
||||
}
|
||||
|
||||
/* Cause corruption in the cache that should prevent loading it. */
|
||||
static void
|
||||
corrupt (void)
|
||||
{
|
||||
int fd = xopen ("/etc/ld.so.cache", O_RDWR, 0);
|
||||
char bytes[] = { 15, 32, 184, 4 };
|
||||
xwrite (fd, bytes, sizeof(bytes));
|
||||
xclose (fd);
|
||||
}
|
||||
|
||||
/* Regenerate the cache from ld.so.conf. */
|
||||
static void
|
||||
ldconfig (void)
|
||||
{
|
||||
char *cmd = xasprintf("%s/ldconfig -X", support_install_rootsbindir);
|
||||
xsystem (cmd);
|
||||
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
/* Change ld.so.conf to refer to the new directory, and generate a new
|
||||
cache. */
|
||||
static void
|
||||
newpath (const char *p)
|
||||
{
|
||||
FILE *f = xfopen ("/etc/ld.so.conf", "w");
|
||||
fprintf (f, "%s\n", p);
|
||||
xfclose (f);
|
||||
|
||||
ldconfig ();
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Test that the cache we started with can still load objects in
|
||||
/a. */
|
||||
try (1, 0);
|
||||
|
||||
/* Create a new cache that doesn't include /a but corrupt it. Test
|
||||
that we still use the cache with /a in it. */
|
||||
newpath ("/c");
|
||||
corrupt ();
|
||||
try (2, 0);
|
||||
|
||||
/* Regenerate a clean cache with /a in it and verify we can load
|
||||
objects in /a. */
|
||||
newpath ("/a");
|
||||
try (3, 0);
|
||||
|
||||
/* Generate a new cache with /b but not /a and make sure objects
|
||||
in /a can't be loaded. */
|
||||
newpath ("/b");
|
||||
try (3, 1);
|
||||
|
||||
/* But objects in /b can be loaded. */
|
||||
try (4, 0);
|
||||
/* Even multiple times. */
|
||||
try (5, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,3 @@
|
||||
/lib
|
||||
/lib64
|
||||
/a
|
||||
@@ -0,0 +1,7 @@
|
||||
mkdirp 0755 /a
|
||||
cp $B/elf/tst-tls-manydynamic01mod.so /a/libcache1.so
|
||||
cp $B/elf/tst-tls-manydynamic02mod.so /a/libcache2.so
|
||||
cp $B/elf/tst-tls-manydynamic03mod.so /a/libcache3.so
|
||||
mkdirp 0755 /b
|
||||
cp $B/elf/tst-tls-manydynamic04mod.so /b/libcache4.so
|
||||
cp $B/elf/tst-tls-manydynamic05mod.so /b/libcache5.so
|
||||
@@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
# Test that ldconfig --install installs a pre-built cache file.
|
||||
# Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
# The GNU C Library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with the GNU C Library; if not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -e
|
||||
|
||||
common_objpfx=$1
|
||||
test_wrapper_env=$2
|
||||
run_program_env=$3
|
||||
|
||||
testroot="${common_objpfx}elf/tst-ldconfig-install-directory"
|
||||
cleanup () {
|
||||
rm -rf "$testroot"
|
||||
}
|
||||
trap cleanup 0
|
||||
|
||||
rm -rf "$testroot"
|
||||
mkdir -p "$testroot/etc"
|
||||
|
||||
ldconfig="${common_objpfx}elf/ldconfig"
|
||||
run_ldconfig () {
|
||||
${test_wrapper_env} ${run_program_env} "$ldconfig" "$@"
|
||||
}
|
||||
|
||||
errors=0
|
||||
fail () {
|
||||
echo "error: $1"
|
||||
errors=1
|
||||
}
|
||||
|
||||
# Build a pre-built cache to install.
|
||||
source="$testroot/prebuilt-ld.so.cache"
|
||||
mkdir -p "$testroot/lib"
|
||||
run_ldconfig -X -f /dev/null -C "$source" "$testroot/lib"
|
||||
test -r "$source" || fail "ldconfig did not create the pre-built cache"
|
||||
|
||||
# Pad the source past the 512-byte internal copy buffer so that the multi-block
|
||||
# copy path is exercised, while leaving the cache magic at the start intact.
|
||||
dd if=/dev/zero bs=1024 count=4 >> "$source" 2>/dev/null
|
||||
|
||||
dest="$testroot/etc/ld.so.cache"
|
||||
temp="$dest~"
|
||||
|
||||
run_ldconfig --install -f /dev/null -C "$dest" "$source"
|
||||
|
||||
# The destination must exist and be byte-identical to the source.
|
||||
if test -r "$dest"; then
|
||||
if cmp -s "$source" "$dest"; then
|
||||
echo "info: installed cache matches the source"
|
||||
else
|
||||
fail "installed cache differs from the source"
|
||||
fi
|
||||
else
|
||||
fail "destination cache file was not created"
|
||||
fi
|
||||
|
||||
# The temporary file used during the atomic rename must not be left behind.
|
||||
if test -e "$temp"; then
|
||||
fail "temporary file $temp was left behind"
|
||||
fi
|
||||
|
||||
# The installed cache must be world-readable (0644).
|
||||
if test -r "$dest"; then
|
||||
mode=$(ls -l "$dest" | cut -c1-10)
|
||||
case "$mode" in
|
||||
(-rw-r--r--) echo "info: installed cache has expected permissions" ;;
|
||||
(*) fail "installed cache has unexpected permissions: $mode" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# A second install over an existing cache must also succeed.
|
||||
run_ldconfig --install -f /dev/null -C "$dest" "$source"
|
||||
if cmp -s "$source" "$dest"; then
|
||||
echo "info: re-install over an existing cache works"
|
||||
else
|
||||
fail "re-install produced a different cache"
|
||||
fi
|
||||
|
||||
# Error case: a source file that is not a cache must be rejected, and no
|
||||
# destination must be produced.
|
||||
rm -f "$dest"
|
||||
notcache="$testroot/not-a-cache"
|
||||
echo "this is not an ld.so.cache file" > "$notcache"
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" "$notcache" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted a file that is not a cache"
|
||||
else
|
||||
if grep -q "does not look like an ld.so.cache file" "$testroot/err"; then
|
||||
echo "info: non-cache source correctly rejected"
|
||||
else
|
||||
fail "unexpected error message for non-cache source"
|
||||
cat "$testroot/err"
|
||||
fi
|
||||
fi
|
||||
test -e "$dest" && fail "destination created from an invalid source"
|
||||
|
||||
# Error case: a missing source argument must be diagnosed.
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted --install without a source file"
|
||||
else
|
||||
grep -q "Missing source file name" "$testroot/err" \
|
||||
|| fail "unexpected error message for missing source"
|
||||
fi
|
||||
|
||||
# Error case: a nonexistent source must be diagnosed.
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" \
|
||||
"$testroot/does-not-exist" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted a nonexistent source file"
|
||||
fi
|
||||
|
||||
exit $errors
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Test that the tunables cache can override env vars.
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <support/check.h>
|
||||
|
||||
#include "dl-tunables.h"
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
size_t tcache_count = TUNABLE_GET_FULL (glibc, malloc, tcache_count, size_t, NULL);
|
||||
size_t tcache_max = TUNABLE_GET_FULL (glibc, malloc, tcache_max, size_t, NULL);
|
||||
int32_t perturb = TUNABLE_GET_FULL (glibc, malloc, perturb, int32_t, NULL);
|
||||
size_t mmap_threshold = TUNABLE_GET_FULL (glibc, malloc, mmap_threshold, size_t, NULL);
|
||||
size_t trim_threshold = TUNABLE_GET_FULL (glibc, malloc, trim_threshold, size_t, NULL);
|
||||
|
||||
printf("tcache count is %zu (should be 5, from env)\n", tcache_count);
|
||||
TEST_COMPARE ((long)tcache_count, 5);
|
||||
printf("tcache max is %zu (should be 4, from /etc)\n", tcache_max);
|
||||
TEST_COMPARE ((long)tcache_max, 4);
|
||||
|
||||
/* This is set by the environment but blocked by the config. */
|
||||
printf("perturb is %" PRId32 " (should be 42, from /etc)\n",
|
||||
perturb);
|
||||
TEST_COMPARE (perturb, 42);
|
||||
|
||||
/* This is blocked by the general config, enabled by filter, set in env. */
|
||||
printf("mmap_threshold is %zu (should be 10002, from env)\n",
|
||||
mmap_threshold);
|
||||
TEST_COMPARE ((long)mmap_threshold, 10002);
|
||||
|
||||
/* This is allowed by the general config, blocked by filter, set in env. */
|
||||
printf("trim_threshold is %zu (should be 10001, from filter)\n",
|
||||
trim_threshold);
|
||||
TEST_COMPARE ((long)trim_threshold, 10001);
|
||||
|
||||
/* Interaction with legacy environment-variable aliases (MALLOC_*). */
|
||||
int32_t mmap_max = TUNABLE_GET_FULL (glibc, malloc, mmap_max, int32_t, NULL);
|
||||
size_t top_pad = TUNABLE_GET_FULL (glibc, malloc, top_pad, size_t, NULL);
|
||||
size_t arena_max = TUNABLE_GET_FULL (glibc, malloc, arena_max, size_t, NULL);
|
||||
|
||||
/* Overridable cache default (100); the MALLOC_MMAP_MAX_ alias overrides
|
||||
it, just like GLIBC_TUNABLES would. */
|
||||
printf("mmap_max is %" PRId32 " (should be 200, from MALLOC_MMAP_MAX_ alias)"
|
||||
"\n",
|
||||
mmap_max);
|
||||
TEST_COMPARE (mmap_max, 200);
|
||||
|
||||
/* Nonoverridable cache default (100); the MALLOC_TOP_PAD_ alias must not
|
||||
override it. */
|
||||
printf("top_pad is %zu (should be 100, from /etc nonoverridable)\n",
|
||||
top_pad);
|
||||
TEST_COMPARE ((long)top_pad, 100);
|
||||
|
||||
/* Set both by GLIBC_TUNABLES (300) and by the MALLOC_ARENA_MAX alias
|
||||
(400); the canonical GLIBC_TUNABLES form wins. */
|
||||
printf("arena_max is %zu (should be 300, from GLIBC_TUNABLES)\n", arena_max);
|
||||
TEST_COMPARE ((long)arena_max, 300);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,31 @@
|
||||
# These test the parser for both the overridability characters as well as
|
||||
# tunables that either never exist, or only exist on some platforms.
|
||||
-glibc.cpu.cached_memopt=1
|
||||
+glibc.cpu.hwcaps=some,random,string
|
||||
@glibc.test_secure=1
|
||||
$glibc.test_unsecure=1
|
||||
|
||||
# These are checked inside the test case
|
||||
glibc.malloc.tcache_max=6
|
||||
$glibc.malloc.tcache_count=3
|
||||
|
||||
-glibc.malloc.perturb=42
|
||||
-glibc.malloc.mmap_threshold=10000
|
||||
overridable glibc.malloc.trim_threshold=10000
|
||||
|
||||
# Interaction with legacy environment-variable aliases (MALLOC_*), checked
|
||||
# in the test case:
|
||||
# - mmap_max: overridable cache default, must be overridable by the
|
||||
# MALLOC_MMAP_MAX_ alias just like by GLIBC_TUNABLES.
|
||||
# - top_pad: nonoverridable cache default, must NOT be overridable by the
|
||||
# MALLOC_TOP_PAD_ alias.
|
||||
glibc.malloc.mmap_max=100
|
||||
-glibc.malloc.top_pad=100
|
||||
|
||||
[proc:/bin/ls]
|
||||
glibc.malloc.tcache_max=7
|
||||
|
||||
[proc:tst-tunconf1]
|
||||
glibc.malloc.tcache_max=4
|
||||
+glibc.malloc.mmap_threshold=10001
|
||||
nonoverridable glibc.malloc.trim_threshold=10001
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
/* Manage /etc/tunables.*
|
||||
Copyright (C) 1999-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <argp.h>
|
||||
#include <assert.h>
|
||||
#include <error.h>
|
||||
#include <inttypes.h>
|
||||
#include <glob.h>
|
||||
#include <libgen.h>
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <programs/xmalloc.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define TUNABLES_INTERNAL
|
||||
#include <elf/dl-tunables.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ldconfig.h>
|
||||
#include <dl-cache.h>
|
||||
#include <version.h>
|
||||
#include <stringtable.h>
|
||||
#include <array_length.h>
|
||||
|
||||
#include "tunconf.h"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef TUNABLES_CONF
|
||||
# define TUNABLES_CONF SYSCONFDIR "/tunables.conf"
|
||||
#endif
|
||||
|
||||
#ifndef TUNABLES_CACHE
|
||||
# define TUNABLES_CACHE SYSCONFDIR "/tunables.cache"
|
||||
#endif
|
||||
|
||||
/* Tunable Override Policies. */
|
||||
typedef enum {
|
||||
TOP_ALLOW = 0, /* let the environment variable override */
|
||||
TOP_DENY /* no override allowed */
|
||||
} TOP;
|
||||
|
||||
struct tunable_entry_int {
|
||||
struct stringtable_entry *name;
|
||||
struct stringtable_entry *value;
|
||||
struct stringtable_entry *filter;
|
||||
TOP top;
|
||||
bool exclude_secure:1;
|
||||
bool exclude_nonsecure:1;
|
||||
int tunable_id;
|
||||
int value_is_negative:1;
|
||||
int value_was_parsed:1;
|
||||
unsigned long long value_ull;
|
||||
signed long long value_sll;
|
||||
long filter_flags;
|
||||
|
||||
struct tunable_entry_int *next;
|
||||
};
|
||||
|
||||
struct tunable_entry_int *entry_list;
|
||||
|
||||
static int filter_flags = 0;
|
||||
static char *filter_string = NULL;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
clear_filter (void)
|
||||
{
|
||||
free (filter_string);
|
||||
filter_string = NULL;
|
||||
filter_flags = 0;
|
||||
}
|
||||
|
||||
/* Filters are lines the are bracketed, like
|
||||
[prog:foo]
|
||||
*/
|
||||
static void
|
||||
parse_filter (char *line, const char *filename, int lineno)
|
||||
{
|
||||
const char *colon = NULL;
|
||||
const char *right_bracket = NULL;
|
||||
const char *cp;
|
||||
|
||||
for (cp = line; *cp != 0; ++cp)
|
||||
{
|
||||
if (*cp == ':')
|
||||
colon = cp;
|
||||
if (*cp == ']')
|
||||
{
|
||||
right_bracket = cp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Special case: [] means "no filter" */
|
||||
if (right_bracket != NULL && right_bracket == line + 1)
|
||||
{
|
||||
clear_filter ();
|
||||
return;
|
||||
}
|
||||
if (colon == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, filter line ignored: `%s' (missing ':')\n",
|
||||
line);
|
||||
return;
|
||||
}
|
||||
if (right_bracket == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, filter line ignored: `%s' (missing ']')\n",
|
||||
line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter_string != NULL)
|
||||
{
|
||||
clear_filter ();
|
||||
}
|
||||
|
||||
if (colon - line - 1 == 4 && memcmp ("proc", line + 1, 4) == 0)
|
||||
{
|
||||
/* Consider this example: [proc:foo] ..." */
|
||||
/* We allocate 4 bytes, [0] through [3]. */
|
||||
filter_string = (char *) xmalloc (right_bracket - colon);
|
||||
/* We copy "foo" for 3 bytes, [0] through [2]. */
|
||||
memcpy (filter_string, colon + 1, right_bracket - colon - 1);
|
||||
/* [3] = 0 so now "foo\0". */
|
||||
filter_string [right_bracket - colon - 1] = 0;
|
||||
filter_flags = TUNCONF_FILTER_PERPROC;
|
||||
}
|
||||
|
||||
else
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"unrecognized filter `%.*s', ignored\n",
|
||||
(int)(colon - line - 1), line + 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_tunable (char *line, const char *filename, int lineno)
|
||||
{
|
||||
TOP top = TOP_ALLOW;
|
||||
char *name;
|
||||
char *value;
|
||||
char *eq;
|
||||
char *orig_line;
|
||||
struct tunable_entry_int *entry;
|
||||
int i, id;
|
||||
static struct tunable_entry_int **entry_list_next = &entry_list;
|
||||
bool exclude_secure = 1, exclude_nonsecure = 0;
|
||||
|
||||
/* Denotes file boundaries. */
|
||||
if (line == NULL)
|
||||
{
|
||||
clear_filter();
|
||||
return;
|
||||
}
|
||||
|
||||
orig_line = line;
|
||||
|
||||
/* Leading whitespace has already been stripped. */
|
||||
|
||||
/* Canonicalize the line. */
|
||||
for (i=0; line[i]; i++)
|
||||
{
|
||||
if (line[i] == '\t')
|
||||
line[i] = ' ';
|
||||
if (line[i] == '\n' || line[i] == '\r')
|
||||
{
|
||||
line[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse modifiers. */
|
||||
while (*line)
|
||||
{
|
||||
int prefix_len;
|
||||
|
||||
#define TUN_PREFIX(s) \
|
||||
prefix_len = sizeof(s) - 1, \
|
||||
strncmp (line, s " ", prefix_len + 1) == 0
|
||||
|
||||
if (TUN_PREFIX("overridable"))
|
||||
{
|
||||
top = TOP_ALLOW;
|
||||
/* The line++ below skips the space. */
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("nonoverridable"))
|
||||
{
|
||||
top = TOP_DENY;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("onlysecure"))
|
||||
{
|
||||
exclude_nonsecure = 1;
|
||||
exclude_secure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("nonsecure"))
|
||||
{
|
||||
exclude_secure = 1;
|
||||
exclude_nonsecure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("anysecure"))
|
||||
{
|
||||
exclude_secure = 0;
|
||||
exclude_nonsecure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else switch (*line)
|
||||
{
|
||||
case '+':
|
||||
top = TOP_ALLOW;
|
||||
break;
|
||||
case '-':
|
||||
top = TOP_DENY;
|
||||
break;
|
||||
case '@':
|
||||
exclude_nonsecure = 1;
|
||||
exclude_secure = 0;
|
||||
break;
|
||||
case '$':
|
||||
exclude_nonsecure = 0;
|
||||
exclude_secure = 1;
|
||||
break;
|
||||
case '*':
|
||||
exclude_nonsecure = 0;
|
||||
exclude_secure = 0;
|
||||
break;
|
||||
case '[':
|
||||
parse_filter (line, filename, lineno);
|
||||
return;
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
line ++;
|
||||
}
|
||||
done:
|
||||
|
||||
/* NAME now points to the start of the tunable name. */
|
||||
name = line;
|
||||
|
||||
/* Look for the '=' separator. */
|
||||
eq = strchr (line, '=');
|
||||
if (eq == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing '=')",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eq == name)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing tunable name)",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* At this point, EQ actually points to '='. */
|
||||
value = eq + 1;
|
||||
|
||||
while (*value && isspace(*value))
|
||||
value ++;
|
||||
|
||||
if (*value == 0)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing value)",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* VALUE now points to the start of the value. */
|
||||
|
||||
/* Split the string into name and value c-strings. */
|
||||
*eq = 0;
|
||||
/* Trim trailing whitespace off NAME. */
|
||||
while (*name && isspace (name[strlen(name)-1]))
|
||||
name[strlen(name)-1] = 0;
|
||||
/* Trim trailing whitespace off VALUE. */
|
||||
while (*value && isspace (value[strlen(value)-1]))
|
||||
value[strlen(value)-1] = 0;
|
||||
|
||||
id = -1;
|
||||
for (i = 0; i < array_length (tunable_list); i ++)
|
||||
if (strcmp (tunable_list[i].name, name) == 0)
|
||||
{
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
if (id == -1)
|
||||
printf ("%s:%d: Warning: tunable %s not recognized.\n",
|
||||
filename, lineno, name);
|
||||
|
||||
entry = (struct tunable_entry_int *) xcalloc (sizeof (struct tunable_entry_int), 1);
|
||||
entry->name = cache_store_string (name);
|
||||
entry->value = cache_store_string (value);
|
||||
entry->tunable_id = id;
|
||||
entry->top = top;
|
||||
entry->exclude_secure = exclude_secure;
|
||||
entry->exclude_nonsecure = exclude_nonsecure;
|
||||
|
||||
if (filter_flags)
|
||||
{
|
||||
entry->filter_flags = filter_flags;
|
||||
entry->filter = cache_store_string (filter_string);
|
||||
}
|
||||
|
||||
if (value[0] == '-')
|
||||
{
|
||||
entry->value_is_negative = 1;
|
||||
if (sscanf (value, "%lld", &entry->value_sll) == 1)
|
||||
entry->value_was_parsed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->value_is_negative = 0;
|
||||
if (sscanf (value, "%llu", &entry->value_ull) == 1)
|
||||
entry->value_was_parsed = 1;
|
||||
}
|
||||
|
||||
*entry_list_next = entry;
|
||||
entry_list_next = & (entry->next);
|
||||
}
|
||||
|
||||
void
|
||||
parse_tunconf (const char *filename, char *opt_chroot)
|
||||
{
|
||||
ldconfig_parse_config (filename, opt_chroot, add_tunable);
|
||||
}
|
||||
|
||||
struct tunable_header_cached *
|
||||
get_tunconf_ext (uint32_t string_table_offset)
|
||||
{
|
||||
struct tunable_entry_int *tei;
|
||||
struct tunable_header_cached *thc;
|
||||
size_t count;
|
||||
size_t size;
|
||||
|
||||
/* First, count the number of entries we have. */
|
||||
tei = entry_list;
|
||||
count = 0;
|
||||
while (tei != NULL)
|
||||
{
|
||||
++ count;
|
||||
tei = tei->next;
|
||||
}
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
|
||||
/* Allocate enough space for the whole cached block. */
|
||||
size = sizeof (struct tunable_header_cached)
|
||||
+ sizeof (struct tunable_entry_cached) * count;
|
||||
thc = (struct tunable_header_cached *) xmalloc (size);
|
||||
|
||||
/* Now, fill in the structures. */
|
||||
|
||||
thc->signature = TUNCONF_SIGNATURE;
|
||||
thc->version = TUNCONF_VERSION;
|
||||
thc->num_tunables = count;
|
||||
thc->unused_1 = 0;
|
||||
|
||||
tei = entry_list;
|
||||
count = 0;
|
||||
while (tei != NULL)
|
||||
{
|
||||
struct tunable_entry_cached *tec;
|
||||
|
||||
tec = & ( thc->tunables[count] );
|
||||
|
||||
tec->flags = 0;
|
||||
if (tei->value_was_parsed)
|
||||
tec->flags |= TUNCONF_FLAG_PARSED;
|
||||
if (tei->value_is_negative)
|
||||
tec->flags |= TUNCONF_FLAG_NEGATIVE;
|
||||
switch (tei->top)
|
||||
{
|
||||
case TOP_ALLOW:
|
||||
tec->flags |= TUNCONF_OVERRIDE_ALLOW;
|
||||
break;
|
||||
case TOP_DENY:
|
||||
tec->flags |= TUNCONF_OVERRIDE_DENY;
|
||||
break;
|
||||
}
|
||||
if (tei->exclude_secure)
|
||||
tec->flags |= TUNCONF_EXCLUDE_SECURE;
|
||||
if (tei->exclude_nonsecure)
|
||||
tec->flags |= TUNCONF_EXCLUDE_UNSECURE;
|
||||
|
||||
tec->tunable_id = tei->tunable_id;
|
||||
tec->name_offset = tei->name->offset + string_table_offset;
|
||||
tec->value_offset = tei->value->offset + string_table_offset;
|
||||
|
||||
if (tei->filter_flags != 0)
|
||||
{
|
||||
tec->flag_offset = tei->filter->offset + string_table_offset;
|
||||
tec->flags |= tei->filter_flags;
|
||||
}
|
||||
else
|
||||
tec->flag_offset = 0;
|
||||
|
||||
tec->unused_1 = 0;
|
||||
if (tei->value_is_negative)
|
||||
tec->parsed_value = (uint64_t) tei->value_sll;
|
||||
else
|
||||
tec->parsed_value = (uint64_t) tei->value_ull;
|
||||
|
||||
++ count;
|
||||
tei = tei->next;
|
||||
}
|
||||
|
||||
return thc;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#define TUNCONF_SIGNATURE 0x7c3ba94f
|
||||
#define TUNCONF_VERSION 0x01000000
|
||||
|
||||
#define TUNCONF_FLAG_PARSED 0x00000001
|
||||
#define TUNCONF_FLAG_NEGATIVE 0x00000002
|
||||
|
||||
#define TUNCONF_FLAG_OVERRIDABLE 0x0000000C
|
||||
#define TUNCONF_OVERRIDE_DENY 0x00000004
|
||||
#define TUNCONF_OVERRIDE_ALLOW 0x00000000
|
||||
|
||||
#define TUNCONF_EXCLUDE_SECURE 0x00000010
|
||||
#define TUNCONF_EXCLUDE_UNSECURE 0x00000020
|
||||
|
||||
#define TUNCONF_FLAG_FILTER 0x0000ff00
|
||||
#define TUNCONF_FILTER_NONE 0x00000000
|
||||
#define TUNCONF_FILTER_PERPROC 0x00000100
|
||||
|
||||
/* An array of [num_tunables] of these follows the below. */
|
||||
struct tunable_entry_cached {
|
||||
uint32_t flags;
|
||||
uint32_t tunable_id;
|
||||
uint32_t name_offset;
|
||||
uint32_t value_offset;
|
||||
uint32_t flag_offset;
|
||||
uint32_t unused_1; /* for alignment */
|
||||
uint64_t parsed_value;
|
||||
};
|
||||
|
||||
/* One of these is at the beginning of the tunable data block. */
|
||||
struct tunable_header_cached {
|
||||
uint32_t signature;
|
||||
uint32_t version;
|
||||
uint32_t num_tunables;
|
||||
uint32_t unused_1; /* for alignment */
|
||||
struct tunable_entry_cached tunables[0 /* num_tunables */];
|
||||
};
|
||||
|
||||
void parse_tunconf (const char *filename, char *opt_chroot);
|
||||
|
||||
struct tunable_header_cached * get_tunconf_ext (uint32_t str_offset);
|
||||
#define TUNCONF_SIZE(thc_p) (sizeof(struct tunable_header_cached) \
|
||||
+ thc_p->num_tunables * sizeof (struct tunable_entry_cached))
|
||||
|
||||
extern const struct tunable_header_cached *
|
||||
_dl_load_cache_tunables (const char **data);
|
||||
@@ -257,3 +257,10 @@ $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(srcdir)/libpthread_sy
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(srcdir)/libpthread_syms.a $(objpfx)libpthread.a
|
||||
endif
|
||||
|
||||
# Like rt, these tests prefer to be run serially.
|
||||
ifeq (yes-yes,$(run-built-tests)-$(serialize-tests))
|
||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||
.NOTPARALLEL:
|
||||
endif
|
||||
endif
|
||||
|
||||
+4
-1
@@ -76,7 +76,8 @@ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
|
||||
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
|
||||
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
|
||||
bug-iconv13 bug-iconv14 bug-iconv15 \
|
||||
tst-iconv-iso-2022-cn-ext tst-bug33980
|
||||
tst-iconv-iso-2022-cn-ext tst-bug33980 \
|
||||
tst-jisx0213-progress
|
||||
ifeq ($(have-thread-library),yes)
|
||||
tests += bug-iconv3
|
||||
endif
|
||||
@@ -335,6 +336,8 @@ $(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules))
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)tst-jisx0213-progress.out: \
|
||||
$(addprefix $(objpfx), $(gconv-modules)) $(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
$(addprefix $(objpfx), $(gconv-modules)) \
|
||||
|
||||
@@ -224,6 +224,9 @@
|
||||
STANDARD_FROM_LOOP_ERR_HANDLER (1); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
/* There was a pending character. Clear it. */ \
|
||||
*statep = 0; \
|
||||
\
|
||||
put32 (outptr, ch); \
|
||||
outptr += 4; \
|
||||
|
||||
@@ -226,6 +226,9 @@
|
||||
STANDARD_FROM_LOOP_ERR_HANDLER (1); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
/* There was a pending character. Clear it. */ \
|
||||
*statep = 0; \
|
||||
\
|
||||
put32 (outptr, ch); \
|
||||
outptr += 4; \
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Test JISX0213 combining character conversion progress (bug 34556, bug 34568).
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Certain JISX0213 byte sequences map to a combining sequence, for
|
||||
example U+304B (HIRAGANA LETTER KA) followed by U+309A (COMBINING
|
||||
SEMI-VOICED SOUND MARK). When converting to internal encoding
|
||||
(actually UTF-32) with a small output buffer, the first code point
|
||||
is emitted and the second is queued in the converter state. This
|
||||
test verifies that the queued code point is consumed exactly once
|
||||
on retry, so that the conversion makes progress and terminates. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
static void
|
||||
test_one (const char *charset, const char *input, size_t outbufsize)
|
||||
{
|
||||
printf ("info: %s: testing output buffer size %zu\n", charset, outbufsize);
|
||||
|
||||
/* Expected UTF-32 output. */
|
||||
static const wchar_t expected[] = { 0x304b, 0x309a, 'A' };
|
||||
|
||||
/* Use WCHAR_T encoding to avoid the BOM. */
|
||||
iconv_t cd = iconv_open ("WCHAR_T", charset);
|
||||
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
|
||||
|
||||
char result[64];
|
||||
size_t result_len = 0;
|
||||
|
||||
char *inptr = (char *) input;
|
||||
size_t inleft = strlen (input);
|
||||
|
||||
char outbuf[64];
|
||||
|
||||
int iterations = 0;
|
||||
while (inleft > 0)
|
||||
{
|
||||
char *outptr = outbuf;
|
||||
size_t outleft = outbufsize;
|
||||
size_t inleft_before = inleft;
|
||||
|
||||
size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);
|
||||
size_t produced = outptr - outbuf;
|
||||
|
||||
TEST_VERIFY_EXIT (result_len + produced <= sizeof (result));
|
||||
memcpy (result + result_len, outbuf, produced);
|
||||
result_len += produced;
|
||||
|
||||
if (ret == (size_t) -1 && errno == E2BIG)
|
||||
{
|
||||
if (produced == 0 && inleft == inleft_before)
|
||||
{
|
||||
/* Output buffer too small for a single code point. */
|
||||
TEST_VERIFY_EXIT (outbufsize < 4);
|
||||
break;
|
||||
}
|
||||
/* Bound iterations to detect non-progress bugs. */
|
||||
if (++iterations < 10)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
FAIL ("%s: no progress", charset);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (ret == (size_t) -1)
|
||||
FAIL_EXIT1 ("outbufsize %zu: iconv: %m", outbufsize);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Flush pending converter state. */
|
||||
{
|
||||
char *outptr = outbuf;
|
||||
size_t outleft = outbufsize;
|
||||
size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
|
||||
TEST_VERIFY (ret == 0);
|
||||
size_t produced = outptr - outbuf;
|
||||
memcpy (result + result_len, outbuf, produced);
|
||||
result_len += produced;
|
||||
}
|
||||
|
||||
if (outbufsize >= 4)
|
||||
{
|
||||
TEST_COMPARE (inleft, 0);
|
||||
TEST_COMPARE_BLOB (result, result_len,
|
||||
expected, sizeof (expected));
|
||||
}
|
||||
|
||||
out:
|
||||
TEST_VERIFY_EXIT (iconv_close (cd) == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
for (size_t outbufsize = 1; outbufsize <= 16; outbufsize++)
|
||||
{
|
||||
test_one ("EUC-JISX0213", "\244\367A", outbufsize);
|
||||
test_one ("SHIFT_JISX0213", "\202\365A", outbufsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
+1
-1
@@ -529,7 +529,7 @@
|
||||
/* Major and minor version number of the GNU C library package. Use
|
||||
these macros to test for features in specific releases. */
|
||||
#define __GLIBC__ 2
|
||||
#define __GLIBC_MINOR__ 43
|
||||
#define __GLIBC_MINOR__ 44
|
||||
|
||||
#define __GLIBC_PREREQ(maj, min) \
|
||||
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
|
||||
|
||||
@@ -91,6 +91,8 @@ enum
|
||||
#define IPPROTO_MPLS IPPROTO_MPLS
|
||||
IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */
|
||||
#define IPPROTO_ETHERNET IPPROTO_ETHERNET
|
||||
IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */
|
||||
#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG
|
||||
IPPROTO_RAW = 255, /* Raw IP packets. */
|
||||
#define IPPROTO_RAW IPPROTO_RAW
|
||||
IPPROTO_SMC = 256, /* Shared Memory Communications. */
|
||||
|
||||
@@ -24,7 +24,7 @@ test_program_prefix=$2
|
||||
objpfx=$3
|
||||
|
||||
# Create the locale directories.
|
||||
mkdir -p ${objpfx}localedir/existing-locale/LC_MESSAGES
|
||||
mkdir -p ${objpfx}domaindir/existing-locale/LC_MESSAGES
|
||||
|
||||
msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/translit.mo \
|
||||
translit.po
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef __OFF_T_MATCHES_OFF64_T
|
||||
#include <kernel_stat.h>
|
||||
|
||||
#if !XSTAT_IS_XSTAT64
|
||||
# include "ftw-common.c"
|
||||
|
||||
versioned_symbol (libc, __new_nftw, nftw, GLIBC_2_3_3);
|
||||
|
||||
+4
-1
@@ -31,6 +31,9 @@
|
||||
#define ftw __rename_ftw
|
||||
#define nftw __rename_nftw
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <kernel_stat.h>
|
||||
#include <shlib-compat.h>
|
||||
#include "ftw-common.c"
|
||||
|
||||
@@ -44,7 +47,7 @@ versioned_symbol (libc, __new_nftw64, nftw64, GLIBC_2_3_3);
|
||||
compat_symbol (libc, __old_nftw64, nftw64, GLIBC_2_1);
|
||||
#endif
|
||||
|
||||
#ifdef __OFF_T_MATCHES_OFF64_T
|
||||
#if XSTAT_IS_XSTAT64
|
||||
weak_alias (__ftw64, ftw)
|
||||
versioned_symbol (libc, __new_nftw64, nftw, GLIBC_2_3_3);
|
||||
# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3)
|
||||
|
||||
@@ -110,6 +110,7 @@ tests = \
|
||||
tst-fgetwc \
|
||||
tst-fgetws \
|
||||
tst-file-init-race \
|
||||
tst-fopen-ccs-empty \
|
||||
tst-fopenloc2 \
|
||||
tst-fputws \
|
||||
tst-freopen \
|
||||
|
||||
+7
-5
@@ -355,12 +355,14 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
|
||||
*((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
|
||||
strip (ccs, ccs);
|
||||
|
||||
if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
|
||||
? upstr (ccs, cs + 5) : ccs) != 0)
|
||||
/* After stripping, ccs[2] == '\0' means the charset name is empty.
|
||||
This is not a valid charset and would cause problems downstream.
|
||||
Reject it with EINVAL (BZ #34574, CVE-2026-18374). */
|
||||
if (ccs[2] == '\0' || __wcsmbs_named_conv (&fcts, ccs) != 0)
|
||||
{
|
||||
/* Something went wrong, we cannot load the conversion modules.
|
||||
This means we cannot proceed since the user explicitly asked
|
||||
for these. */
|
||||
/* Either the charset name is empty after strip(), or conversion
|
||||
modules cannot be loaded. This means we cannot proceed since
|
||||
the user explicitly asked for character conversion. */
|
||||
(void) _IO_file_close_it (fp);
|
||||
free (ccs);
|
||||
__set_errno (EINVAL);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/* Test fopen with an empty ",ccs=" value in the mode string (bug 34574).
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
static void
|
||||
check_fopen_fails (const char *path, const char *mode)
|
||||
{
|
||||
errno = 0;
|
||||
FILE *fp = fopen (path, mode);
|
||||
TEST_VERIFY (fp == NULL);
|
||||
TEST_COMPARE (errno, EINVAL);
|
||||
if (fp != NULL)
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char *path;
|
||||
xclose (create_temp_file ("tst-fopen-ccs-empty", &path));
|
||||
|
||||
/* The value is blank and the mode string continues well past it. */
|
||||
enum { size = 1024 * 1024 };
|
||||
char *mode = xmalloc (size);
|
||||
memset (mode, 'X', size);
|
||||
mode[size - 1] = '\0';
|
||||
static const char prefix[] = "w,ccs= ,";
|
||||
memcpy (mode, prefix, sizeof (prefix) - 1);
|
||||
check_fopen_fails (path, mode);
|
||||
free (mode);
|
||||
|
||||
check_fopen_fails (path, "w,ccs=");
|
||||
check_fopen_fails (path, "w,ccs=,");
|
||||
|
||||
free (path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -32,17 +32,25 @@ generate_locale ()
|
||||
out=$3
|
||||
flags=$4
|
||||
ret=0
|
||||
|
||||
# Use a staging area to avoid writing to locales concurrently.
|
||||
# While this process is running, $$ is sufficiently unique.
|
||||
stage="${common_objpfx}localedata/gen-locale.$$.tmp"
|
||||
mkdir "$stage" 2>/dev/null || true
|
||||
|
||||
${localedef_before_env} ${run_program_env} I18NPATH=../localedata \
|
||||
${localedef_after_env} $flags -f $charmap -i $input \
|
||||
${common_objpfx}localedata/$out || ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
# The makefile checks the timestamp of the LC_CTYPE file,
|
||||
# but localedef won't have touched it if it was able to
|
||||
# hard-link it to an existing file.
|
||||
touch ${common_objpfx}localedata/$out/LC_CTYPE
|
||||
$stage/$out || ret=$?
|
||||
if [ $ret -eq 0 ] ; then
|
||||
# Ignore errors in case some other process has created the same locale.
|
||||
# This rename operation should be atomic, and it should fail if the
|
||||
# $out locale already exists (rename fails with ENOTEMPTY).
|
||||
mv $stage/$out ${common_objpfx}localedata/. 2>/dev/null || true
|
||||
rm -rf $stage
|
||||
else
|
||||
rm -rf $stage
|
||||
echo "Charmap: \"${charmap}\" Inputfile: \"${input}\"" \
|
||||
"Outputdir: \"${out}\" failed"
|
||||
"Outputdir: \"${out}\" failed (exit status $ret)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ title "C locale"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language ""
|
||||
|
||||
@@ -13,7 +13,7 @@ title "Aragonese locale for Spain"
|
||||
source "Softaragones"
|
||||
address ""
|
||||
contact "Jordi Mallach Pérez, Juan Pablo Martínez"
|
||||
email "bug-glibc-locales@gnu.org, softaragones@softaragones.org"
|
||||
email "libc-alpha@sourceware.org, softaragones@softaragones.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Aragonese"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for United Arab Emirates"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Bahrain"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Algeria"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Egypt"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -14,7 +14,7 @@ title "Arabic language locale for India"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Iraq"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Jordan"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user