Compare commits

..
Author SHA1 Message Date
Florian Weimer e51a6bf18e malloc: Increase tcache fill count from 16 to 32
This avoids a regression in the omnetpp and xalancbmk benchmarks
of SPEC.  Apparently, these benchmarks are very sensitive to the
fill rate in malloc.

Suggested-by: Wilco Dijkstra <wilco.dijkstra@arm.com>
Tested-by: Wilco Dijkstra <wilco.dijkstra@arm.com>
2026-06-30 09:07:19 +02:00
Florian Weimer b50e24aea3 malloc: Only fill half of the tcache during batch allocation
This leaves room for subsequent frees.
2026-06-30 09:07:19 +02:00
Florian Weimer c0a1c6e06d malloc: Perform batched frees if tcache is full
Batched frees amortize the locking overhead once the tcache is full.
Previously, once the tcache slot was full, each free acquired the
arena lock.  With this change, neighboring tcache allocations in the
same arena re-use an arena lock that already exists.

Pass the tcache pointer to __libc_free_batch so that it is not
necessary to reload the tcache pointer after the _int_free_chunk
calls.
2026-06-30 09:07:19 +02:00
491 changed files with 27780 additions and 40708 deletions
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -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 16.1.1 is the newest compiler
better code. As of release time, GCC 15.2.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.46.1 is the newest
moment. As of release time, GNU 'binutils' 2.45.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.3 is the newest
differently. As of release time, 'texinfo' 7.2 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.4.1 is the newest verified to work to build the GNU C
version 5.3.2 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.44.0 is the newest verified to work
release time 'perl' version 5.42.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.10 is the newest verified to work to build the GNU C Library.
4.9 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.6 is the newest verified to work for building and
Python 3.14.0 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 7.1 is the newest stable version
As of release time, Linux version 6.12 is the newest stable version
verified to work to build the GNU C Library.
Reporting Bugs
-17
View File
@@ -782,14 +782,6 @@ 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
@@ -823,15 +815,8 @@ $(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.
@@ -898,7 +883,6 @@ 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) \
@@ -910,7 +894,6 @@ 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)
+14 -198
View File
@@ -54,6 +54,9 @@ 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 \
@@ -126,13 +129,6 @@ 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.
@@ -494,159 +490,6 @@ 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.
@@ -697,41 +540,26 @@ $(objpfx)check-local-headers.out: scripts/check-local-headers.sh
$(evaluate-test)
ifneq "$(headers)" ""
# Special test of all the installed headers in this directory. See
# Rules for the per-header split rationale.
# Special test of all the installed headers in this directory.
tests-special += $(objpfx)check-installed-headers-c.out
libof-check-installed-headers-c := testsuite
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
$(headers))
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
$(objpfx)check-installed-headers-c.out: \
scripts/check-installed-headers.sh $(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); \
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
"$(CC) $(test-config-cflags-finput-charset-ascii) \
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
$(headers) > $@; \
$(evaluate-test)
ifneq "$(CXX)" ""
tests-special += $(objpfx)check-installed-headers-cxx.out
libof-check-installed-headers-cxx := testsuite
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
$(headers))
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
$(objpfx)check-installed-headers-cxx.out: \
scripts/check-installed-headers.sh $(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); \
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
$(headers) > $@; \
$(evaluate-test)
endif # $(CXX)
@@ -820,13 +648,8 @@ 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
@@ -877,11 +700,7 @@ 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
@@ -889,14 +708,11 @@ ifneq ($(tests-summary),no)
$(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.
+9 -77
View File
@@ -259,17 +259,7 @@ 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. 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.
# it's used in sysd-rules, 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
@@ -312,12 +302,7 @@ 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)
{ \
@@ -758,20 +743,10 @@ 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
@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
@sed $(sed-remove-objpfx) $< > $(@:.d=.T) && \
mv -f $(@:.d=.T) $@ && \
rm -f $<
# 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.
@@ -1209,55 +1184,12 @@ 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.
# 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
.PHONY: check
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)
@@ -1443,7 +1375,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 $(objpfx)*.T[0-9]*
-rm -f $(objpfx)*.d $(objpfx)*.dt
-rm -fr $(addprefix $(objpfx),$(generated-dirs))
-rm -f $(addprefix $(common-objpfx),$(common-generated))
-rm -f $(gen-as-const-headers:%.sym=$(common-objpfx)%.h)
+17 -172
View File
@@ -5,101 +5,48 @@ 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.45
Major new features:
[Add new features here]
Deprecated and removed features, and other changes affecting compatibility:
[Add deprecations, removals and changes affecting compatibility here]
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
found in the advisories directory of the release tarball:
[The release manager will add the list generated by
scripts/process-advisories.sh just before the release.]
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.]
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 is not disabled in the kernel. When
Transparent Huge Pages (THP) if THP isn't disable in 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.
* 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.
* 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.
* Additional optimized and correctly rounded mathematical functions have
been imported from the CORE-MATH project, in particular cosh, sinh, and
tanh.
* Many additional improvements to existing functions have been synchronized
from the CORE-MATH project.
* The SVID handling for cosh and sinh were moved to compat symbols, allowing
improvements in performance.
* 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.
* New locale added: hrx_BR (Hunsrik language spoken in Brazil).
* 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 the Guarded Control Stack extension all GCS
* On AArch64 targets that support 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 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).
status via prctl syscall. This prevents disabling or corrupting GCS
shadow stack during runtime.
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
@@ -110,6 +57,10 @@ 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
@@ -129,114 +80,8 @@ found in the advisories directory of the release tarball:
The following bugs were resolved with this 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
[The release manager will add the list generated by
scripts/list-fixed-bugs.py just before the release.]
Version 2.43
+12 -28
View File
@@ -80,24 +80,15 @@ common-generated += dummy.o dummy.c
ifneq "$(headers)" ""
# Test that all of the headers installed by this directory can be compiled
# 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.
# in isolation.
tests-special += $(objpfx)check-installed-headers-c.out
libof-check-installed-headers-c := testsuite
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
$(headers))
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
$(objpfx)check-installed-headers-c.out: \
$(..)scripts/check-installed-headers.sh $(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); \
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
"$(CC) $(test-config-cflags-finput-charset-ascii) \
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
$(headers) > $@; \
$(evaluate-test)
ifneq "$(CXX)" ""
@@ -105,19 +96,12 @@ ifneq "$(CXX)" ""
# in isolation as C++.
tests-special += $(objpfx)check-installed-headers-cxx.out
libof-check-installed-headers-cxx := testsuite
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
$(headers))
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
$(objpfx)check-installed-headers-cxx.out: \
$(..)scripts/check-installed-headers.sh $(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); \
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
$(headers) > $@; \
$(evaluate-test)
endif # $(CXX)
@@ -429,7 +413,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-container-via-rtld-prefix) \
$(test-wrapper-env) $(run-program-env) $(test-via-rtld-prefix) \
$(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) $(test-tunables) \
$(host-test-program-cmd) $($*-ARGS) > $@; \
$(evaluate-test)
+1 -1
View File
@@ -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 cf237fa0
# src/binary64/tanh/tanh.c, revision 8ea8ea35
sysdeps/ieee754/dbl-64/s_tanh.c
# src/binary32/acos/acosf.c, revision 56dd347
sysdeps/ieee754/flt-32/e_acosf.c
-19
View File
@@ -1,19 +0,0 @@
wordexp with WRDE_APPEND may result in an invalid call to free()
Calling wordexp with WRDE_APPEND in conjunction with an invalid expansion
(where an error like WRDE_BADCHAR would be returned) can create a stale
address in the wordexp_t that can cause an invalid free from wordfree.
This affects the GNU C Library version 2.0 to version 2.43.
In WRDE_APPEND mode, wordexp saves the caller-visible wordexp_t state
before appending the processing input. If the word expansion grows
we_wordv via realloc, and realloc requires moving we_wordv to a new memory
location (instead of expanding in-place), and the expansion later fails,
the rollback fails to properly restore all previous we_wordv values and
may add stale pointers into the caller-visible state. A subsequent
wordfree may then issue an invalid call to free().
CVE-Id: CVE-2026-6368
Public-Date: 2026-07-14
Vulnerable-Commit: 8f2ece695d8822e9ecc63ecd157e90bf17a6fe65 (1.93-260)
Reported-by: shinobu
+3 -25
View File
@@ -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.
# 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.
# We don't want the benchmark programs to run in parallel since that could
# affect their performance.
.NOTPARALLEL:
bench-extra-objs = json-lib.o
@@ -622,30 +622,8 @@ $(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
+2405 -3006
View File
File diff suppressed because it is too large Load Diff
+4911 -3006
View File
File diff suppressed because it is too large Load Diff
+3446 -2004
View File
File diff suppressed because it is too large Load Diff
+3 -11
View File
@@ -60,14 +60,6 @@ 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:"'
@@ -103,7 +95,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 $(gen-locales)
$(objpfx)test1.cat: test1.msg $(objpfx)gencat
$(built-program-cmd-before-env) \
$(run-program-env) LC_ALL=hr_HR.ISO-8859-2 \
$(built-program-cmd-after-env) -H $(objpfx)test1.h $@ $<; \
@@ -111,7 +103,7 @@ $(objpfx)test1.cat: test1.msg $(objpfx)gencat $(gen-locales)
$(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 $(gen-locales)
$(objpfx)de/libc.cat: $(objpfx)de.msg $(objpfx)gencat
$(make-target-directory)
$(built-program-cmd-before-env) \
$(run-program-env) LC_ALL=de_DE.ISO-8859-1 \
@@ -124,7 +116,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 $(gen-locales)
$(objpfx)sample.SJIS.cat
$(SHELL) $< $(common-objpfx) '$(test-program-cmd-before-env)' \
'$(run-program-env)' '$(test-program-cmd-after-env)'; \
$(evaluate-test)
+1 -1
View File
@@ -264,7 +264,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
_dl_aux_init (auxvec);
# endif
__tunables_init (__environ, argv);
__tunables_init (__environ);
ARCH_INIT_CPU_FEATURES ();
+11 -21
View File
@@ -36,15 +36,10 @@
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[MAX_FUNCTIONS];
void *addresses[NUM_FUNCTIONS];
char **symbols;
int n;
int i;
@@ -75,28 +70,23 @@ handle_signal (int signum)
return;
}
/* 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++)
/* Do not check name for signal trampoline or cancellable syscall
wrappers (__syscall_cancel*). */
for (; i < n - 1; i++)
if (match (symbols[i], "read"))
break;
if (i == n)
if (i == n - 1)
{
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;
}
}
for (; i < n - 1; i++)
if (!match (symbols[i], "fn"))
{
FAIL ();
return;
}
/* Symbol names are not available for static functions, so we do not
check do_test. */
+2 -7
View File
@@ -145,13 +145,8 @@ enum
RTLD_DI_SERINFOSIZE = 5,
/* Treat ARG as `char *', and store there the directory name used to
expand $ORIGIN in this shared object's dependency file names.
Deprecated due to potential for buffer overflows. */
RTLD_DI_ORIGIN
# ifdef __attribute_deprecated_enum__
__attribute_deprecated_enum__ ("Use RTLD_DI_ORIGIN_PATH instead")
# endif
= 6,
expand $ORIGIN in this shared object's dependency file names. */
RTLD_DI_ORIGIN = 6,
RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */
RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */
-5
View File
@@ -22,7 +22,6 @@
#include <libintl.h>
#include <dl-tls.h>
#include <shlib-compat.h>
#include <libc-diag.h>
struct dlinfo_args
{
@@ -64,13 +63,9 @@ dlinfo_doit (void *argsblock)
_dl_rtld_di_serinfo (l, args->arg, true);
break;
DIAG_PUSH_NEEDS_COMMENT;
DIAG_IGNORE_NEEDS_COMMENT (6.1, "-Wdeprecated-declarations");
/* Deprecated via compile-time warning due to buffer overflow risk. */
case RTLD_DI_ORIGIN:
strcpy (args->arg, l->l_origin);
break;
DIAG_POP_NEEDS_COMMENT;
case RTLD_DI_ORIGIN_PATH:
if (l->l_origin != (char *) -1)
-5
View File
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <error.h>
#include <support/check.h>
#include <libc-diag.h>
#define TEST_FUNCTION do_test ()
@@ -52,15 +51,11 @@ do_test (void)
}
}
DIAG_PUSH_NEEDS_COMMENT;
/* Ignore deprecation to be able to test deprecated request type. */
DIAG_IGNORE_NEEDS_COMMENT (6.1, "-Wdeprecated-declarations");
char origin[8192]; /* >= PATH_MAX, in theory */
TRY (RTLD_DI_ORIGIN, origin)
{
printf ("origin: %s\n", origin);
}
DIAG_POP_NEEDS_COMMENT;
const char *origin_path;
TRY (RTLD_DI_ORIGIN_PATH, &origin_path)
+1 -64
View File
@@ -225,7 +225,6 @@ ldconfig-modules := \
readlib \
static-stubs \
stringtable \
tunconf \
xmalloc \
xstrdup \
# ldconfig-modules
@@ -336,7 +335,6 @@ tests-internal := \
$(tests-static-internal) \
tst-tls1 \
tst-tls_tp_offset \
tst-tunconf1 \
# tests-internal
tests-static := $(tests-static-normal) $(tests-static-internal)
@@ -347,17 +345,6 @@ 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)
@@ -590,12 +577,10 @@ 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 = \
@@ -727,7 +712,6 @@ 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 \
@@ -750,9 +734,6 @@ 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 = \
@@ -1460,7 +1441,6 @@ 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 $$@
@@ -1469,7 +1449,6 @@ 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 $$@
@@ -1488,15 +1467,12 @@ $(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))
@@ -1530,38 +1506,6 @@ tests-special += $(objpfx)tst-tls-debug-recursive.out
tests-special += $(objpfx)tst-dl-debug-exclude.out
endif
test-srcs += tst-relro-multi
tests-static += tst-relro-multi-static
extra-test-objs += tst-relro-multi-notes.o
LDFLAGS-tst-relro-multi = -Wl,-z,now -Wl,-T,$(..)elf/tst-relro-multi.lds
LDFLAGS-tst-relro-multi-static = -Wl,-T,$(..)elf/tst-relro-multi.lds
$(objpfx)tst-relro-multi: +nolink-deps += tst-relro-multi.lds
$(objpfx)tst-relro-multi: $(objpfx)tst-relro-multi-notes.o tst-relro-multi.lds
$(objpfx)tst-relro-multi-static: +nolink-deps += tst-relro-multi.lds
$(objpfx)tst-relro-multi-static: $(objpfx)tst-relro-multi-notes.o \
tst-relro-multi.lds
$(objpfx)tst-relro-multi-patched $(objpfx)tst-relro-multi-static-patched: \
%-patched: % $(..)scripts/tst-elf-edit.py
cp $< $@.tmp
$(PYTHON) $(..)scripts/tst-elf-edit.py --note-to-relro 2 $@.tmp
mv $@.tmp $@
$(objpfx)tst-relro-multi-patched.out: $(objpfx)tst-relro-multi-patched \
$(objpfx)ld.so
$(run-program-prefix) $< > $@ 2>&1; \
$(evaluate-test)
$(objpfx)tst-relro-multi-static-patched.out: \
$(objpfx)tst-relro-multi-static-patched
$(test-wrapper) $< > $@ 2>&1; \
$(evaluate-test)
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-relro-multi-patched.out
tests-special += $(objpfx)tst-relro-multi-static-patched.out
endif
# The test requires shared _and_ PIE because the executable
# unit test driver must be able to link with the shared object
# that is going to eventually go into an installed DSO.
@@ -1606,9 +1550,7 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
# when compiled for libc.
rtld-stubbed-symbols = \
__libc_assert_fail \
__libc_single_threaded_internal \
__syscall_cancel_arch \
__syscall_do_cancel \
__syscall_cancel \
calloc \
free \
malloc \
@@ -2882,11 +2824,6 @@ $(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)' > $@; \
+2 -106
View File
@@ -36,7 +36,6 @@
#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;
@@ -276,8 +275,7 @@ check_new_cache (struct cache_file_new *cache)
/* Print the extension information in *EXT. */
static void
print_extensions (struct cache_extension_all_loaded *ext,
const char *cache_data)
print_extensions (struct cache_extension_all_loaded *ext)
{
if (ext->sections[cache_extension_tag_generator].base != NULL)
{
@@ -286,65 +284,6 @@ 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
@@ -455,7 +394,7 @@ print_cache (const char *cache_name)
cache_new->libs[i].hwcap, hwcaps_string,
cache_data + cache_new->libs[i].value);
}
print_extensions (&ext, cache_data);
print_extensions (&ext);
}
/* Cleanup. */
munmap (cache, cache_size);
@@ -527,18 +466,6 @@ 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)
@@ -571,23 +498,6 @@ 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);
@@ -599,14 +509,6 @@ 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);
}
@@ -1204,9 +1106,3 @@ out_fail:
free (temp_name);
free (file_entries);
}
struct stringtable_entry *
cache_store_string (const char *string)
{
return stringtable_add (&strings, string);
}
+90 -239
View File
@@ -17,7 +17,6 @@
<https://www.gnu.org/licenses/>. */
#include <assert.h>
#include <intprops.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/mman.h>
@@ -27,22 +26,11 @@
#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
@@ -65,7 +53,6 @@ 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
@@ -97,6 +84,10 @@ 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)
@@ -383,168 +374,6 @@ _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
@@ -560,14 +389,81 @@ _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 != NULL)
if (cache_new != (void *) -1)
{
const char *string_table = (const char *) cache_new;
best = search_cache (string_table, cachesize,
@@ -606,67 +502,22 @@ _dl_load_cache_lookup (const char *name)
return result;
}
const struct tunable_header_cached *
_dl_load_cache_tunables (const char **data)
#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)
{
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 ++)
if (cache != NULL && cache != (struct cache_file *) -1)
{
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;
__munmap (cache, cachesize);
cache = NULL;
}
return thc;
#ifdef SHARED
/* This marks the glibc_hwcaps_priorities array as out-of-date. */
glibc_hwcaps_priorities_length = 0;
#endif
}
#endif
+5
View File
@@ -1091,6 +1091,11 @@ _dl_map_object_scan_phdrs (struct dl_pt_load_iterator *it,
case PT_GNU_STACK:
*stack_flagsp = pf_to_prot (ph->p_flags);
break;
case PT_GNU_RELRO:
l->l_relro_addr = ph->p_vaddr;
l->l_relro_size = ph->p_memsz;
break;
}
}
+5
View File
@@ -898,6 +898,11 @@ 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
+13 -18
View File
@@ -17,28 +17,23 @@
<https://www.gnu.org/licenses/>. */
#include <ldsodefs.h>
#include <sys/param.h>
static enum dl_readonly_area_error_type
static bool
check_relro (const struct link_map *l, uintptr_t start, uintptr_t end)
{
/* The range may span multiple PT_GNU_RELRO segments whose ranges are
adjacent, so accumulate the covered bytes. */
size_t size = end - start;
for (const ElfW(Phdr) *ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
if (ph->p_type == PT_GNU_RELRO)
{
struct dl_relro_range relro = _dl_relro_range (l, ph);
uintptr_t from = MAX (relro.start, start);
uintptr_t to = MIN (relro.end, end);
if (from < to)
size -= to - from;
if (size == 0)
return dl_readonly_area_rdonly;
}
if (l->l_relro_addr != 0)
{
uintptr_t relro_start = ALIGN_DOWN (l->l_addr + l->l_relro_addr,
GLRO(dl_pagesize));
uintptr_t relro_end = ALIGN_DOWN (l->l_addr + l->l_relro_addr
+ l->l_relro_size,
GLRO(dl_pagesize));
/* RELRO is caved out from a RW segment, so the next range is either
RW or nonexistent. */
return relro_start <= start && end <= relro_end
? dl_readonly_area_rdonly : dl_readonly_area_writable;
/* RELRO is caved out from a RW segment, so any range outside of
a RELRO segment is either RW or nonexistent. */
}
return dl_readonly_area_writable;
}
+56 -110
View File
@@ -37,47 +37,6 @@
#endif
/* Return the number of bytes that would be allocated in the static
TLS block for MAP. If the available space is insufficient, return a
value greater than the available space to indicate failure. OFFSET_OUT
is updated with the TLS offset of the map. */
static inline size_t
__attribute__ ((always_inline))
_dl_static_tls_allocation (struct link_map *map, size_t *offset_out)
{
#if TLS_TCB_AT_TP
size_t freebytes = GLRO(dl_tls_static_size) - GL(dl_tls_static_used);
if (freebytes < TLS_TCB_SIZE)
return TLS_TCB_SIZE + map->l_tls_blocksize;
freebytes -= TLS_TCB_SIZE;
size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
if (freebytes < blsize)
return TLS_TCB_SIZE + blsize;
size_t n = (freebytes - blsize) / map->l_tls_align;
/* Account optional static TLS surplus usage. */
size_t use = freebytes - n * map->l_tls_align - map->l_tls_firstbyte_offset;
*offset_out = GL(dl_tls_static_used) + use;
return use;
#elif TLS_DTV_AT_TP
/* dl_tls_static_used includes the TCB at the beginning. */
size_t offset = (ALIGN_UP(GL(dl_tls_static_used)
- map->l_tls_firstbyte_offset,
map->l_tls_align)
+ map->l_tls_firstbyte_offset);
size_t used = offset + map->l_tls_blocksize;
/* Account optional static TLS surplus usage. */
size_t use = used - GL(dl_tls_static_used);
*offset_out = offset;
return use;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
}
/* We are trying to perform a static TLS relocation in MAP, but it was
dynamically loaded. This can only work if there is enough surplus in
the static TLS area already allocated for each running thread. If this
@@ -95,30 +54,57 @@ _dl_try_allocate_static_tls (struct link_map *map, bool optional)
/* If we've already used the variable with dynamic access, or if the
alignment requirements are too high, fail. */
if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
|| map->l_tls_align > GLRO(dl_tls_static_align))
|| map->l_tls_align > GLRO (dl_tls_static_align))
{
fail:
return -1;
}
size_t offset = 0;
size_t use = _dl_static_tls_allocation (map, &offset);
#if TLS_TCB_AT_TP
size_t freebytes = GLRO (dl_tls_static_size) - GL(dl_tls_static_used);
if (freebytes < TLS_TCB_SIZE)
goto fail;
freebytes -= TLS_TCB_SIZE;
if (use > GLRO(dl_tls_static_size) - GL(dl_tls_static_used))
size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
if (freebytes < blsize)
goto fail;
size_t n = (freebytes - blsize) / map->l_tls_align;
/* Account optional static TLS surplus usage. */
size_t use = freebytes - n * map->l_tls_align - map->l_tls_firstbyte_offset;
if (optional && use > GL(dl_tls_static_optional))
goto fail;
else if (optional)
GL(dl_tls_static_optional) -= use;
size_t offset = GL(dl_tls_static_used) + use;
map->l_tls_offset = GL(dl_tls_static_used) = offset;
#elif TLS_DTV_AT_TP
/* dl_tls_static_used includes the TCB at the beginning. */
size_t offset = (ALIGN_UP(GL(dl_tls_static_used)
- map->l_tls_firstbyte_offset,
map->l_tls_align)
+ map->l_tls_firstbyte_offset);
size_t used = offset + map->l_tls_blocksize;
if (used > GLRO (dl_tls_static_size))
goto fail;
/* Account optional static TLS surplus usage. */
size_t use = used - GL(dl_tls_static_used);
if (optional && use > GL(dl_tls_static_optional))
goto fail;
else if (optional)
GL(dl_tls_static_optional) -= use;
map->l_tls_offset = offset;
#if TLS_TCB_AT_TP
GL(dl_tls_static_used) = offset;
#elif TLS_DTV_AT_TP
map->l_tls_firstbyte_offset = GL(dl_tls_static_used);
GL(dl_tls_static_used) = offset + map->l_tls_blocksize;
GL(dl_tls_static_used) = used;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
/* Initialise the static TLS region, the map may not yet be l_relocated (a
@@ -145,57 +131,13 @@ _dl_try_allocate_static_tls (struct link_map *map, bool optional)
not be inlined as much as possible. */
void
__attribute_noinline__
_dl_allocate_static_tls (struct link_map *map, struct link_map *sym_map,
const ElfW(Sym) *sym)
_dl_allocate_static_tls (struct link_map *map)
{
if (sym_map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
|| _dl_try_allocate_static_tls (sym_map, false))
if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
|| _dl_try_allocate_static_tls (map, false))
{
const char *symname = "unknown";
const char *def_map_info = "";
const char *def_map_name = "";
struct dl_exception exception;
if (sym != NULL)
{
const char *strtab
= (const char *) D_PTR (sym_map, l_info[DT_STRTAB]);
symname = strtab + sym->st_name;
if (symname[0] == '\0')
symname = "unknown";
}
if (sym_map != map)
{
def_map_info = " defined in ";
def_map_name = DSO_FILENAME (sym_map->l_name);
}
if (sym_map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
{
/* XXX We cannot translate the message. */
_dl_exception_create_format (
&exception, DSO_FILENAME (map->l_name),
"cannot allocate memory in static TLS block: "
"%s%s%s: previously used as global-dynamic",
symname, def_map_info, def_map_name);
}
else
{
size_t offset = 0;
size_t requested = _dl_static_tls_allocation (sym_map, &offset);
size_t available
= (GLRO(dl_tls_static_size) - GL(dl_tls_static_used));
/* XXX We cannot translate the message. */
_dl_exception_create_format (
&exception, DSO_FILENAME (map->l_name),
"cannot allocate memory in static TLS block: "
"%s%s%s: requested %zx, available %zx",
symname, def_map_info, def_map_name, requested, available);
}
_dl_signal_exception (0, &exception, N_("TLS allocation error"));
_dl_signal_error (0, map->l_name, NULL, N_("\
cannot allocate memory in static TLS block"));
}
}
@@ -406,19 +348,23 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
void
_dl_protect_relro (struct link_map *l)
{
for (const ElfW(Phdr) *ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
if (ph->p_type == PT_GNU_RELRO)
{
struct dl_relro_range range = _dl_relro_range (l, ph);
if (range.start != range.end
&& __mprotect ((void *) range.start, range.end - range.start,
PROT_READ) < 0)
{
static const char errstring[] = N_("\
if (l->l_relro_size == 0)
return;
ElfW(Addr) start = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr),
GLRO(dl_pagesize));
ElfW(Addr) end = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr
+ l->l_relro_size),
GLRO(dl_pagesize));
if (start != end
&& __mprotect ((void *) start, end - start, PROT_READ) < 0)
{
static const char errstring[] = N_("\
cannot apply additional memory protection after relocation");
_dl_signal_error (errno, l->l_name, NULL, errstring);
}
}
_dl_signal_error (errno, l->l_name, NULL, errstring);
}
}
void
+2 -2
View File
@@ -33,10 +33,10 @@
&& ((sym_map)->l_tls_offset \
!= FORCED_DYNAMIC_TLS_OFFSET), 1))
#define CHECK_STATIC_TLS(map, sym_map, sym) \
#define CHECK_STATIC_TLS(map, sym_map) \
do { \
if (!HAVE_STATIC_TLS (map, sym_map)) \
_dl_allocate_static_tls (map, sym_map, sym); \
_dl_allocate_static_tls (sym_map); \
} while (0)
#define TRY_STATIC_TLS(map, sym_map) \
+5
View File
@@ -327,6 +327,11 @@ _dl_non_dynamic_init (void)
case PT_GNU_STACK:
_dl_stack_prot_flags = pf_to_prot (ph->p_flags);
break;
case PT_GNU_RELRO:
_dl_main_map.l_relro_addr = ph->p_vaddr;
_dl_main_map.l_relro_size = ph->p_memsz;
break;
}
_dl_handle_execstack_tunable ();
+14 -2
View File
@@ -42,6 +42,20 @@ 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
{
@@ -51,8 +65,6 @@ 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. */
+3 -172
View File
@@ -37,7 +37,6 @@
#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)
@@ -72,9 +71,6 @@ 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:
@@ -179,14 +175,6 @@ 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.
@@ -296,10 +284,6 @@ 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;
}
}
@@ -307,7 +291,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, char **argv)
__tunables_init (char **envp)
{
char *envname = NULL;
char *envval = NULL;
@@ -318,155 +302,6 @@ __tunables_init (char **envp, char **argv)
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;
@@ -510,13 +345,9 @@ __tunables_init (char **envp, char **argv)
for (int i = 0; i < tunable_num_env_alias; i++)
{
/* 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. */
/* Skip over tunables that have either been set or already initialized. */
if (tunables_env_alias[i].t == NULL
|| tunable_set_by_env[tunable_env_alias_list[i]])
|| tunables_env_alias[i].t->initialized)
continue;
if (!tunable_initialize (tunables_env_alias[i].t,
+1 -1
View File
@@ -47,7 +47,7 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
#include "dl-tunable-list.h"
extern void __tunables_init (char **, char **);
extern void __tunables_init (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);
+1 -7
View File
@@ -45,13 +45,7 @@ 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
# 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
);
|| r_type == ELF_MACHINE_IRELATIVE);
#else
return false;
#endif
-1
View File
@@ -847,7 +847,6 @@ 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. */
+2 -4
View File
@@ -47,10 +47,8 @@ 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. Will also be called
with a NULL line at the start and end of each file, for
file-scoped config items.
callback - for each non-blank line in the file, this function is called
with the line and it's location.
*/
void
+5 -183
View File
@@ -44,17 +44,12 @@
#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>
@@ -109,18 +104,12 @@ 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 for libraries. */
/* Configuration file. */
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 *)
@@ -138,13 +127,11 @@ 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 for libraries"), 0},
{ NULL, 't', N_("TUNCONF"), 0, N_("Use TUNCONF as configuration file for tunables"), 0},
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 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 }
};
@@ -177,9 +164,6 @@ 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;
@@ -213,9 +197,6 @@ 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;
}
@@ -440,11 +421,8 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
}
static void
add_dir_callback (char *line, const char *from_file, int from_line)
add_dir_callback (const 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
@@ -1048,155 +1026,6 @@ 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)
@@ -1216,8 +1045,8 @@ main (int argc, char **argv)
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
/* Remaining arguments are additional directories if opt_manual_link
and opt_install are not set. */
if (remaining != argc && !opt_manual_link && !opt_install)
is not set. */
if (remaining != argc && !opt_manual_link)
{
int i;
for (i = remaining; i < argc; ++i)
@@ -1260,9 +1089,6 @@ 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)
@@ -1313,8 +1139,6 @@ main (int argc, char **argv)
exit (0);
}
if (opt_install)
install_cache_file (argv[remaining]);
if (opt_build_cache)
init_cache ();
@@ -1340,8 +1164,6 @@ main (int argc, char **argv)
search_dirs ();
parse_tunconf (tunconfig_file, opt_chroot);
if (opt_build_cache)
{
save_cache (cache_file);
+20
View File
@@ -1198,6 +1198,11 @@ rtld_setup_main_map (struct link_map *main_map)
case PT_GNU_STACK:
GL(dl_stack_prot_flags) = pf_to_prot (ph->p_flags);
break;
case PT_GNU_RELRO:
main_map->l_relro_addr = ph->p_vaddr;
main_map->l_relro_size = ph->p_memsz;
break;
}
_dl_executable_postprocess (main_map, phdr, phnum);
@@ -1265,6 +1270,16 @@ rtld_setup_phdr (void)
& ~(GLRO(dl_pagesize) - 1));
}
}
/* PT_GNU_RELRO is usually the last phdr. */
size_t cnt = rtld_ehdr->e_phnum;
while (cnt-- > 0)
if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
{
_dl_rtld_map.l_relro_addr = rtld_phdr[cnt].p_vaddr;
_dl_rtld_map.l_relro_size = rtld_phdr[cnt].p_memsz;
break;
}
}
/* Adjusts the contents of the stack and related globals for the user
@@ -2356,6 +2371,11 @@ 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. */
}
-137
View File
@@ -1,137 +0,0 @@
/* 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>
@@ -1,3 +0,0 @@
/lib
/lib64
/a
@@ -1,7 +0,0 @@
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
-125
View File
@@ -1,125 +0,0 @@
#!/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
-46
View File
@@ -1,46 +0,0 @@
/* Data definitions for the multiple PT_GNU_RELRO test.
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/>. */
/* Assembly is used because compilers emit SHT_PROGBITS for
__attribute__ ((section)) definitions and gas might warns when its
name-based heuristic retypes .note.* sections; and note sections
must not have the SHF_WRITE flag for the same reason. */
.section .note.a, "a", %note
.balign 8
.globl relro_a
.type relro_a, %object
relro_a:
.dc.a 0xAAAA
.size relro_a, .-relro_a
.section .gap, "aw", %progbits
.balign 8
.globl gap_d
.type gap_d, %object
gap_d:
.dc.a 0xDDDD
.size gap_d, .-gap_d
.section .note.b, "a", %note
.balign 8
.globl relro_b
.type relro_b, %object
relro_b:
.dc.a 0xBBBB
.size relro_b, .-relro_b
-43
View File
@@ -1,43 +0,0 @@
/* Multiple PT_GNU_RELRO test.
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 <support/check.h>
#include <support/check_mem_access.h>
/* The tst-elf-edit.py --note-to-relro convert relro_a and relro_b
to page-padded PT_GNU_RELRO seguments. */
extern unsigned long int relro_a;
extern unsigned long int gap_d;
extern unsigned long int relro_b;
static int
do_test (void)
{
/* Both RELRO regions must be readable but not writable. */
TEST_COMPARE (check_mem_access (&relro_a, false), true);
TEST_COMPARE (check_mem_access (&relro_a, true), false);
TEST_COMPARE (check_mem_access (&relro_b, false), true);
TEST_COMPARE (check_mem_access (&relro_b, true), false);
/* The gap between the two RELRO regions must remain writable. */
TEST_COMPARE (check_mem_access (&gap_d, true), true);
return 0;
}
#include <support/test-driver.c>
-24
View File
@@ -1,24 +0,0 @@
/* Multiple PT_GNU_RELRO test.
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/>. */
SECTIONS {
. = ALIGN(CONSTANT(MAXPAGESIZE));
.note.a : { *(.note.a) . = ALIGN(CONSTANT(MAXPAGESIZE)); }
.gap : { *(.gap) . = ALIGN(CONSTANT(MAXPAGESIZE)); }
.note.b : { *(.note.b) . = ALIGN(CONSTANT(MAXPAGESIZE)); }
}
INSERT AFTER .data;
+15 -21
View File
@@ -32,31 +32,25 @@ sys.path.append(os.path.join(
import glibcelf
def find_relro(path: str, img: glibcelf.Image) -> list:
"""Discover the address ranges of the PT_GNU_RELRO segments."""
regions = []
def find_relro(path: str, img: glibcelf.Image) -> (int, int):
"""Discover the address range of the PT_GNU_RELRO segment."""
for phdr in img.phdrs():
if phdr.p_type == glibcelf.Pt.PT_GNU_RELRO:
# The computation is not entirely accurate because
# _dl_protect_relro in elf/dl-reloc.c rounds both the
# start end and downwards using the run-time page size.
regions.append((phdr.p_vaddr, phdr.p_vaddr + phdr.p_memsz))
if not regions:
sys.stdout.write('{}: error: no PT_GNU_RELRO segment\n'.format(path))
sys.exit(1)
return regions
return phdr.p_vaddr, phdr.p_vaddr + phdr.p_memsz
sys.stdout.write('{}: error: no PT_GNU_RELRO segment\n'.format(path))
sys.exit(1)
def check_in_relro(kind, relro_regions, name, start, size, error):
"""Check if a section or symbol falls within in any RELRO segment."""
def check_in_relro(kind, relro_begin, relro_end, name, start, size, error):
"""Check if a section or symbol falls within in the RELRO segment."""
end = start + size - 1
for relro_begin, relro_end in relro_regions:
if relro_begin <= start <= end < relro_end:
return
error(
'{} {!r} of size {} at 0x{:x} is not in any RELRO range: {}'.format(
kind, name.decode('UTF-8'), size, start,
', '.join('[0x{:x}, 0x{:x})'.format(*region)
for region in relro_regions)))
if not (relro_begin <= start < end < relro_end):
error(
'{} {!r} of size {} at 0x{:x} is not in RELRO range [0x{:x}, 0x{:x})'.format(
kind, name.decode('UTF-8'), start, size,
relro_begin, relro_end))
def get_parser():
"""Return an argument parser for this script."""
@@ -84,7 +78,7 @@ def main(argv):
symbols_found = set()
# Discover the extent of the RELRO segment.
relro_regions = find_relro(opts.object, img)
relro_begin, relro_end = find_relro(opts.object, img)
symbol_table_found = False
errors = False
@@ -115,13 +109,13 @@ def main(argv):
sym.st_name.decode('UTF-8')))
continue
check_in_relro('symbol', relro_regions,
check_in_relro('symbol', relro_begin, relro_end,
sym.st_name, sym.st_value, sym.st_size,
error)
continue # SHT_SYMTAB
if shdr.sh_name == b'.data.rel.ro' \
or shdr.sh_name.startswith(b'.data.rel.ro.'):
check_in_relro('section', relro_regions,
check_in_relro('section', relro_begin, relro_end,
shdr.sh_name, shdr.sh_addr, shdr.sh_size,
error)
continue
-81
View File
@@ -1,81 +0,0 @@
/* 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>
-31
View File
@@ -1,31 +0,0 @@
# 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
View File
View File
-440
View File
@@ -1,440 +0,0 @@
/* 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;
}
-45
View File
@@ -1,45 +0,0 @@
#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);
-7
View File
@@ -257,10 +257,3 @@ $(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
+1 -1
View File
@@ -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__ 44
#define __GLIBC_MINOR__ 43
#define __GLIBC_PREREQ(maj, min) \
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
+4
View File
@@ -340,6 +340,10 @@ struct link_map
lock. See also: CONCURRENCY NOTES in cxa_thread_atexit_impl.c. */
size_t l_tls_dtor_count;
/* Information used to change permission after the relocations are
done. */
ElfW(Addr) l_relro_addr;
size_t l_relro_size;
unsigned long long int l_serial;
};
-2
View File
@@ -91,8 +91,6 @@ 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. */
+1 -1
View File
@@ -24,7 +24,7 @@ test_program_prefix=$2
objpfx=$3
# Create the locale directories.
mkdir -p ${objpfx}domaindir/existing-locale/LC_MESSAGES
mkdir -p ${objpfx}localedir/existing-locale/LC_MESSAGES
msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/translit.mo \
translit.po
+1 -3
View File
@@ -18,9 +18,7 @@
#include <sys/types.h>
#include <kernel_stat.h>
#if !XSTAT_IS_XSTAT64
#ifndef __OFF_T_MATCHES_OFF64_T
# include "ftw-common.c"
versioned_symbol (libc, __new_nftw, nftw, GLIBC_2_3_3);
+1 -4
View File
@@ -31,9 +31,6 @@
#define ftw __rename_ftw
#define nftw __rename_nftw
#include <sys/types.h>
#include <kernel_stat.h>
#include <shlib-compat.h>
#include "ftw-common.c"
@@ -47,7 +44,7 @@ versioned_symbol (libc, __new_nftw64, nftw64, GLIBC_2_3_3);
compat_symbol (libc, __old_nftw64, nftw64, GLIBC_2_1);
#endif
#if XSTAT_IS_XSTAT64
#ifdef __OFF_T_MATCHES_OFF64_T
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)
-1
View File
@@ -77,7 +77,6 @@ DEFINE_LANGUAGE_CODE ("Bislama", bi, bis, bis)
DEFINE_LANGUAGE_CODE3 ("Blin; Bilin", byn, byn)
DEFINE_LANGUAGE_CODE3 ("Bodo", brx, brx)
DEFINE_LANGUAGE_CODE ("Bosnian", bs, bos, bos)
DEFINE_LANGUAGE_CODE3 ("Brahui", brh, brh)
DEFINE_LANGUAGE_CODE3 ("Braj", bra, bra)
DEFINE_LANGUAGE_CODE ("Breton", br, bre, bre)
DEFINE_LANGUAGE_CODE3 ("Buginese", bug, bug)
-1
View File
@@ -74,7 +74,6 @@ bo_IN/UTF-8 \
br_FR.UTF-8/UTF-8 \
br_FR/ISO-8859-1 \
br_FR@euro/ISO-8859-15 \
brh_PK/UTF-8 \
brx_IN/UTF-8 \
bs_BA.UTF-8/UTF-8 \
bs_BA/ISO-8859-2 \
+7 -15
View File
@@ -32,25 +32,17 @@ 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 \
$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
${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
else
rm -rf $stage
echo "Charmap: \"${charmap}\" Inputfile: \"${input}\"" \
"Outputdir: \"${out}\" failed (exit status $ret)"
"Outputdir: \"${out}\" failed"
exit 1
fi
}
+1 -1
View File
@@ -15,7 +15,7 @@ title "C locale"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language ""
+1 -1
View File
@@ -13,7 +13,7 @@ title "Aragonese locale for Spain"
source "Softaragones"
address ""
contact "Jordi Mallach Pérez, Juan Pablo Martínez"
email "libc-alpha@sourceware.org, softaragones@softaragones.org"
email "bug-glibc-locales@gnu.org, softaragones@softaragones.org"
tel ""
fax ""
language "Aragonese"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -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 "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Kuwait"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Lebanon"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Libyan Arab Jamahiriya"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Morocco"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Oman"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Qatar"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -17,7 +17,7 @@ title "Arabic locale for Saudi Arabia"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -19,7 +19,7 @@ title "Arabic language locale for Sudan"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -19,7 +19,7 @@ title "Arabic language locale for South Sudan"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Syrian Arab Republic"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Tunisia"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -15,7 +15,7 @@ title "Arabic language locale for Yemen"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Arabic"
+1 -1
View File
@@ -16,7 +16,7 @@ title "Assamese language locale for India"
source "Amitakhya Phukan, Red Hat"
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc@gnu.org"
tel ""
fax ""
language "Assamese"
+1 -1
View File
@@ -23,7 +23,7 @@ title "Belarusian locale for Belarus"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Belarusian"
+1 -1
View File
@@ -23,7 +23,7 @@ title "Belarusian Latin-Script locale for Belarus"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Belarusian"
+1 -1
View File
@@ -17,7 +17,7 @@ LC_IDENTIFICATION
title "Bangla language locale for India"
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Bangla"
+1 -1
View File
@@ -17,7 +17,7 @@ title "Tibetan language locale for P.R. of China"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc@gnu.org"
tel ""
fax ""
language "Tibetan"
+1 -1
View File
@@ -17,7 +17,7 @@ title "Tibetan language locale for India"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc@gnu.org"
tel ""
fax ""
language "Tibetan"
+1 -1
View File
@@ -19,7 +19,7 @@ LC_IDENTIFICATION
title "Breton locale for France with Euro"
source "Free Software Foundation, Inc."
address "https:////www.gnu.org//software//libc//"
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Breton"
-235
View File
@@ -1,235 +0,0 @@
comment_char %
escape_char /
% This file is part of the GNU C Library and contains locale data.
% The Free Software Foundation does not claim any copyright interest
% in the locale data contained in this file. The foregoing does not
% affect the license of the GNU C Library as a whole. It does not
% exempt you from the conditions of the license if your use would
% otherwise be governed by that license.
% Brahui Language Locale for Pakistan
% Source: Unicode CLDR (locale brh)
% Contact: Hammad Mengal
% Email: hammadalo99@gmail.com
% Language: brh
% Territory: PK
% Revision: 0.4
% Date: 2026-07-19
% Users: general
LC_IDENTIFICATION
title "Brahui Language Locale for Pakistan"
source "Unicode CLDR"
address ""
contact "Hammad Mengal"
email "hammadalo99@gmail.com"
tel ""
fax ""
language "Brahui"
territory "Pakistan"
revision "0.4"
date "2026-07-19"
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_COLLATE
category "i18n:2012";LC_TIME
category "i18n:2012";LC_NUMERIC
category "i18n:2012";LC_MONETARY
category "i18n:2012";LC_MESSAGES
category "i18n:2012";LC_PAPER
category "i18n:2012";LC_NAME
category "i18n:2012";LC_ADDRESS
category "i18n:2012";LC_TELEPHONE
category "i18n:2012";LC_MEASUREMENT
END LC_IDENTIFICATION
LC_CTYPE
copy "i18n"
translit_start
include "translit_combining";""
% Maddah above -> Alef with madda above
<U0653> "<U0622>"
% Farsi yeh -> yeh
<U06CC> "<U064A>"
% Heh goal -> heh
<U06C1> "<U0647>"
% Lam with three dots above -> lam
<U06B7> "<U0644>"
translit_end
END LC_CTYPE
LC_COLLATE
% Brahui uses the Arabic-Urdu based Nastaliq script with one additional
% letter not found in standard Urdu: ڷ (Lam with Three Dots Above),
% representing a retroflex lateral.The tailoring below states the
% Brahui rule explicitly rather than relying on that default.
copy "iso14651_t1"
reorder-after <S0644> % Lam
<S06B7> % ڷ Lam with Three Dots Above - Brahui retroflex lateral
reorder-end
END LC_COLLATE
LC_MONETARY
int_curr_symbol "PKR "
currency_symbol "Rs"
mon_decimal_point "."
mon_thousands_sep ","
mon_grouping 3
positive_sign ""
negative_sign "-"
int_frac_digits 2
frac_digits 2
p_cs_precedes 1
p_sep_by_space 1
n_cs_precedes 1
n_sep_by_space 1
p_sign_posn 2
n_sign_posn 1
END LC_MONETARY
LC_NUMERIC
% Brahui uses Western (Latin) digits, not Eastern Arabic-Indic digits.
decimal_point "."
thousands_sep ","
grouping 3
END LC_NUMERIC
LC_TIME
% Brahui day names follow the Persian/Dari ordinal convention
% (yak-shanbeh, do-shanbeh, ...).
% The two elements are written with a space, matching CLDR brh.
% Brahui has no distinct abday names, so abday repeats the
% full forms. ur_PK, pa_PK and fa_IR do the same.
abday "یک شنبہ";/
"دو شنبہ";/
"سہ شنبہ";/
"چار شنبہ";/
"پنچ شنبہ";/
"جمعہ";/
"شنبہ"
day "یک شنبہ";/
"دو شنبہ";/
"سہ شنبہ";/
"چار شنبہ";/
"پنچ شنبہ";/
"جمعہ";/
"شنبہ"
abmon "جنوری";/
"فروری";/
"مارچ";/
"اپریل";/
"مئی";/
"جون";/
"جولائی";/
"اگست";/
"ستمبر";/
"اکتوبر";/
"نومبر";/
"دسمبر"
mon "جنوری";/
"فروری";/
"مارچ";/
"اپریل";/
"مئی";/
"جون";/
"جولائی";/
"اگست";/
"ستمبر";/
"اکتوبر";/
"نومبر";/
"دسمبر"
% Date and time format. The date precedes the time, matching the CLDR
% brh date-time combination pattern, and runs weekday, day, month,
% year, as in the CLDR brh full date pattern. The separator before the
% time is U+060C ARABIC COMMA, which is the comma in the CLDR brh
% punctuation exemplar set. Same shape as sd_PK.
d_t_fmt "%A %d %B %Y<U060C> %H:%M:%S"
% Date and time format for date(1)
date_fmt "%A %d %B %Y<U060C> %H:%M:%S %Z"
% date Format. standard in Pakistan
d_fmt "%d//%m//%Y"
% time format 24 hour
t_fmt "%H:%M:%S"
am_pm "AM";"PM"
% time format 12 hour
t_fmt_ampm "%I:%M:%S %p"
% Calender rtl
cal_direction 3
first_weekday 1
first_workday 2
week 7;19971130;1
END LC_TIME
LC_MESSAGES
% Brahui yes/no expressions
% ہ = ہان (Brahui: yes) - U+06C1 Heh Goal
% آ = آخہ (Brahui: no)
% yesexpr also accepts:
% ه U+0647 ARABIC LETTER HEH, since both spellings of the initial
% letter of ہان are in use
% ب U+0628, the initial of بلکل (bilkul, "absolutely"), a common
% affirmative
% yesexpr matches: + 1 y Y ج(U+062C) ہ(U+06C1) ه(U+0647) ب(U+0628)
% noexpr matches: - 0 n N آ(U+0622) ا(U+0627) ن(U+0646)
yesexpr "^[+1yYجہهب]"
noexpr "^[-0nNآان]"
yesstr "ہان"
nostr "آخہ"
END LC_MESSAGES
LC_PAPER
copy "i18n"
END LC_PAPER
LC_MEASUREMENT
copy "i18n"
END LC_MEASUREMENT
LC_NAME
% Brahui name formatting
% Western order: salutation, given name, middle name, family name
name_fmt "%d%t%g%t%m%t%f"
name_gen "جواننگا"
name_mr "خواجہ"
name_mrs "گودی"
name_miss "بی بی"
name_ms "بی بی"
END LC_NAME
LC_ADDRESS
% Brahui address format for Pakistan
postal_fmt "%a%N%f%N%d%N%b%N%h %s %e %r%N%T %z%N%c%N"
country_name "پاکستان"
country_ab2 "PK"
country_ab3 "PAK"
country_num 586
country_car "PK"
% Brahui has no ISO 639-1 (two-letter) code, so lang_ab is omitted,
% following the ckb_IQ precedent. brh is an ISO 639-3 code.
lang_name "براہوئی"
lang_term "brh"
lang_lib "brh"
END LC_ADDRESS
LC_TELEPHONE
tel_int_fmt "+%c %a %l"
int_prefix "92"
int_select "00"
END LC_TELEPHONE
+1 -1
View File
@@ -16,7 +16,7 @@ title "Bodo language locale for India"
source "Red Hat Pune"
address "Level 1, Tower X, Cybercity, Magarpatta City, Hadapsar, Pune-411013 "
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Bodo"
+1 -1
View File
@@ -26,7 +26,7 @@ title "Catalan locale for Spain"
source "RAP"
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Catalan"
+1 -1
View File
@@ -22,7 +22,7 @@ title "Catalan locale for Catalonia with Euro"
source "Free Software Foundation, Inc."
address "https:////www.gnu.org//software//libc//"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Catalan"
+1 -1
View File
@@ -21,7 +21,7 @@ title "Mandarin Chinese locale for the Republic of China"
source ""
address ""
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Mandarin Chinese"
+1 -1
View File
@@ -113,7 +113,7 @@ title "Czech locale for the Czech Republic"
source "Free Software Foundation, Inc."
address "https:////www.gnu.org//software//libc//"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Czech"
+1 -1
View File
@@ -26,7 +26,7 @@ title "Kashubian locale for Poland"
source "csb_PL locale"
address ""
contact "Michal Ostrowski"
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Kashubian"
+1 -1
View File
@@ -35,7 +35,7 @@ title "Danish locale for Denmark"
source "Danish Standards Association"
address "Kollegievej 6, DK-2920 Charlottenlund, Danmark"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Danish"
+1 -1
View File
@@ -26,7 +26,7 @@ title "German locale for Austria"
source "O:sterreiches Normungsinstitut"
address "Postfach 130, A-1021 Wien"
contact "Gerhard Budin"
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "Austrian German"
+1 -1
View File
@@ -26,7 +26,7 @@ title "German locale for Austria with Euro"
source "O:sterreiches Normungsinstitut"
address "Postfach 130, A-1021 Wien"
contact "Gerhard Budin"
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "German"
+1 -1
View File
@@ -27,7 +27,7 @@ title "German locale for Belgium"
source "RAP"
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
contact ""
email "libc-alpha@sourceware.org"
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "German"

Some files were not shown because too many files have changed in this diff Show More