diff options
428 files changed, 7611 insertions, 2795 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 9ed08d750e2f..84efa04f1ccb 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -194,11 +194,13 @@ precommit_task: matrix: - name: amd64 smoke test using internal ci systems only_if: $CIRRUS_REPO_FULL_NAME != 'freebsd/freebsd-src' || $CIRRUS_BRANCH =~ 'pull/.*' + trigger_type: manual env: TARGET: amd64 TARGET_ARCH: amd64 - name: aarch64 smoke test using internal ci systems only_if: $CIRRUS_REPO_FULL_NAME != 'freebsd/freebsd-src' || $CIRRUS_BRANCH =~ 'pull/.*' + trigger_type: manual env: TARGET: arm64 TARGET_ARCH: aarch64 diff --git a/Makefile.inc1 b/Makefile.inc1 index 97a0b00cc517..6744a25965c6 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1992,8 +1992,16 @@ PKG_ABI!= ${PKG_CMD} -o ABI_FILE=${PKG_ABI_FILE} config ABI _pkgbootstrap: .PHONY .if make(*package*) && !exists(${LOCALBASE}/sbin/pkg) +.if defined(BOOTSTRAP_PKG_FROM_PORTS) + env - UNAME_r=${UNAME_r} PATH=$$PATH \ + make -C ${PORTSDIR}/ports-mgmt/pkg \ + I_DONT_CARE_IF_MY_BUILDS_TARGET_THE_WRONG_RELEASE=1 \ + BATCH=1 WRKDIRPREFIX=/tmp/ports DISTDIR=/tmp/distfiles \ + all install clean +.else @env ASSUME_ALWAYS_YES=YES pkg bootstrap .endif +.endif PKG_BIN_VERSION!=${PKG_CMD} --version </dev/null 2>/dev/null |\ awk -F. '/^[0-9.]+$$/ {print $$1 * 10000 + $$2 * 100 + $$3}' @@ -2038,13 +2046,17 @@ packages: .PHONY update-packages: .PHONY ${_+_}${MAKE} -C ${.CURDIR} ${PKGMAKEARGS} real-update-packages -package-pkg: .PHONY +package-pkg: _pkgbootstrap _repodir .PHONY +.if defined(INCLUDE_PKG_IN_PKGBASE_REPO) +.if exists(${PORTSDIR}) rm -rf /tmp/ports.${TARGET} || : - env ${WMAKEENV:Q} SRCDIR=${.CURDIR} PORTSDIR=${PORTSDIR} REVISION=${_REVISION} \ + env ${WMAKEENV} SRCDIR=${.CURDIR} PORTSDIR=${PORTSDIR} REVISION=${_REVISION} \ PKG_CMD=${PKG_CMD} PKG_VERSION=${PKG_VERSION} REPODIR=${REPODIR} \ WSTAGEDIR=${WSTAGEDIR} \ OSVERSION="${SRCRELDATE}" \ sh ${.CURDIR}/release/scripts/make-pkg-package.sh +.endif +.endif real-packages: stage-packages create-packages sign-packages .PHONY @@ -2127,7 +2139,7 @@ create-packages-source: _pkgbootstrap _repodir .PHONY SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} \ create-source-packages -create-packages: .PHONY create-packages-world create-packages-kernel create-packages-source create-packages-sets +create-packages: .PHONY create-packages-world create-packages-kernel create-packages-source package-pkg create-packages-sets create-source-src-package: _pkgbootstrap .PHONY rm -f ${SSTAGEDIR}/src.plist 2>/dev/null || : diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 02a727d631bd..d3b1a0239e3f 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,13 @@ # xargs -n1 | sort | uniq -d; # done +# 20250917: Remove a miscapitalized manual +OLD_FILES+=usr/share/man/man9/vnet.9.gz +OLD_FILES+=usr/share/man/man9/vimage.9.gz + +# 20250911: This tool is no longer needed +OLD_FILES+=usr/tests/bin/cp/sparse + # 20250826: Remove a misspelled manual OLD_FILES+=usr/share/man/man3/sysdecode_syscallnames.3.gz @@ -27,6 +27,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: world, or to merely disable the most expensive debugging functionality at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20250918: + mandoc (including /usr/bin/man) has been moved to a new package, + FreeBSD-mandoc. If you have the minimal set installed, this package + will be installed automatically, otherwise you may want to install it. + + Kyua has been moved to the FreeBSD-kyua package, and ATF has been moved + to the FreeBSD-atf* packages. If you have FreeBSD-tests installed, + these packages will be installed automatically, otherwise you should + manually install them if you need these tools. + + This only affects pkgbase users. + 20250912: If SRCCONF is unset and a file named src.conf is present at the top of the source tree, it will now be used instead of @@ -333,8 +345,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: 20250106: A new SOC_ROCKCHIP options appeared, so if you have a custom kernel configuration - targetting Rockchip SoC you need to add it so shared and mandatory drivers for - this SoC familly will be selected. + targeting Rockchip SoC you need to add it so shared and mandatory drivers for + this SoC family will be selected. Also a new rk8xx device was added, this select the base driver for Rockchip PMIC. 20241223: @@ -529,7 +541,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: 20230817: Serial communication (in boot loaders, kernel, and userland) has been changed to default to 115200 bps, in line with common industry - practice and typcial firmware serial console redirection + practice and typical firmware serial console redirection configuration. Note that the early x86 BIOS bootloader (i.e., boot0sio) does not @@ -613,7 +625,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: runs make -j${JOB_MAX} buildworld > ../buildworld.log 2>&1 - where JOB_MAX is derrived from ncpus in local.sys.mk if not set in env. + where JOB_MAX is derived from ncpus in local.sys.mk if not set in env. 20230316: Video related devices for some arm devices have been renamed. @@ -641,7 +653,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: 20230130: As of commit 7c40e2d5f685, the dependency on netlink(4) has been added to the linux_common(4) module. Users relying on linux_common may need - to complile netlink(4) module if it is not present in their kernel. + to compile netlink(4) module if it is not present in their kernel. 20230126: The WITHOUT_CXX option has been removed. C++ components in the base @@ -661,7 +673,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW: 20221205: dma(8) has replaced sendmail(8) as the default mta. For people willing - to reenable sendmail(8): + to re-enable sendmail(8): $ cp /usr/share/examples/sendmail/mailer.conf /etc/mail/mailer.conf diff --git a/bin/cp/tests/Makefile b/bin/cp/tests/Makefile index 3fa9ae8f0685..a1917ada8fbf 100644 --- a/bin/cp/tests/Makefile +++ b/bin/cp/tests/Makefile @@ -1,7 +1,5 @@ PACKAGE= tests ATF_TESTS_SH= cp_test -PROGS+= sparse -BINDIR= ${TESTSDIR} .include <bsd.test.mk> diff --git a/bin/cp/tests/cp_test.sh b/bin/cp/tests/cp_test.sh index 999993bfad67..fdf50d042f0b 100755 --- a/bin/cp/tests/cp_test.sh +++ b/bin/cp/tests/cp_test.sh @@ -384,7 +384,7 @@ samefile_body() file_is_sparse() { - atf_check ${0%/*}/sparse "$1" + atf_check -o match:"^[0-9]+-[0-9]" stat -h "$1" } files_are_equal() diff --git a/bin/cp/tests/sparse.c b/bin/cp/tests/sparse.c deleted file mode 100644 index 78957581a56c..000000000000 --- a/bin/cp/tests/sparse.c +++ /dev/null @@ -1,73 +0,0 @@ -/*- - * Copyright (c) 2023 Klara, Inc. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <err.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <sysexits.h> -#include <unistd.h> - -static bool verbose; - -/* - * Returns true if the file named by its argument is sparse, i.e. if - * seeking to SEEK_HOLE returns a different value than seeking to - * SEEK_END. - */ -static bool -sparse(const char *filename) -{ - off_t hole, end; - int fd; - - if ((fd = open(filename, O_RDONLY)) < 0 || - (hole = lseek(fd, 0, SEEK_HOLE)) < 0 || - (end = lseek(fd, 0, SEEK_END)) < 0) - err(1, "%s", filename); - close(fd); - if (end > hole) { - if (verbose) - printf("%s: hole at %zu\n", filename, (size_t)hole); - return (true); - } - return (false); -} - -static void -usage(void) -{ - - fprintf(stderr, "usage: sparse [-v] file [...]\n"); - exit(EX_USAGE); -} - -int -main(int argc, char *argv[]) -{ - int opt, rv; - - while ((opt = getopt(argc, argv, "v")) != -1) { - switch (opt) { - case 'v': - verbose = true; - break; - default: - usage(); - break; - } - } - argc -= optind; - argv += optind; - if (argc == 0) - usage(); - rv = EXIT_SUCCESS; - while (argc-- > 0) - if (!sparse(*argv++)) - rv = EXIT_FAILURE; - exit(rv); -} diff --git a/bin/sh/dot.profile b/bin/sh/dot.profile index d27a2ae2fdbe..cba9bcf18ad9 100644 --- a/bin/sh/dot.profile +++ b/bin/sh/dot.profile @@ -1,6 +1,4 @@ # -HOME=/root -export HOME PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin export PATH TERM=${TERM:-xterm} diff --git a/cddl/lib/libdtrace/psinfo.d b/cddl/lib/libdtrace/psinfo.d index c0cd5b121064..8dc27e812965 100644 --- a/cddl/lib/libdtrace/psinfo.d +++ b/cddl/lib/libdtrace/psinfo.d @@ -55,7 +55,7 @@ translator psinfo_t < struct proc *T > { pr_uid = T->p_ucred->cr_ruid; pr_euid = T->p_ucred->cr_uid; pr_gid = T->p_ucred->cr_rgid; - pr_egid = T->p_ucred->cr_groups[0]; + pr_egid = T->p_ucred->cr_gid; pr_addr = 0; pr_psargs = (T->p_args == 0) ? "" : memstr(T->p_args->ar_args, ' ', T->p_args->ar_length); diff --git a/contrib/expat/Changes b/contrib/expat/Changes index 9d6c64b6a460..092252ed1fa3 100644 --- a/contrib/expat/Changes +++ b/contrib/expat/Changes @@ -15,12 +15,16 @@ !! ClusterFuzz findings with few-days-max response times in communication !! !! in order to (1) have a sound fix ready before the end of a 90 days !! !! grace period and (2) in a sustainable manner, !! -!! - helping CPython Expat bindings with supporting Expat's billion laughs !! +!! - helping CPython Expat bindings with supporting Expat's amplification !! !! attack protection API (https://github.com/python/cpython/issues/90949): !! +!! - XML_SetAllocTrackerActivationThreshold !! +!! - XML_SetAllocTrackerMaximumAmplification !! !! - XML_SetBillionLaughsAttackProtectionActivationThreshold !! !! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !! !! - helping Perl's XML::Parser Expat bindings with supporting Expat's !! !! security API (https://github.com/cpan-authors/XML-Parser/issues/102): !! +!! - XML_SetAllocTrackerActivationThreshold !! +!! - XML_SetAllocTrackerMaximumAmplification !! !! - XML_SetBillionLaughsAttackProtectionActivationThreshold !! !! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !! !! - XML_SetReparseDeferralEnabled !! @@ -37,6 +41,79 @@ !! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Release 2.7.2 Tue September 16 2025 + Security fixes: + #1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of + dynamic memory from within an Expat parser (e.g. previously + a ~250 KiB sized document was able to cause allocation of + ~800 MiB from the heap, i.e. an "amplification" of factor + ~3,300); once a threshold (that defaults to 64 MiB) is + reached, a maximum amplification factor (that defaults to + 100.0) is enforced, and violating documents are rejected + with an out-of-memory error. + There are two new API functions to fine-tune this new + behavior: + - XML_SetAllocTrackerActivationThreshold + - XML_SetAllocTrackerMaximumAmplification . + If you ever need to increase these defaults for non-attack + XML payload, please file a bug report with libexpat. + There is also a new environment variable + EXPAT_MALLOC_DEBUG=(0|1|2) to control the verbosity + of allocations debugging at runtime, disabled by default. + Known impact is (reliable and easy) denial of service: + CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H/E:H/RL:O/RC:C + (Base Score: 7.5, Temporal Score: 7.2) + Please note that a layer of compression around XML can + significantly reduce the minimum attack payload size. + Distributors intending to backport (or cherry-pick) the + fix need to copy 99% of the related pull request, not just + the "lib: Implement tracking of dynamic memory allocations" + commit, to not end up with a state that literally does both + too much and too little at the same time. Appending ".diff" + to the pull request URL could be of help. + + Other changes: + #1008 #1017 Autotools: Sync CMake templates with CMake 3.31 for macOS + #1007 CMake: Drop support for CMake <3.15 + #1004 CMake: Fix off_t detection for -Werror + #1007 CMake|Windows: Fix -DEXPAT_MSVC_STATIC_CRT=ON + #1013 Windows: Drop support for Visual Studio <=16.0/2019 + #1026 xmlwf: Mention supported environment variables in + --help output + #1024 xmlwf: Fix (internal) help generator + #1034 docs: Promote the contract to call function + XML_FreeContentModel when registering a custom + element declaration handler (via a call to function + XML_SetElementDeclHandler) + #1027 docs: Add missing <p>..</p> wrap + #994 docs: Drop AppVeyor badge + #1000 tests: Fix portable_strndup + #1036 Drop casts around malloc/free/realloc that C99 does not need + #1010 Replace empty for-loops with while loops + #1011 Add const with internal XmlInitUnknownEncodingNS + #14 #1037 Drop an OpenVMS support leftover + #999 #1001 Address more clang-tidy warnings + #1030 #1038 Version info bumped from 11:2:10 (libexpat*.so.1.10.2) + to 12:0:11 (libexpat*.so.1.11.0); see https://verbump.de/ + for what these numbers do + + Infrastructure: + #1003 CI: Cover compilation on FreeBSD + #1009 #1035 CI: Upgrade Clang from 19 to 21 + #1031 CI: Make calling Cppcheck without --suppress=objectIndex + and --suppress=unknownMacro possible + #1013 CI|Windows: Get off of deprecated image "windows-2019" + #1008 #1017 .. + #1023 #1025 CI: Adapt to breaking changes in GitHub Actions + + Special thanks to: + Alexander Bluhm + Neil Pang + Theo Buehler + and + OSS-Fuzz / ClusterFuzz + Perl XML::Parser + Release 2.7.1 Thu March 27 2025 Bug fixes: #980 #989 Restore event pointer behavior from Expat 2.6.4 @@ -54,7 +131,7 @@ Release 2.7.1 Thu March 27 2025 #983 #984 Fix printf format specifiers for 32bit Emscripten #992 docs: Promote OpenSSF Best Practices self-certification #978 tests/benchmark: Resolve mistaken double close - #986 Address compiler warnings + #986 Address Frama-C warnings #990 #993 Version info bumped from 11:1:10 (libexpat*.so.1.10.1) to 11:2:10 (libexpat*.so.1.10.2); see https://verbump.de/ for what these numbers do diff --git a/contrib/expat/Makefile.am b/contrib/expat/Makefile.am index c20531a8d6c6..d612d432becb 100644 --- a/contrib/expat/Makefile.am +++ b/contrib/expat/Makefile.am @@ -58,10 +58,8 @@ pkgconfig_DATA = expat.pc pkgconfigdir = $(libdir)/pkgconfig -dist_cmake_DATA = \ - cmake/autotools/expat.cmake - nodist_cmake_DATA = \ + cmake/autotools/expat.cmake \ cmake/autotools/expat-config-version.cmake \ cmake/autotools/expat-noconfig.cmake \ cmake/expat-config.cmake @@ -70,6 +68,9 @@ cmakedir = $(libdir)/cmake/expat-@PACKAGE_VERSION@ _EXTRA_DIST_CMAKE = \ + cmake/autotools/expat__linux.cmake.in \ + cmake/autotools/expat__macos.cmake.in \ + cmake/autotools/expat__windows.cmake.in \ cmake/autotools/expat-noconfig__linux.cmake.in \ cmake/autotools/expat-noconfig__macos.cmake.in \ cmake/autotools/expat-noconfig__windows.cmake.in \ diff --git a/contrib/expat/Makefile.in b/contrib/expat/Makefile.in index 069ec4047eea..b799591f2fc2 100644 --- a/contrib/expat/Makefile.in +++ b/contrib/expat/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -105,6 +105,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -145,12 +147,13 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ - $(am__configure_deps) $(dist_cmake_DATA) $(am__DIST_COMMON) + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = expat_config.h CONFIG_CLEAN_FILES = expat.pc cmake/expat-config.cmake \ + cmake/autotools/expat.cmake \ cmake/autotools/expat-config-version.cmake \ cmake/autotools/expat-noconfig.cmake run.sh CONFIG_CLEAN_VPATH_FILES = @@ -203,14 +206,12 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ + { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } -am__installdirs = "$(DESTDIR)$(cmakedir)" "$(DESTDIR)$(cmakedir)" \ - "$(DESTDIR)$(pkgconfigdir)" -DATA = $(dist_cmake_DATA) $(nodist_cmake_DATA) $(pkgconfig_DATA) +am__installdirs = "$(DESTDIR)$(cmakedir)" "$(DESTDIR)$(pkgconfigdir)" +DATA = $(nodist_cmake_DATA) $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ @@ -256,8 +257,8 @@ distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ - find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -rf "$(distdir)" \ + find "$(distdir)" -type d ! -perm -700 -exec chmod u+rwx {} ';' \ + ; rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) @@ -288,14 +289,16 @@ am__relativize = \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).tar.lz \ $(distdir).tar.xz -GZIP_ENV = --best +GZIP_ENV = -9 DIST_TARGETS = dist-lzip dist-xz dist-bzip2 dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' -distcleancheck_listfiles = find . -type f -print +distcleancheck_listfiles = \ + find . \( -type f -a \! \ + \( -name .nfs* -o -name .smb* -o -name .__afs* \) \) -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ @@ -403,8 +406,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -458,16 +463,17 @@ LIBTOOLFLAGS = --verbose SUBDIRS = lib $(am__append_1) $(am__append_2) $(am__append_3) pkgconfig_DATA = expat.pc pkgconfigdir = $(libdir)/pkgconfig -dist_cmake_DATA = \ - cmake/autotools/expat.cmake - nodist_cmake_DATA = \ + cmake/autotools/expat.cmake \ cmake/autotools/expat-config-version.cmake \ cmake/autotools/expat-noconfig.cmake \ cmake/expat-config.cmake cmakedir = $(libdir)/cmake/expat-@PACKAGE_VERSION@ _EXTRA_DIST_CMAKE = \ + cmake/autotools/expat__linux.cmake.in \ + cmake/autotools/expat__macos.cmake.in \ + cmake/autotools/expat__windows.cmake.in \ cmake/autotools/expat-noconfig__linux.cmake.in \ cmake/autotools/expat-noconfig__macos.cmake.in \ cmake/autotools/expat-noconfig__windows.cmake.in \ @@ -552,12 +558,12 @@ expat_config.h: stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/expat_config.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status expat_config.h + $(AM_V_at)rm -f stamp-h1 + $(AM_V_GEN)cd $(top_builddir) && $(SHELL) ./config.status expat_config.h $(srcdir)/expat_config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ + $(AM_V_GEN)($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + $(AM_V_at)rm -f stamp-h1 + $(AM_V_at)touch $@ distclean-hdr: -rm -f expat_config.h stamp-h1 @@ -565,6 +571,8 @@ expat.pc: $(top_builddir)/config.status $(srcdir)/expat.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ cmake/expat-config.cmake: $(top_builddir)/config.status $(top_srcdir)/cmake/expat-config.cmake.in cd $(top_builddir) && $(SHELL) ./config.status $@ +cmake/autotools/expat.cmake: $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $@ cmake/autotools/expat-config-version.cmake: $(top_builddir)/config.status $(top_srcdir)/cmake/autotools/expat-config-version.cmake.in cd $(top_builddir) && $(SHELL) ./config.status $@ cmake/autotools/expat-noconfig.cmake: $(top_builddir)/config.status @@ -580,27 +588,6 @@ clean-libtool: distclean-libtool: -rm -f libtool config.lt -install-dist_cmakeDATA: $(dist_cmake_DATA) - @$(NORMAL_INSTALL) - @list='$(dist_cmake_DATA)'; test -n "$(cmakedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(cmakedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(cmakedir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(cmakedir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(cmakedir)" || exit $$?; \ - done - -uninstall-dist_cmakeDATA: - @$(NORMAL_UNINSTALL) - @list='$(dist_cmake_DATA)'; test -n "$(cmakedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(cmakedir)'; $(am__uninstall_files_from_dir) install-nodist_cmakeDATA: $(nodist_cmake_DATA) @$(NORMAL_INSTALL) @list='$(nodist_cmake_DATA)'; test -n "$(cmakedir)" || list=; \ @@ -749,12 +736,13 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) - test -d "$(distdir)" || mkdir "$(distdir)" + $(AM_V_at)$(MKDIR_P) "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -822,6 +810,10 @@ dist-gzip: distdir dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) + +dist-bzip3: distdir + tardir=$(distdir) && $(am__tar) | bzip3 -c >$(distdir).tar.bz3 + $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) @@ -862,9 +854,11 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.bz3*) \ + bzip3 -dc $(distdir).tar.bz3 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ @@ -872,7 +866,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ @@ -948,7 +942,7 @@ check: check-recursive all-am: Makefile $(DATA) expat_config.h installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(cmakedir)" "$(DESTDIR)$(cmakedir)" "$(DESTDIR)$(pkgconfigdir)"; do \ + for dir in "$(DESTDIR)$(cmakedir)" "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -975,8 +969,8 @@ mostlyclean-generic: clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -1003,8 +997,7 @@ info: info-recursive info-am: -install-data-am: install-dist_cmakeDATA install-nodist_cmakeDATA \ - install-pkgconfigDATA +install-data-am: install-nodist_cmakeDATA install-pkgconfigDATA install-dvi: install-dvi-recursive @@ -1050,29 +1043,27 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-dist_cmakeDATA uninstall-nodist_cmakeDATA \ - uninstall-pkgconfigDATA +uninstall-am: uninstall-nodist_cmakeDATA uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ - dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ - dist-xz dist-zip dist-zstd distcheck distclean \ + dist-all dist-bzip2 dist-bzip3 dist-gzip dist-lzip dist-shar \ + dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dist_cmakeDATA \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-nodist_cmakeDATA install-pdf \ - install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am tags tags-am uninstall uninstall-am \ - uninstall-dist_cmakeDATA uninstall-nodist_cmakeDATA \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man \ + install-nodist_cmakeDATA install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-nodist_cmakeDATA \ uninstall-pkgconfigDATA .PRECIOUS: Makefile @@ -1149,3 +1140,10 @@ qa: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/README.md b/contrib/expat/README.md index 77c6bf27d307..fdaaf459e204 100644 --- a/contrib/expat/README.md +++ b/contrib/expat/README.md @@ -1,5 +1,4 @@ [](https://github.com/libexpat/libexpat/actions/workflows/linux.yml) -[](https://ci.appveyor.com/project/libexpat/libexpat) [](https://repology.org/metapackage/expat/versions) [](https://sourceforge.net/projects/expat/files/) [](https://github.com/libexpat/libexpat/releases) @@ -12,7 +11,7 @@ > at the top of the `Changes` file. -# Expat, Release 2.7.1 +# Expat, Release 2.7.2 This is Expat, a C99 library for parsing [XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by @@ -27,7 +26,8 @@ Expat supports the following C99 compilers: - GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++) - LLVM Clang >=3.5 -- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`) +- Microsoft Visual Studio >=17.0/2022 + (the oldest version supported by the [official GitHub Actions Windows images](https://github.com/actions/runner-images)) Windows users can use the [`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases), diff --git a/contrib/expat/configure.ac b/contrib/expat/configure.ac index 0c88b8867019..b9966eabcd60 100644 --- a/contrib/expat/configure.ac +++ b/contrib/expat/configure.ac @@ -84,9 +84,9 @@ dnl dnl If the API changes incompatibly set LIBAGE back to 0 dnl -LIBCURRENT=11 # sync -LIBREVISION=2 # with -LIBAGE=10 # CMakeLists.txt! +LIBCURRENT=12 # sync +LIBREVISION=0 # with +LIBAGE=11 # CMakeLists.txt! AC_CONFIG_HEADERS([expat_config.h]) AH_TOP([#ifndef EXPAT_CONFIG_H @@ -440,12 +440,22 @@ AC_MSG_RESULT([${CMAKE_SHARED_LIBRARY_PREFIX}]) AC_SUBST([CMAKE_SHARED_LIBRARY_PREFIX]) AS_CASE("${host_os}", - [darwin*], [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__macos.cmake.in], - [mingw*|cygwin*], [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__windows.cmake.in], - [CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__linux.cmake.in]) + [darwin*], [ + CMAKE_SOURCE=cmake/autotools/expat__macos.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__macos.cmake.in + ], + [mingw*|cygwin*], [ + CMAKE_SOURCE=cmake/autotools/expat__windows.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__windows.cmake.in + ], + [ + CMAKE_SOURCE=cmake/autotools/expat__linux.cmake.in + CMAKE_NOCONFIG_SOURCE=cmake/autotools/expat-noconfig__linux.cmake.in + ]) AC_CONFIG_FILES([Makefile] [expat.pc] [cmake/expat-config.cmake] + [cmake/autotools/expat.cmake:${CMAKE_SOURCE}] [cmake/autotools/expat-config-version.cmake] [cmake/autotools/expat-noconfig.cmake:${CMAKE_NOCONFIG_SOURCE}] [doc/Makefile] diff --git a/contrib/expat/doc/Makefile.in b/contrib/expat/doc/Makefile.in index 72deb0565d94..13be5107f89b 100644 --- a/contrib/expat/doc/Makefile.in +++ b/contrib/expat/doc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -102,6 +102,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -184,10 +186,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ + { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" @@ -303,8 +304,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -442,6 +445,7 @@ ctags CTAGS: cscope cscopelist: @WITH_DISTRIBUTABLE_MANPAGE_TRUE@dist-hook: + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -507,11 +511,11 @@ install-strip: mostlyclean-generic: clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + -$(am__rm_f) $(CLEANFILES) distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -616,3 +620,10 @@ uninstall-man: uninstall-man1 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/doc/reference.html b/contrib/expat/doc/reference.html index 2b3bd39580a9..12b12b92ff6d 100644 --- a/contrib/expat/doc/reference.html +++ b/contrib/expat/doc/reference.html @@ -52,7 +52,7 @@ <div> <h1> The Expat XML Parser - <small>Release 2.7.1</small> + <small>Release 2.7.2</small> </h1> </div> <div class="content"> @@ -157,6 +157,8 @@ interface.</p> <ul> <li><a href="#XML_SetBillionLaughsAttackProtectionMaximumAmplification">XML_SetBillionLaughsAttackProtectionMaximumAmplification</a></li> <li><a href="#XML_SetBillionLaughsAttackProtectionActivationThreshold">XML_SetBillionLaughsAttackProtectionActivationThreshold</a></li> + <li><a href="#XML_SetAllocTrackerMaximumAmplification">XML_SetAllocTrackerMaximumAmplification</a></li> + <li><a href="#XML_SetAllocTrackerActivationThreshold">XML_SetAllocTrackerActivationThreshold</a></li> <li><a href="#XML_SetReparseDeferralEnabled">XML_SetReparseDeferralEnabled</a></li> </ul> </li> @@ -319,7 +321,7 @@ directions in the next section. Otherwise if you have Microsoft's Developer Studio installed, you can use CMake to generate a <code>.sln</code> file, e.g. <code> -cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo . +cmake -G"Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=RelWithDebInfo . </code>, and build Expat using <code>msbuild /m expat.sln</code> after.</p> <p>Alternatively, you may download the Win32 binary package that @@ -1905,7 +1907,7 @@ struct XML_cp { <p>Sets a handler for element declarations in a DTD. The handler gets called with the name of the element in the declaration and a pointer to a structure that contains the element model. It's the user code's -responsibility to free model when finished with it. See <code> +responsibility to free model when finished with via a call to <code> <a href="#XML_FreeContentModel">XML_FreeContentModel</a></code>. There is no need to free the model from the handler, it can be kept around and freed at a later stage.</p> @@ -2198,13 +2200,13 @@ XML_SetBillionLaughsAttackProtectionMaximumAmplification(XML_Parser p, returns <code>XML_TRUE</code> upon success and <code>XML_FALSE</code> upon error. </p> - The amplification factor is calculated as .. - <pre> - amplification := (direct + indirect) / direct - </pre> - .. while parsing, whereas - <code>direct</code> is the number of bytes read from the primary document in parsing and - <code>indirect</code> is the number of bytes added by expanding entities and reading of external DTD files, combined. + <p>The amplification factor is calculated as ..</p> + <pre>amplification := (direct + indirect) / direct</pre> + <p> + .. while parsing, whereas + <code>direct</code> is the number of bytes read from the primary document in parsing and + <code>indirect</code> is the number of bytes added by expanding entities and reading of external DTD files, combined. + </p> <p>For a call to <code>XML_SetBillionLaughsAttackProtectionMaximumAmplification</code> to succeed:</p> <ul> @@ -2267,6 +2269,120 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(XML_Parser p, </p> </div> +<h4 id="XML_SetAllocTrackerMaximumAmplification">XML_SetAllocTrackerMaximumAmplification</h4> +<pre class="fcndec"> +/* Added in Expat 2.7.2. */ +XML_Bool +XML_SetAllocTrackerMaximumAmplification(XML_Parser p, + float maximumAmplificationFactor); +</pre> +<div class="fcndef"> + <p> + Sets the maximum tolerated amplification factor + between direct input and bytes of dynamic memory allocated + (default: <code>100.0</code>) + of parser <code>p</code> to <code>maximumAmplificationFactor</code>, and + returns <code>XML_TRUE</code> upon success and <code>XML_FALSE</code> upon error. + </p> + + <p> + <strong>Note:</strong> + There are three types of allocations that intentionally bypass tracking and limiting: + </p> + <ul> + <li> + application calls to functions + <code><a href="#XML_MemMalloc">XML_MemMalloc</a></code> + and + <code><a href="#XML_MemRealloc">XML_MemRealloc</a></code> + — + <em>healthy</em> use of these two functions continues to be a responsibility + of the application using Expat + —, + </li> + <li> + the main character buffer used by functions + <code><a href="#XML_GetBuffer">XML_GetBuffer</a></code> + and + <code><a href="#XML_ParseBuffer">XML_ParseBuffer</a></code> + (and thus also by plain + <code><a href="#XML_Parse">XML_Parse</a></code>), and + </li> + <li> + the <a href="#XML_SetElementDeclHandler">content model memory</a> + (that is passed to the + <a href="#XML_SetElementDeclHandler">element declaration handler</a> + and freed by a call to + <code><a href="#XML_FreeContentModel">XML_FreeContentModel</a></code>). + </li> + </ul> + + <p>The amplification factor is calculated as ..</p> + <pre>amplification := allocated / direct</pre> + <p> + .. while parsing, whereas + <code>direct</code> is the number of bytes read from the primary document in parsing and + <code>allocated</code> is the number of bytes of dynamic memory allocated in the parser hierarchy. + </p> + + <p>For a call to <code>XML_SetAllocTrackerMaximumAmplification</code> to succeed:</p> + <ul> + <li>parser <code>p</code> must be a non-<code>NULL</code> root parser (without any parent parsers) and</li> + <li><code>maximumAmplificationFactor</code> must be non-<code>NaN</code> and greater than or equal to <code>1.0</code>.</li> + </ul> + + <p> + <strong>Note:</strong> + If you ever need to increase this value for non-attack payload, + please <a href="https://github.com/libexpat/libexpat/issues">file a bug report</a>. + </p> + + <p> + <strong>Note:</strong> + Amplifications factors greater than 100 can been observed near the start of parsing + even with benign files in practice. + + So if you do reduce the maximum allowed amplification, + please make sure that the activation threshold is still big enough + to not end up with undesired false positives (i.e. benign files being rejected). + </p> +</div> + +<h4 id="XML_SetAllocTrackerActivationThreshold">XML_SetAllocTrackerActivationThreshold</h4> +<pre class="fcndec"> +/* Added in Expat 2.7.2. */ +XML_Bool +XML_SetAllocTrackerActivationThreshold(XML_Parser p, + unsigned long long activationThresholdBytes); +</pre> +<div class="fcndef"> + <p> + Sets number of allocated bytes of dynamic memory + needed to activate protection against disproportionate use of RAM + (default: <code>64 MiB</code>) + of parser <code>p</code> to <code>activationThresholdBytes</code>, and + returns <code>XML_TRUE</code> upon success and <code>XML_FALSE</code> upon error. + </p> + + <p> + <strong>Note:</strong> + For types of allocations that intentionally bypass tracking and limiting, please see + <code><a href="#XML_SetAllocTrackerMaximumAmplification">XML_SetAllocTrackerMaximumAmplification</a></code> + above. + </p> + + <p>For a call to <code>XML_SetAllocTrackerActivationThreshold</code> to succeed:</p> + <ul> + <li>parser <code>p</code> must be a non-<code>NULL</code> root parser (without any parent parsers).</li> + </ul> + + <p> + <strong>Note:</strong> + If you ever need to increase this value for non-attack payload, + please <a href="https://github.com/libexpat/libexpat/issues">file a bug report</a>. + </p> +</div> + <h4 id="XML_SetReparseDeferralEnabled">XML_SetReparseDeferralEnabled</h4> <pre class="fcndec"> /* Added in Expat 2.6.0. */ diff --git a/contrib/expat/doc/xmlwf.1 b/contrib/expat/doc/xmlwf.1 index 76aa7e30d074..5f50ba9e4d00 100644 --- a/contrib/expat/doc/xmlwf.1 +++ b/contrib/expat/doc/xmlwf.1 @@ -5,7 +5,7 @@ \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac -.TH XMLWF 1 "March 27, 2025" "" "" +.TH XMLWF 1 "September 16, 2025" "" "" .SH NAME xmlwf \- Determines if an XML document is well-formed .SH SYNOPSIS @@ -88,7 +88,11 @@ supports both. .TP \*(T<\fB\-a\fR\*(T> \fIfactor\fR Sets the maximum tolerated amplification factor -for protection against billion laughs attacks (default: 100.0). +for protection against amplification attacks +like the billion laughs attack +(default: 100.0 +for the sum of direct and indirect output and also +for allocations of dynamic memory). The amplification factor is calculated as .. .nf @@ -97,12 +101,22 @@ The amplification factor is calculated as .. .fi -\&.. while parsing, whereas +\&.. with regard to use of entities and .. + +.nf + + amplification := allocated / direct + +.fi + +\&.. with regard to dynamic memory while parsing. <direct> is the number of bytes read -from the primary document in parsing and +from the primary document in parsing, <indirect> is the number of bytes added by expanding entities and reading of external DTD files, -combined. +combined, and +<allocated> is the total number of bytes of dynamic memory +allocated (and not freed) per hierarchy of parsers. \fINOTE\fR: If you ever need to increase this value for non-attack payload, @@ -110,8 +124,10 @@ please file a bug report. .TP \*(T<\fB\-b\fR\*(T> \fIbytes\fR Sets the number of output bytes (including amplification) -needed to activate protection against billion laughs attacks -(default: 8 MiB). +needed to activate protection against amplification attacks +like billion laughs +(default: 8 MiB for the sum of direct and indirect output, +and 64 MiB for allocations of dynamic memory). This can be thought of as an "activation threshold". \fINOTE\fR: diff --git a/contrib/expat/doc/xmlwf.xml b/contrib/expat/doc/xmlwf.xml index 17e9cf51c191..defe9df8e46a 100644 --- a/contrib/expat/doc/xmlwf.xml +++ b/contrib/expat/doc/xmlwf.xml @@ -21,7 +21,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ <!ENTITY dhfirstname "<firstname>Scott</firstname>"> <!ENTITY dhsurname "<surname>Bronson</surname>"> - <!ENTITY dhdate "<date>March 27, 2025</date>"> + <!ENTITY dhdate "<date>September 16, 2025</date>"> <!-- Please adjust this^^ date whenever cutting a new release. --> <!ENTITY dhsection "<manvolnum>1</manvolnum>"> <!ENTITY dhemail "<email>bronson@rinspin.com</email>"> @@ -158,19 +158,31 @@ supports both. <listitem> <para> Sets the maximum tolerated amplification factor - for protection against billion laughs attacks (default: 100.0). + for protection against amplification attacks + like the billion laughs attack + (default: 100.0 + for the sum of direct and indirect output and also + for allocations of dynamic memory). The amplification factor is calculated as .. </para> <literallayout> amplification := (direct + indirect) / direct </literallayout> <para> - .. while parsing, whereas + .. with regard to use of entities and .. + </para> + <literallayout> + amplification := allocated / direct + </literallayout> + <para> + .. with regard to dynamic memory while parsing. <direct> is the number of bytes read - from the primary document in parsing and + from the primary document in parsing, <indirect> is the number of bytes added by expanding entities and reading of external DTD files, - combined. + combined, and + <allocated> is the total number of bytes of dynamic memory + allocated (and not freed) per hierarchy of parsers. </para> <para> <emphasis>NOTE</emphasis>: @@ -185,8 +197,10 @@ supports both. <listitem> <para> Sets the number of output bytes (including amplification) - needed to activate protection against billion laughs attacks - (default: 8 MiB). + needed to activate protection against amplification attacks + like billion laughs + (default: 8 MiB for the sum of direct and indirect output, + and 64 MiB for allocations of dynamic memory). This can be thought of as an "activation threshold". </para> <para> diff --git a/contrib/expat/examples/Makefile.in b/contrib/expat/examples/Makefile.in index 044c9089c565..0e55052ce6e4 100644 --- a/contrib/expat/examples/Makefile.in +++ b/contrib/expat/examples/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -101,6 +101,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -330,8 +332,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -414,13 +418,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list + $(am__rm_f) $(noinst_PROGRAMS) + test -z "$(EXEEXT)" || $(am__rm_f) $(noinst_PROGRAMS:$(EXEEXT)=) element_declarations$(EXEEXT): $(element_declarations_OBJECTS) $(element_declarations_DEPENDENCIES) $(EXTRA_element_declarations_DEPENDENCIES) @rm -f element_declarations$(EXEEXT) @@ -446,7 +445,7 @@ distclean-compile: $(am__depfiles_remade): @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + @: >>$@ am--depfiles: $(am__depfiles_remade) @@ -528,6 +527,7 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -589,8 +589,8 @@ mostlyclean-generic: clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -601,7 +601,7 @@ clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/element_declarations.Po + -rm -f ./$(DEPDIR)/element_declarations.Po -rm -f ./$(DEPDIR)/elements.Po -rm -f ./$(DEPDIR)/outline.Po -rm -f Makefile @@ -649,7 +649,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/element_declarations.Po + -rm -f ./$(DEPDIR)/element_declarations.Po -rm -f ./$(DEPDIR)/elements.Po -rm -f ./$(DEPDIR)/outline.Po -rm -f Makefile @@ -692,3 +692,10 @@ uninstall-am: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/expat_config.h.in b/contrib/expat/expat_config.h.in index 67ef89c7171a..543db8252448 100644 --- a/contrib/expat/expat_config.h.in +++ b/contrib/expat/expat_config.h.in @@ -24,7 +24,7 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H -/* Define to 1 if you have the `getpagesize' function. */ +/* Define to 1 if you have the 'getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getrandom' function. */ @@ -33,10 +33,10 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `bsd' library (-lbsd). */ +/* Define to 1 if you have the 'bsd' library (-lbsd). */ #undef HAVE_LIBBSD -/* Define to 1 if you have a working `mmap' system call. */ +/* Define to 1 if you have a working 'mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the <stdint.h> header file. */ @@ -93,7 +93,7 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS @@ -133,10 +133,10 @@ /* Define to make XML Namespaces functionality available. */ #undef XML_NS -/* Define to empty if `const' does not conform to ANSI C. */ +/* Define to empty if 'const' does not conform to ANSI C. */ #undef const -/* Define to `long int' if <sys/types.h> does not define. */ +/* Define to 'long int' if <sys/types.h> does not define. */ #undef off_t #endif // ndef EXPAT_CONFIG_H diff --git a/contrib/expat/fuzz/xml_lpm_fuzzer.cpp b/contrib/expat/fuzz/xml_lpm_fuzzer.cpp index f52ea7b21e40..719629a6b547 100644 --- a/contrib/expat/fuzz/xml_lpm_fuzzer.cpp +++ b/contrib/expat/fuzz/xml_lpm_fuzzer.cpp @@ -354,8 +354,10 @@ ExternalEntityRefHandler(XML_Parser parser, const XML_Char *context, if (g_external_entity) { XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, context, g_encoding); - rc = Parse(ext_parser, g_external_entity, g_external_entity_size, 1); - XML_ParserFree(ext_parser); + if (ext_parser != NULL) { + rc = Parse(ext_parser, g_external_entity, g_external_entity_size, 1); + XML_ParserFree(ext_parser); + } } return rc; diff --git a/contrib/expat/fuzz/xml_parse_fuzzer.c b/contrib/expat/fuzz/xml_parse_fuzzer.c index 6a1affe2b1f6..29ab33ff79d9 100644 --- a/contrib/expat/fuzz/xml_parse_fuzzer.c +++ b/contrib/expat/fuzz/xml_parse_fuzzer.c @@ -15,6 +15,7 @@ */ #include <assert.h> +#include <limits.h> // for INT_MAX #include <stdint.h> #include "expat.h" @@ -65,8 +66,9 @@ ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) { XML_SetUserData(p, p); XML_SetElementHandler(p, start, end); XML_SetCharacterDataHandler(p, may_stop_character_handler); - XML_Parse(p, (const XML_Char *)data, size, 0); - if (XML_Parse(p, (const XML_Char *)data, size, 1) == XML_STATUS_ERROR) { + assert(size <= INT_MAX); + XML_Parse(p, (const XML_Char *)data, (int)size, 0); + if (XML_Parse(p, (const XML_Char *)data, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } XML_GetCurrentLineNumber(p); @@ -89,15 +91,17 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { XML_Parser externalEntityParser = XML_ExternalEntityParserCreate(parentParser, "e1", NULL); - assert(externalEntityParser); - ParseOneInput(externalEntityParser, data, size); - XML_ParserFree(externalEntityParser); + if (externalEntityParser != NULL) { + ParseOneInput(externalEntityParser, data, size); + XML_ParserFree(externalEntityParser); + } XML_Parser externalDtdParser = XML_ExternalEntityParserCreate(parentParser, NULL, NULL); - assert(externalDtdParser); - ParseOneInput(externalDtdParser, data, size); - XML_ParserFree(externalDtdParser); + if (externalDtdParser != NULL) { + ParseOneInput(externalDtdParser, data, size); + XML_ParserFree(externalDtdParser); + } // finally frees this parser which served as parent XML_ParserFree(parentParser); diff --git a/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c b/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c index cfc4af202851..38b9981b0b50 100644 --- a/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c +++ b/contrib/expat/fuzz/xml_parsebuffer_fuzzer.c @@ -15,6 +15,7 @@ */ #include <assert.h> +#include <limits.h> // for INT_MAX #include <stdint.h> #include <string.h> @@ -66,16 +67,17 @@ ParseOneInput(XML_Parser p, const uint8_t *data, size_t size) { XML_SetUserData(p, p); XML_SetElementHandler(p, start, end); XML_SetCharacterDataHandler(p, may_stop_character_handler); - void *buf = XML_GetBuffer(p, size); + assert(size <= INT_MAX); + void *buf = XML_GetBuffer(p, (int)size); assert(buf); memcpy(buf, data, size); - XML_ParseBuffer(p, size, 0); - buf = XML_GetBuffer(p, size); + XML_ParseBuffer(p, (int)size, 0); + buf = XML_GetBuffer(p, (int)size); if (buf == NULL) { return; } memcpy(buf, data, size); - if (XML_ParseBuffer(p, size, 1) == XML_STATUS_ERROR) { + if (XML_ParseBuffer(p, (int)size, 1) == XML_STATUS_ERROR) { XML_ErrorString(XML_GetErrorCode(p)); } XML_GetCurrentLineNumber(p); @@ -101,15 +103,17 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { XML_Parser externalEntityParser = XML_ExternalEntityParserCreate(parentParser, "e1", NULL); - assert(externalEntityParser); - ParseOneInput(externalEntityParser, data, size); - XML_ParserFree(externalEntityParser); + if (externalEntityParser != NULL) { + ParseOneInput(externalEntityParser, data, size); + XML_ParserFree(externalEntityParser); + } XML_Parser externalDtdParser = XML_ExternalEntityParserCreate(parentParser, NULL, NULL); - assert(externalDtdParser); - ParseOneInput(externalDtdParser, data, size); - XML_ParserFree(externalDtdParser); + if (externalDtdParser != NULL) { + ParseOneInput(externalDtdParser, data, size); + XML_ParserFree(externalDtdParser); + } // finally frees this parser which served as parent XML_ParserFree(parentParser); diff --git a/contrib/expat/lib/Makefile.in b/contrib/expat/lib/Makefile.in index 1a97e85fc41f..d85f80dbdbba 100644 --- a/contrib/expat/lib/Makefile.in +++ b/contrib/expat/lib/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -104,6 +104,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -168,10 +170,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ + { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ "$(DESTDIR)$(includedir)" @@ -368,8 +369,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -513,26 +516,22 @@ uninstall-libLTLIBRARIES: done clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + -$(am__rm_f) $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } + echo rm -f $${locs}; \ + $(am__rm_f) $${locs} clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + -$(am__rm_f) $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } + echo rm -f $${locs}; \ + $(am__rm_f) $${locs} libexpat.la: $(libexpat_la_OBJECTS) $(libexpat_la_DEPENDENCIES) $(EXTRA_libexpat_la_DEPENDENCIES) $(AM_V_CCLD)$(libexpat_la_LINK) -rpath $(libdir) $(libexpat_la_OBJECTS) $(libexpat_la_LIBADD) $(LIBS) @@ -555,7 +554,7 @@ distclean-compile: $(am__depfiles_remade): @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + @: >>$@ am--depfiles: $(am__depfiles_remade) @@ -700,6 +699,7 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -764,8 +764,8 @@ mostlyclean-generic: clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -776,7 +776,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo + -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo -rm -f ./$(DEPDIR)/xmlparse.Plo @@ -828,7 +828,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo + -rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo -rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo -rm -f ./$(DEPDIR)/xmlparse.Plo @@ -885,3 +885,10 @@ uninstall-local: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/lib/expat.h b/contrib/expat/lib/expat.h index 610e1ddc0e94..bb9cdedbac7d 100644 --- a/contrib/expat/lib/expat.h +++ b/contrib/expat/lib/expat.h @@ -42,21 +42,21 @@ */ #ifndef Expat_INCLUDED -#define Expat_INCLUDED 1 +# define Expat_INCLUDED 1 -#include <stdlib.h> -#include "expat_external.h" +# include <stdlib.h> +# include "expat_external.h" -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif struct XML_ParserStruct; typedef struct XML_ParserStruct *XML_Parser; typedef unsigned char XML_Bool; -#define XML_TRUE ((XML_Bool)1) -#define XML_FALSE ((XML_Bool)0) +# define XML_TRUE ((XML_Bool)1) +# define XML_FALSE ((XML_Bool)0) /* The XML_Status enum gives the possible return values for several API functions. The preprocessor #defines are included so this @@ -73,11 +73,11 @@ typedef unsigned char XML_Bool; */ enum XML_Status { XML_STATUS_ERROR = 0, -#define XML_STATUS_ERROR XML_STATUS_ERROR +# define XML_STATUS_ERROR XML_STATUS_ERROR XML_STATUS_OK = 1, -#define XML_STATUS_OK XML_STATUS_OK +# define XML_STATUS_OK XML_STATUS_OK XML_STATUS_SUSPENDED = 2 -#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED +# define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED }; enum XML_Error { @@ -680,7 +680,7 @@ XMLPARSEAPI(void) XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or NULL. */ -#define XML_GetUserData(parser) (*(void **)(parser)) +# define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. On success XML_SetEncoding returns non-zero, @@ -752,7 +752,7 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser); XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); -#ifdef XML_ATTR_INFO +# ifdef XML_ATTR_INFO /* Source file byte offsets for the start and end of attribute names and values. The value indices are exclusive of surrounding quotes; thus in a UTF-8 source file an attribute value of "blah" will yield: @@ -773,7 +773,7 @@ typedef struct { */ XMLPARSEAPI(const XML_AttrInfo *) XML_GetAttributeInfo(XML_Parser parser); -#endif +# endif /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is detected. The last call to XML_Parse must have isFinal true; len @@ -970,9 +970,9 @@ XMLPARSEAPI(const char *) XML_GetInputContext(XML_Parser parser, int *offset, int *size); /* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex +# define XML_GetErrorLineNumber XML_GetCurrentLineNumber +# define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +# define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees the content model passed to the element declaration handler */ XMLPARSEAPI(void) @@ -1032,7 +1032,10 @@ enum XML_FeatureEnum { XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, /* Added in Expat 2.6.0. */ - XML_FEATURE_GE + XML_FEATURE_GE, + /* Added in Expat 2.7.2. */ + XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT, /* Additional features must be added to the end of this enum. */ }; @@ -1045,7 +1048,7 @@ typedef struct { XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); -#if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) +# if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ XMLPARSEAPI(XML_Bool) @@ -1057,7 +1060,17 @@ XML_SetBillionLaughsAttackProtectionMaximumAmplification( XMLPARSEAPI(XML_Bool) XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes); -#endif + +/* Added in Expat 2.7.2. */ +XMLPARSEAPI(XML_Bool) +XML_SetAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor); + +/* Added in Expat 2.7.2. */ +XMLPARSEAPI(XML_Bool) +XML_SetAllocTrackerActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes); +# endif /* Added in Expat 2.6.0. */ XMLPARSEAPI(XML_Bool) @@ -1066,12 +1079,12 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); /* Expat follows the semantic versioning convention. See https://semver.org */ -#define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 7 -#define XML_MICRO_VERSION 1 +# define XML_MAJOR_VERSION 2 +# define XML_MINOR_VERSION 7 +# define XML_MICRO_VERSION 2 -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not Expat_INCLUDED */ diff --git a/contrib/expat/lib/expat_external.h b/contrib/expat/lib/expat_external.h index 8829f7709104..96f955eefb6b 100644 --- a/contrib/expat/lib/expat_external.h +++ b/contrib/expat/lib/expat_external.h @@ -38,7 +38,7 @@ */ #ifndef Expat_External_INCLUDED -#define Expat_External_INCLUDED 1 +# define Expat_External_INCLUDED 1 /* External API definitions */ @@ -64,12 +64,12 @@ compiled with the cdecl calling convention as the default since system headers may assume the cdecl convention. */ -#ifndef XMLCALL -# if defined(_MSC_VER) -# define XMLCALL __cdecl -# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER) -# define XMLCALL __attribute__((cdecl)) -# else +# ifndef XMLCALL +# if defined(_MSC_VER) +# define XMLCALL __cdecl +# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER) +# define XMLCALL __attribute__((cdecl)) +# else /* For any platform which uses this definition and supports more than one calling convention, we need to extend this definition to declare the convention used on that platform, if it's possible to @@ -80,86 +80,87 @@ pre-processor and how to specify the same calling convention as the platform's malloc() implementation. */ -# define XMLCALL -# endif -#endif /* not defined XMLCALL */ +# define XMLCALL +# endif +# endif /* not defined XMLCALL */ -#if ! defined(XML_STATIC) && ! defined(XMLIMPORT) -# ifndef XML_BUILDING_EXPAT +# if ! defined(XML_STATIC) && ! defined(XMLIMPORT) +# ifndef XML_BUILDING_EXPAT /* using Expat from an application */ -# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) && ! defined(__CYGWIN__) -# define XMLIMPORT __declspec(dllimport) +# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) \ + && ! defined(__CYGWIN__) +# define XMLIMPORT __declspec(dllimport) +# endif + # endif +# endif /* not defined XML_STATIC */ +# ifndef XML_ENABLE_VISIBILITY +# define XML_ENABLE_VISIBILITY 0 # endif -#endif /* not defined XML_STATIC */ - -#ifndef XML_ENABLE_VISIBILITY -# define XML_ENABLE_VISIBILITY 0 -#endif -#if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY -# define XMLIMPORT __attribute__((visibility("default"))) -#endif +# if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY +# define XMLIMPORT __attribute__((visibility("default"))) +# endif /* If we didn't define it above, define it away: */ -#ifndef XMLIMPORT -# define XMLIMPORT -#endif - -#if defined(__GNUC__) \ - && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) -# define XML_ATTR_MALLOC __attribute__((__malloc__)) -#else -# define XML_ATTR_MALLOC -#endif - -#if defined(__GNUC__) \ - && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) -# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) -#else -# define XML_ATTR_ALLOC_SIZE(x) -#endif - -#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL - -#ifdef __cplusplus -extern "C" { -#endif +# ifndef XMLIMPORT +# define XMLIMPORT +# endif + +# if defined(__GNUC__) \ + && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) +# define XML_ATTR_MALLOC __attribute__((__malloc__)) +# else +# define XML_ATTR_MALLOC +# endif -#ifdef XML_UNICODE_WCHAR_T -# ifndef XML_UNICODE -# define XML_UNICODE +# if defined(__GNUC__) \ + && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) +# else +# define XML_ATTR_ALLOC_SIZE(x) # endif -# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) -# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" + +# define XMLPARSEAPI(type) XMLIMPORT type XMLCALL + +# ifdef __cplusplus +extern "C" { # endif -#endif -#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ # ifdef XML_UNICODE_WCHAR_T +# ifndef XML_UNICODE +# define XML_UNICODE +# endif +# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) +# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" +# endif +# endif + +# ifdef XML_UNICODE /* Information is UTF-16 encoded. */ +# ifdef XML_UNICODE_WCHAR_T typedef wchar_t XML_Char; typedef wchar_t XML_LChar; -# else +# else typedef unsigned short XML_Char; typedef char XML_LChar; -# endif /* XML_UNICODE_WCHAR_T */ -#else /* Information is UTF-8 encoded. */ +# endif /* XML_UNICODE_WCHAR_T */ +# else /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; -#endif /* XML_UNICODE */ +# endif /* XML_UNICODE */ -#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ +# ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ typedef long long XML_Index; typedef unsigned long long XML_Size; -#else +# else typedef long XML_Index; typedef unsigned long XML_Size; -#endif /* XML_LARGE_SIZE */ +# endif /* XML_LARGE_SIZE */ -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not Expat_External_INCLUDED */ diff --git a/contrib/expat/lib/internal.h b/contrib/expat/lib/internal.h index 6bde6ae6b31d..6e087858ebbe 100644 --- a/contrib/expat/lib/internal.h +++ b/contrib/expat/lib/internal.h @@ -148,6 +148,11 @@ 100.0f #define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \ 8388608 // 8 MiB, 2^23 + +#define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f +#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \ + 67108864 // 64 MiB, 2^26 + /* NOTE END */ #include "expat.h" // so we can use type XML_Parser below @@ -171,6 +176,9 @@ extern #endif XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c #if defined(XML_TESTING) +void *expat_malloc(XML_Parser parser, size_t size, int sourceLine); +void expat_free(XML_Parser parser, void *ptr, int sourceLine); +void *expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine); extern unsigned int g_bytesScanned; // used for testing only #endif diff --git a/contrib/expat/lib/xmlparse.c b/contrib/expat/lib/xmlparse.c index 38a2d9657b6a..de1594934900 100644 --- a/contrib/expat/lib/xmlparse.c +++ b/contrib/expat/lib/xmlparse.c @@ -1,4 +1,4 @@ -/* d19ae032c224863c1527ba44d228cc34b99192c3a4c5a27af1f4e054d45ee031 (2.7.1+) +/* 60e137abb91af642d6c3988f8f133d23329b32638659c74d47125fc0faf6ddd5 (2.7.2+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -97,7 +97,7 @@ #include <stddef.h> #include <string.h> /* memset(), memcpy() */ #include <assert.h> -#include <limits.h> /* UINT_MAX */ +#include <limits.h> /* INT_MAX, UINT_MAX */ #include <stdio.h> /* fprintf */ #include <stdlib.h> /* getenv, rand_s */ #include <stdint.h> /* uintptr_t */ @@ -234,7 +234,7 @@ typedef struct { unsigned char power; size_t size; size_t used; - const XML_Memory_Handling_Suite *mem; + XML_Parser parser; } HASH_TABLE; static size_t keylen(KEY s); @@ -357,7 +357,7 @@ typedef struct { const XML_Char *end; XML_Char *ptr; XML_Char *start; - const XML_Memory_Handling_Suite *mem; + XML_Parser parser; } STRING_POOL; /* The XML_Char before the name is used to determine whether @@ -452,6 +452,14 @@ typedef struct accounting { unsigned long long activationThresholdBytes; } ACCOUNTING; +typedef struct MALLOC_TRACKER { + XmlBigCount bytesAllocated; + XmlBigCount peakBytesAllocated; // updated live only for debug level >=2 + unsigned long debugLevel; + float maximumAmplificationFactor; // >=1.0 + XmlBigCount activationThresholdBytes; +} MALLOC_TRACKER; + typedef struct entity_stats { unsigned int countEverOpened; unsigned int currentDepth; @@ -555,27 +563,24 @@ static XML_Bool setContext(XML_Parser parser, const XML_Char *context); static void FASTCALL normalizePublicId(XML_Char *s); -static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms); +static DTD *dtdCreate(XML_Parser parser); /* do not call if m_parentParser != NULL */ -static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); -static void dtdDestroy(DTD *p, XML_Bool isDocEntity, - const XML_Memory_Handling_Suite *ms); +static void dtdReset(DTD *p, XML_Parser parser); +static void dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser); static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, - const XML_Memory_Handling_Suite *ms); + XML_Parser parser); static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable); static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); -static void FASTCALL hashTableInit(HASH_TABLE *table, - const XML_Memory_Handling_Suite *ms); +static void FASTCALL hashTableInit(HASH_TABLE *table, XML_Parser parser); static void FASTCALL hashTableClear(HASH_TABLE *table); static void FASTCALL hashTableDestroy(HASH_TABLE *table); static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table); static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter); -static void FASTCALL poolInit(STRING_POOL *pool, - const XML_Memory_Handling_Suite *ms); +static void FASTCALL poolInit(STRING_POOL *pool, XML_Parser parser); static void FASTCALL poolClear(STRING_POOL *pool); static void FASTCALL poolDestroy(STRING_POOL *pool); static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, @@ -595,15 +600,15 @@ static XML_Content *build_model(XML_Parser parser); static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end); -static XML_Char *copyString(const XML_Char *s, - const XML_Memory_Handling_Suite *memsuite); +static XML_Char *copyString(const XML_Char *s, XML_Parser parser); static unsigned long generate_hash_secret_salt(XML_Parser parser); static XML_Bool startParsing(XML_Parser parser); static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, - const XML_Char *nameSep, DTD *dtd); + const XML_Char *nameSep, DTD *dtd, + XML_Parser parentParser); static void parserInit(XML_Parser parser, const XML_Char *encodingName); @@ -627,10 +632,10 @@ static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity, int sourceLine); static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity, int sourceLine); +#endif /* XML_GE == 1 */ static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff); -#endif /* XML_GE == 1 */ static unsigned long getDebugLevel(const char *variableName, unsigned long defaultDebugLevel); @@ -773,14 +778,232 @@ struct XML_ParserStruct { unsigned long m_hash_secret_salt; #if XML_GE == 1 ACCOUNTING m_accounting; + MALLOC_TRACKER m_alloc_tracker; ENTITY_STATS m_entity_stats; #endif XML_Bool m_reenter; }; -#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) -#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s))) -#define FREE(parser, p) (parser->m_mem.free_fcn((p))) +#if XML_GE == 1 +# define MALLOC(parser, s) (expat_malloc((parser), (s), __LINE__)) +# define REALLOC(parser, p, s) (expat_realloc((parser), (p), (s), __LINE__)) +# define FREE(parser, p) (expat_free((parser), (p), __LINE__)) +#else +# define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) +# define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s))) +# define FREE(parser, p) (parser->m_mem.free_fcn((p))) +#endif + +#if XML_GE == 1 +static void +expat_heap_stat(XML_Parser rootParser, char operator, XmlBigCount absDiff, + XmlBigCount newTotal, XmlBigCount peakTotal, int sourceLine) { + // NOTE: This can be +infinity or -nan + const float amplification + = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect; + fprintf( + stderr, + "expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_ULL( + "10") " to " EXPAT_FMT_ULL("10") " (" EXPAT_FMT_ULL("10") " peak), amplification %8.2f (xmlparse.c:%d)\n", + (void *)rootParser, rootParser->m_accounting.countBytesDirect, operator, + absDiff, newTotal, peakTotal, (double)amplification, sourceLine); +} + +static bool +expat_heap_increase_tolerable(XML_Parser rootParser, XmlBigCount increase, + int sourceLine) { + assert(rootParser != NULL); + assert(increase > 0); + + XmlBigCount newTotal = 0; + bool tolerable = true; + + // Detect integer overflow + if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated < increase) { + tolerable = false; + } else { + newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase; + + if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) { + assert(newTotal > 0); + // NOTE: This can be +infinity when dividing by zero but not -nan + const float amplification + = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect; + if (amplification + > rootParser->m_alloc_tracker.maximumAmplificationFactor) { + tolerable = false; + } + } + } + + if (! tolerable && (rootParser->m_alloc_tracker.debugLevel >= 1)) { + expat_heap_stat(rootParser, '+', increase, newTotal, newTotal, sourceLine); + } + + return tolerable; +} + +# if defined(XML_TESTING) +void * +# else +static void * +# endif +expat_malloc(XML_Parser parser, size_t size, int sourceLine) { + // Detect integer overflow + if (SIZE_MAX - size < sizeof(size_t)) { + return NULL; + } + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + + const size_t bytesToAllocate = sizeof(size_t) + size; + + if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated + < bytesToAllocate) { + return NULL; // i.e. signal integer overflow as out-of-memory + } + + if (! expat_heap_increase_tolerable(rootParser, bytesToAllocate, + sourceLine)) { + return NULL; // i.e. signal violation as out-of-memory + } + + // Actually allocate + void *const mallocedPtr = parser->m_mem.malloc_fcn(bytesToAllocate); + + if (mallocedPtr == NULL) { + return NULL; + } + + // Update in-block recorded size + *(size_t *)mallocedPtr = size; + + // Update accounting + rootParser->m_alloc_tracker.bytesAllocated += bytesToAllocate; + + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + expat_heap_stat(rootParser, '+', bytesToAllocate, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } + + return (char *)mallocedPtr + sizeof(size_t); +} + +# if defined(XML_TESTING) +void +# else +static void +# endif +expat_free(XML_Parser parser, void *ptr, int sourceLine) { + assert(parser != NULL); + + if (ptr == NULL) { + return; + } + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + + // Extract size (to the eyes of malloc_fcn/realloc_fcn) and + // the original pointer returned by malloc/realloc + void *const mallocedPtr = (char *)ptr - sizeof(size_t); + const size_t bytesAllocated = sizeof(size_t) + *(size_t *)mallocedPtr; + + // Update accounting + assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated); + rootParser->m_alloc_tracker.bytesAllocated -= bytesAllocated; + + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + expat_heap_stat(rootParser, '-', bytesAllocated, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } + + // NOTE: This may be freeing rootParser, so freeing has to come last + parser->m_mem.free_fcn(mallocedPtr); +} + +# if defined(XML_TESTING) +void * +# else +static void * +# endif +expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) { + assert(parser != NULL); + + if (ptr == NULL) { + return expat_malloc(parser, size, sourceLine); + } + + if (size == 0) { + expat_free(parser, ptr, sourceLine); + return NULL; + } + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + + // Extract original size (to the eyes of the caller) and the original + // pointer returned by malloc/realloc + void *mallocedPtr = (char *)ptr - sizeof(size_t); + const size_t prevSize = *(size_t *)mallocedPtr; + + // Classify upcoming change + const bool isIncrease = (size > prevSize); + const size_t absDiff + = (size > prevSize) ? (size - prevSize) : (prevSize - size); + + // Ask for permission from accounting + if (isIncrease) { + if (! expat_heap_increase_tolerable(rootParser, absDiff, sourceLine)) { + return NULL; // i.e. signal violation as out-of-memory + } + } + + // Actually allocate + mallocedPtr = parser->m_mem.realloc_fcn(mallocedPtr, sizeof(size_t) + size); + + if (mallocedPtr == NULL) { + return NULL; + } + + // Update accounting + if (isIncrease) { + assert((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated + >= absDiff); + rootParser->m_alloc_tracker.bytesAllocated += absDiff; + } else { // i.e. decrease + assert(rootParser->m_alloc_tracker.bytesAllocated >= absDiff); + rootParser->m_alloc_tracker.bytesAllocated -= absDiff; + } + + // Report as needed + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + expat_heap_stat(rootParser, isIncrease ? '+' : '-', absDiff, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); + } + + // Update in-block recorded size + *(size_t *)mallocedPtr = size; + + return (char *)mallocedPtr + sizeof(size_t); +} +#endif // XML_GE == 1 XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName) { @@ -821,11 +1044,14 @@ writeRandomBytes_getrandom_nonblock(void *target, size_t count) { void *const currentTarget = (void *)((char *)target + bytesWrittenTotal); const size_t bytesToWrite = count - bytesWrittenTotal; + assert(bytesToWrite <= INT_MAX); + const int bytesWrittenMore = # if defined(HAVE_GETRANDOM) - getrandom(currentTarget, bytesToWrite, getrandomFlags); + (int)getrandom(currentTarget, bytesToWrite, getrandomFlags); # else - syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); + (int)syscall(SYS_getrandom, currentTarget, bytesToWrite, + getrandomFlags); # endif if (bytesWrittenMore > 0) { @@ -1012,9 +1238,10 @@ generate_hash_secret_salt(XML_Parser parser) { static unsigned long get_hash_secret_salt(XML_Parser parser) { - if (parser->m_parentParser != NULL) - return get_hash_secret_salt(parser->m_parentParser); - return parser->m_hash_secret_salt; + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(! rootParser->m_parentParser); + + return rootParser->m_hash_secret_salt; } static enum XML_Error @@ -1100,19 +1327,40 @@ XML_Parser XMLCALL XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep) { - return parserCreate(encodingName, memsuite, nameSep, NULL); + return parserCreate(encodingName, memsuite, nameSep, NULL, NULL); } static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, - DTD *dtd) { - XML_Parser parser; + DTD *dtd, XML_Parser parentParser) { + XML_Parser parser = NULL; + +#if XML_GE == 1 + const size_t increase = sizeof(size_t) + sizeof(struct XML_ParserStruct); + + if (parentParser != NULL) { + const XML_Parser rootParser = getRootParserOf(parentParser, NULL); + if (! expat_heap_increase_tolerable(rootParser, increase, __LINE__)) { + return NULL; + } + } +#else + UNUSED_P(parentParser); +#endif if (memsuite) { XML_Memory_Handling_Suite *mtemp; +#if XML_GE == 1 + void *const sizeAndParser = memsuite->malloc_fcn( + sizeof(size_t) + sizeof(struct XML_ParserStruct)); + if (sizeAndParser != NULL) { + *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); + parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)); +#else parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); if (parser != NULL) { +#endif mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = memsuite->malloc_fcn; mtemp->realloc_fcn = memsuite->realloc_fcn; @@ -1120,39 +1368,85 @@ parserCreate(const XML_Char *encodingName, } } else { XML_Memory_Handling_Suite *mtemp; - parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); +#if XML_GE == 1 + void *const sizeAndParser + = malloc(sizeof(size_t) + sizeof(struct XML_ParserStruct)); + if (sizeAndParser != NULL) { + *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); + parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)); +#else + parser = malloc(sizeof(struct XML_ParserStruct)); if (parser != NULL) { +#endif mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = malloc; mtemp->realloc_fcn = realloc; mtemp->free_fcn = free; } - } + } // cppcheck-suppress[memleak symbolName=sizeAndParser] // Cppcheck >=2.18.0 if (! parser) return parser; +#if XML_GE == 1 + // Initialize .m_alloc_tracker + memset(&parser->m_alloc_tracker, 0, sizeof(MALLOC_TRACKER)); + if (parentParser == NULL) { + parser->m_alloc_tracker.debugLevel + = getDebugLevel("EXPAT_MALLOC_DEBUG", 0u); + parser->m_alloc_tracker.maximumAmplificationFactor + = EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT; + parser->m_alloc_tracker.activationThresholdBytes + = EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT; + + // NOTE: This initialization needs to come this early because these fields + // are read by allocation tracking code + parser->m_parentParser = NULL; + parser->m_accounting.countBytesDirect = 0; + } else { + parser->m_parentParser = parentParser; + } + + // Record XML_ParserStruct allocation we did a few lines up before + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(rootParser->m_parentParser == NULL); + assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= increase); + rootParser->m_alloc_tracker.bytesAllocated += increase; + + // Report on allocation + if (rootParser->m_alloc_tracker.debugLevel >= 2) { + if (rootParser->m_alloc_tracker.bytesAllocated + > rootParser->m_alloc_tracker.peakBytesAllocated) { + rootParser->m_alloc_tracker.peakBytesAllocated + = rootParser->m_alloc_tracker.bytesAllocated; + } + + expat_heap_stat(rootParser, '+', increase, + rootParser->m_alloc_tracker.bytesAllocated, + rootParser->m_alloc_tracker.peakBytesAllocated, __LINE__); + } +#else + parser->m_parentParser = NULL; +#endif // XML_GE == 1 + parser->m_buffer = NULL; parser->m_bufferLim = NULL; parser->m_attsSize = INIT_ATTS_SIZE; - parser->m_atts - = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE)); + parser->m_atts = MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE)); if (parser->m_atts == NULL) { FREE(parser, parser); return NULL; } #ifdef XML_ATTR_INFO - parser->m_attInfo = (XML_AttrInfo *)MALLOC( - parser, parser->m_attsSize * sizeof(XML_AttrInfo)); + parser->m_attInfo = MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo)); if (parser->m_attInfo == NULL) { FREE(parser, parser->m_atts); FREE(parser, parser); return NULL; } #endif - parser->m_dataBuf - = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + parser->m_dataBuf = MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); if (parser->m_dataBuf == NULL) { FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO @@ -1166,7 +1460,7 @@ parserCreate(const XML_Char *encodingName, if (dtd) parser->m_dtd = dtd; else { - parser->m_dtd = dtdCreate(&parser->m_mem); + parser->m_dtd = dtdCreate(parser); if (parser->m_dtd == NULL) { FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_atts); @@ -1200,8 +1494,8 @@ parserCreate(const XML_Char *encodingName, parser->m_protocolEncodingName = NULL; - poolInit(&parser->m_tempPool, &(parser->m_mem)); - poolInit(&parser->m_temp2Pool, &(parser->m_mem)); + poolInit(&parser->m_tempPool, parser); + poolInit(&parser->m_temp2Pool, parser); parserInit(parser, encodingName); if (encodingName && ! parser->m_protocolEncodingName) { @@ -1233,7 +1527,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_processor = prologInitProcessor; XmlPrologStateInit(&parser->m_prologState); if (encodingName != NULL) { - parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); + parser->m_protocolEncodingName = copyString(encodingName, parser); } parser->m_curBase = NULL; XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0); @@ -1295,7 +1589,6 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_unknownEncodingMem = NULL; parser->m_unknownEncodingRelease = NULL; parser->m_unknownEncodingData = NULL; - parser->m_parentParser = NULL; parser->m_parsingStatus.parsing = XML_INITIALIZED; // Reentry can only be triggered inside m_processor calls parser->m_reenter = XML_FALSE; @@ -1385,7 +1678,7 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { FREE(parser, (void *)parser->m_protocolEncodingName); parser->m_protocolEncodingName = NULL; parserInit(parser, encodingName); - dtdReset(parser->m_dtd, &parser->m_mem); + dtdReset(parser->m_dtd, parser); return XML_TRUE; } @@ -1421,7 +1714,7 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { parser->m_protocolEncodingName = NULL; else { /* Copy the new encoding name into allocated memory */ - parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); + parser->m_protocolEncodingName = copyString(encodingName, parser); if (! parser->m_protocolEncodingName) return XML_STATUS_ERROR; } @@ -1530,9 +1823,10 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, */ if (parser->m_ns) { XML_Char tmp[2] = {parser->m_namespaceSeparator, 0}; - parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd, oldParser); } else { - parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); + parser + = parserCreate(encodingName, &parser->m_mem, NULL, newDtd, oldParser); } if (! parser) @@ -1576,7 +1870,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, parser->m_prologState.inEntityValue = oldInEntityValue; if (context) { #endif /* XML_DTD */ - if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem) + if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, parser) || ! setContext(parser, context)) { XML_ParserFree(parser); return NULL; @@ -1688,14 +1982,16 @@ XML_ParserFree(XML_Parser parser) { #else if (parser->m_dtd) #endif /* XML_DTD */ - dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, - &parser->m_mem); - FREE(parser, (void *)parser->m_atts); + dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, parser); + FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO - FREE(parser, (void *)parser->m_attInfo); + FREE(parser, parser->m_attInfo); #endif FREE(parser, parser->m_groupConnector); - FREE(parser, parser->m_buffer); + // NOTE: We are avoiding FREE(..) here because parser->m_buffer + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(parser->m_buffer); FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_nsAtts); FREE(parser, parser->m_unknownEncodingMem); @@ -2014,12 +2310,14 @@ int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) { if (parser == NULL) return 0; - if (parser->m_parentParser) - return XML_SetHashSalt(parser->m_parentParser, hash_salt); + + const XML_Parser rootParser = getRootParserOf(parser, NULL); + assert(! rootParser->m_parentParser); + /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parserBusy(parser)) + if (parserBusy(rootParser)) return 0; - parser->m_hash_secret_salt = hash_salt; + rootParser->m_hash_secret_salt = hash_salt; return 1; } @@ -2287,7 +2585,9 @@ XML_GetBuffer(XML_Parser parser, int len) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } - newBuf = (char *)MALLOC(parser, bufferSize); + // NOTE: We are avoiding MALLOC(..) here to leave limiting + // the input size to the application using Expat. + newBuf = parser->m_mem.malloc_fcn(bufferSize); if (newBuf == 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; @@ -2298,7 +2598,10 @@ XML_GetBuffer(XML_Parser parser, int len) { memcpy(newBuf, &parser->m_bufferPtr[-keep], EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep); - FREE(parser, parser->m_buffer); + // NOTE: We are avoiding FREE(..) here because parser->m_buffer + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(parser->m_buffer); parser->m_buffer = newBuf; parser->m_bufferEnd = parser->m_buffer @@ -2314,7 +2617,10 @@ XML_GetBuffer(XML_Parser parser, int len) { if (parser->m_bufferPtr) { memcpy(newBuf, parser->m_bufferPtr, EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)); - FREE(parser, parser->m_buffer); + // NOTE: We are avoiding FREE(..) here because parser->m_buffer + // is not being allocated with MALLOC(..) but with plain + // .malloc_fcn(..). + parser->m_mem.free_fcn(parser->m_buffer); parser->m_bufferEnd = newBuf + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr); @@ -2492,28 +2798,43 @@ XML_GetCurrentColumnNumber(XML_Parser parser) { void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - if (parser != NULL) - FREE(parser, model); + if (parser == NULL) + return; + + // NOTE: We are avoiding FREE(..) here because the content model + // has been created using plain .malloc_fcn(..) rather than MALLOC(..). + parser->m_mem.free_fcn(model); } void *XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { if (parser == NULL) return NULL; - return MALLOC(parser, size); + + // NOTE: We are avoiding MALLOC(..) here to not include + // user allocations with allocation tracking and limiting. + return parser->m_mem.malloc_fcn(size); } void *XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { if (parser == NULL) return NULL; - return REALLOC(parser, ptr, size); + + // NOTE: We are avoiding REALLOC(..) here to not include + // user allocations with allocation tracking and limiting. + return parser->m_mem.realloc_fcn(ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { - if (parser != NULL) - FREE(parser, ptr); + if (parser == NULL) + return; + + // NOTE: We are avoiding FREE(..) here because XML_MemMalloc and + // XML_MemRealloc are not using MALLOC(..) and REALLOC(..) + // but plain .malloc_fcn(..) and .realloc_fcn(..), internally. + parser->m_mem.free_fcn(ptr); } void XMLCALL @@ -2713,6 +3034,13 @@ XML_GetFeatureList(void) { EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT}, /* Added in Expat 2.6.0. */ {XML_FEATURE_GE, XML_L("XML_GE"), 0}, + /* Added in Expat 2.7.2. */ + {XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_L("XML_AT_MAX_AMP"), + (long int)EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT}, + {XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT, + XML_L("XML_AT_ACT_THRES"), + (long int)EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT}, #endif {XML_FEATURE_END, NULL, 0}}; @@ -2741,6 +3069,29 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold( parser->m_accounting.activationThresholdBytes = activationThresholdBytes; return XML_TRUE; } + +XML_Bool XMLCALL +XML_SetAllocTrackerMaximumAmplification(XML_Parser parser, + float maximumAmplificationFactor) { + if ((parser == NULL) || (parser->m_parentParser != NULL) + || isnan(maximumAmplificationFactor) + || (maximumAmplificationFactor < 1.0f)) { + return XML_FALSE; + } + parser->m_alloc_tracker.maximumAmplificationFactor + = maximumAmplificationFactor; + return XML_TRUE; +} + +XML_Bool XMLCALL +XML_SetAllocTrackerActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if ((parser == NULL) || (parser->m_parentParser != NULL)) { + return XML_FALSE; + } + parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes; + return XML_TRUE; +} #endif /* XML_GE == 1 */ XML_Bool XMLCALL @@ -2761,8 +3112,8 @@ static XML_Bool storeRawNames(XML_Parser parser) { TAG *tag = parser->m_tagStack; while (tag) { - int bufSize; - int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); + size_t bufSize; + size_t nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); size_t rawNameLen; char *rawNameBuf = tag->buf + nameLen; /* Stop if already stored. Since m_tagStack is a stack, we can stop @@ -2779,9 +3130,9 @@ storeRawNames(XML_Parser parser) { /* Detect and prevent integer overflow. */ if (rawNameLen > (size_t)INT_MAX - nameLen) return XML_FALSE; - bufSize = nameLen + (int)rawNameLen; - if (bufSize > tag->bufEnd - tag->buf) { - char *temp = (char *)REALLOC(parser, tag->buf, bufSize); + bufSize = nameLen + rawNameLen; + if (bufSize > (size_t)(tag->bufEnd - tag->buf)) { + char *temp = REALLOC(parser, tag->buf, bufSize); if (temp == NULL) return XML_FALSE; /* if tag->name.str points to tag->buf (only when namespace @@ -3107,10 +3458,10 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, tag = parser->m_freeTagList; parser->m_freeTagList = parser->m_freeTagList->parent; } else { - tag = (TAG *)MALLOC(parser, sizeof(TAG)); + tag = MALLOC(parser, sizeof(TAG)); if (! tag) return XML_ERROR_NO_MEMORY; - tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE); + tag->buf = MALLOC(parser, INIT_TAG_BUF_SIZE); if (! tag->buf) { FREE(parser, tag); return XML_ERROR_NO_MEMORY; @@ -3143,7 +3494,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, } bufSize = (int)(tag->bufEnd - tag->buf) << 1; { - char *temp = (char *)REALLOC(parser, tag->buf, bufSize); + char *temp = REALLOC(parser, tag->buf, bufSize); if (temp == NULL) return XML_ERROR_NO_MEMORY; tag->buf = temp; @@ -3522,8 +3873,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, } #endif - temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, - parser->m_attsSize * sizeof(ATTRIBUTE)); + temp = REALLOC(parser, parser->m_atts, + parser->m_attsSize * sizeof(ATTRIBUTE)); if (temp == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; @@ -3541,8 +3892,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, } # endif - temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, - parser->m_attsSize * sizeof(XML_AttrInfo)); + temp2 = REALLOC(parser, parser->m_attInfo, + parser->m_attsSize * sizeof(XML_AttrInfo)); if (temp2 == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; @@ -3677,7 +4028,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, and clear flags that say whether attributes were specified */ i = 0; if (nPrefixes) { - int j; /* hash table index */ + unsigned int j; /* hash table index */ unsigned long version = parser->m_nsAttsVersion; /* Detect and prevent invalid shift */ @@ -3718,8 +4069,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, } #endif - temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, - nsAttsSize * sizeof(NS_ATT)); + temp = REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT)); if (! temp) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; @@ -3772,7 +4122,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, if (! b) return XML_ERROR_UNBOUND_PREFIX; - for (j = 0; j < b->uriLen; j++) { + for (j = 0; j < (unsigned int)b->uriLen; j++) { const XML_Char c = b->uri[j]; if (! poolAppendChar(&parser->m_tempPool, c)) return XML_ERROR_NO_MEMORY; @@ -3866,7 +4216,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, return XML_ERROR_NONE; prefixLen = 0; if (parser->m_ns_triplets && binding->prefix->name) { - for (; binding->prefix->name[prefixLen++];) + while (binding->prefix->name[prefixLen++]) ; /* prefixLen includes null terminator */ } tagNamePtr->localPart = localPart; @@ -3900,7 +4250,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, } #endif - uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); + uri = MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); if (! uri) return XML_ERROR_NO_MEMORY; binding->uriAlloc = n + EXPAND_SPARE; @@ -4146,8 +4496,8 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, } #endif - XML_Char *temp = (XML_Char *)REALLOC( - parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + XML_Char *temp + = REALLOC(parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (temp == NULL) return XML_ERROR_NO_MEMORY; b->uri = temp; @@ -4155,7 +4505,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, } parser->m_freeBindingList = b->nextTagBinding; } else { - b = (BINDING *)MALLOC(parser, sizeof(BINDING)); + b = MALLOC(parser, sizeof(BINDING)); if (! b) return XML_ERROR_NO_MEMORY; @@ -4173,8 +4523,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, } #endif - b->uri - = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); + b->uri = MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (! b->uri) { FREE(parser, b); return XML_ERROR_NO_MEMORY; @@ -5545,7 +5894,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, return XML_ERROR_NO_MEMORY; } - char *const new_connector = (char *)REALLOC( + char *const new_connector = REALLOC( parser, parser->m_groupConnector, parser->m_groupSize *= 2); if (new_connector == NULL) { parser->m_groupSize /= 2; @@ -5565,15 +5914,14 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, } #endif - int *const new_scaff_index = (int *)REALLOC( + int *const new_scaff_index = REALLOC( parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); if (new_scaff_index == NULL) return XML_ERROR_NO_MEMORY; dtd->scaffIndex = new_scaff_index; } } else { - parser->m_groupConnector - = (char *)MALLOC(parser, parser->m_groupSize = 32); + parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32); if (! parser->m_groupConnector) { parser->m_groupSize = 0; return XML_ERROR_NO_MEMORY; @@ -5730,8 +6078,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, case XML_ROLE_CONTENT_EMPTY: if (dtd->in_eldecl) { if (parser->m_elementDeclHandler) { - XML_Content *content - = (XML_Content *)MALLOC(parser, sizeof(XML_Content)); + // NOTE: We are avoiding MALLOC(..) here to so that + // applications that are not using XML_FreeContentModel but + // plain free(..) or .free_fcn() to free the content model's + // memory are safe. + XML_Content *content = parser->m_mem.malloc_fcn(sizeof(XML_Content)); if (! content) return XML_ERROR_NO_MEMORY; content->quant = XML_CQUANT_NONE; @@ -5787,7 +6138,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, name = el->name; dtd->scaffold[myindex].name = name; nameLen = 0; - for (; name[nameLen++];) + while (name[nameLen++]) ; /* Detect and prevent integer overflow */ @@ -6008,8 +6359,7 @@ processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl, openEntity = *freeEntityList; *freeEntityList = openEntity->next; } else { - openEntity - = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); + openEntity = MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); if (! openEntity) return XML_ERROR_NO_MEMORY; } @@ -6277,7 +6627,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; - char checkEntityDecl; + bool checkEntityDecl; XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { @@ -6804,8 +7154,8 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, if (type->nDefaultAtts == type->allocDefaultAtts) { if (type->allocDefaultAtts == 0) { type->allocDefaultAtts = 8; - type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC( - parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + type->defaultAtts + = MALLOC(parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! type->defaultAtts) { type->allocDefaultAtts = 0; return 0; @@ -6830,8 +7180,8 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, } #endif - temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, - (count * sizeof(DEFAULT_ATTRIBUTE))); + temp = REALLOC(parser, type->defaultAtts, + (count * sizeof(DEFAULT_ATTRIBUTE))); if (temp == NULL) return 0; type->allocDefaultAtts = count; @@ -7122,19 +7472,19 @@ normalizePublicId(XML_Char *publicId) { } static DTD * -dtdCreate(const XML_Memory_Handling_Suite *ms) { - DTD *p = ms->malloc_fcn(sizeof(DTD)); +dtdCreate(XML_Parser parser) { + DTD *p = MALLOC(parser, sizeof(DTD)); if (p == NULL) return p; - poolInit(&(p->pool), ms); - poolInit(&(p->entityValuePool), ms); - hashTableInit(&(p->generalEntities), ms); - hashTableInit(&(p->elementTypes), ms); - hashTableInit(&(p->attributeIds), ms); - hashTableInit(&(p->prefixes), ms); + poolInit(&(p->pool), parser); + poolInit(&(p->entityValuePool), parser); + hashTableInit(&(p->generalEntities), parser); + hashTableInit(&(p->elementTypes), parser); + hashTableInit(&(p->attributeIds), parser); + hashTableInit(&(p->prefixes), parser); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; - hashTableInit(&(p->paramEntities), ms); + hashTableInit(&(p->paramEntities), parser); #endif /* XML_DTD */ p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; @@ -7154,7 +7504,7 @@ dtdCreate(const XML_Memory_Handling_Suite *ms) { } static void -dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { +dtdReset(DTD *p, XML_Parser parser) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { @@ -7162,7 +7512,7 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { if (! e) break; if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); + FREE(parser, e->defaultAtts); } hashTableClear(&(p->generalEntities)); #ifdef XML_DTD @@ -7179,9 +7529,9 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { p->in_eldecl = XML_FALSE; - ms->free_fcn(p->scaffIndex); + FREE(parser, p->scaffIndex); p->scaffIndex = NULL; - ms->free_fcn(p->scaffold); + FREE(parser, p->scaffold); p->scaffold = NULL; p->scaffLevel = 0; @@ -7195,7 +7545,7 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { } static void -dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { +dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { @@ -7203,7 +7553,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { if (! e) break; if (e->allocDefaultAtts != 0) - ms->free_fcn(e->defaultAtts); + FREE(parser, e->defaultAtts); } hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD @@ -7215,10 +7565,10 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { poolDestroy(&(p->pool)); poolDestroy(&(p->entityValuePool)); if (isDocEntity) { - ms->free_fcn(p->scaffIndex); - ms->free_fcn(p->scaffold); + FREE(parser, p->scaffIndex); + FREE(parser, p->scaffold); } - ms->free_fcn(p); + FREE(parser, p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. @@ -7226,7 +7576,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { */ static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, - const XML_Memory_Handling_Suite *ms) { + XML_Parser parser) { HASH_TABLE_ITER iter; /* Copy the prefix table. */ @@ -7307,7 +7657,7 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, } #endif newE->defaultAtts - = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + = MALLOC(parser, oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! newE->defaultAtts) { return 0; } @@ -7469,7 +7819,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { /* table->size is a power of 2 */ table->size = (size_t)1 << INIT_POWER; tsize = table->size * sizeof(NAMED *); - table->v = table->mem->malloc_fcn(tsize); + table->v = MALLOC(table->parser, tsize); if (! table->v) { table->size = 0; return NULL; @@ -7509,7 +7859,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { } size_t tsize = newSize * sizeof(NAMED *); - NAMED **newV = table->mem->malloc_fcn(tsize); + NAMED **newV = MALLOC(table->parser, tsize); if (! newV) return NULL; memset(newV, 0, tsize); @@ -7525,7 +7875,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { } newV[j] = table->v[i]; } - table->mem->free_fcn(table->v); + FREE(table->parser, table->v); table->v = newV; table->power = newPower; table->size = newSize; @@ -7538,7 +7888,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { } } } - table->v[i] = table->mem->malloc_fcn(createSize); + table->v[i] = MALLOC(table->parser, createSize); if (! table->v[i]) return NULL; memset(table->v[i], 0, createSize); @@ -7551,7 +7901,7 @@ static void FASTCALL hashTableClear(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { - table->mem->free_fcn(table->v[i]); + FREE(table->parser, table->v[i]); table->v[i] = NULL; } table->used = 0; @@ -7561,17 +7911,17 @@ static void FASTCALL hashTableDestroy(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) - table->mem->free_fcn(table->v[i]); - table->mem->free_fcn(table->v); + FREE(table->parser, table->v[i]); + FREE(table->parser, table->v); } static void FASTCALL -hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { +hashTableInit(HASH_TABLE *p, XML_Parser parser) { p->power = 0; p->size = 0; p->used = 0; p->v = NULL; - p->mem = ms; + p->parser = parser; } static void FASTCALL @@ -7591,13 +7941,13 @@ hashTableIterNext(HASH_TABLE_ITER *iter) { } static void FASTCALL -poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) { +poolInit(STRING_POOL *pool, XML_Parser parser) { pool->blocks = NULL; pool->freeBlocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; - pool->mem = ms; + pool->parser = parser; } static void FASTCALL @@ -7624,13 +7974,13 @@ poolDestroy(STRING_POOL *pool) { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; - pool->mem->free_fcn(p); + FREE(pool->parser, p); p = tem; } p = pool->freeBlocks; while (p) { BLOCK *tem = p->next; - pool->mem->free_fcn(p); + FREE(pool->parser, p); p = tem; } } @@ -7785,8 +8135,7 @@ poolGrow(STRING_POOL *pool) { if (bytesToAllocate == 0) return XML_FALSE; - temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks, - (unsigned)bytesToAllocate); + temp = REALLOC(pool->parser, pool->blocks, (unsigned)bytesToAllocate); if (temp == NULL) return XML_FALSE; pool->blocks = temp; @@ -7826,7 +8175,7 @@ poolGrow(STRING_POOL *pool) { if (bytesToAllocate == 0) return XML_FALSE; - tem = pool->mem->malloc_fcn(bytesToAllocate); + tem = MALLOC(pool->parser, bytesToAllocate); if (! tem) return XML_FALSE; tem->size = blockSize; @@ -7857,12 +8206,17 @@ nextScaffoldPart(XML_Parser parser) { return -1; } #endif - dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int)); + dtd->scaffIndex = MALLOC(parser, parser->m_groupSize * sizeof(int)); if (! dtd->scaffIndex) return -1; dtd->scaffIndex[0] = 0; } + // Will casting to int be safe further down? + if (dtd->scaffCount > INT_MAX) { + return -1; + } + if (dtd->scaffCount >= dtd->scaffSize) { CONTENT_SCAFFOLD *temp; if (dtd->scaffold) { @@ -7880,21 +8234,20 @@ nextScaffoldPart(XML_Parser parser) { } #endif - temp = (CONTENT_SCAFFOLD *)REALLOC( - parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + temp = REALLOC(parser, dtd->scaffold, + dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize *= 2; } else { - temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS - * sizeof(CONTENT_SCAFFOLD)); + temp = MALLOC(parser, INIT_SCAFFOLD_ELEMENTS * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; } dtd->scaffold = temp; } - next = dtd->scaffCount++; + next = (int)dtd->scaffCount++; me = &dtd->scaffold[next]; if (dtd->scaffLevel) { CONTENT_SCAFFOLD *parent @@ -7941,7 +8294,10 @@ build_model(XML_Parser parser) { const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) + (dtd->contentStringLen * sizeof(XML_Char))); - ret = (XML_Content *)MALLOC(parser, allocsize); + // NOTE: We are avoiding MALLOC(..) here to so that + // applications that are not using XML_FreeContentModel but plain + // free(..) or .free_fcn() to free the content model's memory are safe. + ret = parser->m_mem.malloc_fcn(allocsize); if (! ret) return NULL; @@ -8062,7 +8418,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, } static XML_Char * -copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { +copyString(const XML_Char *s, XML_Parser parser) { size_t charsRequired = 0; XML_Char *result; @@ -8074,7 +8430,7 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { charsRequired++; /* Now allocate space for the copy */ - result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char)); + result = MALLOC(parser, charsRequired * sizeof(XML_Char)); if (result == NULL) return NULL; /* Copy the original into place */ @@ -8093,10 +8449,10 @@ accountingGetCurrentAmplification(XML_Parser rootParser) { + rootParser->m_accounting.countBytesIndirect; const float amplificationFactor = rootParser->m_accounting.countBytesDirect - ? (countBytesOutput + ? ((float)countBytesOutput / (float)(rootParser->m_accounting.countBytesDirect)) - : ((lenOfShortestInclude - + rootParser->m_accounting.countBytesIndirect) + : ((float)(lenOfShortestInclude + + rootParser->m_accounting.countBytesIndirect) / (float)lenOfShortestInclude); assert(! rootParser->m_parentParser); return amplificationFactor; @@ -8280,6 +8636,8 @@ entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) { rootParser->m_entity_stats.currentDepth--; } +#endif /* XML_GE == 1 */ + static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { XML_Parser rootParser = parser; @@ -8295,6 +8653,8 @@ getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { return rootParser; } +#if XML_GE == 1 + const char * unsignedCharToPrintable(unsigned char c) { switch (c) { diff --git a/contrib/expat/lib/xmlrole.h b/contrib/expat/lib/xmlrole.h index a7904274c91d..67bdd3dd5160 100644 --- a/contrib/expat/lib/xmlrole.h +++ b/contrib/expat/lib/xmlrole.h @@ -34,19 +34,13 @@ */ #ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 +# define XmlRole_INCLUDED 1 -#ifdef __VMS -/* 0 1 2 3 0 1 2 3 - 1234567890123456789012345678901 1234567890123456789012345678901 */ -# define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt -#endif +# include "xmltok.h" -#include "xmltok.h" - -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif enum { XML_ROLE_ERROR = -1, @@ -107,11 +101,11 @@ enum { XML_ROLE_CONTENT_ELEMENT_PLUS, XML_ROLE_PI, XML_ROLE_COMMENT, -#ifdef XML_DTD +# ifdef XML_DTD XML_ROLE_TEXT_DECL, XML_ROLE_IGNORE_SECT, XML_ROLE_INNER_PARAM_ENTITY_REF, -#endif /* XML_DTD */ +# endif /* XML_DTD */ XML_ROLE_PARAM_ENTITY_REF }; @@ -120,23 +114,23 @@ typedef struct prolog_state { const char *end, const ENCODING *enc); unsigned level; int role_none; -#ifdef XML_DTD +# ifdef XML_DTD unsigned includeLevel; int documentEntity; int inEntityValue; -#endif /* XML_DTD */ +# endif /* XML_DTD */ } PROLOG_STATE; void XmlPrologStateInit(PROLOG_STATE *state); -#ifdef XML_DTD +# ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state); -#endif /* XML_DTD */ +# endif /* XML_DTD */ -#define XmlTokenRole(state, tok, ptr, end, enc) \ - (((state)->handler)(state, tok, ptr, end, enc)) +# define XmlTokenRole(state, tok, ptr, end, enc) \ + (((state)->handler)(state, tok, ptr, end, enc)) -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif #endif /* not XmlRole_INCLUDED */ diff --git a/contrib/expat/lib/xmltok.c b/contrib/expat/lib/xmltok.c index 29a66d72ceea..95d5e84b67f1 100644 --- a/contrib/expat/lib/xmltok.c +++ b/contrib/expat/lib/xmltok.c @@ -1398,7 +1398,7 @@ unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, } ENCODING * -XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, +XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert, void *userData) { int i; struct unknown_encoding *e = (struct unknown_encoding *)mem; @@ -1661,7 +1661,7 @@ initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc, # undef ns ENCODING * -XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, +XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert, void *userData) { ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); if (enc) diff --git a/contrib/expat/lib/xmltok.h b/contrib/expat/lib/xmltok.h index c51fce1ec151..79a9fb76871f 100644 --- a/contrib/expat/lib/xmltok.h +++ b/contrib/expat/lib/xmltok.h @@ -35,113 +35,113 @@ */ #ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 +# define XmlTok_INCLUDED 1 -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /* The following token may be returned by XmlContentTok */ -#define XML_TOK_TRAILING_RSQB \ - -5 /* ] or ]] at the end of the scan; might be \ - start of illegal ]]> sequence */ +# define XML_TOK_TRAILING_RSQB \ + -5 /* ] or ]] at the end of the scan; might be \ + start of illegal ]]> sequence */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ -#define XML_TOK_NONE -4 /* The string to be scanned is empty */ -#define XML_TOK_TRAILING_CR \ - -3 /* A CR at the end of the scan; \ - might be part of CRLF sequence */ -#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ -#define XML_TOK_PARTIAL -1 /* only part of a token */ -#define XML_TOK_INVALID 0 +# define XML_TOK_NONE -4 /* The string to be scanned is empty */ +# define XML_TOK_TRAILING_CR \ + -3 /* A CR at the end of the scan; \ + might be part of CRLF sequence */ +# define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ +# define XML_TOK_PARTIAL -1 /* only part of a token */ +# define XML_TOK_INVALID 0 /* The following tokens are returned by XmlContentTok; some are also returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. */ -#define XML_TOK_START_TAG_WITH_ATTS 1 -#define XML_TOK_START_TAG_NO_ATTS 2 -#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ -#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 -#define XML_TOK_END_TAG 5 -#define XML_TOK_DATA_CHARS 6 -#define XML_TOK_DATA_NEWLINE 7 -#define XML_TOK_CDATA_SECT_OPEN 8 -#define XML_TOK_ENTITY_REF 9 -#define XML_TOK_CHAR_REF 10 /* numeric character reference */ +# define XML_TOK_START_TAG_WITH_ATTS 1 +# define XML_TOK_START_TAG_NO_ATTS 2 +# define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ +# define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 +# define XML_TOK_END_TAG 5 +# define XML_TOK_DATA_CHARS 6 +# define XML_TOK_DATA_NEWLINE 7 +# define XML_TOK_CDATA_SECT_OPEN 8 +# define XML_TOK_ENTITY_REF 9 +# define XML_TOK_CHAR_REF 10 /* numeric character reference */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ -#define XML_TOK_PI 11 /* processing instruction */ -#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ -#define XML_TOK_COMMENT 13 -#define XML_TOK_BOM 14 /* Byte order mark */ +# define XML_TOK_PI 11 /* processing instruction */ +# define XML_TOK_XML_DECL 12 /* XML decl or text decl */ +# define XML_TOK_COMMENT 13 +# define XML_TOK_BOM 14 /* Byte order mark */ /* The following tokens are returned only by XmlPrologTok */ -#define XML_TOK_PROLOG_S 15 -#define XML_TOK_DECL_OPEN 16 /* <!foo */ -#define XML_TOK_DECL_CLOSE 17 /* > */ -#define XML_TOK_NAME 18 -#define XML_TOK_NMTOKEN 19 -#define XML_TOK_POUND_NAME 20 /* #name */ -#define XML_TOK_OR 21 /* | */ -#define XML_TOK_PERCENT 22 -#define XML_TOK_OPEN_PAREN 23 -#define XML_TOK_CLOSE_PAREN 24 -#define XML_TOK_OPEN_BRACKET 25 -#define XML_TOK_CLOSE_BRACKET 26 -#define XML_TOK_LITERAL 27 -#define XML_TOK_PARAM_ENTITY_REF 28 -#define XML_TOK_INSTANCE_START 29 +# define XML_TOK_PROLOG_S 15 +# define XML_TOK_DECL_OPEN 16 /* <!foo */ +# define XML_TOK_DECL_CLOSE 17 /* > */ +# define XML_TOK_NAME 18 +# define XML_TOK_NMTOKEN 19 +# define XML_TOK_POUND_NAME 20 /* #name */ +# define XML_TOK_OR 21 /* | */ +# define XML_TOK_PERCENT 22 +# define XML_TOK_OPEN_PAREN 23 +# define XML_TOK_CLOSE_PAREN 24 +# define XML_TOK_OPEN_BRACKET 25 +# define XML_TOK_CLOSE_BRACKET 26 +# define XML_TOK_LITERAL 27 +# define XML_TOK_PARAM_ENTITY_REF 28 +# define XML_TOK_INSTANCE_START 29 /* The following occur only in element type declarations */ -#define XML_TOK_NAME_QUESTION 30 /* name? */ -#define XML_TOK_NAME_ASTERISK 31 /* name* */ -#define XML_TOK_NAME_PLUS 32 /* name+ */ -#define XML_TOK_COND_SECT_OPEN 33 /* <![ */ -#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */ -#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ -#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ -#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ -#define XML_TOK_COMMA 38 +# define XML_TOK_NAME_QUESTION 30 /* name? */ +# define XML_TOK_NAME_ASTERISK 31 /* name* */ +# define XML_TOK_NAME_PLUS 32 /* name+ */ +# define XML_TOK_COND_SECT_OPEN 33 /* <![ */ +# define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */ +# define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ +# define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ +# define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ +# define XML_TOK_COMMA 38 /* The following token is returned only by XmlAttributeValueTok */ -#define XML_TOK_ATTRIBUTE_VALUE_S 39 +# define XML_TOK_ATTRIBUTE_VALUE_S 39 /* The following token is returned only by XmlCdataSectionTok */ -#define XML_TOK_CDATA_SECT_CLOSE 40 +# define XML_TOK_CDATA_SECT_CLOSE 40 /* With namespace processing this is returned by XmlPrologTok for a name with a colon. */ -#define XML_TOK_PREFIXED_NAME 41 +# define XML_TOK_PREFIXED_NAME 41 -#ifdef XML_DTD -# define XML_TOK_IGNORE_SECT 42 -#endif /* XML_DTD */ +# ifdef XML_DTD +# define XML_TOK_IGNORE_SECT 42 +# endif /* XML_DTD */ -#ifdef XML_DTD -# define XML_N_STATES 4 -#else /* not XML_DTD */ -# define XML_N_STATES 3 -#endif /* not XML_DTD */ +# ifdef XML_DTD +# define XML_N_STATES 4 +# else /* not XML_DTD */ +# define XML_N_STATES 3 +# endif /* not XML_DTD */ -#define XML_PROLOG_STATE 0 -#define XML_CONTENT_STATE 1 -#define XML_CDATA_SECTION_STATE 2 -#ifdef XML_DTD -# define XML_IGNORE_SECTION_STATE 3 -#endif /* XML_DTD */ +# define XML_PROLOG_STATE 0 +# define XML_CONTENT_STATE 1 +# define XML_CDATA_SECTION_STATE 2 +# ifdef XML_DTD +# define XML_IGNORE_SECTION_STATE 3 +# endif /* XML_DTD */ -#define XML_N_LITERAL_TYPES 2 -#define XML_ATTRIBUTE_VALUE_LITERAL 0 -#define XML_ENTITY_VALUE_LITERAL 1 +# define XML_N_LITERAL_TYPES 2 +# define XML_ATTRIBUTE_VALUE_LITERAL 0 +# define XML_ENTITY_VALUE_LITERAL 1 /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ -#define XML_UTF8_ENCODE_MAX 4 +# define XML_UTF8_ENCODE_MAX 4 /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ -#define XML_UTF16_ENCODE_MAX 2 +# define XML_UTF16_ENCODE_MAX 2 typedef struct position { /* first line and first column are 0 not 1 */ @@ -220,63 +220,63 @@ struct encoding { the prolog outside literals, comments and processing instructions. */ -#define XmlTok(enc, state, ptr, end, nextTokPtr) \ - (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) +# define XmlTok(enc, state, ptr, end, nextTokPtr) \ + (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) -#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) +# define XmlPrologTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) -#define XmlContentTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) +# define XmlContentTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) -#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) +# define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) -#ifdef XML_DTD +# ifdef XML_DTD -# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) +# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) -#endif /* XML_DTD */ +# endif /* XML_DTD */ /* This is used for performing a 2nd-level tokenization on the content of a literal that has already been returned by XmlTok. */ -#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ - (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) +# define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ + (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) -#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) +# define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) -#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) +# define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) -#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ - (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) +# define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ + (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) -#define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr)) +# define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr)) -#define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr)) +# define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr)) -#define XmlGetAttributes(enc, ptr, attsMax, atts) \ - (((enc)->getAtts)(enc, ptr, attsMax, atts)) +# define XmlGetAttributes(enc, ptr, attsMax, atts) \ + (((enc)->getAtts)(enc, ptr, attsMax, atts)) -#define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr)) +# define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr)) -#define XmlPredefinedEntityName(enc, ptr, end) \ - (((enc)->predefinedEntityName)(enc, ptr, end)) +# define XmlPredefinedEntityName(enc, ptr, end) \ + (((enc)->predefinedEntityName)(enc, ptr, end)) -#define XmlUpdatePosition(enc, ptr, end, pos) \ - (((enc)->updatePosition)(enc, ptr, end, pos)) +# define XmlUpdatePosition(enc, ptr, end, pos) \ + (((enc)->updatePosition)(enc, ptr, end, pos)) -#define XmlIsPublicId(enc, ptr, end, badPtr) \ - (((enc)->isPublicId)(enc, ptr, end, badPtr)) +# define XmlIsPublicId(enc, ptr, end, badPtr) \ + (((enc)->isPublicId)(enc, ptr, end, badPtr)) -#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) +# define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) -#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) +# define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) typedef struct { ENCODING initEnc; @@ -299,7 +299,7 @@ int XmlSizeOfUnknownEncoding(void); typedef int(XMLCALL *CONVERTER)(void *userData, const char *p); -ENCODING *XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, +ENCODING *XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert, void *userData); int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc, @@ -312,10 +312,10 @@ int XmlInitEncodingNS(INIT_ENCODING *p, const ENCODING **encPtr, const char *name); const ENCODING *XmlGetUtf8InternalEncodingNS(void); const ENCODING *XmlGetUtf16InternalEncodingNS(void); -ENCODING *XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, - void *userData); -#ifdef __cplusplus +ENCODING *XmlInitUnknownEncodingNS(void *mem, const int *table, + CONVERTER convert, void *userData); +# ifdef __cplusplus } -#endif +# endif #endif /* not XmlTok_INCLUDED */ diff --git a/contrib/expat/tests/Makefile.in b/contrib/expat/tests/Makefile.in index eb00a068cbd2..830560e2daba 100644 --- a/contrib/expat/tests/Makefile.in +++ b/contrib/expat/tests/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -102,6 +102,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -324,10 +326,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ + { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* @@ -415,12 +416,13 @@ am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ + $$am__collect_skipped_logs \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the -# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# developer-defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). @@ -439,6 +441,11 @@ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ +if test -n '$(IGNORE_SKIPPED_LOGS)'; then \ + am__collect_skipped_logs='--collect-skipped-logs no'; \ +else \ + am__collect_skipped_logs=''; \ +fi; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ @@ -620,8 +627,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -757,13 +766,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list + $(am__rm_f) $(check_PROGRAMS) + test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=) runtests$(EXEEXT): $(runtests_OBJECTS) $(runtests_DEPENDENCIES) $(EXTRA_runtests_DEPENDENCIES) @rm -f runtests$(EXEEXT) @@ -810,7 +814,7 @@ distclean-compile: $(am__depfiles_remade): @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + @: >>$@ am--depfiles: $(am__depfiles_remade) @@ -974,7 +978,6 @@ distclean-tags: am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: - $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ @@ -1050,10 +1053,37 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ + output_system_information () \ + { \ + echo; \ + { uname -a | $(AWK) '{ \ + printf "System information (uname -a):"; \ + for (i = 1; i < NF; ++i) \ + { \ + if (i != 2) \ + printf " %s", $$i; \ + } \ + printf "\n"; \ +}'; } 2>&1; \ + if test -r /etc/os-release; then \ + echo "Distribution information (/etc/os-release):"; \ + sed 8q /etc/os-release; \ + elif test -r /etc/issue; then \ + echo "Distribution information (/etc/issue):"; \ + cat /etc/issue; \ + fi; \ + }; \ + please_report () \ + { \ +echo "Some test(s) failed. Please report this to $(PACKAGE_BUGREPORT),"; \ +echo "together with the test-suite.log file (gzipped) and your system"; \ +echo "information. Thanks."; \ + }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ + output_system_information; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ @@ -1073,26 +1103,25 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ - echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG) for debugging.$${std}";\ if test -n "$(PACKAGE_BUGREPORT)"; then \ - echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + please_report | sed -e "s/^/$${col}/" -e s/'$$'/"$${std}"/; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) - @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list - @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @$(am__rm_f) $(RECHECK_LOGS) + @$(am__rm_f) $(RECHECK_LOGS:.log=.trs) + @$(am__rm_f) $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ - trs_list=`for i in $$bases; do echo $$i.trs; done`; \ - log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @$(am__rm_f) $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ @@ -1130,6 +1159,7 @@ runtests_cxx.log: runtests_cxx$(EXEEXT) @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -1215,15 +1245,15 @@ install-strip: "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: - -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) - -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) - -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + -$(am__rm_f) $(TEST_LOGS) + -$(am__rm_f) $(TEST_LOGS:.log=.trs) + -$(am__rm_f) $(TEST_SUITE_LOG) clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -1234,7 +1264,7 @@ clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-recursive - -rm -f ./$(DEPDIR)/acc_tests.Po + -rm -f ./$(DEPDIR)/acc_tests.Po -rm -f ./$(DEPDIR)/acc_tests_cxx.Po -rm -f ./$(DEPDIR)/alloc_tests.Po -rm -f ./$(DEPDIR)/alloc_tests_cxx.Po @@ -1307,7 +1337,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive - -rm -f ./$(DEPDIR)/acc_tests.Po + -rm -f ./$(DEPDIR)/acc_tests.Po -rm -f ./$(DEPDIR)/acc_tests_cxx.Po -rm -f ./$(DEPDIR)/alloc_tests.Po -rm -f ./$(DEPDIR)/alloc_tests_cxx.Po @@ -1376,3 +1406,10 @@ uninstall-am: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/tests/alloc_tests.c b/contrib/expat/tests/alloc_tests.c index 12ea3b2a81d2..644a49523c6e 100644 --- a/contrib/expat/tests/alloc_tests.c +++ b/contrib/expat/tests/alloc_tests.c @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> - Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> @@ -46,10 +46,16 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include <math.h> /* NAN, INFINITY */ +#include <stdbool.h> +#include <stdint.h> /* for SIZE_MAX */ #include <string.h> #include <assert.h> +#include "expat_config.h" + #include "expat.h" +#include "internal.h" #include "common.h" #include "minicheck.h" #include "dummy.h" @@ -323,7 +329,7 @@ START_TEST(test_alloc_run_external_parser) { XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetUserData(g_parser, foo_text); XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); - g_allocation_count = i; + g_allocation_count = (int)i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; @@ -434,7 +440,7 @@ START_TEST(test_alloc_internal_entity) { const unsigned int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, NULL); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) @@ -2085,6 +2091,203 @@ START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) { } END_TEST +START_TEST(test_alloc_tracker_size_recorded) { + XML_Memory_Handling_Suite memsuite = {malloc, realloc, free}; + + bool values[] = {true, false}; + for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); i++) { + const bool useMemSuite = values[i]; + set_subtest("useMemSuite=%d", (int)useMemSuite); + XML_Parser parser = useMemSuite + ? XML_ParserCreate_MM(NULL, &memsuite, XCS("|")) + : XML_ParserCreate(NULL); + +#if XML_GE == 1 + void *ptr = expat_malloc(parser, 10, -1); + + assert_true(ptr != NULL); + assert_true(*((size_t *)ptr - 1) == 10); + + assert_true(expat_realloc(parser, ptr, SIZE_MAX / 2, -1) == NULL); + + assert_true(*((size_t *)ptr - 1) == 10); // i.e. unchanged + + ptr = expat_realloc(parser, ptr, 20, -1); + + assert_true(ptr != NULL); + assert_true(*((size_t *)ptr - 1) == 20); + + expat_free(parser, ptr, -1); +#endif + + XML_ParserFree(parser); + } +} +END_TEST + +START_TEST(test_alloc_tracker_maximum_amplification) { + if (g_reparseDeferralEnabledDefault == XML_TRUE) { + return; + } + + XML_Parser parser = XML_ParserCreate(NULL); + + // Get .m_accounting.countBytesDirect from 0 to 3 + const char *const chunk = "<e>"; + assert_true(_XML_Parse_SINGLE_BYTES(parser, chunk, (int)strlen(chunk), + /*isFinal=*/XML_FALSE) + == XML_STATUS_OK); + +#if XML_GE == 1 + // Stop activation threshold from interfering + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); + + // Exceed maximum amplification: should be rejected. + assert_true(expat_malloc(parser, 1000, -1) == NULL); + + // Increase maximum amplification, and try the same amount once more: should + // work. + assert_true(XML_SetAllocTrackerMaximumAmplification(parser, 3000.0f) + == XML_TRUE); + + void *const ptr = expat_malloc(parser, 1000, -1); + assert_true(ptr != NULL); + expat_free(parser, ptr, -1); +#endif + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_threshold) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + // Exceed maximum amplification *before* (default) threshold: should work. + void *const ptr = expat_malloc(parser, 1000, -1); + assert_true(ptr != NULL); + expat_free(parser, ptr, -1); + + // Exceed maximum amplification *after* threshold: should be rejected. + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 999) == XML_TRUE); + assert_true(expat_malloc(parser, 1000, -1) == NULL); +#endif + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_getbuffer_unlimited) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + // Artificially lower threshold + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); + + // Self-test: Prove that threshold is as rejecting as expected + assert_true(expat_malloc(parser, 1000, -1) == NULL); +#endif + // XML_GetBuffer should be allowed to pass, though + assert_true(XML_GetBuffer(parser, 1000) != NULL); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_alloc_tracker_api) { + XML_Parser parserWithoutParent = XML_ParserCreate(NULL); + XML_Parser parserWithParent = XML_ExternalEntityParserCreate( + parserWithoutParent, XCS("entity123"), NULL); + if (parserWithoutParent == NULL) + fail("parserWithoutParent is NULL"); + if (parserWithParent == NULL) + fail("parserWithParent is NULL"); + +#if XML_GE == 1 + // XML_SetAllocTrackerMaximumAmplification, error cases + if (XML_SetAllocTrackerMaximumAmplification(NULL, 123.0f) == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithParent, 123.0f) + == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, NAN) + == XML_TRUE) + fail("Call with NaN limit is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, -1.0f) + == XML_TRUE) + fail("Call with negative limit is NOT supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 0.9f) + == XML_TRUE) + fail("Call with positive limit <1.0 is NOT supposed to succeed"); + + // XML_SetAllocTrackerMaximumAmplification, success cases + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 1.0f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, 123456.789f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetAllocTrackerMaximumAmplification(parserWithoutParent, INFINITY) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + + // XML_SetAllocTrackerActivationThreshold, error cases + if (XML_SetAllocTrackerActivationThreshold(NULL, 123) == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetAllocTrackerActivationThreshold(parserWithParent, 123) == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + + // XML_SetAllocTrackerActivationThreshold, success cases + if (XML_SetAllocTrackerActivationThreshold(parserWithoutParent, 123) + == XML_FALSE) + fail("Call with non-NULL parentless parser is supposed to succeed"); +#endif // XML_GE == 1 + + XML_ParserFree(parserWithParent); + XML_ParserFree(parserWithoutParent); +} +END_TEST + +START_TEST(test_mem_api_cycle) { + XML_Parser parser = XML_ParserCreate(NULL); + + void *ptr = XML_MemMalloc(parser, 10); + + assert_true(ptr != NULL); + memset(ptr, 'x', 10); // assert writability, with ASan in mind + + ptr = XML_MemRealloc(parser, ptr, 20); + + assert_true(ptr != NULL); + memset(ptr, 'y', 20); // assert writability, with ASan in mind + + XML_MemFree(parser, ptr); + + XML_ParserFree(parser); +} +END_TEST + +START_TEST(test_mem_api_unlimited) { + XML_Parser parser = XML_ParserCreate(NULL); + +#if XML_GE == 1 + assert_true(XML_SetAllocTrackerActivationThreshold(parser, 0) == XML_TRUE); +#endif + + void *ptr = XML_MemMalloc(parser, 1000); + + assert_true(ptr != NULL); + + ptr = XML_MemRealloc(parser, ptr, 2000); + + assert_true(ptr != NULL); + + XML_MemFree(parser, ptr); + + XML_ParserFree(parser); +} +END_TEST + void make_alloc_test_case(Suite *s) { TCase *tc_alloc = tcase_create("allocation tests"); @@ -2151,4 +2354,15 @@ make_alloc_test_case(Suite *s) { tcase_add_test__ifdef_xml_dtd( tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); + + tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_size_recorded); + tcase_add_test__ifdef_xml_dtd(tc_alloc, + test_alloc_tracker_maximum_amplification); + tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_threshold); + tcase_add_test__ifdef_xml_dtd(tc_alloc, + test_alloc_tracker_getbuffer_unlimited); + tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_api); + + tcase_add_test(tc_alloc, test_mem_api_cycle); + tcase_add_test__ifdef_xml_dtd(tc_alloc, test_mem_api_unlimited); } diff --git a/contrib/expat/tests/basic_tests.c b/contrib/expat/tests/basic_tests.c index e813df8b6fd2..0231e0949ee9 100644 --- a/contrib/expat/tests/basic_tests.c +++ b/contrib/expat/tests/basic_tests.c @@ -412,13 +412,13 @@ START_TEST(test_utf16_le_epilog_newline) { if (first_chunk_bytes >= sizeof(text) - 1) fail("bad value of first_chunk_bytes"); - if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE) + if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)first_chunk_bytes, XML_FALSE) == XML_STATUS_ERROR) xml_failure(g_parser); else { enum XML_Status rc; rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes, - sizeof(text) - first_chunk_bytes - 1, + (int)(sizeof(text) - first_chunk_bytes - 1), XML_TRUE); if (rc == XML_STATUS_ERROR) xml_failure(g_parser); @@ -3123,6 +3123,10 @@ START_TEST(test_buffer_can_grow_to_max) { for (int i = 0; i < num_prefixes; ++i) { set_subtest("\"%s\"", prefixes[i]); XML_Parser parser = XML_ParserCreate(NULL); +#if XML_GE == 1 + assert_true(XML_SetAllocTrackerActivationThreshold(parser, (size_t)-1) + == XML_TRUE); // i.e. deactivate +#endif const int prefix_len = (int)strlen(prefixes[i]); const enum XML_Status s = _XML_Parse_SINGLE_BYTES(parser, prefixes[i], prefix_len, XML_FALSE); diff --git a/contrib/expat/tests/benchmark/Makefile.in b/contrib/expat/tests/benchmark/Makefile.in index d0e6d0769db0..e72e901a39af 100644 --- a/contrib/expat/tests/benchmark/Makefile.in +++ b/contrib/expat/tests/benchmark/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -101,6 +101,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -320,8 +322,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -403,13 +407,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list + $(am__rm_f) $(noinst_PROGRAMS) + test -z "$(EXEEXT)" || $(am__rm_f) $(noinst_PROGRAMS:$(EXEEXT)=) benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES) $(EXTRA_benchmark_DEPENDENCIES) @rm -f benchmark$(EXEEXT) @@ -425,7 +424,7 @@ distclean-compile: $(am__depfiles_remade): @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + @: >>$@ am--depfiles: $(am__depfiles_remade) @@ -507,6 +506,7 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -568,8 +568,8 @@ mostlyclean-generic: clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -580,7 +580,7 @@ clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/benchmark.Po + -rm -f ./$(DEPDIR)/benchmark.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -626,7 +626,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/benchmark.Po + -rm -f ./$(DEPDIR)/benchmark.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -667,3 +667,10 @@ uninstall-am: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/tests/common.c b/contrib/expat/tests/common.c index b158385f56a8..b2537d0deee1 100644 --- a/contrib/expat/tests/common.c +++ b/contrib/expat/tests/common.c @@ -303,7 +303,14 @@ duff_reallocator(void *ptr, size_t size) { return realloc(ptr, size); } -// Portable remake of strndup(3) for C99; does not care about space efficiency +// Portable remake of strnlen(3) for C99 +static size_t +portable_strnlen(const char *s, size_t maxlen) { + const char *const end = (const char *)memchr(s, '\0', maxlen); + return (end == NULL) ? maxlen : (size_t)(end - s); +} + +// Portable remake of strndup(3) for C99 char * portable_strndup(const char *s, size_t n) { if ((s == NULL) || (n == SIZE_MAX)) { @@ -311,6 +318,8 @@ portable_strndup(const char *s, size_t n) { return NULL; } + n = portable_strnlen(s, n); + char *const buffer = (char *)malloc(n + 1); if (buffer == NULL) { errno = ENOMEM; diff --git a/contrib/expat/tests/handlers.c b/contrib/expat/tests/handlers.c index ac459507580b..5bca2b1f551e 100644 --- a/contrib/expat/tests/handlers.c +++ b/contrib/expat/tests/handlers.c @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> - Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> @@ -89,15 +89,15 @@ start_element_event_handler2(void *userData, const XML_Char *name, const XML_Char **attr) { StructData *storage = (StructData *)userData; UNUSED_P(attr); - StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), - XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), + (int)XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); } void XMLCALL end_element_event_handler2(void *userData, const XML_Char *name) { StructData *storage = (StructData *)userData; - StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), - XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); + StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser), + (int)XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); } void XMLCALL @@ -132,7 +132,7 @@ counting_start_element_handler(void *userData, const XML_Char *name, fail("ID not present"); return; } - if (id != -1 && xcstrcmp(atts[id], info->id_name)) { + if (id != -1 && xcstrcmp(atts[id], info->id_name) != 0) { fail("ID does not have the correct name"); return; } @@ -147,7 +147,7 @@ counting_start_element_handler(void *userData, const XML_Char *name, fail("Attribute not recognised"); return; } - if (xcstrcmp(atts[1], attr->value)) { + if (xcstrcmp(atts[1], attr->value) != 0) { fail("Attribute has wrong value"); return; } @@ -1110,7 +1110,7 @@ external_entity_devaluer(XML_Parser parser, const XML_Char *context, UNUSED_P(publicId); if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) return XML_STATUS_OK; - if (xcstrcmp(systemId, XCS("foo"))) + if (xcstrcmp(systemId, XCS("foo")) != 0) fail("Unexpected system ID"); ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (ext_parser == NULL) @@ -1276,7 +1276,7 @@ external_entity_duff_loader(XML_Parser parser, const XML_Char *context, UNUSED_P(publicId); /* Try a few different allocation levels */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); if (new_parser != NULL) { XML_ParserFree(new_parser); @@ -1552,15 +1552,16 @@ verify_attlist_decl_handler(void *userData, const XML_Char *element_name, const XML_Char *default_value, int is_required) { AttTest *at = (AttTest *)userData; - if (xcstrcmp(element_name, at->element_name)) + if (xcstrcmp(element_name, at->element_name) != 0) fail("Unexpected element name in attribute declaration"); - if (xcstrcmp(attr_name, at->attr_name)) + if (xcstrcmp(attr_name, at->attr_name) != 0) fail("Unexpected attribute name in attribute declaration"); - if (xcstrcmp(attr_type, at->attr_type)) + if (xcstrcmp(attr_type, at->attr_type) != 0) fail("Unexpected attribute type in attribute declaration"); if ((default_value == NULL && at->default_value != NULL) || (default_value != NULL && at->default_value == NULL) - || (default_value != NULL && xcstrcmp(default_value, at->default_value))) + || (default_value != NULL + && xcstrcmp(default_value, at->default_value) != 0)) fail("Unexpected default value in attribute declaration"); if (is_required != at->is_required) fail("Requirement mismatch in attribute declaration"); @@ -1751,7 +1752,7 @@ param_entity_match_handler(void *userData, const XML_Char *entityName, * going to overflow an int. */ if (value_length != (int)xcstrlen(entity_value_to_match) - || xcstrncmp(value, entity_value_to_match, value_length)) { + || xcstrncmp(value, entity_value_to_match, value_length) != 0) { entity_match_flag = ENTITY_MATCH_FAIL; } else { entity_match_flag = ENTITY_MATCH_SUCCESS; diff --git a/contrib/expat/tests/minicheck.h b/contrib/expat/tests/minicheck.h index 29ae4cb2420d..140eaaa5c105 100644 --- a/contrib/expat/tests/minicheck.h +++ b/contrib/expat/tests/minicheck.h @@ -134,8 +134,7 @@ void _check_set_test_info(char const *function, char const *filename, __attribute__((noreturn)) # endif # endif -void -_fail(const char *file, int line, const char *msg); +void _fail(const char *file, int line, const char *msg); Suite *suite_create(const char *name); TCase *tcase_create(const char *name); void suite_add_tcase(Suite *suite, TCase *tc); diff --git a/contrib/expat/tests/misc_tests.c b/contrib/expat/tests/misc_tests.c index fb95014b142f..3346bce6074b 100644 --- a/contrib/expat/tests/misc_tests.c +++ b/contrib/expat/tests/misc_tests.c @@ -70,7 +70,7 @@ START_TEST(test_misc_alloc_create_parser) { /* Something this simple shouldn't need more than 10 allocations */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); if (g_parser != NULL) break; @@ -90,7 +90,7 @@ START_TEST(test_misc_alloc_create_parser_with_encoding) { /* Try several levels of allocation */ for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); if (g_parser != NULL) break; @@ -211,7 +211,8 @@ START_TEST(test_misc_version) { if (! versions_equal(&read_version, &parsed_version)) fail("Version mismatch"); - if (xcstrcmp(version_text, XCS("expat_2.7.1"))) /* needs bump on releases */ + if (xcstrcmp(version_text, XCS("expat_2.7.2")) + != 0) /* needs bump on releases */ fail("XML_*_VERSION in expat.h out of sync?\n"); } END_TEST diff --git a/contrib/expat/tests/nsalloc_tests.c b/contrib/expat/tests/nsalloc_tests.c index ec88586af1d4..60fa87f83461 100644 --- a/contrib/expat/tests/nsalloc_tests.c +++ b/contrib/expat/tests/nsalloc_tests.c @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> - Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2017 Joe Orton <jorton@redhat.com> Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> @@ -83,7 +83,7 @@ START_TEST(test_nsalloc_xmlns) { const unsigned int max_alloc_count = 30; for (i = 0; i < max_alloc_count; i++) { - g_allocation_count = i; + g_allocation_count = (int)i; /* Exercise more code paths with a default handler */ XML_SetDefaultHandler(g_parser, dummy_default_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) @@ -454,10 +454,15 @@ START_TEST(test_nsalloc_realloc_attributes) { nsalloc_teardown(); nsalloc_setup(); } +#if XML_GE == 1 + assert_true( + i == 0); // because expat_realloc relies on expat_malloc to some extent +#else if (i == 0) fail("Parsing worked despite failing reallocations"); else if (i == max_realloc_count) fail("Parsing failed at max reallocation count"); +#endif } END_TEST @@ -523,7 +528,7 @@ START_TEST(test_nsalloc_realloc_binding_uri) { /* Now repeat with a longer URI and a duff reallocator */ for (i = 0; i < max_realloc_count; i++) { XML_ParserReset(g_parser, NULL); - g_reallocation_count = i; + g_reallocation_count = (int)i; if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) != XML_STATUS_ERROR) break; diff --git a/contrib/expat/xmlwf/Makefile.in b/contrib/expat/xmlwf/Makefile.in index 480fd3e04103..07f2423aea10 100644 --- a/contrib/expat/xmlwf/Makefile.in +++ b/contrib/expat/xmlwf/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.5 from Makefile.am. +# Makefile.in generated by automake 1.18.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2021 Free Software Foundation, Inc. +# Copyright (C) 1994-2025 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -100,6 +100,8 @@ am__make_running_with_option = \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -328,8 +330,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ +am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ +am__xargs_n = @am__xargs_n@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -464,16 +468,11 @@ uninstall-binPROGRAMS: `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(bindir)" && rm -f $$files + cd "$(DESTDIR)$(bindir)" && $(am__rm_f) $$files clean-binPROGRAMS: - @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list + $(am__rm_f) $(bin_PROGRAMS) + test -z "$(EXEEXT)" || $(am__rm_f) $(bin_PROGRAMS:$(EXEEXT)=) xmlwf$(EXEEXT): $(xmlwf_OBJECTS) $(xmlwf_DEPENDENCIES) $(EXTRA_xmlwf_DEPENDENCIES) @rm -f xmlwf$(EXEEXT) @@ -492,7 +491,7 @@ distclean-compile: $(am__depfiles_remade): @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + @: >>$@ am--depfiles: $(am__depfiles_remade) @@ -630,6 +629,7 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -694,8 +694,8 @@ mostlyclean-generic: clean-generic: distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -705,7 +705,7 @@ clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po + -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po -rm -f ./$(DEPDIR)/xmlwf-codepage.Po -rm -f ./$(DEPDIR)/xmlwf-xmlfile.Po -rm -f ./$(DEPDIR)/xmlwf-xmlwf.Po @@ -754,7 +754,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po + -rm -f ./$(DEPDIR)/xmlwf-@FILEMAP@.Po -rm -f ./$(DEPDIR)/xmlwf-codepage.Po -rm -f ./$(DEPDIR)/xmlwf-xmlfile.Po -rm -f ./$(DEPDIR)/xmlwf-xmlwf.Po @@ -798,3 +798,10 @@ uninstall-am: uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: + +# Tell GNU make to disable its built-in pattern rules. +%:: %,v +%:: RCS/%,v +%:: RCS/% +%:: s.% +%:: SCCS/s.% diff --git a/contrib/expat/xmlwf/unixfilemap.c b/contrib/expat/xmlwf/unixfilemap.c index d0ce9cc60a8a..d2e0b174680b 100644 --- a/contrib/expat/xmlwf/unixfilemap.c +++ b/contrib/expat/xmlwf/unixfilemap.c @@ -10,7 +10,7 @@ Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net> Copyright (c) 2001-2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2006 Karl Waclawek <karl@waclawek.net> - Copyright (c) 2016-2017 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: @@ -41,6 +41,7 @@ #include <errno.h> #include <string.h> #include <stdio.h> +#include <stdlib.h> // NULL #include <unistd.h> #ifndef MAP_FILE @@ -93,8 +94,7 @@ filemap(const tchar *name, close(fd); return 1; } - p = (void *)mmap((void *)0, (size_t)nbytes, PROT_READ, MAP_FILE | MAP_PRIVATE, - fd, (off_t)0); + p = mmap(NULL, nbytes, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t)0); if (p == (void *)-1) { tperror(name); close(fd); diff --git a/contrib/expat/xmlwf/xmlfile.c b/contrib/expat/xmlwf/xmlfile.c index 9c4f7f8dbadd..54617fcc5a1a 100644 --- a/contrib/expat/xmlwf/xmlfile.c +++ b/contrib/expat/xmlwf/xmlfile.c @@ -11,7 +11,7 @@ Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2004-2006 Karl Waclawek <karl@waclawek.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> - Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2019 David Loffredo <loffredo@steptools.com> Copyright (c) 2021 Donghee Na <donghee.na@python.org> @@ -56,12 +56,19 @@ #include "xmltchar.h" #include "filemap.h" +/* Function "read": */ #if defined(_MSC_VER) # include <io.h> -#endif - -#ifdef HAVE_UNISTD_H +/* https://msdn.microsoft.com/en-us/library/wyssk1bs(v=vs.100).aspx */ +# define EXPAT_read _read +# define EXPAT_read_count_t int +# define EXPAT_read_req_t unsigned int +#else /* POSIX */ # include <unistd.h> +/* https://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */ +# define EXPAT_read read +# define EXPAT_read_count_t ssize_t +# define EXPAT_read_req_t size_t #endif #ifndef O_BINARY @@ -192,7 +199,7 @@ processStream(const XML_Char *filename, XML_Parser parser) { } } for (;;) { - int nread; + EXPAT_read_count_t nread; char *buf = (char *)XML_GetBuffer(parser, g_read_size_bytes); if (! buf) { if (filename != NULL) @@ -201,14 +208,14 @@ processStream(const XML_Char *filename, XML_Parser parser) { filename != NULL ? filename : T("xmlwf")); return 0; } - nread = read(fd, buf, g_read_size_bytes); + nread = EXPAT_read(fd, buf, (EXPAT_read_req_t)g_read_size_bytes); if (nread < 0) { tperror(filename != NULL ? filename : T("STDIN")); if (filename != NULL) close(fd); return 0; } - if (XML_ParseBuffer(parser, nread, nread == 0) == XML_STATUS_ERROR) { + if (XML_ParseBuffer(parser, (int)nread, nread == 0) == XML_STATUS_ERROR) { reportError(parser, filename != NULL ? filename : T("STDIN")); if (filename != NULL) close(fd); diff --git a/contrib/expat/xmlwf/xmlwf.c b/contrib/expat/xmlwf/xmlwf.c index 7c0a8cd4d6a4..534f32170590 100644 --- a/contrib/expat/xmlwf/xmlwf.c +++ b/contrib/expat/xmlwf/xmlwf.c @@ -11,7 +11,7 @@ Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2004-2009 Karl Waclawek <karl@waclawek.net> Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> - Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Copyright (c) 2019 David Loffredo <loffredo@steptools.com> Copyright (c) 2020 Joe Orton <jorton@redhat.com> @@ -305,7 +305,7 @@ static XML_Char * xcsdup(const XML_Char *s) { XML_Char *result; int count = 0; - int numBytes; + size_t numBytes; /* Get the length of the string, including terminator */ while (s[count++] != 0) { @@ -913,11 +913,11 @@ usage(const XML_Char *prog, int rc) { T(" -t write no XML output for [t]iming of plain parsing\n") T(" -N enable adding doctype and [n]otation declarations\n") T("\n") - T("billion laughs attack protection:\n") + T("amplification attack protection (e.g. billion laughs):\n") T(" NOTE: If you ever need to increase these values for non-attack payload, please file a bug report.\n") T("\n") T(" -a FACTOR set maximum tolerated [a]mplification factor (default: 100.0)\n") - T(" -b BYTES set number of output [b]ytes needed to activate (default: 8 MiB)\n") + T(" -b BYTES set number of output [b]ytes needed to activate (default: 8 MiB/64 MiB)\n") T("\n") T("reparse deferral:\n") T(" -q disable reparse deferral, and allow [q]uadratic parse runtime with large tokens\n") @@ -926,6 +926,16 @@ usage(const XML_Char *prog, int rc) { T(" -h, --help show this [h]elp message and exit\n") T(" -v, --version show program's [v]ersion number and exit\n") T("\n") + T("environment variables:\n") + T(" EXPAT_ACCOUNTING_DEBUG=(0|1|2|3)\n") + T(" Control verbosity of accounting debugging (default: 0)\n") + T(" EXPAT_ENTITY_DEBUG=(0|1)\n") + T(" Control verbosity of entity debugging (default: 0)\n") + T(" EXPAT_ENTROPY_DEBUG=(0|1)\n") + T(" Control verbosity of entropy debugging (default: 0)\n") + T(" EXPAT_MALLOC_DEBUG=(0|1|2)\n") + T(" Control verbosity of allocation tracker (default: 0)\n") + T("\n") T("exit status:\n") T(" 0 the input files are well-formed and the output (if requested) was written successfully\n") T(" 1 could not allocate data structures, signals a serious problem with execution environment\n") @@ -1171,12 +1181,15 @@ tmain(int argc, XML_Char **argv) { #if XML_GE == 1 XML_SetBillionLaughsAttackProtectionMaximumAmplification( parser, attackMaximumAmplification); + XML_SetAllocTrackerMaximumAmplification(parser, + attackMaximumAmplification); #endif } if (attackThresholdGiven) { #if XML_GE == 1 XML_SetBillionLaughsAttackProtectionActivationThreshold( parser, attackThresholdBytes); + XML_SetAllocTrackerActivationThreshold(parser, attackThresholdBytes); #else (void)attackThresholdBytes; // silence -Wunused-but-set-variable #endif diff --git a/contrib/expat/xmlwf/xmlwf_helpgen.py b/contrib/expat/xmlwf/xmlwf_helpgen.py index 3d32f5d148b7..71f7baa43396 100755 --- a/contrib/expat/xmlwf/xmlwf_helpgen.py +++ b/contrib/expat/xmlwf/xmlwf_helpgen.py @@ -6,7 +6,7 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2019-2023 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2019-2025 Sebastian Pipping <sebastian@pipping.org> # Copyright (c) 2021 Tim Bray <tbray@textuality.com> # Licensed under the MIT license: # @@ -32,6 +32,16 @@ import argparse epilog = """ +environment variables: + EXPAT_ACCOUNTING_DEBUG=(0|1|2|3) + Control verbosity of accounting debugging (default: 0) + EXPAT_ENTITY_DEBUG=(0|1) + Control verbosity of entity debugging (default: 0) + EXPAT_ENTROPY_DEBUG=(0|1) + Control verbosity of entropy debugging (default: 0) + EXPAT_MALLOC_DEBUG=(0|1|2) + Control verbosity of allocation tracker (default: 0) + exit status: 0 the input files are well-formed and the output (if requested) was written successfully 1 could not allocate data structures, signals a serious problem with execution environment @@ -74,16 +84,16 @@ output_mode.add_argument('-m', action='store_true', help='write [m]eta XML, not output_mode.add_argument('-t', action='store_true', help='write no XML output for [t]iming of plain parsing') output_related.add_argument('-N', action='store_true', help='enable adding doctype and [n]otation declarations') -billion_laughs = parser.add_argument_group('billion laughs attack protection', +billion_laughs = parser.add_argument_group('amplification attack protection (e.g. billion laughs)', description='NOTE: ' 'If you ever need to increase these values ' 'for non-attack payload, please file a bug report.') billion_laughs.add_argument('-a', metavar='FACTOR', help='set maximum tolerated [a]mplification factor (default: 100.0)') -billion_laughs.add_argument('-b', metavar='BYTES', help='set number of output [b]ytes needed to activate (default: 8 MiB)') +billion_laughs.add_argument('-b', metavar='BYTES', help='set number of output [b]ytes needed to activate (default: 8 MiB/64 MiB)') reparse_deferral = parser.add_argument_group('reparse deferral') -reparse_deferral.add_argument('-q', metavar='FACTOR', +reparse_deferral.add_argument('-q', action='store_true', help='disable reparse deferral, and allow [q]uadratic parse runtime with large tokens') parser.add_argument('files', metavar='FILE', nargs='*', help='file to process (default: STDIN)') diff --git a/contrib/kyua/doc/kyuafile.5.in b/contrib/kyua/doc/kyuafile.5.in index 43f00816d407..a9106e95d790 100644 --- a/contrib/kyua/doc/kyuafile.5.in +++ b/contrib/kyua/doc/kyuafile.5.in @@ -485,7 +485,7 @@ plain_test_program{name='the_test', .Ss FreeBSD jail execution environment The following example configures the test to be run within a temporary jail with -.Xr vnet 9 +.Xr VNET 9 support and the permission to create raw sockets: .Bd -literal -offset indent syntax(2) diff --git a/contrib/llvm-project/libcxx/include/__functional/binary_function.h b/contrib/llvm-project/libcxx/include/__functional/binary_function.h index ddee3b170311..18879f65112b 100644 --- a/contrib/llvm-project/libcxx/include/__functional/binary_function.h +++ b/contrib/llvm-project/libcxx/include/__functional/binary_function.h @@ -39,11 +39,10 @@ struct __binary_function_keep_layout_base { }; #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template <class _Arg1, class _Arg2, class _Result> using __binary_function = binary_function<_Arg1, _Arg2, _Result>; -_LIBCPP_DIAGNOSTIC_POP +_LIBCPP_SUPPRESS_DEPRECATED_POP #else template <class _Arg1, class _Arg2, class _Result> using __binary_function = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; diff --git a/contrib/llvm-project/libcxx/include/__functional/unary_function.h b/contrib/llvm-project/libcxx/include/__functional/unary_function.h index 69b1bc94220a..d46df2e86fbd 100644 --- a/contrib/llvm-project/libcxx/include/__functional/unary_function.h +++ b/contrib/llvm-project/libcxx/include/__functional/unary_function.h @@ -36,11 +36,10 @@ struct __unary_function_keep_layout_base { }; #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template <class _Arg, class _Result> using __unary_function = unary_function<_Arg, _Result>; -_LIBCPP_DIAGNOSTIC_POP +_LIBCPP_SUPPRESS_DEPRECATED_POP #else template <class _Arg, class _Result> using __unary_function = __unary_function_keep_layout_base<_Arg, _Result>; diff --git a/contrib/llvm-project/libcxx/include/__functional/weak_result_type.h b/contrib/llvm-project/libcxx/include/__functional/weak_result_type.h index ad7a8395186c..488fec9dac21 100644 --- a/contrib/llvm-project/libcxx/include/__functional/weak_result_type.h +++ b/contrib/llvm-project/libcxx/include/__functional/weak_result_type.h @@ -77,6 +77,7 @@ struct __maybe_derive_from_unary_function // bool is true template <class _Tp> struct __maybe_derive_from_unary_function<_Tp, false> {}; +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template <class _Tp, bool = __derives_from_binary_function<_Tp>::value> struct __maybe_derive_from_binary_function // bool is true : public __derives_from_binary_function<_Tp>::type {}; @@ -99,6 +100,7 @@ struct __weak_result_type_imp<_Tp, false> template <class _Tp> struct __weak_result_type : public __weak_result_type_imp<_Tp> {}; +_LIBCPP_SUPPRESS_DEPRECATED_POP // 0 argument case diff --git a/contrib/llvm-project/libcxx/include/__memory/allocator_traits.h b/contrib/llvm-project/libcxx/include/__memory/allocator_traits.h index c5fcc89327b8..f3e327edda12 100644 --- a/contrib/llvm-project/libcxx/include/__memory/allocator_traits.h +++ b/contrib/llvm-project/libcxx/include/__memory/allocator_traits.h @@ -40,6 +40,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> \ struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {} +_LIBCPP_SUPPRESS_DEPRECATED_PUSH // __pointer template <class _Tp, class _Alloc, @@ -67,6 +68,7 @@ struct __const_pointer<_Tp, _Ptr, _Alloc, false> { using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const _Tp>; #endif }; +_LIBCPP_SUPPRESS_DEPRECATED_POP // __void_pointer _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_void_pointer, void_pointer); diff --git a/contrib/llvm-project/libcxx/include/__memory/uninitialized_algorithms.h b/contrib/llvm-project/libcxx/include/__memory/uninitialized_algorithms.h index 7475ef5cf85d..79cab80dcf73 100644 --- a/contrib/llvm-project/libcxx/include/__memory/uninitialized_algorithms.h +++ b/contrib/llvm-project/libcxx/include/__memory/uninitialized_algorithms.h @@ -642,7 +642,8 @@ __uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _ __guard.__complete(); std::__allocator_destroy(__alloc, __first, __last); } else { - __builtin_memcpy(const_cast<__remove_const_t<_Tp>*>(__result), __first, sizeof(_Tp) * (__last - __first)); + // Casting to void* to suppress clang complaining that this is technically UB. + __builtin_memcpy(static_cast<void*>(const_cast<__remove_const_t<_Tp>*>(__result)), __first, sizeof(_Tp) * (__last - __first)); } } diff --git a/contrib/llvm-project/libcxx/include/__type_traits/is_trivially_relocatable.h b/contrib/llvm-project/libcxx/include/__type_traits/is_trivially_relocatable.h index c0871731cc00..9b0e240de55f 100644 --- a/contrib/llvm-project/libcxx/include/__type_traits/is_trivially_relocatable.h +++ b/contrib/llvm-project/libcxx/include/__type_traits/is_trivially_relocatable.h @@ -11,7 +11,6 @@ #include <__config> #include <__type_traits/enable_if.h> -#include <__type_traits/integral_constant.h> #include <__type_traits/is_same.h> #include <__type_traits/is_trivially_copyable.h> @@ -23,8 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD // A type is trivially relocatable if a move construct + destroy of the original object is equivalent to // `memcpy(dst, src, sizeof(T))`. - -#if __has_builtin(__is_trivially_relocatable) +// +// Note that we don't use the __is_trivially_relocatable Clang builtin right now because it does not +// implement the semantics of any current or future trivial relocation proposal and it can lead to +// incorrect optimizations on some platforms (Windows) and supported compilers (AppleClang). +#if __has_builtin(__is_trivially_relocatable) && 0 template <class _Tp, class = void> struct __libcpp_is_trivially_relocatable : integral_constant<bool, __is_trivially_relocatable(_Tp)> {}; #else diff --git a/contrib/llvm-project/libcxx/include/tuple b/contrib/llvm-project/libcxx/include/tuple index 081b90c7bbec..1d39974d5a6b 100644 --- a/contrib/llvm-project/libcxx/include/tuple +++ b/contrib/llvm-project/libcxx/include/tuple @@ -302,7 +302,9 @@ class __tuple_leaf { template <class _Tp> static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { -# if __has_keyword(__reference_binds_to_temporary) +# if __has_keyword(__reference_constructs_from_temporary) + return !__reference_constructs_from_temporary(_Hp, _Tp); +# elif __has_keyword(__reference_binds_to_temporary) return !__reference_binds_to_temporary(_Hp, _Tp); # else return true; diff --git a/crypto/openssl/BSDmakefile b/crypto/openssl/BSDmakefile index bd2bfe0ea033..d260808ffac3 100644 --- a/crypto/openssl/BSDmakefile +++ b/crypto/openssl/BSDmakefile @@ -12,8 +12,12 @@ LCRYPTO_SRC= ${SRCTOP}/crypto/openssl LCRYPTO_DOC= ${LCRYPTO_SRC}/doc CAT?= /bin/cat +CC?= cc +GMAKE?= gmake +LD?= ld MV?= /bin/mv PERL?= perl +SETENVI= /usr/bin/env -i BN_CONF_H= include/crypto/bn_conf.h BN_CONF_H_ORIG= ${BN_CONF_H}.orig @@ -23,8 +27,14 @@ CONFIGURATION_H_ORIG= ${CONFIGURATION_H}.orig .PHONY: configure patch all .ORDER: configure patch all +LOCALBASE= /usr/local +WRK_ENV= CC=${CC} \ + LD=${LD} \ + PATH=${LOCALBASE}/bin:/bin:/usr/bin + configure: - @cd ${.CURDIR} && \ + @(cd ${.CURDIR} && ${SETENVI} \ + ${WRK_ENV} \ ${PERL} ./Configure \ disable-aria \ disable-egd \ @@ -37,34 +47,45 @@ configure: enable-ktls \ enable-sctp \ --openssldir=etc \ - --prefix=/usr - @cd ${.CURDIR} && gmake configdata.pm - @cd ${LCRYPTO_SRC} && ${PERL} \ - ${LCRYPTO_SRC}/freebsd/dump_version_from_configdata.pl > \ - ${SRCTOP}/secure/lib/libcrypto/Makefile.version + --prefix=/usr) + @echo "Building configdata.pm for later use." + @(cd ${.CURDIR} && \ + ${SETENVI} ${WRK_ENV} ${GMAKE} -j ${.MAKE.JOBS} configdata.pm) -all: patch - # Passing `-j ${.MAKE.JOBS}` doesn't work here for some reason. - @cd ${.CURDIR} && gmake build_all_generated + @echo "Populating Makefile.version with release information" + @(cd ${LCRYPTO_SRC} && ${SETENVI} ${WRK_ENV} ${PERL} \ + ${LCRYPTO_SRC}/freebsd/dump_version_from_configdata.pl > \ + ${SRCTOP}/secure/lib/libcrypto/Makefile.version) - # Clean the pkgconfig files: - # 1. Fix --prefix (not sure why configure --prefix isn't honored properly). +all: patch + @echo "==> Building generated files (headers, manpages, etc)" + @(cd ${.CURDIR} && \ + ${SETENVI} ${WRK_ENV} ${GMAKE} -j ${.MAKE.JOBS} build_all_generated) + + # 1. Fix --prefix. + # a. Not sure why --prefix isn't honored properly, even though it's + # passed to Configure; the files might be getting rebuilt + # post-Configure, somehow. # 2. Remove duplicate path in CFLAGS. # 3. Remove duplicate path in includedir(s). + @echo "==> Fixing pkgconfig files" @find . -name \*.pc -print -exec sed -i '' -E \ -e 's,^prefix=.+,prefix=/usr,' \ -e 's,[[:space:]]+(\-I)?\$\{prefix\}/\./include[[:space:]]*,,g' \ {} + - @cd ${SRCTOP}/secure/lib/libcrypto && \ - ${MAKE} cleanasm && \ - ${MAKE} buildasm + @echo "==> Cleaning / rebuilding ASM" + @(cd ${SRCTOP}/secure/lib/libcrypto && \ + ${SETENVI} ${WRK_ENV} ${MAKE} cleanasm && \ + ${SETENVI} ${WRK_ENV} ${MAKE} buildasm) + @echo "==> Syncing manpages (section 1)" @rsync -a --delete \ --exclude 'Makefile*' --exclude '*.1' \ ${LCRYPTO_DOC}/man/ \ ${SRCTOP}/secure/lib/libcrypto/man + @echo "==> Syncing manpages (sections {3,5,7})" @rsync -a --delete \ --exclude 'Makefile*' --exclude '*.[357]' \ ${LCRYPTO_DOC}/man/man1/ \ @@ -75,25 +96,26 @@ all: patch # depending on the host architecture. patch: configure # Spam arch-specific overrides to config files. + @echo "==> Patching headers" + @(cd ${.CURDIR} && ${SETENVI} ${WRK_ENV} ${GMAKE} ${BN_CONF_H} && \ + ${MV} ${BN_CONF_H} ${BN_CONF_H_ORIG} && \ + ${CAT} ${BN_CONF_H}.orig \ + ${LCRYPTO_SRC}/freebsd/${BN_CONF_H} >> \ + ${BN_CONF_H}) - @cd ${.CURDIR} && gmake ${BN_CONF_H} && \ - ${MV} ${BN_CONF_H} ${BN_CONF_H_ORIG} && \ - ${CAT} ${BN_CONF_H}.orig \ - ${LCRYPTO_SRC}/freebsd/${BN_CONF_H} >> \ - ${BN_CONF_H} - - @cd ${.CURDIR} && \ - ${MV} ${CONFIGURATION_H} ${CONFIGURATION_H_ORIG} && \ - ${CAT} ${CONFIGURATION_H_ORIG} \ - ${LCRYPTO_SRC}/freebsd/${CONFIGURATION_H} >> \ - ${CONFIGURATION_H} + @(cd ${.CURDIR} && \ + ${MV} ${CONFIGURATION_H} ${CONFIGURATION_H_ORIG} && \ + ${CAT} ${CONFIGURATION_H_ORIG} \ + ${LCRYPTO_SRC}/freebsd/${CONFIGURATION_H} >> \ + ${CONFIGURATION_H}) clean: .PHONY - @cd ${.CURDIR} && rm -f ${BN_CONF_H_ORIG} ${CONFIGURATION_H_ORIG} + @(cd ${.CURDIR} && rm -f ${BN_CONF_H_ORIG} ${CONFIGURATION_H_ORIG}) - @cd ${SRCTOP}/secure/lib/libcrypto && ${MAKE} cleanasm + @(cd ${SRCTOP}/secure/lib/libcrypto && \ + ${SETENVI} ${WRK_ENV} ${MAKE} cleanasm) - -@cd ${.CURDIR} && gmake ${.TARGET} + -@(cd ${.CURDIR} && ${GMAKE} ${.TARGET}) .include <sys.mk> diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index 5ea99ccbdb89..6ba632894ca7 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -122,15 +122,15 @@ resolvconf .. .. - media + media tags=package=runtime .. - mnt + mnt tags=package=runtime .. - net + net tags=package=autofs .. - proc mode=0555 + proc mode=0555 tags=package=runtime .. - rescue + rescue tags=package=rescue .. root mode=0750 .. diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 7d3a72f43fa1..19da845e962f 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -26,6 +26,8 @@ .. .. .. + samplerate + .. sqlite3 .. ucl diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc index f8f329842eb4..bebed0280596 100644 --- a/lib/atf/Makefile.inc +++ b/lib/atf/Makefile.inc @@ -24,6 +24,8 @@ # SUCH DAMAGE. # +PACKAGE= atf +LIB_PACKAGE= CFLAGS+= -DHAVE_CONFIG_H WARNS?= 3 diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile index 985a79b7dc03..4f4f7f12ec05 100644 --- a/lib/atf/libatf-c++/Makefile +++ b/lib/atf/libatf-c++/Makefile @@ -27,7 +27,6 @@ .include <src.opts.mk> .include <bsd.init.mk> -PACKAGE= tests LIB_CXX= atf-c++ PRIVATELIB= true SHLIB_MAJOR= 2 diff --git a/lib/atf/libatf-c++/tests/Makefile b/lib/atf/libatf-c++/tests/Makefile index dc052c19df67..839c6902d6b1 100644 --- a/lib/atf/libatf-c++/tests/Makefile +++ b/lib/atf/libatf-c++/tests/Makefile @@ -1,7 +1,5 @@ .include <bsd.init.mk> -PACKAGE= tests - TESTS_SUBDIRS= detail ATF= ${SRCTOP}/contrib/atf diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile index 4cfee2ed824f..c0890abc7640 100644 --- a/lib/atf/libatf-c/Makefile +++ b/lib/atf/libatf-c/Makefile @@ -27,7 +27,6 @@ .include <src.opts.mk> .include <bsd.init.mk> -PACKAGE= tests LIB= atf-c PRIVATELIB= true SHLIB_MAJOR= 1 diff --git a/lib/atf/libatf-c/tests/Makefile b/lib/atf/libatf-c/tests/Makefile index c81c18a91f00..5647e7b9fcbe 100644 --- a/lib/atf/libatf-c/tests/Makefile +++ b/lib/atf/libatf-c/tests/Makefile @@ -1,7 +1,5 @@ .include <bsd.init.mk> -PACKAGE= tests - TESTS_SUBDIRS= detail ATF= ${SRCTOP}/contrib/atf diff --git a/lib/libc/gdtoa/_hdtoa.c b/lib/libc/gdtoa/_hdtoa.c index 8ae739acf0db..9c42630cd918 100644 --- a/lib/libc/gdtoa/_hdtoa.c +++ b/lib/libc/gdtoa/_hdtoa.c @@ -40,6 +40,7 @@ #define DBL_ADJ (DBL_MAX_EXP - 2) #define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1) +#define MAX_HEX_DIGITS ((DBL_MANT_DIG + 3 - 1) / 4 + 1) static const float one[] = { 1.0f, -1.0f }; @@ -111,7 +112,7 @@ __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, s0 = rv_alloc(bufsize); /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { + if (MAX_HEX_DIGITS > ndigits && ndigits > 0) { float redux = one[u.bits.sign]; int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG; u.bits.exp = offset; diff --git a/lib/libc/gdtoa/_hldtoa.c b/lib/libc/gdtoa/_hldtoa.c index 965d2349d103..5f10d12c5c09 100644 --- a/lib/libc/gdtoa/_hldtoa.c +++ b/lib/libc/gdtoa/_hldtoa.c @@ -65,6 +65,7 @@ typedef uint32_t manl_t; #define LDBL_ADJ (LDBL_MAX_EXP - 2) #define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1) +#define MAX_HEX_DIGITS ((LDBL_MANT_DIG + 3 - 1) / 4 + 1) static const float one[] = { 1.0f, -1.0f }; @@ -125,7 +126,7 @@ __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign, s0 = rv_alloc(bufsize); /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { + if (MAX_HEX_DIGITS > ndigits && ndigits > 0) { float redux = one[u.bits.sign]; int offset = 4 * ndigits + LDBL_MAX_EXP - 4 - LDBL_MANT_DIG; #ifdef __i386__ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 26f638568efc..494b65bc5cc1 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -193,7 +193,6 @@ FBSD_1.0 { __isinff; __isinfl; isatty; - initgroups; jrand48; lcong48; ldexp; @@ -462,6 +461,7 @@ FBSD_1.8 { fdscandir_b; fts_open_b; glob_b; + initgroups; inotify_add_watch; inotify_init; inotify_init1; diff --git a/lib/libc/gen/gen-compat.h b/lib/libc/gen/gen-compat.h index 08e80ede6b6e..74678301af6f 100644 --- a/lib/libc/gen/gen-compat.h +++ b/lib/libc/gen/gen-compat.h @@ -52,4 +52,12 @@ int freebsd11_getmntinfo(struct freebsd11_statfs **, int); char *freebsd11_devname(__uint32_t dev, __mode_t type); char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, int len); +#define F14SG int freebsd14_setgroups(int gidsize, const __gid_t *gidset) +#ifdef PIC +static F14SG __attribute__((__weakref__("setgroups@FBSD_1.0"))); +#else +F14SG; +#endif +#undef F14SG + #endif /* _GEN_COMPAT_H_ */ diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3 index e9a980f99751..e3939fc2481a 100644 --- a/lib/libc/gen/getgrouplist.3 +++ b/lib/libc/gen/getgrouplist.3 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 26, 2014 +.Dd August 29, 2025 .Dt GETGROUPLIST 3 .Os .Sh NAME .Nm getgrouplist -.Nd calculate group access list +.Nd produce a user's effective group list .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,16 +48,16 @@ .Sh DESCRIPTION The .Fn getgrouplist -function reads through the group file and calculates -the group access list for the user specified in -.Fa name . -The +function reads through the group database to retrieve the supplementary groups +for the user specified in +.Fa name , +and returns the effective group list, whose first group is the value of +.Fa basegid +and the others are the retrieved supplementary groups. .Fa basegid -is automatically included in the groups list. -Typically this value is given as -the group number from the password file. +typically is the user's group number from the password database. .Pp -The resulting group list is returned in the array pointed to by +The effective group list is returned in the array pointed to by .Fa groups . The caller specifies the size of the .Fa groups @@ -70,6 +78,7 @@ Here, the group array will be filled with as many groups as will fit. group membership list .El .Sh SEE ALSO +.Xr setcred 2 , .Xr setgroups 2 , .Xr initgroups 3 .Sh HISTORY diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3 index 03bd07494fc9..4f538fb180ec 100644 --- a/lib/libc/gen/initgroups.3 +++ b/lib/libc/gen/initgroups.3 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 26, 2014 +.Dd September 17, 2025 .Dt INITGROUPS 3 .Os .Sh NAME .Nm initgroups -.Nd initialize group access list +.Nd initialize supplementary groups as per the group database .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,19 +48,18 @@ .Sh DESCRIPTION The .Fn initgroups -function -uses the -.Xr getgrouplist 3 -function to calculate the group access list for the user -specified in +function initializes the current process' supplementary groups as prescribed by +its arguments and the system's group database. +.Pp +It first uses the +.Fn getgrouplist +function to compute a list of groups containing the passed +.Fa basegid , +which typically is the user's initial numerical group ID from the password +database, and the supplementary groups in the group database for the user named .Fa name . -This group list is then setup for the current process using -.Xr setgroups 2 . -The -.Fa basegid -is automatically included in the groups list. -Typically this value is given as -the group number from the password file. +It then installs this list as the current process' supplementary groups using +.Fn setgroups . .Sh RETURN VALUES .Rv -std initgroups .Sh ERRORS @@ -60,7 +67,7 @@ The .Fn initgroups function may fail and set .Va errno -for any of the errors specified for the library function +to any of the errors specified for the library function .Xr setgroups 2 . It may also return: .Bl -tag -width Er @@ -77,3 +84,67 @@ The .Fn initgroups function appeared in .Bx 4.2 . +.Pp +The +.Fn initgroups +function changed semantics in +.Fx 15 , +following that of +.Xr setgroups 2 +in the same release. +Before that, it would also set the effective group ID to +.Fa basegid , +and would not include the latter in the supplementary groups except before +.Fx 8 . +Its current behavior in these respects is known to be compatible with that of +the following systems up to the specified versions that are current at time of +this writing: +.Bl -dash -width "-" -compact +.It +Linux (up to 6.6) with the GNU libc (up to 2.42) +.It +.Nx 1.1 and greater (up to 10) +.It +.Ox (up to 7.7) +.It +Systems based on illumos (up to August 2025 sources) +.El +.Sh SECURITY CONSIDERATIONS +As +.Fa basegid +is typically the user's initial numerical group ID, to which the current +process' effective group ID is generally initialized, processes using functions +to change their effective group ID +.Pq via Xr setgid 2 or similar +or that are spawned from executables with the set-group-ID mode bit set will not +be able to relinquish the access rights deriving from being a member of +.Fa basegid , +as these functions do not change the supplementary groups. +.Pp +This behavior is generally desirable in order to paper over the difference of +treatment between the effective group and supplementary ones in this situation, +as they are all in the end indiscriminately used in traditional UNIX +discretionary access checks. +It blends well with the practice of allocating each user its own private group, +as processes launched from a set-group-ID executable keep the same user and +consistently stay also in the same user's group. +Finally, it was also chosen for compatibility with other systems +.Po +see the +.Sx HISTORY +section +.Pc . +.Pp +This convention of including +.Fa basegid +in the supplementary groups is however only enforced by the +.Fn initgroups +function, and not by the +.Xr setgroups 2 +system call, so applications expressly wanting to include in the supplementary +groups only those specified by the group database can themselves call +.Fn getgrouplist +and then +.Fn setgroups +on the result with the first element skipped +.Pq see Xr getgrouplist 3 . diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c index b6697dd7ed8f..a1a7d92250e2 100644 --- a/lib/libc/gen/initgroups.c +++ b/lib/libc/gen/initgroups.c @@ -3,6 +3,11 @@ * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Olivier Certner + * <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD + * Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,34 +34,52 @@ * SUCH DAMAGE. */ -#include <sys/param.h> +/* For __sym_compat(). */ +#include <sys/cdefs.h> -#include "namespace.h" -#include <err.h> -#include "un-namespace.h" #include <errno.h> -#include <stdio.h> #include <stdlib.h> #include <unistd.h> -int -initgroups(const char *uname, gid_t agroup) +/* For freebsd14_setgroups(). */ +#include "gen-compat.h" + +static int +initgroups_impl(const char *uname, gid_t agroup, + int (*setgroups)(int, const gid_t *)) { - int ngroups, ret; - long ngroups_max; gid_t *groups; + long ngroups_max; + int ngroups, ret; /* - * Provide space for one group more than possible to allow - * setgroups to fail and set errno. + * Provide space for one group more than possible to allow setgroups() + * to fail and set 'errno' in case we get back more than {NGROUPS_MAX} + + * 1 groups. */ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2; - if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL) - return (ENOMEM); + groups = malloc(sizeof(*groups) * ngroups_max); + if (groups == NULL) + return (-1); /* malloc() set 'errno'. */ ngroups = (int)ngroups_max; - getgrouplist(uname, agroup, groups, &ngroups); - ret = setgroups(ngroups, groups); + (void)getgrouplist(uname, agroup, groups, &ngroups); + ret = (*setgroups)(ngroups, groups); + free(groups); - return (ret); + return (ret); /* setgroups() set 'errno'. */ } + +int +initgroups(const char *uname, gid_t agroup) +{ + return (initgroups_impl(uname, agroup, setgroups)); +} + +int +freebsd14_initgroups(const char *uname, gid_t agroup) +{ + return (initgroups_impl(uname, agroup, freebsd14_setgroups)); +} + +__sym_compat(initgroups, freebsd14_initgroups, FBSD_1.0); diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h index 97f22607ddd7..630ffe7daae3 100644 --- a/lib/libc/include/compat.h +++ b/lib/libc/include/compat.h @@ -80,4 +80,3 @@ __sym_compat(setgroups, freebsd14_setgroups, FBSD_1.0); #undef __weak_reference #endif /* __LIBC_COMPAT_H__ */ - diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c index 031859124163..4493fe1c15d3 100644 --- a/lib/libc/tests/stdio/printfloat_test.c +++ b/lib/libc/tests/stdio/printfloat_test.c @@ -398,6 +398,18 @@ ATF_TC_BODY(subnormal_float, tc) testfmt("-0X1P-149", "%A", negative); } +ATF_TC_WITHOUT_HEAD(hexadecimal_rounding_fullprec); +ATF_TC_BODY(hexadecimal_rounding_fullprec, tc) +{ + /* Double: %.13a with binary64 mantissa=53 */ + testfmt("0x1.1234567890bbbp+0", "%.13a", 0x1.1234567890bbbp+0); + +#if defined(__aarch64__) + /* On arm64, long double is IEEE binary128 (mantissa=113) */ + testfmt("0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0", "%.28La", 0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0L); +#endif +} + ATF_TP_ADD_TCS(tp) { @@ -414,6 +426,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, hexadecimal_rounding); ATF_TP_ADD_TC(tp, subnormal_double); ATF_TP_ADD_TC(tp, subnormal_float); + ATF_TP_ADD_TC(tp, hexadecimal_rounding_fullprec); return (atf_no_error()); } diff --git a/lib/libc/tests/tls/dso/Makefile b/lib/libc/tests/tls/dso/Makefile index 5efd8b29a6bd..783534ff7aae 100644 --- a/lib/libc/tests/tls/dso/Makefile +++ b/lib/libc/tests/tls/dso/Makefile @@ -6,6 +6,7 @@ SRCS= h_tls_dlopen.c MAN= PACKAGE= tests +NO_DEV_PACKAGE= LIBDIR= ${TESTSBASE}/lib/libc/tls SHLIB_MAJOR= 1 diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile index 89296c643695..7cb8f98b431e 100644 --- a/lib/libc/tests/tls_dso/Makefile +++ b/lib/libc/tests/tls_dso/Makefile @@ -7,6 +7,7 @@ LIBDIR= ${TESTSBASE}/lib/libc/tls SHLIBDIR= ${TESTSBASE}/lib/libc/tls SHLIB_MAJOR= 1 PACKAGE= tests +NO_DEV_PACKAGE= WITHOUT_STATIC= WITHOUT_PROFILE= diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h index 748f75ee157d..64da66e1cf6f 100644 --- a/lib/libexpat/expat_config.h +++ b/lib/libexpat/expat_config.h @@ -31,7 +31,7 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #define HAVE_FCNTL_H 1 -/* Define to 1 if you have the `getpagesize' function. */ +/* Define to 1 if you have the 'getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define to 1 if you have the `getrandom' function. */ @@ -40,10 +40,10 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #define HAVE_INTTYPES_H 1 -/* Define to 1 if you have the `bsd' library (-lbsd). */ +/* Define to 1 if you have the 'bsd' library (-lbsd). */ /* #undef HAVE_LIBBSD */ -/* Define to 1 if you have a working `mmap' system call. */ +/* Define to 1 if you have a working 'mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the <stdint.h> header file. */ @@ -89,7 +89,7 @@ #define PACKAGE_NAME "expat" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "expat 2.7.1" +#define PACKAGE_STRING "expat 2.7.2" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "expat" @@ -98,15 +98,15 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.7.1" +#define PACKAGE_VERSION "2.7.2" -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "2.7.1" +#define VERSION "2.7.2" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ @@ -140,10 +140,10 @@ /* Define to make XML Namespaces functionality available. */ #define XML_NS 1 -/* Define to empty if `const' does not conform to ANSI C. */ +/* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ -/* Define to `long int' if <sys/types.h> does not define. */ +/* Define to 'long int' if <sys/types.h> does not define. */ /* #undef off_t */ #endif // ndef EXPAT_CONFIG_H diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3 index c91184840b70..60aa64fba20d 100644 --- a/lib/libexpat/libbsdxml.3 +++ b/lib/libexpat/libbsdxml.3 @@ -34,7 +34,7 @@ .Sh DESCRIPTION The .Nm -library is a verbatim copy of the eXpat XML library version 2.7.1. +library is a verbatim copy of the eXpat XML library version 2.7.2. .Pp The .Nm diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 190ee46baf21..b96b973ddc7c 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -391,6 +391,8 @@ static const struct snl_attr_parser ap_getstatus[] = { { .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes }, { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array }, { .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array }, + { .type = PF_GS_NCOUNTERS, .off = _OUT(ncounters), .cb = snl_attr_get_counters }, + { .type = PF_GS_FRAGMENTS, .off = _OUT(fragments), .cb = snl_attr_get_uint64 }, }; SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getstatus); #undef _OUT @@ -429,6 +431,7 @@ pfctl_get_status_h(struct pfctl_handle *h) TAILQ_INIT(&status->lcounters); TAILQ_INIT(&status->fcounters); TAILQ_INIT(&status->scounters); + TAILQ_INIT(&status->ncounters); while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status)) diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index da16d5179ec0..dd76cab163b5 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -62,6 +62,8 @@ struct pfctl_status { struct pfctl_status_counters lcounters; struct pfctl_status_counters fcounters; struct pfctl_status_counters scounters; + struct pfctl_status_counters ncounters; + uint64_t fragments; uint64_t pcounters[2][2][2]; uint64_t bcounters[2][2]; }; diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index 1651cbc6820f..df77cabcd36b 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -1973,6 +1973,7 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) struct ucred ucred; gid_t *groups; size_t len; + unsigned int ngroups; assert(kd != NULL); assert(kp != NULL); @@ -1990,19 +1991,22 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) proc.p_ucred, kp->ki_pid); return (NULL); } - len = ucred.cr_ngroups * sizeof(gid_t); + ngroups = 1 + ucred.cr_ngroups; + len = ngroups * sizeof(gid_t); groups = malloc(len); if (groups == NULL) { warn("malloc(%zu)", len); return (NULL); } - if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) { + groups[0] = ucred.cr_gid; + if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups + 1, + len - sizeof(gid_t))) { warnx("can't read groups at %p for pid %d", ucred.cr_groups, kp->ki_pid); free(groups); return (NULL); } - *cntp = ucred.cr_ngroups; + *cntp = ngroups; return (groups); } diff --git a/lib/libsamplerate/Makefile b/lib/libsamplerate/Makefile index 256f2087284f..6ca87d8b20ca 100644 --- a/lib/libsamplerate/Makefile +++ b/lib/libsamplerate/Makefile @@ -1,7 +1,7 @@ .PATH: ${SRCTOP}/contrib/libsamplerate LIB= samplerate -INTERNALLIB= +PRIVATELIB= SRCS= samplerate.c \ src_linear.c \ diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3 index dcd9077798ea..015f9cd8fb44 100644 --- a/lib/libsdp/sdp.3 +++ b/lib/libsdp/sdp.3 @@ -24,7 +24,7 @@ .\" .\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $ .\" -.Dd April 30, 2018 +.Dd September 16, 2025 .Dt SDP 3 .Os .Sh NAME @@ -87,7 +87,7 @@ .Fn sdp_uuid2desc "uint16_t uuid" .Ft int32_t .Fo sdp_register_service -.Fa "void *xss" "uint16_t uuid" "bdaddr_p const bdaddr" "uint8_t const *data" +.Fa "void *xss" "uint16_t uuid" "const bdaddr_t *bdaddr" "uint8_t const *data" .Fa "uint32_t datalen" "uint32_t *handle" .Fc .Ft int32_t diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h index faad36aefca6..0c9474a70eff 100644 --- a/lib/libsdp/sdp.h +++ b/lib/libsdp/sdp.h @@ -702,7 +702,7 @@ typedef struct sdp_panu_profile sdp_panu_profile_t; typedef struct sdp_panu_profile * sdp_panu_profile_p; int32_t sdp_register_service (void *xss, uint16_t uuid, - bdaddr_p const bdaddr, uint8_t const *data, + const bdaddr_t *bdaddr, uint8_t const *data, uint32_t datalen, uint32_t *handle); int32_t sdp_unregister_service (void *xss, uint32_t handle); int32_t sdp_change_service (void *xss, uint32_t handle, diff --git a/lib/libsdp/service.c b/lib/libsdp/service.c index 9f07d1ba86ba..2cce6c133600 100644 --- a/lib/libsdp/service.c +++ b/lib/libsdp/service.c @@ -45,7 +45,7 @@ static int32_t sdp_receive_error_pdu(sdp_session_p ss); int32_t -sdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr, +sdp_register_service(void *xss, uint16_t uuid, const bdaddr_t *bdaddr, uint8_t const *data, uint32_t datalen, uint32_t *handle) { sdp_session_p ss = (sdp_session_p) xss; diff --git a/lib/libsys/getgroups.2 b/lib/libsys/getgroups.2 index 37c8fbad7215..4881a65d532e 100644 --- a/lib/libsys/getgroups.2 +++ b/lib/libsys/getgroups.2 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 1, 2025 +.Dd September 17, 2025 .Dt GETGROUPS 2 .Os .Sh NAME .Nm getgroups -.Nd get group access list +.Nd get the calling process' supplementary groups .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,36 +48,39 @@ .Sh DESCRIPTION The .Fn getgroups -system call -gets the current supplementary groups of the user process and stores it in the -array -.Fa gidset . -The +system call gets the calling process' supplementary groups and stores them in +the +.Fa gidset +array in strictly ascending order. +The value of .Fa gidsetlen -argument -indicates the number of entries that may be placed in +indicates the maximum number of entries that may be placed in .Fa gidset . -The -.Fn getgroups -system call -returns the actual number of groups returned in -.Fa gidset . -As many as {NGROUPS_MAX} values may be returned. +.Pp If .Fa gidsetlen is zero, .Fn getgroups -returns the number of supplementary group IDs associated with -the calling process without modifying the array pointed to by +returns the cardinal of the calling process' supplementary groups set and +ignores argument .Fa gidset . .Pp +No more than +.Dv {NGROUPS_MAX} +values may ever be returned. The value of .Dv {NGROUPS_MAX} should be obtained using .Xr sysconf 3 to avoid hard-coding it into the executable. .Sh RETURN VALUES -A successful call returns the number of groups in the group set. +On success, the +.Fn getgroups +system call returns the cardinal of the supplementary groups set. +It always succeeds if argument +.Fa gidsetlen +is zero. +.Pp A value of -1 indicates that an error occurred, and the error code is stored in the global variable .Va errno . @@ -81,12 +92,12 @@ are: .It Bq Er EINVAL The argument .Fa gidsetlen -is smaller than the number of groups in the group set. +is smaller than the number of supplementary groups +.Pq but not zero . .It Bq Er EFAULT -The argument +An invalid address was encountered while reading from the .Fa gidset -specifies -an invalid address. +array. .El .Sh SEE ALSO .Xr setgroups 2 , @@ -96,16 +107,51 @@ an invalid address. The .Fn getgroups system call conforms to -.St -p1003.1-2008 . +.St -p1003.1-2008 +with the additional properties that supplementary groups are reported in +strictly ascending order and the returned size coincides with the cardinal of +the set. .Sh HISTORY The .Fn getgroups system call appeared in .Bx 4.2 . .Pp +Since +.Fx 14.3 , +the +.Fn getgroups +system call has treated the supplementary groups as a set, reporting them in +strictly ascending order and returning the cardinal of the set. +.Pp Before .Fx 15.0 , the .Fn getgroups -system call always returned the effective group ID for the process as the first +system call would additionally return the effective group ID as the first element of the array, before the supplementary groups. +.Sh SECURITY CONSIDERATIONS +The +.Fn getgroups +system call gets the supplementary groups set in the +.Fa gidset +array. +In particular, as evoked in +.Sx HISTORY , +it does not anymore retrieve the effective GID in the first slot of +.Fa gidset . +Programs should not make any assumption about which group is placed in the first +slot of +.Fa gidset +other than it being the supplementary group with smallest GID. +.Pp +The effective GID is present in the supplementary groups set if and only if it +was explicitly set as a supplementary group. +The function +.Fn initgroups +enforces that, while the +.Fn setgroups +system call does not. +Please consult the +.Xr initgroups 3 +manual page for the rationale. diff --git a/lib/libsys/jail.2 b/lib/libsys/jail.2 index d3f871608c1d..ee4e5b03d38e 100644 --- a/lib/libsys/jail.2 +++ b/lib/libsys/jail.2 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 9, 2025 +.Dd September 15, 2025 .Dt JAIL 2 .Os .Sh NAME @@ -555,6 +555,9 @@ and call .Xr chroot 2 internally, so they can fail for all the same reasons. +In particular, they return the +.Bq Er EPERM +error when the process to join a jail has open directories. Please consult the .Xr chroot 2 manual page for details. diff --git a/lib/libsys/setcred.2 b/lib/libsys/setcred.2 index 86f61ddfdb30..f5d1f15b631b 100644 --- a/lib/libsys/setcred.2 +++ b/lib/libsys/setcred.2 @@ -6,7 +6,7 @@ .\" This documentation was written by Olivier Certner <olce.freebsd@certner.fr> .\" at Kumacom SARL under sponsorship from the FreeBSD Foundation. .\" -.Dd December 19, 2024 +.Dd August 29, 2025 .Dt SETCRED 2 .Os .Sh NAME @@ -119,11 +119,6 @@ It must be less than or equal to An array of IDs to set the supplementary groups to, if flag .Dv SETCREDF_SUPP_GROUPS is specified. -Note that all groups in this array will be set as supplementary groups only, in -contrast to -.Xr setgroups 2 -which treats the first element specially as the new effective group, not adding -it to supplementary groups. .It Fa sc_label A pointer to a valid MAC label structure, e.g., built with the .Xr mac_from_text 3 diff --git a/lib/libsys/setgroups.2 b/lib/libsys/setgroups.2 index 451f63ba1266..0ec99507cfb0 100644 --- a/lib/libsys/setgroups.2 +++ b/lib/libsys/setgroups.2 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 1, 2025 +.Dd September 17, 2025 .Dt SETGROUPS 2 .Os .Sh NAME .Nm setgroups -.Nd set group access list +.Nd set the calling process' supplementary groups .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -41,21 +49,21 @@ .Sh DESCRIPTION The .Fn setgroups -system call -sets the supplementary group list of the current user process -according to the array -.Fa gidset . +system call sets the calling process' supplementary groups according to the +.Fa gidset +array. The .Fa ngroups -argument -indicates the number of entries in the array and must be no -more than +argument indicates the number of entries in the array and must be no more than .Dv {NGROUPS_MAX} . +.Pp The .Fa ngroups -argument may be set to 0 to clear the supplementary group list. +argument may be set to zero to clear all supplementary groups, in which case +.Fa gidset +is ignored. .Pp -Only the super-user may set a new supplementary group list. +Only the super-user may install a new supplementary groups set. .Sh RETURN VALUES .Rv -std setgroups .Sh ERRORS @@ -69,16 +77,16 @@ The caller is not the super-user. The number specified in the .Fa ngroups argument is larger than the -.Dv {NGROUPS_MAX}+1 +.Dv {NGROUPS_MAX} limit. .It Bq Er EFAULT -The address specified for +Part of the groups array starting at .Fa gidset -is outside the process -address space. +is outside the process address space. .El .Sh SEE ALSO .Xr getgroups 2 , +.Xr setcred 2 , .Xr initgroups 3 .Sh HISTORY The @@ -92,4 +100,63 @@ the .Fn setgroups system call would set the effective group ID for the process to the first element of -.Fa gidset . +.Fa gidset , +and only the other elements as supplementary groups. +Despite treating the first element as the effective group ID to set, it accepted +an empty +.Fa gidset +.Po +.Fa ngroups +being zero +.Pc +as a stance requiring to drop all supplementary groups, leaving the effective +group ID unchanged. +.Sh SECURITY CONSIDERATIONS +The +.Fn setgroups +system call sets the process' supplementary groups to those contained in the +.Fa gidset +array. +In particular, as evoked in +.Sx HISTORY , +it does not anymore treat the first element of +.Fa gidset +separately. +Formerly, it would set it as the effective group ID while only the others were +used as supplementary groups. +.Pp +Programs solely relying on +.Fn setgroups +to change the effective group ID must be modified, e.g., to also call +.Xr setegid 2 +or to instead use +.Xr setcred 2 , +else they will unwillingly keep their effective group ID. +.Pp +Programs using +.Fn setgroups +with the effective group ID as the first element of array +.Fa gidset +and not duplicating it in the rest of the array, which includes those using +.Fn initgroups , +now insert this group ID in the supplementary groups set. +This is in general desirable, as explained in the +.Xr initgroups 3 +manual page, and has the consequence that subsequent process' effective group +ID's changes do not remove membership of the original effective group ID, since +these changes do not affect the supplementary groups. +Applications that expressly do not want that must be modified to stop passing +the effective group ID as the first element to +.Fn setgroups . +.Pp +To clear all the calling process' supplementary groups, always use the statement +.Bd -literal -offset indent +setgroups(0, NULL); +.Ed +.Pp +which works also on older FreeBSD version +.Po +see the +.Sx HISTORY +section +.Pc . diff --git a/lib/libxo/tests/encoder/Makefile b/lib/libxo/tests/encoder/Makefile index 7522328b0818..02634b971ace 100644 --- a/lib/libxo/tests/encoder/Makefile +++ b/lib/libxo/tests/encoder/Makefile @@ -1,4 +1,5 @@ PACKAGE= tests +NO_DEV_PACKAGE= LIBXOSRC= ${SRCTOP}/contrib/libxo diff --git a/libexec/atf/Makefile.inc b/libexec/atf/Makefile.inc index 42c507a6f772..e40827fa0b69 100644 --- a/libexec/atf/Makefile.inc +++ b/libexec/atf/Makefile.inc @@ -24,6 +24,8 @@ # SUCH DAMAGE. # +PACKAGE= atf +LIB_PACKAGE= CFLAGS+= -DHAVE_CONFIG_H WARNS?= 3 diff --git a/libexec/atf/atf-check/Makefile b/libexec/atf/atf-check/Makefile index 87d7a7cfdada..cf598e384c86 100644 --- a/libexec/atf/atf-check/Makefile +++ b/libexec/atf/atf-check/Makefile @@ -30,7 +30,6 @@ ATF= ${SRCTOP}/contrib/atf .PATH: ${ATF}/atf-sh -PACKAGE= tests PROG_CXX= atf-check SRCS= atf-check.cpp MAN= atf-check.1 diff --git a/libexec/atf/atf-pytest-wrapper/Makefile b/libexec/atf/atf-pytest-wrapper/Makefile index 80b5e411ec4e..75b1bc3e1004 100644 --- a/libexec/atf/atf-pytest-wrapper/Makefile +++ b/libexec/atf/atf-pytest-wrapper/Makefile @@ -1,7 +1,6 @@ .include <src.opts.mk> .include <bsd.init.mk> -PACKAGE= tests PROG_CXX= atf_pytest_wrapper SRCS= atf_pytest_wrapper.cpp MAN= diff --git a/libexec/atf/atf-sh/Makefile b/libexec/atf/atf-sh/Makefile index 2e821684d8a8..afd848581f36 100644 --- a/libexec/atf/atf-sh/Makefile +++ b/libexec/atf/atf-sh/Makefile @@ -30,7 +30,6 @@ ATF= ${SRCTOP}/contrib/atf .PATH: ${ATF}/atf-sh -PACKAGE= tests PROG_CXX= atf-sh SRCS= atf-sh.cpp MAN= atf-sh.1 atf-sh.3 diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 0ef3012892dd..1220d060232d 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -586,11 +586,11 @@ font8x14="NO" # font 8x14 from /usr/share/{syscons,vt}/fonts/* (or NO). font8x8="NO" # font 8x8 from /usr/share/{syscons,vt}/fonts/* (or NO). blanktime="300" # blank time (in seconds) or "NO" to turn it off. saver="NO" # screen saver: Uses /boot/kernel/${saver}_saver.ko -moused_nondefault_enable="NO" # Treat non-default mice as enabled unless +moused_nondefault_enable="YES" # Treat non-default mice as enabled unless # specifically overridden in rc.conf(5). moused_enable="NO" # Run the mouse daemon. -moused_type="auto" # See man page for rc.conf(5) for available settings. -moused_port="auto" # Set to your mouse port. +moused_type="evdev" # See man page for rc.conf(5) for available settings. +moused_port="/dev/psm0" # Set to your mouse port. moused_flags="" # Any additional flags to moused. mousechar_start="NO" # if 0xd0-0xd3 default range is occupied in your # language code table, specify alternative range diff --git a/libexec/rc/rc.d/moused b/libexec/rc/rc.d/moused index aaf0dd0890a8..35a26bd57275 100755 --- a/libexec/rc/rc.d/moused +++ b/libexec/rc/rc.d/moused @@ -16,6 +16,7 @@ start_cmd="moused_start" pidprefix="/var/run/moused" pidfile="${pidprefix}.pid" pidarg= +typearg= load_rc_config $name # doesn't make sense to run in a svcj: nojail keyword @@ -27,9 +28,10 @@ moused_svcj="NO" # expected to be the mouse device. # if [ -n "$2" ]; then - eval moused_$2_enable=\${moused_$2_enable-${moused_nondefault_enable}} - rcvar="moused_${2}_enable" - pidfile="${pidprefix}.$2.pid" + ms=`basename $2` + eval moused_${ms}_enable=\${moused_${ms}_enable-${moused_nondefault_enable}} + rcvar="moused_${ms}_enable" + pidfile="${pidprefix}.${ms}.pid" pidarg="-I $pidfile" fi @@ -44,20 +46,22 @@ moused_start() # the moused_port variable, which if not defined sets it to the # passed in device name. # - ms=$1 + ms=`basename $1` if [ -n "$ms" ]; then eval myflags=\${moused_${ms}_flags-$moused_flags} - eval myport=\${moused_${ms}_port-/dev/$ms} + eval myport=\${moused_${ms}_port-/dev/$1} eval mytype=\${moused_${ms}_type-$moused_type} + if [ -n "$mytype" ] && check_kern_features evdev_support; then + typearg="-t ${mytype}" + fi else ms="default" myflags="$moused_flags" myport="$moused_port" - mytype="$moused_type" fi startmsg -n "Starting ${ms} moused" - /usr/sbin/moused ${myflags} -p ${myport} -t ${mytype} ${pidarg} + /usr/sbin/moused ${myflags} -p ${myport} ${typearg} ${pidarg} startmsg '.' mousechar_arg= diff --git a/libexec/rtld-elf/tests/Makefile.inc b/libexec/rtld-elf/tests/Makefile.inc index 01cf83634239..3bd0b8590cdc 100644 --- a/libexec/rtld-elf/tests/Makefile.inc +++ b/libexec/rtld-elf/tests/Makefile.inc @@ -1,2 +1,3 @@ PACKAGE?= tests +NO_DEV_PACKAGE= TESTSDIR?= ${TESTSBASE}/libexec/rtld-elf diff --git a/release/Makefile b/release/Makefile index 6be29a425f0f..b4da9c68eca1 100644 --- a/release/Makefile +++ b/release/Makefile @@ -22,7 +22,7 @@ # WORLDDIR: location of src tree -- must have built world and default kernel # (by default, the directory above this one) # NODISTSETS: if set, do not include dist sets or MANIFEST -# PKGBASE: if set, include pkgbase packages rather than dist tarballs in +# NOPKGBASE: if set, include dist tarballs rather than pkgbase packages in # disc1 and dvd1 installation media # PORTSDIR: location of ports tree to distribute (default: /usr/ports) # XTRADIR: xtra-bits-dir argument for <arch>/mkisoimages.sh @@ -128,7 +128,7 @@ CLEANFILES+= ${I}.xz .if defined(WITH_DVD) && !empty(WITH_DVD) CLEANFILES+= pkg-stage .endif -CLEANDIRS= dist pkgbase-repo pkgbase-repo-conf ftp disc1 disc1-disc1 disc1-memstick bootonly bootonly-bootonly bootonly-memstick dvd +CLEANDIRS= dist pkgdb pkgbase-repo pkgbase-repo-conf ftp disc1 disc1-disc1 disc1-memstick bootonly bootonly-bootonly bootonly-memstick dvd beforeclean: chflags -R noschg . .include <bsd.obj.mk> @@ -188,14 +188,16 @@ bootonly: packagesystem dvd: packagesystem .endif -.if defined(PKGBASE) +.if !defined(NOPKGBASE) || empty(NOPKGBASE) PKGBASE_REPO= pkgbase-repo PKG_ABI= $$(${PKG_CMD} -o ABI_FILE=${.TARGET}/usr/bin/uname config ABI) .endif pkgbase-repo: mkdir -p pkgbase-repo - ( ${IMAKE} -C ${WORLDDIR} packages REPODIR=${.OBJDIR}/pkgbase-repo ) + mkdir -p /tmp/ports /tmp/distfiles + ( ${IMAKE} -C ${WORLDDIR} packages REPODIR=${.OBJDIR}/pkgbase-repo \ + INCLUDE_PKG_IN_PKGBASE_REPO=YES BOOTSTRAP_PKG_FROM_PORTS=YES ) disc1: ${PKGBASE_REPO} # Install system @@ -207,7 +209,7 @@ disc1: ${PKGBASE_REPO} MK_TOOLCHAIN=no \ MK_RESCUE=no MK_DICT=no \ MK_KERNEL_SYMBOLS=no MK_TESTS=no MK_DEBUG_FILES=no) -.if defined(PKGBASE) +.if !defined(NOPKGBASE) || empty(NOPKGBASE) # Create offline pkgbase repo on release media mkdir -p ${.TARGET}/usr/freebsd-packages/repos/ ${.CURDIR}/scripts/pkgbase-stage.lua disc \ @@ -226,7 +228,7 @@ disc1: ${PKGBASE_REPO} echo "./usr/freebsd-dist type=dir uname=root gname=wheel mode=0755" >> ${.TARGET}/METALOG cp MANIFEST ${.TARGET}/usr/freebsd-dist echo "./usr/freebsd-dist/MANIFEST type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG -.if !defined(PKGBASE) +.if defined(NOPKGBASE) && !empty(NOPKGBASE) # Copy distfiles for dist in $$(ls *.txz | grep -v container | grep -vE -- '(${base ${_ALL_libcompats}:L:ts|})-dbg'); do \ cp $${dist} ${.TARGET}/usr/freebsd-dist; \ @@ -303,13 +305,13 @@ dvd: ${PKGBASE_REPO} ( cd ${WORLDDIR} && ${IMAKE} installworld installkernel distribution \ DESTDIR=${.OBJDIR}/${.TARGET} MK_RESCUE=no MK_KERNEL_SYMBOLS=no \ MK_TESTS=no MK_DEBUG_FILES=no) -.if defined(PKGBASE) +.if !defined(NOPKGBASE) || empty(NOPKGBASE) # Create offline pkgbase repo on release media mkdir -p ${.TARGET}/usr/freebsd-packages/repos/ ${.CURDIR}/scripts/pkgbase-stage.lua dvd \ ${.OBJDIR}/pkgbase-repo/${PKG_ABI}/latest \ ${.TARGET}/usr/freebsd-packages/offline \ - "${_ALL_libcompats}" + "${_ALL_libcompats}" ${PKG_ABI} cp ${.CURDIR}/scripts/FreeBSD-base-offline.conf \ ${.TARGET}/usr/freebsd-packages/repos/ mtree -c -p ${.TARGET}/usr/freebsd-packages | \ @@ -322,7 +324,6 @@ dvd: ${PKGBASE_REPO} echo "./usr/freebsd-dist type=dir uname=root gname=wheel mode=0755" >> ${.TARGET}/METALOG cp MANIFEST ${.TARGET}/usr/freebsd-dist echo "./usr/freebsd-dist/MANIFEST type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG -.if !defined(PKGBASE) # Copy distfiles mkdir -p ${.TARGET}/usr/freebsd-dist for dist in $$(ls *.txz | grep -v container); do \ @@ -330,7 +331,6 @@ dvd: ${PKGBASE_REPO} echo "./usr/freebsd-dist/$${dist} type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG; \ done .endif -.endif .if ${.MAKE.OS} == "FreeBSD" && (!defined(NOPKG) || empty(NOPKG)) # Install packages onto release media. ${PKG_INSTALL} pkg || true diff --git a/release/Makefile.oci b/release/Makefile.oci index a6f998002f92..16c475937d15 100644 --- a/release/Makefile.oci +++ b/release/Makefile.oci @@ -3,7 +3,7 @@ # .if defined(WITH_OCIIMAGES) && !empty(WITH_OCIIMAGES) -OCI_IMAGES= static dynamic runtime +OCI_IMAGES= static dynamic runtime notoolchain toolchain .endif oci-install: @@ -16,8 +16,10 @@ oci-install: OCI_TARGETS= OCI_DEPS_static= -OCI_DEPS_dynamic= container-image-static.txz -OCI_DEPS_runtime= container-image-dynamic.txz +OCI_DEPS_dynamic=container-image-static.txz +OCI_DEPS_runtime=container-image-dynamic.txz +OCI_DEPS_notoolchain=container-image-runtime.txz +OCI_DEPS_toolchain=container-image-notoolchain.txz .for _IMG in ${OCI_IMAGES} OCI_TARGETS+= container-image-${_IMG}.txz diff --git a/release/Makefile.vm b/release/Makefile.vm index 8375650cd9aa..25c37ade1121 100644 --- a/release/Makefile.vm +++ b/release/Makefile.vm @@ -138,6 +138,9 @@ cw-${_CW:tl}-${_FS}-${_FMT}: ${QEMUTGT} EC2BASEIMG=${.OBJDIR}/${EC2-BASE${_FS:tu}${_FMT:tu}IMAGE} \ ${WITHOUT_QEMU:DWITHOUT_QEMU=true} \ ${NO_ROOT:DNO_ROOT=true} \ + PKG_CMD=${PKG_CMD:Upkg} \ + PKG_REPOS_DIR=${PKG_REPOS_DIR:U${.OBJDIR}/${.TARGET}/etc/pkg} \ + PKG_REPO_NAME=${PKG_REPO_NAME:UFreeBSD-ports} \ PKG_INSTALL_EPOCH=${PKG_INSTALL_EPOCH:U${GITEPOCH}} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \ @@ -191,6 +194,9 @@ vm-image: ${QEMUTGT} QEMUSTATIC=${QEMUSTATIC} \ ${WITHOUT_QEMU:DWITHOUT_QEMU=true} \ ${NO_ROOT:DNO_ROOT=true} \ + PKG_CMD=${PKG_CMD:Upkg} \ + PKG_REPOS_DIR=${PKG_REPOS_DIR:U${.OBJDIR}/${.TARGET}-${FORMAT}-${FS}/etc/pkg} \ + PKG_REPO_NAME=${PKG_REPO_NAME:UFreeBSD-ports} \ PKG_INSTALL_EPOCH=${PKG_INSTALL_EPOCH:U${GITEPOCH}} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr \ diff --git a/release/packages/create-sets.sh b/release/packages/create-sets.sh index 6c034834672e..8c564ecfeb92 100755 --- a/release/packages/create-sets.sh +++ b/release/packages/create-sets.sh @@ -25,10 +25,12 @@ for pkg in "$repodir"/*.pkg; do set -- $(pkg query -F "$pkg" '%At %n %Av' | grep '^set ') pkgname="$2" - set="$3" - SETS="$SETS $set" - setvar="$(echo "$set" | tr - _)" - eval PKGS_${setvar}=\"\$PKGS_${setvar} $pkgname\" + sets="$(echo "$3" | tr , ' ')" + for set in $sets; do + SETS="$SETS $set" + setvar="$(echo "$set" | tr - _)" + eval PKGS_${setvar}=\"\$PKGS_${setvar} $pkgname\" + done done for set in $(echo $SETS | tr ' ' '\n' | sort | uniq); do diff --git a/release/packages/generate-ucl.lua b/release/packages/generate-ucl.lua index 47f0a0e9a6a9..ea3743894740 100755 --- a/release/packages/generate-ucl.lua +++ b/release/packages/generate-ucl.lua @@ -166,12 +166,14 @@ if add_gen_dep(pkgname, pkggenname) then end -- --- Handle the 'set' annotation. +-- Handle the 'set' annotation, a comma-separated list of sets which this +-- package should be placed in. If it's not specified, the package goes +-- in the default set which is base. -- -- Ensure we have an annotations table to work with. obj["annotations"] = obj["annotations"] or {} -- If no set is provided, use the default set which is "base". -set = obj["annotations"]["set"] or "base" +sets = obj["annotations"]["set"] or "base" -- For subpackages, we may need to rewrite the set name. This is done a little -- differently from the normal pkg suffix processing, because we don't need sets -- to be as a granular as the base packages. @@ -181,23 +183,32 @@ set = obj["annotations"]["set"] or "base" -- However, lib32 debug symbols still go into their own package since they're -- quite large. if pkgname:match("%-dbg%-lib32$") then - set = "lib32-dbg" + sets = "lib32-dbg" elseif pkgname:match("%-lib32$") then - set = "lib32" + sets = "lib32" -- If this is a -dev package, put it in a single set called "devel" which -- contains all development files. Also include lib*-man packages, which -- contain manpages for libraries. Having a separate <set>-dev for every -- set is not necessary, because generally you either want development -- support or you don't. elseif pkgname:match("%-dev$") or pkgname:match("^lib.*%-man$") then - set = "devel" --- If this is a -dbg package, it goes in <set>-dbg, which means the user can --- install debug symbols only for the sets they have installed. + sets = "devel" +-- Don't separate tests and tests-dbg into 2 sets, if the user wants tests +-- they should be able to debug failures. +elseif sets == "tests" then + sets = sets +-- If this is a -dbg package, put it in the -dbg subpackage of each set, +-- which means the user can install debug symbols only for the sets they +-- have installed. elseif pkgname:match("%-dbg$") then - set = set .. "-dbg" + local newsets = {} + for set in sets:gmatch("[^,]+") do + newsets[#newsets + 1] = set .. "-dbg" + end + sets = table.concat(newsets, ",") end --- Put our new set back into the package. -obj["annotations"]["set"] = set +-- Put our new sets back into the package. +obj["annotations"]["set"] = sets -- If PKG_NAME_PREFIX is provided, rewrite the names of dependency packages. -- We can't do this in UCL since variable substitution doesn't work in array diff --git a/release/packages/sets/base.ucl b/release/packages/sets/base.ucl index 42dd2095f808..2d94ff4f4f2e 100644 --- a/release/packages/sets/base.ucl +++ b/release/packages/sets/base.ucl @@ -1,5 +1,7 @@ comment = "Base system (metapackage)" +vital = true + desc = <<EOD This metapackage installs all packages which are part of the base system. EOD diff --git a/release/packages/sets/devel-dbg.ucl b/release/packages/sets/devel-dbg.ucl index 5da492b93750..c3fcd9806272 100644 --- a/release/packages/sets/devel-dbg.ucl +++ b/release/packages/sets/devel-dbg.ucl @@ -1,4 +1,4 @@ -comment = "Developments tools debugging symbols (metapackage)" +comment = "Development tools debugging symbols (metapackage)" desc = <<EOD This metapackage installs debugging symbols for the base system compiler and diff --git a/release/packages/sets/devel.ucl b/release/packages/sets/devel.ucl index ac6b6bab7ef8..08914a85a5b4 100644 --- a/release/packages/sets/devel.ucl +++ b/release/packages/sets/devel.ucl @@ -1,4 +1,6 @@ -comment = "Developments tools (metapackage)" +comment = "Development tools (metapackage)" + +vital = true desc = <<EOD This metapackage installs development support for the base system, including diff --git a/release/packages/sets/lib32.ucl b/release/packages/sets/lib32.ucl index c1b921c30b2e..b23ae15d00ae 100644 --- a/release/packages/sets/lib32.ucl +++ b/release/packages/sets/lib32.ucl @@ -1,5 +1,7 @@ comment = "32-bit compatibility libraries (metapackage)" +vital = true + desc = <<EOD This metapackage installs compatibility libraries required for building and running 32-bit applications on a 64-bit host system. diff --git a/release/packages/sets/minimal-jail-dbg.ucl b/release/packages/sets/minimal-jail-dbg.ucl new file mode 100644 index 000000000000..3f7df227d3a9 --- /dev/null +++ b/release/packages/sets/minimal-jail-dbg.ucl @@ -0,0 +1,6 @@ +comment = "Basic multi-user jail debugging symbols (metapackage)" + +desc = <<EOD +This metapackage installs debugging symbols for the packages required to bring +up a basic multi-user jail. +EOD diff --git a/release/packages/sets/minimal-jail.ucl b/release/packages/sets/minimal-jail.ucl new file mode 100644 index 000000000000..04e71912898c --- /dev/null +++ b/release/packages/sets/minimal-jail.ucl @@ -0,0 +1,8 @@ +comment = "Basic multi-user jail system (metapackage)" + +vital = true + +desc = <<EOD +This metapackage installs the packages required to bring up a basic multi-user +jail. This is equivalent to the minimal set, but without hardware support. +EOD diff --git a/release/packages/sets/minimal.ucl b/release/packages/sets/minimal.ucl index 0895f198824e..f2338f4c2e3b 100644 --- a/release/packages/sets/minimal.ucl +++ b/release/packages/sets/minimal.ucl @@ -1,5 +1,7 @@ comment = "Basic multi-user system (metapackage)" +vital = true + desc = <<EOD This metapackage installs the packages required to bring up a basic multi-user system. diff --git a/release/packages/sets/src.ucl b/release/packages/sets/src.ucl new file mode 100644 index 000000000000..7ab94eb420df --- /dev/null +++ b/release/packages/sets/src.ucl @@ -0,0 +1,7 @@ +comment = "System source code" + +vital = yes + +desc = <<EOD +This metapackage installs source code for the base system and kernel. +EOD diff --git a/release/packages/sets/tests.ucl b/release/packages/sets/tests.ucl new file mode 100644 index 000000000000..07b463fb7d69 --- /dev/null +++ b/release/packages/sets/tests.ucl @@ -0,0 +1,7 @@ +comment = "System test suite" + +vital = yes + +desc = <<EOD +This metapackage installs the system test suite. +EOD diff --git a/release/packages/ucl/at-all.ucl b/release/packages/ucl/at-all.ucl index 3e837d781d38..dc7592db39ce 100644 --- a/release/packages/ucl/at-all.ucl +++ b/release/packages/ucl/at-all.ucl @@ -4,5 +4,5 @@ AT Utilities EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/atf-all.ucl b/release/packages/ucl/atf-all.ucl new file mode 100644 index 000000000000..de8cd55eeb9f --- /dev/null +++ b/release/packages/ucl/atf-all.ucl @@ -0,0 +1,8 @@ +comment = "Automated Testing Framework" + +desc = <<EOD +The Automated Testing Framework (ATF) is a collection of libraries to implement +test programs in a variety of languages. These libraries all offer similar +functionality and any test program written with them exposes a consistent user +interface. +EOD diff --git a/release/packages/ucl/caroot-all.ucl b/release/packages/ucl/caroot-all.ucl index f62f4ff2be37..bd5b5eef5b48 100644 --- a/release/packages/ucl/caroot-all.ucl +++ b/release/packages/ucl/caroot-all.ucl @@ -4,5 +4,5 @@ SSL Certificates EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/certctl-all.ucl b/release/packages/ucl/certctl-all.ucl index 0e3dd49d7b00..f48144ecaef9 100644 --- a/release/packages/ucl/certctl-all.ucl +++ b/release/packages/ucl/certctl-all.ucl @@ -4,5 +4,5 @@ SSL Certificate Utility EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/clibs-all.ucl b/release/packages/ucl/clibs-all.ucl index 65353d515403..1a2374ab3f84 100644 --- a/release/packages/ucl/clibs-all.ucl +++ b/release/packages/ucl/clibs-all.ucl @@ -5,5 +5,5 @@ Core C Libraries EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/cron-all.ucl b/release/packages/ucl/cron-all.ucl index 39bd69b0ba4b..6b781c64f991 100644 --- a/release/packages/ucl/cron-all.ucl +++ b/release/packages/ucl/cron-all.ucl @@ -4,5 +4,5 @@ cron(8) and crontab(1) EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/fetch-all.ucl b/release/packages/ucl/fetch-all.ucl index 5c488cc1d865..c5754d6ecd80 100644 --- a/release/packages/ucl/fetch-all.ucl +++ b/release/packages/ucl/fetch-all.ucl @@ -6,5 +6,5 @@ HTTP or FTP. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/inetd-all.ucl b/release/packages/ucl/inetd-all.ucl index 5a6bb05f1675..3093a3fc2c51 100644 --- a/release/packages/ucl/inetd-all.ucl +++ b/release/packages/ucl/inetd-all.ucl @@ -7,5 +7,5 @@ built-in servers for basic services are also provided. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/kernel-man.ucl b/release/packages/ucl/kernel-man.ucl index 9d70baf2c3af..e4c376379fe3 100644 --- a/release/packages/ucl/kernel-man.ucl +++ b/release/packages/ucl/kernel-man.ucl @@ -1,5 +1,10 @@ comment = "Kernel manual pages" + desc = <<EOD Manual pages for kernel interfaces and drivers (section 4) and the kernel developer manual pages (section 9). EOD + +annotations { + set = "minimal" +} diff --git a/release/packages/ucl/kyua-all.ucl b/release/packages/ucl/kyua-all.ucl new file mode 100644 index 000000000000..4a669041f7e9 --- /dev/null +++ b/release/packages/ucl/kyua-all.ucl @@ -0,0 +1,20 @@ +comment = "Testing framework for infrastructure software" + +desc = <<EOD +Kyua is a testing framework for infrastructure software, originally designed +to equip BSD-based operating systems with a test suite. This means that Kyua +is lightweight and simple, and that Kyua integrates well with various build +systems and continuous integration frameworks. + +Kyua features an expressive test suite definition language, a safe runtime +engine for test suites and a powerful report generation engine. + +Kyua is for both developers and users, from the developer applying a simple +fix to a library to the system administrator deploying a new release on a +production machine. + +Kyua is able to execute test programs written with a plethora of testing +libraries and languages. The test program library of choice is ATF, which +kyua's design originated from. However, framework-less test programs and +TAP-compliant test programs can also be executed through kyua. +EOD diff --git a/release/packages/ucl/locales-all.ucl b/release/packages/ucl/locales-all.ucl index 78a15501d493..9018fb5c3c75 100644 --- a/release/packages/ucl/locales-all.ucl +++ b/release/packages/ucl/locales-all.ucl @@ -5,5 +5,5 @@ Provides the locale definitions (LC_*) for supported locales. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/mandoc-all.ucl b/release/packages/ucl/mandoc-all.ucl new file mode 100644 index 000000000000..9c43e9f7a46c --- /dev/null +++ b/release/packages/ucl/mandoc-all.ucl @@ -0,0 +1,11 @@ +comment = "Online manual page reader" + +desc = <<EOD +This packages provides man(1), a utility which can format and display system +manual pages, along with the related utilities apropos(1) and makewhatis(8), +and the mandoc(1) backend. +EOD + +annotations { + set = minimal +} diff --git a/release/packages/ucl/newsyslog-all.ucl b/release/packages/ucl/newsyslog-all.ucl index 824a5d62f587..1701ecbccc4d 100644 --- a/release/packages/ucl/newsyslog-all.ucl +++ b/release/packages/ucl/newsyslog-all.ucl @@ -6,5 +6,5 @@ create log files in /var/log and periodically rotate existing log files. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/periodic-all.ucl b/release/packages/ucl/periodic-all.ucl index b1b3e47ec10a..75b286963328 100644 --- a/release/packages/ucl/periodic-all.ucl +++ b/release/packages/ucl/periodic-all.ucl @@ -7,5 +7,5 @@ the base periodic tasks for the base system. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/pkg-bootstrap-all.ucl b/release/packages/ucl/pkg-bootstrap-all.ucl index 47b28ba1d374..2a5bc560140e 100644 --- a/release/packages/ucl/pkg-bootstrap-all.ucl +++ b/release/packages/ucl/pkg-bootstrap-all.ucl @@ -7,5 +7,5 @@ the FreeBSD.org package repository. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/rc-all.ucl b/release/packages/ucl/rc-all.ucl index 1d5a1b9b728d..5f9f155c4db6 100644 --- a/release/packages/ucl/rc-all.ucl +++ b/release/packages/ucl/rc-all.ucl @@ -7,5 +7,5 @@ the service scripts for the base system. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/runtime-all.ucl b/release/packages/ucl/runtime-all.ucl index 7635248dd76e..6f8da8e584c2 100644 --- a/release/packages/ucl/runtime-all.ucl +++ b/release/packages/ucl/runtime-all.ucl @@ -6,5 +6,5 @@ required for basic multi-user operation. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/src-all.ucl b/release/packages/ucl/src-all.ucl index 15b2b7d5b29d..d41d9b5fee1a 100644 --- a/release/packages/ucl/src-all.ucl +++ b/release/packages/ucl/src-all.ucl @@ -3,3 +3,7 @@ desc = <<EOD The source code used to rebuild the system, located in /usr/src. This package includes everything except the kernel source code. EOD + +annotations { + set = src +} diff --git a/release/packages/ucl/src-sys-all.ucl b/release/packages/ucl/src-sys-all.ucl index 9b1c5b64bfbb..4912ea870658 100644 --- a/release/packages/ucl/src-sys-all.ucl +++ b/release/packages/ucl/src-sys-all.ucl @@ -3,3 +3,7 @@ desc = <<EOD The source code used to rebuild the system, located in /usr/src. This package includes the kernel source code. EOD + +annotations { + set = src +} diff --git a/release/packages/ucl/syslogd-all.ucl b/release/packages/ucl/syslogd-all.ucl index 0f174ef7401d..f77b12c9752a 100644 --- a/release/packages/ucl/syslogd-all.ucl +++ b/release/packages/ucl/syslogd-all.ucl @@ -6,5 +6,5 @@ writes them to an appropriate log file. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/tests-all.ucl b/release/packages/ucl/tests-all.ucl index 39bd365bee5b..9aefbd0205f6 100644 --- a/release/packages/ucl/tests-all.ucl +++ b/release/packages/ucl/tests-all.ucl @@ -1,4 +1,31 @@ -comment = "Test Suite" +comment = "Test suite" + desc = <<EOD -Test Suite +The test suite, installed in /usr/tests, allows the functionality of the +installed system to be verified. EOD + +deps { + # Nearly all the tests require atf to run. + "atf": { + version = "${VERSION}" + origin = "base" + }, + + # The test framework requires Kyua. + "kyua": { + version = "${VERSION}" + origin = "base" + }, + + # Since the purpose of the tests is to test the base system, the base + # system must be installed. + "set-base": { + version = "${VERSION}" + origin = "base" + } +} + +annotations { + set = tests +} diff --git a/release/packages/ucl/utilities-all.ucl b/release/packages/ucl/utilities-all.ucl index 6e83b6584c02..8a6eeabd3396 100644 --- a/release/packages/ucl/utilities-all.ucl +++ b/release/packages/ucl/utilities-all.ucl @@ -5,5 +5,5 @@ Non-vital programs and libraries EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/vi-all.ucl b/release/packages/ucl/vi-all.ucl index 4504281e0549..7b79ee428113 100644 --- a/release/packages/ucl/vi-all.ucl +++ b/release/packages/ucl/vi-all.ucl @@ -6,5 +6,5 @@ text editor, and vi(1), a user-friendly full-screen text editor based on ex. EOD annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/packages/ucl/zoneinfo-all.ucl b/release/packages/ucl/zoneinfo-all.ucl index 3fc90fc3f88a..1b3aef1df1d7 100644 --- a/release/packages/ucl/zoneinfo-all.ucl +++ b/release/packages/ucl/zoneinfo-all.ucl @@ -8,5 +8,5 @@ EOD licenses = [ "PD" ] annotations { - set = minimal + set = "minimal,minimal-jail" } diff --git a/release/powerpc/mkisoimages.sh b/release/powerpc/mkisoimages.sh index 9d83390f1a4e..705545dead4b 100644 --- a/release/powerpc/mkisoimages.sh +++ b/release/powerpc/mkisoimages.sh @@ -112,7 +112,7 @@ if [ -n "${METALOG}" ]; then fi ${MAKEFS} -D -N ${BASEBITSDIR}/etc -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@" rm -f "$BASEBITSDIR/etc/fstab" -if [ n "$bootable" ]; then +if [ -n "$bootable" ]; then rm $BOOTBLOCK fi rm -rf "$BASEBITSDIR/ppc" diff --git a/release/release.sh b/release/release.sh index eed02f0f36d3..0815c7c78d14 100755 --- a/release/release.sh +++ b/release/release.sh @@ -199,7 +199,7 @@ env_check() { KERNCONF=\"${KERNEL}\" ${CONF_FILES} ${SRCPORTS} \ WITH_DVD=${WITH_DVD} WITH_VMIMAGES=${WITH_VMIMAGES} \ WITH_CLOUDWARE=${WITH_CLOUDWARE} WITH_OCIIMAGES=${WITH_OCIIMAGES} \ - XZ_THREADS=${XZ_THREADS} PKGBASE=${PKGBASE}" + XZ_THREADS=${XZ_THREADS} NOPKGBASE=${NOPKGBASE}" return 0 } # env_check() @@ -328,7 +328,9 @@ chroot_build_target() { eval chroot ${CHROOTDIR} make -C /usr/src ${RELEASE_WMAKEFLAGS} buildworld eval chroot ${CHROOTDIR} make -C /usr/src ${RELEASE_KMAKEFLAGS} buildkernel if [ -n "${WITH_OCIIMAGES}" ]; then - eval chroot ${CHROOTDIR} make -C /usr/src ${RELEASE_WMAKEFLAGS} packages + mkdir -p ${CHROOT}/tmp/ports ${CHROOT}/tmp/distfiles + eval chroot ${CHROOTDIR} make -C /usr/src ${RELEASE_WMAKEFLAGS} \ + BOOTSTRAP_PKG_FROM_PORTS=YES packages fi return 0 diff --git a/release/scripts/make-oci-image.sh b/release/scripts/make-oci-image.sh index 8a620e9d8973..6e5ad69741f7 100644 --- a/release/scripts/make-oci-image.sh +++ b/release/scripts/make-oci-image.sh @@ -47,7 +47,7 @@ install_packages() { # metadata for what was installed). This trims more than 40Mb from the # resulting image. env IGNORE_OSVERSION=yes ABI=${abi} pkg --rootdir ${rootdir} --repo-conf-dir ${workdir}/repos \ - install -yq "$@" || exit $? + install -yq -g "$@" || exit $? rm -rf ${rootdir}/var/db/pkg/repos } diff --git a/release/scripts/make-pkg-package.sh b/release/scripts/make-pkg-package.sh index 68172c47f326..ee75e7d68d14 100755 --- a/release/scripts/make-pkg-package.sh +++ b/release/scripts/make-pkg-package.sh @@ -1,26 +1,24 @@ #!/bin/sh -# -# -# Simulate the build environment. -eval $(make -C ${SRCDIR} TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} buildenvvars) +# Simulate the build environment. Note that we need to unset some variables +# which are set in the src tree since they have different (unwanted) effects +# in the ports tree. +SRC_PKG_VERSION=${PKG_VERSION} +PKG_ABI=$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/bin/sh config ABI) +unset PKG_VERSION +unset MAKEFLAGS +unset PKGBASE export WRKDIRPREFIX=/tmp/ports.${TARGET} -export WSTAGEDIR=${WSTAGEDIR} -export REPODIR=${REPODIR} -export PKG_CMD=${PKG_CMD} -export PKG_VERSION=${PKG_VERSION} -export OSVERSION=${OSVERSION} -export WRKDIR=$(make -C ${PORTSDIR}/ports-mgmt/pkg -V WRKDIR) +export DISTDIR=/tmp/distfiles +export WRKDIR=$(make -C ${PORTSDIR}/ports-mgmt/pkg I_DONT_CARE_IF_MY_BUILDS_TARGET_THE_WRONG_RELEASE=YES -V WRKDIR) make -C ${PORTSDIR}/ports-mgmt/pkg TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ CONFIGURE_ARGS="--host=$(uname -m)-portbld-freebsd${REVISION}" \ - stage create-manifest + I_DONT_CARE_IF_MY_BUILDS_TARGET_THE_WRONG_RELEASE=YES \ + BATCH=YES stage create-manifest -${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/bin/sh \ - create -v -m ${WRKDIR}/.metadir/ \ +${PKG_CMD} -o ABI=${PKG_ABI} \ + create -v -m ${WRKDIR}/.metadir.pkg/ \ -r ${WRKDIR}/stage \ -p ${WRKDIR}/.PLIST.mktmp \ - -o ${REPODIR}/$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/bin/sh config ABI)/${PKG_VERSION} -mkdir -p ${REPODIR}/$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/bin/sh config ABI)/${PKG_VERSION}/Latest/ -cd ${REPODIR}/$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/bin/sh config ABI)/${PKG_VERSION}/Latest/ && \ - ln -s ../pkg-*.txz + -o ${REPODIR}/${PKG_ABI}/${SRC_PKG_VERSION} diff --git a/release/scripts/pkgbase-stage.lua b/release/scripts/pkgbase-stage.lua index a12ec372d1a9..9e968fd150f8 100755 --- a/release/scripts/pkgbase-stage.lua +++ b/release/scripts/pkgbase-stage.lua @@ -18,87 +18,47 @@ local function capture(command) return output:match("(.-)\n$") or output end -local function append_list(list, other) - for _, item in ipairs(other) do - table.insert(list, item) - end -end - -- Returns a list of packages to be included in the given media local function select_packages(pkg, media, all_libcompats) - local components = { - kernel = {}, - kernel_dbg = {}, - base = {}, - base_dbg = {}, - src = {}, - tests = {}, - } - - for compat in all_libcompats:gmatch("%S+") do - components["lib" .. compat] = {} - components["lib" .. compat .. "_dbg"] = {} - end - + local components = {} local rquery = capture(pkg .. "rquery -U -r FreeBSD-base %n") for package in rquery:gmatch("[^\n]+") do - if package == "FreeBSD-src" or package:match("^FreeBSD%-src%-.*") then - table.insert(components["src"], package) - elseif package == "FreeBSD-tests" or package:match("^FreeBSD%-tests%-.*") then - table.insert(components["tests"], package) - elseif package:match("^FreeBSD%-kernel%-.*") and - package ~= "FreeBSD-kernel-man" - then - -- Kernels other than FreeBSD-kernel-generic are ignored - if package == "FreeBSD-kernel-generic" then - table.insert(components["kernel"], package) - elseif package == "FreeBSD-kernel-generic-dbg" then - table.insert(components["kernel_dbg"], package) - end - elseif package:match(".*%-dbg$") then - table.insert(components["base_dbg"], package) - else - local found = false - for compat in all_libcompats:gmatch("%S+") do - if package:match(".*%-dbg%-lib" .. compat .. "$") then - table.insert(components["lib" .. compat .. "_dbg"], package) - found = true - break - elseif package:match(".*%-lib" .. compat .. "$") then - table.insert(components["lib" .. compat], package) - found = true - break - end - end - if not found then - table.insert(components["base"], package) - end + local set = package:match("^FreeBSD%-set%-(.*)$") + if set then + components[set] = package + -- Kernels other than FreeBSD-kernel-generic are ignored + -- Note that on powerpc64 and powerpc64le the names are + -- slightly different. + elseif package:match("^FreeBSD%-kernel%-generic.*-dbg") then + components["kernel-dbg"] = package + elseif package:match("^FreeBSD%-kernel%-generic.*") then + components["kernel"] = package end end - assert(#components["kernel"] == 1) - assert(#components["base"] > 0) + assert(components["kernel"]) + assert(components["base"]) local selected = {} if media == "disc" then - append_list(selected, components["base"]) - append_list(selected, components["kernel"]) - append_list(selected, components["kernel_dbg"]) - append_list(selected, components["src"]) - append_list(selected, components["tests"]) + table.insert(selected, components["base"]) + table.insert(selected, components["kernel"]) + table.insert(selected, components["kernel-dbg"]) + table.insert(selected, components["src"]) + table.insert(selected, components["tests"]) for compat in all_libcompats:gmatch("%S+") do - append_list(selected, components["lib" .. compat]) + table.insert(selected, components["lib" .. compat]) end else assert(media == "dvd") - append_list(selected, components["base"]) - append_list(selected, components["base_dbg"]) - append_list(selected, components["kernel"]) - append_list(selected, components["kernel_dbg"]) - append_list(selected, components["src"]) - append_list(selected, components["tests"]) + table.insert(selected, components["base"]) + table.insert(selected, components["base-dbg"]) + table.insert(selected, components["kernel"]) + table.insert(selected, components["kernel-dbg"]) + table.insert(selected, components["src"]) + table.insert(selected, components["tests"]) for compat in all_libcompats:gmatch("%S+") do - append_list(selected, components["lib" .. compat]) - append_list(selected, components["lib" .. compat .. "_dbg"]) + table.insert(selected, components["lib" .. compat]) + table.insert(selected, components["lib" .. compat .. "-dbg"]) end end @@ -136,7 +96,7 @@ local function main() local packages = select_packages(pkg, media, all_libcompats) - assert(os.execute(pkg .. "fetch -o " .. target .. " " .. table.concat(packages, " "))) + assert(os.execute(pkg .. "fetch -d -o " .. target .. " " .. table.concat(packages, " "))) assert(os.execute(pkg .. "repo " .. target)) end diff --git a/release/tools/azure.conf b/release/tools/azure.conf index e13b63067fee..7975e1db0822 100644 --- a/release/tools/azure.conf +++ b/release/tools/azure.conf @@ -19,20 +19,25 @@ export NOSWAP=YES export VM_BOOTPARTSOFFSET=1M vm_extra_pre_umount() { - mount -t devfs devfs ${DESTDIR}/dev - - # The firstboot_pkgs rc.d script will download the repository - # catalogue and install or update pkg when the instance first - # launches, so these files would just be replaced anyway; removing - # them from the image allows it to boot faster. - chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ - /usr/sbin/pkg delete -f -y pkg - rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports - rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports-kmods - - chroot ${DESTDIR} ${EMULATOR} pw usermod root -h - - - umount ${DESTDIR}/dev + # Remove the pkg package and repo databases as they will likely + # be out of date by the time the image is used. In unprivileged + # builds this is unnecessary as pkg will not be installed to + # begin with. + if [ -z "${NO_ROOT}" ]; then + mount -t devfs devfs ${DESTDIR}/dev + + # The firstboot_pkgs rc.d script will download the repository + # catalogue and install or update pkg when the instance first + # launches, so these files would just be replaced anyway; removing + # them from the image allows it to boot faster. + chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ + /usr/sbin/pkg delete -f -y pkg + umount ${DESTDIR}/dev + rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports + rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports-kmods + fi + + pw -R ${DESTDIR} usermod root -h - cat << EOF >> ${DESTDIR}/etc/rc.conf ifconfig_hn0="SYNCDHCP" @@ -51,6 +56,7 @@ boot_serial="YES" mlx4en_load="YES" mlx5en_load="YES" EOF + metalog_add_data ./boot/loader.conf return 0 } diff --git a/release/tools/ec2-base.conf b/release/tools/ec2-base.conf index 3ed20474a4e8..b6354db3d9d1 100644 --- a/release/tools/ec2-base.conf +++ b/release/tools/ec2-base.conf @@ -28,6 +28,7 @@ vm_extra_pre_umount() { # be "new" disks; there is no "previous boot" when they might have # been seen and used already. touch ${DESTDIR}/var/db/ec2_ephemeral_diskseen + metalog_add_data ./var/db/ec2_ephemeral_diskseen # Configuration common to all EC2 AMIs ec2_common diff --git a/release/tools/ec2-builder.conf b/release/tools/ec2-builder.conf index 7927fc13a74d..993dffc565eb 100644 --- a/release/tools/ec2-builder.conf +++ b/release/tools/ec2-builder.conf @@ -28,6 +28,7 @@ vm_extra_pre_umount() { # be "new" disks; there is no "previous boot" when they might have # been seen and used already. touch ${DESTDIR}/var/db/ec2_ephemeral_diskseen + metalog_add_data ./var/db/ec2_ephemeral_diskseen # Configuration common to all EC2 AMIs ec2_common @@ -37,21 +38,25 @@ vm_extra_pre_umount() { # Grab a copy of the ec2-base disk image, and compress it zstd < ${EC2BASEIMG} > ${DESTDIR}/image.zst + metalog_add_data ./image.zst # Disable fortune so we don't have extra noise at login chmod a-x ${DESTDIR}/usr/bin/fortune # Install the AMI-building script install -m 755 ${WORLDDIR}/release/tools/mkami.sh ${DESTDIR}/bin/mkami + metalog_add_data ./bin/mkami 0755 # Install an /etc/rc which juggles disks around for us install -m 755 ${WORLDDIR}/release/tools/rc.amibuilder ${DESTDIR}/etc + metalog_add_data ./etc/rc.amibuilder 0755 # We want to mount from the UFS disk and juggle disks first cat >> ${DESTDIR}/boot/loader.conf <<-EOF vfs.root.mountfrom="ufs:/dev/gpt/rootfs" init_script="/etc/rc.amibuilder" EOF + metalog_add_data ./boot/loader.conf return 0 } diff --git a/release/tools/ec2-cloud-init.conf b/release/tools/ec2-cloud-init.conf index 048202e252f6..2a15ae5c57d8 100644 --- a/release/tools/ec2-cloud-init.conf +++ b/release/tools/ec2-cloud-init.conf @@ -27,6 +27,7 @@ vm_extra_pre_umount() { doas: - permit nopass ec2-user EOF + metalog_add_data ./usr/local/etc/cloud/cloud.cfg.d/98_ec2.cfg return 0 } diff --git a/release/tools/ec2-small.conf b/release/tools/ec2-small.conf index 858836717f5a..e2a348d6ba8f 100644 --- a/release/tools/ec2-small.conf +++ b/release/tools/ec2-small.conf @@ -33,6 +33,7 @@ vm_extra_pre_umount() { # be "new" disks; there is no "previous boot" when they might have # been seen and used already. touch ${DESTDIR}/var/db/ec2_ephemeral_diskseen + metalog_add_data ./var/db/ec2_ephemeral_diskseen # Configuration common to all EC2 AMIs ec2_common diff --git a/release/tools/ec2.conf b/release/tools/ec2.conf index 704a8f3f0073..335db6cca93a 100644 --- a/release/tools/ec2.conf +++ b/release/tools/ec2.conf @@ -22,17 +22,27 @@ export NOSWAP=YES ec2_common() { # Delete the pkg package and the repo database; they will likely be - # long out of date before the EC2 instance is launched. - mount -t devfs devfs ${DESTDIR}/dev - chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ - /usr/sbin/pkg delete -f -y pkg - umount ${DESTDIR}/dev - rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports - rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports-kmods + # long out of date before the EC2 instance is launched. In + # unprivileged builds this is unnecessary as pkg will not be + # installed to begin with. + if [ -z "${NO_ROOT}" ]; then + mount -t devfs devfs ${DESTDIR}/dev + chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ + /usr/sbin/pkg delete -f -y pkg + umount ${DESTDIR}/dev + rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports + rm -r ${DESTDIR}/var/db/pkg/repos/FreeBSD-ports-kmods + fi # Turn off IPv6 Duplicate Address Detection; the EC2 networking # configuration makes it unnecessary. echo 'net.inet6.ip6.dad_count=0' >> ${DESTDIR}/etc/sysctl.conf + metalog_add_data ./etc/sysctl.conf + + # Tell gptboot not to wait 3 seconds for a keypress which will + # never arrive. + printf -- "-n\n" > ${DESTDIR}/boot.config + metalog_add_data ./boot.config # Booting quickly is more important than giving users a chance to # access the boot loader via the serial port. @@ -43,10 +53,6 @@ ec2_common() { # default 2048 bytes of entropy; ask for 64 bytes instead. echo 'entropy_efi_seed_size="64"' >> ${DESTDIR}/boot/loader.conf - # Tell gptboot not to wait 3 seconds for a keypress which will - # never arrive. - printf -- "-n\n" > ${DESTDIR}/boot.config - # The emulated keyboard attached to EC2 instances is inaccessible to # users, and there is no mouse attached at all; disable to keyboard # and the keyboard controller (to which the mouse would attach, if @@ -93,6 +99,7 @@ ec2_common() { # by pressing the "Attention button" a second time, but in the EC2 # environment this delay serves no purpose. echo 'hw.pci.pcie_hp_detach_timeout="0"' >> ${DESTDIR}/boot/loader.conf + metalog_add_data ./boot/loader.conf # Disable KbdInteractiveAuthentication according to EC2 requirements. sed -i '' -e \ @@ -127,6 +134,7 @@ REGION=`fetch -qo- http://169.254.169.254/latest/meta-data/placement/availabilit echo "-nfsv4,minorversion=1,oneopenown ${FS}.efs.${REGION}.amazonaws.com:/" EOF chmod 755 ${DESTDIR}/etc/autofs/special_efs + metalog_add_data ./etc/autofs/special_efs 0755 return 0 } @@ -154,6 +162,7 @@ ec2_base_networking () { /usr/local/sbin/dhclient -6 -nw -N -cf /dev/null $1 EOF chmod 755 ${DESTDIR}/usr/local/libexec/rtsold-M + metalog_add_data ./usr/local/libexec/rtsold-M 0755 return 0 } diff --git a/release/tools/gce.conf b/release/tools/gce.conf index dc56be30c7ca..a7ccfc27a75c 100644 --- a/release/tools/gce.conf +++ b/release/tools/gce.conf @@ -21,6 +21,7 @@ vm_extra_install_base() { echo 'search google.internal' > ${DESTDIR}/etc/resolv.conf echo 'nameserver 169.254.169.254' >> ${DESTDIR}/etc/resolv.conf echo 'nameserver 8.8.8.8' >> ${DESTDIR}/etc/resolv.conf + metalog_add ./etc/resolv.conf } vm_extra_pre_umount() { @@ -94,25 +95,18 @@ EOF # ports.txz distributions to the target virtual machine disk image # and fetch the sources for the third-party software installed on # the image. - if [ ! -c "${DESTDIR}/dev/null" ]; then - DEVFSISOURS=1 - mkdir -p ${DESTDIR}/dev - mount -t devfs devfs ${DESTDIR}/dev - fi if [ -e "${DESTDIR}/../ftp/src.txz" ]; then tar fxJ ${DESTDIR}/../ftp/src.txz -C ${DESTDIR} fi if [ -e "${DESTDIR}/../ftp/ports.txz" ]; then tar fxJ ${DESTDIR}/../ftp/ports.txz -C ${DESTDIR} - _INSTALLED_PACKAGES=$(chroot ${DESTDIR} pkg info -o -q -a) + _INSTALLED_PACKAGES=$(pkg -r ${DESTDIR} info -o -q -a) for PACKAGE in ${_INSTALLED_PACKAGES}; do - chroot ${DESTDIR} \ - make -C /usr/ports/${PACKAGE} fetch + make -C ${DESTDIR}/usr/ports/${PACKAGE} fetch \ + DISTDIR=${DESTDIR}/usr/ports/distfiles + done fi - if [ "$DEVFSISOURS" = "1" ]; then - umount_loop ${DESTDIR}/dev - fi ## XXX: Verify this is needed. I do not see this requirement ## in the docs, and it impairs the ability to boot-test a copy @@ -128,6 +122,5 @@ vm_emulation_cleanup() { if [ -n "${QEMUSTATIC}" ]; then rm -f ${DESTDIR}/${EMULATOR} fi - umount_loop ${DESTDIR}/dev return 0 } diff --git a/release/tools/oci-image-notoolchain.conf b/release/tools/oci-image-notoolchain.conf new file mode 100644 index 000000000000..e251281a7357 --- /dev/null +++ b/release/tools/oci-image-notoolchain.conf @@ -0,0 +1,68 @@ +#! /bin/sh + +# Build OCI container image with almost all packages suitable for jails, excluding compiler + +OCI_BASE_IMAGE=runtime + +oci_image_build() { + set_cmd ${workdir} /bin/sh + install_packages ${abi} ${workdir} \ + FreeBSD-acct \ + FreeBSD-at \ + FreeBSD-audit \ + FreeBSD-autofs \ + FreeBSD-blocklist \ + FreeBSD-bsnmp \ + FreeBSD-caroot \ + FreeBSD-certctl \ + FreeBSD-clibs \ + FreeBSD-console-tools \ + FreeBSD-cron \ + FreeBSD-csh \ + FreeBSD-dma \ + FreeBSD-ee \ + FreeBSD-fd \ + FreeBSD-fetch \ + FreeBSD-ftp \ + FreeBSD-ftpd \ + FreeBSD-inetd \ + FreeBSD-ipf \ + FreeBSD-ipfw \ + FreeBSD-iscsi \ + FreeBSD-jail \ + FreeBSD-kerberos \ + FreeBSD-kerberos-lib \ + FreeBSD-libarchive \ + FreeBSD-libcompiler_rt-dev \ + FreeBSD-libexecinfo \ + FreeBSD-libucl \ + FreeBSD-locales \ + FreeBSD-lp \ + FreeBSD-mtree \ + FreeBSD-natd \ + FreeBSD-netmap \ + FreeBSD-newsyslog \ + FreeBSD-nfs \ + FreeBSD-nuageinit \ + FreeBSD-openssl \ + FreeBSD-periodic \ + FreeBSD-pf \ + FreeBSD-pkg-bootstrap \ + FreeBSD-quotacheck \ + FreeBSD-rc \ + FreeBSD-rcmds \ + FreeBSD-rescue \ + FreeBSD-resolvconf \ + FreeBSD-runtime \ + FreeBSD-ssh \ + FreeBSD-syslogd \ + FreeBSD-tcpd \ + FreeBSD-telnet \ + FreeBSD-ufs \ + FreeBSD-unbound \ + FreeBSD-utilities \ + FreeBSD-vi \ + FreeBSD-yp \ + FreeBSD-zfs \ + FreeBSD-zoneinfo +} diff --git a/release/tools/oci-image-toolchain.conf b/release/tools/oci-image-toolchain.conf new file mode 100644 index 000000000000..b3b7eed8e8d1 --- /dev/null +++ b/release/tools/oci-image-toolchain.conf @@ -0,0 +1,16 @@ +#! /bin/sh + +# Build Open Container Initiative (OCI) container image with almost all of FreeBSD base.txz + +OCI_BASE_IMAGE=notoolchain + +oci_image_build() { + set_cmd ${workdir} /bin/sh + install_packages ${abi} ${workdir} \ + FreeBSD-clang \ + FreeBSD-ctf-tools \ + FreeBSD-lld \ + FreeBSD-lldb \ + FreeBSD-toolchain \ + FreeBSD-*-dev +} diff --git a/release/tools/oracle.conf b/release/tools/oracle.conf index 688820be9cbe..ebda3b3d6e61 100644 --- a/release/tools/oracle.conf +++ b/release/tools/oracle.conf @@ -55,6 +55,7 @@ EOF xz_load="YES" zfs_load="YES" EOF + metalog_add_data ./boot/loader.conf cat <<-'EOF' >> ${DESTDIR}/etc/ssh/sshd_config # S11 Configure the SSH service to prevent password-based login @@ -82,10 +83,11 @@ EOF network: renderers: ['freebsd'] EOF + metalog_add_data ./usr/local/etc/cloud/cloud.cfg.d/98_oracle.cfg # Use Oracle Cloud Infrastructure NTP server sed -i '' -E -e 's/^pool.*iburst/server 169.254.169.254 iburst/' \ - ${DESTDIR}/etc/ntp.conf + ${DESTDIR}/etc/ntp.conf return 0 } diff --git a/release/tools/vagrant.conf b/release/tools/vagrant.conf index 506174d0ea16..7ab0e1238693 100644 --- a/release/tools/vagrant.conf +++ b/release/tools/vagrant.conf @@ -47,19 +47,22 @@ vagrant_common () { -c 'Vagrant User' -d '/home/vagrant' -s '/bin/csh' # Change root's password to vagrant - echo 'vagrant' | /usr/sbin/pw -R ${DESTDIR} \ - usermod root -h 0 + echo 'vagrant' | /usr/sbin/pw -R ${DESTDIR} usermod root -h 0 # Configure sudo to allow the vagrant user echo 'vagrant ALL=(ALL:ALL) NOPASSWD: ALL' >> ${DESTDIR}/usr/local/etc/sudoers # Configure the vagrant ssh keys mkdir ${DESTDIR}/home/vagrant/.ssh - chmod 700 ${DESTDIR}/home/vagrant/.ssh + echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" > ${DESTDIR}/home/vagrant/.ssh/authorized_keys echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN1YdxBpNlzxDqfJyw/QKow1F+wvG9hXGoqiysfJOn5Y vagrant insecure public key" >> ${DESTDIR}/home/vagrant/.ssh/authorized_keys - chown -R 1001 ${DESTDIR}/home/vagrant/.ssh chmod 600 ${DESTDIR}/home/vagrant/.ssh/authorized_keys + metalog_add_data ./home/vagrant/.ssh/authorized_keys 0600 + + chmod 700 ${DESTDIR}/home/vagrant/.ssh + chown -R 1001 ${DESTDIR}/home/vagrant/.ssh + echo "./home/vagrant/.ssh type=dir uid=1001 gid=1001 mode=0700" >> METALOG # Reboot quickly, Don't wait at the panic screen echo 'debug.trace_on_panic=1' >> ${DESTDIR}/etc/sysctl.conf @@ -68,6 +71,7 @@ vagrant_common () { # The console is not interactive, so we might as well boot quickly. echo 'autoboot_delay="-1"' >> ${DESTDIR}/boot/loader.conf + metalog_add_data ./boot/loader.conf # The first time the VM boots, the installed "first boot" scripts # should be allowed to run: diff --git a/release/tools/vmimage.subr b/release/tools/vmimage.subr index 41f889a1e665..b3187efd6526 100644 --- a/release/tools/vmimage.subr +++ b/release/tools/vmimage.subr @@ -163,19 +163,32 @@ vm_extra_enable_services() { } vm_extra_install_packages() { - if [ -n "${WITHOUT_QEMU}" ]; then - return 0 - fi - if [ -z "${VM_EXTRA_PACKAGES}" ]; then return 0 fi - chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ - /usr/sbin/pkg bootstrap -y - for p in ${VM_EXTRA_PACKAGES}; do + if [ -n "${NO_ROOT}" ]; then + for pkg in ${VM_EXTRA_PACKAGES}; do + INSTALL_AS_USER=yes \ + ${PKG_CMD} \ + -o METALOG=${DESTDIR}/METALOG.pkg \ + -o REPOS_DIR=${PKG_REPOS_DIR} \ + -o PKG_DBDIR=${DESTDIR}/var/db/pkg \ + -r ${DESTDIR} \ + install -y -r ${PKG_REPO_NAME} $pkg + done + metalog_add_data ./var/db/pkg/local.sqlite + else + if [ -n "${WITHOUT_QEMU}" ]; then + return 0 + fi + chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ - /usr/sbin/pkg install -y ${p} - done + /usr/sbin/pkg bootstrap -y + for p in ${VM_EXTRA_PACKAGES}; do + chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ + /usr/sbin/pkg install -y ${p} + done + fi return 0 } @@ -219,6 +232,10 @@ vm_extra_pkg_rmcache() { buildfs() { local md tmppool + if [ -f ${DESTDIR}/METALOG.pkg ]; then + cat ${DESTDIR}/METALOG.pkg >> ${DESTDIR}/METALOG + fi + case "${VMFS}" in ufs) cd ${DESTDIR} && ${MAKEFS} ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ diff --git a/sbin/devd/moused.conf b/sbin/devd/moused.conf index ed1060ffdf2e..8821c2bb8375 100644 --- a/sbin/devd/moused.conf +++ b/sbin/devd/moused.conf @@ -33,3 +33,12 @@ notify 100 { action "service moused quietstop $cdev"; }; + +notify 100 { + match "system" "DEVFS"; + match "subsystem" "CDEV"; + match "type" "CREATE"; + match "cdev" "input/event[0-9]+"; + + action "service moused quietstart $cdev"; +}; diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c index add1280e960b..084ea50dae7c 100644 --- a/sbin/hastd/subr.c +++ b/sbin/hastd/subr.c @@ -156,7 +156,6 @@ drop_privs(const struct hast_resource *res) struct passwd *pw; uid_t ruid, euid, suid; gid_t rgid, egid, sgid; - gid_t gidset[1]; bool capsicum, jailed; /* @@ -285,7 +284,6 @@ drop_privs(const struct hast_resource *res) PJDLOG_VERIFY(egid == pw->pw_gid); PJDLOG_VERIFY(sgid == pw->pw_gid); PJDLOG_VERIFY(getgroups(0, NULL) == 0); - PJDLOG_VERIFY(getgroups(1, gidset) == 0); pjdlog_debug(1, "Privileges successfully dropped using %s%s+setgid+setuid.", diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index e0f34f0c4d82..9386f5eaf513 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -726,6 +726,8 @@ static struct cmd inet6_cmds[] = { DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), + DEF_CMD("stableaddr", ND6_IFF_STABLEADDR, setnd6flags), + DEF_CMD("-stableaddr", -ND6_IFF_STABLEADDR, setnd6flags), #ifdef EXPERIMENTAL DEF_CMD("ipv6_only", ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags), DEF_CMD("-ipv6_only", -ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags), diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index 2899ad6a0778..fb7e72028e2e 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -66,6 +66,7 @@ static const char *ND6BITS[] = { [9] = "IPV6_ONLY", [10] = "IPV6_ONLY_MANUAL", #endif + [11] = "STABLEADDR", [15] = "DEFAULTIF", }; diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index b580191383b3..fafb77e1ca6c 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 10, 2025 +.Dd September 12, 2025 .Dt IFCONFIG 8 .Os .Sh NAME @@ -36,7 +36,7 @@ .Nd configure network interface parameters .Sh SYNOPSIS .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Op Fl DkLmn .Op Fl f Ar type Ns Cm \&: Ns Ar format .Ar interface @@ -50,11 +50,11 @@ .Oc .Op Ar parameters .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Ar interface .Cm destroy .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Fl a .Op Fl dDkLmuv .Op Fl f Ar type Ns Cm \&: Ns Ar format @@ -64,16 +64,16 @@ .Nm .Fl C .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Fl g Ar groupname .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Fl l .Op Fl du .Op Fl g Ar groupname .Op Ar address_family .Nm -.Op Fl j Ar jail +.Op Fl j Ar jid .Op Fl dkLmuv .Op Fl f Ar type Ns Cm \&: Ns Ar format .Sh DESCRIPTION @@ -257,22 +257,22 @@ Setting to .Cm all selects all interfaces. -.It Fl j Ar jail -Perform the actions inside the -.Ar jail . +.It Fl j Ar jid +Perform the actions inside the jail specified by +.Ar jid , +which may be either a jail name or a numeric jail ID. .Pp The -.Cm ifconfig -will first attach to the -.Ar jail -(by jail id or jail name) before performing the effects. -.Pp -This allow network interfaces of -.Ar jail -to be configured even if the -.Cm ifconfig -binary is not available in -.Ar jail . +.Nm +utility will attach to the specified jail immediately upon +encountering the option on the command line. +The option may be specified multiple times to attach to a nested jail +(jail within a jail). +.Pp +This makes it possible to configure network interfaces within a vnet +jail even if the +.Nm +binary is not available inside the jail. .It Fl k Print keying information for the .Ar interface , @@ -1004,6 +1004,36 @@ Set a flag to disable Duplicate Address Detection. .It Cm -no_dad Clear a flag .Cm no_dad . +.It Cm stableaddr +Set a flag to create SLAAC addresses using a stable algorithm according to RFC 7217 +The +.Xr sysctl 8 +variable +.Va net.inet6.ip6.use_stableaddr +controls whether this flag is set by default or not for newly created interfaces. +To get consistent defaults for interfaces created at boot it should be set as a tunable via loader.conf(8). +The +.Xr sysctl 8 +variable +.Va net.inet6.ip6.stableaddr_maxretries +sets the maximum number of retries to generate a unique IPv6 address to be performed in case of DAD failures. +This defaults to 3 which is also the reccommended minimum value. +The interface ID source can be configured using the +.Xr sysctl 8 +variable +.Va net.inet6.ip6.stableaddr_netifsource: +.Bl -tag -compact +.It Cm 0 +uses the interface name string (the default) +.It Cm 1 +uses the interface ID +.It Cm 2 +uses the MAC address of the interface (if one can be obtained for it) +.El +.Pp +.It Cm -stableaddr +Clear the flag +.Cm stableaddr . .El .Ss IPv6 Parameters The following parameters are specific for IPv6 addresses. diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 3f998b7f2b52..9aeb4a09ef49 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -463,6 +463,9 @@ args_parse(struct ifconfig_args *args, int argc, char *argv[]) { char options[1024]; struct option *p; +#ifdef JAIL + int jid; +#endif int c; /* Parse leading line options */ @@ -494,7 +497,11 @@ args_parse(struct ifconfig_args *args, int argc, char *argv[]) #ifdef JAIL if (optarg == NULL) usage(); - args->jail_name = optarg; + jid = jail_getid(optarg); + if (jid == -1) + Perror("jail not found"); + if (jail_attach(jid) != 0) + Perror("cannot attach to jail"); #else Perror("not built with jail support"); #endif @@ -611,9 +618,6 @@ main(int ac, char *av[]) { char *envformat; int flags; -#ifdef JAIL - int jid; -#endif struct ifconfig_args _args = {}; struct ifconfig_args *args = &_args; @@ -638,16 +642,6 @@ main(int ac, char *av[]) args_parse(args, ac, av); -#ifdef JAIL - if (args->jail_name) { - jid = jail_getid(args->jail_name); - if (jid == -1) - Perror("jail not found"); - if (jail_attach(jid) != 0) - Perror("cannot attach to jail"); - } -#endif - if (!args->all && !args->namesonly) { /* not listing, need an argument */ args->ifname = args_pop(args); @@ -1669,9 +1663,10 @@ static const char *IFCAPBITS[] = { [20] = "NETMAP", [21] = "RXCSUM_IPV6", [22] = "TXCSUM_IPV6", + [23] = "HWSTATS", [24] = "TXRTLMT", [25] = "HWRXTSTMP", - [26] = "NOMAP", + [26] = "MEXTPG", [27] = "TXTLS4", [28] = "TXTLS6", [29] = "VXLAN_HWCSUM", diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h index 468c9b4e80da..672020443b8c 100644 --- a/sbin/ifconfig/ifconfig.h +++ b/sbin/ifconfig/ifconfig.h @@ -249,7 +249,6 @@ struct ifconfig_args { const char *matchgroup; /* Group name to match */ const char *nogroup; /* Group name to exclude */ const struct afswtch *afp; /* AF we're operating on */ - const char *jail_name; /* Jail name or jail id specified */ }; struct option { diff --git a/sbin/init/init.c b/sbin/init/init.c index b345c8fa219a..d28501053c7f 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -851,9 +851,9 @@ single_user(void) const char *shell; char *argv[2]; struct timeval tv, tn; + struct passwd *pp; #ifdef SECURE struct ttyent *typ; - struct passwd *pp; static const char banner[] = "Enter root password, or ^D to go multi-user\n"; char *clear, *password; @@ -885,6 +885,7 @@ single_user(void) */ open_console(); + pp = getpwnam("root"); #ifdef SECURE /* * Check the root password. @@ -892,7 +893,6 @@ single_user(void) * it's the only tty that can be 'off' and 'secure'. */ typ = getttynam("console"); - pp = getpwnam("root"); if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp && *pp->pw_passwd) { write_stderr(banner); @@ -909,7 +909,6 @@ single_user(void) } } endttyent(); - endpwent(); #endif /* SECURE */ #ifdef DEBUGSHELL @@ -930,6 +929,15 @@ single_user(void) } #endif /* DEBUGSHELL */ + if (pp != NULL && pp->pw_dir != NULL && *pp->pw_dir != '\0' && + chdir(pp->pw_dir) == 0) { + setenv("HOME", pp->pw_dir, 1); + } else { + chdir("/"); + setenv("HOME", "/", 1); + } + endpwent(); + /* * Unblock signals. * We catch all the interesting ones, diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 46e9f60fe48e..0628b387b4b3 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -420,6 +420,8 @@ int rt_tableid_max(void); void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *); void mv_eth_rules(struct pfctl_eth_ruleset *, struct pfctl_eth_ruleset *); +void mv_tables(struct pfctl *, struct pfr_ktablehead *, + struct pfctl_anchor *, struct pfctl_anchor *); void decide_address_family(struct node_host *, sa_family_t *); void remove_invalid_hosts(struct node_host **, sa_family_t *); int invalid_redirect(struct node_host *, sa_family_t); @@ -949,6 +951,7 @@ anchorname : STRING { pfa_anchorlist : /* empty */ | pfa_anchorlist '\n' + | pfa_anchorlist tabledef '\n' | pfa_anchorlist pfrule '\n' | pfa_anchorlist anchorrule '\n' | pfa_anchorlist include '\n' @@ -974,7 +977,7 @@ pfa_anchor : '{' snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); rs = pf_find_or_create_ruleset(ta); if (rs == NULL) - err(1, "pfa_anchor: pf_find_or_create_ruleset"); + err(1, "pfa_anchor: pf_find_or_create_ruleset (%s)", ta); pf->astack[pf->asd] = rs->anchor; pf->anchor = rs->anchor; } '\n' pfa_anchorlist '}' @@ -1026,6 +1029,7 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto } mv_rules(&pf->alast->ruleset, &r.anchor->ruleset); + mv_tables(pf, &pfr_ktables, r.anchor, pf->alast); } pf_remove_if_empty_ruleset(&pf->alast->ruleset); pf->alast = r.anchor; @@ -5456,6 +5460,7 @@ process_tabledef(char *name, struct table_opts *opts, int popts) { struct pfr_buffer ab; struct node_tinit *ti; + struct pfr_uktable *ukt; unsigned long maxcount; size_t s = sizeof(maxcount); @@ -5488,9 +5493,23 @@ process_tabledef(char *name, struct table_opts *opts, int popts) else if (pf->opts & PF_OPT_VERBOSE) fprintf(stderr, "%s:%d: skipping duplicate table checks" " for <%s>\n", file->name, yylval.lineno, name); + /* + * postpone definition of non-root tables to moment + * when path is fully resolved. + */ + if (pf->asd > 0) { + ukt = calloc(1, sizeof(struct pfr_uktable)); + if (ukt == NULL) { + DBGPRINT( + "%s:%d: not enough memory for <%s>\n", file->name, + yylval.lineno, name); + goto _error; + } + } else + ukt = NULL; if (!(pf->opts & PF_OPT_NOACTION) && pfctl_define_table(name, opts->flags, opts->init_addr, - pf->anchor->path, &ab, pf->anchor->ruleset.tticket)) { + pf->anchor->path, &ab, pf->anchor->ruleset.tticket, ukt)) { if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s, NULL, 0) == -1) @@ -5506,6 +5525,28 @@ process_tabledef(char *name, struct table_opts *opts, int popts) goto _error; } + + if (ukt != NULL) { + ukt->pfrukt_init_addr = opts->init_addr; + if (RB_INSERT(pfr_ktablehead, &pfr_ktables, + &ukt->pfrukt_kt) != NULL) { + /* + * I think this should not happen, because + * pfctl_define_table() above does the same check + * effectively. + */ + DBGPRINT( + "%s:%d table %s already exists in %s\n", + file->name, yylval.lineno, + ukt->pfrukt_name, pf->anchor->path); + free(ukt); + goto _error; + } + DBGPRINT("%s %s@%s inserted to tree\n", + __func__, ukt->pfrukt_name, pf->anchor->path); + } else + DBGPRINT("%s ukt is null\n", __func__); + pf->tdirty = 1; pfr_buf_clear(&ab); return (0); @@ -7277,6 +7318,61 @@ mv_eth_rules(struct pfctl_eth_ruleset *src, struct pfctl_eth_ruleset *dst) } void +mv_tables(struct pfctl *pf, struct pfr_ktablehead *ktables, + struct pfctl_anchor *a, struct pfctl_anchor *alast) +{ + struct pfr_ktable *kt, *kt_safe; + char new_path[PF_ANCHOR_MAXPATH]; + char *path_cut; + int sz; + struct pfr_uktable *ukt; + SLIST_HEAD(, pfr_uktable) ukt_list; + + /* + * Here we need to rename anchor path from temporal names such as + * _1/_2/foo to _1/bar/foo etc. + * + * This also means we need to remove and insert table to ktables + * tree as anchor path is being updated. + */ + SLIST_INIT(&ukt_list); + DBGPRINT("%s [ %s ] (%s)\n", __func__, a->path, alast->path); + RB_FOREACH_SAFE(kt, pfr_ktablehead, ktables, kt_safe) { + path_cut = strstr(kt->pfrkt_anchor, alast->path); + if (path_cut != NULL) { + path_cut += strlen(alast->path); + if (*path_cut) + sz = snprintf(new_path, sizeof (new_path), + "%s%s", a->path, path_cut); + else + sz = snprintf(new_path, sizeof (new_path), + "%s", a->path); + if (sz >= sizeof (new_path)) + errx(1, "new path is too long for %s@%s\n", + kt->pfrkt_name, kt->pfrkt_anchor); + + DBGPRINT("%s %s@%s -> %s@%s\n", __func__, + kt->pfrkt_name, kt->pfrkt_anchor, + kt->pfrkt_name, new_path); + RB_REMOVE(pfr_ktablehead, ktables, kt); + strlcpy(kt->pfrkt_anchor, new_path, + sizeof(kt->pfrkt_anchor)); + SLIST_INSERT_HEAD(&ukt_list, (struct pfr_uktable *)kt, + pfrukt_entry); + } + } + + while ((ukt = SLIST_FIRST(&ukt_list)) != NULL) { + SLIST_REMOVE_HEAD(&ukt_list, pfrukt_entry); + if (RB_INSERT(pfr_ktablehead, ktables, + (struct pfr_ktable *)ukt) != NULL) + errx(1, "%s@%s exists already\n", + ukt->pfrukt_name, + ukt->pfrukt_anchor); + } +} + +void decide_address_family(struct node_host *n, sa_family_t *af) { if (*af != 0 || n == NULL) @@ -7485,7 +7581,7 @@ parseport(char *port, struct range *r, int extensions) } int -pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) +pfctl_load_anchors(int dev, struct pfctl *pf) { struct loadanchors *la; @@ -7494,7 +7590,7 @@ pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) fprintf(stderr, "\nLoading anchor %s from %s\n", la->anchorname, la->filename); if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize, - la->anchorname, trans) == -1) + la->anchorname, pf->trans) == -1) return (-1); } diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 index 5a74a8fd3444..f1a2bbef6236 100644 --- a/sbin/pfctl/pfctl.8 +++ b/sbin/pfctl/pfctl.8 @@ -24,7 +24,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 5, 2025 +.Dd August 25, 2025 .Dt PFCTL 8 .Os .Sh NAME @@ -115,8 +115,9 @@ Apply flags .Fl f , .Fl F , .Fl s , +.Fl T , and -.Fl T +.Fl z only to the rules in the specified .Ar anchor . In addition to the main ruleset, @@ -211,31 +212,31 @@ Flush the filter parameters specified by .Ar modifier (may be abbreviated): .Pp -.Bl -tag -width xxxxxxxxxxxx -compact -.It Fl F Cm nat +.Bl -tag -width xxxxxxxxx -compact +.It Cm nat Flush the NAT rules. -.It Fl F Cm queue +.It Cm queue Flush the queue rules. -.It Fl F Cm ethernet +.It Cm ethernet Flush the Ethernet filter rules. -.It Fl F Cm rules +.It Cm rules Flush the filter rules. -.It Fl F Cm states +.It Cm states Flush the state table (NAT and filter). -.It Fl F Cm Sources +.It Cm Sources Flush the source tracking table. -.It Fl F Cm info +.It Cm info Flush the filter information (statistics that are not bound to rules). -.It Fl F Cm Tables +.It Cm Tables Flush the tables. -.It Fl F Cm osfp +.It Cm osfp Flush the passive operating system fingerprints. -.It Fl F Cm Reset +.It Cm Reset Reset limits, timeouts and other options back to default settings. See the OPTIONS section in .Xr pf.conf 5 for details. -.It Fl F Cm all +.It Cm all Flush all of the above. .El .Pp @@ -401,13 +402,13 @@ Other rules and options are ignored. .It Fl o Ar level Control the ruleset optimizer, overriding any rule file settings. .Pp -.Bl -tag -width xxxxxxxxxxxx -compact -.It Fl o Cm none +.Bl -tag -width xxxxxxxxx -compact +.It Cm none Disable the ruleset optimizer. -.It Fl o Cm basic +.It Cm basic Enable basic ruleset optimizations. This is the default behaviour. -.It Fl o Cm profile +.It Cm profile Enable basic ruleset optimizations with profiling. .El .Pp @@ -437,10 +438,10 @@ Show the filter parameters specified by .Ar modifier (may be abbreviated): .Pp -.Bl -tag -width xxxxxxxxxxxxx -compact -.It Fl s Cm nat +.Bl -tag -width xxxxxxxxxxx -compact +.It Cm nat Show the currently loaded NAT rules. -.It Fl s Cm queue +.It Cm queue Show the currently loaded queue rules. When used together with .Fl v , @@ -450,13 +451,13 @@ When used together with .Nm will loop and show updated queue statistics every five seconds, including measured bandwidth and packets per second. -.It Fl s Cm ether +.It Cm ether Show the currently loaded Ethernet rules. When used together with .Fl v , the per-rule statistics (number of evaluations, packets, and bytes) are also shown. -.It Fl s Cm rules +.It Cm rules Show the currently loaded filter rules. When used together with .Fl v , @@ -469,7 +470,7 @@ will skip evaluation of rules where possible. Packets passed statefully are counted in the rule that created the state (even though the rule is not evaluated more than once for the entire connection). -.It Fl s Cm Anchors +.It Cm Anchors Show the currently loaded anchors directly attached to the main ruleset. If .Fl a Ar anchor @@ -480,11 +481,11 @@ If .Fl v is specified, all anchors attached under the target anchor will be displayed recursively. -.It Fl s Cm states +.It Cm states Show the contents of the state table. -.It Fl s Cm Sources +.It Cm Sources Show the contents of the source tracking table. -.It Fl s Cm info +.It Cm info Show filter information (statistics and counters). When used together with .Fl v , @@ -492,21 +493,21 @@ source tracking statistics, the firewall's 32-bit hostid number and the main ruleset's MD5 checksum for use with .Xr pfsync 4 are also shown. -.It Fl s Cm Running +.It Cm Running Show the running status and provide a non-zero exit status when disabled. -.It Fl s Cm labels +.It Cm labels Show per-rule statistics (label, evaluations, packets total, bytes total, packets in, bytes in, packets out, bytes out, state creations) of filter rules with labels, useful for accounting. -.It Fl s Cm timeouts +.It Cm timeouts Show the current global timeouts. -.It Fl s Cm memory +.It Cm memory Show the current pool memory hard limits. -.It Fl s Cm Tables +.It Cm Tables Show the list of tables. -.It Fl s Cm osfp +.It Cm osfp Show the list of operating system fingerprints. -.It Fl s Cm Interfaces +.It Cm Interfaces Show the list of interfaces and interface groups available to PF. When used together with .Fl v , @@ -516,7 +517,7 @@ When used together with interface statistics are also shown. .Fl i can be used to select an interface or a group of interfaces. -.It Fl s Cm all +.It Cm all Show all of the above, except for the lists of interfaces and operating system fingerprints. .El @@ -571,38 +572,38 @@ Specify the .Ar table . Commands include: .Pp -.Bl -tag -width "-T expire number" -compact -.It Fl T Cm add +.Bl -tag -width "expire number" -compact +.It Cm add Add one or more addresses to a table. Automatically create a persistent table if it does not exist. -.It Fl T Cm delete +.It Cm delete Delete one or more addresses from a table. -.It Fl T Cm expire Ar number +.It Cm expire Ar number Delete addresses which had their statistics cleared more than .Ar number seconds ago. For entries which have never had their statistics cleared, .Ar number refers to the time they were added to the table. -.It Fl T Cm flush +.It Cm flush Flush all addresses in a table. -.It Fl T Cm kill +.It Cm kill Kill a table. -.It Fl T Cm replace +.It Cm replace Replace the addresses of the table. Automatically create a persistent table if it does not exist. -.It Fl T Cm show +.It Cm show Show the content (addresses) of a table. -.It Fl T Cm test +.It Cm test Test if the given addresses match a table. -.It Fl T Cm zero Op Ar address ... +.It Cm zero Op Ar address ... Clear all the statistics of a table, or only for specified addresses. -.It Fl T Cm reset +.It Cm reset Clear statistics only for addresses with non-zero statistics. Addresses with counter values at zero and their .Dq Cleared timestamp are left untouched. -.It Fl T Cm load +.It Cm load Load only the table definitions from .Xr pf.conf 5 . This is used in conjunction with the diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 2c12387ee388..b29d992b1cda 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -110,6 +110,8 @@ int pfctl_show_status(int, int); int pfctl_show_running(int); int pfctl_show_timeouts(int, int); int pfctl_show_limits(int, int); +void pfctl_read_limits(struct pfctl_handle *); +void pfctl_restore_limits(void); void pfctl_debug(int, u_int32_t, int); int pfctl_test_altqsupport(int, int); int pfctl_show_anchors(int, int, char *); @@ -189,6 +191,8 @@ static const struct { { NULL, 0 } }; +static unsigned int limit_curr[PF_LIMIT_MAX]; + struct pf_hint { const char *name; int timeout; @@ -1781,6 +1785,31 @@ pfctl_show_limits(int dev, int opts) } void +pfctl_read_limits(struct pfctl_handle *h) +{ + int i; + + for (i = 0; pf_limits[i].name; i++) { + if (pfctl_get_limit(h, i, &limit_curr[i])) + err(1, "DIOCGETLIMIT"); + } +} + +void +pfctl_restore_limits(void) +{ + int i; + + if (pfh == NULL) + return; + + for (i = 0; pf_limits[i].name; i++) { + if (pfctl_set_limit(pfh, i, limit_curr[i])) + warn("DIOCSETLIMIT (%s)", pf_limits[i].name); + } +} + +void pfctl_show_creators(int opts) { int ret; @@ -2065,6 +2094,41 @@ pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r, return (0); } +static int +pfctl_load_tables(struct pfctl *pf, char *path, struct pfctl_anchor *a, + int rs_num) +{ + struct pfr_ktable *kt, *ktw; + struct pfr_uktable *ukt; + char anchor_path[PF_ANCHOR_MAXPATH]; + int e; + + RB_FOREACH_SAFE(kt, pfr_ktablehead, &pfr_ktables, ktw) { + if (strcmp(kt->pfrkt_anchor, a->path) != 0) + continue; + + if (path != NULL && *path) { + strlcpy(anchor_path, kt->pfrkt_anchor, + sizeof(anchor_path)); + snprintf(kt->pfrkt_anchor, PF_ANCHOR_MAXPATH, "%s/%s", + path, anchor_path); + } + ukt = (struct pfr_uktable *)kt; + e = pfr_ina_define(&ukt->pfrukt_t, ukt->pfrukt_addrs.pfrb_caddr, + ukt->pfrukt_addrs.pfrb_size, NULL, NULL, + pf->anchor->ruleset.tticket, + ukt->pfrukt_init_addr ? PFR_FLAG_ADDRSTOO : 0); + if (e != 0) + err(1, "%s pfr_ina_define() %s@%s", __func__, + kt->pfrkt_name, kt->pfrkt_anchor); + RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt); + pfr_buf_clear(&ukt->pfrukt_addrs); + free(ukt); + } + + return (0); +} + int pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, int rs_num, int depth) @@ -2113,6 +2177,8 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, if ((error = pfctl_load_ruleset(pf, path, &r->anchor->ruleset, rs_num, depth + 1))) goto error; + if ((error = pfctl_load_tables(pf, path, r->anchor, rs_num))) + goto error; } else if (pf->opts & PF_OPT_VERBOSE) printf("\n"); free(r); @@ -2135,15 +2201,17 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) { u_int8_t rs_num = pf_get_ruleset_number(r->action); char *name; - u_int32_t ticket; char anchor[PF_ANCHOR_NAME_SIZE]; int len = strlen(path); int error; bool was_present; /* set up anchor before adding to path for anchor_call */ - if ((pf->opts & PF_OPT_NOACTION) == 0) - ticket = pfctl_get_ticket(pf->trans, rs_num, path); + if ((pf->opts & PF_OPT_NOACTION) == 0) { + if (pf->trans == NULL) + errx(1, "pfctl_load_rule: no transaction"); + pf->anchor->ruleset.tticket = pfctl_get_ticket(pf->trans, rs_num, path); + } if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) errx(1, "pfctl_load_rule: strlcpy"); @@ -2175,7 +2243,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) return (1); if (pfctl_add_pool(pf, &r->route, PF_RT)) return (1); - error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket, + error = pfctl_add_rule_h(pf->h, r, anchor, name, pf->anchor->ruleset.tticket, pf->paddr.ticket); switch (error) { case 0: @@ -2245,6 +2313,8 @@ pfctl_rules(int dev, char *filename, int opts, int optimize, RB_INIT(&pf_anchors); memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); pf_init_ruleset(&pf_main_anchor.ruleset); + memset(&pf, 0, sizeof(pf)); + memset(&trs, 0, sizeof(trs)); pf_main_anchor.ruleset.anchor = &pf_main_anchor; memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor)); @@ -2254,6 +2324,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize, if (trans == NULL) { bzero(&buf, sizeof(buf)); buf.pfrb_type = PFRB_TRANS; + pf.trans = &buf; t = &buf; osize = 0; } else { @@ -2364,7 +2435,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize, if (trans == NULL) { /* process "load anchor" directives */ - if (pfctl_load_anchors(dev, &pf, t) == -1) + if (pfctl_load_anchors(dev, &pf) == -1) ERRX("load anchors"); if ((opts & PF_OPT_NOACTION) == 0) { @@ -2445,8 +2516,14 @@ pfctl_init_options(struct pfctl *pf) pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; - pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; - pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; + + pf->limit[PF_LIMIT_SRC_NODES] = (limit_curr[PF_LIMIT_SRC_NODES] == 0) ? + PFSNODE_HIWAT : limit_curr[PF_LIMIT_SRC_NODES]; + pf->limit[PF_LIMIT_TABLE_ENTRIES] = + (limit_curr[PF_LIMIT_TABLE_ENTRIES] == 0) ? + PFR_KENTRY_HIWAT : limit_curr[PF_LIMIT_TABLE_ENTRIES]; + pf->limit[PF_LIMIT_ANCHORS] = (limit_curr[PF_LIMIT_ANCHORS] == 0) ? + PF_ANCHOR_HIWAT : limit_curr[PF_LIMIT_ANCHORS]; pf->debug = PF_DEBUG_URGENT; pf->reassemble = 0; @@ -2547,6 +2624,9 @@ pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit) if (pf->opts & PF_OPT_VERBOSE) printf("set limit %s %d\n", opt, limit); + if ((pf->opts & PF_OPT_NOACTION) == 0) + pfctl_load_options(pf); + return (0); } @@ -3410,6 +3490,11 @@ main(int argc, char *argv[]) if (pfh == NULL) err(1, "Failed to open netlink"); + if ((opts & PF_OPT_NOACTION) == 0) { + pfctl_read_limits(pfh); + atexit(pfctl_restore_limits); + } + if (opts & PF_OPT_DISABLE) if (pfctl_disable(dev, opts)) exit_val = 1; @@ -3653,7 +3738,18 @@ main(int argc, char *argv[]) } } - exit(exit_val); + /* + * prevent pfctl_restore_limits() exit handler from restoring + * pf(4) options settings on successful exit. + */ + if (exit_val == 0) { + close(dev); + dev = -1; + pfctl_close(pfh); + pfh = NULL; + } + + return (exit_val); } char * diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index afecc78086e0..136f51ea08f9 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -36,6 +36,12 @@ #include <libpfctl.h> +#ifdef PFCTL_DEBUG +#define DBGPRINT(...) fprintf(stderr, __VA_ARGS__) +#else +#define DBGPRINT(...) (void)(0) +#endif + extern struct pfctl_handle *pfh; struct pfctl; @@ -55,6 +61,41 @@ struct pfr_buffer { (var) != NULL; \ (var) = pfr_buf_next((buf), (var))) +RB_HEAD(pfr_ktablehead, pfr_ktable); +struct pfr_ktable { + struct pfr_tstats pfrkt_ts; + RB_ENTRY(pfr_ktable) pfrkt_tree; + SLIST_ENTRY(pfr_ktable) pfrkt_workq; + struct radix_node_head *pfrkt_ip4; + struct radix_node_head *pfrkt_ip6; + struct pfr_ktable *pfrkt_shadow; + struct pfr_ktable *pfrkt_root; + struct pf_kruleset *pfrkt_rs; + long pfrkt_larg; + int pfrkt_nflags; +}; +#define pfrkt_t pfrkt_ts.pfrts_t +#define pfrkt_name pfrkt_t.pfrt_name +#define pfrkt_anchor pfrkt_t.pfrt_anchor +#define pfrkt_ruleset pfrkt_t.pfrt_ruleset +#define pfrkt_flags pfrkt_t.pfrt_flags +#define pfrkt_cnt pfrkt_kts.pfrkts_cnt +#define pfrkt_refcnt pfrkt_kts.pfrkts_refcnt +#define pfrkt_tzero pfrkt_kts.pfrkts_tzero + +struct pfr_uktable { + struct pfr_ktable pfrukt_kt; + struct pfr_buffer pfrukt_addrs; + int pfrukt_init_addr; + SLIST_ENTRY(pfr_uktable) pfrukt_entry; +}; + +#define pfrukt_t pfrukt_kt.pfrkt_ts.pfrts_t +#define pfrukt_name pfrukt_kt.pfrkt_t.pfrt_name +#define pfrukt_anchor pfrukt_kt.pfrkt_t.pfrt_anchor + +extern struct pfr_ktablehead pfr_ktables; + struct pfr_anchoritem { SLIST_ENTRY(pfr_anchoritem) pfra_sle; char *pfra_anchorname; @@ -62,7 +103,6 @@ struct pfr_anchoritem { SLIST_HEAD(pfr_anchors, pfr_anchoritem); -int pfr_get_fd(void); int pfr_add_table(struct pfr_table *, int *, int); int pfr_del_table(struct pfr_table *, int *, int); int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int); @@ -85,7 +125,6 @@ int pfr_buf_load(struct pfr_buffer *, char *, int, int (*)(struct pfr_buffer *, char *, int, int), int); char *pf_strerror(int); int pfi_get_ifaces(const char *, struct pfi_kif *, int *); -int pfi_clr_istats(const char *, int *, int); void pfctl_print_title(char *); int pfctl_do_clear_tables(const char *, int); diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c index 1d2a60555f19..2d16bbd22b39 100644 --- a/sbin/pfctl/pfctl_optimize.c +++ b/sbin/pfctl/pfctl_optimize.c @@ -1331,7 +1331,8 @@ again: if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1, - pf->astack[0]->path, tbl->pt_buf, pf->astack[0]->ruleset.tticket)) { + pf->astack[0]->path, tbl->pt_buf, pf->astack[0]->ruleset.tticket, + NULL)) { warn("failed to create table %s in %s", tbl->pt_name, pf->astack[0]->name); return (1); diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index ce58e0636022..9609e880584f 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -614,6 +614,20 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts) printf("%14s\n", ""); } } + if (opts & PF_OPT_VERBOSE) { + printf("Fragments\n"); + printf(" %-25s %14ju %14s\n", "current entries", + s->fragments, ""); + TAILQ_FOREACH(c, &s->ncounters, entry) { + printf(" %-25s %14ju ", c->name, + c->counter); + if (runtime > 0) + printf("%14.1f/s\n", + (double)c->counter / (double)runtime); + else + printf("%14s\n", ""); + } + } printf("Counters\n"); TAILQ_FOREACH(c, &s->counters, entry) { printf(" %-25s %14ju ", c->name, c->counter); @@ -844,7 +858,7 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer { static const char *actiontypes[] = { "pass", "block", "scrub", "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr", - "", "", "match"}; + "synproxy drop", "defer", "match", "af-rt", "route-to" }; static const char *anchortypes[] = { "anchor", "anchor", "anchor", "anchor", "nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor", "rdr-anchor", "rdr-anchor" }; @@ -853,21 +867,22 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer if (verbose) printf("@%d ", r->nr); - if (r->action == PF_MATCH) - printf("match"); - else if (r->action > PF_NORDR) - printf("action(%d)", r->action); - else if (anchor_call[0]) { - p = strrchr(anchor_call, '/'); - if (p ? p[1] == '_' : anchor_call[0] == '_') - printf("%s", anchortypes[r->action]); - else - printf("%s \"%s\"", anchortypes[r->action], - anchor_call); + if (anchor_call[0]) { + if (r->action >= nitems(anchortypes)) { + printf("anchor(%d)", r->action); + } else { + p = strrchr(anchor_call, '/'); + if (p ? p[1] == '_' : anchor_call[0] == '_') + printf("%s", anchortypes[r->action]); + else + printf("%s \"%s\"", anchortypes[r->action], + anchor_call); + } } else { - printf("%s", actiontypes[r->action]); - if (r->natpass) - printf(" pass"); + if (r->action >= nitems(actiontypes)) + printf("action(%d)", r->action); + else + printf("%s", actiontypes[r->action]); } if (r->action == PF_DROP) { if (r->rule_flag & PFRULE_RETURN) diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 58d3abc36691..e96ff0195e03 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -36,6 +36,8 @@ #include <libpfctl.h> +#include <pfctl.h> + #define PF_OSFP_FILE "/etc/pf.os" #define PF_OPT_DISABLE 0x00001 @@ -90,6 +92,7 @@ struct pfctl { struct pfioc_queue *pqueue; struct pfr_buffer *trans; struct pfctl_anchor *anchor, *alast; + struct pfr_ktablehead pfr_ktlast; int eth_nr; struct pfctl_eth_anchor *eanchor, *ealast; struct pfctl_eth_anchor *eastack[PFCTL_ANCHOR_STACK_DEPTH]; @@ -277,6 +280,8 @@ struct pf_opt_rule { TAILQ_HEAD(pf_opt_queue, pf_opt_rule); +struct pfr_uktable; + void copy_satopfaddr(struct pf_addr *, struct sockaddr *); int pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *); @@ -303,7 +308,7 @@ int pfctl_cfg_syncookies(struct pfctl *, uint8_t, struct pfctl_watermarks *); int parse_config(char *, struct pfctl *); int parse_flags(char *); -int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *); +int pfctl_load_anchors(int, struct pfctl *); void print_pool(struct pfctl_pool *, u_int16_t, u_int16_t, int); void print_src_node(struct pfctl_src_node *, int); @@ -324,7 +329,7 @@ void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *, int, struct node_queue_opt *); int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *, - u_int32_t); + u_int32_t, struct pfr_uktable *); void pfctl_clear_fingerprints(int, int); int pfctl_file_fingerprints(int, int, const char *); @@ -380,5 +385,8 @@ struct node_host *host(const char *, int); int append_addr(struct pfr_buffer *, char *, int, int); int append_addr_host(struct pfr_buffer *, struct node_host *, int, int); +int pfr_ktable_compare(struct pfr_ktable *, + struct pfr_ktable *); +RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); #endif /* _PFCTL_PARSER_H_ */ diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index 398c5e998330..98f907738d95 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -48,6 +48,7 @@ #include <err.h> #include "pfctl.h" +#include "pfctl_parser.h" #define BUF_SIZE 256 @@ -55,6 +56,19 @@ extern int dev; static int pfr_next_token(char buf[BUF_SIZE], FILE *); +struct pfr_ktablehead pfr_ktables = { 0 }; +RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); + +int +pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q) +{ + int d; + + if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE))) + return (d); + return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor)); +} + static void pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io, const char *err) @@ -256,6 +270,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, struct pfioc_table io; if (tbl == NULL || size < 0 || (size && addr == NULL)) { + DBGPRINT("%s %p %d %p\n", __func__, tbl, size, addr); errno = EINVAL; return (-1); } diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c index 0845f765a063..4955e1791fd7 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -437,14 +437,19 @@ print_table(const struct pfr_table *ta, int verbose, int debug) int print_tstats(const struct pfr_tstats *ts, int debug) { - time_t time = ts->pfrts_tzero; - int dir, op; + time_t time = ts->pfrts_tzero; + int dir, op; + char *ct; if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) return (0); + ct = ctime(&time); print_table(&ts->pfrts_t, 1, debug); printf("\tAddresses: %d\n", ts->pfrts_cnt); - printf("\tCleared: %s", ctime(&time)); + if (ct) + printf("\tCleared: %s", ct); + else + printf("\tCleared: %lld\n", (long long)time); printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n", ts->pfrts_refcnt[PFR_REFCNT_ANCHOR], ts->pfrts_refcnt[PFR_REFCNT_RULE]); @@ -543,12 +548,17 @@ nonzero_astats(struct pfr_astats *as) void print_astats(struct pfr_astats *as, int dns) { - time_t time = as->pfras_tzero; - int dir, op; + time_t time = as->pfras_tzero; + int dir, op; + char *ct; + ct = ctime(&time); print_addrx(&as->pfras_a, NULL, dns); - printf("\tCleared: %s", ctime(&time)); - if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT) + if (ct) + printf("\tCleared: %s", ct); + else + printf("\tCleared: %lld\n", (long long)time); + if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT) return; for (dir = 0; dir < PFR_DIR_MAX; dir++) for (op = 0; op < PFR_OP_ADDR_MAX; op++) @@ -560,19 +570,50 @@ print_astats(struct pfr_astats *as, int dns) int pfctl_define_table(char *name, int flags, int addrs, const char *anchor, - struct pfr_buffer *ab, u_int32_t ticket) + struct pfr_buffer *ab, u_int32_t ticket, struct pfr_uktable *ukt) { - struct pfr_table tbl; + struct pfr_table tbl_buf; + struct pfr_table *tbl; + + if (ukt == NULL) { + bzero(&tbl_buf, sizeof(tbl_buf)); + tbl = &tbl_buf; + } else { + if (ab->pfrb_size != 0) { + /* + * copy IP addresses which come with table from + * temporal buffer to buffer attached to table. + */ + ukt->pfrukt_addrs = *ab; + ab->pfrb_size = 0; + ab->pfrb_msize = 0; + ab->pfrb_caddr = NULL; + } else + memset(&ukt->pfrukt_addrs, 0, + sizeof(struct pfr_buffer)); + + tbl = &ukt->pfrukt_t; + } - bzero(&tbl, sizeof(tbl)); - if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >= - sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor, - sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor)) - errx(1, "pfctl_define_table: strlcpy"); - tbl.pfrt_flags = flags; + if (strlcpy(tbl->pfrt_name, name, sizeof(tbl->pfrt_name)) >= + sizeof(tbl->pfrt_name) || + strlcpy(tbl->pfrt_anchor, anchor, sizeof(tbl->pfrt_anchor)) >= + sizeof(tbl->pfrt_anchor)) + errx(1, "%s: strlcpy", __func__); + tbl->pfrt_flags = flags; + DBGPRINT("%s %s@%s [%x]\n", __func__, tbl->pfrt_name, tbl->pfrt_anchor, + tbl->pfrt_flags); + + /* + * non-root anchors processed by parse.y are loaded to kernel later. + * Here we load tables, which are either created for root anchor + * or by 'pfctl -t ... -T ...' command. + */ + if (ukt != NULL) + return (0); - return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, - NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0); + return (pfr_ina_define(tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, NULL, + ticket, addrs ? PFR_FLAG_ADDRSTOO : 0)); } void @@ -653,8 +694,9 @@ pfctl_show_ifaces(const char *filter, int opts) void print_iface(struct pfi_kif *p, int opts) { - time_t tzero = p->pfik_tzero; - int i, af, dir, act; + time_t tzero = p->pfik_tzero; + int i, af, dir, act; + char *ct; printf("%s", p->pfik_name); if (opts & PF_OPT_VERBOSE) { @@ -665,7 +707,11 @@ print_iface(struct pfi_kif *p, int opts) if (!(opts & PF_OPT_VERBOSE2)) return; - printf("\tCleared: %s", ctime(&tzero)); + ct = ctime(&tzero); + if (ct) + printf("\tCleared: %s", ct); + else + printf("\tCleared: %lld\n", (long long)tzero); printf("\tReferences: %-18d\n", p->pfik_rulerefs); for (i = 0; i < 8; i++) { af = (i>>2) & 1; diff --git a/secure/lib/libcrypto/Makefile b/secure/lib/libcrypto/Makefile index 75ebb6e65327..5cb3f5a7c3fe 100644 --- a/secure/lib/libcrypto/Makefile +++ b/secure/lib/libcrypto/Makefile @@ -91,7 +91,7 @@ SRCS+= x_bignum.c x_info.c x_int64.c x_long.c x_pkey.c x_sig.c x_spki.c SRCS+= x_val.c # async -SRCS+= async.c async_err.c async_posix.c async_wait.c +SRCS+= async.c async_err.c async_null.c async_posix.c async_wait.c async_win.c # bf SRCS+= bf_cfb64.c bf_ecb.c bf_ofb64.c bf_prefix.c bf_readbuff.c bf_skey.c @@ -224,7 +224,11 @@ SRCS+= dsa_gen.c dsa_key.c dsa_lib.c dsa_meth.c dsa_ossl.c dsa_pmeth.c SRCS+= dsa_prn.c dsa_sign.c dsa_vrf.c # dso +SRCS+= dso_dl.c SRCS+= dso_dlfcn.c dso_err.c dso_lib.c +SRCS+= dso_openssl.c +SRCS+= dso_vms.c +SRCS+= dso_win32.c # ec SRCS+= curve25519.c curve448.c curve448_tables.c ec2_oct.c ec2_smpl.c @@ -291,7 +295,7 @@ SRCS+= ffc_params.c ffc_params_generate.c ffc_params_validate.c SRCS+= hashtable.c hashfunc.c # hmac -SRCS+= hmac.c hmac_s390x.c +SRCS+= hmac.c # hpke SRCS+= hpke_util.c hpke.c @@ -424,17 +428,10 @@ SRCS+= cipher_aes_xts_fips.c SRCS+= cipher_aes_gcm_siv.c cipher_aes_gcm_siv_hw.c \ cipher_aes_gcm_siv_polyval.c SRCS+= cipher_aes_siv.c cipher_aes_siv_hw.c -SRCS+= cipher_blowfish.c cipher_blowfish_hw.c SRCS+= cipher_camellia.c cipher_camellia_hw.c -SRCS+= cipher_cast5.c cipher_cast5_hw.c SRCS+= cipher_chacha20.c cipher_chacha20_hw.c SRCS+= cipher_chacha20_poly1305.c cipher_chacha20_poly1305_hw.c -SRCS+= cipher_des.c cipher_des_hw.c -SRCS+= cipher_desx.c cipher_desx_hw.c SRCS+= cipher_null.c -SRCS+= cipher_rc4.c cipher_rc4_hw.c -SRCS+= cipher_rc4_hmac_md5.c cipher_rc4_hmac_md5_hw.c -SRCS+= cipher_seed.c cipher_seed_hw.c SRCS+= cipher_tdes.c cipher_tdes_common.c cipher_tdes_hw.c SRCS+= cipher_tdes_default.c cipher_tdes_default_hw.c \ cipher_tdes_wrap.c cipher_tdes_wrap_hw.c @@ -442,12 +439,10 @@ SRCS+= cipher_tdes_default.c cipher_tdes_default_hw.c \ # providers/implementations/digests SRCS+= digestcommon.c SRCS+= blake2_prov.c blake2b_prov.c blake2s_prov.c -SRCS+= md4_prov.c SRCS+= md5_prov.c md5_sha1_prov.c SRCS+= null_prov.c SRCS+= ripemd_prov.c SRCS+= sha2_prov.c sha3_prov.c -SRCS+= wp_prov.c # providers/implementations/encode_decode SRCS+= decode_der2key.c decode_epki2pki.c decode_msblob2key.c decode_pvk2key.c @@ -463,8 +458,8 @@ SRCS+= kdf_exch.c # providers/implementations/kdfs SRCS+= argon2.c hkdf.c hmacdrbg_kdf.c kbkdf.c krb5kdf.c -SRCS+= pbkdf1.c pbkdf2.c pbkdf2_fips.c -SRCS+= pkcs12kdf.c pvkkdf.c scrypt.c sskdf.c sshkdf.c tls1_prf.c x942kdf.c +SRCS+= pbkdf2.c pbkdf2_fips.c +SRCS+= pkcs12kdf.c scrypt.c sskdf.c sshkdf.c tls1_prf.c x942kdf.c # providers/implementations/kem SRCS+= ec_kem.c ecx_kem.c kem_util.c ml_kem_kem.c mlx_kem.c rsa_kem.c @@ -484,6 +479,7 @@ SRCS+= siphash_prov.c # providers/implementations/rands SRCS+= drbg.c drbg_ctr.c drbg_hash.c drbg_hmac.c test_rng.c SRCS+= seed_src.c +SRCS+= seed_src_jitter.c # providers/implementations/rands/seeding SRCS+= rand_cpu_x86.c rand_tsc.c rand_unix.c rand_win.c @@ -499,7 +495,7 @@ SRCS+= aes_skmgmt.c generic.c SRCS+= file_store.c file_store_any2obj.c # rand -SRCS+= prov_seed.c rand_deprecated.c rand_egd.c rand_err.c rand_lib.c +SRCS+= prov_seed.c rand_deprecated.c rand_err.c rand_lib.c SRCS+= rand_meth.c rand_pool.c rand_uniform.c randfile.c # rc2 @@ -573,7 +569,10 @@ SRCS+= store_err.c store_init.c store_lib.c store_meth.c store_register.c SRCS+= store_result.c store_strings.c # thread -SRCS+= api.c arch.c arch/thread_win.c arch/thread_posix.c arch/thread_none.c internal.c +SRCS+= api.c arch.c internal.c +SRCS+= thread_none.c +SRCS+= thread_posix.c +SRCS+= thread_win.c # ts SRCS+= ts_asn1.c ts_conf.c ts_err.c ts_lib.c ts_req_print.c ts_req_utils.c @@ -620,11 +619,21 @@ SRCS+= x509type.c INCS= aes.h asn1.h asn1err.h asn1t.h async.h asyncerr.h bio.h INCS+= bioerr.h blowfish.h bn.h bnerr.h buffer.h buffererr.h byteorder.h camellia.h -INCS+= cast.h cmac.h cmp.h cmp_util.h cmperr.h cms.h cmserr.h comp.h comperr.h conf.h conf_api.h +INCS+= cast.h cmac.h cmp.h cmp_util.h cmperr.h cms.h cmserr.h comp.h comperr.h conf.h INCS+= conferr.h configuration.h conftypes.h core.h core_dispatch.h core_names.h core_object.h INCS+= crmf.h crmferr.h crypto.h cryptoerr.h cryptoerr_legacy.h ct.h cterr.h -INCS+= decoder.h decodererr.h des.h dh.h dherr.h dsa.h -INCS+= dsaerr.h dtls1.h e_os2.h e_ostime.h ebcdic.h ec.h ecdh.h ecdsa.h ecerr.h encoder.h encodererr.h +INCS+= decoder.h decodererr.h +INCS+= der_digests.h +INCS+= der_dsa.h +INCS+= der_ec.h +INCS+= der_ecx.h +INCS+= der_ml_dsa.h +INCS+= der_rsa.h +INCS+= der_slh_dsa.h +INCS+= der_wrap.h +INCS+= des.h dh.h dherr.h dsa.h +INCS+= dsaerr.h +INCS+= dtls1.h e_os2.h e_ostime.h ebcdic.h ec.h ecdh.h ecdsa.h ecerr.h encoder.h encodererr.h INCS+= engine.h engineerr.h err.h ess.h esserr.h evp.h evperr.h fips_names.h fipskey.h hmac.h hpke.h http.h httperr.h idea.h indicator.h INCS+= kdf.h kdferr.h lhash.h macros.h md2.h md4.h md5.h mdc2.h modes.h obj_mac.h INCS+= objects.h objectserr.h ocsp.h ocsperr.h opensslconf.h opensslv.h @@ -762,6 +771,7 @@ PICFLAG+= -DOPENSSL_PIC ${LCRYPTO_SRC}/crypto/stack \ ${LCRYPTO_SRC}/crypto/store \ ${LCRYPTO_SRC}/crypto/thread \ + ${LCRYPTO_SRC}/crypto/thread/arch \ ${LCRYPTO_SRC}/crypto/ts \ ${LCRYPTO_SRC}/crypto/txt_db \ ${LCRYPTO_SRC}/crypto/ui \ @@ -771,6 +781,7 @@ PICFLAG+= -DOPENSSL_PIC ${LCRYPTO_SRC}/providers \ ${LCRYPTO_SRC}/providers/common \ ${LCRYPTO_SRC}/providers/common/der \ + ${LCRYPTO_SRC}/providers/common/include/prov \ ${LCRYPTO_SRC}/providers/implementations/asymciphers \ ${LCRYPTO_SRC}/providers/implementations/ciphers \ ${LCRYPTO_SRC}/providers/implementations/digests \ @@ -787,4 +798,4 @@ PICFLAG+= -DOPENSSL_PIC ${LCRYPTO_SRC}/providers/implementations/storemgmt \ ${LCRYPTO_SRC}/ssl \ ${LCRYPTO_SRC}/ssl/record \ - ${LCRYPTO_SRC}/ssl/record/methods + ${LCRYPTO_SRC}/ssl/record/methods \ diff --git a/secure/lib/libcrypto/modules/Makefile.inc b/secure/lib/libcrypto/modules/Makefile.inc index 4b3d9fc512ce..64fb57ee74c5 100644 --- a/secure/lib/libcrypto/modules/Makefile.inc +++ b/secure/lib/libcrypto/modules/Makefile.inc @@ -10,11 +10,4 @@ CFLAGS+= -I${LCRYPTO_SRC}/providers/common/include CFLAGS+= -I${LCRYPTO_SRC}/providers/fips/include CFLAGS+= -I${LCRYPTO_SRC}/providers/implementations/include -# common -SRCS+= provider_err.c provider_ctx.c -SRCS+= provider_util.c - -.PATH: ${LCRYPTO_SRC}/providers \ - ${LCRYPTO_SRC}/providers/common - WARNS?= 0 diff --git a/secure/lib/libcrypto/modules/legacy/Makefile b/secure/lib/libcrypto/modules/legacy/Makefile index db05f212f62a..8f91d9504504 100644 --- a/secure/lib/libcrypto/modules/legacy/Makefile +++ b/secure/lib/libcrypto/modules/legacy/Makefile @@ -1,7 +1,7 @@ SHLIB_NAME?= legacy.so LIBADD= crypto -SRCS+= legacyprov.c prov_running.c params_idx.c +SRCS+= legacyprov.c prov_running.c # ciphers SRCS+= ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \ @@ -16,17 +16,48 @@ SRCS+= cipher_rc4.c cipher_rc4_hw.c SRCS+= cipher_rc4_hmac_md5.c cipher_rc4_hmac_md5_hw.c SRCS+= cipher_seed.c cipher_seed_hw.c -# digests +# crypto +SRCS+= cpuid.c +SRCS+= ctype.c + +# crypto/des +SRCS+= des_enc.c +SRCS+= fcrypt_b.c + +# crypto/md5 +SRCS+= md5_dgst.c +SRCS+= md5_one.c +SRCS+= md5_sha1.c + +# providers/implementations/digests SRCS+= digestcommon.c SRCS+= md4_prov.c wp_prov.c ripemd_prov.c -# kdfs -SRCS+= pbkdf1.c pvkkdf.c +# providers/implementations/kdfs +SRCS+= pbkdf1.c +SRCS+= pvkkdf.c + +# common +SRCS+= provider_err.c provider_ctx.c +SRCS+= provider_util.c + +SRCS+= tls_pad.c + +# This is needed so the provider can be loaded for us. +# +# There's a discrepancy between how this provider gets built in OpenSSL proper +# and FreeBSD. +SRCS+= params_idx.c .include <bsd.lib.mk> .PATH: ${LCRYPTO_SRC}/crypto \ + ${LCRYPTO_SRC}/crypto/des \ + ${LCRYPTO_SRC}/crypto/md5 \ + ${LCRYPTO_SRC}/providers \ + ${LCRYPTO_SRC}/providers/common \ ${LCRYPTO_SRC}/providers/implementations/ciphers \ ${LCRYPTO_SRC}/providers/implementations/digests \ ${LCRYPTO_SRC}/providers/implementations/kdfs \ - ${LCRYPTO_SRC}/ssl + ${LCRYPTO_SRC}/ssl \ + ${LCRYPTO_SRC}/ssl/record/methods \ diff --git a/secure/lib/libssl/Makefile b/secure/lib/libssl/Makefile index b0ca31644279..fe2e2492045f 100644 --- a/secure/lib/libssl/Makefile +++ b/secure/lib/libssl/Makefile @@ -76,7 +76,7 @@ CFLAGS+=-DOPENSSL_NO_KTLS SRCS+= ktls_meth.c .endif -LIBADD= crypto +LIBADD= pthread crypto CFLAGS+= -I${LCRYPTO_SRC}/ssl CFLAGS+= -I${.OBJDIR:H}/libcrypto diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 1d708cfda019..f5d7a0e081fc 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,7 +1,7 @@ .include <src.opts.mk> MANGROUPS= MAN -MANPACKAGE= kernel +MANPACKAGE= kernel-man # If you add a new file here, please consider adding an entry to the # hardware notes template (website/archetypes/release/hardware.adoc in @@ -1065,6 +1065,7 @@ MAN+= \ ucom.4 \ ucycom.4 \ udav.4 \ + udbc.4 \ udbp.4 \ udl.4 \ uep.4 \ diff --git a/share/man/man4/cdceem.4 b/share/man/man4/cdceem.4 index 6d8caf53cc02..c2a282027241 100644 --- a/share/man/man4/cdceem.4 +++ b/share/man/man4/cdceem.4 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 2019 Edward Tomasz Napierala <trasz@FreeBSD.org> .\" .\" Redistribution and use in source and binary forms, with or without @@ -20,12 +23,12 @@ .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. -.Dd November 7, 2019 +.Dd September 18, 2025 .Dt CDCEEM 4 .Os .Sh NAME .Nm cdceem -.Nd "USB Communication Device Class Ethernet Emulation Model (CDC EEM) driver" +.Nd USB Communication Device Class Ethernet Emulation Model driver .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your diff --git a/share/man/man4/udbc.4 b/share/man/man4/udbc.4 new file mode 100644 index 000000000000..c8fa02ec18f1 --- /dev/null +++ b/share/man/man4/udbc.4 @@ -0,0 +1,132 @@ +.\" +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" This documentation was written by Tom Jones <thj@freebsd.org> under +.\" sponsorship from the FreeBSD Foundation. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" +.Dd September 3, 2025 +.Dt UDBC 4 +.Os +.Sh NAME +.Nm udbc +.Nd USB Debug Class device driver +.Sh SYNOPSIS +.Cd "device usb" +.Cd "device ucom" +.Cd "device udbc" +.Pp +In +.Xr rc.conf 5 : +.Cd kld_list="udbc" +.Sh DESCRIPTION +The +.Nm +driver provides support for USB Debug Class devices whose +interface class is Diagnostic Class and the subclass is DbC.GP. +.Pp +The USB Debug Class is defined in the USB 3.1 Device Class +Specification for Debug Devices. +This is designed to provide a general-purpose communication channel +for debugging. +It has also been widely implemented in USB xHCs +.Pq USB eXtensible Host Controllers , +which can be found on many commodity computers, +as an optional feature. +Once this feature is enabled on a USB xHC, one of the USB ports will +behave as a USB Debug Class device, +not a host port, +when a USB debug cable is connected. +The supported class in USB xHCs is typically DbC.GP, +while the specification defines several types of Debug Class devices. +The DbC.GP uses IN and OUT endpoint pairs and realizes a single +bidirectional serial communication channel. +On most systems, +including +.Fx , +the DbC.GP is seen as a simple serial device. +.Pp +Most systems with USB xHC can be configured to provide DbC.GP access. +The +.Nm +is a driver that connects to DbC.GP-supported devices, +offering +.Xr tty 4 +devices to connect to them via the +.Xr ucom 4 +device driver. +.Sh HARDWARE CONFIGURATION +A native DbC.GP device can be attached using the +.Nm +driver in a straightforward way. +.Pp +A USB xHC DbC.GP device on a target system needs a special hardware +configuration because all of the ports are supposed to be a USB Host. +There is one method to expose DbC.GP is to use a USB 3.1 A-to-A cable +.Pq section 5.5.2 in USB 3.1 Legacy Cable and Connector Specification . +When this cable is connected to a USB 3.1 port on the target system, +the DbC-enabled USB xHC automatically switches the port as a USB Device. +The +.Nm +driver can find a DbC.GP device on that port. +.Pp +Note that a USB xHC with USB 3.2 support +.Pq USB Type-C connectors +is not compatible with the USB 3.1 A-to-A cable. +Connecting a USB 3.2 C-to-C cable or A-to-C cable does not automatically work, +either, +because it needs role configuration of the port, which is not supported on +.Fx +yet. +.Sh FILES +.Bl -tag -width "/dev/ttyU*.*.init" -compact +.It Pa /dev/ttyU*.* +for callin ports +.It Pa /dev/ttyU*.*.init +.It Pa /dev/ttyU*.*.lock +corresponding callin initial-state and lock-state devices +.Pp +.It Pa /dev/cuaU*.* +for callout ports +.It Pa /dev/cuaU*.*.init +.It Pa /dev/cuaU*.*.lock +corresponding callout initial-state and lock-state devices +.El +.Sh SEE ALSO +.Xr tty 4 , +.Xr ucom 4 , +.Xr usb 4 , +.Xr xhci 4 +.Sh STANDARDS +.Rs +.%T eXtensible Host Controller Interface for Universal Serial Bus (XHCI) +.%U https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf +.Re +.Rs +.%T USB 3.1 Device Class Specification for Debug Devices +.%U https://www.usb.org/sites/default/files/documents/usb_debug_class_rev_1_0_final_0.pdf +.Re +.Rs +.%T USB 3.1 Legacy Cable and Connector Specification +.%U https://www.usb.org/document-library/usb-31-legacy-cable-and-connector-revision-10 +.Re +.Sh HISTORY +The +.Nm +driver first appeared +.Fx +15.0. +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Hiroki Sato Aq Mt hrs@FreeBSD.org . +.Sh BUGS +According to the XHCI specification the host side of USB Debug should work with +any USB 3.0 port, +whether connected directly to a controller or with a hub in between. +Testing on some controllers has encountered issues when using a hub rather than +a directly connected port on the controller. diff --git a/share/man/man4/vtnet.4 b/share/man/man4/vtnet.4 index 1df79da5f42e..0594ca70e99a 100644 --- a/share/man/man4/vtnet.4 +++ b/share/man/man4/vtnet.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 8, 2025 +.Dd September 16, 2025 .Dt VTNET 4 .Os .Sh NAME @@ -84,6 +84,8 @@ field of the structure .Vt struct virtio_net_hdr . It also marks the checksum as being correct in the mbuf packet header. The default value is 0. +This tunable is deprecated and will be removed in +.Fx 16 . .It Va hw.vtnet.tso_disable .It Va hw.vtnet. Ns Ar X Ns Va .tso_disable This tunable disables TCP segmentation offloading. diff --git a/share/man/man5/group.5 b/share/man/man5/group.5 index 044164a3c955..8f7c59c59d52 100644 --- a/share/man/man5/group.5 +++ b/share/man/man5/group.5 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 8, 2013 +.Dd August 29, 2025 .Dt GROUP 5 .Os .Sh NAME @@ -145,6 +145,7 @@ may still have this limit. .Sh SEE ALSO .Xr newgrp 1 , .Xr passwd 1 , +.Xr setcred 2 , .Xr setgroups 2 , .Xr crypt 3 , .Xr getgrent 3 , diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index bdd8a843d72a..02114b3eaf3c 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -27,7 +27,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd July 30, 2025 +.Dd August 25, 2025 .Dt PF.CONF 5 .Os .Sh NAME @@ -92,14 +92,20 @@ keyword, for example: include "/etc/pf/sub.filter.conf" .Ed .Sh MACROS -Macros can be defined that will later be expanded in context. -Macro names must start with a letter, and may contain letters, digits -and underscores. -Macro names may not be reserved words (for example +A macro is defined with a command of the form +.Ar name Ns = Ns Ar value . +The macro +.Ar name +can contain letters, digits, and underscores and cannot be a reserved word +(for example, .Ar pass , .Ar in , +or .Ar out ) . -Macros are not expanded inside quotes. +Within unquoted arguments, the string +.Pf $ Ar name +is later expanded to +.Ar value . Ranges of network addresses used in macros that will be expanded in lists later on must be quoted with additional simple quotes. .Pp @@ -267,6 +273,10 @@ which corresponds to the connection state. Each packet which matches this state will reset the TTL. Tuning these values may improve the performance of the firewall at the risk of dropping valid idle connections. +Alternatively, these values may be adjusted collectively +in a manner suitable for a specific environment using +.Cm set optimization +(see above). .Pp .Bl -tag -width xxxx -compact .It Ar tcp.first @@ -274,6 +284,9 @@ The state after the first packet. .It Ar tcp.opening The state after the second packet but before both endpoints have acknowledged the connection. +.It Ar tcp.tsdiff +Maximum allowed time difference between RFC 1323 compliant packet timestamps. +30 seconds by default. .It Ar tcp.established The fully established state. .It Ar tcp.closing @@ -3580,7 +3593,7 @@ fragmentation = [ "fragment reassemble" ] timeout-list = timeout [ [ "," ] timeout-list ] timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" | - "tcp.closing" | "tcp.finwait" | "tcp.closed" | + "tcp.closing" | "tcp.finwait" | "tcp.closed" | "tcp.tsdiff" | "sctp.first" | "sctp.opening" | "sctp.established" | "sctp.closing" | "sctp.closed" | "udp.first" | "udp.single" | "udp.multiple" | diff --git a/share/man/man7/release.7 b/share/man/man7/release.7 index 36c14afe0bf1..05f80374926f 100644 --- a/share/man/man7/release.7 +++ b/share/man/man7/release.7 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 20, 2025 +.Dd September 11, 2025 .Dt RELEASE 7 .Os .Sh NAME @@ -286,6 +286,19 @@ is expected to exist by alternative means. Include base system packages for use with .Xr pkg 8 on the install media, instead of legacy tarball distribution sets. +.It Va PKG_CMD +A path to the +.Xr pkg 8 +executable to use when installing packages in release images as a non-root user. +.It Va PKG_REPOS_DIR +An optional path to a directory containing +.Xr pkg 8 +repository configuration files. +These configuration files will be used when installing packages in release +images as a non-root user. +.It Va PKG_REPO_NAME +The name of the repository configuration to use when installing packages in +release images as a non-root user. .El .Sh EMBEDDED BUILDS The following diff --git a/share/man/man9/MODULE_PNP_INFO.9 b/share/man/man9/MODULE_PNP_INFO.9 index 529afd70096d..b1cc935b1aca 100644 --- a/share/man/man9/MODULE_PNP_INFO.9 +++ b/share/man/man9/MODULE_PNP_INFO.9 @@ -65,7 +65,7 @@ The second name is encoded by appending a forward slash and the second name after the first.) .Pp Types are one of the following: -.Bl -tag -width U16 +.Bl -tag -width indent .It Dq Vt U8 .Vt uint8_t element. diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 5bcde3030ebc..fe764e7c4ed7 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1,6 +1,6 @@ .include <src.opts.mk> -PACKAGE= kernel +PACKAGE= kernel-man MAN= accept_filter.9 \ accf_data.9 \ @@ -417,7 +417,7 @@ MAN= accept_filter.9 \ vn_deallocate.9 \ vn_fullpath.9 \ vn_isdisk.9 \ - vnet.9 \ + VNET.9 \ vnode.9 \ vnode_pager_setsize.9 \ vnode_pager_purge_range.9 \ @@ -2474,7 +2474,7 @@ MLINKS+=VOP_OPENCLOSE.9 VOP_CLOSE.9 \ MLINKS+=VOP_RDWR.9 VOP_READ.9 \ VOP_RDWR.9 VOP_WRITE.9 MLINKS+=VOP_REMOVE.9 VOP_RMDIR.9 -MLINKS+=vnet.9 vimage.9 +MLINKS+=VNET.9 VIMAGE.9 MLINKS+=vref.9 VREF.9 \ vref.9 vrefl.9 MLINKS+=vrele.9 vput.9 \ diff --git a/share/man/man9/vnet.9 b/share/man/man9/VNET.9 index 28e28bfd3242..28e28bfd3242 100644 --- a/share/man/man9/vnet.9 +++ b/share/man/man9/VNET.9 diff --git a/share/man/man9/taskqueue.9 b/share/man/man9/taskqueue.9 index 5afeffcb558b..8ffa9a96d816 100644 --- a/share/man/man9/taskqueue.9 +++ b/share/man/man9/taskqueue.9 @@ -530,7 +530,7 @@ If queueing delays cannot be tolerated then a private taskqueue should be created with a dedicated processing thread. .Sh SEE ALSO .Xr callout 9 , -.Xr ithread 9 , +.Xr intr_event 9 , .Xr kthread 9 , .Xr swi 9 .Sh HISTORY diff --git a/share/man/man9/ucred.9 b/share/man/man9/ucred.9 index 38759bddb5b0..453df386ff18 100644 --- a/share/man/man9/ucred.9 +++ b/share/man/man9/ucred.9 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH .\" DAMAGE. .\" -.Dd July 29, 2025 +.Dd August 29, 2025 .Dt UCRED 9 .Os .Sh NAME @@ -113,28 +113,26 @@ The actual copying is performed by .Pp The .Fn crsetgroups -and -.Fn crsetgroups_and_egid -functions set the +function sets the .Va cr_groups and .Va cr_ngroups -variables and allocates space as needed. -They also truncate the group list to the current maximum number of -groups. -No other mechanism should be used to modify the -.Va cr_groups -array. -Note that +variables representing the supplementary groups, allocating space as needed. +It also truncates the group list to the current maximum number of groups. +The .Fn crsetgroups_and_egid -will interpret the first element of +function is similar, but interprets separately the first group of .Va groups -as the new effective GID and the rest of the array as the supplementary groups, -and +as the effective GID to set, only setting the subsequent groups as supplementary +ones. +It will use .Va default_egid -will be used as the new effective GID only if +as the new effective GID if .Va groups is empty. +No other mechanism should be used to modify the +.Va cr_groups +array. .Pp The .Fn cru2x diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index 73d142b875f2..6035dd031216 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -211,6 +211,7 @@ igoro [label="Igor Ostapenko\nigoro@FreeBSD.org\n2024/08/22"] imp [label="Warner Losh\nimp@FreeBSD.org\n1996/09/20"] ivoras [label="Ivan Voras\nivoras@FreeBSD.org\n2008/06/10"] ivy [label="Lexi Winter\nivy@FreeBSD.org\n2025/04/18"] +jaeyoon [label="Jaeyoon Choi\njaeyoon@FreeBSD.org\n2025/09/09"] jah [label="Jason A. Harmening\njah@FreeBSD.org\n2015/03/08"] jamie [label="Jamie Gritton\njamie@FreeBSD.org\n2009/01/28"] jasone [label="Jason Evans\njasone@FreeBSD.org\n1999/03/03"] @@ -642,6 +643,7 @@ imp -> toshi imp -> tsoome imp -> uch imp -> vexeduxr +imp -> jaeyoon jake -> bms jake -> gordon diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index 6caad8956c14..065e635ed43d 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -74,7 +74,14 @@ LIB_TAG_ARGS= ${TAG_ARGS} TAG_ARGS= -T ${TAGS:ts,:[*]} DBG_TAG_ARGS= ${TAG_ARGS},dbg +# Usually we want to put development files (e.g., static libraries) into a +# separate -dev packages but for a few cases, like tests, that's not wanted, +# so allow the caller to disable it by setting NO_DEV_PACKAGE. +.if !defined(NO_DEV_PACKAGE) DEV_TAG_ARGS= ${TAG_ARGS},dev +.else +DEV_TAG_ARGS= ${TAG_ARGS} +.endif .endif # !defined(NO_ROOT) # ELF hardening knobs @@ -450,7 +457,11 @@ LINKGRP?= ${LIBGRP} LINKMODE?= ${LIBMODE} SYMLINKOWN?= ${LIBOWN} SYMLINKGRP?= ${LIBGRP} +.if !defined(NO_DEV_PACKAGE) LINKTAGS= dev${_COMPAT_TAG} +.else +LINKTAGS= ${_COMPAT_TAG} +.endif .include <bsd.links.mk> .if ${MK_MAN} != "no" && !defined(LIBRARIES_ONLY) diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk index a2c34eff9e3e..0a3594e05d94 100644 --- a/share/mk/bsd.man.mk +++ b/share/mk/bsd.man.mk @@ -105,15 +105,16 @@ manlinksinstall: manlinksinstall-${__group} ${__group}OWN?= ${MANOWN} ${__group}GRP?= ${MANGRP} ${__group}MODE?= ${MANMODE} +${__group}PACKAGE?= ${PACKAGE:Uutilities} # Tag processing is only done for NO_ROOT installs. .if defined(NO_ROOT) .if !defined(${__group}TAGS) || ! ${${__group}TAGS:Mpackage=*} -.if ${MK_MANSPLITPKG} == "no" -${__group}TAGS+= package=${${__group}PACKAGE:U${PACKAGE:Uutilities}} +.if ${MK_MANSPLITPKG} == "no" || ${${__group}PACKAGE:M*-man} +${__group}TAGS+= package=${${__group}PACKAGE} .else -${__group}TAGS+= package=${${__group}PACKAGE:U${PACKAGE:Uutilities}}-man +${__group}TAGS+= package=${${__group}PACKAGE}-man .endif .endif diff --git a/share/mk/bsd.test.mk b/share/mk/bsd.test.mk index a2e15c840e02..9f20e5835369 100644 --- a/share/mk/bsd.test.mk +++ b/share/mk/bsd.test.mk @@ -16,6 +16,9 @@ LOCALBASE?= /usr/local TESTSDIR?= ${TESTSBASE}/${RELDIR:H} PACKAGE?= tests +# Prevent creating a -dev package for tests. Sometimes tests include static +# libraries or other artifacts which are not actually "development" files. +NO_DEV_PACKAGE= FILESGROUPS+= ${PACKAGE}FILES ${PACKAGE}FILESPACKAGE= ${PACKAGE} diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index 9ca043e7733c..95cd3b02d8e4 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -29,6 +29,7 @@ _PRIVATELIBS= \ heimipcs \ kldelf \ ldns \ + samplerate \ sqlite3 \ ssh \ ucl \ @@ -72,7 +73,6 @@ _INTERNALLIBS= \ pfctl \ pkgecc \ pmcstat \ - samplerate \ sl \ sm \ smdb \ @@ -329,7 +329,7 @@ _DP_archive+= md .endif .endif _DP_sqlite3= pthread -_DP_ssl= crypto +_DP_ssl= pthread crypto _DP_ssh= crypto crypt z .if ${MK_LDNS} != "no" _DP_ssh+= ldns diff --git a/stand/efi/acpica/acpi_detect.c b/stand/efi/acpica/acpi_detect.c new file mode 100644 index 000000000000..1f15a882ff9d --- /dev/null +++ b/stand/efi/acpica/acpi_detect.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2014 Ed Maste <emaste@freebsd.org> + * Copyright (c) 2025 Kayla Powell <kpowkitty@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <machine/_inttypes.h> +#include <efi.h> +#include <acpi.h> +#include "acpi_detect.h" + +/* For ACPI rsdp discovery. */ +EFI_GUID acpi = ACPI_TABLE_GUID; +EFI_GUID acpi20 = ACPI_20_TABLE_GUID; +ACPI_TABLE_RSDP *rsdp; + +void +acpi_detect(void) +{ + char buf[24]; + int revision; + + feature_enable(FEATURE_EARLY_ACPI); + if ((rsdp = efi_get_table(&acpi20)) == NULL) + if ((rsdp = efi_get_table(&acpi)) == NULL) + return; + + sprintf(buf, "0x%016"PRIxPTR, (uintptr_t)rsdp); + setenv("acpi.rsdp", buf, 1); + revision = rsdp->Revision; + if (revision == 0) + revision = 1; + sprintf(buf, "%d", revision); + setenv("acpi.revision", buf, 1); + strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); + buf[sizeof(rsdp->OemId)] = '\0'; + setenv("acpi.oem", buf, 1); + sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); + setenv("acpi.rsdt", buf, 1); + if (revision >= 2) { + /* XXX extended checksum? */ + sprintf(buf, "0x%016llx", + (unsigned long long)rsdp->XsdtPhysicalAddress); + setenv("acpi.xsdt", buf, 1); + sprintf(buf, "%d", rsdp->Length); + setenv("acpi.xsdt_length", buf, 1); + } +} diff --git a/stand/efi/acpica/include/acpi_detect.h b/stand/efi/acpica/include/acpi_detect.h new file mode 100644 index 000000000000..246e790be9fb --- /dev/null +++ b/stand/efi/acpica/include/acpi_detect.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Kayla Powell <kpowkitty@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACPI_DETECT_H +#define ACPI_DETECT_H + +#include <efi.h> +#include <efilib.h> + +struct ACPI_TABLE_RSDP; // forward declaration + +extern EFI_GUID acpi; +extern EFI_GUID acpi20; +extern ACPI_TABLE_RSDP *rsdp; + +void acpi_detect(void); + +#endif diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile index b30c563d4331..b4520b957b74 100644 --- a/stand/efi/loader/Makefile +++ b/stand/efi/loader/Makefile @@ -30,6 +30,10 @@ SRCS= autoload.c \ gfx_fb.c \ 8x16.c +SRCS+= acpi_detect.c +.PATH: ${EFISRC}/acpica +CFLAGS+= -I${EFISRC}/acpica/include + CFLAGS+= -I${.CURDIR}/../loader .if ${MK_LOADER_ZFS} != "no" CFLAGS+= -I${ZFSSRC} diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 304b2e48272c..2e51f15f0b5f 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -69,6 +69,8 @@ #include "actypes.h" #include "actbl.h" +#include <acpi_detect.h> + #include "loader_efi.h" struct arch_switch archsw = { /* MI/MD interface boundary */ @@ -83,8 +85,6 @@ struct arch_switch archsw = { /* MI/MD interface boundary */ .arch_zfs_probe = efi_zfs_probe, }; -EFI_GUID acpi = ACPI_TABLE_GUID; -EFI_GUID acpi20 = ACPI_20_TABLE_GUID; EFI_GUID devid = DEVICE_PATH_PROTOCOL; EFI_GUID imgid = LOADED_IMAGE_PROTOCOL; EFI_GUID mps = MPS_TABLE_GUID; @@ -120,11 +120,6 @@ UINT16 boot_current; */ EFI_LOADED_IMAGE *boot_img; -/* - * RSDP base table. - */ -ACPI_TABLE_RSDP *rsdp; - static bool has_keyboard(void) { @@ -1130,39 +1125,6 @@ ptov(uintptr_t x) } static void -acpi_detect(void) -{ - char buf[24]; - int revision; - - feature_enable(FEATURE_EARLY_ACPI); - if ((rsdp = efi_get_table(&acpi20)) == NULL) - if ((rsdp = efi_get_table(&acpi)) == NULL) - return; - - sprintf(buf, "0x%016"PRIxPTR, (uintptr_t)rsdp); - setenv("acpi.rsdp", buf, 1); - revision = rsdp->Revision; - if (revision == 0) - revision = 1; - sprintf(buf, "%d", revision); - setenv("acpi.revision", buf, 1); - strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); - buf[sizeof(rsdp->OemId)] = '\0'; - setenv("acpi.oem", buf, 1); - sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); - setenv("acpi.rsdt", buf, 1); - if (revision >= 2) { - /* XXX extended checksum? */ - sprintf(buf, "0x%016llx", - (unsigned long long)rsdp->XsdtPhysicalAddress); - setenv("acpi.xsdt", buf, 1); - sprintf(buf, "%d", rsdp->Length); - setenv("acpi.xsdt_length", buf, 1); - } -} - -static void efi_smbios_detect(void) { VOID *smbios_v2_ptr = NULL; diff --git a/stand/man/boot1.efi.8 b/stand/man/boot1.efi.8 index b6135f8e0e12..2c882a595592 100644 --- a/stand/man/boot1.efi.8 +++ b/stand/man/boot1.efi.8 @@ -1,4 +1,6 @@ .\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 2020 Netflix, Inc .\" .\" Redistribution and use in source and binary forms, with or without diff --git a/stand/man/loader.8 b/stand/man/loader.8 index 4fc3bbb7cff0..234eabd571e0 100644 --- a/stand/man/loader.8 +++ b/stand/man/loader.8 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" Copyright (c) 2021 Warner Losh <imp@FreeBSD.org> @@ -115,11 +118,11 @@ scripting language changed to Lua by default in The .Nm was written by -.An Michael Smith Aq msmith@FreeBSD.org . +.An Michael Smith Aq Mt msmith@FreeBSD.org . .Pp FICL was written by -.An John Sadler Aq john_sadler@alum.mit.edu . +.An John Sadler Aq Mt john_sadler@alum.mit.edu . .Pp -.An Warner Losh Aq imp@FreeBSD.org +.An Warner Losh Aq Mt imp@FreeBSD.org integrated Lua into the tree based on initial work done by Pedro Souza for the 2014 Google Summer of Code. diff --git a/stand/man/loader_4th.8 b/stand/man/loader_4th.8 index 9e87326f893b..21e907bd8630 100644 --- a/stand/man/loader_4th.8 +++ b/stand/man/loader_4th.8 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" @@ -576,8 +579,8 @@ first appeared in The .Nm was written by -.An Michael Smith Aq msmith@FreeBSD.org . +.An Michael Smith Aq Mt msmith@FreeBSD.org . .Pp .Tn FICL was written by -.An John Sadler Aq john_sadler@alum.mit.edu . +.An John Sadler Aq Mt john_sadler@alum.mit.edu . diff --git a/stand/man/loader_lua.8 b/stand/man/loader_lua.8 index 0aa467237266..c60de9417abc 100644 --- a/stand/man/loader_lua.8 +++ b/stand/man/loader_lua.8 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" diff --git a/stand/man/loader_simp.8 b/stand/man/loader_simp.8 index cdacd823b1a5..683ca8b2da5d 100644 --- a/stand/man/loader_simp.8 +++ b/stand/man/loader_simp.8 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 1999 Daniel C. Sobral .\" All rights reserved. .\" @@ -755,4 +758,4 @@ first appeared in The .Nm was written by -.An Michael Smith Aq msmith@FreeBSD.org . +.An Michael Smith Aq Mt msmith@FreeBSD.org . diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index d180f5c76afb..e6c9f47ea261 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -76,7 +76,7 @@ static __inline void clflushopt(u_long addr) { - __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); + __asm __volatile("clflushopt %0" : : "m" (*(char *)addr)); } static __inline void diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index 97976408c943..c4a1f44a0079 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -889,7 +889,7 @@ wfxt_check(const struct cpu_feat *feat __unused, u_int midr __unused) if (!get_kernel_reg(ID_AA64ISAR2_EL1, &id_aa64isar2)) return (FEAT_ALWAYS_DISABLE); - if (ID_AA64ISAR2_WFxT_VAL(id_aa64isar2) >= ID_AA64ISAR2_WFxT_NONE) + if (ID_AA64ISAR2_WFxT_VAL(id_aa64isar2) >= ID_AA64ISAR2_WFxT_IMPL) return (FEAT_DEFAULT_ENABLE); return (FEAT_ALWAYS_DISABLE); @@ -905,8 +905,15 @@ wfxt_enable(const struct cpu_feat *feat __unused, return (true); } +static void +wfxt_disabled(const struct cpu_feat *feat __unused) +{ + if (PCPU_GET(cpuid) == 0) + update_special_reg(ID_AA64ISAR2_EL1, ID_AA64ISAR2_WFxT_MASK, 0); +} + CPU_FEAT(feat_wfxt, "WFE and WFI instructions with timeout", - wfxt_check, NULL, wfxt_enable, + wfxt_check, NULL, wfxt_enable, wfxt_disabled, CPU_FEAT_AFTER_DEV | CPU_FEAT_SYSTEM); #endif diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h index f3313b136656..f66953710615 100644 --- a/sys/arm/include/atomic.h +++ b/sys/arm/include/atomic.h @@ -1103,11 +1103,9 @@ atomic_thread_fence_seq_cst(void) #define atomic_store_rel_int atomic_store_rel_32 #define atomic_swap_int atomic_swap_32 -/* - * For: - * - atomic_load_acq_8 - * - atomic_load_acq_16 - */ #include <sys/_atomic_subword.h> +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 + #endif /* _MACHINE_ATOMIC_H_ */ diff --git a/sys/arm64/arm64/cpu_feat.c b/sys/arm64/arm64/cpu_feat.c index 986d5079e980..94114d47f846 100644 --- a/sys/arm64/arm64/cpu_feat.c +++ b/sys/arm64/arm64/cpu_feat.c @@ -54,6 +54,21 @@ enable_cpu_feat(uint32_t stage) SET_FOREACH(featp, cpu_feat_set) { feat = *featp; + /* Read any tunable the user may have set */ + if (stage == CPU_FEAT_EARLY_BOOT && PCPU_GET(cpuid) == 0) { + snprintf(tunable, sizeof(tunable), "hw.feat.%s", + feat->feat_name); + if (TUNABLE_BOOL_FETCH(tunable, &val)) { + if (val) { + feat->feat_flags |= + CPU_FEAT_USER_ENABLED; + } else { + feat->feat_flags |= + CPU_FEAT_USER_DISABLED; + } + } + } + /* Run the enablement code at the correct stage of boot */ if ((feat->feat_flags & CPU_FEAT_STAGE_MASK) != stage) continue; @@ -63,25 +78,26 @@ enable_cpu_feat(uint32_t stage) PCPU_GET(cpuid) != 0) continue; - if (feat->feat_check != NULL) - continue; - - check_status = feat->feat_check(feat, midr); + if (feat->feat_check != NULL) { + check_status = feat->feat_check(feat, midr); + } else { + check_status = FEAT_DEFAULT_ENABLE; + } /* Ignore features that are not present */ if (check_status == FEAT_ALWAYS_DISABLE) - continue; + goto next; - snprintf(tunable, sizeof(tunable), "hw.feat.%s", - feat->feat_name); - if (TUNABLE_BOOL_FETCH(tunable, &val)) { - /* Is the feature disabled by the tunable? */ - if (!val) - continue; - /* If enabled by the tunable then enable it */ - } else if (check_status == FEAT_DEFAULT_DISABLE) { - /* No tunable set and disabled by default */ - continue; - } + /* The user disabled the feature */ + if ((feat->feat_flags & CPU_FEAT_USER_DISABLED) != 0) + goto next; + + /* + * The feature was disabled by default and the user + * didn't enable it then skip. + */ + if (check_status == FEAT_DEFAULT_DISABLE && + (feat->feat_flags & CPU_FEAT_USER_ENABLED) == 0) + goto next; /* * Check if the feature has any errata that may need a @@ -122,6 +138,10 @@ enable_cpu_feat(uint32_t stage) if (feat->feat_enable(feat, errata_status, errata_list, errata_count)) feat->feat_enabled = true; + +next: + if (!feat->feat_enabled && feat->feat_disabled != NULL) + feat->feat_disabled(feat); } } diff --git a/sys/arm64/arm64/exception.S b/sys/arm64/arm64/exception.S index 13095def8b00..5a4181348a54 100644 --- a/sys/arm64/arm64/exception.S +++ b/sys/arm64/arm64/exception.S @@ -42,10 +42,9 @@ */ .macro save_registers_head el .if \el == 1 - mov x18, sp - stp x0, x1, [sp, #(TF_X - TF_SIZE - 128)]! + stp x0, x1, [sp, #-(TF_SIZE - TF_X + 128)]! .else - stp x0, x1, [sp, #(TF_X - TF_SIZE)]! + stp x0, x1, [sp, #-(TF_SIZE - TF_X)]! .endif stp x2, x3, [sp, #(2 * 8)] stp x4, x5, [sp, #(4 * 8)] @@ -61,7 +60,9 @@ stp x24, x25, [sp, #(24 * 8)] stp x26, x27, [sp, #(26 * 8)] stp x28, x29, [sp, #(28 * 8)] -.if \el == 0 +.if \el == 1 + add x18, sp, #(TF_SIZE - TF_X + 128) +.else mrs x18, sp_el0 .endif mrs x10, elr_el1 diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c index a001be200518..2d07420bcdb0 100644 --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -232,6 +232,10 @@ static const struct cpu_parts cpu_parts_arm[] = { { CPU_PART_CORTEX_X2, "Cortex-X2" }, { CPU_PART_CORTEX_X3, "Cortex-X3" }, { CPU_PART_CORTEX_X4, "Cortex-X4" }, + { CPU_PART_C1_NANO, "C1-Nano" }, + { CPU_PART_C1_PRO, "C1-Pro" }, + { CPU_PART_C1_PREMIUM, "C1-Premium" }, + { CPU_PART_C1_ULTRA, "C1-Ultra" }, { CPU_PART_NEOVERSE_E1, "Neoverse-E1" }, { CPU_PART_NEOVERSE_N1, "Neoverse-N1" }, { CPU_PART_NEOVERSE_N2, "Neoverse-N2" }, @@ -2349,7 +2353,7 @@ user_ctr_enable(const struct cpu_feat *feat __unused, } CPU_FEAT(trap_ctr, "Trap CTR_EL0", - user_ctr_check, user_ctr_has_errata, user_ctr_enable, + user_ctr_check, user_ctr_has_errata, user_ctr_enable, NULL, CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU); static bool diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 4a10a2b4f2d3..50a3eda846da 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -39,6 +39,23 @@ #define VIRT_BITS 48 +/* + * Loads a 64-bit value into reg using 1 to 4 mov/movk instructions. + * This can be used early on when we don't know the CPUs endianness. + */ +.macro mov_q reg, val + mov \reg, :abs_g0_nc:\val +.if (\val >> 16) & 0xffff != 0 + movk \reg, :abs_g1_nc:\val +.endif +.if (\val >> 32) & 0xffff != 0 + movk \reg, :abs_g2_nc:\val +.endif +.if (\val >> 48) & 0xffff != 0 + movk \reg, :abs_g3:\val +.endif +.endm + #if PAGE_SIZE == PAGE_SIZE_16K /* * The number of level 3 tables to create. 32 will allow for 1G of address @@ -324,15 +341,23 @@ LENTRY(enter_kernel_el) cmp x23, #(CURRENTEL_EL_EL2) b.eq 1f - ldr x2, =SCTLR_MMU_OFF + /* + * Ensure there are no memory operations here. If the boot loader + * enters the kernel in big-endian mode then loading sctlr will + * be incorrect. As instructions are the same in both endians it is + * safe to use mov instructions. + */ + mov_q x2, SCTLR_MMU_OFF msr sctlr_el1, x2 - /* SCTLR_EOS is set so eret is a context synchronizing event so we + /* + * SCTLR_EOS is set to make eret a context synchronizing event. We * need an isb here to ensure it's observed by later instructions, * but don't need it in the eret below. */ isb - /* Ensure SPSR_EL1 and pstate are in sync. The only wat to set the + /* + * Ensure SPSR_EL1 and pstate are in sync. The only way to set the * latter is to set the former and return from an exception with eret. */ mov x2, #(PSR_DAIF | PSR_M_EL1h) @@ -346,11 +371,19 @@ LENTRY(enter_kernel_el) * Set just the reserved bits in sctlr_el2. This will disable the * MMU which may have broken the kernel if we enter the kernel in * EL2, e.g. when using VHE. + * + * As with sctlr_el1 above use mov instructions to ensure there are + * no memory operations. */ - ldr x2, =(SCTLR_EL2_RES1 | SCTLR_EL2_EIS | SCTLR_EL2_EOS) + mov_q x2, (SCTLR_EL2_RES1 | SCTLR_EL2_EIS | SCTLR_EL2_EOS) msr sctlr_el2, x2 isb + /* + * The hardware is now in little-endian mode so memory operations + * are safe. + */ + /* Configure the Hypervisor */ ldr x2, =(HCR_RW | HCR_APK | HCR_API) msr hcr_el2, x2 diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 47c701e8588c..322bad273a08 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -178,7 +178,8 @@ pan_check(const struct cpu_feat *feat __unused, u_int midr __unused) { uint64_t id_aa64mfr1; - id_aa64mfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); + if (!get_kernel_reg(ID_AA64MMFR1_EL1, &id_aa64mfr1)) + return (FEAT_ALWAYS_DISABLE); if (ID_AA64MMFR1_PAN_VAL(id_aa64mfr1) == ID_AA64MMFR1_PAN_NONE) return (FEAT_ALWAYS_DISABLE); @@ -207,9 +208,16 @@ pan_enable(const struct cpu_feat *feat __unused, return (true); } +static void +pan_disabled(const struct cpu_feat *feat __unused) +{ + if (PCPU_GET(cpuid) == 0) + update_special_reg(ID_AA64MMFR1_EL1, ID_AA64MMFR1_PAN_MASK, 0); +} + CPU_FEAT(feat_pan, "Privileged access never", - pan_check, NULL, pan_enable, - CPU_FEAT_EARLY_BOOT | CPU_FEAT_PER_CPU); + pan_check, NULL, pan_enable, pan_disabled, + CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU); bool has_hyp(void) diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 8a4395aa1c89..dbf5c820d20b 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -1722,7 +1722,7 @@ pmap_dbm_enable(const struct cpu_feat *feat __unused, } CPU_FEAT(feat_hafdbs, "Hardware management of the Access flag and dirty state", - pmap_dbm_check, pmap_dbm_has_errata, pmap_dbm_enable, + pmap_dbm_check, pmap_dbm_has_errata, pmap_dbm_enable, NULL, CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU); static cpu_feat_en @@ -1767,7 +1767,7 @@ pmap_multiple_tlbi_enable(const struct cpu_feat *feat __unused, } CPU_FEAT(errata_multi_tlbi, "Multiple TLBI errata", - pmap_multiple_tlbi_check, NULL, pmap_multiple_tlbi_enable, + pmap_multiple_tlbi_check, NULL, pmap_multiple_tlbi_enable, NULL, CPU_FEAT_EARLY_BOOT | CPU_FEAT_PER_CPU); /* diff --git a/sys/arm64/arm64/ptrauth.c b/sys/arm64/arm64/ptrauth.c index fdab5414e24c..ab40b72887e9 100644 --- a/sys/arm64/arm64/ptrauth.c +++ b/sys/arm64/arm64/ptrauth.c @@ -97,11 +97,11 @@ ptrauth_check(const struct cpu_feat *feat __unused, u_int midr __unused) if (!pac_enable) { if (boothowto & RB_VERBOSE) printf("Pointer authentication is disabled\n"); - goto out; + return (FEAT_ALWAYS_DISABLE); } if (ptrauth_disable()) - goto out; + return (FEAT_ALWAYS_DISABLE); /* * This assumes if there is pointer authentication on the boot CPU @@ -127,17 +127,6 @@ ptrauth_check(const struct cpu_feat *feat __unused, u_int midr __unused) } } -out: - /* - * Pointer authentication may be disabled, mask out the ID fields we - * expose to userspace and the rest of the kernel so they don't try - * to use it. - */ - update_special_reg(ID_AA64ISAR1_EL1, ID_AA64ISAR1_API_MASK | - ID_AA64ISAR1_APA_MASK | ID_AA64ISAR1_GPA_MASK | - ID_AA64ISAR1_GPI_MASK, 0); - update_special_reg(ID_AA64ISAR2_EL1, ID_AA64ISAR2_APA3_MASK, 0); - return (FEAT_ALWAYS_DISABLE); } @@ -157,8 +146,25 @@ ptrauth_enable(const struct cpu_feat *feat __unused, return (true); } +static void +ptrauth_disabled(const struct cpu_feat *feat __unused) +{ + /* + * Pointer authentication may be disabled, mask out the ID fields we + * expose to userspace and the rest of the kernel so they don't try + * to use it. + */ + if (PCPU_GET(cpuid) == 0) { + update_special_reg(ID_AA64ISAR1_EL1, ID_AA64ISAR1_API_MASK | + ID_AA64ISAR1_APA_MASK | ID_AA64ISAR1_GPA_MASK | + ID_AA64ISAR1_GPI_MASK, 0); + update_special_reg(ID_AA64ISAR2_EL1, ID_AA64ISAR2_APA3_MASK, 0); + } + +} + CPU_FEAT(feat_pauth, "Pointer Authentication", - ptrauth_check, NULL, ptrauth_enable, + ptrauth_check, NULL, ptrauth_enable, ptrauth_disabled, CPU_FEAT_EARLY_BOOT | CPU_FEAT_SYSTEM); /* Copy the keys when forking a new process */ diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 500f35c48787..c2065fdb3f8c 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -2612,10 +2612,12 @@ (SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_EIS | SCTLR_TSCXT | SCTLR_EOS) #define SCTLR_MMU_ON \ (SCTLR_MMU_OFF | \ + SCTLR_EPAN | \ SCTLR_BT1 | \ SCTLR_BT0 | \ SCTLR_UCI | \ SCTLR_SPAN | \ + SCTLR_IESB | \ SCTLR_nTWE | \ SCTLR_nTWI | \ SCTLR_UCT | \ diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h index 07a783138f42..124da8c215ed 100644 --- a/sys/arm64/include/cpu.h +++ b/sys/arm64/include/cpu.h @@ -125,7 +125,11 @@ #define CPU_PART_NEOVERSE_V3 0xD84 #define CPU_PART_CORTEX_X925 0xD85 #define CPU_PART_CORTEX_A725 0xD87 +#define CPU_PART_C1_NANO 0xD8A +#define CPU_PART_C1_PRO 0xD8B +#define CPU_PART_C1_ULTRA 0xD8C #define CPU_PART_NEOVERSE_N3 0xD8E +#define CPU_PART_C1_PREMIUM 0xD90 /* Cavium Part numbers */ #define CPU_PART_THUNDERX 0x0A1 diff --git a/sys/arm64/include/cpu_feat.h b/sys/arm64/include/cpu_feat.h index 6a554b6baedf..6a311d4000bb 100644 --- a/sys/arm64/include/cpu_feat.h +++ b/sys/arm64/include/cpu_feat.h @@ -73,6 +73,9 @@ typedef enum { #define CPU_FEAT_PER_CPU 0x00000000 #define CPU_FEAT_SYSTEM 0x00000010 +#define CPU_FEAT_USER_ENABLED 0x40000000 +#define CPU_FEAT_USER_DISABLED 0x80000000 + struct cpu_feat; typedef cpu_feat_en (cpu_feat_check)(const struct cpu_feat *, u_int); @@ -80,12 +83,14 @@ typedef bool (cpu_feat_has_errata)(const struct cpu_feat *, u_int, u_int **, u_int *); typedef bool (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata, u_int *, u_int); +typedef void (cpu_feat_disabled)(const struct cpu_feat *); struct cpu_feat { const char *feat_name; cpu_feat_check *feat_check; cpu_feat_has_errata *feat_has_errata; cpu_feat_enable *feat_enable; + cpu_feat_disabled *feat_disabled; uint32_t feat_flags; bool feat_enabled; }; @@ -93,12 +98,13 @@ SET_DECLARE(cpu_feat_set, struct cpu_feat); SYSCTL_DECL(_hw_feat); -#define CPU_FEAT(name, descr, check, has_errata, enable, flags) \ +#define CPU_FEAT(name, descr, check, has_errata, enable, disabled, flags) \ static struct cpu_feat name = { \ .feat_name = #name, \ .feat_check = check, \ .feat_has_errata = has_errata, \ .feat_enable = enable, \ + .feat_disabled = disabled, \ .feat_flags = flags, \ .feat_enabled = false, \ }; \ diff --git a/sys/arm64/rockchip/rk_tsadc.c b/sys/arm64/rockchip/rk_tsadc.c index e6cbad36f697..d83b09480a0c 100644 --- a/sys/arm64/rockchip/rk_tsadc.c +++ b/sys/arm64/rockchip/rk_tsadc.c @@ -484,7 +484,7 @@ tsadc_init_tsensor(struct tsadc_softc *sc, struct tsensor *sensor) WR4(sc, TSADC_INT_EN, val); /* Shutdown temperature */ - val = tsadc_raw_to_temp(sc, sc->shutdown_temp); + val = tsadc_temp_to_raw(sc, sc->shutdown_temp); WR4(sc, TSADC_COMP_SHUT(sensor->channel), val); val = RD4(sc, TSADC_AUTO_CON); val |= TSADC_AUTO_SRC_EN(sensor->channel); diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 8078f3f6d4b1..853cfb845878 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -707,6 +707,31 @@ dtrace_error(uint32_t *counter) } while (dtrace_cas32(counter, oval, nval) != oval); } +void +dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) +{ + cpuset_t cpus; + + if (cpu == DTRACE_CPUALL) + cpus = all_cpus; + else + CPU_SETOF(cpu, &cpus); + + smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, + smp_no_rendezvous_barrier, arg); +} + +static void +dtrace_sync_func(void) +{ +} + +void +dtrace_sync(void) +{ + dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); +} + /* * Use the DTRACE_LOADFUNC macro to define functions for each of loading a * uint8_t, a uint16_t, a uint32_t and a uint64_t. diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c index 32e84d8fbfe9..ff880e804770 100644 --- a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c @@ -124,33 +124,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) (*func)(0, (uintptr_t)VM_MIN_KERNEL_ADDRESS); } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ - -} - -void -dtrace_sync(void) -{ - - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - static uint64_t nsec_scale; #define SCALE_SHIFT 25 diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c index 81aa53d00bd8..877d52fe18a7 100644 --- a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c @@ -142,31 +142,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) (*func)(0, la57 ? (uintptr_t)addr_P5Tmap : (uintptr_t)addr_P4Tmap); } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ -} - -void -dtrace_sync(void) -{ - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - #ifdef notyet void dtrace_safe_synchronous_signal(void) diff --git a/sys/cddl/dev/dtrace/arm/dtrace_subr.c b/sys/cddl/dev/dtrace/arm/dtrace_subr.c index bb42044aa477..10e9281709b6 100644 --- a/sys/cddl/dev/dtrace/arm/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/arm/dtrace_subr.c @@ -138,31 +138,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) */ } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ -} - -void -dtrace_sync(void) -{ - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - /* * DTrace needs a high resolution time function which can * be called from a probe context and guaranteed not to have diff --git a/sys/cddl/dev/dtrace/i386/dtrace_subr.c b/sys/cddl/dev/dtrace/i386/dtrace_subr.c index 026581f5a899..ebe2194a4b2f 100644 --- a/sys/cddl/dev/dtrace/i386/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/i386/dtrace_subr.c @@ -139,31 +139,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) (*func)(0, kernelbase); } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ -} - -void -dtrace_sync(void) -{ - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - #ifdef notyet void dtrace_safe_synchronous_signal(void) diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c index 5dd083310e6f..ee8be8da642f 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c @@ -123,31 +123,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) */ } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ -} - -void -dtrace_sync(void) -{ - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - static int64_t tgt_cpu_tsc; static int64_t hst_cpu_tsc; static int64_t timebase_skew[MAXCPU]; diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c index 3a6aacd86fcd..ed2c0bdba7e2 100644 --- a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c @@ -127,33 +127,6 @@ dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) (*func)(0, (uintptr_t)VM_MIN_KERNEL_ADDRESS); } -void -dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) -{ - cpuset_t cpus; - - if (cpu == DTRACE_CPUALL) - cpus = all_cpus; - else - CPU_SETOF(cpu, &cpus); - - smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func, - smp_no_rendezvous_barrier, arg); -} - -static void -dtrace_sync_func(void) -{ - -} - -void -dtrace_sync(void) -{ - - dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); -} - /* * DTrace needs a high resolution time function which can * be called from a probe context and guaranteed not to have diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 5e32353c6b8e..0925ffb64480 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1028,24 +1028,24 @@ linux_nice(struct thread *td, struct linux_nice_args *args) int linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { + const int ngrp = args->gidsetsize; struct ucred *newcred, *oldcred; l_gid_t *linux_gidset; - int ngrp, error; + int error; struct proc *p; - ngrp = args->gidsetsize; - if (ngrp < 0 || ngrp >= ngroups_max) + if (ngrp < 0 || ngrp > ngroups_max) return (EINVAL); linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) goto out; + newcred = crget(); crextend(newcred, ngrp); p = td->td_proc; PROC_LOCK(p); - oldcred = p->p_ucred; - crcopy(newcred, oldcred); + oldcred = crcopysafe(p, newcred); if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) { PROC_UNLOCK(p); @@ -1071,34 +1071,29 @@ out: int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { - struct ucred *cred; + const struct ucred *const cred = td->td_ucred; l_gid_t *linux_gidset; - gid_t *bsd_gidset; - int bsd_gidsetsz, ngrp, error; + int ngrp, error; - cred = td->td_ucred; - bsd_gidset = cred->cr_groups; - bsd_gidsetsz = cred->cr_ngroups; + ngrp = args->gidsetsize; - if ((ngrp = args->gidsetsize) == 0) { - td->td_retval[0] = bsd_gidsetsz; + if (ngrp == 0) { + td->td_retval[0] = cred->cr_ngroups; return (0); } - - if (ngrp < bsd_gidsetsz) + if (ngrp < cred->cr_ngroups) return (EINVAL); - ngrp = 0; - linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), - M_LINUX, M_WAITOK); - while (ngrp < bsd_gidsetsz) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } + ngrp = cred->cr_ngroups; + + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); + for (int i = 0; i < ngrp; ++i) + linux_gidset[i] = cred->cr_groups[i]; error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); free(linux_gidset, M_LINUX); - if (error) + + if (error != 0) return (error); td->td_retval[0] = ngrp; diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 539d153431c4..0e07b0a60ced 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -2179,6 +2179,7 @@ static int linux_getsockopt_so_peergroups(struct thread *td, struct linux_getsockopt_args *args) { + l_gid_t *out = PTRIN(args->optval); struct xucred xu; socklen_t xulen, len; int error, i; @@ -2197,13 +2198,12 @@ linux_getsockopt_so_peergroups(struct thread *td, return (error); } - /* - * "- 1" to skip the primary group. - */ + /* "- 1" to skip the primary group. */ for (i = 0; i < xu.cr_ngroups - 1; i++) { - error = copyout(xu.cr_groups + i + 1, - (void *)(args->optval + i * sizeof(l_gid_t)), - sizeof(l_gid_t)); + /* Copy to cope with a possible type discrepancy. */ + const l_gid_t g = xu.cr_groups[i + 1]; + + error = copyout(&g, out + i, sizeof(l_gid_t)); if (error != 0) return (error); } diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index 1d9a19916412..8ac093e004d0 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -85,13 +85,13 @@ linux_lchown16(struct thread *td, struct linux_lchown16_args *args) int linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) { + const int ngrp = args->gidsetsize; struct ucred *newcred, *oldcred; l_gid16_t *linux_gidset; - int ngrp, error; + int error; struct proc *p; - ngrp = args->gidsetsize; - if (ngrp < 0 || ngrp >= ngroups_max) + if (ngrp < 0 || ngrp > ngroups_max) return (EINVAL); linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t)); @@ -100,7 +100,9 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) free(linux_gidset, M_LINUX); return (error); } + newcred = crget(); + crextend(newcred, ngrp); p = td->td_proc; PROC_LOCK(p); oldcred = crcopysafe(p, newcred); @@ -133,34 +135,29 @@ out: int linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) { - struct ucred *cred; + const struct ucred *const cred = td->td_ucred; l_gid16_t *linux_gidset; - gid_t *bsd_gidset; - int bsd_gidsetsz, ngrp, error; + int ngrp, error; - cred = td->td_ucred; - bsd_gidset = cred->cr_groups; - bsd_gidsetsz = cred->cr_ngroups; + ngrp = args->gidsetsize; - if ((ngrp = args->gidsetsize) == 0) { - td->td_retval[0] = bsd_gidsetsz; + if (ngrp == 0) { + td->td_retval[0] = cred->cr_ngroups; return (0); } - - if (ngrp < bsd_gidsetsz) + if (ngrp < cred->cr_ngroups) return (EINVAL); - ngrp = 0; - linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), - M_LINUX, M_WAITOK); - while (ngrp < bsd_gidsetsz) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } + ngrp = cred->cr_ngroups; + + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK); + for (int i = 0; i < ngrp; ++i) + linux_gidset[i] = cred->cr_groups[i]; error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t)); free(linux_gidset, M_LINUX); - if (error) { + + if (error != 0) { LIN_SDT_PROBE1(uid16, linux_getgroups16, copyout_error, error); return (error); } diff --git a/sys/compat/linuxkpi/common/include/linux/string_choices.h b/sys/compat/linuxkpi/common/include/linux/string_choices.h new file mode 100644 index 000000000000..74aa3fd019b2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/string_choices.h @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_STRING_CHOICES_H_ +#define _LINUXKPI_LINUX_STRING_CHOICES_H_ + +#include <sys/types.h> + +static inline const char * +str_yes_no(bool value) +{ + if (value) + return "yes"; + else + return "no"; +} + +static inline const char * +str_on_off(bool value) +{ + if (value) + return "on"; + else + return "off"; +} + +static inline const char * +str_enabled_disabled(bool value) +{ + if (value) + return "enabled"; + else + return "disabled"; +} + +static inline const char * +str_enable_disable(bool value) +{ + if (value) + return "enable"; + else + return "disable"; +} + +#define str_disable_enable(_v) str_enable_disable(!(_v)) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/string_helpers.h b/sys/compat/linuxkpi/common/include/linux/string_helpers.h index 2c6fe0b1708d..07d113c0cb21 100644 --- a/sys/compat/linuxkpi/common/include/linux/string_helpers.h +++ b/sys/compat/linuxkpi/common/include/linux/string_helpers.h @@ -1,71 +1,12 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. +/* + * Copyright (c) 2025 The FreeBSD Foundation * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-2-Clause */ #ifndef _LINUXKPI_LINUX_STRING_HELPERS_H_ #define _LINUXKPI_LINUX_STRING_HELPERS_H_ -#include <sys/types.h> - -static inline const char * -str_yes_no(bool value) -{ - if (value) - return "yes"; - else - return "no"; -} - -static inline const char * -str_on_off(bool value) -{ - if (value) - return "on"; - else - return "off"; -} - -static inline const char * -str_enabled_disabled(bool value) -{ - if (value) - return "enabled"; - else - return "disabled"; -} - -static inline const char * -str_enable_disable(bool value) -{ - if (value) - return "enable"; - else - return "disable"; -} - -#define str_disable_enable(_v) str_enable_disable(!(_v)) +#include <linux/string_choices.h> #endif diff --git a/sys/conf/files b/sys/conf/files index 9661bafea8f9..db05a1424f00 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -4369,15 +4369,23 @@ netinet/cc/cc.c optional cc_newreno inet | cc_vegas inet | \ cc_chd inet | cc_cdg inet | cc_newreno inet6 | cc_vegas inet6 | \ cc_htcp inet6 | cc_hd inet6 |cc_dctcp inet6 | cc_cubic inet6 | \ cc_chd inet6 | cc_cdg inet6 -netinet/cc/cc_cdg.c optional inet cc_cdg tcp_hhook -netinet/cc/cc_chd.c optional inet cc_chd tcp_hhook +netinet/cc/cc_cdg.c optional inet cc_cdg tcp_hhook | \ + inet6 cc_cdg tcp_hhook +netinet/cc/cc_chd.c optional inet cc_chd tcp_hhook | \ + inet6 cc_chd tcp_hhook netinet/cc/cc_cubic.c optional inet cc_cubic | inet6 cc_cubic netinet/cc/cc_dctcp.c optional inet cc_dctcp | inet6 cc_dctcp -netinet/cc/cc_hd.c optional inet cc_hd tcp_hhook +netinet/cc/cc_hd.c optional inet cc_hd tcp_hhook | \ + inet6 cc_hd tcp_hhook netinet/cc/cc_htcp.c optional inet cc_htcp | inet6 cc_htcp netinet/cc/cc_newreno.c optional inet cc_newreno | inet6 cc_newreno -netinet/cc/cc_vegas.c optional inet cc_vegas tcp_hhook -netinet/khelp/h_ertt.c optional inet tcp_hhook +netinet/cc/cc_vegas.c optional inet cc_vegas tcp_hhook | \ + inet6 cc_vegas tcp_hhook +netinet/khelp/h_ertt.c optional inet tcp_hhook cc_cdg | \ + inet tcp_hhook cc_chd | inet tcp_hhook cc_hd | \ + inet tcp_hhook cc_vegas | inet6 tcp_hhook cc_cdg | \ + inet6 tcp_hhook cc_chd | inet6 tcp_hhook cc_hd | \ + inet6 tcp_hhook cc_vegas netinet/sctp_asconf.c optional inet sctp | inet6 sctp netinet/sctp_auth.c optional inet sctp | inet6 sctp netinet/sctp_bsd_addr.c optional inet sctp | inet6 sctp diff --git a/sys/contrib/dev/qat/qat_402xx.bin b/sys/contrib/dev/qat/qat_402xx.bin Binary files differnew file mode 100644 index 000000000000..74151547edce --- /dev/null +++ b/sys/contrib/dev/qat/qat_402xx.bin diff --git a/sys/contrib/dev/qat/qat_402xx_mmp.bin b/sys/contrib/dev/qat/qat_402xx_mmp.bin Binary files differnew file mode 100644 index 000000000000..6404eb009d2f --- /dev/null +++ b/sys/contrib/dev/qat/qat_402xx_mmp.bin diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c index a222c5de4a2a..4de48e013ec4 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c @@ -674,7 +674,6 @@ zfsctl_root_readdir(struct vop_readdir_args *ap) zfs_uio_t uio; int *eofp = ap->a_eofflag; off_t dots_offset; - ssize_t orig_resid; int error; zfs_uio_init(&uio, ap->a_uio); @@ -694,11 +693,13 @@ zfsctl_root_readdir(struct vop_readdir_args *ap) return (0); } - orig_resid = zfs_uio_resid(&uio); error = sfs_readdir_common(zfsvfs->z_root, ZFSCTL_INO_ROOT, ap, &uio, &dots_offset); - if (error != 0) - goto err; + if (error != 0) { + if (error == ENAMETOOLONG) /* ran out of destination space */ + error = 0; + return (error); + } if (zfs_uio_offset(&uio) != dots_offset) return (SET_ERROR(EINVAL)); @@ -711,11 +712,8 @@ zfsctl_root_readdir(struct vop_readdir_args *ap) entry.d_reclen = sizeof (entry); error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio)); if (error != 0) { -err: - if (error == ENAMETOOLONG) { - error = orig_resid == zfs_uio_resid(&uio) ? - EINVAL : 0; - } + if (error == ENAMETOOLONG) + error = 0; return (SET_ERROR(error)); } if (eofp != NULL) @@ -1060,21 +1058,17 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap) zfs_uio_t uio; int *eofp = ap->a_eofflag; off_t dots_offset; - ssize_t orig_resid; int error; zfs_uio_init(&uio, ap->a_uio); - orig_resid = zfs_uio_resid(&uio); ASSERT3S(vp->v_type, ==, VDIR); error = sfs_readdir_common(ZFSCTL_INO_ROOT, ZFSCTL_INO_SNAPDIR, ap, &uio, &dots_offset); if (error != 0) { - if (error == ENAMETOOLONG) { /* ran out of destination space */ - error = orig_resid == zfs_uio_resid(&uio) ? - EINVAL : 0; - } + if (error == ENAMETOOLONG) /* ran out of destination space */ + error = 0; return (error); } @@ -1092,13 +1086,9 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap) dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG); if (error != 0) { if (error == ENOENT) { - if (orig_resid == zfs_uio_resid(&uio)) { - error = EINVAL; - } else { - error = 0; - if (eofp != NULL) - *eofp = 1; - } + if (eofp != NULL) + *eofp = 1; + error = 0; } zfs_exit(zfsvfs, FTAG); return (error); @@ -1111,10 +1101,8 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap) entry.d_reclen = sizeof (entry); error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio)); if (error != 0) { - if (error == ENAMETOOLONG) { - error = orig_resid == zfs_uio_resid(&uio) ? - EINVAL : 0; - } + if (error == ENAMETOOLONG) + error = 0; zfs_exit(zfsvfs, FTAG); return (SET_ERROR(error)); } diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c index 8dce97baba66..411225786089 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c @@ -1698,7 +1698,6 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp, objset_t *os; caddr_t outbuf; size_t bufsize; - ssize_t orig_resid; zap_cursor_t zc; zap_attribute_t *zap; uint_t bytes_wanted; @@ -1747,7 +1746,6 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp, error = 0; os = zfsvfs->z_os; offset = zfs_uio_offset(uio); - orig_resid = zfs_uio_resid(uio); prefetch = zp->z_zn_prefetch; zap = zap_attribute_long_alloc(); @@ -1927,7 +1925,7 @@ update: kmem_free(outbuf, bufsize); if (error == ENOENT) - error = orig_resid == zfs_uio_resid(uio) ? EINVAL : 0; + error = 0; ZFS_ACCESSTIME_STAMP(zfsvfs, zp); diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz.c b/sys/contrib/openzfs/module/zfs/vdev_raidz.c index 80727b0d8f91..56b8e3b60b22 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz.c @@ -5495,7 +5495,7 @@ ZFS_MODULE_PARAM(zfs, zfs_, scrub_after_expand, INT, ZMOD_RW, "completes"); ZFS_MODULE_PARAM(zfs_vdev, vdev_, read_sit_out_secs, ULONG, ZMOD_RW, "Raidz/draid slow disk sit out time period in seconds"); -ZFS_MODULE_PARAM(zfs_vdev, vdev_, raidz_outlier_check_interval_ms, ULONG, +ZFS_MODULE_PARAM(zfs_vdev, vdev_, raidz_outlier_check_interval_ms, U64, ZMOD_RW, "Interval to check for slow raidz/draid children"); ZFS_MODULE_PARAM(zfs_vdev, vdev_, raidz_outlier_insensitivity, UINT, ZMOD_RW, "How insensitive the slow raidz/draid child check should be"); diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index a2159b12876f..574d3aacbcde 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -4,6 +4,10 @@ * Copyright (c) 2000, 2001 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -181,7 +185,8 @@ static const char *acpi_sstate2sname(int sstate); static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS); -static int acpi_pm_func(u_long cmd, void *arg, ...); +static int acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype); +static int acpi_pm_func(u_long cmd, void *arg, enum power_stype stype); static void acpi_enable_pcie(void); static void acpi_reset_interfaces(device_t dev); @@ -741,6 +746,28 @@ acpi_attach(device_t dev) return_VALUE (error); } +static int +acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype) +{ + switch (stype) { + case POWER_STYPE_AWAKE: + return (ACPI_STATE_S0); + case POWER_STYPE_STANDBY: + return (sc->acpi_standby_sx); + case POWER_STYPE_SUSPEND_TO_MEM: + return (ACPI_STATE_S3); + case POWER_STYPE_HIBERNATE: + return (ACPI_STATE_S4); + case POWER_STYPE_POWEROFF: + return (ACPI_STATE_S5); + case POWER_STYPE_SUSPEND_TO_IDLE: + case POWER_STYPE_COUNT: + case POWER_STYPE_UNKNOWN: + return (ACPI_STATE_UNKNOWN); + } + return (ACPI_STATE_UNKNOWN); +} + static void acpi_set_power_children(device_t dev, int state) { @@ -4621,12 +4648,10 @@ acpi_reset_interfaces(device_t dev) } static int -acpi_pm_func(u_long cmd, void *arg, ...) +acpi_pm_func(u_long cmd, void *arg, enum power_stype stype) { - int state, acpi_state; - int error; + int error, sstate; struct acpi_softc *sc; - va_list ap; error = 0; switch (cmd) { @@ -4636,27 +4661,8 @@ acpi_pm_func(u_long cmd, void *arg, ...) error = EINVAL; goto out; } - - va_start(ap, arg); - state = va_arg(ap, int); - va_end(ap); - - switch (state) { - case POWER_SLEEP_STATE_STANDBY: - acpi_state = sc->acpi_standby_sx; - break; - case POWER_SLEEP_STATE_SUSPEND: - acpi_state = sc->acpi_suspend_sx; - break; - case POWER_SLEEP_STATE_HIBERNATE: - acpi_state = ACPI_STATE_S4; - break; - default: - error = EINVAL; - goto out; - } - - if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_state))) + sstate = acpi_stype_to_sstate(sc, stype); + if (ACPI_FAILURE(acpi_EnterSleepState(sc, sstate))) error = ENXIO; break; default: diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 7495a010432b..fac32d832598 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -40,6 +40,7 @@ #include <sys/ktr.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/power.h> #include <sys/selinfo.h> #include <sys/sx.h> #include <sys/sysctl.h> diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 934024ddfbcf..1304b597c545 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -924,6 +924,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) | IEEE80211_C_PMGT /* Station side power mgmt */ | IEEE80211_C_SWSLEEP ; + + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* * Query the hal to figure out h/w crypto support. */ diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 1559b66a7c7d..deadd63c3d18 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -1588,6 +1588,10 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, */ pktlen = m0->m_pkthdr.len - (hdrlen & 3); + /* seqno allocate, only if AMPDU isn't running */ + if ((m0->m_flags & M_AMPDU_MPDU) == 0) + ieee80211_output_seqno_assign(ni, -1, m0); + /* Handle encryption twiddling if needed */ if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { @@ -2201,6 +2205,10 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, * for QoS frames. */ + /* seqno allocate, only if AMPDU isn't running */ + if ((m0->m_flags & M_AMPDU_MPDU) == 0) + ieee80211_output_seqno_assign(ni, -1, m0); + /* Handle encryption twiddling if needed */ if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, @@ -2981,6 +2989,8 @@ ath_tx_tid_seqno_assign(struct ath_softc *sc, struct ieee80211_node *ni, ATH_TX_LOCK_ASSERT(sc); + /* TODO: can this use ieee80211_output_seqno_assign() now? */ + /* * Is it a QOS NULL Data frame? Give it a sequence number from * the default TID (IEEE80211_NONQOS_TID.) diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 1087ca813d65..85146d4c4010 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -498,6 +498,9 @@ bwi_attach(struct bwi_softc *sc) IEEE80211_C_BGSCAN | IEEE80211_C_MONITOR; ic->ic_opmode = IEEE80211_M_STA; + + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + ieee80211_ifattach(ic); ic->ic_headroom = sizeof(struct bwi_txbuf_hdr); @@ -1361,6 +1364,7 @@ bwi_start_locked(struct bwi_softc *sc) (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; wh = mtod(m, struct ieee80211_frame *); + ieee80211_output_seqno_assign(ni, -1, m); if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 && ieee80211_crypto_encap(ni, m) == NULL) { if_inc_counter(ni->ni_vap->iv_ifp, diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 38bf6f5d31a3..ec9d56661034 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -774,6 +774,7 @@ bwn_attach_post(struct bwn_softc *sc) ; ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */ + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; /* Determine the NVRAM variable containing our MAC address */ core_unit = bhnd_get_core_unit(sc->sc_dev); @@ -999,6 +1000,7 @@ bwn_start(struct bwn_softc *sc) continue; } wh = mtod(m, struct ieee80211_frame *); + ieee80211_output_seqno_assign(ni, -1, m); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m); if (k == NULL) { diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index 9253b17a259d..b0ab3467df69 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -402,19 +402,20 @@ out: * its workings. */ static void -amd_ucode_wrmsr(void *ucode_ptr) +amd_ucode_wrmsr(void *arg) { + struct ucode_update_data *d = arg; uint32_t tmp[4]; - wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)ucode_ptr); + if (PCPU_GET(cpuid) == d->cpu) + d->ret = wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)d->ptr); do_cpuid(0, tmp); } static int update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) { - void *ptr; - int ret; + struct ucode_update_data d = { .cpu = cpu }; if (args->size == 0 || args->data == NULL) { DPRINTF("[cpuctl,%d]: zero-sized firmware image", __LINE__); @@ -430,18 +431,17 @@ update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) * malloc(9) always returns the pointer aligned at least on * the size of the allocation. */ - ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK); - if (copyin(args->data, ptr, args->size) != 0) { + d.ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK); + if (copyin(args->data, d.ptr, args->size) != 0) { DPRINTF("[cpuctl,%d]: copyin %p->%p of %zd bytes failed", __LINE__, args->data, ptr, args->size); - ret = EFAULT; + d.ret = EFAULT; goto fail; } - smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, ptr); - ret = 0; + smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, &d); fail: - free(ptr, M_CPUCTL); - return (ret); + free(d.ptr, M_CPUCTL); + return (d.ret); } static int diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 20df466b4e76..247cf9d7fed3 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -4815,7 +4815,8 @@ em_if_get_vf_counter(if_ctx_t ctx, ift_counter cnt) case IFCOUNTER_IERRORS: return sc->dropped_pkts; case IFCOUNTER_OERRORS: - return sc->watchdog_events; + return (if_get_counter_default(ifp, cnt) + + sc->watchdog_events); default: return (if_get_counter_default(ifp, cnt)); } diff --git a/sys/dev/gpio/gpioled.c b/sys/dev/gpio/gpioled.c index 71af5741b2fe..a36c2faef379 100644 --- a/sys/dev/gpio/gpioled.c +++ b/sys/dev/gpio/gpioled.c @@ -75,8 +75,6 @@ gpioled_control(void *priv, int onoff) struct gpioled_softc *sc; sc = (struct gpioled_softc *)priv; - if (onoff == -1) /* Keep the current state. */ - return; if (sc->sc_softinvert) onoff = !onoff; GPIOLED_LOCK(sc); diff --git a/sys/dev/hid/ietp.c b/sys/dev/hid/ietp.c index 73a5cb7414d4..a9d0295fb121 100644 --- a/sys/dev/hid/ietp.c +++ b/sys/dev/hid/ietp.c @@ -199,17 +199,32 @@ static const struct hid_device_id ietp_iic_devs[] = { IETP_IIC_DEV("ELAN1000"), }; -static uint8_t const ietp_dummy_rdesc[] = { +static uint8_t const ietp_dummy_rdesc_lo[] = { 0x05, HUP_GENERIC_DESKTOP, /* Usage Page (Generic Desktop Ctrls) */ 0x09, HUG_MOUSE, /* Usage (Mouse) */ 0xA1, 0x01, /* Collection (Application) */ 0x09, 0x01, /* Usage (0x01) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 0x95, IETP_REPORT_LEN_LO, /* Report Count (IETP_REPORT_LEN_LO) */ 0x75, 0x08, /* Report Size (8) */ 0x81, 0x02, /* Input (Data,Var,Abs) */ 0xC0, /* End Collection */ }; +static uint8_t const ietp_dummy_rdesc_hi[] = { + 0x05, HUP_GENERIC_DESKTOP, /* Usage Page (Generic Desktop Ctrls) */ + 0x09, HUG_MOUSE, /* Usage (Mouse) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (0x01) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x95, IETP_REPORT_LEN_HI, /* Report Count (IETP_REPORT_LEN_HI) */ + 0x75, 0x08, /* Report Size (8) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0xC0, /* End Collection */ +}; + static const struct evdev_methods ietp_evdev_methods = { .ev_open = &ietp_ev_open, .ev_close = &ietp_ev_close, @@ -433,28 +448,38 @@ ietp_res2dpmm(uint8_t res, bool hi_precision) static void ietp_iic_identify(driver_t *driver, device_t parent) { - void *d_ptr; - hid_size_t d_len; - int isize; - uint8_t iid; + device_t iichid = device_get_parent(parent); + static const uint16_t reg = IETP_PATTERN; + uint16_t addr = iicbus_get_addr(iichid) << 1; + uint8_t resp[2]; + uint8_t cmd[2] = { reg & 0xff, (reg >> 8) & 0xff }; + struct iic_msg msgs[2] = { + { addr, IIC_M_WR | IIC_M_NOSTOP, sizeof(cmd), cmd }, + { addr, IIC_M_RD, sizeof(resp), resp }, + }; + struct iic_rdwr_data ird = { msgs, nitems(msgs) }; + uint8_t pattern; if (HIDBUS_LOOKUP_ID(parent, ietp_iic_devs) == NULL) return; - if (hid_get_report_descr(parent, &d_ptr, &d_len) != 0) + + if (device_get_devclass(iichid) != devclass_find("iichid")) return; - /* - * Some Elantech trackpads have a mangled HID report descriptor, which - * reads as having an incorrect input size (i.e. < IETP_REPORT_LEN_LO). - * If the input size is incorrect, load a dummy report descriptor. - */ + DPRINTF("Read reg 0x%04x with size %zu\n", reg, sizeof(resp)); - isize = hid_report_size_max(d_ptr, d_len, hid_input, &iid); - if (isize >= IETP_REPORT_LEN_LO) + if (hid_ioctl(parent, I2CRDWR, (uintptr_t)&ird) != 0) return; - hid_set_report_descr(parent, ietp_dummy_rdesc, - sizeof(ietp_dummy_rdesc)); + DPRINTF("Response: %*D\n", (int)size(resp), resp, " "); + + pattern = (resp[0] == 0xFF && resp[1] == 0xFF) ? 0 : resp[1]; + if (pattern >= 0x02) + hid_set_report_descr(parent, ietp_dummy_rdesc_hi, + sizeof(ietp_dummy_rdesc_hi)); + else + hid_set_report_descr(parent, ietp_dummy_rdesc_lo, + sizeof(ietp_dummy_rdesc_lo)); } static int diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index c344bda930b0..5f6423135f46 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -331,7 +331,7 @@ iicbb_getack(device_t dev) { struct iicbb_softc *sc = device_get_softc(dev); int noack, err; - int t; + int t = 0; /* Release SDA so that the slave can drive it. */ err = iicbb_clockin(dev, 1); @@ -341,12 +341,13 @@ iicbb_getack(device_t dev) } /* Sample SDA until ACK (low) or udelay runs out. */ - for (t = 0; t < sc->udelay; t++) { + do { noack = I2C_GETSDA(dev); if (!noack) break; DELAY(1); - } + t++; + } while(t < sc->udelay); DELAY(sc->udelay - t); iicbb_clockout(dev); diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c index fdb4816b8bd9..5ca3f1b84e48 100644 --- a/sys/dev/iicbus/iichid.c +++ b/sys/dev/iicbus/iichid.c @@ -540,7 +540,7 @@ iichid_sampling_task(void *context, int pending) error = iichid_cmd_read(sc, sc->intr_buf, sc->intr_bufsize, &actual); if (error == 0) { if (actual > 0) { - sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2, actual); + sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2, actual - 2); sc->missing_samples = 0; if (sc->dup_size != actual || memcmp(sc->dup_buf, sc->intr_buf, actual) != 0) { @@ -607,7 +607,7 @@ iichid_intr(void *context) if (sc->power_on && sc->open) { if (actual != 0) sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2, - actual); + actual - 2); else DPRINTF(sc, "no data received\n"); } @@ -816,12 +816,13 @@ iichid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr, sc = device_get_softc(dev); /* - * Do not rely just on wMaxInputLength, as some devices (which?) - * may set it to a wrong length. Also find the longest input report - * in report descriptor, and add two for the length field. + * Start with wMaxInputLength to follow HID-over-I2C specs. Than if + * semi-HID device like ietp(4) requested changing of input buffer + * size with report descriptor overloading, find the longest input + * report in the descriptor, and add two for the length field. */ - rdesc->rdsize = 2 + - MAX(rdesc->isize, le16toh(sc->desc.wMaxInputLength)); + rdesc->rdsize = rdesc->rdsize == 0 ? + le16toh(sc->desc.wMaxInputLength) - 2 : rdesc->isize; /* Write and get/set_report sizes are limited by I2C-HID protocol. */ rdesc->grsize = rdesc->srsize = IICHID_SIZE_MAX; rdesc->wrsize = IICHID_SIZE_MAX; @@ -831,7 +832,7 @@ iichid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr, sc->intr_handler = intr; sc->intr_ctx = context; - sc->intr_bufsize = rdesc->rdsize; + sc->intr_bufsize = rdesc->rdsize + 2; sc->intr_buf = realloc(sc->intr_buf, sc->intr_bufsize, M_DEVBUF, M_WAITOK | M_ZERO); #ifdef IICHID_SAMPLING @@ -1093,7 +1094,8 @@ iichid_probe(device_t dev) } if (le16toh(sc->desc.wHIDDescLength) != 30 || - le16toh(sc->desc.bcdVersion) != 0x100) { + le16toh(sc->desc.bcdVersion) != 0x100 || + le16toh(sc->desc.wMaxInputLength) < 2) { DPRINTF(sc, "HID descriptor is broken\n"); return (ENXIO); } diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c index 01d713cdae18..9db562669487 100644 --- a/sys/dev/ipw/if_ipw.c +++ b/sys/dev/ipw/if_ipw.c @@ -283,6 +283,8 @@ ipw_attach(device_t dev) | IEEE80211_C_WPA /* 802.11i supported */ ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* read MAC address from EEPROM */ val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0); ic->ic_macaddr[0] = val >> 8; @@ -1557,6 +1559,7 @@ ipw_tx_start(struct ipw_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) wh = mtod(m0, struct ieee80211_frame *); + ieee80211_output_seqno_assign(ni, -1, m0); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c index 3a410a5cbf2c..26b8037186a6 100644 --- a/sys/dev/iwi/if_iwi.c +++ b/sys/dev/iwi/if_iwi.c @@ -371,6 +371,8 @@ iwi_attach(device_t dev) #endif ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* read MAC address from EEPROM */ val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0); ic->ic_macaddr[0] = val & 0xff; @@ -1834,6 +1836,8 @@ iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, } else staid = 0; + ieee80211_output_seqno_assign(ni, -1, m0); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index 1e9090310ece..6840c6a4d00a 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -3773,6 +3773,10 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) rinfo = iwm_tx_fill_cmd(sc, in, m, tx); + /* Offloaded sequence number assignment; non-AMPDU case */ + if ((m->m_flags & M_AMPDU_MPDU) == 0) + ieee80211_output_seqno_assign(ni, -1, m); + /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { /* Retrieve key for TX && do software encryption. */ @@ -6142,7 +6146,8 @@ iwm_attach(device_t dev) // IEEE80211_C_BGSCAN /* capable of bg scanning */ ; /* Advertise full-offload scanning */ - ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD; + ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; for (i = 0; i < nitems(sc->sc_phyctxt); i++) { sc->sc_phyctxt[i].id = i; sc->sc_phyctxt[i].color = 0; diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index b7c452a4f074..a949103f20d4 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -584,6 +584,11 @@ iwn_attach(device_t dev) | IEEE80211_C_PMGT /* Station-side power mgmt */ ; + /* Driver / firmware assigned sequence numbers */ + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* Don't originate null data frames in net80211 */ + ic->ic_flags_ext |= IEEE80211_FEXT_NO_NULLDATA; + /* Read MAC address, channels, etc from EEPROM. */ if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) { device_printf(dev, "could not read EEPROM, error %d\n", @@ -4577,6 +4582,9 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) * XXX TODO: Group addressed frames aren't aggregated and must * go to the normal non-aggregation queue, and have a NONQOS TID * assigned from net80211. + * + * TODO: same with NULL QOS frames, which we shouldn't be sending + * anyway ourselves (and should stub out / warn / etc.) */ ac = M_WME_GETAC(m); @@ -4589,6 +4597,10 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) ac = *(int *)tap->txa_private; } + /* Only assign if not A-MPDU; the A-MPDU TX path will do its own */ + if ((m->m_flags & M_AMPDU_MPDU) == 0) + ieee80211_output_seqno_assign(ni, -1, m); + /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { /* Retrieve key for TX. */ diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c index 1fe531d69933..8422fcb787c3 100644 --- a/sys/dev/iwx/if_iwx.c +++ b/sys/dev/iwx/if_iwx.c @@ -5673,8 +5673,9 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (rinfo == NULL) return EINVAL; - /* Offloaded sequence number assignment */ - /* Note: Should be done in firmware on all supported devices */ + /* Offloaded sequence number assignment; non-AMPDU case */ + if ((m->m_flags & M_AMPDU_MPDU) == 0) + ieee80211_output_seqno_assign(ni, -1, m); /* Radiotap */ if (ieee80211_radiotap_active_vap(vap)) { @@ -10474,6 +10475,8 @@ iwx_attach(device_t dev) ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD; /* Enable seqno offload */ ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* Don't send null data frames; let firmware do it */ + ic->ic_flags_ext |= IEEE80211_FEXT_NO_NULLDATA; ic->ic_txstream = 2; ic->ic_rxstream = 2; diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c index 79a3213c6802..2e4f3967ace4 100644 --- a/sys/dev/malo/if_malo.c +++ b/sys/dev/malo/if_malo.c @@ -263,6 +263,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc) ; IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr); + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* * Transmit requires space in the packet for a special format transmit * record and optional padding between this record and the payload. @@ -1040,6 +1042,8 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni, } else qos = 0; + ieee80211_output_seqno_assign(ni, -1, m0); + if (iswep) { struct ieee80211_key *k; diff --git a/sys/dev/mpi3mr/mpi3mr.c b/sys/dev/mpi3mr/mpi3mr.c index 99edd3542619..bcf8f46ddf5d 100644 --- a/sys/dev/mpi3mr/mpi3mr.c +++ b/sys/dev/mpi3mr/mpi3mr.c @@ -2799,10 +2799,11 @@ retry_init: U32 fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & MPI3_SYSIF_FAULT_CODE_MASK; - if (fault == MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER) + if (fault == MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER) { mpi3mr_dprint(sc, MPI3MR_INFO, "controller faulted due to insufficient power, try by connecting it in a different slot\n"); goto err; + } U32 host_diagnostic; timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; @@ -4486,7 +4487,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc, Mpi3SuccessReplyDescriptor_t *success_desc; Mpi3DefaultReply_t *def_reply = NULL; struct mpi3mr_drvr_cmd *cmdptr = NULL; - Mpi3SCSIIOReply_t *scsi_reply; + Mpi3SCSIIOReply_t *scsi_reply = NULL; U8 *sense_buf = NULL; *reply_dma = 0; @@ -4589,7 +4590,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc, } } out: - if (sense_buf != NULL) + if (scsi_reply != NULL && sense_buf != NULL) mpi3mr_repost_sense_buf(sc, scsi_reply->SenseDataBufferAddress); return; @@ -6161,7 +6162,7 @@ static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type, { int retval = -1; U8 unlock_retry_count = 0; - U32 host_diagnostic, ioc_status, ioc_config, scratch_pad0; + U32 host_diagnostic = 0, ioc_status, ioc_config, scratch_pad0; U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10; if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && diff --git a/sys/dev/mpi3mr/mpi3mr_cam.c b/sys/dev/mpi3mr/mpi3mr_cam.c index 77e25339a1a9..a5120e2788db 100644 --- a/sys/dev/mpi3mr/mpi3mr_cam.c +++ b/sys/dev/mpi3mr/mpi3mr_cam.c @@ -1856,10 +1856,11 @@ int mpi3mr_remove_device_from_os(struct mpi3mr_softc *sc, U16 handle) "Poll reply queue once\n", target_outstanding, target->per_id); mpi3mr_poll_pend_io_completions(sc); target_outstanding = mpi3mr_atomic_read(&target->outstanding); - if (target_outstanding) + if (target_outstanding) { target_outstanding = mpi3mr_atomic_read(&target->outstanding); mpi3mr_dprint(sc, MPI3MR_ERROR, "[%2d] outstanding IOs present on target: %d " - "despite poll\n", target_outstanding, target->per_id); + "despite poll\n", target_outstanding, target->per_id); + } } if (target->exposed_to_os && !sc->reset_in_progress) { diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index c885968dfe15..9f3d34f4f50d 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -433,6 +433,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) | IEEE80211_HTC_SMPS /* SMPS available */ ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + /* * Mark h/w crypto support. * XXX no way to query h/w support. @@ -3087,6 +3089,8 @@ mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node *ni, struct mwl_txbuf * } else qos = 0; + ieee80211_output_seqno_assign(ni, -1, m0); + if (iswep) { const struct ieee80211_cipher *cip; struct ieee80211_key *k; diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c index 5919e75a59cf..f6c4a0118b68 100644 --- a/sys/dev/otus/if_otus.c +++ b/sys/dev/otus/if_otus.c @@ -728,6 +728,12 @@ otus_attachhook(struct otus_softc *sc) IEEE80211_C_SWAMSDUTX | /* Do software A-MSDU TX */ IEEE80211_C_WPA; /* WPA/RSN. */ + /* + * Although A-MPDU RX is fine, A-MPDU TX apparently has some + * hardware bugs. Looking at Linux carl9170, it has a work-around + * that forces all frames into the AC_BE queue regardless of + * the actual QoS queue. + */ ic->ic_htcaps = IEEE80211_HTC_HT | #if 0 @@ -737,6 +743,8 @@ otus_attachhook(struct otus_softc *sc) IEEE80211_HTCAP_MAXAMSDU_3839 | IEEE80211_HTCAP_SMPS_OFF; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + otus_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -2232,6 +2240,9 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, struct mbuf *m, int hasqos, xferlen, type, ismcast; wh = mtod(m, struct ieee80211_frame *); + + ieee80211_output_seqno_assign(ni, -1, m); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m); if (k == NULL) { diff --git a/sys/dev/qat/include/common/adf_accel_devices.h b/sys/dev/qat/include/common/adf_accel_devices.h index c09aee8ea4bd..eeffc6a9132c 100644 --- a/sys/dev/qat/include/common/adf_accel_devices.h +++ b/sys/dev/qat/include/common/adf_accel_devices.h @@ -39,12 +39,16 @@ #define ADF_4XXXIOV_PCI_DEVICE_ID 0x4941 #define ADF_401XX_PCI_DEVICE_ID 0x4942 #define ADF_401XXIOV_PCI_DEVICE_ID 0x4943 +#define ADF_402XX_PCI_DEVICE_ID 0x4944 +#define ADF_402XXIOV_PCI_DEVICE_ID 0x4945 #define IS_QAT_GEN3(ID) ({ (ID == ADF_C4XXX_PCI_DEVICE_ID); }) static inline bool IS_QAT_GEN4(const unsigned int id) { return (id == ADF_4XXX_PCI_DEVICE_ID || id == ADF_401XX_PCI_DEVICE_ID || + id == ADF_402XX_PCI_DEVICE_ID || + id == ADF_402XXIOV_PCI_DEVICE_ID || id == ADF_4XXXIOV_PCI_DEVICE_ID || id == ADF_401XXIOV_PCI_DEVICE_ID); } diff --git a/sys/dev/qat/qat_api/include/icp_sal_versions.h b/sys/dev/qat/qat_api/include/icp_sal_versions.h index 03bcef4fcbbb..0eb227ade09c 100644 --- a/sys/dev/qat/qat_api/include/icp_sal_versions.h +++ b/sys/dev/qat/qat_api/include/icp_sal_versions.h @@ -26,7 +26,7 @@ /* Part name and number of the accelerator device */ #define SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER 3 -#define SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER 15 +#define SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER 16 #define SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER 0 /** diff --git a/sys/dev/qat/qat_common/qat_uclo.c b/sys/dev/qat/qat_common/qat_uclo.c index 54e8e8eb7421..b17020286d24 100644 --- a/sys/dev/qat/qat_common/qat_uclo.c +++ b/sys/dev/qat/qat_common/qat_uclo.c @@ -892,6 +892,7 @@ qat_uclo_get_dev_type(struct icp_qat_fw_loader_handle *handle) return ICP_QAT_AC_C4XXX_DEV_TYPE; case ADF_4XXX_PCI_DEVICE_ID: case ADF_401XX_PCI_DEVICE_ID: + case ADF_402XX_PCI_DEVICE_ID: return ICP_QAT_AC_4XXX_A_DEV_TYPE; default: pr_err("QAT: unsupported device 0x%x\n", diff --git a/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.c b/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.c index d730efd5952b..49e1e1859e78 100644 --- a/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.c +++ b/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.c @@ -536,8 +536,8 @@ adf_exit_accel_units(struct adf_accel_dev *accel_dev) } static const char * -get_obj_name(struct adf_accel_dev *accel_dev, - enum adf_accel_unit_services service) +get_obj_name_4xxx(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) { switch (service) { case ADF_ACCEL_ASYM: @@ -553,6 +553,24 @@ get_obj_name(struct adf_accel_dev *accel_dev, } } +static const char * +get_obj_name_402xx(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + switch (service) { + case ADF_ACCEL_ASYM: + return ADF_402XX_ASYM_OBJ; + case ADF_ACCEL_CRYPTO: + return ADF_402XX_SYM_OBJ; + case ADF_ACCEL_COMPRESSION: + return ADF_402XX_DC_OBJ; + case ADF_ACCEL_ADMIN: + return ADF_402XX_ADMIN_OBJ; + default: + return NULL; + } +} + static uint32_t get_objs_num(struct adf_accel_dev *accel_dev) { @@ -982,8 +1000,23 @@ adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 id) hw_data->clock_frequency = ADF_4XXX_AE_FREQ; hw_data->get_sku = get_sku; hw_data->heartbeat_ctr_num = ADF_NUM_HB_CNT_PER_AE; - hw_data->fw_name = ADF_4XXX_FW; - hw_data->fw_mmp_name = ADF_4XXX_MMP; + switch (id) { + case ADF_402XX_PCI_DEVICE_ID: + hw_data->fw_name = ADF_402XX_FW; + hw_data->fw_mmp_name = ADF_402XX_MMP; + hw_data->asym_ae_active_thd_mask = DEFAULT_4XXX_ASYM_AE_MASK; + break; + case ADF_401XX_PCI_DEVICE_ID: + hw_data->fw_name = ADF_4XXX_FW; + hw_data->fw_mmp_name = ADF_4XXX_MMP; + hw_data->asym_ae_active_thd_mask = DEFAULT_401XX_ASYM_AE_MASK; + break; + + default: + hw_data->fw_name = ADF_4XXX_FW; + hw_data->fw_mmp_name = ADF_4XXX_MMP; + hw_data->asym_ae_active_thd_mask = DEFAULT_4XXX_ASYM_AE_MASK; + } hw_data->init_admin_comms = adf_init_admin_comms; hw_data->exit_admin_comms = adf_exit_admin_comms; hw_data->send_admin_init = adf_4xxx_send_admin_init; @@ -1002,7 +1035,13 @@ adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 id) hw_data->get_ring_svc_map_data = get_ring_svc_map_data; hw_data->admin_ae_mask = ADF_4XXX_ADMIN_AE_MASK; hw_data->get_objs_num = get_objs_num; - hw_data->get_obj_name = get_obj_name; + switch (id) { + case ADF_402XX_PCI_DEVICE_ID: + hw_data->get_obj_name = get_obj_name_402xx; + break; + default: + hw_data->get_obj_name = get_obj_name_4xxx; + } hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; hw_data->get_service_type = adf_4xxx_get_service_type; hw_data->set_msix_rttable = set_msix_default_rttable; @@ -1022,15 +1061,6 @@ adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 id) hw_data->query_storage_cap = 1; hw_data->ring_pair_reset = adf_gen4_ring_pair_reset; - switch (id) { - case ADF_401XX_PCI_DEVICE_ID: - hw_data->asym_ae_active_thd_mask = DEFAULT_401XX_ASYM_AE_MASK; - break; - case ADF_4XXX_PCI_DEVICE_ID: - default: - hw_data->asym_ae_active_thd_mask = DEFAULT_4XXX_ASYM_AE_MASK; - } - adf_gen4_init_hw_csr_info(&hw_data->csr_info); adf_gen4_init_pf_pfvf_ops(&hw_data->csr_info.pfvf_ops); } diff --git a/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.h b/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.h index c35ebbcadcd7..fa7249dca596 100644 --- a/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.h +++ b/sys/dev/qat/qat_hw/qat_4xxx/adf_4xxx_hw_data.h @@ -87,6 +87,12 @@ #define ADF_4XXX_SYM_OBJ "qat_4xxx_sym.bin" #define ADF_4XXX_ASYM_OBJ "qat_4xxx_asym.bin" #define ADF_4XXX_ADMIN_OBJ "qat_4xxx_admin.bin" +#define ADF_402XX_FW "qat_402xx_fw" +#define ADF_402XX_MMP "qat_402xx_mmp_fw" +#define ADF_402XX_DC_OBJ "qat_402xx_dc.bin" +#define ADF_402XX_SYM_OBJ "qat_402xx_sym.bin" +#define ADF_402XX_ASYM_OBJ "qat_402xx_asym.bin" +#define ADF_402XX_ADMIN_OBJ "qat_402xx_admin.bin" /* Only 3 types of images can be loaded including the admin image */ #define ADF_4XXX_MAX_OBJ 3 diff --git a/sys/dev/qat/qat_hw/qat_4xxx/adf_drv.c b/sys/dev/qat/qat_hw/qat_4xxx/adf_drv.c index cb534dd03b86..f9ad39fa45f0 100644 --- a/sys/dev/qat/qat_hw/qat_4xxx/adf_drv.c +++ b/sys/dev/qat/qat_hw/qat_4xxx/adf_drv.c @@ -22,12 +22,14 @@ static MALLOC_DEFINE(M_QAT_4XXX, "qat_4xxx", "qat_4xxx"); PCI_VENDOR_ID_INTEL, device_id \ } -static const struct pci_device_id adf_pci_tbl[] = - { ADF_SYSTEM_DEVICE(ADF_4XXX_PCI_DEVICE_ID), - ADF_SYSTEM_DEVICE(ADF_401XX_PCI_DEVICE_ID), - { - 0, - } }; +static const struct pci_device_id adf_pci_tbl[] = { + ADF_SYSTEM_DEVICE(ADF_4XXX_PCI_DEVICE_ID), + ADF_SYSTEM_DEVICE(ADF_401XX_PCI_DEVICE_ID), + ADF_SYSTEM_DEVICE(ADF_402XX_PCI_DEVICE_ID), + { + 0, + } +}; static int adf_probe(device_t dev) @@ -135,6 +137,7 @@ adf_cleanup_accel(struct adf_accel_dev *accel_dev) switch (pci_get_device(accel_pci_dev->pci_dev)) { case ADF_4XXX_PCI_DEVICE_ID: case ADF_401XX_PCI_DEVICE_ID: + case ADF_402XX_PCI_DEVICE_ID: adf_clean_hw_data_4xxx(accel_dev->hw_device); break; default: diff --git a/sys/dev/qat/qat_hw/qat_4xxxvf/adf_drv.c b/sys/dev/qat/qat_hw/qat_4xxxvf/adf_drv.c index 2bbccb4d6b17..dbe40835ccbf 100644 --- a/sys/dev/qat/qat_hw/qat_4xxxvf/adf_drv.c +++ b/sys/dev/qat/qat_hw/qat_4xxxvf/adf_drv.c @@ -22,12 +22,14 @@ static MALLOC_DEFINE(M_QAT_4XXXVF, "qat_4xxxvf", "qat_4xxxvf"); PCI_VENDOR_ID_INTEL, device_id \ } -static const struct pci_device_id adf_pci_tbl[] = - { ADF_SYSTEM_DEVICE(ADF_4XXXIOV_PCI_DEVICE_ID), - ADF_SYSTEM_DEVICE(ADF_401XXIOV_PCI_DEVICE_ID), - { - 0, - } }; +static const struct pci_device_id adf_pci_tbl[] = { + ADF_SYSTEM_DEVICE(ADF_4XXXIOV_PCI_DEVICE_ID), + ADF_SYSTEM_DEVICE(ADF_401XXIOV_PCI_DEVICE_ID), + ADF_SYSTEM_DEVICE(ADF_402XXIOV_PCI_DEVICE_ID), + { + 0, + } +}; static int adf_probe(device_t dev) @@ -76,6 +78,7 @@ adf_cleanup_accel(struct adf_accel_dev *accel_dev) switch (pci_get_device(accel_pci_dev->pci_dev)) { case ADF_4XXXIOV_PCI_DEVICE_ID: case ADF_401XXIOV_PCI_DEVICE_ID: + case ADF_402XXIOV_PCI_DEVICE_ID: adf_clean_hw_data_4xxxiov(accel_dev->hw_device); break; default: diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 09b01ea55be9..7feb324eb21d 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -281,6 +281,8 @@ rt2560_attach(device_t dev, int id) #endif ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + rt2560_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1516,6 +1518,8 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); + ieee80211_output_seqno_assign(ni, -1, m0); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 38cd99d899ed..c9c86d4f089a 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -282,6 +282,8 @@ rt2661_attach(device_t dev, int id) #endif ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + rt2661_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1284,7 +1286,7 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0, rate = ni->ni_txparms->mgmtrate; wh = mtod(m0, struct ieee80211_frame *); - + ieee80211_output_seqno_assign(ni, -1, m0); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c index 1449df683a93..76fe4652839d 100644 --- a/sys/dev/ral/rt2860.c +++ b/sys/dev/ral/rt2860.c @@ -323,6 +323,8 @@ rt2860_attach(device_t dev, int id) | IEEE80211_C_WME /* 802.11e */ ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + rt2860_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1471,6 +1473,7 @@ rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) wh = mtod(m, struct ieee80211_frame *); + ieee80211_output_seqno_assign(ni, -1, m); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m); if (k == NULL) { diff --git a/sys/dev/random/fenestrasX/fx_pool.c b/sys/dev/random/fenestrasX/fx_pool.c index d2e6f0db71ee..f4ad1e295d54 100644 --- a/sys/dev/random/fenestrasX/fx_pool.c +++ b/sys/dev/random/fenestrasX/fx_pool.c @@ -164,6 +164,9 @@ static const struct fxrng_ent_char { [RANDOM_CALLOUT] = { .entc_cls = &fxrng_lo_push, }, + [RANDOM_RANDOMDEV] = { + .entc_cls = &fxrng_lo_push, + }, [RANDOM_PURE_OCTEON] = { .entc_cls = &fxrng_hi_push, /* Could be made pull. */ }, diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c index 67864c2de388..d56c975a43d2 100644 --- a/sys/dev/re/if_re.c +++ b/sys/dev/re/if_re.c @@ -353,6 +353,8 @@ static driver_t re_driver = { DRIVER_MODULE(re, pci, re_driver, 0, 0); DRIVER_MODULE(miibus, re, miibus_driver, 0, 0); +MODULE_PNP_INFO("U16:vendor;U16:device;U32:#;D:#", pci, re, re_devs, + nitems(re_devs) - 1); #define EE_SET(x) \ CSR_WRITE_1(sc, RL_EECMD, \ diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index 25287f222270..c5889937fb08 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -271,6 +271,11 @@ rtwn_attach(struct rtwn_softc *sc) /* Enable seqno offload */ ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; +#ifdef RTWN_WITHOUT_UCODE + /* Don't originate NULL data frames - let firmware do this */ + ic->ic_flags_ext |= IEEE80211_FEXT_NO_NULLDATA; +#endif + /* Adjust capabilities. */ rtwn_adj_devcaps(sc); diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index fab182b22774..9ad21d219001 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -408,7 +408,7 @@ enum { #define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD | \ CHN_F_VIRTUAL | CHN_F_HAS_VCHAN | \ - CHN_F_VCHAN_DYNAMIC | \ + CHN_F_VCHAN_DYNAMIC | CHN_F_NBIO | \ CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE) #define CHN_F_MMAP_INVALID (CHN_F_DEAD | CHN_F_RUNNING) diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index aa6ad4a59778..da38f52021ae 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -299,7 +299,7 @@ dsp_close(void *data) CHN_LOCK(rdch); chn_abort(rdch); /* won't sleep */ rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | - CHN_F_DEAD | CHN_F_EXCLUSIVE); + CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO); chn_reset(rdch, 0, 0); chn_release(rdch); if (rdch->flags & CHN_F_VIRTUAL) { @@ -323,7 +323,7 @@ dsp_close(void *data) CHN_LOCK(wrch); chn_flush(wrch); /* may sleep */ wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | - CHN_F_DEAD | CHN_F_EXCLUSIVE); + CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO); chn_reset(wrch, 0, 0); chn_release(wrch); if (wrch->flags & CHN_F_VIRTUAL) { diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c index 36be94b8b8b7..35663b480cfa 100644 --- a/sys/dev/ufshci/ufshci_ctrlr.c +++ b/sys/dev/ufshci/ufshci_ctrlr.c @@ -12,8 +12,108 @@ #include "ufshci_private.h" #include "ufshci_reg.h" +static void +ufshci_ctrlr_fail(struct ufshci_controller *ctrlr) +{ + ctrlr->is_failed = true; + + ufshci_req_queue_fail(ctrlr, + ctrlr->task_mgmt_req_queue.qops.get_hw_queue( + &ctrlr->task_mgmt_req_queue)); + ufshci_req_queue_fail(ctrlr, + ctrlr->transfer_req_queue.qops.get_hw_queue( + &ctrlr->transfer_req_queue)); +} + +static void +ufshci_ctrlr_start(struct ufshci_controller *ctrlr, bool resetting) +{ + TSENTER(); + + /* + * If `resetting` is true, we are on the reset path. + * Re-enable request queues here because ufshci_ctrlr_reset_task() + * disables them during reset. + */ + if (resetting) { + if (ufshci_utmr_req_queue_enable(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + if (ufshci_utr_req_queue_enable(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + } + + if (ufshci_ctrlr_send_nop(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* Initialize UFS target drvice */ + if (ufshci_dev_init(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* Initialize Reference Clock */ + if (ufshci_dev_init_reference_clock(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* Initialize unipro */ + if (ufshci_dev_init_unipro(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* + * Initialize UIC Power Mode + * QEMU UFS devices do not support unipro and power mode. + */ + if (!(ctrlr->quirks & UFSHCI_QUIRK_IGNORE_UIC_POWER_MODE) && + ufshci_dev_init_uic_power_mode(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* Initialize UFS Power Mode */ + if (ufshci_dev_init_ufs_power_mode(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* Read Controller Descriptor (Device, Geometry) */ + if (ufshci_dev_get_descriptor(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + if (ufshci_dev_config_write_booster(ctrlr)) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + /* TODO: Configure Write Protect */ + + /* TODO: Configure Background Operations */ + + /* + * If the reset is due to a timeout, it is already attached to the SIM + * and does not need to be attached again. + */ + if (!resetting && ufshci_sim_attach(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + + TSEXIT(); +} + static int -ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) +ufshci_ctrlr_disable_host_ctrlr(struct ufshci_controller *ctrlr) { int timeout = ticks + MSEC_2_TICKS(ctrlr->device_init_timeout_in_ms); sbintime_t delta_t = SBT_1US; @@ -27,6 +127,35 @@ ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) ufshci_mmio_write_4(ctrlr, hce, hce); } + /* Wait for the HCE flag to change */ + while (1) { + hce = ufshci_mmio_read_4(ctrlr, hce); + if (!UFSHCIV(UFSHCI_HCE_REG_HCE, hce)) + break; + if (timeout - ticks < 0) { + ufshci_printf(ctrlr, + "host controller failed to disable " + "within %d ms\n", + ctrlr->device_init_timeout_in_ms); + return (ENXIO); + } + + pause_sbt("ufshci_disable_hce", delta_t, 0, C_PREL(1)); + delta_t = min(SBT_1MS, delta_t * 3 / 2); + } + + return (0); +} + +static int +ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) +{ + int timeout = ticks + MSEC_2_TICKS(ctrlr->device_init_timeout_in_ms); + sbintime_t delta_t = SBT_1US; + uint32_t hce; + + hce = ufshci_mmio_read_4(ctrlr, hce); + /* Enable UFS host controller */ hce |= UFSHCIM(UFSHCI_HCE_REG_HCE); ufshci_mmio_write_4(ctrlr, hce, hce); @@ -36,7 +165,7 @@ ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) * unstable, so we need to read the HCE value after some time after * initialization is complete. */ - pause_sbt("ufshci_hce", ustosbt(100), 0, C_PREL(1)); + pause_sbt("ufshci_enable_hce", ustosbt(100), 0, C_PREL(1)); /* Wait for the HCE flag to change */ while (1) { @@ -51,17 +180,103 @@ ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) return (ENXIO); } - pause_sbt("ufshci_hce", delta_t, 0, C_PREL(1)); + pause_sbt("ufshci_enable_hce", delta_t, 0, C_PREL(1)); delta_t = min(SBT_1MS, delta_t * 3 / 2); } return (0); } +static int +ufshci_ctrlr_disable(struct ufshci_controller *ctrlr) +{ + int error; + + /* Disable all interrupts */ + ufshci_mmio_write_4(ctrlr, ie, 0); + + error = ufshci_ctrlr_disable_host_ctrlr(ctrlr); + return (error); +} + +static int +ufshci_ctrlr_enable(struct ufshci_controller *ctrlr) +{ + uint32_t ie, hcs; + int error; + + error = ufshci_ctrlr_enable_host_ctrlr(ctrlr); + if (error) + return (error); + + /* Send DME_LINKSTARTUP command to start the link startup procedure */ + error = ufshci_uic_send_dme_link_startup(ctrlr); + if (error) + return (error); + + /* + * The device_present(UFSHCI_HCS_REG_DP) bit becomes true if the host + * controller has successfully received a Link Startup UIC command + * response and the UFS device has found a physical link to the + * controller. + */ + hcs = ufshci_mmio_read_4(ctrlr, hcs); + if (!UFSHCIV(UFSHCI_HCS_REG_DP, hcs)) { + ufshci_printf(ctrlr, "UFS device not found\n"); + return (ENXIO); + } + + /* Enable additional interrupts by programming the IE register. */ + ie = ufshci_mmio_read_4(ctrlr, ie); + ie |= UFSHCIM(UFSHCI_IE_REG_UTRCE); /* UTR Completion */ + ie |= UFSHCIM(UFSHCI_IE_REG_UEE); /* UIC Error */ + ie |= UFSHCIM(UFSHCI_IE_REG_UTMRCE); /* UTMR Completion */ + ie |= UFSHCIM(UFSHCI_IE_REG_DFEE); /* Device Fatal Error */ + ie |= UFSHCIM(UFSHCI_IE_REG_UTPEE); /* UTP Error */ + ie |= UFSHCIM(UFSHCI_IE_REG_HCFEE); /* Host Ctrlr Fatal Error */ + ie |= UFSHCIM(UFSHCI_IE_REG_SBFEE); /* System Bus Fatal Error */ + ie |= UFSHCIM(UFSHCI_IE_REG_CEFEE); /* Crypto Engine Fatal Error */ + ufshci_mmio_write_4(ctrlr, ie, ie); + + /* TODO: Initialize interrupt Aggregation Control Register (UTRIACR) */ + + return (0); +} + +static int +ufshci_ctrlr_hw_reset(struct ufshci_controller *ctrlr) +{ + int error; + + error = ufshci_ctrlr_disable(ctrlr); + if (error) + return (error); + + error = ufshci_ctrlr_enable(ctrlr); + return (error); +} + +static void +ufshci_ctrlr_reset_task(void *arg, int pending) +{ + struct ufshci_controller *ctrlr = arg; + int error; + + /* Release resources */ + ufshci_utmr_req_queue_disable(ctrlr); + ufshci_utr_req_queue_disable(ctrlr); + + error = ufshci_ctrlr_hw_reset(ctrlr); + if (error) + return (ufshci_ctrlr_fail(ctrlr)); + + ufshci_ctrlr_start(ctrlr, true); +} + int ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) { - uint32_t ver, cap, hcs, ie, ahit; + uint32_t ver, cap, ahit; uint32_t timeout_period, retry_count; int error; @@ -114,16 +329,15 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) TUNABLE_INT_FETCH("hw.ufshci.retry_count", &retry_count); ctrlr->retry_count = retry_count; - /* Disable all interrupts */ - ufshci_mmio_write_4(ctrlr, ie, 0); - - /* Enable Host Controller */ - error = ufshci_ctrlr_enable_host_ctrlr(ctrlr); - if (error) - return (error); + ctrlr->enable_aborts = 1; + if (ctrlr->quirks & UFSHCI_QUIRK_NOT_SUPPORT_ABORT_TASK) + ctrlr->enable_aborts = 0; + else + TUNABLE_INT_FETCH("hw.ufshci.enable_aborts", + &ctrlr->enable_aborts); - /* Send DME_LINKSTARTUP command to start the link startup procedure */ - error = ufshci_uic_send_dme_link_startup(ctrlr); + /* Reset the UFSHCI controller */ + error = ufshci_ctrlr_hw_reset(ctrlr); if (error) return (error); @@ -134,18 +348,6 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) ahit = 0; ufshci_mmio_write_4(ctrlr, ahit, ahit); - /* - * The device_present(UFSHCI_HCS_REG_DP) bit becomes true if the host - * controller has successfully received a Link Startup UIC command - * response and the UFS device has found a physical link to the - * controller. - */ - hcs = ufshci_mmio_read_4(ctrlr, hcs); - if (!UFSHCIV(UFSHCI_HCS_REG_DP, hcs)) { - ufshci_printf(ctrlr, "UFS device not found\n"); - return (ENXIO); - } - /* Allocate and initialize UTP Task Management Request List. */ error = ufshci_utmr_req_queue_construct(ctrlr); if (error) @@ -156,27 +358,21 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) if (error) return (error); - /* Enable additional interrupts by programming the IE register. */ - ie = ufshci_mmio_read_4(ctrlr, ie); - ie |= UFSHCIM(UFSHCI_IE_REG_UTRCE); /* UTR Completion */ - ie |= UFSHCIM(UFSHCI_IE_REG_UEE); /* UIC Error */ - ie |= UFSHCIM(UFSHCI_IE_REG_UTMRCE); /* UTMR Completion */ - ie |= UFSHCIM(UFSHCI_IE_REG_DFEE); /* Device Fatal Error */ - ie |= UFSHCIM(UFSHCI_IE_REG_UTPEE); /* UTP Error */ - ie |= UFSHCIM(UFSHCI_IE_REG_HCFEE); /* Host Ctrlr Fatal Error */ - ie |= UFSHCIM(UFSHCI_IE_REG_SBFEE); /* System Bus Fatal Error */ - ie |= UFSHCIM(UFSHCI_IE_REG_CEFEE); /* Crypto Engine Fatal Error */ - ufshci_mmio_write_4(ctrlr, ie, ie); - - /* TODO: Initialize interrupt Aggregation Control Register (UTRIACR) */ - /* TODO: Separate IO and Admin slot */ + /* * max_hw_pend_io is the number of slots in the transfer_req_queue. * Reduce num_entries by one to reserve an admin slot. */ ctrlr->max_hw_pend_io = ctrlr->transfer_req_queue.num_entries - 1; + /* Create a thread for the taskqueue. */ + ctrlr->taskqueue = taskqueue_create("ufshci_taskq", M_WAITOK, + taskqueue_thread_enqueue, &ctrlr->taskqueue); + taskqueue_start_threads(&ctrlr->taskqueue, 1, PI_DISK, "ufshci taskq"); + + TASK_INIT(&ctrlr->reset_task, 0, ufshci_ctrlr_reset_task, ctrlr); + return (0); } @@ -208,50 +404,21 @@ ufshci_ctrlr_destruct(struct ufshci_controller *ctrlr, device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, ctrlr->resource_id, ctrlr->resource); nores: + KASSERT(!mtx_owned(&ctrlr->uic_cmd_lock), + ("destroying uic_cmd_lock while still owned")); mtx_destroy(&ctrlr->uic_cmd_lock); + + KASSERT(!mtx_owned(&ctrlr->sc_mtx), + ("destroying sc_mtx while still owned")); mtx_destroy(&ctrlr->sc_mtx); return; } -int +void ufshci_ctrlr_reset(struct ufshci_controller *ctrlr) { - uint32_t ie; - int error; - - /* Backup and disable all interrupts */ - ie = ufshci_mmio_read_4(ctrlr, ie); - ufshci_mmio_write_4(ctrlr, ie, 0); - - /* Release resources */ - ufshci_utmr_req_queue_destroy(ctrlr); - ufshci_utr_req_queue_destroy(ctrlr); - - /* Reset Host Controller */ - error = ufshci_ctrlr_enable_host_ctrlr(ctrlr); - if (error) - return (error); - - /* Send DME_LINKSTARTUP command to start the link startup procedure */ - error = ufshci_uic_send_dme_link_startup(ctrlr); - if (error) - return (error); - - /* Enable interrupts */ - ufshci_mmio_write_4(ctrlr, ie, ie); - - /* Allocate and initialize UTP Task Management Request List. */ - error = ufshci_utmr_req_queue_construct(ctrlr); - if (error) - return (error); - - /* Allocate and initialize UTP Transfer Request List or SQ/CQ. */ - error = ufshci_utr_req_queue_construct(ctrlr); - if (error) - return (error); - - return (0); + taskqueue_enqueue(ctrlr->taskqueue, &ctrlr->reset_task); } int @@ -295,84 +462,6 @@ ufshci_ctrlr_send_nop(struct ufshci_controller *ctrlr) return (0); } -static void -ufshci_ctrlr_fail(struct ufshci_controller *ctrlr, bool admin_also) -{ - printf("ufshci(4): ufshci_ctrlr_fail\n"); - - ctrlr->is_failed = true; - - /* TODO: task_mgmt_req_queue should be handled as fail */ - - ufshci_req_queue_fail(ctrlr, - &ctrlr->transfer_req_queue.hwq[UFSHCI_SDB_Q]); -} - -static void -ufshci_ctrlr_start(struct ufshci_controller *ctrlr) -{ - TSENTER(); - - if (ufshci_ctrlr_send_nop(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* Initialize UFS target drvice */ - if (ufshci_dev_init(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* Initialize Reference Clock */ - if (ufshci_dev_init_reference_clock(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* Initialize unipro */ - if (ufshci_dev_init_unipro(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* - * Initialize UIC Power Mode - * QEMU UFS devices do not support unipro and power mode. - */ - if (!(ctrlr->quirks & UFSHCI_QUIRK_IGNORE_UIC_POWER_MODE) && - ufshci_dev_init_uic_power_mode(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* Initialize UFS Power Mode */ - if (ufshci_dev_init_ufs_power_mode(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* Read Controller Descriptor (Device, Geometry) */ - if (ufshci_dev_get_descriptor(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - if (ufshci_dev_config_write_booster(ctrlr)) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - /* TODO: Configure Background Operations */ - - if (ufshci_sim_attach(ctrlr) != 0) { - ufshci_ctrlr_fail(ctrlr, false); - return; - } - - TSEXIT(); -} - void ufshci_ctrlr_start_config_hook(void *arg) { @@ -382,9 +471,9 @@ ufshci_ctrlr_start_config_hook(void *arg) if (ufshci_utmr_req_queue_enable(ctrlr) == 0 && ufshci_utr_req_queue_enable(ctrlr) == 0) - ufshci_ctrlr_start(ctrlr); + ufshci_ctrlr_start(ctrlr, false); else - ufshci_ctrlr_fail(ctrlr, false); + ufshci_ctrlr_fail(ctrlr); ufshci_sysctl_initialize_ctrlr(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); diff --git a/sys/dev/ufshci/ufshci_ctrlr_cmd.c b/sys/dev/ufshci/ufshci_ctrlr_cmd.c index 71d163d998af..253f31a93c2e 100644 --- a/sys/dev/ufshci/ufshci_ctrlr_cmd.c +++ b/sys/dev/ufshci/ufshci_ctrlr_cmd.c @@ -15,7 +15,7 @@ ufshci_ctrlr_cmd_send_task_mgmt_request(struct ufshci_controller *ctrlr, struct ufshci_request *req; struct ufshci_task_mgmt_request_upiu *upiu; - req = ufshci_allocate_request_vaddr(NULL, 0, M_WAITOK, cb_fn, cb_arg); + req = ufshci_allocate_request_vaddr(NULL, 0, M_NOWAIT, cb_fn, cb_arg); req->request_size = sizeof(struct ufshci_task_mgmt_request_upiu); req->response_size = sizeof(struct ufshci_task_mgmt_response_upiu); diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c index dd196b1d638b..975468e5156f 100644 --- a/sys/dev/ufshci/ufshci_dev.c +++ b/sys/dev/ufshci/ufshci_dev.c @@ -774,4 +774,3 @@ out: ufshci_dev_disable_write_booster(ctrlr); return (error); } - diff --git a/sys/dev/ufshci/ufshci_pci.c b/sys/dev/ufshci/ufshci_pci.c index d64b7526f713..992026fd4f4d 100644 --- a/sys/dev/ufshci/ufshci_pci.c +++ b/sys/dev/ufshci/ufshci_pci.c @@ -49,7 +49,8 @@ static struct _pcsid { uint32_t ref_clk; uint32_t quirks; } pci_ids[] = { { 0x131b36, "QEMU UFS Host Controller", UFSHCI_REF_CLK_19_2MHz, - UFSHCI_QUIRK_IGNORE_UIC_POWER_MODE }, + UFSHCI_QUIRK_IGNORE_UIC_POWER_MODE | + UFSHCI_QUIRK_NOT_SUPPORT_ABORT_TASK }, { 0x98fa8086, "Intel Lakefield UFS Host Controller", UFSHCI_REF_CLK_19_2MHz, UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE | diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h index 2e033f84c373..ec388c06e248 100644 --- a/sys/dev/ufshci/ufshci_private.h +++ b/sys/dev/ufshci/ufshci_private.h @@ -68,7 +68,6 @@ struct ufshci_request { bool is_admin; int32_t retries; bool payload_valid; - bool timeout; bool spare[2]; /* Future use */ STAILQ_ENTRY(ufshci_request) stailq; }; @@ -82,6 +81,7 @@ enum ufshci_slot_state { }; struct ufshci_tracker { + TAILQ_ENTRY(ufshci_tracker) tailq; struct ufshci_request *req; struct ufshci_req_queue *req_queue; struct ufshci_hw_queue *hwq; @@ -121,6 +121,8 @@ struct ufshci_qops { struct ufshci_req_queue *req_queue); int (*enable)(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue); + void (*disable)(struct ufshci_controller *ctrlr, + struct ufshci_req_queue *req_queue); int (*reserve_slot)(struct ufshci_req_queue *req_queue, struct ufshci_tracker **tr); int (*reserve_admin_slot)(struct ufshci_req_queue *req_queue, @@ -137,16 +139,27 @@ struct ufshci_qops { #define UFSHCI_SDB_Q 0 /* Queue number for a single doorbell queue */ +enum ufshci_recovery { + RECOVERY_NONE = 0, /* Normal operations */ + RECOVERY_WAITING, /* waiting for the reset to complete */ +}; + /* * Generic queue container used by both SDB (fixed 32-slot bitmap) and MCQ * (ring buffer) modes. Fields are shared; some such as sq_head, sq_tail and * cq_head are not used in SDB but used in MCQ. */ struct ufshci_hw_queue { + struct ufshci_controller *ctrlr; + struct ufshci_req_queue *req_queue; uint32_t id; int domain; int cpu; + struct callout timer; /* recovery lock */ + bool timer_armed; /* recovery lock */ + enum ufshci_recovery recovery_state; /* recovery lock */ + union { struct ufshci_utp_xfer_req_desc *utrd; struct ufshci_utp_task_mgmt_req_desc *utmrd; @@ -161,6 +174,9 @@ struct ufshci_hw_queue { uint32_t num_entries; uint32_t num_trackers; + TAILQ_HEAD(, ufshci_tracker) free_tr; + TAILQ_HEAD(, ufshci_tracker) outstanding_tr; + /* * A Request List using the single doorbell method uses a dedicated * ufshci_tracker, one per slot. @@ -177,7 +193,13 @@ struct ufshci_hw_queue { int64_t num_retries; int64_t num_failures; + /* + * Each lock may be acquired independently. + * When both are required, acquire them in this order to avoid + * deadlocks. (recovery_lock -> qlock) + */ struct mtx_padalign qlock; + struct mtx_padalign recovery_lock; }; struct ufshci_req_queue { @@ -242,6 +264,9 @@ struct ufshci_controller { 4 /* Need to wait 1250us after power mode change */ #define UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY \ 8 /* Need to change the number of lanes before changing HS-GEAR. */ +#define UFSHCI_QUIRK_NOT_SUPPORT_ABORT_TASK \ + 16 /* QEMU does not support Task Management Request */ + uint32_t ref_clk; struct cam_sim *ufshci_sim; @@ -264,6 +289,9 @@ struct ufshci_controller { /* Fields for tracking progress during controller initialization. */ struct intr_config_hook config_hook; + struct task reset_task; + struct taskqueue *taskqueue; + /* For shared legacy interrupt. */ int rid; struct resource *res; @@ -272,6 +300,8 @@ struct ufshci_controller { uint32_t major_version; uint32_t minor_version; + uint32_t enable_aborts; + uint32_t num_io_queues; uint32_t max_hw_pend_io; @@ -345,7 +375,7 @@ void ufshci_sim_detach(struct ufshci_controller *ctrlr); /* Controller */ int ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev); void ufshci_ctrlr_destruct(struct ufshci_controller *ctrlr, device_t dev); -int ufshci_ctrlr_reset(struct ufshci_controller *ctrlr); +void ufshci_ctrlr_reset(struct ufshci_controller *ctrlr); /* ctrlr defined as void * to allow use with config_intrhook. */ void ufshci_ctrlr_start_config_hook(void *arg); void ufshci_ctrlr_poll(struct ufshci_controller *ctrlr); @@ -388,7 +418,9 @@ int ufshci_utmr_req_queue_construct(struct ufshci_controller *ctrlr); int ufshci_utr_req_queue_construct(struct ufshci_controller *ctrlr); void ufshci_utmr_req_queue_destroy(struct ufshci_controller *ctrlr); void ufshci_utr_req_queue_destroy(struct ufshci_controller *ctrlr); +void ufshci_utmr_req_queue_disable(struct ufshci_controller *ctrlr); int ufshci_utmr_req_queue_enable(struct ufshci_controller *ctrlr); +void ufshci_utr_req_queue_disable(struct ufshci_controller *ctrlr); int ufshci_utr_req_queue_enable(struct ufshci_controller *ctrlr); void ufshci_req_queue_fail(struct ufshci_controller *ctrlr, struct ufshci_hw_queue *hwq); @@ -404,6 +436,8 @@ void ufshci_req_sdb_destroy(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue); struct ufshci_hw_queue *ufshci_req_sdb_get_hw_queue( struct ufshci_req_queue *req_queue); +void ufshci_req_sdb_disable(struct ufshci_controller *ctrlr, + struct ufshci_req_queue *req_queue); int ufshci_req_sdb_enable(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue); int ufshci_req_sdb_reserve_slot(struct ufshci_req_queue *req_queue, @@ -489,13 +523,12 @@ _ufshci_allocate_request(const int how, ufshci_cb_fn_t cb_fn, void *cb_arg) struct ufshci_request *req; KASSERT(how == M_WAITOK || how == M_NOWAIT, - ("nvme_allocate_request: invalid how %d", how)); + ("ufshci_allocate_request: invalid how %d", how)); req = malloc(sizeof(*req), M_UFSHCI, how | M_ZERO); if (req != NULL) { req->cb_fn = cb_fn; req->cb_arg = cb_arg; - req->timeout = true; } return (req); } diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c index bb6efa6d2ccc..7aa164d00bec 100644 --- a/sys/dev/ufshci/ufshci_req_queue.c +++ b/sys/dev/ufshci/ufshci_req_queue.c @@ -24,6 +24,7 @@ static const struct ufshci_qops sdb_utmr_qops = { .destroy = ufshci_req_sdb_destroy, .get_hw_queue = ufshci_req_sdb_get_hw_queue, .enable = ufshci_req_sdb_enable, + .disable = ufshci_req_sdb_disable, .reserve_slot = ufshci_req_sdb_reserve_slot, .reserve_admin_slot = ufshci_req_sdb_reserve_slot, .ring_doorbell = ufshci_req_sdb_utmr_ring_doorbell, @@ -38,6 +39,7 @@ static const struct ufshci_qops sdb_utr_qops = { .destroy = ufshci_req_sdb_destroy, .get_hw_queue = ufshci_req_sdb_get_hw_queue, .enable = ufshci_req_sdb_enable, + .disable = ufshci_req_sdb_disable, .reserve_slot = ufshci_req_sdb_reserve_slot, .reserve_admin_slot = ufshci_req_sdb_reserve_slot, .ring_doorbell = ufshci_req_sdb_utr_ring_doorbell, @@ -74,6 +76,13 @@ ufshci_utmr_req_queue_destroy(struct ufshci_controller *ctrlr) &ctrlr->task_mgmt_req_queue); } +void +ufshci_utmr_req_queue_disable(struct ufshci_controller *ctrlr) +{ + ctrlr->task_mgmt_req_queue.qops.disable(ctrlr, + &ctrlr->task_mgmt_req_queue); +} + int ufshci_utmr_req_queue_enable(struct ufshci_controller *ctrlr) { @@ -109,6 +118,13 @@ ufshci_utr_req_queue_destroy(struct ufshci_controller *ctrlr) &ctrlr->transfer_req_queue); } +void +ufshci_utr_req_queue_disable(struct ufshci_controller *ctrlr) +{ + ctrlr->transfer_req_queue.qops.disable(ctrlr, + &ctrlr->transfer_req_queue); +} + int ufshci_utr_req_queue_enable(struct ufshci_controller *ctrlr) { @@ -226,31 +242,30 @@ void ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr) { struct ufshci_req_queue *req_queue = tr->req_queue; + struct ufshci_hw_queue *hwq = tr->hwq; struct ufshci_request *req = tr->req; struct ufshci_completion cpl; uint8_t ocs; bool retry, error, retriable; - mtx_assert(&tr->hwq->qlock, MA_NOTOWNED); + mtx_assert(&hwq->qlock, MA_NOTOWNED); /* Copy the response from the Request Descriptor or UTP Command * Descriptor. */ + cpl.size = tr->response_size; if (req_queue->is_task_mgmt) { - cpl.size = tr->response_size; memcpy(&cpl.response_upiu, - (void *)tr->hwq->utmrd[tr->slot_num].response_upiu, - cpl.size); + (void *)hwq->utmrd[tr->slot_num].response_upiu, cpl.size); - ocs = tr->hwq->utmrd[tr->slot_num].overall_command_status; + ocs = hwq->utmrd[tr->slot_num].overall_command_status; } else { bus_dmamap_sync(req_queue->dma_tag_ucd, req_queue->ucdmem_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - cpl.size = tr->response_size; memcpy(&cpl.response_upiu, (void *)tr->ucd->response_upiu, cpl.size); - ocs = tr->hwq->utrd[tr->slot_num].overall_command_status; + ocs = hwq->utrd[tr->slot_num].overall_command_status; } error = ufshci_req_queue_response_is_error(req_queue, ocs, @@ -262,9 +277,9 @@ ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr) retry = error && retriable && req->retries < req_queue->ctrlr->retry_count; if (retry) - tr->hwq->num_retries++; + hwq->num_retries++; if (error && req->retries >= req_queue->ctrlr->retry_count && retriable) - tr->hwq->num_failures++; + hwq->num_failures++; KASSERT(tr->req, ("there is no request assigned to the tracker\n")); KASSERT(cpl.response_upiu.header.task_tag == @@ -282,7 +297,7 @@ ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr) req->cb_fn(req->cb_arg, &cpl, error); } - mtx_lock(&tr->hwq->qlock); + mtx_lock(&hwq->qlock); /* Clear the UTRL Completion Notification register */ req_queue->qops.clear_cpl_ntf(req_queue->ctrlr, tr); @@ -301,6 +316,9 @@ ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr) ufshci_free_request(req); tr->req = NULL; tr->slot_state = UFSHCI_SLOT_STATE_FREE; + + TAILQ_REMOVE(&hwq->outstanding_tr, tr, tailq); + TAILQ_INSERT_HEAD(&hwq->free_tr, tr, tailq); } mtx_unlock(&tr->hwq->qlock); @@ -309,7 +327,16 @@ ufshci_req_queue_complete_tracker(struct ufshci_tracker *tr) bool ufshci_req_queue_process_completions(struct ufshci_req_queue *req_queue) { - return (req_queue->qops.process_cpl(req_queue)); + struct ufshci_hw_queue *hwq; + bool done; + + hwq = req_queue->qops.get_hw_queue(req_queue); + + mtx_lock(&hwq->recovery_lock); + done = req_queue->qops.process_cpl(req_queue); + mtx_unlock(&hwq->recovery_lock); + + return (done); } static void @@ -427,6 +454,225 @@ ufshci_req_queue_fill_utr_descriptor(struct ufshci_utp_xfer_req_desc *desc, desc->prdt_length = prdt_entry_cnt; } +static void +ufshci_req_queue_timeout_recovery(struct ufshci_controller *ctrlr, + struct ufshci_hw_queue *hwq) +{ + /* TODO: Step 2. Logical unit reset */ + /* TODO: Step 3. Target device reset */ + /* TODO: Step 4. Bus reset */ + + /* + * Step 5. All previous commands were timeout. + * Recovery failed, reset the host controller. + */ + ufshci_printf(ctrlr, + "Recovery step 5: Resetting controller due to a timeout.\n"); + hwq->recovery_state = RECOVERY_WAITING; + + ufshci_ctrlr_reset(ctrlr); +} + +static void +ufshci_abort_complete(void *arg, const struct ufshci_completion *status, + bool error) +{ + struct ufshci_tracker *tr = arg; + + /* + * We still need to check the active tracker array, to cover race where + * I/O timed out at same time controller was completing the I/O. An + * abort request always is on the Task Management Request queue, but + * affects either an Task Management Request or an I/O (UTRL) queue, so + * take the appropriate queue lock for the original command's queue, + * since we'll need it to avoid races with the completion code and to + * complete the command manually. + */ + mtx_lock(&tr->hwq->qlock); + if (tr->slot_state != UFSHCI_SLOT_STATE_FREE) { + mtx_unlock(&tr->hwq->qlock); + /* + * An I/O has timed out, and the controller was unable to abort + * it for some reason. And we've not processed a completion for + * it yet. Construct a fake completion status, and then complete + * the I/O's tracker manually. + */ + ufshci_printf(tr->hwq->ctrlr, + "abort task request failed, aborting task manually\n"); + ufshci_req_queue_manual_complete_tracker(tr, + UFSHCI_DESC_ABORTED, UFSHCI_RESPONSE_CODE_GENERAL_FAILURE); + + if ((status->response_upiu.task_mgmt_response_upiu + .output_param1 == + UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE) || + (status->response_upiu.task_mgmt_response_upiu + .output_param1 == + UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED)) { + ufshci_printf(tr->hwq->ctrlr, + "Warning: the abort task request completed \ + successfully, but the original task is still incomplete."); + return; + } + + /* Abort Task failed. Perform recovery steps 2-5 */ + ufshci_req_queue_timeout_recovery(tr->hwq->ctrlr, tr->hwq); + } else { + mtx_unlock(&tr->hwq->qlock); + } +} + +static void +ufshci_req_queue_timeout(void *arg) +{ + struct ufshci_hw_queue *hwq = arg; + struct ufshci_controller *ctrlr = hwq->ctrlr; + struct ufshci_tracker *tr; + sbintime_t now; + bool idle = true; + bool fast; + + mtx_assert(&hwq->recovery_lock, MA_OWNED); + + /* + * If the controller is failed, then stop polling. This ensures that any + * failure processing that races with the hwq timeout will fail safely. + */ + if (ctrlr->is_failed) { + ufshci_printf(ctrlr, + "Failed controller, stopping watchdog timeout.\n"); + hwq->timer_armed = false; + return; + } + + /* + * Shutdown condition: We set hwq->timer_armed to false in + * ufshci_req_sdb_destroy before calling callout_drain. When we call + * that, this routine might get called one last time. Exit w/o setting a + * timeout. None of the watchdog stuff needs to be done since we're + * destroying the hwq. + */ + if (!hwq->timer_armed) { + ufshci_printf(ctrlr, + "Timeout fired during ufshci_utr_req_queue_destroy\n"); + return; + } + + switch (hwq->recovery_state) { + case RECOVERY_NONE: + /* + * See if there's any recovery needed. First, do a fast check to + * see if anything could have timed out. If not, then skip + * everything else. + */ + fast = false; + mtx_lock(&hwq->qlock); + now = getsbinuptime(); + TAILQ_FOREACH(tr, &hwq->outstanding_tr, tailq) { + /* + * If the first real transaction is not in timeout, then + * we're done. Otherwise, we try recovery. + */ + idle = false; + if (now <= tr->deadline) + fast = true; + break; + } + mtx_unlock(&hwq->qlock); + if (idle || fast) + break; + + /* + * There's a stale transaction at the start of the queue whose + * deadline has passed. Poll the competions as a last-ditch + * effort in case an interrupt has been missed. + */ + hwq->req_queue->qops.process_cpl(hwq->req_queue); + + /* + * Now that we've run the ISR, re-rheck to see if there's any + * timed out commands and abort them or reset the card if so. + */ + mtx_lock(&hwq->qlock); + idle = true; + TAILQ_FOREACH(tr, &hwq->outstanding_tr, tailq) { + /* + * If we know this tracker hasn't timed out, we also + * know all subsequent ones haven't timed out. The tr + * queue is in submission order and all normal commands + * in a queue have the same timeout (or the timeout was + * changed by the user, but we eventually timeout then). + */ + idle = false; + if (now <= tr->deadline) + break; + + /* + * Timeout recovery is performed in five steps. If + * recovery fails at any step, the process continues to + * the next one: + * next steps: + * Step 1. Abort task + * Step 2. Logical unit reset (TODO) + * Step 3. Target device reset (TODO) + * Step 4. Bus reset (TODO) + * Step 5. Host controller reset + * + * If the timeout occurred in the Task Management + * Request queue, ignore Step 1. + */ + if (ctrlr->enable_aborts && + !hwq->req_queue->is_task_mgmt && + tr->req->cb_fn != ufshci_abort_complete) { + /* + * Step 1. Timeout expired, abort the task. + * + * This isn't an abort command, ask for a + * hardware abort. This goes to the Task + * Management Request queue which will reset the + * task if it times out. + */ + ufshci_printf(ctrlr, + "Recovery step 1: Timeout occurred. aborting the task(%d).\n", + tr->req->request_upiu.header.task_tag); + ufshci_ctrlr_cmd_send_task_mgmt_request(ctrlr, + ufshci_abort_complete, tr, + UFSHCI_TASK_MGMT_FUNCTION_ABORT_TASK, + tr->req->request_upiu.header.lun, + tr->req->request_upiu.header.task_tag, 0); + } else { + /* Recovery Step 2-5 */ + ufshci_req_queue_timeout_recovery(ctrlr, hwq); + idle = false; + break; + } + } + mtx_unlock(&hwq->qlock); + break; + + case RECOVERY_WAITING: + /* + * These messages aren't interesting while we're suspended. We + * put the queues into waiting state while suspending. + * Suspending takes a while, so we'll see these during that time + * and they aren't diagnostic. At other times, they indicate a + * problem that's worth complaining about. + */ + if (!device_is_suspended(ctrlr->dev)) + ufshci_printf(ctrlr, "Waiting for reset to complete\n"); + idle = false; /* We want to keep polling */ + break; + } + + /* + * Rearm the timeout. + */ + if (!idle) { + callout_schedule_sbt(&hwq->timer, SBT_1S / 2, SBT_1S / 2, 0); + } else { + hwq->timer_armed = false; + } +} + /* * Submit the tracker to the hardware. */ @@ -436,13 +682,30 @@ ufshci_req_queue_submit_tracker(struct ufshci_req_queue *req_queue, { struct ufshci_controller *ctrlr = req_queue->ctrlr; struct ufshci_request *req = tr->req; + struct ufshci_hw_queue *hwq; uint64_t ucd_paddr; uint16_t request_len, response_off, response_len; uint8_t slot_num = tr->slot_num; + int timeout; - mtx_assert(&req_queue->qops.get_hw_queue(req_queue)->qlock, MA_OWNED); + hwq = req_queue->qops.get_hw_queue(req_queue); + + mtx_assert(&hwq->qlock, MA_OWNED); - /* TODO: Check timeout */ + if (req->cb_fn == ufshci_completion_poll_cb) + timeout = 1; + else + timeout = ctrlr->timeout_period; + tr->deadline = getsbinuptime() + timeout * SBT_1S; + if (!hwq->timer_armed) { + hwq->timer_armed = true; + /* + * It wakes up once every 0.5 seconds to check if the deadline + * has passed. + */ + callout_reset_sbt_on(&hwq->timer, SBT_1S / 2, SBT_1S / 2, + ufshci_req_queue_timeout, hwq, hwq->cpu, 0); + } if (req_queue->is_task_mgmt) { /* Prepare UTP Task Management Request Descriptor. */ @@ -508,6 +771,9 @@ _ufshci_req_queue_submit_request(struct ufshci_req_queue *req_queue, tr->deadline = SBT_MAX; tr->req = req; + TAILQ_REMOVE(&tr->hwq->free_tr, tr, tailq); + TAILQ_INSERT_TAIL(&tr->hwq->outstanding_tr, tr, tailq); + ufshci_req_queue_submit_tracker(req_queue, tr, req->data_direction); return (0); diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c index 834a459d48e3..ca47aa159c5b 100644 --- a/sys/dev/ufshci/ufshci_req_sdb.c +++ b/sys/dev/ufshci/ufshci_req_sdb.c @@ -40,6 +40,8 @@ ufshci_req_sdb_cmd_desc_destroy(struct ufshci_req_queue *req_queue) bus_dma_tag_destroy(req_queue->dma_tag_ucd); req_queue->dma_tag_ucd = NULL; } + + free(req_queue->hwq->ucd_bus_addr, M_UFSHCI); } static void @@ -74,6 +76,10 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, uint8_t *ucdmem; int i, error; + req_queue->hwq->ucd_bus_addr = malloc(sizeof(bus_addr_t) * + req_queue->num_trackers, + M_UFSHCI, M_ZERO | M_NOWAIT); + /* * Each component must be page aligned, and individual PRP lists * cannot cross a page boundary. @@ -152,6 +158,9 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, uint64_t queuemem_phys; uint8_t *queuemem; struct ufshci_tracker *tr; + const size_t lock_name_len = 32; + char qlock_name[lock_name_len], recovery_lock_name[lock_name_len]; + char *base; int i, error; req_queue->ctrlr = ctrlr; @@ -169,11 +178,21 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, hwq = &req_queue->hwq[UFSHCI_SDB_Q]; hwq->num_entries = req_queue->num_entries; hwq->num_trackers = req_queue->num_trackers; - req_queue->hwq->ucd_bus_addr = malloc(sizeof(bus_addr_t) * - req_queue->num_trackers, - M_UFSHCI, M_ZERO | M_NOWAIT); + hwq->ctrlr = ctrlr; + hwq->req_queue = req_queue; + + base = is_task_mgmt ? "ufshci utmrq" : "ufshci utrq"; + snprintf(qlock_name, sizeof(qlock_name), "%s #%d lock", base, + UFSHCI_SDB_Q); + snprintf(recovery_lock_name, sizeof(recovery_lock_name), + "%s #%d recovery lock", base, UFSHCI_SDB_Q); - mtx_init(&hwq->qlock, "ufshci req_queue lock", NULL, MTX_DEF); + mtx_init(&hwq->qlock, qlock_name, NULL, MTX_DEF); + mtx_init(&hwq->recovery_lock, recovery_lock_name, NULL, MTX_DEF); + + callout_init_mtx(&hwq->timer, &hwq->recovery_lock, 0); + hwq->timer_armed = false; + hwq->recovery_state = RECOVERY_WAITING; /* * Allocate physical memory for request queue (UTP Transfer Request @@ -219,6 +238,9 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, req_queue->num_entries, M_UFSHCI, DOMAINSET_PREF(req_queue->domain), M_ZERO | M_WAITOK); + TAILQ_INIT(&hwq->free_tr); + TAILQ_INIT(&hwq->outstanding_tr); + for (i = 0; i < req_queue->num_trackers; i++) { tr = malloc_domainset(sizeof(struct ufshci_tracker), M_UFSHCI, DOMAINSET_PREF(req_queue->domain), M_ZERO | M_WAITOK); @@ -226,6 +248,7 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, tr->req_queue = req_queue; tr->slot_num = i; tr->slot_state = UFSHCI_SLOT_STATE_FREE; + TAILQ_INSERT_HEAD(&hwq->free_tr, tr, tailq); hwq->act_tr[i] = tr; } @@ -255,8 +278,6 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, ctrlr) != 0) { ufshci_printf(ctrlr, "failed to construct cmd descriptor memory\n"); - bus_dmamem_free(hwq->dma_tag_queue, hwq->utrd, - hwq->queuemem_map); goto out; } @@ -280,6 +301,11 @@ ufshci_req_sdb_destroy(struct ufshci_controller *ctrlr, struct ufshci_tracker *tr; int i; + mtx_lock(&hwq->recovery_lock); + hwq->timer_armed = false; + mtx_unlock(&hwq->recovery_lock); + callout_drain(&hwq->timer); + if (!req_queue->is_task_mgmt) ufshci_req_sdb_cmd_desc_destroy(&ctrlr->transfer_req_queue); @@ -305,10 +331,11 @@ ufshci_req_sdb_destroy(struct ufshci_controller *ctrlr, hwq->dma_tag_queue = NULL; } + if (mtx_initialized(&hwq->recovery_lock)) + mtx_destroy(&hwq->recovery_lock); if (mtx_initialized(&hwq->qlock)) mtx_destroy(&hwq->qlock); - free(req_queue->hwq->ucd_bus_addr, M_UFSHCI); free(req_queue->hwq, M_UFSHCI); } @@ -318,10 +345,36 @@ ufshci_req_sdb_get_hw_queue(struct ufshci_req_queue *req_queue) return &req_queue->hwq[UFSHCI_SDB_Q]; } +void +ufshci_req_sdb_disable(struct ufshci_controller *ctrlr, + struct ufshci_req_queue *req_queue) +{ + struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q]; + struct ufshci_tracker *tr, *tr_temp; + + mtx_lock(&hwq->recovery_lock); + mtx_lock(&hwq->qlock); + + if (mtx_initialized(&hwq->recovery_lock)) + mtx_assert(&hwq->recovery_lock, MA_OWNED); + if (mtx_initialized(&hwq->qlock)) + mtx_assert(&hwq->qlock, MA_OWNED); + + hwq->recovery_state = RECOVERY_WAITING; + TAILQ_FOREACH_SAFE(tr, &hwq->outstanding_tr, tailq, tr_temp) { + tr->deadline = SBT_MAX; + } + + mtx_unlock(&hwq->qlock); + mtx_unlock(&hwq->recovery_lock); +} + int ufshci_req_sdb_enable(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue) { + struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q]; + if (req_queue->is_task_mgmt) { uint32_t hcs, utmrldbr, utmrlrsr; @@ -373,6 +426,14 @@ ufshci_req_sdb_enable(struct ufshci_controller *ctrlr, ufshci_mmio_write_4(ctrlr, utrlrsr, utrlrsr); } + if (mtx_initialized(&hwq->recovery_lock)) + mtx_assert(&hwq->recovery_lock, MA_OWNED); + if (mtx_initialized(&hwq->qlock)) + mtx_assert(&hwq->qlock, MA_OWNED); + KASSERT(!req_queue->ctrlr->is_failed, ("Enabling a failed hwq\n")); + + hwq->recovery_state = RECOVERY_NONE; + return (0); } @@ -466,6 +527,8 @@ ufshci_req_sdb_process_cpl(struct ufshci_req_queue *req_queue) uint8_t slot; bool done = false; + mtx_assert(&hwq->recovery_lock, MA_OWNED); + hwq->num_intr_handler_calls++; bus_dmamap_sync(hwq->dma_tag_queue, hwq->queuemem_map, diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c index db24561f4169..828b520614a5 100644 --- a/sys/dev/ufshci/ufshci_sim.c +++ b/sys/dev/ufshci/ufshci_sim.c @@ -241,7 +241,6 @@ ufshci_cam_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_ABORT: - /* TODO: Implement Task Management CMD*/ ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; break; case XPT_SET_TRAN_SETTINGS: diff --git a/sys/dev/usb/serial/udbc.c b/sys/dev/usb/serial/udbc.c new file mode 100644 index 000000000000..d7ca6b25bf32 --- /dev/null +++ b/sys/dev/usb/serial/udbc.c @@ -0,0 +1,404 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * Copyright (c) 2016-2024 Hiroki Sato <hrs@FreeBSD.org> + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/callout.h> +#include <sys/condvar.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/priv.h> +#include <sys/queue.h> +#include <sys/stddef.h> +#include <sys/stdint.h> +#include <sys/sx.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usb_ioctl.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> +#include <dev/usb/usb_core.h> + +#include "usbdevs.h" + +#define USB_DEBUG_VAR udbc_debug +#include <dev/usb/usb_process.h> +#include <dev/usb/serial/usb_serial.h> +#include <dev/usb/usb_debug.h> + +static SYSCTL_NODE(_hw_usb, OID_AUTO, udbc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "USB DbC Client"); + +#ifdef USB_DEBUG +static int udbc_debug = 0; +SYSCTL_INT(_hw_usb_udbc, OID_AUTO, debug, CTLFLAG_RWTUN, &udbc_debug, 0, + "Debug level"); +#endif + +#define UDBC_CONFIG_INDEX 0 + +#define UDBC_IBUFSIZE 1024 +#define UDBC_OBUFSIZE 1024 + +enum { + UDBC_BULK_DT_WR, + UDBC_BULK_DT_RD, + UDBC_N_TRANSFER, /* n of EP */ +}; + +struct udbc_softc { + struct ucom_super_softc sc_super_ucom; + struct ucom_softc sc_ucom; + + struct usb_device *sc_udev; + struct usb_xfer *sc_xfer[UDBC_N_TRANSFER]; + device_t sc_dev; + struct mtx sc_mtx; + + uint32_t sc_unit; +}; + +/* prototypes */ + +static device_probe_t udbc_probe; +static device_attach_t udbc_attach; +static device_detach_t udbc_detach; +static void udbc_free_softc(struct udbc_softc *); + +static usb_callback_t udbc_write_callback; +static usb_callback_t udbc_read_callback; + +static void udbc_free(struct ucom_softc *); +static void udbc_cfg_open(struct ucom_softc *); +static void udbc_cfg_close(struct ucom_softc *); +static int udbc_pre_param(struct ucom_softc *, struct termios *); +static int udbc_ioctl(struct ucom_softc *, uint32_t, caddr_t, int, + struct thread *); +static void udbc_start_read(struct ucom_softc *); +static void udbc_stop_read(struct ucom_softc *); +static void udbc_start_write(struct ucom_softc *); +static void udbc_stop_write(struct ucom_softc *); +static void udbc_poll(struct ucom_softc *ucom); + +static const struct usb_config udbc_config[UDBC_N_TRANSFER] = { + [UDBC_BULK_DT_WR] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = UDBC_OBUFSIZE, + .flags = {.pipe_bof = 1,}, + .callback = &udbc_write_callback, + }, + + [UDBC_BULK_DT_RD] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = UDBC_IBUFSIZE, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .callback = &udbc_read_callback, + }, +}; + +static const struct ucom_callback udbc_callback = { + .ucom_cfg_open = &udbc_cfg_open, + .ucom_cfg_close = &udbc_cfg_close, + .ucom_pre_param = &udbc_pre_param, + .ucom_ioctl = &udbc_ioctl, + .ucom_start_read = &udbc_start_read, + .ucom_stop_read = &udbc_stop_read, + .ucom_start_write = &udbc_start_write, + .ucom_stop_write = &udbc_stop_write, + .ucom_poll = &udbc_poll, + .ucom_free = &udbc_free, +}; + +static device_method_t udbc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, udbc_probe), + DEVMETHOD(device_attach, udbc_attach), + DEVMETHOD(device_detach, udbc_detach), + DEVMETHOD_END +}; + +static int +udbc_probe(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != UDBC_CONFIG_INDEX) + return (ENXIO); + if (uaa->info.bInterfaceClass != UICLASS_DIAGNOSTIC) + return (ENXIO); + if (uaa->info.bDeviceProtocol != 0x00) /* GNU GDB == 1 */ + return (ENXIO); + + return (BUS_PROBE_SPECIFIC); +} + +static int +udbc_attach(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + struct udbc_softc *sc = device_get_softc(dev); + int error; + + DPRINTF("\n"); + + sc->sc_udev = uaa->device; + sc->sc_dev = dev; + sc->sc_unit = device_get_unit(dev); + + device_set_usb_desc(dev); + mtx_init(&sc->sc_mtx, "udbc", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); + + sc->sc_ucom.sc_portno = 0; + + error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, + sc->sc_xfer, udbc_config, UDBC_N_TRANSFER, sc, &sc->sc_mtx); + + if (error) { + device_printf(dev, + "allocating USB transfers failed\n"); + goto detach; + } + /* clear stall at first run */ + mtx_lock(&sc->sc_mtx); + usbd_xfer_set_stall(sc->sc_xfer[UDBC_BULK_DT_WR]); + usbd_xfer_set_stall(sc->sc_xfer[UDBC_BULK_DT_RD]); + mtx_unlock(&sc->sc_mtx); + + error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &udbc_callback, &sc->sc_mtx); + if (error) + goto detach; + ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); + + return (0); /* success */ + +detach: + udbc_detach(dev); + return (ENXIO); +} + +static int +udbc_detach(device_t dev) +{ + struct udbc_softc *sc = device_get_softc(dev); + + ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); + usbd_transfer_unsetup(sc->sc_xfer, UDBC_N_TRANSFER); + + device_claim_softc(dev); + + udbc_free_softc(sc); + + return (0); +} + +UCOM_UNLOAD_DRAIN(udbc); + +static void +udbc_free_softc(struct udbc_softc *sc) +{ + if (ucom_unref(&sc->sc_super_ucom)) { + mtx_destroy(&sc->sc_mtx); + device_free_softc(sc); + } +} + +static void +udbc_free(struct ucom_softc *ucom) +{ + udbc_free_softc(ucom->sc_parent); +} + +static void +udbc_cfg_open(struct ucom_softc *ucom) +{ + /* + * This do-nothing open routine exists for the sole purpose of this + * DPRINTF() so that you can see the point at which open gets called + * when debugging is enabled. + */ + DPRINTF("\n"); +} + +static void +udbc_cfg_close(struct ucom_softc *ucom) +{ + /* + * This do-nothing close routine exists for the sole purpose of this + * DPRINTF() so that you can see the point at which close gets called + * when debugging is enabled. + */ + DPRINTF("\n"); +} + +static void +udbc_write_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct udbc_softc *sc = usbd_xfer_softc(xfer); + struct usb_page_cache *pc; + uint32_t buflen; + + DPRINTFN(3, "\n"); + + switch (USB_GET_STATE(xfer)) { + default: /* Error */ + if (error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + usbd_xfer_set_stall(xfer); + } + /* FALLTHROUGH */ + case USB_ST_SETUP: + case USB_ST_TRANSFERRED: + pc = usbd_xfer_get_frame(xfer, 0); + if (ucom_get_data(&sc->sc_ucom, pc, 0, UDBC_OBUFSIZE, + &buflen) == 0) + break; + if (buflen != 0) { + usbd_xfer_set_frame_len(xfer, 0, buflen); + usbd_transfer_submit(xfer); + } + break; + } +} + +static void +udbc_read_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct udbc_softc *sc = usbd_xfer_softc(xfer); + struct usb_page_cache *pc; + int buflen; + + DPRINTFN(3, "\n"); + + usbd_xfer_status(xfer, &buflen, NULL, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + pc = usbd_xfer_get_frame(xfer, 0); + ucom_put_data(&sc->sc_ucom, pc, 0, buflen); + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); + usbd_transfer_submit(xfer); + return; + + default: /* Error */ + if (error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + return; + } +} + +static int +udbc_pre_param(struct ucom_softc *ucom, struct termios *t) +{ + DPRINTF("\n"); + + return (0); +} + +static int +udbc_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data, int flag, + struct thread *td) +{ + return (ENOIOCTL); +} + +static void +udbc_start_read(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_start(sc->sc_xfer[UDBC_BULK_DT_RD]); +} + +static void +udbc_stop_read(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_stop(sc->sc_xfer[UDBC_BULK_DT_RD]); +} + +static void +udbc_start_write(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_start(sc->sc_xfer[UDBC_BULK_DT_WR]); +} + +static void +udbc_stop_write(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_stop(sc->sc_xfer[UDBC_BULK_DT_WR]); +} + +static void +udbc_poll(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_poll(sc->sc_xfer, UDBC_N_TRANSFER); +} + +static driver_t udbc_driver = { + .name = "udbc", + .methods = udbc_methods, + .size = sizeof(struct udbc_softc), +}; + +DRIVER_MODULE(udbc, uhub, udbc_driver, NULL, NULL); +MODULE_DEPEND(udbc, ucom, 1, 1, 1); +MODULE_DEPEND(udbc, usb, 1, 1, 1); +MODULE_VERSION(udbc, 1); diff --git a/sys/dev/usb/wlan/if_mtw.c b/sys/dev/usb/wlan/if_mtw.c index 137590651948..6967e5081542 100644 --- a/sys/dev/usb/wlan/if_mtw.c +++ b/sys/dev/usb/wlan/if_mtw.c @@ -638,6 +638,7 @@ mtw_attach(device_t self) ic->ic_flags |= IEEE80211_F_DATAPAD; ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; mtw_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -3131,6 +3132,8 @@ mtw_tx(struct mtw_softc *sc, struct mbuf *m, struct ieee80211_node *ni) data->ni = ni; data->ridx = ridx; + ieee80211_output_seqno_assign(ni, -1, m); + mtw_set_tx_desc(sc, data); /* @@ -3390,6 +3393,8 @@ mtw_tx_param(struct mtw_softc *sc, struct mbuf *m, struct ieee80211_node *ni, break; data->ridx = ridx; + ieee80211_output_seqno_assign(ni, -1, m); + mtw_set_tx_desc(sc, data); MTW_DPRINTF(sc, MTW_DEBUG_XMIT, "sending raw frame len=%u rate=%u\n", diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index b49c75032d77..cc303e565bca 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -432,6 +432,8 @@ uath_attach(device_t dev) /* put a regulatory domain to reveal informations. */ uath_regdomain = sc->sc_devcap.regDomain; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); @@ -1548,6 +1550,8 @@ uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, ieee80211_radiotap_tx(vap, m0); } + ieee80211_output_seqno_assign(ni, -1, m0); + wh = mtod(m0, struct ieee80211_frame *); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 642631ae34b7..1ab833301b3c 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -354,6 +354,8 @@ upgt_attach(device_t dev) ic->ic_transmit = upgt_transmit; ic->ic_parent = upgt_parent; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), UPGT_TX_RADIOTAP_PRESENT, @@ -2116,6 +2118,9 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni, upgt_set_led(sc, UPGT_LED_BLINK); + /* Assign sequence number */ + ieee80211_output_seqno_assign(ni, -1, m); + /* * Software crypto. */ diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 260d75a9821d..adef924a085c 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -473,6 +473,8 @@ ural_attach(device_t self) | IEEE80211_C_WPA /* 802.11i */ ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + ural_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1073,6 +1075,8 @@ ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) STAILQ_REMOVE_HEAD(&sc->tx_free, next); sc->tx_nfree--; + ieee80211_output_seqno_assign(ni, -1, m0); + wh = mtod(m0, struct ieee80211_frame *); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); @@ -1229,6 +1233,8 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) rate = ieee80211_node_get_txrate_dot11rate(ni); } + ieee80211_output_seqno_assign(ni, -1, m0); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 439faeefc408..86cf4c653ae7 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -884,6 +884,8 @@ urtw_attach(device_t dev) /* XXX TODO: setup regdomain if URTW_EPROM_CHANPLAN_BY_HW bit is set.*/ + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + urtw_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1699,6 +1701,10 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + + /* Assign sequence number */ + ieee80211_output_seqno_assign(ni, -1, m0); + /* * Software crypto. */ diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 1a698caef3c5..7affdcdce089 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -384,6 +384,8 @@ zyd_attach(device_t dev) | IEEE80211_C_WPA /* 802.11i */ ; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; + zyd_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -2463,6 +2465,8 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) } } + ieee80211_output_seqno_assign(ni, -1, m0); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c index a751c09159ff..7f754ab7f1d4 100644 --- a/sys/fs/fuse/fuse_ipc.c +++ b/sys/fs/fuse/fuse_ipc.c @@ -193,7 +193,6 @@ fuse_interrupt_send(struct fuse_ticket *otick, int err) struct fuse_data *data = otick->tk_data; struct fuse_ticket *tick, *xtick; struct ucred reused_creds; - gid_t reused_groups[1]; if (otick->irq_unique == 0) { /* @@ -237,8 +236,7 @@ fuse_interrupt_send(struct fuse_ticket *otick, int err) */ ftick_hdr = fticket_in_header(otick); reused_creds.cr_uid = ftick_hdr->uid; - reused_groups[0] = ftick_hdr->gid; - reused_creds.cr_groups = reused_groups; + reused_creds.cr_gid = ftick_hdr->gid; fdisp_init(&fdi, sizeof(*fii)); fdisp_make_pid(&fdi, FUSE_INTERRUPT, data, ftick_hdr->nodeid, ftick_hdr->pid, &reused_creds); diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index de60a4717dd4..5c28db29fc63 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -795,11 +795,15 @@ fuse_vnop_close(struct vop_close_args *ap) struct mount *mp = vnode_mount(vp); struct ucred *cred = ap->a_cred; int fflag = ap->a_fflag; - struct thread *td = ap->a_td; - pid_t pid = td->td_proc->p_pid; + struct thread *td; struct fuse_vnode_data *fvdat = VTOFUD(vp); + pid_t pid; int err = 0; + /* NB: a_td will be NULL from some async kernel contexts */ + td = ap->a_td ? ap->a_td : curthread; + pid = td->td_proc->p_pid; + if (fuse_isdeadfs(vp)) return 0; if (vnode_isdir(vp)) @@ -838,7 +842,7 @@ fuse_vnop_close(struct vop_close_args *ap) } /* TODO: close the file handle, if we're sure it's no longer used */ if ((fvdat->flag & FN_SIZECHANGE) != 0) { - fuse_vnode_savesize(vp, cred, td->td_proc->p_pid); + fuse_vnode_savesize(vp, cred, pid); } return err; } @@ -953,7 +957,7 @@ fuse_vnop_copy_file_range(struct vop_copy_file_range_args *ap) *ap->a_outoffp += fwo->size; fuse_internal_clear_suid_on_write(outvp, outcred, td); if (*ap->a_outoffp > outfvdat->cached_attrs.va_size) { - fuse_vnode_setsize(outvp, *ap->a_outoffp, false); + fuse_vnode_setsize(outvp, *ap->a_outoffp, false); getnanouptime(&outfvdat->last_local_modify); } fuse_vnode_update(invp, FN_ATIMECHANGE); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 7040c4afb797..5ba86314ead1 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -3478,11 +3478,6 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, (nd->nd_flag & ND_AUTHNONE) != 0) { nd->nd_cred->cr_uid = credanon->cr_uid; nd->nd_cred->cr_gid = credanon->cr_gid; - /* - * 'credanon' is already a 'struct ucred' that was built - * internally with calls to crsetgroups_and_egid(), so - * we don't need a fallback here. - */ crsetgroups(nd->nd_cred, credanon->cr_ngroups, credanon->cr_groups); } else if ((nd->nd_flag & ND_GSS) == 0) { diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index fe83b54953cc..5461c6dd73d3 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -1107,8 +1107,6 @@ g_concat_ctl_append(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No 'arg%u' argument.", 1); goto fail; } - if (strncmp(name, "/dev/", strlen("/dev/")) == 0) - name += strlen("/dev/"); pp = g_provider_by_name(name); if (pp == NULL) { G_CONCAT_DEBUG(1, "Disk %s is invalid.", name); diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 250a2c60ffee..4459bd9f03f5 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -949,7 +949,6 @@ g_multipath_ctl_add_name(struct gctl_req *req, struct g_class *mp, struct g_consumer *cp; struct g_provider *pp; const char *mpname; - static const char devpf[6] = _PATH_DEV; int error; g_topology_assert(); @@ -966,8 +965,6 @@ g_multipath_ctl_add_name(struct gctl_req *req, struct g_class *mp, } sc = gp->softc; - if (strncmp(name, devpf, 5) == 0) - name += 5; pp = g_provider_by_name(name); if (pp == NULL) { gctl_error(req, "Provider %s is invalid", name); diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 8a7f67d8a313..4c0d0c3aa902 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -552,8 +552,6 @@ g_part_parm_provider(struct gctl_req *req, const char *name, pname = gctl_get_asciiparam(req, name); if (pname == NULL) return (ENOATTR); - if (strncmp(pname, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) - pname += sizeof(_PATH_DEV) - 1; pp = g_provider_by_name(pname); if (pp == NULL) { gctl_error(req, "%d %s '%s'", EINVAL, name, pname); diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c index 590f28aaa46c..d35695482eea 100644 --- a/sys/geom/raid/g_raid.c +++ b/sys/geom/raid/g_raid.c @@ -775,8 +775,6 @@ g_raid_open_consumer(struct g_raid_softc *sc, const char *name) g_topology_assert(); - if (strncmp(name, _PATH_DEV, 5) == 0) - name += 5; pp = g_provider_by_name(name); if (pp == NULL) return (NULL); diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index 4bed57b5afbf..b200588b0739 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -74,7 +74,7 @@ static __inline void clflushopt(u_long addr) { - __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); + __asm __volatile("clflushopt %0" : : "m" (*(char *)addr)); } static __inline void diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 2a833d2eafbe..19118eb7f275 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -658,6 +658,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) error = EBADF; break; } + fsetfl_lock(fp); do { tmp = flg = fp->f_flag; tmp &= ~FCNTLFLAGS; @@ -677,6 +678,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) if (error != 0) goto revert_nonblock; } + fsetfl_unlock(fp); fdrop(fp, td); break; revert_nonblock: @@ -691,6 +693,7 @@ revert_flags: tmp |= got_cleared; tmp &= ~got_set; } while (atomic_cmpset_int(&fp->f_flag, flg, tmp) == 0); + fsetfl_unlock(fp); fdrop(fp, td); break; diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index a75ba89d2a7e..3697d95fe0e5 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -243,6 +243,9 @@ static struct bool_flags pr_flag_allow[NBBY * NBPW] = { {"allow.unprivileged_parent_tampering", "allow.nounprivileged_parent_tampering", PR_ALLOW_UNPRIV_PARENT_TAMPER}, +#ifdef AUDIT + {"allow.setaudit", "allow.nosetaudit", PR_ALLOW_SETAUDIT}, +#endif }; static unsigned pr_allow_all = PR_ALLOW_ALL_STATIC; const size_t pr_flag_allow_size = sizeof(pr_flag_allow); @@ -4289,7 +4292,6 @@ prison_priv_check(struct ucred *cred, int priv) */ case PRIV_KTRACE: -#if 0 /* * Allow jailed processes to configure audit identity and * submit audit records (login, etc). In the future we may @@ -4298,6 +4300,11 @@ prison_priv_check(struct ucred *cred, int priv) */ case PRIV_AUDIT_GETAUDIT: case PRIV_AUDIT_SETAUDIT: + if (cred->cr_prison->pr_allow & PR_ALLOW_SETAUDIT) + return (0); + else + return (EPERM); +#if 0 case PRIV_AUDIT_SUBMIT: #endif @@ -5034,6 +5041,10 @@ SYSCTL_JAIL_PARAM(_allow, settime, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail may set system time"); SYSCTL_JAIL_PARAM(_allow, routing, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail may modify routing table"); +#ifdef AUDIT +SYSCTL_JAIL_PARAM(_allow, setaudit, CTLTYPE_INT | CTLFLAG_RW, + "B", "Jail may set and get audit session state"); +#endif SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags"); SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW, diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 0ca42d640767..a4c5bcc52529 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -291,11 +291,6 @@ sys_getgid(struct thread *td, struct getgid_args *uap) return (0); } -/* - * Get effective group ID. The "egid" is groups[0], and could be obtained - * via getgroups. This syscall exists because it is somewhat painful to do - * correctly in a library function. - */ #ifndef _SYS_SYSPROTO_H_ struct getegid_args { int dummy; @@ -1803,12 +1798,6 @@ groupmember(gid_t gid, const struct ucred *cred) bool realgroupmember(gid_t gid, const struct ucred *cred) { - /* - * Although the equality test on 'cr_rgid' below doesn't access - * 'cr_groups', we check for the latter's length here as we assume that, - * if 'cr_ngroups' is 0, the passed 'struct ucred' is invalid, and - * 'cr_rgid' may not have been filled. - */ groups_check_positive_len(cred->cr_ngroups); if (gid == cred->cr_rgid) @@ -1896,19 +1885,22 @@ SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, static int cr_canseeothergids(struct ucred *u1, struct ucred *u2) { - if (!see_other_gids) { - if (realgroupmember(u1->cr_rgid, u2)) - return (0); + if (see_other_gids) + return (0); - for (int i = 1; i < u1->cr_ngroups; i++) - if (realgroupmember(u1->cr_groups[i], u2)) - return (0); + /* Restriction in force. */ - if (priv_check_cred(u1, PRIV_SEEOTHERGIDS) != 0) - return (ESRCH); - } + if (realgroupmember(u1->cr_rgid, u2)) + return (0); - return (0); + for (int i = 0; i < u1->cr_ngroups; i++) + if (realgroupmember(u1->cr_groups[i], u2)) + return (0); + + if (priv_check_cred(u1, PRIV_SEEOTHERGIDS) == 0) + return (0); + + return (ESRCH); } /* @@ -2276,6 +2268,7 @@ cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred) } } grpsubset = grpsubset && + groupmember(obj_cred->cr_gid, active_cred) && groupmember(obj_cred->cr_rgid, active_cred) && groupmember(obj_cred->cr_svgid, active_cred); @@ -2921,8 +2914,8 @@ crextend(struct ucred *cr, int n) * Normalizes a set of groups to be applied to a 'struct ucred'. * * Normalization ensures that the supplementary groups are sorted in ascending - * order and do not contain duplicates. This allows group_is_supplementary - * to do a binary search. + * order and do not contain duplicates. This allows group_is_supplementary() to + * do a binary search. */ static void groups_normalize(int *ngrp, gid_t *groups) @@ -2985,9 +2978,9 @@ crsetgroups_internal(struct ucred *cr, int ngrp, const gid_t *groups) * Copy groups in to a credential after expanding it if required. * * May sleep in order to allocate memory (except if, e.g., crextend() was called - * before with 'ngrp' or greater). Truncates the list to ngroups_max if + * before with 'ngrp' or greater). Truncates the list to 'ngroups_max' if * it is too large. Array 'groups' doesn't need to be sorted. 'ngrp' must be - * strictly positive. + * positive. */ void crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups) @@ -3018,8 +3011,8 @@ crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups) * Same as crsetgroups() but sets the effective GID as well. * * This function ensures that an effective GID is always present in credentials. - * An empty array will only set the effective GID to the default_egid, while a - * non-empty array will peel off groups[0] to set as the effective GID and use + * An empty array will only set the effective GID to 'default_egid', while + * a non-empty array will peel off groups[0] to set as the effective GID and use * the remainder, if any, as supplementary groups. */ void diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index da0efac0598d..8efc0886988b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2656,9 +2656,11 @@ ptrace_coredumpreq(struct thread *td, struct proc *p, return; } + memset(&wctx, 0, sizeof(wctx)); wctx.vp = tcq->tc_vp; wctx.fcred = NOCRED; + memset(&cdw, 0, sizeof(wctx)); cdw.ctx = &wctx; cdw.write_fn = core_vn_write; cdw.extend_fn = core_vn_extend; diff --git a/sys/kern/subr_asan.c b/sys/kern/subr_asan.c index 464efda1e91a..fee6c1a844e2 100644 --- a/sys/kern/subr_asan.c +++ b/sys/kern/subr_asan.c @@ -835,6 +835,7 @@ ASAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t); ASAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t); ASAN_ATOMIC_FUNC_TESTANDSET(int, u_int); ASAN_ATOMIC_FUNC_TESTANDSET(long, u_long); +ASAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long); ASAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t); ASAN_ATOMIC_FUNC_SWAP(32, uint32_t); diff --git a/sys/kern/subr_msan.c b/sys/kern/subr_msan.c index a3238b61482b..883dbd2b7604 100644 --- a/sys/kern/subr_msan.c +++ b/sys/kern/subr_msan.c @@ -1301,6 +1301,7 @@ MSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t); MSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t); MSAN_ATOMIC_FUNC_TESTANDSET(int, u_int); MSAN_ATOMIC_FUNC_TESTANDSET(long, u_long); +MSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long); MSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t); MSAN_ATOMIC_FUNC_SWAP(32, uint32_t); diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c index 471640c290a7..a67e5fa6cbff 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -235,14 +235,11 @@ init_param1(void) * specification for <limits.h>, paragraph "Runtime Increasable * Values"). * - * On the other hand, INT_MAX would result in an overflow for the common - * 'ngroups_max + 1' computation (to obtain the size of the internal - * groups array, its first element being reserved for the effective - * GID). Also, the number of allocated bytes for the group array must - * not overflow on 32-bit machines. For all these reasons, we limit the - * number of supplementary groups to some very high number that we - * expect will never be reached in all practical uses and ensures we - * avoid the problems just exposed, even if 'gid_t' was to be enlarged + * On the other hand, a too high value would result in an overflow when + * computing the number of bytes to allocate for the groups array. We + * thus limit the number of supplementary groups to some very high + * number that we expect will never be reached in all practical uses, + * avoiding the problem just exposed even if 'gid_t' were to be enlarged * by a magnitude. */ ngroups_max = NGROUPS_MAX; diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c index db0e7bf5b0e3..eb5bd03f5018 100644 --- a/sys/kern/subr_power.c +++ b/sys/kern/subr_power.c @@ -3,6 +3,10 @@ * * Copyright (c) 2001 Mitsuru IWASAKI * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,20 +34,83 @@ #include <sys/eventhandler.h> #include <sys/power.h> #include <sys/proc.h> +#include <sys/sbuf.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <sys/taskqueue.h> +enum power_stype power_standby_stype = POWER_STYPE_STANDBY; +enum power_stype power_suspend_stype = POWER_STYPE_SUSPEND_TO_IDLE; +enum power_stype power_hibernate_stype = POWER_STYPE_HIBERNATE; + static u_int power_pm_type = POWER_PM_TYPE_NONE; static power_pm_fn_t power_pm_fn = NULL; static void *power_pm_arg = NULL; static struct task power_pm_task; +enum power_stype +power_name_to_stype(const char *name) +{ + enum power_stype stype; + + for (stype = 0; stype < POWER_STYPE_COUNT; stype++) { + if (strcasecmp(name, power_stype_names[stype]) == 0) + return (stype); + } + return (POWER_STYPE_UNKNOWN); +} + +const char * +power_stype_to_name(enum power_stype stype) +{ + if (stype == POWER_STYPE_UNKNOWN) + return ("NONE"); + if (stype < POWER_STYPE_AWAKE || stype >= POWER_STYPE_COUNT) + return (NULL); + return (power_stype_names[stype]); +} + +static int +power_sysctl_stype(SYSCTL_HANDLER_ARGS) +{ + char name[10]; + int err; + enum power_stype new_stype, old_stype; + + old_stype = *(enum power_stype *)oidp->oid_arg1; + strlcpy(name, power_stype_to_name(old_stype), sizeof(name)); + err = sysctl_handle_string(oidp, name, sizeof(name), req); + if (err != 0 || req->newptr == NULL) + return (err); + + new_stype = power_name_to_stype(name); + if (new_stype == POWER_STYPE_UNKNOWN) + return (EINVAL); + /* TODO Check to see if the new stype is supported. */ + if (new_stype != old_stype) + *(enum power_stype *)oidp->oid_arg1 = new_stype; + return (0); +} + +static SYSCTL_NODE(_kern, OID_AUTO, power, CTLFLAG_RW, 0, + "Generic power management related sysctls"); + +SYSCTL_PROC(_kern_power, OID_AUTO, standby, CTLTYPE_STRING | CTLFLAG_RW, + &power_standby_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on standby"); +SYSCTL_PROC(_kern_power, OID_AUTO, suspend, CTLTYPE_STRING | CTLFLAG_RW, + &power_suspend_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on suspend"); +SYSCTL_PROC(_kern_power, OID_AUTO, hibernate, CTLTYPE_STRING | CTLFLAG_RW, + &power_hibernate_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on hibernate"); + static void power_pm_deferred_fn(void *arg, int pending) { - int state = (intptr_t)arg; + enum power_stype stype = (intptr_t)arg; - power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state); + power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, stype); } int @@ -75,14 +142,27 @@ power_pm_get_type(void) void power_pm_suspend(int state) { + enum power_stype stype; + if (power_pm_fn == NULL) return; - if (state != POWER_SLEEP_STATE_STANDBY && - state != POWER_SLEEP_STATE_SUSPEND && - state != POWER_SLEEP_STATE_HIBERNATE) + switch (state) { + case POWER_SLEEP_STATE_STANDBY: + stype = power_standby_stype; + break; + case POWER_SLEEP_STATE_SUSPEND: + stype = power_suspend_stype; + break; + case POWER_SLEEP_STATE_HIBERNATE: + stype = power_hibernate_stype; + break; + default: + printf("%s: unknown sleep state %d\n", __func__, state); return; - power_pm_task.ta_context = (void *)(intptr_t)state; + } + + power_pm_task.ta_context = (void *)(intptr_t)stype; taskqueue_enqueue(taskqueue_thread, &power_pm_task); } diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index a65c3ca128d9..c937f6a82757 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -1515,6 +1515,10 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line) else lock_list = PCPU_PTR(spinlocks); + /* Update per-witness last file and line acquire. */ + w->w_file = file; + w->w_line = line; + /* Check to see if we are recursing on a lock we already own. */ instance = find_instance(*lock_list, lock); if (instance != NULL) { @@ -1522,15 +1526,9 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line) CTR4(KTR_WITNESS, "%s: pid %d recursed on %s r=%d", __func__, td->td_proc->p_pid, lock->lo_name, instance->li_flags & LI_RECURSEMASK); - instance->li_file = file; - instance->li_line = line; return; } - /* Update per-witness last file and line acquire. */ - w->w_file = file; - w->w_line = line; - /* Find the next open lock instance in the list and fill it. */ lle = *lock_list; if (lle == NULL || lle->ll_count == LOCK_NCHILDREN) { diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index ed651da96b14..30527fdd4fd0 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -234,6 +234,7 @@ static void pipeinit(void *dummy __unused); static void pipeclose(struct pipe *cpipe); static void pipe_free_kmem(struct pipe *cpipe); static int pipe_create(struct pipe *pipe, bool backing); +static void pipe_destroy(struct pipe *pipe); static int pipe_paircreate(struct thread *td, struct pipepair **p_pp); static __inline int pipelock(struct pipe *cpipe, bool catch); static __inline void pipeunlock(struct pipe *cpipe); @@ -399,16 +400,7 @@ pipe_paircreate(struct thread *td, struct pipepair **p_pp) goto fail; error = pipe_create(wpipe, false); if (error != 0) { - /* - * This cleanup leaves the pipe inode number for rpipe - * still allocated, but never used. We do not free - * inode numbers for opened pipes, which is required - * for correctness because numbers must be unique. - * But also it avoids any memory use by the unr - * allocator, so stashing away the transient inode - * number is reasonable. - */ - pipe_free_kmem(rpipe); + pipe_destroy(rpipe); goto fail; } @@ -743,6 +735,16 @@ pipe_create(struct pipe *pipe, bool large_backing) return (error); } +static void +pipe_destroy(struct pipe *pipe) +{ + pipe_free_kmem(pipe); + /* + * Note: we "leak" pipe_ino -- by design the alloc_unr64 mechanism does + * not undo allocations. + */ +} + /* ARGSUSED */ static int pipe_read(struct file *fp, struct uio *uio, struct ucred *active_cred, diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index 54b03fc82c90..acaf1241cb2e 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -175,7 +175,7 @@ kern_pdgetpid(struct thread *td, int fd, const cap_rights_t *rightsp, if (error) return (error); if (fp->f_type != DTYPE_PROCDESC) { - error = EINVAL; + error = EBADF; goto out; } *pidp = procdesc_pid(fp); diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 911f9093824b..967af1f5313c 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -552,13 +552,13 @@ _Out_writes_bytes_(len/PAGE_SIZE) char *vec ); } -79 AUE_GETGROUPS STD|CAPENABLED|COMPAT14 { +79 AUE_GETGROUPS COMPAT14|CAPENABLED { int getgroups( int gidsetsize, _Out_writes_opt_(gidsetsize) gid_t *gidset ); } -80 AUE_SETGROUPS STD|COMPAT14 { +80 AUE_SETGROUPS COMPAT14 { int setgroups( int gidsetsize, _In_reads_(gidsetsize) const gid_t *gidset diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 6138e543fae7..340d84666459 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -3667,11 +3667,14 @@ unp_internalize(struct mbuf *control, struct mchain *mc, struct thread *td) cmcred->cmcred_uid = td->td_ucred->cr_ruid; cmcred->cmcred_gid = td->td_ucred->cr_rgid; cmcred->cmcred_euid = td->td_ucred->cr_uid; - cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups, + _Static_assert(CMGROUP_MAX >= 1, + "Room needed for the effective GID."); + cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups + 1, CMGROUP_MAX); - for (i = 0; i < cmcred->cmcred_ngroups; i++) + cmcred->cmcred_groups[0] = td->td_ucred->cr_gid; + for (i = 1; i < cmcred->cmcred_ngroups; i++) cmcred->cmcred_groups[i] = - td->td_ucred->cr_groups[i]; + td->td_ucred->cr_groups[i - 1]; break; case SCM_RIGHTS: diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index f86bda2aa6f0..fe299ecc9c56 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3567,11 +3567,6 @@ enum vput_op { VRELE, VPUT, VUNREF }; * exclusive lock on the vnode, while it is legal to call here with only a * shared lock (or no locks). If locking the vnode in an expected manner fails, * inactive processing gets deferred to the syncer. - * - * XXX Some filesystems pass in an exclusively locked vnode and strongly depend - * on the lock being held all the way until VOP_INACTIVE. This in particular - * happens with UFS which adds half-constructed vnodes to the hash, where they - * can be found by other code. */ static void vput_final(struct vnode *vp, enum vput_op func) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index a4f41192f684..3d4567b6ab1e 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -798,58 +798,82 @@ vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, size_t len, } #if OFF_MAX <= LONG_MAX -off_t -foffset_lock(struct file *fp, int flags) +static void +file_v_lock(struct file *fp, short lock_bit, short lock_wait_bit) { - volatile short *flagsp; - off_t res; + short *flagsp; short state; - KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); - - if ((flags & FOF_NOLOCK) != 0) - return (atomic_load_long(&fp->f_offset)); - - /* - * According to McKusick the vn lock was protecting f_offset here. - * It is now protected by the FOFFSET_LOCKED flag. - */ - flagsp = &fp->f_vnread_flags; - if (atomic_cmpset_acq_16(flagsp, 0, FOFFSET_LOCKED)) - return (atomic_load_long(&fp->f_offset)); + flagsp = &fp->f_vflags; + state = atomic_load_16(flagsp); + if ((state & lock_bit) == 0 && + atomic_cmpset_acq_16(flagsp, state, state | lock_bit)) + return; - sleepq_lock(&fp->f_vnread_flags); + sleepq_lock(flagsp); state = atomic_load_16(flagsp); for (;;) { - if ((state & FOFFSET_LOCKED) == 0) { + if ((state & lock_bit) == 0) { if (!atomic_fcmpset_acq_16(flagsp, &state, - FOFFSET_LOCKED)) + state | lock_bit)) continue; break; } - if ((state & FOFFSET_LOCK_WAITING) == 0) { + if ((state & lock_wait_bit) == 0) { if (!atomic_fcmpset_acq_16(flagsp, &state, - state | FOFFSET_LOCK_WAITING)) + state | lock_wait_bit)) continue; } DROP_GIANT(); - sleepq_add(&fp->f_vnread_flags, NULL, "vofflock", 0, 0); - sleepq_wait(&fp->f_vnread_flags, PRI_MAX_KERN); + sleepq_add(flagsp, NULL, "vofflock", 0, 0); + sleepq_wait(flagsp, PRI_MAX_KERN); PICKUP_GIANT(); - sleepq_lock(&fp->f_vnread_flags); + sleepq_lock(flagsp); state = atomic_load_16(flagsp); } - res = atomic_load_long(&fp->f_offset); - sleepq_release(&fp->f_vnread_flags); - return (res); + sleepq_release(flagsp); } -void -foffset_unlock(struct file *fp, off_t val, int flags) +static void +file_v_unlock(struct file *fp, short lock_bit, short lock_wait_bit) { - volatile short *flagsp; + short *flagsp; short state; + flagsp = &fp->f_vflags; + state = atomic_load_16(flagsp); + if ((state & lock_wait_bit) == 0 && + atomic_cmpset_rel_16(flagsp, state, state & ~lock_bit)) + return; + + sleepq_lock(flagsp); + MPASS((*flagsp & lock_bit) != 0); + MPASS((*flagsp & lock_wait_bit) != 0); + atomic_clear_16(flagsp, lock_bit | lock_wait_bit); + sleepq_broadcast(flagsp, SLEEPQ_SLEEP, 0, 0); + sleepq_release(flagsp); +} + +off_t +foffset_lock(struct file *fp, int flags) +{ + KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); + + if ((flags & FOF_NOLOCK) == 0) { + file_v_lock(fp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); + } + + /* + * According to McKusick the vn lock was protecting f_offset here. + * It is now protected by the FOFFSET_LOCKED flag. + */ + return (atomic_load_long(&fp->f_offset)); +} + +void +foffset_unlock(struct file *fp, off_t val, int flags) +{ KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); if ((flags & FOF_NOUPDATE) == 0) @@ -859,21 +883,10 @@ foffset_unlock(struct file *fp, off_t val, int flags) if ((flags & FOF_NEXTOFF_W) != 0) fp->f_nextoff[UIO_WRITE] = val; - if ((flags & FOF_NOLOCK) != 0) - return; - - flagsp = &fp->f_vnread_flags; - state = atomic_load_16(flagsp); - if ((state & FOFFSET_LOCK_WAITING) == 0 && - atomic_cmpset_rel_16(flagsp, state, 0)) - return; - - sleepq_lock(&fp->f_vnread_flags); - MPASS((fp->f_vnread_flags & FOFFSET_LOCKED) != 0); - MPASS((fp->f_vnread_flags & FOFFSET_LOCK_WAITING) != 0); - fp->f_vnread_flags = 0; - sleepq_broadcast(&fp->f_vnread_flags, SLEEPQ_SLEEP, 0, 0); - sleepq_release(&fp->f_vnread_flags); + if ((flags & FOF_NOLOCK) == 0) { + file_v_unlock(fp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); + } } static off_t @@ -882,7 +895,47 @@ foffset_read(struct file *fp) return (atomic_load_long(&fp->f_offset)); } -#else + +void +fsetfl_lock(struct file *fp) +{ + file_v_lock(fp, FILE_V_SETFL_LOCKED, FILE_V_SETFL_LOCK_WAITING); +} + +void +fsetfl_unlock(struct file *fp) +{ + file_v_unlock(fp, FILE_V_SETFL_LOCKED, FILE_V_SETFL_LOCK_WAITING); +} + +#else /* OFF_MAX <= LONG_MAX */ + +static void +file_v_lock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit, + short lock_wait_bit) +{ + mtx_assert(mtxp, MA_OWNED); + + while ((fp->f_vflags & lock_bit) != 0) { + fp->f_vflags |= lock_wait_bit; + msleep(&fp->f_vflags, mtxp, PRI_MAX_KERN, + "vofflock", 0); + } + fp->f_vflags |= lock_bit; +} + +static void +file_v_unlock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit, + short lock_wait_bit) +{ + mtx_assert(mtxp, MA_OWNED); + + KASSERT((fp->f_vflags & lock_bit) != 0, ("Lost lock_bit")); + if ((fp->f_vflags & lock_wait_bit) != 0) + wakeup(&fp->f_vflags); + fp->f_vflags &= ~(lock_bit | lock_wait_bit); +} + off_t foffset_lock(struct file *fp, int flags) { @@ -894,12 +947,8 @@ foffset_lock(struct file *fp, int flags) mtxp = mtx_pool_find(mtxpool_sleep, fp); mtx_lock(mtxp); if ((flags & FOF_NOLOCK) == 0) { - while (fp->f_vnread_flags & FOFFSET_LOCKED) { - fp->f_vnread_flags |= FOFFSET_LOCK_WAITING; - msleep(&fp->f_vnread_flags, mtxp, PRI_MAX_KERN, - "vofflock", 0); - } - fp->f_vnread_flags |= FOFFSET_LOCKED; + file_v_lock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); } res = fp->f_offset; mtx_unlock(mtxp); @@ -922,11 +971,8 @@ foffset_unlock(struct file *fp, off_t val, int flags) if ((flags & FOF_NEXTOFF_W) != 0) fp->f_nextoff[UIO_WRITE] = val; if ((flags & FOF_NOLOCK) == 0) { - KASSERT((fp->f_vnread_flags & FOFFSET_LOCKED) != 0, - ("Lost FOFFSET_LOCKED")); - if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) - wakeup(&fp->f_vnread_flags); - fp->f_vnread_flags = 0; + file_v_unlock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); } mtx_unlock(mtxp); } @@ -937,6 +983,30 @@ foffset_read(struct file *fp) return (foffset_lock(fp, FOF_NOLOCK)); } + +void +fsetfl_lock(struct file *fp) +{ + struct mtx *mtxp; + + mtxp = mtx_pool_find(mtxpool_sleep, fp); + mtx_lock(mtxp); + file_v_lock_mtxp(fp, mtxp, FILE_V_SETFL_LOCKED, + FILE_V_SETFL_LOCK_WAITING); + mtx_unlock(mtxp); +} + +void +fsetfl_unlock(struct file *fp) +{ + struct mtx *mtxp; + + mtxp = mtx_pool_find(mtxpool_sleep, fp); + mtx_lock(mtxp); + file_v_unlock_mtxp(fp, mtxp, FILE_V_SETFL_LOCKED, + FILE_V_SETFL_LOCK_WAITING); + mtx_unlock(mtxp); +} #endif void diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 5315d518afd8..f9fdbca78869 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -576,7 +576,10 @@ _mlx5ib= mlx5ib ${MACHINE_CPUARCH} == "i386" _ena= ena _gve= gve +# gcc13 and earlier lack __builtin_bitcountg used by linux emulation +.if !(${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} < 140000) _iwlwifi= iwlwifi +.endif _rtw88= rtw88 _rtw89= rtw89 _vmware= vmware diff --git a/sys/modules/dtrace/dtraceall/dtraceall.c b/sys/modules/dtrace/dtraceall/dtraceall.c index 851d33a7e518..1978b9ead362 100644 --- a/sys/modules/dtrace/dtraceall/dtraceall.c +++ b/sys/modules/dtrace/dtraceall/dtraceall.c @@ -74,11 +74,11 @@ MODULE_DEPEND(dtraceall, dtnfscl, 1, 1, 1); defined(__i386__) || defined(__powerpc__) || defined(__riscv) MODULE_DEPEND(dtraceall, fbt, 1, 1, 1); #endif -#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__) -MODULE_DEPEND(dtraceall, fasttrap, 1, 1, 1); -#if defined(__amd64__) +#if defined(__amd64__) || defined(__aarch64__) || defined(__riscv) MODULE_DEPEND(dtraceall, kinst, 1, 1, 1); #endif +#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__) +MODULE_DEPEND(dtraceall, fasttrap, 1, 1, 1); #endif MODULE_DEPEND(dtraceall, sdt, 1, 1, 1); MODULE_DEPEND(dtraceall, systrace, 1, 1, 1); diff --git a/sys/modules/qatfw/qat_4xxx/Makefile b/sys/modules/qatfw/qat_4xxx/Makefile index fb7171bcaf45..f6f19d6cbe32 100644 --- a/sys/modules/qatfw/qat_4xxx/Makefile +++ b/sys/modules/qatfw/qat_4xxx/Makefile @@ -4,6 +4,9 @@ KMOD= qat_4xxx_fw -FIRMWS= qat_4xxx.bin:qat_4xxx_fw:111 qat_4xxx_mmp.bin:qat_4xxx_mmp_fw:111 +FIRMWS= qat_4xxx.bin:qat_4xxx_fw:111 \ + qat_4xxx_mmp.bin:qat_4xxx_mmp_fw:111 \ + qat_402xx.bin:qat_402xx_fw:111 \ + qat_402xx_mmp.bin:qat_402xx_mmp_fw:111 .include <bsd.kmod.mk> diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile index 1290b878fa37..d9b1c8635b30 100644 --- a/sys/modules/usb/Makefile +++ b/sys/modules/usb/Makefile @@ -46,10 +46,9 @@ SUBDIR = usb SUBDIR += ${_dwc_otg} ehci ${_musb} ohci uhci xhci ${_uss820dci} \ ${_atmegadci} ${_avr32dci} ${_rsu} ${_rsufw} ${_bcm2838_xhci} SUBDIR += mtw ${_rum} ${_run} ${_runfw} ${_uath} upgt usie ural ${_zyd} ${_urtw} -SUBDIR += atp cfumass uhid uhid_snes ukbd ums udbp uep wmt wsp ugold uled \ - usbhid -SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ - umb umct umcs umodem umoscom uplcom uslcom uvisor uvscom +SUBDIR += atp cfumass uhid uhid_snes ukbd ums udbp uep wmt wsp ugold uled usbhid +SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom udbc ufoma uftdi ugensa uipaq +SUBDIR += ulpt umb umct umcs umodem umoscom uplcom uslcom uvisor uvscom SUBDIR += i2ctinyusb SUBDIR += cp2112 SUBDIR += udl diff --git a/sys/modules/usb/udbc/Makefile b/sys/modules/usb/udbc/Makefile new file mode 100644 index 000000000000..9996b2e391fb --- /dev/null +++ b/sys/modules/usb/udbc/Makefile @@ -0,0 +1,9 @@ +S= ${SRCTOP}/sys + +.PATH: $S/dev/usb/serial + +KMOD= udbc +SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \ + udbc.c + +.include <bsd.kmod.mk> diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c index fe015632f33e..1c18baac3417 100644 --- a/sys/net/if_ovpn.c +++ b/sys/net/if_ovpn.c @@ -904,9 +904,11 @@ ovpn_create_kkey_dir(struct ovpn_kkey_dir **kdirp, kdir->cipher = cipher; kdir->keylen = keylen; kdir->tx_seq = 1; - memcpy(kdir->key, key, keylen); + if (keylen != 0) + memcpy(kdir->key, key, keylen); kdir->noncelen = ivlen; - memcpy(kdir->nonce, iv, ivlen); + if (ivlen != 0) + memcpy(kdir->nonce, iv, ivlen); if (kdir->cipher != OVPN_CIPHER_ALG_NONE) { /* Crypto init */ diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index e6fb1c2c3e1b..8b102f198de8 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1751,6 +1751,7 @@ struct pf_kstatus { counter_u64_t lcounters[KLCNT_MAX]; /* limit counters */ struct pf_counter_u64 fcounters[FCNT_MAX]; /* state operation counters */ counter_u64_t scounters[SCNT_MAX]; /* src_node operation counters */ + counter_u64_t ncounters[NCNT_MAX]; uint32_t states; uint32_t src_nodes; uint32_t running; @@ -2391,8 +2392,6 @@ extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t, extern u_int16_t pf_proto_cksum_fixup(struct mbuf *, u_int16_t, u_int16_t, u_int16_t, u_int8_t); -VNET_DECLARE(struct ifnet *, sync_ifp); -#define V_sync_ifp VNET(sync_ifp); VNET_DECLARE(struct pf_krule, pf_default_rule); #define V_pf_default_rule VNET(pf_default_rule) extern void pf_addrcpy(struct pf_addr *, const struct pf_addr *, @@ -2440,6 +2439,7 @@ int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); void pf_normalize_init(void); void pf_normalize_cleanup(void); +uint64_t pf_normalize_get_frag_count(void); int pf_normalize_tcp(struct pf_pdesc *); void pf_normalize_tcp_cleanup(struct pf_kstate *); int pf_normalize_tcp_init(struct pf_pdesc *, @@ -2543,22 +2543,23 @@ struct mbuf *pf_build_tcp(const struct pf_krule *, sa_family_t, const struct pf_addr *, const struct pf_addr *, u_int16_t, u_int16_t, u_int32_t, u_int32_t, u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, - u_int16_t, u_int16_t, u_int, int); + u_int16_t, u_int16_t, u_int, int, u_short *); void pf_send_tcp(const struct pf_krule *, sa_family_t, const struct pf_addr *, const struct pf_addr *, u_int16_t, u_int16_t, u_int32_t, u_int32_t, u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, - u_int16_t, u_int16_t, int); + u_int16_t, u_int16_t, int, u_short *); void pf_syncookies_init(void); void pf_syncookies_cleanup(void); int pf_get_syncookies(struct pfioc_nv *); int pf_set_syncookies(struct pfioc_nv *); int pf_synflood_check(struct pf_pdesc *); -void pf_syncookie_send(struct pf_pdesc *); +void pf_syncookie_send(struct pf_pdesc *, u_short *); bool pf_syncookie_check(struct pf_pdesc *); u_int8_t pf_syncookie_validate(struct pf_pdesc *); -struct mbuf * pf_syncookie_recreate_syn(struct pf_pdesc *); +struct mbuf * pf_syncookie_recreate_syn(struct pf_pdesc *, + u_short *); VNET_DECLARE(struct pf_kstatus, pf_status); #define V_pf_status VNET(pf_status) diff --git a/sys/netgraph/bluetooth/include/ng_hci.h b/sys/netgraph/bluetooth/include/ng_hci.h index 44a14e62f4ed..ce3291770740 100644 --- a/sys/netgraph/bluetooth/include/ng_hci.h +++ b/sys/netgraph/bluetooth/include/ng_hci.h @@ -448,7 +448,7 @@ typedef struct { typedef bdaddr_t * bdaddr_p; /* Any BD_ADDR. Note: This is actually 7 bytes (count '\0' terminator) */ -#define NG_HCI_BDADDR_ANY ((bdaddr_p) "\000\000\000\000\000\000") +#define NG_HCI_BDADDR_ANY (&(const bdaddr_t){"\000\000\000\000\000\000"}) /* HCI status return parameter */ typedef struct { diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c index 6c0a6fda1fb1..73a0897857b2 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c @@ -113,7 +113,7 @@ static void ng_btsocket_rfcomm_connect_cfm static int ng_btsocket_rfcomm_session_create (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so, - bdaddr_p src, bdaddr_p dst, struct thread *td); + const bdaddr_t *src, const bdaddr_t *dst, struct thread *td); static int ng_btsocket_rfcomm_session_accept (ng_btsocket_rfcomm_session_p s0); static int ng_btsocket_rfcomm_session_connect @@ -1250,7 +1250,7 @@ ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s) static int ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp, - struct socket *l2so, bdaddr_p src, bdaddr_p dst, + struct socket *l2so, const bdaddr_t *src, const bdaddr_t *dst, struct thread *td) { ng_btsocket_rfcomm_session_p s = NULL; diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 4f756a75fac7..8ef755e2dc0a 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2604,6 +2604,8 @@ in6_domifattach(struct ifnet *ifp) COUNTER_ARRAY_ALLOC(ext->icmp6_ifstat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_WAITOK); + ext->dad_failures = counter_u64_alloc(M_WAITOK); + ext->nd_ifinfo = nd6_ifattach(ifp); ext->scope6_id = scope6_ifattach(ifp); ext->lltable = in6_lltattach(ifp); @@ -2639,6 +2641,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux) COUNTER_ARRAY_FREE(ext->icmp6_ifstat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); free(ext->icmp6_ifstat, M_IFADDR); + counter_u64_free(ext->dad_failures); free(ext, M_IFADDR); } diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 1ca846ebf514..a7fe03b9c3d7 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -358,11 +358,11 @@ extern const struct in6_addr in6addr_linklocal_allv2routers; #define IFA6_IS_DEPRECATED(a) \ ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \ - (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \ + (u_int32_t)((time_uptime - (a)->ia6_updatetime)) >= \ (a)->ia6_lifetime.ia6t_pltime) #define IFA6_IS_INVALID(a) \ ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \ - (u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \ + (u_int32_t)((time_uptime - (a)->ia6_updatetime)) >= \ (a)->ia6_lifetime.ia6t_vltime) #endif /* _KERNEL */ @@ -609,6 +609,8 @@ struct ip6_mtuinfo { /* IPV6CTL_RTMINEXPIRE 26 deprecated */ /* IPV6CTL_RTMAXCACHE 27 deprecated */ +#define IPV6CTL_STABLEADDR_NETIFSRC 30 /* semantically opaque addresses (RFC7217) hash algo netif parameter src */ +#define IPV6CTL_STABLEADDR_MAXRETRIES 31 /* semantically opaque addresses (RFC7217) max DAD retries */ #define IPV6CTL_USETEMPADDR 32 /* use temporary addresses (RFC3041) */ #define IPV6CTL_TEMPPLTIME 33 /* preferred lifetime for tmpaddrs */ #define IPV6CTL_TEMPVLTIME 34 /* valid lifetime for tmpaddrs */ @@ -617,6 +619,7 @@ struct ip6_mtuinfo { #define IPV6CTL_PREFER_TEMPADDR 37 /* prefer temporary addr as src */ #define IPV6CTL_ADDRCTLPOLICY 38 /* get/set address selection policy */ #define IPV6CTL_USE_DEFAULTZONE 39 /* use default scope zone */ +#define IPV6CTL_USESTABLEADDR 40 /* use semantically opaque addresses (RFC7217) */ #define IPV6CTL_MAXFRAGS 41 /* max fragments */ #if 0 diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index cc149616006e..4fde346fb691 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -33,6 +33,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/counter.h> #include <sys/malloc.h> #include <sys/socket.h> #include <sys/sockio.h> @@ -43,6 +44,7 @@ #include <sys/rmlock.h> #include <sys/syslog.h> #include <sys/md5.h> +#include <crypto/sha2/sha256.h> #include <net/if.h> #include <net/if_var.h> @@ -79,6 +81,8 @@ VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */ VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch); #define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) +VNET_DEFINE(int, ip6_stableaddr_netifsource) = IP6_STABLEADDR_NETIFSRC_NAME; /* Use interface name by default */ + VNET_DECLARE(struct inpcbinfo, ripcbinfo); #define V_ripcbinfo VNET(ripcbinfo) @@ -98,6 +102,9 @@ static void in6_purgemaddrs(struct ifnet *); #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5C + /* * Generate a last-resort interface identifier, when the machine has no * IEEE802/EUI64 address sources. @@ -147,22 +154,14 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) } -/* - * Get interface identifier for the specified interface. - * XXX assumes single sockaddr_dl (AF_LINK address) per an interface - * - * in6 - upper 64bits are preserved +/** + * Get interface link level sockaddr */ -int -in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) +static struct sockaddr_dl * +get_interface_link_level(struct ifnet *ifp) { struct ifaddr *ifa; struct sockaddr_dl *sdl; - u_int8_t *addr; - size_t addrlen; - static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static u_int8_t allone[8] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; NET_EPOCH_ASSERT(); @@ -175,14 +174,30 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) if (sdl->sdl_alen == 0) continue; - goto found; + return sdl; } - return -1; + return NULL; +} + +/* + * Get hwaddr from link interface + */ +static uint8_t * +in6_get_interface_hwaddr(struct ifnet *ifp, size_t *len) +{ + struct sockaddr_dl *sdl; + u_int8_t *addr; + static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + static u_int8_t allone[8] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + sdl = get_interface_link_level(ifp); + if (sdl == NULL) + return (NULL); -found: addr = LLADDR(sdl); - addrlen = sdl->sdl_alen; + *len = sdl->sdl_alen; /* get EUI64 */ switch (ifp->if_type) { @@ -193,36 +208,21 @@ found: case IFT_IEEE1394: /* IEEE802/EUI64 cases - what others? */ /* IEEE1394 uses 16byte length address starting with EUI64 */ - if (addrlen > 8) - addrlen = 8; + if (*len > 8) + *len = 8; /* look at IEEE802/EUI64 only */ - if (addrlen != 8 && addrlen != 6) - return -1; + if (*len != 8 && *len != 6) + return (NULL); /* * check for invalid MAC address - on bsdi, we see it a lot * since wildboar configures all-zero MAC on pccard before * card insertion. */ - if (bcmp(addr, allzero, addrlen) == 0) - return -1; - if (bcmp(addr, allone, addrlen) == 0) - return -1; - - /* make EUI64 address */ - if (addrlen == 8) - bcopy(addr, &in6->s6_addr[8], 8); - else if (addrlen == 6) { - in6->s6_addr[8] = addr[0]; - in6->s6_addr[9] = addr[1]; - in6->s6_addr[10] = addr[2]; - in6->s6_addr[11] = 0xff; - in6->s6_addr[12] = 0xfe; - in6->s6_addr[13] = addr[3]; - in6->s6_addr[14] = addr[4]; - in6->s6_addr[15] = addr[5]; - } + if (memcmp(addr, allzero, *len) == 0 || memcmp(addr, allone, *len) == 0) + return (NULL); + break; case IFT_GIF: @@ -233,16 +233,51 @@ found: * identifier source (can be renumbered). * we don't do this. */ - return -1; + return (NULL); case IFT_INFINIBAND: - if (addrlen != 20) - return -1; - bcopy(addr + 12, &in6->s6_addr[8], 8); + if (*len != 20) + return (NULL); + *len = 8; + addr += 12; break; default: + return (NULL); + } + + return addr; +} + + /* + * Get interface identifier for the specified interface. + * XXX assumes single sockaddr_dl (AF_LINK address) per an interface + * + * in6 - upper 64bits are preserved + */ +int +in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) +{ + size_t hwaddr_len; + uint8_t *hwaddr; + static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + hwaddr = in6_get_interface_hwaddr(ifp, &hwaddr_len); + if (hwaddr == NULL || (hwaddr_len != 6 && hwaddr_len != 8)) return -1; + + /* make EUI64 address */ + if (hwaddr_len == 8) + memcpy(&in6->s6_addr[8], hwaddr, 8); + else if (hwaddr_len == 6) { + in6->s6_addr[8] = hwaddr[0]; + in6->s6_addr[9] = hwaddr[1]; + in6->s6_addr[10] = hwaddr[2]; + in6->s6_addr[11] = 0xff; + in6->s6_addr[12] = 0xfe; + in6->s6_addr[13] = hwaddr[3]; + in6->s6_addr[14] = hwaddr[4]; + in6->s6_addr[15] = hwaddr[5]; } /* sanity check: g bit must not indicate "group" */ @@ -264,6 +299,153 @@ found: } /* + * Validate generated interface id to make sure it does not fall in any reserved range: + * + * https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xhtml + */ +static bool +validate_ifid(uint8_t *iid) +{ + static uint8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint8_t reserved_eth[5] = { 0x02, 0x00, 0x5E, 0xFF, 0xFE }; + static uint8_t reserved_anycast[7] = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + /* Subnet-Router Anycast (RFC 4291)*/ + if (memcmp(iid, allzero, 8) == 0) + return (false); + + /* + * Reserved IPv6 Interface Identifiers corresponding to the IANA Ethernet Block (RFC 4291) + * and + * Proxy Mobile IPv6 (RFC 6543) + */ + if (memcmp(iid, reserved_eth, 5) == 0) + return (false); + + /* Reserved Subnet Anycast Addresses (RFC 2526) */ + if (memcmp(iid, reserved_anycast, 7) == 0 && iid[7] >= 0x80) + return (false); + + return (true); +} + +/* + * Get interface identifier for the specified interface, according to + * RFC 7217 Stable and Opaque IDs with SLAAC, using HMAC-SHA256 digest. + * + * in6 - upper 64bits are preserved + */ +bool +in6_get_stableifid(struct ifnet *ifp, struct in6_addr *in6, int prefixlen) +{ + struct sockaddr_dl *sdl; + const uint8_t *netiface; + size_t netiface_len, hostuuid_len; + uint8_t hostuuid[HOSTUUIDLEN + 1], hmac_key[SHA256_BLOCK_LENGTH], + hk_ipad[SHA256_BLOCK_LENGTH], hk_opad[SHA256_BLOCK_LENGTH]; + uint64_t dad_failures; + SHA256_CTX ctxt; + + switch (V_ip6_stableaddr_netifsource) { + case IP6_STABLEADDR_NETIFSRC_ID: + sdl = get_interface_link_level(ifp); + if (sdl == NULL) + return (false); + netiface = (uint8_t *)&LLINDEX(sdl); + netiface_len = sizeof(u_short); /* real return type of LLINDEX */ + break; + + case IP6_STABLEADDR_NETIFSRC_MAC: + netiface = in6_get_interface_hwaddr(ifp, &netiface_len); + if (netiface == NULL) + return (false); + break; + + case IP6_STABLEADDR_NETIFSRC_NAME: + default: + netiface = (const uint8_t *)if_name(ifp); + netiface_len = strlen(netiface); + break; + } + + /* Use hostuuid as constant "secret" key */ + getcredhostuuid(curthread->td_ucred, hostuuid, sizeof(hostuuid)); + if (strncmp(hostuuid, DEFAULT_HOSTUUID, sizeof(hostuuid)) == 0) { + // If hostuuid is not set, use a random value + arc4rand(hostuuid, HOSTUUIDLEN, 0); + hostuuid[HOSTUUIDLEN] = '\0'; + } + hostuuid_len = strlen(hostuuid); + + dad_failures = counter_u64_fetch(DAD_FAILURES(ifp)); + + /* + * RFC 7217 section 7 + * + * default max retries + */ + if (dad_failures > V_ip6_stableaddr_maxretries) + return (false); + + /* + * Use hostuuid as basis for HMAC key + */ + memset(hmac_key, 0, sizeof(hmac_key)); + if (hostuuid_len <= SHA256_BLOCK_LENGTH) { + /* copy to hmac key variable, zero padded */ + memcpy(hmac_key, hostuuid, hostuuid_len); + } else { + /* if longer than block length, use hash of the value, zero padded */ + SHA256_Init(&ctxt); + SHA256_Update(&ctxt, hostuuid, hostuuid_len); + SHA256_Final(hmac_key, &ctxt); + } + /* XOR key with ipad and opad values */ + for (uint16_t i = 0; i < sizeof(hmac_key); i++) { + hk_ipad[i] = hmac_key[i] ^ HMAC_IPAD; + hk_opad[i] = hmac_key[i] ^ HMAC_OPAD; + } + + /* + * Generate interface id in a loop, adding an offset to be factored in the hash function. + * This is necessary, because if the generated interface id happens to be invalid we + * want to force the hash function to generate a different one, otherwise we would end up + * in an infinite loop trying the same invalid interface id over and over again. + * + * Using an uint8 counter for the offset, so limit iteration at UINT8_MAX. This is a safety + * measure, this will never iterate more than once or twice in practice. + */ + for(uint8_t offset = 0; offset < UINT8_MAX; offset++) { + uint8_t digest[SHA256_DIGEST_LENGTH]; + + /* Calculate inner hash */ + SHA256_Init(&ctxt); + SHA256_Update(&ctxt, hk_ipad, sizeof(hk_ipad)); + SHA256_Update(&ctxt, in6->s6_addr, prefixlen / 8); + SHA256_Update(&ctxt, netiface, netiface_len); + SHA256_Update(&ctxt, (uint8_t *)&dad_failures, 8); + SHA256_Update(&ctxt, hostuuid, hostuuid_len); + SHA256_Update(&ctxt, &offset, 1); + SHA256_Final(digest, &ctxt); + + /* Calculate outer hash */ + SHA256_Init(&ctxt); + SHA256_Update(&ctxt, hk_opad, sizeof(hk_opad)); + SHA256_Update(&ctxt, digest, sizeof(digest)); + SHA256_Final(digest, &ctxt); + + if (validate_ifid(digest)) { + /* assumes sizeof(digest) > sizeof(ifid) */ + memcpy(&in6->s6_addr[8], digest, 8); + + return (true); + } + } + + return (false); +} + +/* * Get interface identifier for the specified interface. If it is not * available on ifp0, borrow interface identifier from other information * sources. @@ -278,7 +460,14 @@ in6_get_ifid(struct ifnet *ifp0, struct ifnet *altifp, NET_EPOCH_ASSERT(); - /* first, try to get it from the interface itself */ + /* first, try to get it from the interface itself, with stable algorithm, if configured */ + if ((ND_IFINFO(ifp0)->flags & ND6_IFF_STABLEADDR) && in6_get_stableifid(ifp0, in6, 64) == 0) { + nd6log((LOG_DEBUG, "%s: got interface identifier from itself (stable private)\n", + if_name(ifp0))); + goto success; + } + + /* then/otherwise try to get it from the interface itself */ if (in6_get_hw_ifid(ifp0, in6) == 0) { nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", if_name(ifp0))); diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h index fd52422b10be..75b2ca4fa018 100644 --- a/sys/netinet6/in6_ifattach.h +++ b/sys/netinet6/in6_ifattach.h @@ -39,6 +39,8 @@ void in6_ifattach(struct ifnet *, struct ifnet *); void in6_ifattach_destroy(void); void in6_ifdetach(struct ifnet *); void in6_ifdetach_destroy(struct ifnet *); +int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int); +bool in6_get_stableifid(struct ifnet *, struct in6_addr *, int); void in6_tmpaddrtimer(void *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); int in6_get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index b289d4eeb0a2..6669a2ba56ce 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -167,6 +167,7 @@ VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix * walk list every 5 sec. */ VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */ VNET_DEFINE(int, ip6_v6only) = 1; +VNET_DEFINE(int, ip6_stableaddr_maxretries) = IP6_IDGEN_RETRIES; #ifdef IPSTEALTH VNET_DEFINE(int, ip6stealth) = 0; @@ -313,6 +314,15 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE, rr_prune, SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USETEMPADDR, use_tempaddr, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_use_tempaddr), 0, "Create RFC3041 temporary addresses for autoconfigured addresses"); +SYSCTL_BOOL(_net_inet6_ip6, IPV6CTL_USESTABLEADDR, use_stableaddr, + CTLFLAG_VNET | CTLFLAG_RWTUN, &VNET_NAME(ip6_use_stableaddr), 0, + "Create RFC7217 semantically opaque address for autoconfigured addresses (default for new interfaces)"); +SYSCTL_INT(_net_inet6_ip6, IPV6CTL_STABLEADDR_MAXRETRIES, stableaddr_maxretries, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_stableaddr_maxretries), IP6_IDGEN_RETRIES, + "RFC7217 semantically opaque address DAD max retries"); +SYSCTL_INT(_net_inet6_ip6, IPV6CTL_STABLEADDR_NETIFSRC, stableaddr_netifsource, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_stableaddr_netifsource), IP6_STABLEADDR_NETIFSRC_NAME, + "RFC7217 semantically opaque address Net_Iface source (0 - name, 1 - ID, 2 - MAC addr)"); SYSCTL_PROC(_net_inet6_ip6, IPV6CTL_TEMPPLTIME, temppltime, CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, NULL, 0, sysctl_ip6_temppltime, "I", diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index e5ab83e6a2a1..e511ead24f08 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -106,9 +106,11 @@ struct in6_ifextra { struct scope6_id *scope6_id; struct lltable *lltable; struct mld_ifsoftc *mld_ifinfo; + counter_u64_t dad_failures; /* DAD failures when using RFC 7217 stable addresses */ }; #define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) +#define DAD_FAILURES(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->dad_failures) #ifdef _KERNEL diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 45fd23ea6c21..99dad1e7c309 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -235,6 +235,7 @@ ip6_vnet_init(void *arg __unused) &V_ip6_auto_linklocal); TUNABLE_INT_FETCH("net.inet6.ip6.accept_rtadv", &V_ip6_accept_rtadv); TUNABLE_INT_FETCH("net.inet6.ip6.no_radr", &V_ip6_no_radr); + TUNABLE_BOOL_FETCH("net.inet6.ip6.use_stableaddr", &V_ip6_use_stableaddr); CK_STAILQ_INIT(&V_in6_ifaddrhead); V_in6_ifaddrhashtbl = hashinit(IN6ADDR_NHASH, M_IFADDR, @@ -1197,8 +1198,8 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); -#ifdef SO_TIMESTAMP - if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) { +#if defined(SO_TIMESTAMP) && defined(SO_BINTIME) + if ((inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) != 0) { union { struct timeval tv; struct bintime bt; @@ -1206,47 +1207,66 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, } t; struct bintime boottimebin, bt1; struct timespec ts1; + int ts_clock; bool stamped; + ts_clock = inp->inp_socket->so_ts_clock; stamped = false; - switch (inp->inp_socket->so_ts_clock) { - case SO_TS_REALTIME_MICRO: + + /* + * Handle BINTIME first. We create the same output options + * for both SO_BINTIME and the case where SO_TIMESTAMP is + * set with the timestamp clock set to SO_TS_BINTIME. + */ + if ((inp->inp_socket->so_options & SO_BINTIME) != 0 || + ts_clock == SO_TS_BINTIME) { if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | M_TSTMP)) { mbuf_tstmp2timespec(m, &ts1); - timespec2bintime(&ts1, &bt1); + timespec2bintime(&ts1, &t.bt); getboottimebin(&boottimebin); - bintime_add(&bt1, &boottimebin); - bintime2timeval(&bt1, &t.tv); + bintime_add(&t.bt, &boottimebin); } else { - microtime(&t.tv); + bintime(&t.bt); } - *mp = sbcreatecontrol(&t.tv, sizeof(t.tv), - SCM_TIMESTAMP, SOL_SOCKET, M_NOWAIT); + *mp = sbcreatecontrol(&t.bt, sizeof(t.bt), SCM_BINTIME, + SOL_SOCKET, M_NOWAIT); if (*mp != NULL) { mp = &(*mp)->m_next; stamped = true; } - break; - case SO_TS_BINTIME: + /* + * Suppress other timestamps if SO_TIMESTAMP is not + * set. + */ + if ((inp->inp_socket->so_options & SO_TIMESTAMP) == 0) + ts_clock = SO_TS_BINTIME; + } + + switch (ts_clock) { + case SO_TS_REALTIME_MICRO: if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | M_TSTMP)) { mbuf_tstmp2timespec(m, &ts1); - timespec2bintime(&ts1, &t.bt); + timespec2bintime(&ts1, &bt1); getboottimebin(&boottimebin); - bintime_add(&t.bt, &boottimebin); + bintime_add(&bt1, &boottimebin); + bintime2timeval(&bt1, &t.tv); } else { - bintime(&t.bt); + microtime(&t.tv); } - *mp = sbcreatecontrol(&t.bt, sizeof(t.bt), SCM_BINTIME, - SOL_SOCKET, M_NOWAIT); + *mp = sbcreatecontrol(&t.tv, sizeof(t.tv), + SCM_TIMESTAMP, SOL_SOCKET, M_NOWAIT); if (*mp != NULL) { mp = &(*mp)->m_next; stamped = true; } break; + case SO_TS_BINTIME: + break; + case SO_TS_REALTIME: if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | M_TSTMP)) { diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 12b00d4f9934..e1a4e8678ebb 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -338,8 +338,20 @@ VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */ VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary * addresses in the source address * selection */ +VNET_DECLARE(bool, ip6_use_stableaddr); /* Whether to use stable address generation (RFC 7217) */ #define V_ip6_use_tempaddr VNET(ip6_use_tempaddr) #define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr) +#define V_ip6_use_stableaddr VNET(ip6_use_stableaddr) + +#define IP6_IDGEN_RETRIES 3 /* RFC 7217 section 7 default max retries */ +VNET_DECLARE(int, ip6_stableaddr_maxretries); +#define V_ip6_stableaddr_maxretries VNET(ip6_stableaddr_maxretries) + +#define IP6_STABLEADDR_NETIFSRC_NAME 0 +#define IP6_STABLEADDR_NETIFSRC_ID 1 +#define IP6_STABLEADDR_NETIFSRC_MAC 2 +VNET_DECLARE(int, ip6_stableaddr_netifsource); +#define V_ip6_stableaddr_netifsource VNET(ip6_stableaddr_netifsource) VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope * zone when unspecified */ diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 8480e7fc90e3..00df5efcef92 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -324,6 +324,11 @@ nd6_ifattach(struct ifnet *ifp) /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */ nd6_setmtu0(ifp, nd); + /* Configure default value for stable addresses algorithm, skip loopback interface */ + if (V_ip6_use_stableaddr && !(ifp->if_flags & IFF_LOOPBACK)) { + nd->flags |= ND6_IFF_STABLEADDR; + } + return nd; } diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 9cb2571da58b..5fe027ac5e7c 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -89,6 +89,7 @@ struct nd_ifinfo { #define ND6_IFF_NO_RADR 0x40 #define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */ #define ND6_IFF_NO_DAD 0x100 +#define ND6_IFF_STABLEADDR 0x800 #ifdef EXPERIMENTAL /* XXX: not related to ND. */ #define ND6_IFF_IPV6_ONLY 0x200 /* draft-ietf-6man-ipv6only-flag */ diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index 640348a1d198..cc17b4e1a402 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -38,6 +38,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/counter.h> #include <sys/eventhandler.h> #include <sys/malloc.h> #include <sys/libkern.h> @@ -1466,9 +1467,14 @@ nd6_dad_timer(void *arg) * No duplicate address found. Check IFDISABLED flag * again in case that it is changed between the * beginning of this function and here. + * + * Reset DAD failures counter if using stable addresses. */ - if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) + if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + if ((ND_IFINFO(ifp)->flags & ND6_IFF_STABLEADDR) && !(ia->ia6_flags & IN6_IFF_TEMPORARY)) + counter_u64_zero(DAD_FAILURES(ifp)); + } nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", @@ -1497,20 +1503,39 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp) struct ifnet *ifp; char ip6buf[INET6_ADDRSTRLEN]; + ifp = ifa->ifa_ifp; + log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: " "NS in/out/loopback=%d/%d/%d, NA in=%d\n", - if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), + if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount, dp->dad_na_icount); ia->ia6_flags &= ~IN6_IFF_TENTATIVE; ia->ia6_flags |= IN6_IFF_DUPLICATED; - ifp = ifa->ifa_ifp; log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n", if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)); - log(LOG_ERR, "%s: manual intervention required\n", - if_name(ifp)); + + /* + * For RFC 7217 stable addresses, increment failure counter here if we still have retries. + * More addresses will be generated as long as retries are not exhausted. + */ + if ((ND_IFINFO(ifp)->flags & ND6_IFF_STABLEADDR) && !(ia->ia6_flags & IN6_IFF_TEMPORARY)) { + uint64_t dad_failures = counter_u64_fetch(DAD_FAILURES(ifp)); + + if (dad_failures <= V_ip6_stableaddr_maxretries) { + counter_u64_add(DAD_FAILURES(ifp), 1); + /* if retries exhausted, output an informative error message */ + if (dad_failures == V_ip6_stableaddr_maxretries) + log(LOG_ERR, "%s: manual intervention required, consider disabling \"stableaddr\" on the interface" + " or checking hostuuid for uniqueness\n", + if_name(ifp)); + } + } else { + log(LOG_ERR, "%s: manual intervention required\n", + if_name(ifp)); + } /* * If the address is a link-local address formed from an interface diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 6fe78083df23..78dc55dd292f 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -92,6 +92,7 @@ VNET_DEFINE(int, nd6_defifindex); #define V_nd6_defifp VNET(nd6_defifp) VNET_DEFINE(int, ip6_use_tempaddr) = 0; +VNET_DEFINE(bool, ip6_use_stableaddr) = 0; VNET_DEFINE(int, ip6_desync_factor); VNET_DEFINE(uint32_t, ip6_temp_max_desync_factor) = TEMP_MAX_DESYNC_FACTOR_BASE; @@ -1184,7 +1185,7 @@ in6_ifadd(struct nd_prefixctl *pr, int mcast) struct in6_aliasreq ifra; struct in6_ifaddr *ia = NULL, *ib = NULL; int error, plen0; - struct in6_addr *ifid_addr = NULL, mask; + struct in6_addr *ifid_addr = NULL, mask, newaddr; int prefixlen = pr->ndpr_plen; int updateflags; char ip6buf[INET6_ADDRSTRLEN]; @@ -1210,61 +1211,70 @@ in6_ifadd(struct nd_prefixctl *pr, int mcast) * (4) it is easier to manage when an interface has addresses * with the same interface identifier, than to have multiple addresses * with different interface identifiers. + * + * If using stable privacy generation, generate a new address with + * the algorithm specified in RFC 7217 section 5 */ - ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */ - if (ifa) { - ib = (struct in6_ifaddr *)ifa; - ifid_addr = &ib->ia_addr.sin6_addr; - - /* prefixlen + ifidlen must be equal to 128 */ - plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL); - if (prefixlen != plen0) { - ifa_free(ifa); - ifid_addr = NULL; - nd6log((LOG_DEBUG, - "%s: wrong prefixlen for %s (prefix=%d ifid=%d)\n", - __func__, if_name(ifp), prefixlen, 128 - plen0)); - } - } - /* No suitable LL address, get the ifid directly */ - if (ifid_addr == NULL) { - struct in6_addr taddr; - ifa = ifa_alloc(sizeof(taddr), M_WAITOK); + /* make ifaddr */ + in6_prepare_ifra(&ifra, &pr->ndpr_prefix.sin6_addr, &mask); + + if (ND_IFINFO(ifp)->flags & ND6_IFF_STABLEADDR) { + memcpy(&newaddr, &pr->ndpr_prefix.sin6_addr, sizeof(pr->ndpr_prefix.sin6_addr)); + + if(!in6_get_stableifid(ifp, &newaddr, prefixlen)) + return NULL; + } else { + ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */ if (ifa) { ib = (struct in6_ifaddr *)ifa; ifid_addr = &ib->ia_addr.sin6_addr; - if(in6_get_ifid(ifp, NULL, ifid_addr) != 0) { - nd6log((LOG_DEBUG, - "%s: failed to get ifid for %s\n", - __func__, if_name(ifp))); + + /* prefixlen + ifidlen must be equal to 128 */ + plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL); + if (prefixlen != plen0) { ifa_free(ifa); ifid_addr = NULL; + nd6log((LOG_DEBUG, + "%s: wrong prefixlen for %s (prefix=%d ifid=%d)\n", + __func__, if_name(ifp), prefixlen, 128 - plen0)); } } - } - if (ifid_addr == NULL) { - nd6log((LOG_INFO, - "%s: could not determine ifid for %s\n", - __func__, if_name(ifp))); - return NULL; - } + /* No suitable LL address, get the ifid directly */ + if (ifid_addr == NULL) { + struct in6_addr taddr; + ifa = ifa_alloc(sizeof(taddr), M_WAITOK); + if (ifa) { + ib = (struct in6_ifaddr *)ifa; + ifid_addr = &ib->ia_addr.sin6_addr; + if(in6_get_ifid(ifp, NULL, ifid_addr) != 0) { + nd6log((LOG_DEBUG, + "%s: failed to get ifid for %s\n", + __func__, if_name(ifp))); + ifa_free(ifa); + ifid_addr = NULL; + } + } + } - /* make ifaddr */ - in6_prepare_ifra(&ifra, &pr->ndpr_prefix.sin6_addr, &mask); + if (ifid_addr == NULL) { + nd6log((LOG_INFO, + "%s: could not determine ifid for %s\n", + __func__, if_name(ifp))); + return NULL; + } + + memcpy(&newaddr, &ib->ia_addr.sin6_addr, sizeof(ib->ia_addr.sin6_addr)); + ifa_free(ifa); + } IN6_MASK_ADDR(&ifra.ifra_addr.sin6_addr, &mask); /* interface ID */ - ifra.ifra_addr.sin6_addr.s6_addr32[0] |= - (ifid_addr->s6_addr32[0] & ~mask.s6_addr32[0]); - ifra.ifra_addr.sin6_addr.s6_addr32[1] |= - (ifid_addr->s6_addr32[1] & ~mask.s6_addr32[1]); - ifra.ifra_addr.sin6_addr.s6_addr32[2] |= - (ifid_addr->s6_addr32[2] & ~mask.s6_addr32[2]); - ifra.ifra_addr.sin6_addr.s6_addr32[3] |= - (ifid_addr->s6_addr32[3] & ~mask.s6_addr32[3]); - ifa_free(ifa); + ifra.ifra_addr.sin6_addr.s6_addr32[0] |= (newaddr.s6_addr32[0] & ~mask.s6_addr32[0]); + ifra.ifra_addr.sin6_addr.s6_addr32[1] |= (newaddr.s6_addr32[1] & ~mask.s6_addr32[1]); + ifra.ifra_addr.sin6_addr.s6_addr32[2] |= (newaddr.s6_addr32[2] & ~mask.s6_addr32[2]); + ifra.ifra_addr.sin6_addr.s6_addr32[3] |= (newaddr.s6_addr32[3] & ~mask.s6_addr32[3]); /* lifetimes. */ ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime; @@ -1495,6 +1505,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, int auth; struct in6_addrlifetime lt6_tmp; char ip6buf[INET6_ADDRSTRLEN]; + bool has_temporary = false; NET_EPOCH_ASSERT(); @@ -1640,9 +1651,6 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, if (ifa6->ia6_ndpr != pr) continue; - if (ia6_match == NULL) /* remember the first one */ - ia6_match = ifa6; - /* * An already autoconfigured address matched. Now that we * are sure there is at least one matched address, we can @@ -1702,6 +1710,13 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0) { u_int32_t maxvltime, maxpltime; + /* + * if stable addresses (RFC 7217) are enabled, mark that a temporary address has been found + * to avoid generating uneeded extra ones. + */ + if (ND_IFINFO(ifp)->flags & ND6_IFF_STABLEADDR) + has_temporary = true; + if (V_ip6_temp_valid_lifetime > (u_int32_t)((time_uptime - ifa6->ia6_createtime) + V_ip6_desync_factor)) { @@ -1730,6 +1745,24 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, } ifa6->ia6_lifetime = lt6_tmp; ifa6->ia6_updatetime = time_uptime; + + /* + * If using stable addresses (RFC 7217) and we still have retries to perform, ignore + * addresses already marked as duplicated, since a new one will be generated. + * Also ignore addresses marked as temporary, since their generation is orthogonal to + * opaque stable ones. + * + * There is a small race condition, in that the dad_counter could be incremented + * between here and when a new address is generated, but this will cause that generation + * to fail and no further retries should happen. + */ + if (ND_IFINFO(ifp)->flags & ND6_IFF_STABLEADDR && + counter_u64_fetch(DAD_FAILURES(ifp)) <= V_ip6_stableaddr_maxretries && + ifa6->ia6_flags & (IN6_IFF_DUPLICATED | IN6_IFF_TEMPORARY)) + continue; + + if (ia6_match == NULL) /* remember the first one */ + ia6_match = ifa6; } if (ia6_match == NULL && new->ndpr_vltime) { int ifidlen; @@ -1780,8 +1813,11 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, * immediately together with a new set of temporary * addresses. Thus, we specifiy 1 as the 2nd arg of * in6_tmpifadd(). + * + * Skip this if a temporary address has been marked as + * found (happens only if stable addresses (RFC 7217) is in use) */ - if (V_ip6_use_tempaddr) { + if (V_ip6_use_tempaddr && !has_temporary) { int e; if ((e = in6_tmpifadd(ia6, 1, 1)) != 0) { nd6log((LOG_NOTICE, "%s: failed to " diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 3f810533b7fc..b59d8d08bf80 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -67,6 +67,7 @@ #include <net/route/nhop.h> #include <net/pfil.h> #include <net/vnet.h> +#include <net/if_gif.h> #include <net/if_pfsync.h> #include <netpfil/pf/pf_mtag.h> @@ -1757,6 +1758,12 @@ do { \ PULLUP_TO(hlen, ulp, struct ip); break; + case IPPROTO_ETHERIP: /* RFC 3378 */ + PULLUP_LEN(hlen, ulp, + sizeof(struct etherip_header) + + sizeof(struct ether_header)); + break; + case IPPROTO_PFSYNC: PULLUP_TO(hlen, ulp, struct pfsync_header); break; diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 5889bb9d68e6..2705df61a1f7 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -2834,7 +2834,7 @@ pf_remove_state(struct pf_kstate *s) s->key[PF_SK_WIRE]->port[0], s->src.seqhi, s->src.seqlo + 1, TH_RST|TH_ACK, 0, 0, 0, M_SKIP_FIREWALL, s->tag, 0, - s->act.rtableid); + s->act.rtableid, NULL); } LIST_REMOVE(s, entry); @@ -4080,7 +4080,7 @@ pf_build_tcp(const struct pf_krule *r, sa_family_t af, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int8_t tcp_flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int mbuf_flags, u_int16_t mtag_tag, u_int16_t mtag_flags, u_int sack, - int rtableid) + int rtableid, u_short *reason) { struct mbuf *m; int len, tlen; @@ -4120,13 +4120,16 @@ pf_build_tcp(const struct pf_krule *r, sa_family_t af, } m = m_gethdr(M_NOWAIT, MT_DATA); - if (m == NULL) + if (m == NULL) { + REASON_SET(reason, PFRES_MEMORY); return (NULL); + } #ifdef MAC mac_netinet_firewall_send(m); #endif if ((pf_mtag = pf_get_mtag(m)) == NULL) { + REASON_SET(reason, PFRES_MEMORY); m_freem(m); return (NULL); } @@ -4346,13 +4349,14 @@ pf_send_tcp(const struct pf_krule *r, sa_family_t af, const struct pf_addr *saddr, const struct pf_addr *daddr, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int8_t tcp_flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, - int mbuf_flags, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid) + int mbuf_flags, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid, + u_short *reason) { struct pf_send_entry *pfse; struct mbuf *m; m = pf_build_tcp(r, af, saddr, daddr, sport, dport, seq, ack, tcp_flags, - win, mss, ttl, mbuf_flags, mtag_tag, mtag_flags, 0, rtableid); + win, mss, ttl, mbuf_flags, mtag_tag, mtag_flags, 0, rtableid, reason); if (m == NULL) return; @@ -4360,6 +4364,7 @@ pf_send_tcp(const struct pf_krule *r, sa_family_t af, pfse = malloc(sizeof(*pfse), M_PFTEMP, M_NOWAIT); if (pfse == NULL) { m_freem(m); + REASON_SET(reason, PFRES_MEMORY); return; } @@ -4421,9 +4426,10 @@ pf_return(struct pf_krule *r, struct pf_krule *nr, struct pf_pdesc *pd, if (tcp_get_flags(th) & TH_FIN) ack++; pf_send_tcp(r, pd->af, pd->dst, - pd->src, th->th_dport, th->th_sport, - ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0, - r->return_ttl, M_SKIP_FIREWALL, 0, 0, rtableid); + pd->src, th->th_dport, th->th_sport, + ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0, + r->return_ttl, M_SKIP_FIREWALL, 0, 0, rtableid, + reason); } } else if (pd->proto == IPPROTO_SCTP && (r->rule_flag & PFRULE_RETURN)) { @@ -4474,7 +4480,8 @@ pf_icmp_to_bandlim(uint8_t type) static void pf_send_challenge_ack(struct pf_pdesc *pd, struct pf_kstate *s, - struct pf_state_peer *src, struct pf_state_peer *dst) + struct pf_state_peer *src, struct pf_state_peer *dst, + u_short *reason) { /* * We are sending challenge ACK as a response to SYN packet, which @@ -4488,7 +4495,7 @@ pf_send_challenge_ack(struct pf_pdesc *pd, struct pf_kstate *s, pf_send_tcp(s->rule, pd->af, pd->dst, pd->src, pd->hdr.tcp.th_dport, pd->hdr.tcp.th_sport, dst->seqlo, src->seqlo, TH_ACK, 0, 0, s->rule->return_ttl, 0, 0, 0, - s->rule->rtableid); + s->rule->rtableid, reason); } static void @@ -6320,7 +6327,7 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx, pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport, th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0, M_SKIP_FIREWALL, 0, 0, - pd->act.rtableid); + pd->act.rtableid, &ctx->reason); REASON_SET(&ctx->reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } @@ -6768,8 +6775,12 @@ pf_tcp_track_full(struct pf_kstate *state, struct pf_pdesc *pd, (ackskew <= (MAXACKWINDOW << sws)) && /* Acking not more than one window forward */ ((tcp_get_flags(th) & TH_RST) == 0 || orig_seq == src->seqlo || - (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo))) { + (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo) || /* Require an exact/+1 sequence match on resets when possible */ + (SEQ_GEQ(orig_seq, src->seqlo - (dst->max_win << dws)) && + SEQ_LEQ(orig_seq, src->seqlo + 1) && ackskew == 0 && + (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)))) { + /* Allow resets to match sequence window if ack is perfect match */ if (dst->scrub || src->scrub) { if (pf_normalize_tcp_stateful(pd, reason, th, @@ -6910,7 +6921,7 @@ pf_tcp_track_full(struct pf_kstate *state, struct pf_pdesc *pd, th->th_sport, ntohl(th->th_ack), 0, TH_RST, 0, 0, state->rule->return_ttl, M_SKIP_FIREWALL, - 0, 0, state->act.rtableid); + 0, 0, state->act.rtableid, reason); src->seqlo = 0; src->seqhi = 1; src->max_win = 1; @@ -7035,7 +7046,8 @@ pf_synproxy(struct pf_pdesc *pd, struct pf_kstate *state, u_short *reason) pd->src, th->th_dport, th->th_sport, state->src.seqhi, ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, state->src.mss, 0, - M_SKIP_FIREWALL, 0, 0, state->act.rtableid); + M_SKIP_FIREWALL, 0, 0, state->act.rtableid, + reason); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if ((tcp_get_flags(th) & (TH_ACK|TH_RST|TH_FIN)) != TH_ACK || @@ -7068,7 +7080,8 @@ pf_synproxy(struct pf_pdesc *pd, struct pf_kstate *state, u_short *reason) state->dst.seqhi, 0, TH_SYN, 0, state->src.mss, 0, state->orig_kif->pfik_ifp == V_loif ? M_LOOP : 0, - state->tag, 0, state->act.rtableid); + state->tag, 0, state->act.rtableid, + reason); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } else if (((tcp_get_flags(th) & (TH_SYN|TH_ACK)) != @@ -7083,13 +7096,15 @@ pf_synproxy(struct pf_pdesc *pd, struct pf_kstate *state, u_short *reason) pd->src, th->th_dport, th->th_sport, ntohl(th->th_ack), ntohl(th->th_seq) + 1, TH_ACK, state->src.max_win, 0, 0, 0, - state->tag, 0, state->act.rtableid); + state->tag, 0, state->act.rtableid, + reason); pf_send_tcp(state->rule, pd->af, &sk->addr[pd->sidx], &sk->addr[pd->didx], sk->port[pd->sidx], sk->port[pd->didx], state->src.seqhi + 1, state->src.seqlo + 1, TH_ACK, state->dst.max_win, 0, 0, - M_SKIP_FIREWALL, 0, 0, state->act.rtableid); + M_SKIP_FIREWALL, 0, 0, state->act.rtableid, + reason); state->src.seqdiff = state->dst.seqhi - state->src.seqlo; state->dst.seqdiff = state->src.seqhi - @@ -7189,7 +7204,7 @@ pf_test_state(struct pf_kstate **state, struct pf_pdesc *pd, u_short *reason) * ACK enables all parties (firewall and peers) * to get in sync again. */ - pf_send_challenge_ack(pd, *state, src, dst); + pf_send_challenge_ack(pd, *state, src, dst, reason); return (PF_DROP); } } @@ -10899,7 +10914,7 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 /* Respond to SYN with a syncookie. */ if ((tcp_get_flags(&pd.hdr.tcp) & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN && pd.dir == PF_IN && pf_synflood_check(&pd)) { - pf_syncookie_send(&pd); + pf_syncookie_send(&pd, &reason); action = PF_DROP; break; } @@ -10923,7 +10938,7 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 pd.dir == PF_IN) { struct mbuf *msyn; - msyn = pf_syncookie_recreate_syn(&pd); + msyn = pf_syncookie_recreate_syn(&pd, &reason); if (msyn == NULL) { action = PF_DROP; break; diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index 8edd5a5110a1..54ffdbed3de5 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -247,6 +247,12 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, #define SCNT_SRC_NODE_REMOVALS 2 #define SCNT_MAX 3 +/* fragment counters */ +#define NCNT_FRAG_SEARCH 0 +#define NCNT_FRAG_INSERT 1 +#define NCNT_FRAG_REMOVALS 2 +#define NCNT_MAX 3 + #define PF_TABLE_NAME_SIZE 32 #define PF_QNAME_SIZE 64 diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 06c40a03f575..bd506c092da2 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -421,6 +421,8 @@ pfattach_vnet(void) pf_counter_u64_init(&V_pf_status.fcounters[i], M_WAITOK); for (int i = 0; i < SCNT_MAX; i++) V_pf_status.scounters[i] = counter_u64_alloc(M_WAITOK); + for (int i = 0; i < NCNT_MAX; i++) + V_pf_status.ncounters[i] = counter_u64_alloc(M_WAITOK); if (swi_add(&V_pf_swi_ie, "pf send", pf_intr, curvnet, SWI_NET, INTR_MPSAFE, &V_pf_swi_cookie) != 0) @@ -2508,6 +2510,8 @@ pf_ioctl_clear_status(void) pf_counter_u64_zero(&V_pf_status.fcounters[i]); for (int i = 0; i < SCNT_MAX; i++) counter_u64_zero(V_pf_status.scounters[i]); + for (int i = 0; i < NCNT_MAX; i++) + counter_u64_zero(V_pf_status.ncounters[i]); for (int i = 0; i < KLCNT_MAX; i++) counter_u64_zero(V_pf_status.lcounters[i]); V_pf_status.since = time_uptime; @@ -6547,6 +6551,11 @@ shutdown_pf(void) pf_kill_srcnodes(NULL); + for (int i = 0; i < PF_RULESET_MAX; i++) { + pf_rule_tree_free(pf_main_ruleset.rules[i].active.tree); + pf_rule_tree_free(pf_main_ruleset.rules[i].inactive.tree); + } + /* status does not use malloced mem so no need to cleanup */ /* fingerprints and interfaces have their own cleanup code */ } while(0); @@ -6949,6 +6958,8 @@ pf_unload_vnet(void) pf_counter_u64_deinit(&V_pf_status.fcounters[i]); for (int i = 0; i < SCNT_MAX; i++) counter_u64_free(V_pf_status.scounters[i]); + for (int i = 0; i < NCNT_MAX; i++) + counter_u64_free(V_pf_status.ncounters[i]); rm_destroy(&V_pf_rules_lock); sx_destroy(&V_pf_ioctl_lock); diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index 73f018db0266..5c8f56ea4567 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -1234,6 +1234,9 @@ pf_handle_get_status(struct nlmsghdr *hdr, struct nl_pstate *npt) V_pf_status.fcounters); nlattr_add_counters(nw, PF_GS_SCOUNTERS, SCNT_MAX, pf_fcounter, V_pf_status.scounters); + nlattr_add_counters(nw, PF_GS_NCOUNTERS, NCNT_MAX, pf_fcounter, + V_pf_status.ncounters); + nlattr_add_u64(nw, PF_GS_FRAGMENTS, pf_normalize_get_frag_count()); pfi_update_status(V_pf_status.ifname, &s); nlattr_add_u64_array(nw, PF_GS_BCOUNTERS, 2 * 2, (uint64_t *)s.bcounters); diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index b60d3d4797c6..b769421bbfcc 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -352,6 +352,8 @@ enum pf_get_status_types_t { PF_GS_CHKSUM = 14, /* byte array */ PF_GS_PCOUNTERS = 15, /* u64 array */ PF_GS_BCOUNTERS = 16, /* u64 array */ + PF_GS_NCOUNTERS = 17, /* nested, */ + PF_GS_FRAGMENTS = 18, /* u64, */ }; enum pf_natlook_types_t { diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 56074bedbc40..53010222dd07 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -211,6 +211,12 @@ pf_normalize_cleanup(void) mtx_destroy(&V_pf_frag_mtx); } +uint64_t +pf_normalize_get_frag_count(void) +{ + return (uma_zone_get_cur(V_pf_frent_z)); +} + static int pf_frnode_compare(struct pf_frnode *a, struct pf_frnode *b) { @@ -314,6 +320,7 @@ pf_free_fragment(struct pf_fragment *frag) /* Free all fragment entries */ while ((frent = TAILQ_FIRST(&frag->fr_queue)) != NULL) { TAILQ_REMOVE(&frag->fr_queue, frent, fr_next); + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_REMOVALS], 1); m_freem(frent->fe_m); uma_zfree(V_pf_frent_z, frent); @@ -331,6 +338,7 @@ pf_find_fragment(struct pf_frnode *key, uint32_t id) PF_FRAG_ASSERT(); frnode = RB_FIND(pf_frnode_tree, &V_pf_frnode_tree, key); + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_SEARCH], 1); if (frnode == NULL) return (NULL); MPASS(frnode->fn_fragments >= 1); @@ -438,6 +446,7 @@ pf_frent_insert(struct pf_fragment *frag, struct pf_frent *frent, ("overlapping fragment")); TAILQ_INSERT_AFTER(&frag->fr_queue, prev, frent, fr_next); } + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_INSERT], 1); if (frag->fr_firstoff[index] == NULL) { KASSERT(prev == NULL || pf_frent_index(prev) < index, @@ -496,6 +505,7 @@ pf_frent_remove(struct pf_fragment *frag, struct pf_frent *frent) } TAILQ_REMOVE(&frag->fr_queue, frent, fr_next); + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_REMOVALS], 1); KASSERT(frag->fr_entries[index] > 0, ("No fragments remaining")); frag->fr_entries[index]--; @@ -768,6 +778,7 @@ pf_join_fragment(struct pf_fragment *frag) frent = TAILQ_FIRST(&frag->fr_queue); TAILQ_REMOVE(&frag->fr_queue, frent, fr_next); + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_REMOVALS], 1); m = frent->fe_m; if ((frent->fe_hdrlen + frent->fe_len) < m->m_pkthdr.len) @@ -775,6 +786,7 @@ pf_join_fragment(struct pf_fragment *frag) uma_zfree(V_pf_frent_z, frent); while ((frent = TAILQ_FIRST(&frag->fr_queue)) != NULL) { TAILQ_REMOVE(&frag->fr_queue, frent, fr_next); + counter_u64_add(V_pf_status.ncounters[NCNT_FRAG_REMOVALS], 1); m2 = frent->fe_m; /* Strip off ip header. */ diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c index 1711e690f6bb..4e16eaa76f9d 100644 --- a/sys/netpfil/pf/pf_ruleset.c +++ b/sys/netpfil/pf/pf_ruleset.c @@ -336,12 +336,6 @@ pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset) int i; while (ruleset != NULL) { - for (int i = 0; i < PF_RULESET_MAX; i++) { - pf_rule_tree_free(ruleset->rules[i].active.tree); - ruleset->rules[i].active.tree = NULL; - pf_rule_tree_free(ruleset->rules[i].inactive.tree); - ruleset->rules[i].inactive.tree = NULL; - } if (ruleset == &pf_main_ruleset || !RB_EMPTY(&ruleset->anchor->children) || ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || @@ -352,6 +346,12 @@ pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset) !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || ruleset->rules[i].inactive.open) return; + for (int i = 0; i < PF_RULESET_MAX; i++) { + pf_rule_tree_free(ruleset->rules[i].active.tree); + ruleset->rules[i].active.tree = NULL; + pf_rule_tree_free(ruleset->rules[i].inactive.tree); + ruleset->rules[i].inactive.tree = NULL; + } RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor); if ((parent = ruleset->anchor->parent) != NULL) RB_REMOVE(pf_kanchor_node, &parent->children, diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c index 4a935bc65767..d11551ffb6ae 100644 --- a/sys/netpfil/pf/pf_syncookies.c +++ b/sys/netpfil/pf/pf_syncookies.c @@ -287,7 +287,7 @@ pf_synflood_check(struct pf_pdesc *pd) } void -pf_syncookie_send(struct pf_pdesc *pd) +pf_syncookie_send(struct pf_pdesc *pd, u_short *reason) { uint16_t mss; uint32_t iss; @@ -297,7 +297,7 @@ pf_syncookie_send(struct pf_pdesc *pd) pf_send_tcp(NULL, pd->af, pd->dst, pd->src, *pd->dport, *pd->sport, iss, ntohl(pd->hdr.tcp.th_seq) + 1, TH_SYN|TH_ACK, 0, mss, 0, M_SKIP_FIREWALL | (pd->m->m_flags & M_LOOP), 0, 0, - pd->act.rtableid); + pd->act.rtableid, reason); counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_SENT], 1); /* XXX Maybe only in adaptive mode? */ atomic_add_64(&V_pf_status.syncookies_inflight[V_pf_syncookie_status.oddeven], @@ -495,7 +495,7 @@ pf_syncookie_generate(struct pf_pdesc *pd, uint16_t mss) } struct mbuf * -pf_syncookie_recreate_syn(struct pf_pdesc *pd) +pf_syncookie_recreate_syn(struct pf_pdesc *pd, u_short *reason) { uint8_t wscale; uint16_t mss; @@ -516,5 +516,5 @@ pf_syncookie_recreate_syn(struct pf_pdesc *pd) return (pf_build_tcp(NULL, pd->af, pd->src, pd->dst, *pd->sport, *pd->dport, seq, 0, TH_SYN, wscale, mss, pd->ttl, (pd->m->m_flags & M_LOOP), 0, PF_MTAG_FLAG_SYNCOOKIE_RECREATED, - cookie.flags.sack_ok, pd->act.rtableid)); + cookie.flags.sack_ok, pd->act.rtableid, reason)); } diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h index 015a283e2de7..b2d7549e5bd0 100644 --- a/sys/powerpc/include/atomic.h +++ b/sys/powerpc/include/atomic.h @@ -1137,7 +1137,38 @@ atomic_thread_fence_seq_cst(void) #define atomic_cmpset_short atomic_cmpset_16 #define atomic_fcmpset_char atomic_fcmpset_8 #define atomic_fcmpset_short atomic_fcmpset_16 -#endif +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 +#else + +static __inline void +atomic_set_short(volatile u_short *p, u_short bit) +{ + u_short v; + + v = atomic_load_short(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v | bit)) + break; + } +} + +static __inline void +atomic_clear_short(volatile u_short *p, u_short bit) +{ + u_short v; + + v = atomic_load_short(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v & ~bit)) + break; + } +} + +#define atomic_set_16 atomic_set_short +#define atomic_clear_16 atomic_clear_short + +#endif /* ISA_206_ATOMICS */ /* These need sys/_atomic_subword.h on non-ISA-2.06-atomic platforms. */ ATOMIC_CMPSET_ACQ_REL(char); diff --git a/sys/riscv/include/atomic.h b/sys/riscv/include/atomic.h index 74ffc171b028..c90cb02c482c 100644 --- a/sys/riscv/include/atomic.h +++ b/sys/riscv/include/atomic.h @@ -656,4 +656,7 @@ atomic_thread_fence_seq_cst(void) #include <sys/_atomic_subword.h> +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 + #endif /* _MACHINE_ATOMIC_H_ */ diff --git a/sys/riscv/include/ieeefp.h b/sys/riscv/include/ieeefp.h index 03a96e8a000f..84b554a04c65 100644 --- a/sys/riscv/include/ieeefp.h +++ b/sys/riscv/include/ieeefp.h @@ -5,4 +5,9 @@ /* TODO */ typedef int fp_except_t; +__BEGIN_DECLS +extern fp_except_t fpgetmask(void); +extern fp_except_t fpsetmask(fp_except_t); +__END_DECLS + #endif /* _MACHINE_IEEEFP_H_ */ diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c index 40b2fb3d1c9f..f50c627b7515 100644 --- a/sys/security/audit/audit_syscalls.c +++ b/sys/security/audit/audit_syscalls.c @@ -54,6 +54,29 @@ #ifdef AUDIT +static int +audit_priv_check_cred(struct ucred *cred, int priv) +{ + int error; + + error = priv_check_cred(cred, priv); + if (error == EPERM && jailed(cred)) { + /* + * The audit system calls historically returned ENOSYS when + * invoked from within a jail, and some userspace applications + * handle that case specially. Thus, convert the error here. + */ + error = ENOSYS; + } + return (error); +} + +static int +audit_priv_check(struct thread *td, int priv) +{ + return (audit_priv_check_cred(td->td_ucred, priv)); +} + /* * System call to allow a user space application to submit a BSM audit record * to the kernel for inclusion in the audit log. This function does little @@ -592,9 +615,7 @@ sys_getauid(struct thread *td, struct getauid_args *uap) { int error; - if (jailed(td->td_ucred)) - return (ENOSYS); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid, @@ -609,8 +630,6 @@ sys_setauid(struct thread *td, struct setauid_args *uap) au_id_t id; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auid, &id, sizeof(id)); if (error) return (error); @@ -624,7 +643,7 @@ sys_setauid(struct thread *td, struct setauid_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; newcred->cr_audit.ai_auid = id; @@ -650,9 +669,7 @@ sys_getaudit(struct thread *td, struct getaudit_args *uap) int error; cred = td->td_ucred; - if (jailed(cred)) - return (ENOSYS); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); if (cred->cr_audit.ai_termid.at_type == AU_IPv6) @@ -674,8 +691,6 @@ sys_setaudit(struct thread *td, struct setaudit_args *uap) struct auditinfo ai; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auditinfo, &ai, sizeof(ai)); if (error) return (error); @@ -689,7 +704,7 @@ sys_setaudit(struct thread *td, struct setaudit_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; bzero(&newcred->cr_audit, sizeof(newcred->cr_audit)); @@ -715,11 +730,9 @@ sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) { int error; - if (jailed(td->td_ucred)) - return (ENOSYS); if (uap->length < sizeof(*uap->auditinfo_addr)) return (EOVERFLOW); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr, @@ -734,8 +747,6 @@ sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) struct auditinfo_addr aia; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auditinfo_addr, &aia, sizeof(aia)); if (error) return (error); @@ -752,7 +763,7 @@ sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; newcred->cr_audit = aia; diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c index 8a6549214380..bf95c008e2f2 100644 --- a/sys/security/mac_bsdextended/mac_bsdextended.c +++ b/sys/security/mac_bsdextended/mac_bsdextended.c @@ -246,7 +246,9 @@ ugidfw_rulecheck(struct mac_bsdextended_rule *rule, } if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { - match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && + match = ((cred->cr_gid <= rule->mbr_subject.mbs_gid_max && + cred->cr_gid >= rule->mbr_subject.mbs_gid_min) || + (cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c index 7a5ac2e01f75..6f3e63d06198 100644 --- a/sys/security/mac_do/mac_do.c +++ b/sys/security/mac_do/mac_do.c @@ -1650,7 +1650,7 @@ rule_grant_supplementary_groups(const struct rule *const rule, const bool current_has_supp = (gid_flags & MDF_CURRENT) != 0 && (gid_flags & MDF_SUPP_MASK) != 0; id_nb_t rule_idx = 0; - int old_idx = 1, new_idx = 1; + int old_idx = 0, new_idx = 0; if ((gid_flags & MDF_ANY_SUPP) != 0 && (gid_flags & MDF_MAY_REJ_SUPP) == 0) diff --git a/sys/sys/_atomic_subword.h b/sys/sys/_atomic_subword.h index dee5a3bed871..284e2bfa340f 100644 --- a/sys/sys/_atomic_subword.h +++ b/sys/sys/_atomic_subword.h @@ -205,4 +205,32 @@ atomic_load_acq_16(const volatile uint16_t *p) #undef _ATOMIC_BYTE_SHIFT #undef _ATOMIC_HWORD_SHIFT +#ifndef atomic_set_16 +static __inline void +atomic_set_16(volatile uint16_t *p, uint16_t bit) +{ + uint16_t v; + + v = atomic_load_16(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v | bit)) + break; + } +} +#endif + +#ifndef atomic_clear_16 +static __inline void +atomic_clear_16(volatile uint16_t *p, uint16_t bit) +{ + uint16_t v; + + v = atomic_load_16(p); + for (;;) { + if (atomic_fcmpset_16(p, &v, v & ~bit)) + break; + } +} +#endif + #endif /* _SYS__ATOMIC_SUBWORD_H_ */ diff --git a/sys/sys/file.h b/sys/sys/file.h index cc3c733580fd..c44fd0f28929 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -93,6 +93,8 @@ void foffset_lock_pair(struct file *fp1, off_t *off1p, struct file *fp2, void foffset_lock_uio(struct file *fp, struct uio *uio, int flags); void foffset_unlock(struct file *fp, off_t val, int flags); void foffset_unlock_uio(struct file *fp, struct uio *uio, int flags); +void fsetfl_lock(struct file *fp); +void fsetfl_unlock(struct file *fp); static inline off_t foffset_get(struct file *fp) @@ -197,7 +199,7 @@ struct file { struct vnode *f_vnode; /* NULL or applicable vnode */ struct ucred *f_cred; /* associated credentials. */ short f_type; /* descriptor type */ - short f_vnread_flags; /* (f) Sleep lock for f_offset */ + short f_vflags; /* (f) Sleep lock flags for members */ /* * DTYPE_VNODE specific fields. */ @@ -220,8 +222,10 @@ struct file { #define f_cdevpriv f_vnun.fvn_cdevpriv #define f_advice f_vnun.fvn_advice -#define FOFFSET_LOCKED 0x1 -#define FOFFSET_LOCK_WAITING 0x2 +#define FILE_V_FOFFSET_LOCKED 0x0001 +#define FILE_V_FOFFSET_LOCK_WAITING 0x0002 +#define FILE_V_SETFL_LOCKED 0x0004 +#define FILE_V_SETFL_LOCK_WAITING 0x0008 #endif /* __BSD_VISIBLE */ #endif /* _KERNEL || _WANT_FILE */ diff --git a/sys/sys/jail.h b/sys/sys/jail.h index e12e8c3178c9..e6a13e6719dd 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -271,6 +271,7 @@ struct prison_racct { #define PR_ALLOW_SETTIME 0x00100000 #define PR_ALLOW_ROUTING 0x00200000 #define PR_ALLOW_UNPRIV_PARENT_TAMPER 0x00400000 +#define PR_ALLOW_SETAUDIT 0x00800000 /* * PR_ALLOW_PRISON0 are the allow flags that we apply by default to prison0, @@ -278,7 +279,7 @@ struct prison_racct { * build time. PR_ALLOW_ALL_STATIC should contain any bit above that we expect * to be used on the system, while PR_ALLOW_PRISON0 will be some subset of that. */ -#define PR_ALLOW_ALL_STATIC 0x007f87ff +#define PR_ALLOW_ALL_STATIC 0x00ff87ff #define PR_ALLOW_PRISON0 \ (PR_ALLOW_ALL_STATIC & ~(PR_ALLOW_UNPRIV_PARENT_TAMPER)) diff --git a/sys/sys/power.h b/sys/sys/power.h index 3ee021b0e587..44d7fc354423 100644 --- a/sys/sys/power.h +++ b/sys/sys/power.h @@ -3,6 +3,10 @@ * * Copyright (c) 2001 Mitsuru IWASAKI * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +35,7 @@ #ifdef _KERNEL #include <sys/_eventhandler.h> +#include <sys/types.h> /* Power management system type */ #define POWER_PM_TYPE_ACPI 0x01 @@ -39,13 +44,54 @@ /* Commands for Power management function */ #define POWER_CMD_SUSPEND 0x00 -/* Sleep state */ +/* + * Sleep state. + * + * These are high-level sleep states that the system can enter. They map to + * a specific generic sleep type (enum power_stype). + */ #define POWER_SLEEP_STATE_STANDBY 0x00 #define POWER_SLEEP_STATE_SUSPEND 0x01 #define POWER_SLEEP_STATE_HIBERNATE 0x02 -typedef int (*power_pm_fn_t)(u_long, void*, ...); -extern int power_pm_register(u_int, power_pm_fn_t, void *); +/* + * Sleep type. + * + * These are the specific generic methods of entering a sleep state. E.g. + * POWER_SLEEP_STATE_SUSPEND could be set to enter either suspend-to-RAM (which + * is S3 on ACPI systems), or suspend-to-idle (S0ix on ACPI systems). This + * would be done through the kern.power.suspend sysctl. + */ +enum power_stype { + POWER_STYPE_AWAKE, + POWER_STYPE_STANDBY, + POWER_STYPE_SUSPEND_TO_MEM, + POWER_STYPE_SUSPEND_TO_IDLE, + POWER_STYPE_HIBERNATE, + POWER_STYPE_POWEROFF, + POWER_STYPE_COUNT, + POWER_STYPE_UNKNOWN, +}; + +static const char * const power_stype_names[POWER_STYPE_COUNT] = { + [POWER_STYPE_AWAKE] = "awake", + [POWER_STYPE_STANDBY] = "standby", + [POWER_STYPE_SUSPEND_TO_MEM] = "s2mem", + [POWER_STYPE_SUSPEND_TO_IDLE] = "s2idle", + [POWER_STYPE_HIBERNATE] = "hibernate", + [POWER_STYPE_POWEROFF] = "poweroff", +}; + +extern enum power_stype power_standby_stype; +extern enum power_stype power_suspend_stype; +extern enum power_stype power_hibernate_stype; + +extern enum power_stype power_name_to_stype(const char *_name); +extern const char *power_stype_to_name(enum power_stype _stype); + +typedef int (*power_pm_fn_t)(u_long _cmd, void* _arg, enum power_stype _stype); +extern int power_pm_register(u_int _pm_type, power_pm_fn_t _pm_fn, + void *_pm_arg); extern u_int power_pm_get_type(void); extern void power_pm_suspend(int); diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 9c1d8545af34..254f58841993 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -112,15 +112,21 @@ struct xucred { short cr_ngroups; /* number of groups (incl. cr_gid). */ union { /* - * Special little hack to avoid needing a cr_gid macro, which - * would cause problems if one were to use it with struct ucred - * which also has a cr_groups member. + * The effective GID has been the first element of cr_groups[] + * for historical reasons. It should be accessed using the + * 'cr_gid' identifier. Supplementary groups should be accessed + * using cr_sgroups[]. Note that 'cr_ngroups' currently + * includes the effective GID. + * + * XXXOC: On the next API change (requires versioning), please + * replace this union with a true unaliased field 'cr_gid' and + * make sure that cr_groups[]/'cr_ngroups' only account for + * supplementary groups. */ struct { gid_t cr_gid; /* effective group id */ gid_t cr_sgroups[XU_NGROUPS - 1]; }; - gid_t cr_groups[XU_NGROUPS]; /* groups */ }; union { diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 58f8ac16fa0c..2e150b368d71 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -71,11 +71,9 @@ * Page fault handling module. */ -#include <sys/cdefs.h> #include "opt_ktrace.h" #include "opt_vm.h" -#include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/lock.h> @@ -204,7 +202,10 @@ vm_fault_page_release(vm_page_t *mp) * pageout while optimizing fault restarts. */ vm_page_deactivate(m); - vm_page_xunbusy(m); + if (vm_page_xbusied(m)) + vm_page_xunbusy(m); + else + vm_page_sunbusy(m); *mp = NULL; } } @@ -260,6 +261,12 @@ vm_fault_unlock_vp(struct faultstate *fs) } } +static bool +vm_fault_might_be_cow(struct faultstate *fs) +{ + return (fs->object != fs->first_object); +} + static void vm_fault_deallocate(struct faultstate *fs) { @@ -267,7 +274,7 @@ vm_fault_deallocate(struct faultstate *fs) vm_fault_page_release(&fs->m_cow); vm_fault_page_release(&fs->m); vm_object_pip_wakeup(fs->object); - if (fs->object != fs->first_object) { + if (vm_fault_might_be_cow(fs)) { VM_OBJECT_WLOCK(fs->first_object); vm_fault_page_free(&fs->first_m); VM_OBJECT_WUNLOCK(fs->first_object); @@ -329,6 +336,13 @@ vm_fault_dirty(struct faultstate *fs, vm_page_t m) } +static bool +vm_fault_is_read(const struct faultstate *fs) +{ + return ((fs->prot & VM_PROT_WRITE) == 0 && + (fs->fault_type & (VM_PROT_COPY | VM_PROT_WRITE)) == 0); +} + /* * Unlocks fs.first_object and fs.map on success. */ @@ -694,21 +708,18 @@ _Static_assert(UCODE_PAGEFLT == T_PAGEFLT, "T_PAGEFLT"); #endif /* - * vm_fault_trap: - * - * Handle a page fault occurring at the given address, - * requiring the given permissions, in the map specified. - * If successful, the page is inserted into the - * associated physical map. + * vm_fault_trap: * - * NOTE: the given address should be truncated to the - * proper page address. + * Helper for the page fault trap handlers, wrapping vm_fault(). + * Issues ktrace(2) tracepoints for the faults. * - * KERN_SUCCESS is returned if the page fault is handled; otherwise, - * a standard error specifying why the fault is fatal is returned. + * If a fault cannot be handled successfully by satisfying the + * required mapping, and the faulted instruction cannot be restarted, + * the signal number and si_code values are returned for trapsignal() + * to deliver. * - * The map in question must be referenced, and remains so. - * Caller may hold no locks. + * Returns Mach error codes, but callers should only check for + * KERN_SUCCESS. */ int vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, @@ -1002,12 +1013,22 @@ vm_fault_relookup(struct faultstate *fs) return (KERN_SUCCESS); } +static bool +vm_fault_can_cow_rename(struct faultstate *fs) +{ + return ( + /* Only one shadow object and no other refs. */ + fs->object->shadow_count == 1 && fs->object->ref_count == 1 && + /* No other ways to look the object up. */ + fs->object->handle == NULL && (fs->object->flags & OBJ_ANON) != 0); +} + static void vm_fault_cow(struct faultstate *fs) { - bool is_first_object_locked; + bool is_first_object_locked, rename_cow; - KASSERT(fs->object != fs->first_object, + KASSERT(vm_fault_might_be_cow(fs), ("source and target COW objects are identical")); /* @@ -1019,21 +1040,29 @@ vm_fault_cow(struct faultstate *fs) * object so that it will go out to swap when needed. */ is_first_object_locked = false; - if ( - /* - * Only one shadow object and no other refs. - */ - fs->object->shadow_count == 1 && fs->object->ref_count == 1 && - /* - * No other ways to look the object up - */ - fs->object->handle == NULL && (fs->object->flags & OBJ_ANON) != 0 && - /* - * We don't chase down the shadow chain and we can acquire locks. - */ - (is_first_object_locked = VM_OBJECT_TRYWLOCK(fs->first_object)) && - fs->object == fs->first_object->backing_object && - VM_OBJECT_TRYWLOCK(fs->object)) { + rename_cow = false; + + if (vm_fault_can_cow_rename(fs) && vm_page_xbusied(fs->m)) { + /* + * Check that we don't chase down the shadow chain and + * we can acquire locks. Recheck the conditions for + * rename after the shadow chain is stable after the + * object locking. + */ + is_first_object_locked = VM_OBJECT_TRYWLOCK(fs->first_object); + if (is_first_object_locked && + fs->object == fs->first_object->backing_object) { + if (VM_OBJECT_TRYWLOCK(fs->object)) { + rename_cow = vm_fault_can_cow_rename(fs); + if (!rename_cow) + VM_OBJECT_WUNLOCK(fs->object); + } + } + } + + if (rename_cow) { + vm_page_assert_xbusied(fs->m); + /* * Remove but keep xbusy for replace. fs->m is moved into * fs->first_object and left busy while fs->first_m is @@ -1090,8 +1119,12 @@ vm_fault_cow(struct faultstate *fs) * address space. If OBJ_ONEMAPPING is set after the check, * removing mappings will at worse trigger some unnecessary page * faults. + * + * In the fs->m shared busy case, the xbusy state of + * fs->first_m prevents new mappings of fs->m from + * being created because a parallel fault on this + * shadow chain should wait for xbusy on fs->first_m. */ - vm_page_assert_xbusied(fs->m_cow); if ((fs->first_object->flags & OBJ_ONEMAPPING) == 0) pmap_remove_all(fs->m_cow); } @@ -1171,7 +1204,7 @@ vm_fault_zerofill(struct faultstate *fs) * If there's no object left, fill the page in the top * object with zeros. */ - if (fs->object != fs->first_object) { + if (vm_fault_might_be_cow(fs)) { vm_object_pip_wakeup(fs->object); fs->object = fs->first_object; fs->pindex = fs->first_pindex; @@ -1420,14 +1453,13 @@ vm_fault_getpages(struct faultstate *fs, int *behindp, int *aheadp) * and we could end up trying to pagein and pageout the same page * simultaneously. * - * We can theoretically allow the busy case on a read fault if the page - * is marked valid, but since such pages are typically already pmap'd, - * putting that special case in might be more effort then it is worth. - * We cannot under any circumstances mess around with a shared busied - * page except, perhaps, to pmap it. + * We allow the busy case on a read fault if the page is valid. We + * cannot under any circumstances mess around with a shared busied + * page except, perhaps, to pmap it. This is controlled by the + * VM_ALLOC_SBUSY bit in the allocflags argument. */ static void -vm_fault_busy_sleep(struct faultstate *fs) +vm_fault_busy_sleep(struct faultstate *fs, int allocflags) { /* * Reference the page before unlocking and @@ -1435,13 +1467,13 @@ vm_fault_busy_sleep(struct faultstate *fs) * likely to reclaim it. */ vm_page_aflag_set(fs->m, PGA_REFERENCED); - if (fs->object != fs->first_object) { + if (vm_fault_might_be_cow(fs)) { vm_fault_page_release(&fs->first_m); vm_object_pip_wakeup(fs->first_object); } vm_object_pip_wakeup(fs->object); vm_fault_unlock_map(fs); - if (!vm_page_busy_sleep(fs->m, "vmpfw", 0)) + if (!vm_page_busy_sleep(fs->m, "vmpfw", allocflags)) VM_OBJECT_UNLOCK(fs->object); VM_CNT_INC(v_intrans); vm_object_deallocate(fs->first_object); @@ -1487,8 +1519,53 @@ vm_fault_object(struct faultstate *fs, int *behindp, int *aheadp) vm_page_iter_init(&pages, fs->object); fs->m = vm_radix_iter_lookup(&pages, fs->pindex); if (fs->m != NULL) { + /* + * If the found page is valid, will be either shadowed + * or mapped read-only, and will not be renamed for + * COW, then busy it in shared mode. This allows + * other faults needing this page to proceed in + * parallel. + * + * Unlocked check for validity, rechecked after busy + * is obtained. + */ + if (vm_page_all_valid(fs->m) && + /* + * No write permissions for the new fs->m mapping, + * or the first object has only one mapping, so + * other writeable COW mappings of fs->m cannot + * appear under us. + */ + (vm_fault_is_read(fs) || vm_fault_might_be_cow(fs)) && + /* + * fs->m cannot be renamed from object to + * first_object. These conditions will be + * re-checked with proper synchronization in + * vm_fault_cow(). + */ + (!vm_fault_can_cow_rename(fs) || + fs->object != fs->first_object->backing_object)) { + if (!vm_page_trysbusy(fs->m)) { + vm_fault_busy_sleep(fs, VM_ALLOC_SBUSY); + return (FAULT_RESTART); + } + + /* + * Now make sure that racily checked + * conditions are still valid. + */ + if (__predict_true(vm_page_all_valid(fs->m) && + (vm_fault_is_read(fs) || + vm_fault_might_be_cow(fs)))) { + VM_OBJECT_UNLOCK(fs->object); + return (FAULT_SOFT); + } + + vm_page_sunbusy(fs->m); + } + if (!vm_page_tryxbusy(fs->m)) { - vm_fault_busy_sleep(fs); + vm_fault_busy_sleep(fs, 0); return (FAULT_RESTART); } @@ -1546,6 +1623,27 @@ vm_fault_object(struct faultstate *fs, int *behindp, int *aheadp) return (res); } +/* + * vm_fault: + * + * Handle a page fault occurring at the given address, requiring the + * given permissions, in the map specified. If successful, the page + * is inserted into the associated physical map, and optionally + * referenced and returned in *m_hold. + * + * The given address should be truncated to the proper page address. + * + * KERN_SUCCESS is returned if the page fault is handled; otherwise, a + * Mach error specifying why the fault is fatal is returned. + * + * The map in question must be alive, either being the map for current + * process, or the owner process hold count incremented to prevent + * exit(). + * + * If the thread private TDP_NOFAULTING flag is set, any fault results + * in immediate protection failure. Otherwise the fault is processed, + * and caller may hold no locks. + */ int vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags, vm_page_t *m_hold) @@ -1701,10 +1799,15 @@ RetryFault: found: /* - * A valid page has been found and exclusively busied. The - * object lock must no longer be held. + * A valid page has been found and busied. The object lock + * must no longer be held if the page was busied. + * + * Regardless of the busy state of fs.m, fs.first_m is always + * exclusively busied after the first iteration of the loop + * calling vm_fault_object(). This is an ordering point for + * the parallel faults occuring in on the same page. */ - vm_page_assert_xbusied(fs.m); + vm_page_assert_busied(fs.m); VM_OBJECT_ASSERT_UNLOCKED(fs.object); /* @@ -1712,7 +1815,7 @@ found: * top-level object, we have to copy it into a new page owned by the * top-level object. */ - if (fs.object != fs.first_object) { + if (vm_fault_might_be_cow(&fs)) { /* * We only really need to copy if we want to write it. */ @@ -1773,7 +1876,7 @@ found: * Page must be completely valid or it is not fit to * map into user space. vm_pager_get_pages() ensures this. */ - vm_page_assert_xbusied(fs.m); + vm_page_assert_busied(fs.m); KASSERT(vm_page_all_valid(fs.m), ("vm_fault: page %p partially invalid", fs.m)); @@ -1805,7 +1908,13 @@ found: (*fs.m_hold) = fs.m; vm_page_wire(fs.m); } - vm_page_xunbusy(fs.m); + + KASSERT(fs.first_object == fs.object || vm_page_xbusied(fs.first_m), + ("first_m must be xbusy")); + if (vm_page_xbusied(fs.m)) + vm_page_xunbusy(fs.m); + else + vm_page_sunbusy(fs.m); fs.m = NULL; /* diff --git a/sys/x86/include/ucode.h b/sys/x86/include/ucode.h index 0338d48a0832..75b9ff3afbd0 100644 --- a/sys/x86/include/ucode.h +++ b/sys/x86/include/ucode.h @@ -63,7 +63,7 @@ struct ucode_intel_extsig_table { }; const void *ucode_amd_find(const char *path, uint32_t signature, - uint32_t revision, const uint8_t *fw_data, size_t fw_size, + uint32_t *revision, const uint8_t *fw_data, size_t fw_size, size_t *selected_sizep); int ucode_intel_load(const void *data, bool unsafe, uint64_t *nrevp, uint64_t *orevp); diff --git a/sys/x86/x86/ucode.c b/sys/x86/x86/ucode.c index 0c153c0b656c..1973047fafd1 100644 --- a/sys/x86/x86/ucode.c +++ b/sys/x86/x86/ucode.c @@ -277,7 +277,8 @@ ucode_amd_match(const uint8_t *data, size_t *len) signature = regs[0]; revision = rdmsr(MSR_BIOS_SIGN); - return (ucode_amd_find("loader blob", signature, revision, data, *len, len)); + return (ucode_amd_find("loader blob", signature, &revision, data, *len, + len)); } /* diff --git a/sys/x86/x86/ucode_subr.c b/sys/x86/x86/ucode_subr.c index 9e128ad2bf04..53d7cfc06769 100644 --- a/sys/x86/x86/ucode_subr.c +++ b/sys/x86/x86/ucode_subr.c @@ -94,7 +94,7 @@ typedef struct container_header { * source code. */ const void * -ucode_amd_find(const char *path, uint32_t signature, uint32_t revision, +ucode_amd_find(const char *path, uint32_t signature, uint32_t *revision, const uint8_t *fw_data, size_t fw_size, size_t *selected_sizep) { const amd_10h_fw_header_t *fw_header; @@ -112,7 +112,7 @@ ucode_amd_find(const char *path, uint32_t signature, uint32_t revision, (signature >> 4) & 0x0f, (signature >> 0) & 0x0f, (signature >> 20) & 0xff, (signature >> 16) & 0x0f); - WARNX(1, "microcode revision %#x", revision); + WARNX(1, "microcode revision %#x", *revision); nextfile: WARNX(1, "checking %s for update.", path); @@ -212,9 +212,9 @@ nextfile: fw_header->processor_rev_id, equiv_id); continue; /* different cpu */ } - if (fw_header->patch_id <= revision) { + if (fw_header->patch_id <= *revision) { WARNX(1, "patch_id %x, revision %x", - fw_header->patch_id, revision); + fw_header->patch_id, *revision); continue; /* not newer revision */ } if (fw_header->nb_dev_id != 0 || fw_header->sb_dev_id != 0) { @@ -222,7 +222,7 @@ nextfile: } WARNX(3, "selecting revision: %x", fw_header->patch_id); - revision = fw_header->patch_id; + *revision = fw_header->patch_id; selected_fw = fw_header; selected_size = section_header->size; } diff --git a/tests/atf_python/atf_pytest.py b/tests/atf_python/atf_pytest.py index 19b5f88fa200..02ed502ace67 100644 --- a/tests/atf_python/atf_pytest.py +++ b/tests/atf_python/atf_pytest.py @@ -256,7 +256,7 @@ class ATFHandler(object): # Record failure & override "skipped" state self.set_report_state(test_name, state, reason) elif state == "skipped": - if hasattr(reason, "wasxfail"): + if hasattr(report, "wasxfail"): # xfail() called in the test body state = "expected_failure" else: @@ -264,7 +264,7 @@ class ATFHandler(object): pass self.set_report_state(test_name, state, reason) elif state == "passed": - if hasattr(reason, "wasxfail"): + if hasattr(report, "wasxfail"): # the test was expected to fail but didn't # mark as hard failure state = "failed" diff --git a/tests/sys/fs/fusefs/last_local_modify.cc b/tests/sys/fs/fusefs/last_local_modify.cc index 5fcd3c36c892..6b8c19f1efc7 100644 --- a/tests/sys/fs/fusefs/last_local_modify.cc +++ b/tests/sys/fs/fusefs/last_local_modify.cc @@ -174,7 +174,15 @@ static void* write_th(void* arg) { if (sem) sem_wait(sem); - fd = open("mountpoint/some_file.txt", O_RDWR); + /* + * Open the file in direct mode. + * The race condition affects both direct and non-direct writes, and + * they have separate code paths. However, in the non-direct case, the + * kernel updates last_local_modify _before_ sending FUSE_WRITE to the + * server. So the technique that this test program uses to invoke the + * race cannot work. Therefore, test with O_DIRECT only. + */ + fd = open("mountpoint/some_file.txt", O_RDWR | O_DIRECT); if (fd < 0) return (void*)(intptr_t)errno; @@ -332,7 +340,7 @@ TEST_P(LastLocalModify, lookup) /* Wait for FUSE_SETATTR to be sent */ sem_wait(&sem); - /* Lookup again, which will race with setattr */ + /* Lookup again, which will race with the mutator */ ASSERT_EQ(0, stat(FULLPATH, &sb)) << strerror(errno); ASSERT_EQ((off_t)newsize, sb.st_size); diff --git a/tests/sys/fs/fusefs/release.cc b/tests/sys/fs/fusefs/release.cc index b664ba512b64..9df236bfbaf7 100644 --- a/tests/sys/fs/fusefs/release.cc +++ b/tests/sys/fs/fusefs/release.cc @@ -29,6 +29,9 @@ */ extern "C" { +#include <sys/socket.h> +#include <sys/un.h> + #include <fcntl.h> #include <unistd.h> } @@ -188,6 +191,57 @@ TEST_F(Release, ok) ASSERT_EQ(0, close(fd)) << strerror(errno); } +/* + * Nothing bad should happen when closing a Unix-domain named socket that + * contains a fusefs file descriptor within its receive buffer. + * Regression test for + * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289686 + */ +TEST_F(Release, scm_rights) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + struct msghdr msg; + struct iovec iov; + char message[CMSG_SPACE(sizeof(int))]; + uint64_t ino = 42; + int fd; + int s[2]; + union { + char buf[CMSG_SPACE(sizeof(fd))]; + struct cmsghdr align; + } u; + + expect_lookup(RELPATH, ino, 1); + expect_open(ino, 0, 1); + expect_flush(ino, 1, ReturnErrno(0)); + expect_release(ino, getpid(), O_RDONLY, 0); + + ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, s)) << strerror(errno); + + fd = open(FULLPATH, O_RDONLY); + ASSERT_LE(0, fd) << strerror(errno); + + memset(&message, 0, sizeof(message)); + memset(&msg, 0, sizeof(msg)); + iov.iov_base = NULL; + iov.iov_len = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = u.buf, + msg.msg_controllen = sizeof(u.buf); + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + ASSERT_GE(sendmsg(s[0], &msg, 0), 0) << strerror(errno); + + close(fd); // Close fd within our process + close(s[0]); + close(s[1]); // The last copy of fd is within this socket's rcvbuf +} + /* When closing a file with a POSIX file lock, release should release the lock*/ TEST_F(ReleaseWithLocks, unlock_on_close) { diff --git a/tests/sys/fs/fusefs/write.cc b/tests/sys/fs/fusefs/write.cc index 1fe2e3cc522d..f5573a865a04 100644 --- a/tests/sys/fs/fusefs/write.cc +++ b/tests/sys/fs/fusefs/write.cc @@ -32,9 +32,11 @@ extern "C" { #include <sys/param.h> #include <sys/mman.h> #include <sys/resource.h> +#include <sys/socket.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/uio.h> +#include <sys/un.h> #include <aio.h> #include <fcntl.h> @@ -1398,6 +1400,77 @@ TEST_F(WriteBackAsync, eof) leak(fd); } +/* + * Nothing bad should happen if a file with a dirty writeback cache is closed + * while the last copy lies in some socket's socket buffer. Inspired by bug + * 289686 . + */ +TEST_F(WriteBackAsync, scm_rights) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefgh"; + uint64_t ino = 42; + int fd; + ssize_t bufsize = strlen(CONTENTS); + int s[2]; + struct msghdr msg; + struct iovec iov; + char message[CMSG_SPACE(sizeof(int))]; + union { + char buf[CMSG_SPACE(sizeof(fd))]; + struct cmsghdr align; + } u; + + expect_lookup(RELPATH, ino, 0); + expect_open(ino, 0, 1); + /* VOP_SETATTR will try to set timestamps during flush */ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in.header.opcode == FUSE_SETATTR && + in.header.nodeid == ino); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { + SET_OUT_HEADER_LEN(out, attr); + out.body.attr.attr.ino = ino; + out.body.attr.attr.mode = S_IFREG | 0644; + out.body.attr.attr.size = bufsize; + }))); + + expect_write(ino, 0, bufsize, bufsize, CONTENTS); + expect_flush(ino, 1, ReturnErrno(0)); + expect_release(ino, ReturnErrno(0)); + + /* Open a file on the fusefs file system */ + fd = open(FULLPATH, O_RDWR); + ASSERT_LE(0, fd) << strerror(errno); + + /* Write to the file to dirty its writeback cache */ + ASSERT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno); + + /* Send the file into a socket */ + ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, s)) << strerror(errno); + memset(&message, 0, sizeof(message)); + memset(&msg, 0, sizeof(msg)); + iov.iov_base = NULL; + iov.iov_len = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = u.buf, + msg.msg_controllen = sizeof(u.buf); + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + ASSERT_GE(sendmsg(s[0], &msg, 0), 0) << strerror(errno); + + close(fd); // Close fd within our process + close(s[0]); + close(s[1]); // The last copy of fd is within this socket's rcvbuf +} + /* * When a file has dirty writes that haven't been flushed, the server's notion * of its mtime and ctime will be wrong. The kernel should ignore those if it diff --git a/tests/sys/netpfil/pf/fragmentation_pass.sh b/tests/sys/netpfil/pf/fragmentation_pass.sh index 5deaba18301d..c749aac793ee 100644 --- a/tests/sys/netpfil/pf/fragmentation_pass.sh +++ b/tests/sys/netpfil/pf/fragmentation_pass.sh @@ -648,6 +648,72 @@ dummynet_fragmented_cleanup() pft_cleanup } +atf_test_case "counters" "cleanup" +counters_head() +{ + atf_set descr 'Test fragment counters' + atf_set require.user root +} + +counters_body() +{ + pft_init + + epair=$(vnet_mkepair) + vnet_mkjail alcatraz ${epair}a + + ifconfig ${epair}b inet 192.0.2.1/24 up + jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "set reassemble yes" \ + "pass keep state" + + # All fragment counters are zero + counters=$(jexec alcatraz pfctl -si -v | grep -A 4 '^Fragments') + atf_check -s exit:0 -o match:"current entries[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"searches[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"inserts[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"removals[[:space:]]+0" \ + echo $counters + + # They remain zero after we've seen non-fragmented traffic + atf_check -s exit:0 -o ignore \ + ping -c 1 192.0.2.2 + counters=$(jexec alcatraz pfctl -si -v | grep -A 4 '^Fragments') + atf_check -s exit:0 -o match:"current entries[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"searches[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"inserts[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"removals[[:space:]]+0" \ + echo $counters + + # But once we've reassembled they're no longer zero + # (Count is 2, because in + out) + atf_check -s exit:0 -o ignore \ + ping -c 1 -s 2000 192.0.2.2 + counters=$(jexec alcatraz pfctl -si -v | grep -A 4 '^Fragments') + atf_check -s exit:0 -o match:"current entries[[:space:]]+0" \ + echo $counters + atf_check -s exit:0 -o match:"searches[[:space:]]+2" \ + echo $counters + atf_check -s exit:0 -o match:"inserts[[:space:]]+2" \ + echo $counters + atf_check -s exit:0 -o match:"removals[[:space:]]+2" \ + echo $counters +} + +counters_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "too_many_fragments" @@ -665,4 +731,5 @@ atf_init_test_cases() atf_add_test_case "dummynet" atf_add_test_case "dummynet_nat" atf_add_test_case "dummynet_fragmented" + atf_add_test_case "counters" } diff --git a/tests/sys/netpfil/pf/limits.sh b/tests/sys/netpfil/pf/limits.sh index 69f0b6af2ccf..a0d6b891ee19 100644 --- a/tests/sys/netpfil/pf/limits.sh +++ b/tests/sys/netpfil/pf/limits.sh @@ -112,8 +112,43 @@ zero_cleanup() pft_cleanup } +atf_test_case "anchors" "cleanup" +anchors_head() +{ + atf_set descr 'Test increasing maximum number of anchors' + atf_set require.user root +} + +anchors_body() +{ + pft_init + + vnet_mkjail alcatraz + + jexec alcatraz pfctl -e + + pft_set_rules alcatraz \ + "set limit anchors 1" + + pft_set_rules alcatraz \ + "set limit anchors 2" \ + "pass" \ + "anchor \"foo\" {\n + pass in\n + }" \ + "anchor \"bar\" {\n + pass out\n + }" +} + +anchors_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "basic" atf_add_test_case "zero" + atf_add_test_case "anchors" } diff --git a/tests/sys/netpfil/pf/pflog.sh b/tests/sys/netpfil/pf/pflog.sh index a34ec893a75c..550548a59c11 100644 --- a/tests/sys/netpfil/pf/pflog.sh +++ b/tests/sys/netpfil/pf/pflog.sh @@ -394,6 +394,64 @@ rdr_action_cleanup() pft_cleanup } +atf_test_case "rule_number" "cleanup" +rule_number_head() +{ + atf_set descr 'Test rule numbers with anchors' + atf_set require.user root +} + +rule_number_body() +{ + pflog_init + + epair=$(vnet_mkepair) + + vnet_mkjail alcatraz ${epair}b + jexec alcatraz ifconfig ${epair}b 192.0.2.1/24 up + + ifconfig ${epair}a 192.0.2.2/24 up + ifconfig ${epair}a inet alias 192.0.2.3/24 up + ifconfig ${epair}a inet alias 192.0.2.4/24 up + + jexec alcatraz pfctl -e + jexec alcatraz ifconfig pflog0 up + pft_set_rules alcatraz \ + "pass log from 192.0.2.2" \ + "anchor \"foo\" {\n \ + pass log from 192.0.2.3\n \ + }" \ + "pass log from 192.0.2.4" + + jexec alcatraz tcpdump -n -e -ttt --immediate-mode -l -U -i pflog0 >> pflog.txt & + sleep 1 # Wait for tcpdump to start + + atf_check -s exit:0 -o ignore \ + ping -c 1 -S 192.0.2.2 192.0.2.1 + atf_check -s exit:0 -o ignore \ + ping -c 1 -S 192.0.2.3 192.0.2.1 + atf_check -s exit:0 -o ignore \ + ping -c 1 -S 192.0.2.4 192.0.2.1 + + jexec alcatraz pfctl -sr -a '*' -vv + + # Give tcpdump a little time to finish writing to the file + sleep 1 + cat pflog.txt + + atf_check -o match:"rule 0/0\(match\): pass in.*: 192.0.2.2.*ICMP echo request" \ + cat pflog.txt + atf_check -o match:"rule 1.foo.0/0\(match\): pass in.*: 192.0.2.3.*: ICMP echo request" \ + cat pflog.txt + atf_check -o match:"rule 2/0\(match\): pass in.*: 192.0.2.4.*: ICMP echo request" \ + cat pflog.txt +} + +rule_number_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "malformed" @@ -403,4 +461,5 @@ atf_init_test_cases() atf_add_test_case "unspecified_v4" atf_add_test_case "unspecified_v6" atf_add_test_case "rdr_action" + atf_add_test_case "rule_number" } diff --git a/tests/sys/netpfil/pf/route_to.sh b/tests/sys/netpfil/pf/route_to.sh index 872de0dcbb91..13b60c8f80bc 100644 --- a/tests/sys/netpfil/pf/route_to.sh +++ b/tests/sys/netpfil/pf/route_to.sh @@ -968,6 +968,7 @@ table_loop_head() { atf_set descr 'Check that iterating over tables poperly loops' atf_set require.user root + atf_set require.progs python3 scapy } table_loop_body() @@ -1032,6 +1033,7 @@ roundrobin_head() { atf_set descr 'multiple gateways of mixed AF, including prefixes and tables, for IPv6 packets' atf_set require.user root + atf_set require.progs python3 scapy } roundrobin_body() @@ -1094,6 +1096,7 @@ random_table_head() { atf_set descr 'Pool with random flag and a table for IPv6' atf_set require.user root + atf_set require.progs python3 scapy } random_table_body() @@ -1131,6 +1134,7 @@ random_prefix_head() { atf_set descr 'Pool with random flag and a table for IPv4' atf_set require.user root + atf_set require.progs python3 scapy } random_prefix_body() @@ -1167,6 +1171,7 @@ prefer_ipv6_nexthop_single_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for a single IPv4 gateway' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_single_ipv4_body() @@ -1219,6 +1224,7 @@ prefer_ipv6_nexthop_single_ipv6_head() { atf_set descr 'prefer-ipv6-nexthop option for a single IPv6 gateway' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_single_ipv6_body() @@ -1269,6 +1275,7 @@ prefer_ipv6_nexthop_mixed_af_roundrobin_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for multiple gateways of mixed AF with prefixes and tables, round robin selection, for IPv4 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_mixed_af_roundrobin_ipv4_body() @@ -1337,6 +1344,7 @@ prefer_ipv6_nexthop_mixed_af_roundrobin_ipv6_head() { atf_set descr 'prefer-ipv6-nexthop option for multiple gateways of mixed AF with prefixes and tables, round-robin selection, for IPv6 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_mixed_af_roundrobin_ipv6_body() @@ -1407,6 +1415,7 @@ prefer_ipv6_nexthop_mixed_af_random_table_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for a mixed-af table with random selection for IPv4 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_mixed_af_random_table_ipv4_body() @@ -1444,6 +1453,7 @@ prefer_ipv6_nexthop_ipv4_random_table_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv4-only table with random selection for IPv4 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv4_random_table_ipv4_body() @@ -1479,6 +1489,7 @@ prefer_ipv6_nexthop_ipv4_random_table_ipv6_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv4-only table with random selection for IPv6 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv4_random_table_ipv6_body() @@ -1516,6 +1527,7 @@ prefer_ipv6_nexthop_ipv6_random_prefix_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv6 prefix with random selection for IPv4 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv6_random_prefix_ipv4_body() @@ -1544,6 +1556,7 @@ prefer_ipv6_nexthop_ipv6_random_prefix_ipv6_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv6 prefix with random selection for IPv6 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv6_random_prefix_ipv6_body() @@ -1572,6 +1585,7 @@ prefer_ipv6_nexthop_ipv4_random_prefix_ipv4_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv4 prefix with random selection for IPv4 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv4_random_prefix_ipv4_body() @@ -1600,6 +1614,7 @@ prefer_ipv6_nexthop_ipv4_random_prefix_ipv6_head() { atf_set descr 'prefer-ipv6-nexthop option for an IPv4 prefix with random selection for IPv6 packets' atf_set require.user root + atf_set require.progs python3 scapy } prefer_ipv6_nexthop_ipv4_random_prefix_ipv6_body() diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index 26fc5bf6cda2..69fe12fc9804 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -710,6 +710,43 @@ show_recursive_cleanup() pft_cleanup } +atf_test_case "in_anchor" "cleanup" +in_anchor_head() +{ + atf_set descr 'Test declaring tables in anchors' + atf_set require.user root +} + +in_anchor_body() +{ + pft_init + + epair_send=$(vnet_mkepair) + ifconfig ${epair_send}a 192.0.2.1/24 up + + vnet_mkjail alcatraz ${epair_send}b + jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up + + jexec alcatraz pfctl -e + + pft_set_rules alcatraz \ + "block all" \ + "anchor \"foo\" {\n + table <bar> counters { 192.0.2.1 }\n + pass in from <bar>\n + }\n" + + atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 + + jexec alcatraz pfctl -sr -a "*" -vv + jexec alcatraz pfctl -sT -a "*" -vv +} + +in_anchor_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4_counters" @@ -727,4 +764,5 @@ atf_init_test_cases() atf_add_test_case "flush" atf_add_test_case "large" atf_add_test_case "show_recursive" + atf_add_test_case "in_anchor" } diff --git a/tools/boot/universe.sh b/tools/boot/universe.sh index e97858ff2bcb..80a9cc0b90ff 100755 --- a/tools/boot/universe.sh +++ b/tools/boot/universe.sh @@ -95,11 +95,11 @@ for i in \ dobuild $ta _.boot.${ta}.no_zfs.log "MK_LOADER_ZFS=no" done -# Build w/ LOADER_BIOS_TEXTONLY +# Build w/o LOADER_BIOS_TEXTONLY for i in \ amd64/amd64 \ i386/i386 \ ; do ta=${i##*/} - dobuild $ta _.boot.${ta}.no_zfs.log "MK_LOADER_BIOS_TEXTONLY=yes" + dobuild $ta _.boot.${ta}.no_zfs.log "MK_LOADER_BIOS_TEXTONLY=no" done diff --git a/tools/regression/priv/main.c b/tools/regression/priv/main.c index dbcb5759f6b9..979e6ed65284 100644 --- a/tools/regression/priv/main.c +++ b/tools/regression/priv/main.c @@ -423,12 +423,10 @@ setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode) static void set_creds(const char *test, uid_t uid, gid_t gid) { - gid_t gids[1] = { gid }; - if (setgid(gid) < 0) err(-1, "test %s: setegid(%d)", test, gid); - if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0) - err(-1, "test %s: setgroups(%d)", test, gid); + if (setgroups(0, NULL) < 0) + err(-1, "test %s: setgroups(NULL)", test); if (setuid(uid) < 0) err(-1, "test %s: seteuid(%d)", test, uid); } diff --git a/tools/regression/sockets/udp_pingpong/udp_pingpong.c b/tools/regression/sockets/udp_pingpong/udp_pingpong.c index 2fe342debdc6..e852f7a7af87 100644 --- a/tools/regression/sockets/udp_pingpong/udp_pingpong.c +++ b/tools/regression/sockets/udp_pingpong/udp_pingpong.c @@ -601,11 +601,9 @@ main(void) test_run(TT_TIMESTAMP, i, 1, "send()/recvmsg(), setsockopt(SO_TIMESTAMP, 1)"); printf("OK\n"); - if (i == 0) { - test_run(TT_BINTIME, i, 1, - "send()/recvmsg(), setsockopt(SO_BINTIME, 1)"); - printf("OK\n"); - } + test_run(TT_BINTIME, i, 1, + "send()/recvmsg(), setsockopt(SO_BINTIME, 1)"); + printf("OK\n"); test_run(TT_REALTIME_MICRO, i, 1, "send()/recvmsg(), setsockopt(SO_TS_CLOCK, SO_TS_REALTIME_MICRO)"); printf("OK\n"); diff --git a/tools/test/stress2/misc/beneath4.sh b/tools/test/stress2/misc/beneath4.sh index 48458f088a96..3ba448cd06c7 100755 --- a/tools/test/stress2/misc/beneath4.sh +++ b/tools/test/stress2/misc/beneath4.sh @@ -88,7 +88,7 @@ main(int argc, char *argv[]) warn("cwd=%s, top=%s. flag=%0.6x. fstatf(%s) = %2d (expect %2d). %4s", cwd, dir, flag, obj, r, exp, s); - return (r == exp ? 0 : errno); + return (r != exp); } EOF cc -o beneath4 -Wall -Wextra -O2 -g beneath4.c || exit 1 @@ -129,5 +129,5 @@ $dir/beneath4 $top $top/.. 0x2000 93 || s=1 $dir/beneath4 $top ../a 0x2000 93 || s=1 printf "\nNo flag\n" $dir/beneath4 $top ../a 0x0000 0 || s=1 -rm -rf $top +rm -rf $dir exit $s diff --git a/tools/test/stress2/misc/fdatasync.sh b/tools/test/stress2/misc/fdatasync.sh index f17e2826ad94..9abd31e5bd94 100755 --- a/tools/test/stress2/misc/fdatasync.sh +++ b/tools/test/stress2/misc/fdatasync.sh @@ -178,7 +178,7 @@ main(int argc, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/fdatasync2.sh b/tools/test/stress2/misc/fdatasync2.sh index 6011eba53698..42ade0cedbd3 100755 --- a/tools/test/stress2/misc/fdatasync2.sh +++ b/tools/test/stress2/misc/fdatasync2.sh @@ -177,7 +177,7 @@ main(int argc, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/fdescfs2.sh b/tools/test/stress2/misc/fdescfs2.sh new file mode 100755 index 000000000000..21b82dcddd5e --- /dev/null +++ b/tools/test/stress2/misc/fdescfs2.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Test scenario description by: Kyle Evans <kevans@FreeBSD.org> + +# "panic: mtx_lock() of destroyed mutex 0xffffffff83717540 @ /usr/src/sys/fs/fdescfs/fdesc_vnops.c:151" seen + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u + +kldstat | grep -q fdescfs.ko && { kldunload fdescfs.ko && wasloaded=1; } +while true; do + mount | grep -q "on $mntpoint " || + mount -t fdescfs dummy $mntpoint || continue + ls $mntpoint > /dev/null + if mount | grep -q "on $mntpoint "; then + if ! umount $mntpoint; then + umount -f $mntpoint || break + fi + fi +done > /dev/null 2>&1 & + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 10 ]; do + kldstat | grep -q fdescfs.ko && + kldunload fdescfs.ko 2>/dev/null + sleep .1 + kldstat | grep -q fdescfs.ko || + kldload fdescfs.ko +done +kill %1 +wait +mount | grep -q "on $mntpoint " && umount $mntpoint +sleep .1 +set +u +[ $wasloaded ] || kldunload fdescfs.ko +exit 0 diff --git a/tools/test/stress2/misc/fdescfs3.sh b/tools/test/stress2/misc/fdescfs3.sh new file mode 100755 index 000000000000..eb24a6eac085 --- /dev/null +++ b/tools/test/stress2/misc/fdescfs3.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +mounts=15 # Number of parallel scripts +mdstart=$mdstart # Use md unit numbers from this point + +if [ $# -eq 0 ]; then + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m + mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m + done + ../testcases/swap/swap -t 2m -i 20 & + + # start the parallel tests + touch /tmp/$0 + for i in `jot $mounts`; do + m=$(( i + mdstart - 1 )) + ./$0 $m & + ./$0 find $m > /dev/null 2>&1 & + done + wait +else + if [ $1 = find ]; then + while [ -r /tmp/$0 ]; do + ls -lR ${mntpoint}* + done + else + + # The test: Parallel mount and unmounts + start=`date +%s` + while [ $((`date +%s` - start)) -lt 120 ]; do + m=$1 + mount -t fdescfs null ${mntpoint}$m + while mount | grep -qw $mntpoint$m; do + opt=$([ $((`date '+%s'` % 2)) -eq 0 ] && echo "-f") + umount $opt ${mntpoint}$m > /dev/null 2>&1 + done + done + rm -f /tmp/$0 + fi +fi diff --git a/tools/test/stress2/misc/fifo2.sh b/tools/test/stress2/misc/fifo2.sh index 4a7b986931d9..e84506cbfb01 100755 --- a/tools/test/stress2/misc/fifo2.sh +++ b/tools/test/stress2/misc/fifo2.sh @@ -167,7 +167,7 @@ main(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/ftruncate.sh b/tools/test/stress2/misc/ftruncate.sh index ddec85b6745a..f9aa1869756f 100755 --- a/tools/test/stress2/misc/ftruncate.sh +++ b/tools/test/stress2/misc/ftruncate.sh @@ -170,7 +170,7 @@ main(int argc, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/ftruncate2.sh b/tools/test/stress2/misc/ftruncate2.sh index 35db3a4c5f8d..94d9b6ca810f 100755 --- a/tools/test/stress2/misc/ftruncate2.sh +++ b/tools/test/stress2/misc/ftruncate2.sh @@ -185,7 +185,7 @@ main(int argc, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/kevent10.sh b/tools/test/stress2/misc/kevent10.sh index b7f74f487cec..cebbd040c37d 100755 --- a/tools/test/stress2/misc/kevent10.sh +++ b/tools/test/stress2/misc/kevent10.sh @@ -72,15 +72,15 @@ main(void) struct kevent events; char *fn = "/tmp/kevent10.trace"; - if (open(fn, O_RDWR | O_CREAT, 0666) == -1) - err(1, "%s", fn); + if (open(fn, O_RDWR | O_CREAT | O_TRUNC, 0666) == -1) + err(1, "open(%s)", fn); if (ktrace(fn, KTRFLAG_DESCEND | KTROP_SET, KTRFAC_GENIO, 0) == -1) err(1, "ktrace"); memset(&changes, 0, sizeof(struct kevent)); memset(&events, 0, sizeof(struct kevent)); if (kevent(0, &changes, -1, &events, 1, 0) == -1) - if (errno != EBADF) - err(1, "kevent"); + if (errno != EBADF && errno != EINVAL) + warn("kevent"); if (ktrace(fn, KTROP_CLEARFILE, KTRFAC_GENIO, 0) == -1) err(1, "ktrace clear"); diff --git a/tools/test/stress2/misc/kevent16.sh b/tools/test/stress2/misc/kevent16.sh index 23dd222821da..58a8f6971c21 100755 --- a/tools/test/stress2/misc/kevent16.sh +++ b/tools/test/stress2/misc/kevent16.sh @@ -88,5 +88,5 @@ cc -o /tmp/kevent16 -Wall -Wextra -O2 /tmp/kevent16.c || exit 1 /tmp/kevent16; s=$? -rm -f /tmp/kevent16.c kevent16 kevent16.core +rm -f /tmp/kevent16.c /tmp/kevent16 kevent16.core exit $s diff --git a/tools/test/stress2/misc/kevent7.sh b/tools/test/stress2/misc/kevent7.sh index 8b58c35551f7..4c7718c6ae5f 100755 --- a/tools/test/stress2/misc/kevent7.sh +++ b/tools/test/stress2/misc/kevent7.sh @@ -236,7 +236,7 @@ main(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/killpg.sh b/tools/test/stress2/misc/killpg.sh index c6af55a3d593..ea99f5e0d0fd 100755 --- a/tools/test/stress2/misc/killpg.sh +++ b/tools/test/stress2/misc/killpg.sh @@ -113,7 +113,7 @@ killer(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/killpg2.sh b/tools/test/stress2/misc/killpg2.sh index 5e986f059637..cf186d686dfd 100755 --- a/tools/test/stress2/misc/killpg2.sh +++ b/tools/test/stress2/misc/killpg2.sh @@ -77,7 +77,7 @@ looper(void) if ((pw = getpwnam("TUSER")) == NULL) err(1, "no such user: TUSER"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"TUSER\""); diff --git a/tools/test/stress2/misc/killpg3.sh b/tools/test/stress2/misc/killpg3.sh index 304b3e320f2f..4fcb4fa7a643 100755 --- a/tools/test/stress2/misc/killpg3.sh +++ b/tools/test/stress2/misc/killpg3.sh @@ -109,7 +109,7 @@ looper(void) if ((pw = getpwnam("TUSER")) == NULL) err(1, "no such user: TUSER"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"TUSER\""); diff --git a/tools/test/stress2/misc/maxproc.sh b/tools/test/stress2/misc/maxproc.sh index c425c307e06b..3241e275375e 100755 --- a/tools/test/stress2/misc/maxproc.sh +++ b/tools/test/stress2/misc/maxproc.sh @@ -32,12 +32,12 @@ . ../default.cfg +[ `sysctl -n kern.maxproc` -gt 37028 ] && exit 0 # Excessive run time here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > maxproc.c mycc -o maxproc -Wall -Wextra maxproc.c -lkvm || exit 1 rm -f maxproc.c -[ `sysctl -n kern.maxproc` -gt 37028 ] && exit 0 # Excessive run time cd $here /tmp/maxproc @@ -103,7 +103,7 @@ t1(int priv) err(1, "no such user: nobody"); if (priv == 0) { - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/mlockall3.sh b/tools/test/stress2/misc/mlockall3.sh index 0ff1e24eaa7f..aa53e75166a5 100755 --- a/tools/test/stress2/misc/mlockall3.sh +++ b/tools/test/stress2/misc/mlockall3.sh @@ -130,7 +130,7 @@ main(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/mlockall7.sh b/tools/test/stress2/misc/mlockall7.sh index 987e312f19e7..5a927043cb56 100755 --- a/tools/test/stress2/misc/mlockall7.sh +++ b/tools/test/stress2/misc/mlockall7.sh @@ -179,7 +179,7 @@ testing(unsigned long maxl) maxlock = maxl; if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/mmap43.sh b/tools/test/stress2/misc/mmap43.sh index 8508d5865aef..424e189b8b84 100755 --- a/tools/test/stress2/misc/mmap43.sh +++ b/tools/test/stress2/misc/mmap43.sh @@ -180,7 +180,7 @@ cd $here umount $mntpoint mdconfig -d -u $mdstart -rm /tmp/$prog /tmp/$prog.c /tmp/$prog.sort +rm /tmp/$prog /tmp/$prog.c /tmp/$prog.sort /tmp/$prog.serial.c /tmp/$prog.serial $log [ $s -eq 0 ] && printf "OK File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter || printf "FAIL File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter diff --git a/tools/test/stress2/misc/mountu.sh b/tools/test/stress2/misc/mountu.sh index abd3c744d160..95043e634ef1 100755 --- a/tools/test/stress2/misc/mountu.sh +++ b/tools/test/stress2/misc/mountu.sh @@ -241,7 +241,7 @@ main(int argc __unused, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/msync.sh b/tools/test/stress2/misc/msync.sh index 326c7e723774..df05875afb45 100755 --- a/tools/test/stress2/misc/msync.sh +++ b/tools/test/stress2/misc/msync.sh @@ -166,7 +166,7 @@ main(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/nfs_halfpage.sh b/tools/test/stress2/misc/nfs_halfpage.sh index 8d02ca8ebbcf..b2f606e9607b 100755 --- a/tools/test/stress2/misc/nfs_halfpage.sh +++ b/tools/test/stress2/misc/nfs_halfpage.sh @@ -35,6 +35,11 @@ # https://reviews.freebsd.org/D11697 # Committed as r321580 + r321581. +[ -z "$nfs_export" ] && exit 0 +ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || + exit 0 + +mount | grep "$mntpoint" | grep -q nfs && umount $mntpoint dir=/tmp odir=`pwd` cd $dir @@ -43,11 +48,6 @@ mycc -o nfs_halfpage -Wall -Wextra -O0 -g nfs_halfpage.c || exit 1 rm -f nfs_halfpage.c cd $odir -[ -z "$nfs_export" ] && exit 0 -ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || - exit 0 - -mount | grep "$mntpoint" | grep -q nfs && umount $mntpoint mount -t nfs -o tcp -o retrycnt=3 -o intr,soft -o rw $nfs_export $mntpoint file=$mntpoint/nfs_halfpage.file diff --git a/tools/test/stress2/misc/nfs_halfpage2.sh b/tools/test/stress2/misc/nfs_halfpage2.sh index b916531c7a9d..8ca907f25e09 100755 --- a/tools/test/stress2/misc/nfs_halfpage2.sh +++ b/tools/test/stress2/misc/nfs_halfpage2.sh @@ -35,6 +35,10 @@ # https://reviews.freebsd.org/D11697 # Committed as r321580 + r321581. +[ -z "$nfs_export" ] && exit 0 +ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || + exit 0 + dir=/tmp odir=`pwd` cd $dir @@ -43,10 +47,6 @@ mycc -o nfs_halfpage -Wall -Wextra -O0 -g nfs_halfpage.c || exit 1 rm -f nfs_halfpage.c cd $odir -[ -z "$nfs_export" ] && exit 0 -ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || - exit 0 - mount | grep "$mntpoint" | grep -q nfs && umount $mntpoint mount -t nfs -o tcp -o retrycnt=3 -o intr,soft -o rw $nfs_export $mntpoint diff --git a/tools/test/stress2/misc/nullfs29.sh b/tools/test/stress2/misc/nullfs29.sh index aa606fd5f526..977e3c087523 100755 --- a/tools/test/stress2/misc/nullfs29.sh +++ b/tools/test/stress2/misc/nullfs29.sh @@ -73,5 +73,5 @@ while mount | grep $mp1 | grep -q /dev/md; do [ $n -gt 30 ] && { echo FAIL; s=2; } done mdconfig -d -u $mdstart -rm -f /tmp/nullfs29.c +rm -f /tmp/nullfs29.c /tmp/nullfs29 exit $s diff --git a/tools/test/stress2/misc/pread.sh b/tools/test/stress2/misc/pread.sh index 24ee2efb696a..985d3f643df1 100755 --- a/tools/test/stress2/misc/pread.sh +++ b/tools/test/stress2/misc/pread.sh @@ -170,7 +170,7 @@ main(int argc __unused, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/rsync.sh b/tools/test/stress2/misc/rsync.sh index fa52f98c6f02..1e677c7c1f6c 100755 --- a/tools/test/stress2/misc/rsync.sh +++ b/tools/test/stress2/misc/rsync.sh @@ -31,7 +31,7 @@ if [ $s -eq 0 ]; then fi if [ $s -eq 0 ]; then - diff -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? + diff --no-dereference -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? [ $s -ne 0 ] && { echo "/usr/src $mntpoint/usr/src differ!"; head -10 $log; } fi diff --git a/tools/test/stress2/misc/rsync3.sh b/tools/test/stress2/misc/rsync3.sh index 1d77bdfbcaa5..e5e4db128b0f 100755 --- a/tools/test/stress2/misc/rsync3.sh +++ b/tools/test/stress2/misc/rsync3.sh @@ -30,7 +30,7 @@ if [ $s -eq 0 ]; then fi if [ $s -eq 0 ]; then - diff -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? + diff --no-dereference -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? [ $s -ne 0 ] && { echo "/usr/src $mntpoint/usr/src differ!"; head -10 $log; } fi diff --git a/tools/test/stress2/misc/sched.sh b/tools/test/stress2/misc/sched.sh index 1a1db70eb38a..8b33d7b16094 100755 --- a/tools/test/stress2/misc/sched.sh +++ b/tools/test/stress2/misc/sched.sh @@ -107,7 +107,7 @@ work(void) if ((pw = getpwnam("nobody")) == NULL) err(1, "no such user: nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/setrlimit2.sh b/tools/test/stress2/misc/setrlimit2.sh index 4eea25ef3ee4..8c717fe72458 100755 --- a/tools/test/stress2/misc/setrlimit2.sh +++ b/tools/test/stress2/misc/setrlimit2.sh @@ -114,5 +114,5 @@ h1=`md5 < $data` ./setrlimit2 $data h2=`md5 < $data` -rm -f /tmp/setrlimit2 /tmp/setrlimit2.c +rm -f /tmp/setrlimit2 /tmp/setrlimit2.c $data [ $h1 = $h2 ] && exit 1 || exit 0 diff --git a/tools/test/stress2/misc/sigreturn3.sh b/tools/test/stress2/misc/sigreturn3.sh index 271ade287e9a..6795c4fd0846 100755 --- a/tools/test/stress2/misc/sigreturn3.sh +++ b/tools/test/stress2/misc/sigreturn3.sh @@ -121,7 +121,7 @@ main(int argc, char **argv) fprintf(stderr, "Running syscall4 as root for %s.\n", argv[1]); else { - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); @@ -177,5 +177,5 @@ start=`date +%s` while [ $((`date +%s` - start)) -lt 300 ]; do ./$prog > /dev/null 2>&1 done -rm -f /tmp/$prog /tmp/$ptog.c /tmp/$prog.core +rm -f /tmp/$prog /tmp/$prog.c /tmp/$prog.core exit 0 diff --git a/tools/test/stress2/misc/sigreturn4.sh b/tools/test/stress2/misc/sigreturn4.sh index 9e2a6a32715c..90ee16777e03 100755 --- a/tools/test/stress2/misc/sigreturn4.sh +++ b/tools/test/stress2/misc/sigreturn4.sh @@ -147,7 +147,7 @@ main(int argc, char **argv) fprintf(stderr, "Running sigreturn4 as root for %s.\n", argv[1]); else { - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); @@ -203,5 +203,5 @@ start=`date +%s` while [ $((`date +%s` - start)) -lt 300 ]; do ./$prog > /dev/null 2>&1 done -rm -f /tmp/$prog /tmp/$ptog.c /tmp/$prog.core +rm -f /tmp/$prog /tmp/$prog.c /tmp/$prog.core exit 0 diff --git a/tools/test/stress2/misc/syscall4.sh b/tools/test/stress2/misc/syscall4.sh index 3937d45c0303..92150c782ac1 100755 --- a/tools/test/stress2/misc/syscall4.sh +++ b/tools/test/stress2/misc/syscall4.sh @@ -318,7 +318,7 @@ main(int argc, char **argv) fprintf(stderr, "Running syscall4 as root for %s.\n", argv[1]); else { - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/syzkaller13.sh b/tools/test/stress2/misc/syzkaller13.sh index 9b46ebd290af..fe15652b0a25 100755 --- a/tools/test/stress2/misc/syzkaller13.sh +++ b/tools/test/stress2/misc/syzkaller13.sh @@ -246,4 +246,5 @@ pkill -9 syzkaller13 wait rm -f /tmp/syzkaller13 /tmp/syzkaller13.* /tmp/file0 +rm -rf /tmp/syzkaller.* exit 0 diff --git a/tools/test/stress2/misc/syzkaller21.sh b/tools/test/stress2/misc/syzkaller21.sh index 3a7eeb05ef6c..07eef4bc5861 100755 --- a/tools/test/stress2/misc/syzkaller21.sh +++ b/tools/test/stress2/misc/syzkaller21.sh @@ -398,6 +398,6 @@ if pgrep -q syzkaller21; then fi wait -rm -rf /tmp/syzkaller21.* +rm -rf /tmp/syzkaller21.* /tmp/syzkaller.* rm -f /tmp/syzkaller21 exit 0 diff --git a/tools/test/stress2/misc/syzkaller61.sh b/tools/test/stress2/misc/syzkaller61.sh index a25ae4cf00d8..d07f12b05b1a 100755 --- a/tools/test/stress2/misc/syzkaller61.sh +++ b/tools/test/stress2/misc/syzkaller61.sh @@ -1,15 +1,7 @@ #!/bin/sh -# Seen: -# [root@mercat1 /usr/src/tools/test/stress2/misc]# pgrep syzkaller61 | xargs procstat -k -# PID TID COMM TDNAME KSTACK -# 13332 106396 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast -# 13332 560662 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common -# 13332 560776 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common -# 13662 356440 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast -# 13662 561098 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common -# 13662 561160 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common -# [root@mercat1 /usr/src/tools/test/stress2/misc]# +# "panic: inconsistent boundary count 2" seen. +# Fixed by: 8321d0da2ce2 - main - kern/kern_thread.c: improve assert in thread_single_end() [ `uname -p` != "amd64" ] && exit 0 @@ -276,7 +268,7 @@ void execute_call(int call) { switch (call) { case 0: - NONFAILING(*(uint32_t*)0x20001f00 = 0x16); + NONFAILING(*(uint32_t*)0x20001f00 = 0x16); /* SIGTTOU */ NONFAILING(*(uint32_t*)0x20001f04 = 0); NONFAILING(*(uint32_t*)0x20001f08 = 0); NONFAILING(*(uint32_t*)0x20001f0c = 0); @@ -302,18 +294,16 @@ mycc -o /tmp/syzkaller61 -Wall -Wextra -O0 /tmp/syzkaller61.c -lpthread || (cd ../testcases/swap; ./swap -t 3m -i 10 -l 100 > /dev/null 2>&1) & for i in `jot 300`; do - (cd /tmp; timeout -k 3s 2s ./syzkaller61) & + (cd /tmp; su -m $testuser -c ./syzkaller61) & pids="$pids $!" done sleep 5 -pkill -9 syzkaller61 swap; sleep 1 -pgrep -q syzkaller61 && { pgrep syzkaller61 | xargs ps -lHp; exit 1; } -for pid in $pids; do - wait $pid -done +kill -9 $pids +wait $pids +while pkill -9 syzkaller61; do :; done while pkill swap; do :; done wait rm -rf /tmp/syzkaller61 /tmp/syzkaller61.c /tmp/syzkaller61.core \ /tmp/syzkaller.?????? -exit 0 +exit 0 diff --git a/tools/test/stress2/misc/syzkaller73.sh b/tools/test/stress2/misc/syzkaller73.sh index 776ace385f21..fa07dc7ff26f 100755 --- a/tools/test/stress2/misc/syzkaller73.sh +++ b/tools/test/stress2/misc/syzkaller73.sh @@ -533,5 +533,5 @@ done while pkill swap; do :; done wait -rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/syzkaller.* exit 0 diff --git a/tools/test/stress2/misc/syzkaller74.sh b/tools/test/stress2/misc/syzkaller74.sh index 886c6047585b..0c2b4e1d5325 100755 --- a/tools/test/stress2/misc/syzkaller74.sh +++ b/tools/test/stress2/misc/syzkaller74.sh @@ -465,5 +465,5 @@ mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 cd /tmp timeout 3m /tmp/$prog > /dev/null 2>&1 -rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? /tmp/syzkaller.* exit 0 diff --git a/tools/test/stress2/misc/temp.sh b/tools/test/stress2/misc/temp.sh index 5c1a73cd18e1..4cddd48079ec 100755 --- a/tools/test/stress2/misc/temp.sh +++ b/tools/test/stress2/misc/temp.sh @@ -32,6 +32,10 @@ . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +[ -z "$nfs_export" ] && exit 0 +ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || + exit 0 + export LANG=C dir=/tmp odir=`pwd` @@ -41,10 +45,6 @@ mycc -o temp -Wall -Wextra -O0 -g temp.c || exit 1 rm -f temp.c cd $odir -[ -z "$nfs_export" ] && exit 0 -ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 || - exit 0 - mount | grep "on $mntpoint " | grep -q nfs && umount $mntpoint mount -t nfs -o tcp -o retrycnt=3 -o soft -o rw $nfs_export $mntpoint mp2=$mntpoint/temp.`jot -rc 8 a z | tr -d '\n'`/temp.dir diff --git a/tools/test/stress2/misc/tmpfs16.sh b/tools/test/stress2/misc/tmpfs16.sh index 8cc3c3596a4e..683817ce6497 100755 --- a/tools/test/stress2/misc/tmpfs16.sh +++ b/tools/test/stress2/misc/tmpfs16.sh @@ -181,7 +181,7 @@ main(int argc, char **argv) if ((pw = getpwnam("nobody")) == NULL) err(1, "failed to resolve nobody"); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setegid(pw->pw_gid) || setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) err(1, "Can't drop privileges to \"nobody\""); diff --git a/tools/test/stress2/misc/unionfs7.sh b/tools/test/stress2/misc/unionfs7.sh index 6adcd01a5f83..9c00ba73e5c2 100755 --- a/tools/test/stress2/misc/unionfs7.sh +++ b/tools/test/stress2/misc/unionfs7.sh @@ -61,8 +61,8 @@ set +e mount | grep -E "$mp1|$mp2" set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` -export KBLOCKS=$(($1 / 4)) -export INODES=$(($2 / 4)) +export KBLOCKS=$(($1 / 6)) +export INODES=$(($2 / 6)) export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 @@ -95,7 +95,7 @@ export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` set +e chmod 777 $mp2 su $testuser -c \ - "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS)" + "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS > /dev/null 2>&1)" while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh index 4c4323c4bd87..4f0cc2fa99bd 100755 --- a/tools/tools/nanobsd/defaults.sh +++ b/tools/tools/nanobsd/defaults.sh @@ -209,30 +209,29 @@ SRC_ENV_CONF=/dev/null # ####################################################################### -# Export values into the shell. Must use { } instead of ( ) like -# other functions to avoid a subshell. +# Export values into the shell. # We set __MAKE_CONF as a global since it is easier to get quoting # right for paths with spaces in them. -make_export ( ) { +make_export() { # Similar to export_var, except puts the data out to stdout - var=$1 + local var=$1 eval val=\$$var echo "Setting variable: $var=\"$val\"" export $1 } -nano_make_build_env ( ) { +nano_make_build_env() { __MAKE_CONF="${NANO_MAKE_CONF_BUILD}" make_export __MAKE_CONF } -nano_make_install_env ( ) { +nano_make_install_env() { __MAKE_CONF="${NANO_MAKE_CONF_INSTALL}" make_export __MAKE_CONF } # Extra environment variables for kernel builds -nano_make_kernel_env ( ) { +nano_make_kernel_env() { if [ -f "${NANO_KERNEL}" ] ; then KERNCONFDIR="$(realpath $(dirname ${NANO_KERNEL}))" KERNCONF="$(basename ${NANO_KERNEL})" @@ -244,23 +243,23 @@ nano_make_kernel_env ( ) { fi } -nano_global_make_env ( ) ( +nano_global_make_env() { # global settings for the make.conf file, if set [ -z "${NANO_ARCH}" ] || echo TARGET_ARCH="${NANO_ARCH}" [ -z "${NANO_CPUTYPE}" ] || echo TARGET_CPUTYPE="${NANO_CPUTYPE}" -) +} # # Create empty files in the target tree, and record the fact. All paths # are relative to NANO_WORLDDIR. # -tgt_touch ( ) ( +tgt_touch() { cd "${NANO_WORLDDIR}" for i; do touch $i echo "./${i} type=file" >> ${NANO_METALOG} done -) +} # # Convert a directory into a symlink. Takes two arguments, the @@ -268,9 +267,9 @@ tgt_touch ( ) ( # directory is removed and a symlink is created. If we're doing # a nopriv build, then append this fact to the metalog # -tgt_dir2symlink ( ) ( - dir=$1 - symlink=$2 +tgt_dir2symlink() { + local dir=$1 + local symlink=$2 cd "${NANO_WORLDDIR}" rm -xrf "$dir" @@ -278,28 +277,28 @@ tgt_dir2symlink ( ) ( if [ -n "$NANO_METALOG" ]; then echo "./${dir} type=link mode=0777 link=${symlink}" >> ${NANO_METALOG} fi -) +} # run in the world chroot, errors fatal -CR ( ) { +CR() { chroot "${NANO_WORLDDIR}" /bin/sh -exc "$*" } # run in the world chroot, errors not fatal -CR0 ( ) { +CR0() { chroot "${NANO_WORLDDIR}" /bin/sh -c "$*" || true } -clean_build ( ) ( +clean_build() { pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})" if ! rm -xrf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then chflags -R noschg ${MAKEOBJDIRPREFIX}/ rm -xr ${MAKEOBJDIRPREFIX}/ fi -) +} -make_conf_build ( ) ( +make_conf_build() { pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" mkdir -p ${MAKEOBJDIRPREFIX} @@ -312,9 +311,9 @@ make_conf_build ( ) ( echo "${CONF_WORLD}" echo "${CONF_BUILD}" ) > ${NANO_MAKE_CONF_BUILD} -) +} -build_world ( ) ( +build_world() { pprint 2 "run buildworld" pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw" @@ -324,9 +323,9 @@ build_world ( ) ( cd "${NANO_SRC}" ${NANO_PMAKE} buildworld ) > ${MAKEOBJDIRPREFIX}/_.bw 2>&1 -) +} -build_kernel ( ) ( +build_kernel() { pprint 2 "build kernel ($NANO_KERNEL)" pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk" @@ -342,9 +341,9 @@ build_kernel ( ) ( cd "${NANO_SRC}" ${NANO_PMAKE} buildkernel ) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1 -) +} -clean_world ( ) ( +clean_world() { if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then pprint 2 "Clean and create object directory (${NANO_OBJ})" if ! rm -xrf ${NANO_OBJ}/ > /dev/null 2>&1 ; then @@ -361,9 +360,9 @@ clean_world ( ) ( fi mkdir -p "${NANO_WORLDDIR}" fi -) +} -make_conf_install ( ) ( +make_conf_install() { pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)" # Make sure we get all the global settings that NanoBSD wants @@ -377,9 +376,9 @@ make_conf_install ( ) ( echo METALOG=${NANO_METALOG} fi ) > ${NANO_MAKE_CONF_INSTALL} -) +} -install_world ( ) ( +install_world() { pprint 2 "installworld" pprint 3 "log: ${NANO_LOG}/_.iw" @@ -390,9 +389,9 @@ install_world ( ) ( ${NANO_MAKE} installworld DESTDIR="${NANO_WORLDDIR}" DB_FROM_SRC=yes chflags -R noschg "${NANO_WORLDDIR}" ) > ${NANO_LOG}/_.iw 2>&1 -) +} -install_etc ( ) ( +install_etc() { pprint 2 "install /etc" pprint 3 "log: ${NANO_LOG}/_.etc" @@ -405,9 +404,9 @@ install_etc ( ) ( # so they can spam it. cp /dev/null "${NANO_WORLDDIR}"/etc/make.conf ) > ${NANO_LOG}/_.etc 2>&1 -) +} -install_kernel ( ) ( +install_kernel() { pprint 2 "install kernel ($NANO_KERNEL)" pprint 3 "log: ${NANO_LOG}/_.ik" @@ -426,9 +425,9 @@ install_kernel ( ) ( ${NANO_MAKE} installkernel DESTDIR="${NANO_WORLDDIR}" DB_FROM_SRC=yes ) > ${NANO_LOG}/_.ik 2>&1 -) +} -native_xtools ( ) ( +native_xtools() { pprint 2 "Installing the optimized native build tools for cross env" pprint 3 "log: ${NANO_LOG}/_.native_xtools" @@ -441,13 +440,13 @@ native_xtools ( ) ( ${NANO_MAKE} native-xtools-install DESTDIR="${NANO_WORLDDIR}" ) > ${NANO_LOG}/_.native_xtools 2>&1 -) +} # # Run the requested set of early customization scripts, run before # buildworld. # -run_early_customize ( ) { +run_early_customize() { pprint 2 "run early customize scripts" for c in $NANO_EARLY_CUSTOMIZE do @@ -467,7 +466,7 @@ run_early_customize ( ) { # done an installworld, installed the etc files, installed the kernel # and tweaked them in the standard way. # -run_customize ( ) ( +run_customize() { pprint 2 "run customize scripts" for c in $NANO_CUSTOMIZE @@ -477,13 +476,13 @@ run_customize ( ) ( pprint 4 "`type $c`" ( set -o xtrace ; $c ) > ${NANO_LOG}/_.cust.$c 2>&1 done -) +} # # Run any last-minute customization commands after we've had a chance to # setup nanobsd, prune empty dirs from /usr, etc # -run_late_customize ( ) ( +run_late_customize() { pprint 2 "run late customize scripts" for c in $NANO_LATE_CUSTOMIZE do @@ -492,7 +491,7 @@ run_late_customize ( ) ( pprint 4 "`type $c`" ( set -o xtrace ; $c ) > ${NANO_LOG}/_.late_cust.$c 2>&1 done -) +} # # Hook called after we run all the late customize commands, but @@ -501,7 +500,7 @@ run_late_customize ( ) ( # have been recording their actions. It's not anticipated that # a user's cfg file would override this. # -fixup_before_diskimage ( ) ( +fixup_before_diskimage() { # Run the deduplication script that takes the metalog journal and # combines multiple entries for the same file (see source for # details). We take the extra step of removing the size keywords. This @@ -517,9 +516,9 @@ fixup_before_diskimage ( ) ( cat ${NANO_METALOG}.pre | ${NANO_TOOLS}/mtree-dedup.awk | \ sed -e 's/ size=[0-9][0-9]*//' | sort >> ${NANO_METALOG} fi -) +} -setup_nanobsd ( ) ( +setup_nanobsd() { pprint 2 "configure nanobsd setup" pprint 3 "log: ${NANO_LOG}/_.dl" @@ -564,9 +563,9 @@ setup_nanobsd ( ) ( tgt_dir2symlink tmp var/tmp ) > ${NANO_LOG}/_.dl 2>&1 -) +} -setup_nanobsd_etc ( ) ( +setup_nanobsd_etc() { pprint 2 "configure nanobsd /etc" ( @@ -623,18 +622,18 @@ EOF # Create directory for eventual /usr/local/etc contents mkdir -p etc/local ) -) +} -prune_usr ( ) ( +prune_usr() { # Remove all empty directories in /usr find "${NANO_WORLDDIR}"/usr -type d -depth -print | while read d do rmdir $d > /dev/null 2>&1 || true done -) +} -newfs_part ( ) ( +newfs_part() { local dev mnt lbl dev=$1 mnt=$2 @@ -642,15 +641,15 @@ newfs_part ( ) ( echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} mount -o async ${dev} ${mnt} -) +} # Convenient spot to work around any umount issues that your build environment # hits by overriding this method. -nano_umount ( ) ( +nano_umount() { umount ${1} -) +} -populate_slice ( ) ( +populate_slice() { local dev dir mnt lbl dev=$1 dir=$2 @@ -665,23 +664,23 @@ populate_slice ( ) ( fi df -i ${mnt} nano_umount ${mnt} -) +} -populate_cfg_slice ( ) ( +populate_cfg_slice() { populate_slice "$1" "$2" "$3" "$4" -) +} -populate_data_slice ( ) ( +populate_data_slice() { populate_slice "$1" "$2" "$3" "$4" -) +} -last_orders ( ) ( +last_orders() { # Redefine this function with any last orders you may have # after the build completed, for instance to copy the finished # image to a more convenient place: # cp ${NANO_DISKIMGDIR}/${NANO_IMG1NAME} /home/ftp/pub/nanobsd.disk true -) +} ####################################################################### # @@ -693,7 +692,7 @@ last_orders ( ) ( # Common Flash device geometries # -FlashDevice ( ) { +FlashDevice() { if [ -d ${NANO_TOOLS} ] ; then . ${NANO_TOOLS}/FlashDevice.sub else @@ -722,8 +721,8 @@ FlashDevice ( ) { # The generic-hdd device is preferred for flash devices larger than 1GB. # -UsbDevice ( ) { - a1=`echo $1 | tr '[:upper:]' '[:lower:]'` +UsbDevice() { + local a1=`echo $1 | tr '[:upper:]' '[:lower:]'` case $a1 in generic-fdd) NANO_HEADS=64 @@ -745,7 +744,7 @@ UsbDevice ( ) { ####################################################################### # Setup serial console -cust_comconsole ( ) ( +cust_comconsole() { # Enable getty on console sed -i "" -e '/^tty[du]0/s/off/onifconsole/' ${NANO_WORLDDIR}/etc/ttys @@ -754,32 +753,32 @@ cust_comconsole ( ) ( # Tell loader to use serial console early. echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config -) +} ####################################################################### # Allow root login via ssh -cust_allow_ssh_root ( ) ( +cust_allow_ssh_root() { sed -i "" -E 's/^#?PermitRootLogin.*/PermitRootLogin yes/' \ ${NANO_WORLDDIR}/etc/ssh/sshd_config -) +} ####################################################################### # Install the stuff under ./Files -cust_install_files ( ) ( +cust_install_files() { cd "${NANO_TOOLS}/Files" find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)/' | cpio ${CPIO_SYMLINK} -Ldumpv ${NANO_WORLDDIR} if [ -n "${NANO_CUST_FILES_MTREE}" -a -f ${NANO_CUST_FILES_MTREE} ]; then CR "mtree -eiU -p /" <${NANO_CUST_FILES_MTREE} fi -) +} ####################################################################### # Install packages from ${NANO_PACKAGE_DIR} -cust_pkgng ( ) ( +cust_pkgng() { mkdir -p ${NANO_WORLDDIR}/usr/local/etc local PKG_CONF="${NANO_WORLDDIR}/usr/local/etc/pkg.conf" local PKGCMD="env BATCH=YES ASSUME_ALWAYS_YES=YES PKG_DBDIR=${NANO_PKG_META_BASE}/pkg SIGNATURE_TYPE=none /usr/sbin/pkg" @@ -841,14 +840,14 @@ cust_pkgng ( ) ( umount ${NANO_WORLDDIR}/dev umount ${NANO_WORLDDIR}/_.p rm -xrf ${NANO_WORLDDIR}/_.p -) +} ####################################################################### # Convenience function: # Register all args as early customize function to run just before # build commences. -early_customize_cmd ( ) { +early_customize_cmd() { NANO_EARLY_CUSTOMIZE="$NANO_EARLY_CUSTOMIZE $*" } @@ -856,7 +855,7 @@ early_customize_cmd ( ) { # Convenience function: # Register all args as customize function. -customize_cmd ( ) { +customize_cmd() { NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*" } @@ -865,7 +864,7 @@ customize_cmd ( ) { # Register all args as late customize function to run just before # image creation. -late_customize_cmd ( ) { +late_customize_cmd() { NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*" } @@ -877,14 +876,14 @@ late_customize_cmd ( ) { # Progress Print # Print $2 at level $1. -pprint ( ) ( +pprint() { if [ "$1" -le $PPLEVEL ]; then runtime=$(( `date +%s` - $NANO_STARTTIME )) printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3 fi -) +} -usage ( ) { +usage() { ( echo "Usage: $0 [-BbfhIiKknpqvWwX] [-c config_file]" echo " -B suppress installs (both kernel and world)" @@ -911,7 +910,7 @@ usage ( ) { # Setup and Export Internal variables # -export_var ( ) { # Don't want a subshell +export_var() { var=$1 # Lookup value of the variable. eval val=\$$var @@ -920,8 +919,7 @@ export_var ( ) { # Don't want a subshell } # Call this function to set defaults _after_ parsing options. -# don't want a subshell otherwise variable setting is thrown away. -set_defaults_and_export ( ) { +set_defaults_and_export() { : ${NANO_OBJ:=/usr/obj/nanobsd.${NANO_NAME}${NANO_LAYOUT:+.${NANO_LAYOUT}}} : ${MAKEOBJDIRPREFIX:=${NANO_OBJ}} : ${NANO_DISKIMGDIR:=${NANO_OBJ}} diff --git a/tools/tools/nanobsd/embedded/common b/tools/tools/nanobsd/embedded/common index 4aecd3602f6f..132ca9e2ba5b 100644 --- a/tools/tools/nanobsd/embedded/common +++ b/tools/tools/nanobsd/embedded/common @@ -1,4 +1,4 @@ - +#!/bin/sh #- # Copyright (c) 2015 M. Warner Losh <imp@FreeBSD.org> # Copyright (c) 2010-2011 iXsystems, Inc. @@ -113,18 +113,18 @@ NANO_FAT_DIR=${NANO_LOG}/_.fat customize_cmd cust_allow_ssh_root -add_etc_make_conf ( ) ( +add_etc_make_conf() { touch ${NANO_WORLDDIR}/etc/make.conf -) +} customize_cmd add_etc_make_conf -cust_install_machine_files ( ) ( +cust_install_machine_files() { echo "cd ${NANO_CFG_BASE}/Files" cd ${NANO_CFG_BASE}/Files find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${NANO_WORLDDIR} -) +} customize_cmd cust_install_files -customize_cmd cust_install_machine_files +customize_cmd cust_install_machine_files CONF_BUILD=" LOCAL_XTOOL_DIRS=usr.bin/mkimg @@ -173,13 +173,13 @@ NANO_PACKAGE_ONLY=1 # Creates images for all the formats that use MBR / GPT # split later if the #ifdef soup gets too bad. -create_diskimage_gpt ( ) ( +create_diskimage_gpt() { pprint 2 "build diskimage gpt ${NANO_NAME}" create_diskimage_mbr $* -) +} -create_diskimage_mbr ( ) ( +create_diskimage_mbr() { local fmt @@ -314,7 +314,7 @@ create_diskimage_mbr ( ) ( rm -f ${out}.xz xz -9 --keep ${out} ) > ${NANO_LOG}/_.di 2>&1 -) +} die( ) { echo "$*" @@ -373,7 +373,7 @@ $var=$val" fi done -typical_embedded ( ) ( +typical_embedded() { # Need to create rc.conf before we copy over /etc to /conf/base/etc # so now's a good time. @@ -388,10 +388,10 @@ typical_embedded ( ) ( # Make sure that firstboot scripts run so growfs works. # Note: still some issues remvoing this XXX touch ${NANO_WORLDDIR}/firstboot -) +} customize_cmd typical_embedded -fix_pkg ( ) ( +fix_pkg() { chdir ${NANO_WORLDDIR} mkdir -p pkg mkdir -p pkg/db @@ -410,20 +410,20 @@ fix_pkg ( ) ( echo "./pkg/db type=dir uname=root gname=wheel mode=0755" echo "./pkg/tmp type=dir uname=root gname=wheel mode=0755" ) >> ${NANO_METALOG} -) +} customize_cmd fix_pkg -save_build ( ) ( +save_build() { VERSION_FILE=${NANO_WORLDDIR}/etc/version if [ "${SVNREVISION}" = "${REVISION}" ]; then echo "${NANO_NAME}" > "${VERSION_FILE}" else echo "${NANO_NAME} (${SVNREVISION})" > "${VERSION_FILE}" fi -) +} customize_cmd save_build -shrink_md_fbsize ( ) ( +shrink_md_fbsize() { # We have a lot of little files on our memory disks. Let's decrease # the block and frag size to fit more little files on them (this # halves our space requirement by ~50% on /etc and /var on 8.x -- @@ -431,12 +431,12 @@ shrink_md_fbsize ( ) ( # are 4 times larger). sed -i '' -e 's,-S -i 4096,-S -i 4096 -b 4096 -f 512,' \ ${NANO_WORLDDIR}/etc/rc.initdiskless -) +} customize_cmd shrink_md_fbsize customize_cmd cust_comconsole -dos_boot_part ( ) ( +dos_boot_part() { local d=/usr/local/share/u-boot/${NANO_BOOT_PKG} local f=${NANO_FAT_DIR} @@ -453,7 +453,7 @@ dos_boot_part ( ) ( # Now we need to copy over dtb files from the build. cp ${NANO_WORLDDIR}/boot/dtb/*.dtb . -) +} if [ -n "$NANO_BOOT_PKG" ]; then d=/usr/local/share/u-boot/${NANO_BOOT_PKG} @@ -468,7 +468,7 @@ if [ -n "$NANO_BOOT_PKG" ]; then customize_cmd dos_boot_part fi -product_custom ( ) ( +product_custom() { # not quite ready to tweak these in nopriv build if [ -z ${NANO_NOPRIV_BUILD} ]; then # Last second tweaks -- generally not needed @@ -480,7 +480,7 @@ product_custom ( ) ( chown root:wheel ${NANO_WORLDDIR}/ chown root:wheel ${NANO_WORLDDIR}/usr fi -) +} late_customize_cmd product_custom # @@ -615,19 +615,19 @@ esac NANO_SLICE_DATA= # Not included # These don't make any sense to this strategy, so stub them out. -calculate_partitioning ( ) ( -) +calculate_partitioning() { +} # These don't make any sense to this strategy, so stub them out. -create_code_slice ( ) ( -) +create_code_slice() { +} # Each major disk scheme has its own routine. Generally # this is for mbr, gpt, etc. These are generally are widely # shared, but some specialized formats won't be shared. -create_diskimage ( ) ( +create_diskimage() { eval create_diskimage_${NANO_DISK_SCHEME} -) +} # Set the path to the same path we use for buldworld to use latest mkimg NANO_TARGET=$(cd ${NANO_SRC}; ${NANO_MAKE} TARGET_ARCH=${NANO_ARCH} -V _TARGET) diff --git a/tools/tools/nanobsd/legacy.sh b/tools/tools/nanobsd/legacy.sh index 2f689212263e..cbe56d6f560c 100644 --- a/tools/tools/nanobsd/legacy.sh +++ b/tools/tools/nanobsd/legacy.sh @@ -34,7 +34,7 @@ # Functions and variable definitions used by the legacy nanobsd # image building system. -calculate_partitioning ( ) ( +calculate_partitioning() { echo $NANO_MEDIASIZE $NANO_IMAGES \ $NANO_SECTS $NANO_HEADS \ $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | @@ -90,9 +90,9 @@ calculate_partitioning ( ) ( } } ' > ${NANO_LOG}/_.partitioning -) +} -create_code_slice ( ) ( +create_code_slice() { pprint 2 "build code slice" pprint 3 "log: ${NANO_OBJ}/_.cs" @@ -142,10 +142,10 @@ create_code_slice ( ) ( trap - 1 2 15 EXIT ) > ${NANO_OBJ}/_.cs 2>&1 -) +} -create_diskimage ( ) ( +create_diskimage() { pprint 2 "build diskimage" pprint 3 "log: ${NANO_OBJ}/_.di" @@ -243,4 +243,4 @@ create_diskimage ( ) ( trap - 1 2 15 EXIT ) > ${NANO_LOG}/_.di 2>&1 -) +} diff --git a/tools/tools/nanobsd/rescue/common b/tools/tools/nanobsd/rescue/common index 15bf10f5e67d..a145a1ded32a 100644 --- a/tools/tools/nanobsd/rescue/common +++ b/tools/tools/nanobsd/rescue/common @@ -1,5 +1,5 @@ -# -# +#!/bin/sh + #NANO_SRC=$(pwd) #NANO_SRC=${NANO_SRC%/tools/tools/nanobsd/rescue} #NANO_OBJ=${NANO_SRC}/../nanobsd-builds/${NANO_NAME}/obj @@ -24,12 +24,12 @@ NANO_MD_BACKING=file # Options to put in make.conf during buildworld only CONF_BUILD=' ' -# Options to put in make.conf during installworld only +# Options to put in make.conf during installworld only CONF_INSTALL=' ' -# Options to put in make.conf during both build- & installworld. -CONF_WORLD=' -CFLAGS=-O -pipe +# Options to put in make.conf during both build- & installworld. +CONF_WORLD=' +CFLAGS=-O -pipe # We do not need these for rescue WITHOUT_TESTS=true WITHOUT_DEBUG_FILES=true @@ -71,9 +71,9 @@ customize_cmd cust_install_files #customize_cmd cust_pkgng -cust_etc_cfg () ( - cd ${NANO_WORLDDIR} -# mkdir -pv scratch +cust_etc_cfg() { + cd ${NANO_WORLDDIR} + # mkdir -pv scratch echo "hostname=\"rescue\"" > etc/rc.conf echo "font8x14=\"iso15-8x14\"" >> etc/rc.conf echo "font8x16=\"iso15-8x16\"" >> etc/rc.conf @@ -85,12 +85,12 @@ cust_etc_cfg () ( echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab echo "tmpfs /boot/zfs tmpfs rw,size=1048576,mode=777 0 0" >> etc/fstab echo "ports:/usr/ports /usr/ports nfs rw,noauto,noatime,bg,soft,intr,nfsv3 0 0" >> etc/fstab -# echo "/dev/ad1s1a /scratch ufs rw,noauto,noatime 0 0" >> etc/fstab + # echo "/dev/ad1s1a /scratch ufs rw,noauto,noatime 0 0" >> etc/fstab /usr/sbin/pwd_mkdb -d etc etc/master.passwd -) +} customize_cmd cust_etc_cfg -setup_nanobsd_etc ( ) ( +setup_nanobsd_etc() { pprint 2 "configure nanobsd /etc" ( cd ${NANO_WORLDDIR} @@ -102,8 +102,8 @@ setup_nanobsd_etc ( ) ( echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf mkdir -p cfg ) -) -last_orders () ( +} +last_orders() { pprint 2 "last orders" ( cd ${NANO_WORLDDIR} @@ -112,7 +112,7 @@ last_orders () ( echo "/dev/iso9660/${BIGLABEL} / cd9660 ro,noatime 0 0" > etc/fstab echo "tmpfs /boot/zfs tmpfs rw,size=1048576,mode=777 0 0" >> etc/fstab echo "ports:/usr/ports /usr/ports nfs rw,noauto,noatime,bg,soft,intr,nfsv3 0 0" >> etc/fstab -# echo "/dev/ad1s1a /scratch ufs rw,noauto,noatime 0 0" >> etc/fstab + # echo "/dev/ad1s1a /scratch ufs rw,noauto,noatime 0 0" >> etc/fstab rm -f conf/default/etc/remount touch conf/default/etc/.keepme touch conf/default/var/.keepme @@ -125,4 +125,4 @@ last_orders () ( -o label="${BIGLABEL}" -o publisher="RMX" \ -o bootimage="i386;_.w/boot/cdboot" -o no-emul-boot _.disk.iso _.w/ ) -) +} diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile index daefedbf8bca..178a1d083b79 100644 --- a/usr.bin/kyua/Makefile +++ b/usr.bin/kyua/Makefile @@ -10,7 +10,7 @@ KYUA_VERSION= 0.13 KYUA_SRCDIR= ${SRCTOP}/contrib/kyua .PATH: ${KYUA_SRCDIR} -PACKAGE= tests +PACKAGE= kyua PROG_CXX= kyua SRCS= main.cpp LIBADD= lutok sqlite3 util diff --git a/usr.bin/man/Makefile b/usr.bin/man/Makefile index 9c9098270735..9e47006cac0a 100644 --- a/usr.bin/man/Makefile +++ b/usr.bin/man/Makefile @@ -1,3 +1,5 @@ +PACKAGE= mandoc + SCRIPTS= man.sh LINKS= ${BINDIR}/man ${BINDIR}/manpath diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 0d04aad4e558..2c7c3ed85040 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -3,6 +3,8 @@ MANDOCDIR= ${SRCTOP}/contrib/mandoc .PATH: ${MANDOCDIR} +PACKAGE= mandoc + PROG= mandoc MAN= mandoc.1 mandoc.db.5 eqn.7 mandoc_char.7 tbl.7 man.7 mdoc.7 roff.7 MLINKS= mandoc.1 mdocml.1 @@ -16,6 +18,10 @@ LINKS= ${BINDIR}/mandoc ${BINDIR}/whatis \ .error MK_MAN_UTILS should be set to yes when bootstrapping .endif +FILESGROUPS= TRIGGERS +TRIGGERS= mandoc.ucl +TRIGGERSDIR= /usr/share/pkg/triggers + LIBMAN_SRCS= man.c \ man_macro.c \ man_validate.c diff --git a/usr.bin/mandoc/mandoc.ucl b/usr.bin/mandoc/mandoc.ucl new file mode 100644 index 000000000000..f320b6f547fd --- /dev/null +++ b/usr.bin/mandoc/mandoc.ucl @@ -0,0 +1,18 @@ +path_glob: "/usr/share/man/*" + +cleanup: { + type: lua + sandbox: false + script: <<EOD + os.remove("/usr/share/man/mandoc.db") +EOD +} + +trigger: { + type: lua + sandbox: false + script: <<EOD + print("Generating apropos(1) database...") + pkg.exec({"/usr/bin/makewhatis", "/usr/share/man"}) +EOD +} diff --git a/usr.bin/stat/stat.1 b/usr.bin/stat/stat.1 index 2996781fafa6..55e64de0767e 100644 --- a/usr.bin/stat/stat.1 +++ b/usr.bin/stat/stat.1 @@ -6,6 +6,8 @@ .\" This code is derived from software contributed to The NetBSD Foundation .\" by Andrew Brown and Jan Schaumann. .\" +.\" Copyright (c) 2025 Klara, Inc. +.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: @@ -27,7 +29,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 22, 2017 +.Dd September 9, 2025 .Dt STAT 1 .Os .Sh NAME @@ -36,7 +38,7 @@ .Nd display file status .Sh SYNOPSIS .Nm -.Op Fl FHLnq +.Op Fl FHhLnq .Op Fl f Ar format | Fl l | r | s | x .Op Fl t Ar timefmt .Op Ar @@ -129,6 +131,45 @@ and use instead of .Xr lstat 2 . This requires root privileges. +.It Fl h +For each file argument, print a line consisting of a comma-separated +list of holes, a space, and the file name. +Each hole is reported as its starting offset as a decimal number +followed by a hyphen and the ending offset (one less than the starting +offset of the data region that follows the hole) as a decimal number. +If the file ends in a hole, the ending offset of the final hole will +be one less than the size of the file. +Otherwise, the final entry in the list (indeed, the only entry in the +list, if the file is not sparse), is a single decimal number +corresponding to the size of the file, representing the virtual hole +at the end of the file. +.Pp +If the argument is a directory, instead of a list of holes, a single +number is printed, corresponding to the minimum hole size for that +directory as reported by +.Xr pathconf 2 , +followed by a space and the directory name. +.Pp +Please note that the only way to retrieve information about the holes +in a file is to open it and walk the list of holes and data regions +using +.Xr lseek 2 . +If the file is being modified by another process at the same time as +.Nm +is inspecting it, the result may be inconsistent. +.Pp +This option cannot be combined with the +.Fl F , +.Fl f , +.Fl H , +.Fl L , +.Fl l , +.Fl r , +.Fl s , +.Fl t , +or +.Fl x +options. .It Fl L Use .Xr stat 2 diff --git a/usr.bin/stat/stat.c b/usr.bin/stat/stat.c index 1fd8288728c1..0ed5d3ae5b53 100644 --- a/usr.bin/stat/stat.c +++ b/usr.bin/stat/stat.c @@ -7,6 +7,8 @@ * This code is derived from software contributed to The NetBSD Foundation * by Andrew Brown. * + * Copyright (c) 2025 Klara, Inc. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -47,18 +49,19 @@ __RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $" #endif /* HAVE_CONFIG_H */ #include <sys/param.h> -#include <sys/types.h> #include <sys/stat.h> #include <sys/mount.h> #include <ctype.h> #include <err.h> #include <errno.h> +#include <fcntl.h> #include <grp.h> #include <limits.h> #include <locale.h> #include <paths.h> #include <pwd.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -178,22 +181,24 @@ __RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $" #define SHOW_filename 'N' #define SHOW_sizerdev 'Z' -void usage(const char *); -void output(const struct stat *, const char *, - const char *, int, int); -int format1(const struct stat *, /* stat info */ +static void usage(const char *); +static void output(const struct stat *, const char *, const char *, int); +static int format1(const struct stat *, /* stat info */ const char *, /* the file name */ const char *, int, /* the format string itself */ char *, size_t, /* a place to put the output */ int, int, int, int, /* the parsed format */ int, int); -int hex2byte(const char [2]); +static int hex2byte(const char [2]); #if HAVE_STRUCT_STAT_ST_FLAGS -char *xfflagstostr(unsigned long); +static char *xfflagstostr(unsigned long); #endif +static int fdlistholes(int, const char *); +static int listholes(const char *); static const char *timefmt; static int linkfail; +static bool nonl; #define addchar(s, c, nl) \ do { \ @@ -205,20 +210,22 @@ int main(int argc, char *argv[]) { struct stat st; - int ch, rc, errs, am_readlink; - int lsF, fmtchar, usestat, nfs_handle, fn, nonl, quiet; - const char *statfmt, *options, *synopsis; char dname[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV; - fhandle_t fhnd; + const char *statfmt, *options, *synopsis; const char *file; + fhandle_t fhnd; + int ch, rc, errs, am_readlink, fn, fmtchar; + bool lsF, holes, usestat, nfs_handle, quiet; am_readlink = 0; - lsF = 0; + errs = 0; + lsF = false; fmtchar = '\0'; - usestat = 0; - nfs_handle = 0; - nonl = 0; - quiet = 0; + holes = false; + usestat = false; + nfs_handle = false; + nonl = false; + quiet = false; linkfail = 0; statfmt = NULL; timefmt = NULL; @@ -231,28 +238,35 @@ main(int argc, char *argv[]) fmtchar = 'f'; quiet = 1; } else { - options = "f:FHlLnqrst:x"; - synopsis = "[-FLnq] [-f format | -l | -r | -s | -x] " + options = "Ff:HhLlnqrst:x"; + synopsis = "[-FHhLnq] [-f format | -l | -r | -s | -x] " "[-t timefmt] [file|handle ...]"; } while ((ch = getopt(argc, argv, options)) != -1) switch (ch) { case 'F': - lsF = 1; + lsF = true; break; case 'H': - nfs_handle = 1; + nfs_handle = true; + break; + case 'h': + holes = true; break; case 'L': - usestat = 1; + usestat = true; break; case 'n': - nonl = 1; + nonl = true; + break; + case 't': + timefmt = optarg; break; case 'q': - quiet = 1; + quiet = true; break; + /* remaining cases are purposefully out of order */ case 'f': if (am_readlink) { statfmt = "%R"; @@ -269,9 +283,6 @@ main(int argc, char *argv[]) fmtchar, ch); fmtchar = ch; break; - case 't': - timefmt = optarg; - break; default: usage(synopsis); } @@ -280,6 +291,28 @@ main(int argc, char *argv[]) argv += optind; fn = 1; + if (holes) { + if (fmtchar || lsF || nfs_handle || usestat || timefmt) + usage(synopsis); + if (argc > 0) { + while (argc-- > 0) { + if (listholes(*argv) != 0) { + if (!quiet) + warn("%s", *argv); + errs++; + } + argv++; + } + } else { + if (fdlistholes(STDIN_FILENO, "stdin") != 0) { + if (!quiet) + warn("stdin"); + errs++; + } + } + exit(errs ? 1 : 0); + } + if (fmtchar == '\0') { if (lsF) fmtchar = 'l'; @@ -318,7 +351,6 @@ main(int argc, char *argv[]) if (timefmt == NULL) timefmt = TIME_FORMAT; - errs = 0; do { if (argc == 0) { if (fdevname_r(STDIN_FILENO, dname + @@ -361,8 +393,7 @@ main(int argc, char *argv[]) errno == ENOENT && (rc = lstat(file, &st)) == -1) errno = ENOENT; - } - else + } else rc = lstat(file, &st); } @@ -371,9 +402,8 @@ main(int argc, char *argv[]) linkfail = 1; if (!quiet) warn("%s", file); - } - else - output(&st, file, statfmt, fn, nonl); + } else + output(&st, file, statfmt, fn); argv++; argc--; @@ -387,7 +417,7 @@ main(int argc, char *argv[]) /* * fflagstostr() wrapper that leaks only once */ -char * +static char * xfflagstostr(unsigned long fflags) { static char *str = NULL; @@ -402,10 +432,9 @@ xfflagstostr(unsigned long fflags) } #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ -void +static void usage(const char *synopsis) { - (void)fprintf(stderr, "usage: %s %s\n", getprogname(), synopsis); exit(1); } @@ -413,9 +442,8 @@ usage(const char *synopsis) /* * Parses a format string. */ -void -output(const struct stat *st, const char *file, - const char *statfmt, int fn, int nonl) +static void +output(const struct stat *st, const char *file, const char *statfmt, int fn) { int flags, size, prec, ofmt, hilo, what; char buf[PATH_MAX + 4 + 1]; @@ -606,7 +634,7 @@ output(const struct stat *st, const char *file, /* * Arranges output according to a single parsed format substring. */ -int +static int format1(const struct stat *st, const char *file, const char *fmt, int flen, @@ -1073,7 +1101,7 @@ format1(const struct stat *st, (void)strcat(lfmt, "ll"); switch (ofmt) { case FMTF_DECIMAL: (void)strcat(lfmt, "d"); break; - case FMTF_OCTAL: (void)strcat(lfmt, "o"); break; + case FMTF_OCTAL: (void)strcat(lfmt, "o"); break; case FMTF_UNSIGNED: (void)strcat(lfmt, "u"); break; case FMTF_HEX: (void)strcat(lfmt, "x"); break; } @@ -1083,9 +1111,75 @@ format1(const struct stat *st, #define hex2nibble(c) (c <= '9' ? c - '0' : toupper(c) - 'A' + 10) -int +static int hex2byte(const char c[2]) { if (!(ishexnumber(c[0]) && ishexnumber(c[1]))) return -1; return (hex2nibble(c[0]) << 4) + hex2nibble(c[1]); } + +static int +fdlistholes(int fd, const char *fn) +{ + struct stat sb; + off_t pos = 0, off; + long l; + + if (fstat(fd, &sb) < 0) + return (-1); + if (S_ISDIR(sb.st_mode)) { + if ((l = fpathconf(fd, _PC_MIN_HOLE_SIZE)) < 0) + return (-1); + printf("%ld", l); + } else if (!S_ISREG(sb.st_mode)) { + errno = ESPIPE; + return (-1); + } else { + for (;;) { + if ((off = lseek(fd, pos, SEEK_HOLE)) < 0) { + if (errno != ENXIO) + return (-1); + /* + * This can only happen if the file was + * truncated while we were scanning it, or + * on the initial seek if the file is + * empty. Report the virtual hole at the + * end of the file at this position. + */ + off = pos; + } + printf("%jd", (intmax_t)off); + pos = off; + if ((off = lseek(fd, pos, SEEK_DATA)) < 0) { + if (errno != ENXIO) + return (-1); + /* + * There are no more data regions in the + * file, or it got truncated. However, we + * may not be at the end yet. + */ + if ((off = lseek(fd, 0, SEEK_END)) > pos) + printf("-%jd", (intmax_t)off - 1); + break; + } + printf("-%jd,", (intmax_t)off - 1); + pos = off; + } + } + printf(" %s", fn); + if (!nonl) + printf("\n"); + return (0); +} + +static int +listholes(const char *fn) +{ + int fd, ret; + + if ((fd = open(fn, O_RDONLY)) < 0) + return (-1); + ret = fdlistholes(fd, fn); + close(fd); + return (ret); +} diff --git a/usr.bin/stat/tests/stat_test.sh b/usr.bin/stat/tests/stat_test.sh index e75fd0c56490..afe698575034 100755 --- a/usr.bin/stat/tests/stat_test.sh +++ b/usr.bin/stat/tests/stat_test.sh @@ -1,6 +1,7 @@ # # Copyright (c) 2017 Dell EMC # All rights reserved. +# Copyright (c) 2025 Klara, Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -45,6 +46,76 @@ F_flag_body() atf_check -o match:'.* f\|' stat -Fn f } +atf_test_case h_flag cleanup +h_flag_head() +{ + atf_set "descr" "Verify the output format for -h" + atf_set "require.user" "root" +} +h_flag_body() +{ + # POSIX defines a hole as “[a] contiguous region of bytes + # within a file, all having the value of zero” and requires + # that “all seekable files shall have a virtual hole starting + # at the current size of the file” but says “it is up to the + # implementation to define when sparse files can be created + # and with what granularity for the size of holes”. It also + # defines a sparse file as “[a] file that contains more holes + # than just the virtual hole at the end of the file”. That's + # pretty much the extent of its discussion of holes, apart + # from the description of SEEK_HOLE and SEEK_DATA in the lseek + # manual page. In other words, there is no portable way to + # reliably create a hole in a file on any given file system. + # + # On FreeBSD, this test is likely to run on either tmpfs, ufs + # (ffs2), or zfs. Of those three, only tmpfs has predictable + # semantics and supports all possible configurations (the + # minimum hole size on zfs is variable for small files, and + # ufs will not allow a file to end in a hole). + atf_check mkdir mnt + atf_check mount -t tmpfs tmpfs mnt + cd mnt + + # For a directory, prints the minimum hole size, which on + # tmpfs is the system page size. + ps=$(sysctl -n hw.pagesize) + atf_check -o inline:"$((ps)) .\n" stat -h . + atf_check -o inline:"$((ps)) ." stat -hn . + + # For a file, prints a list of holes. + atf_check truncate -s 0 foo + atf_check -o inline:"0 foo" \ + stat -hn foo + atf_check truncate -s "$((ps))" foo + atf_check -o inline:"0-$((ps-1)) foo" \ + stat -hn foo + atf_check dd status=none if=/COPYRIGHT of=foo \ + oseek="$((ps))" bs=1 count=1 + atf_check -o inline:"0-$((ps-1)),$((ps+1)) foo" \ + stat -hn foo + atf_check truncate -s "$((ps*3))" foo + atf_check -o inline:"0-$((ps-1)),$((ps*2))-$((ps*3-1)) foo" \ + stat -hn foo + + # Test multiple files. + atf_check dd status=none if=/COPYRIGHT of=bar + sz=$(stat -f%z bar) + atf_check -o inline:"0-$((ps-1)),$((ps*2))-$((ps*3-1)) foo +$((sz)) bar +" \ + stat -h foo bar + + # For a device, fail. + atf_check -s exit:1 -e match:"/dev/null: Illegal seek" \ + stat -h /dev/null +} +h_flag_cleanup() +{ + if [ -d mnt ]; then + umount mnt || true + fi +} + atf_test_case l_flag l_flag_head() { @@ -233,6 +304,7 @@ atf_init_test_cases() { atf_add_test_case F_flag #atf_add_test_case H_flag + atf_add_test_case h_flag #atf_add_test_case L_flag #atf_add_test_case f_flag atf_add_test_case l_flag diff --git a/usr.sbin/bhyve/amd64/Makefile.inc b/usr.sbin/bhyve/amd64/Makefile.inc index 92e53433ff01..50a011ed4bfd 100644 --- a/usr.sbin/bhyve/amd64/Makefile.inc +++ b/usr.sbin/bhyve/amd64/Makefile.inc @@ -13,6 +13,7 @@ SRCS+= \ pci_gvt-d.c \ pci_lpc.c \ pci_passthru.c \ + pci_passthru_quirks.c \ pctestdev.c \ pm.c \ post.c \ diff --git a/usr.sbin/bhyve/pci_passthru_quirks.c b/usr.sbin/bhyve/pci_passthru_quirks.c new file mode 100644 index 000000000000..5ba0e674f311 --- /dev/null +++ b/usr.sbin/bhyve/pci_passthru_quirks.c @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Beckhoff Automation GmbH & Co. KG + * Author: Corvin Köhne <c.koehne@beckhoff.com> + */ + +#include <dev/pci/pcireg.h> + +#include <errno.h> + +#include "pci_passthru.h" + +#define PCI_VENDOR_NVIDIA 0x10DE + +static int +nvidia_gpu_probe(struct pci_devinst *const pi) +{ + struct passthru_softc *sc; + uint16_t vendor; + uint8_t class; + + sc = pi->pi_arg; + + vendor = pci_host_read_config(passthru_get_sel(sc), PCIR_VENDOR, 0x02); + if (vendor != PCI_VENDOR_NVIDIA) + return (ENXIO); + + class = pci_host_read_config(passthru_get_sel(sc), PCIR_CLASS, 0x01); + if (class != PCIC_DISPLAY) + return (ENXIO); + + return (0); +} + +static int +nvidia_gpu_init(struct pci_devinst *const pi, nvlist_t *const nvl __unused) +{ + pci_set_cfgdata8(pi, PCIR_INTPIN, 1); + + return (0); +} + +static struct passthru_dev nvidia_gpu = { + .probe = nvidia_gpu_probe, + .init = nvidia_gpu_init, +}; +PASSTHRU_DEV_SET(nvidia_gpu); diff --git a/usr.sbin/bsdinstall/scripts/pkgbase.in b/usr.sbin/bsdinstall/scripts/pkgbase.in index d123394c170e..c06a3f789791 100755 --- a/usr.sbin/bsdinstall/scripts/pkgbase.in +++ b/usr.sbin/bsdinstall/scripts/pkgbase.in @@ -77,37 +77,57 @@ end -- traditional tarball component selection dialog. local function select_components(components, options) local descriptions = { - kernel_dbg = "Kernel debug info", - base_dbg = "Base system debug info", - src = "System source tree", - tests = "Test suite", - lib32 = "32-bit compatibility libraries", - lib32_dbg = "32-bit compatibility libraries debug info", + ["kernel-dbg"] = "Debug symbols for the kernel", + ["devel"] = "C/C++ compilers and related utilities", + ["base"] = "The complete base system (includes devel)", + ["src"] = "System source tree", + ["tests"] = "Test suite", + ["lib32"] = "32-bit compatibility libraries", + ["debug"] = "Debug symbols for the selected components", } + + -- These defaults match what the non-pkgbase installer selects + -- by default. local defaults = { - kernel_dbg = "on", - base_dbg = "off", - src = "off", - tests = "off", - lib32 = "on", - lib32_dbg = "off", + ["base"] = "on", + ["kernel-dbg"] = "on", } + -- Enable compat sets by default. + for compat in all_libcompats:gmatch("%S+") do + defaults["lib" .. compat] = "on" + end -- Sorting the components is necessary to ensure that the ordering is -- consistent in the UI. local sorted_components = {} for component, _ in pairs(components) do - table.insert(sorted_components, component) + -- Decide which sets we want to offer to the user: + -- + -- "minimal" is not offered since it's always included. + -- + -- "-dbg" sets are never offered, because those are handled + -- via the "debug" component. + -- + -- "kernels" is never offered because we only want one kernel, + -- which is handled separately. + -- + -- Sets whose name ends in "-jail" are intended for jails, and + -- are only offered if no_kernel is set. + if not component:match("^minimal") and + not component:match("%-dbg$") and + not (component == "kernels") and + not (not options.no_kernel and component:match("%-jail$")) then + table.insert(sorted_components, component) + end end table.sort(sorted_components) local checklist_items = {} for _, component in ipairs(sorted_components) do - if component ~= "base" and component ~= "kernel" and - not (component == "kernel_dbg" and options.no_kernel) and - #components[component] > 0 then - local description = descriptions[component] or "''" - local default = defaults[component] or "off" + if component ~= "kernel" and not + (component == "kernel-dbg" and options.no_kernel) then + local description = descriptions[component] or "" + local default = defaults[component] or "off" table.insert(checklist_items, component) table.insert(checklist_items, description) table.insert(checklist_items, default) @@ -120,7 +140,10 @@ local function select_components(components, options) "--nocancel", "--disable-esc", "--separate-output", - "--checklist", "Choose optional system components to install:", + "--checklist", + "A minimal set of packages suitable for a multi-user system ".. + "is always installed. Select additional packages you wish ".. + "to install:", "0", "0", "0", -- autosize } append_list(bsddialog_args, checklist_items) @@ -132,10 +155,16 @@ local function select_components(components, options) -- hopefully useful stack trace. assert(exit_code == 0) - local selected = {"base"} + -- Always install the minimal set, since it's required for the system + -- to work. The base set depends on minimal, but it's fine to install + -- both, and this way the user can remove the base set without pkg + -- autoremove then trying to remove minimal. + local selected = {"minimal"} + if not options.no_kernel then table.insert(selected, "kernel") end + for component in output:gmatch("[^\n]+") do table.insert(selected, component) end @@ -145,26 +174,21 @@ end -- Returns a list of pkgbase packages selected by the user local function select_packages(pkg, options) + -- These are the components which aren't generated automatically from + -- package sets. local components = { - kernel = {}, - kernel_dbg = {}, - base = {}, - base_dbg = {}, - src = {}, - tests = {}, + ["kernel"] = {}, + ["kernel-dbg"] = {}, + ["debug"] = {}, } - for compat in all_libcompats:gmatch("%S+") do - components["lib" .. compat] = {} - components["lib" .. compat .. "_dbg"] = {} - end - local rquery = capture(pkg .. "rquery -U -r FreeBSD-base %n") for package in rquery:gmatch("[^\n]+") do - if package == "FreeBSD-src" or package:match("^FreeBSD%-src%-.*") then - table.insert(components["src"], package) - elseif package == "FreeBSD-tests" or package:match("^FreeBSD%-tests%-.*") then - table.insert(components["tests"], package) + local setname = package:match("^FreeBSD%-set%-(.+)$") + + if setname then + components[setname] = components[setname] or {} + table.insert(components[setname], package) elseif package:match("^FreeBSD%-kernel%-.*") and package ~= "FreeBSD-kernel-man" then @@ -172,40 +196,51 @@ local function select_packages(pkg, options) if package == "FreeBSD-kernel-generic" then table.insert(components["kernel"], package) elseif package == "FreeBSD-kernel-generic-dbg" then - table.insert(components["kernel_dbg"], package) - end - elseif package:match(".*%-dbg$") then - table.insert(components["base_dbg"], package) - else - local found = false - for compat in all_libcompats:gmatch("%S+") do - if package:match(".*%-dbg%-lib" .. compat .. "$") then - table.insert(components["lib" .. compat .. "_dbg"], package) - found = true - break - elseif package:match(".*%-lib" .. compat .. "$") then - table.insert(components["lib" .. compat], package) - found = true - break - end - end - if not found then - table.insert(components["base"], package) + table.insert(components["kernel-dbg"], package) end end end - -- Don't assert the existence of dbg, tests, and src packages here. If using - -- a custom local repository with BSDINSTALL_PKG_REPOS_DIR we shouldn't - -- require it to have all packages. + + -- Assert that both a kernel and the "minimal" set are available, since + -- those are both required to install a functional system. Don't worry + -- if other sets are missing (e.g. base or src), which might happen + -- when using custom install media. assert(#components["kernel"] == 1) - assert(#components["base"] > 0) + assert(#components["minimal"] == 1) - local selected = {} - for _, component in ipairs(select_components(components, options)) do - append_list(selected, components[component]) + -- Prompt the user for what to install. + local selected = select_components(components, options) + + -- Determine if the "debug" component was selected. + local debug = false + for _, component in ipairs(selected) do + if component == "debug" then + debug = true + break + end end - return selected + local packages = {} + for _, component in ipairs(selected) do + local pkglist = components[component] + append_list(packages, pkglist) + + -- If the debug component was selected, install the -dbg + -- package for each set. We have to check if the dbg set + -- actually exists, because some sets (src, tests) don't + -- have a -dbg subpackage. + for _, c in ipairs(pkglist) do + local setname = c:match("^FreeBSD%-set%-(.*)$") + if debug and setname then + local dbgset = setname.."-dbg" + if components[dbgset] then + append_list(packages, components[dbgset]) + end + end + end + end + + return packages end local function parse_options() diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index aa05faa7d3dd..5fbf56ea59ac 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -69,7 +69,7 @@ f_include $BSDCFG_SHARE/variable.subr : ${ZFSBOOT_VDEV_TYPE:=stripe} # -# Should we use sysctl(8) vfs.zfs.min_auto_ashift=12 to force 4K sectors? +# Should we use sysctl(8) vfs.zfs.vdev.min_auto_ashift=12 to force 4K sectors? # : ${ZFSBOOT_FORCE_4K_SECTORS=1} @@ -221,7 +221,7 @@ PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\"" PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"' SHELL_TRUNCATE=':> "%s"' SWAP_GMIRROR_LABEL='gmirror label swap %s' -SYSCTL_ZFS_MIN_ASHIFT_12='sysctl vfs.zfs.min_auto_ashift=12' +SYSCTL_ZFS_MIN_ASHIFT_12='sysctl vfs.zfs.vdev.min_auto_ashift=12' UMOUNT='umount "%s"' ZFS_CREATE_WITH_OPTIONS='zfs create %s "%s"' ZFS_MOUNT='zfs mount "%s"' @@ -255,7 +255,7 @@ msg_encrypt_disks="Encrypt Disks?" msg_encrypt_disks_help="Use geli(8) to encrypt all data partitions" msg_error="Error" msg_force_4k_sectors="Force 4K Sectors?" -msg_force_4k_sectors_help="Align partitions to 4K sector boundries and set vfs.zfs.min_auto_ashift=12" +msg_force_4k_sectors_help="Align partitions to 4K sector boundries and set vfs.zfs.vdev.min_auto_ashift=12" msg_freebsd_installer="$OSNAME Installer" msg_geli_password="Enter a strong passphrase, used to protect your encryption keys. You will be required to enter this passphrase each time the system is booted" msg_geli_setup="Initializing encryption on selected disks,\n this will take several seconds per disk" @@ -1099,7 +1099,7 @@ zfs_create_boot() # f_dprintf "$funcname: Preparing disk partitions for ZFS pool..." - # Force 4K sectors using vfs.zfs.min_auto_ashift=12 + # Force 4K sectors using vfs.zfs.vdev.min_auto_ashift=12 if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then f_dprintf "$funcname: With 4K sectors..." f_eval_catch $funcname sysctl "$SYSCTL_ZFS_MIN_ASHIFT_12" \ @@ -1382,7 +1382,7 @@ zfs_create_boot() if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then f_eval_catch $funcname echo "$ECHO_APPEND" \ - 'vfs.zfs.min_auto_ashift=12' \ + 'vfs.zfs.vdev.min_auto_ashift=12' \ $BSDINSTALL_TMPETC/sysctl.conf.zfs || return $FAILURE fi diff --git a/usr.sbin/cpucontrol/amd10h.c b/usr.sbin/cpucontrol/amd10h.c index 4fda44f0b797..9fc861fe5914 100644 --- a/usr.sbin/cpucontrol/amd10h.c +++ b/usr.sbin/cpucontrol/amd10h.c @@ -93,7 +93,7 @@ amd10h_update(const struct ucode_update_params *params) size_t fw_size; size_t selected_size; uint32_t revision; - uint32_t new_rev; + uint32_t new_rev, old_rev; uint32_t signature; int devfd; int error; @@ -121,15 +121,16 @@ amd10h_update(const struct ucode_update_params *params) WARN(0, "ioctl(%s)", dev); goto done; } - revision = (uint32_t)msrargs.data; + old_rev = revision = (uint32_t)msrargs.data; - selected_fw = ucode_amd_find(path, signature, revision, fw_image, + selected_fw = ucode_amd_find(path, signature, &revision, fw_image, fw_size, &selected_size); if (selected_fw != NULL) { WARNX(1, "selected ucode size is %zu", selected_size); - fprintf(stderr, "%s: updating cpu %s to revision %#x... ", - path, dev, revision); + fprintf(stderr, + "%s: updating cpu %s from rev %#x to rev %#x... ", + path, dev, old_rev, revision); args.data = __DECONST(void *, selected_fw); args.size = selected_size; diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 index 421aa9babb4c..d44b7f66a64e 100644 --- a/usr.sbin/jail/jail.8 +++ b/usr.sbin/jail/jail.8 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 7, 2025 +.Dd September 15, 2025 .Dt JAIL 8 .Os .Sh NAME @@ -702,15 +702,15 @@ The super-user will be disabled automatically if its parent system has it disabled. The super-user is enabled by default. .It Va allow.extattr -Allow privileged process in the jail to manipulate filesystem extended +Allow privileged processes in the jail to manipulate filesystem extended attributes in the system namespace. .It Va allow.adjtime -Allow privileged process in the jail to slowly adjusting global operating system +Allow privileged processes in the jail to slowly adjusting global operating system time. For example through utilities like .Xr ntpd 8 . .It Va allow.settime -Allow privileged process in the jail to set global operating system data +Allow privileged processes in the jail to set global operating system data and time. For example through utilities like .Xr date 1 . @@ -719,6 +719,17 @@ This permission includes also .It Va allow.routing Allow privileged process in the non-VNET jail to modify the system routing table. +.It Va allow.setaudit +Allow privileged processes in the jail to set +.Xr audit 4 +session state using +.Xr setaudit 2 +and related system calls. +This is useful, for example, for allowing a jailed +.Xr sshd 8 +to set the audit user ID for an authenticated session. +However, it gives jailed processes the ability to modify or disable audit +session state, so should be configured with care. .El .El .Pp diff --git a/usr.sbin/jail/tests/jail_basic_test.sh b/usr.sbin/jail/tests/jail_basic_test.sh index 6802da7b049a..c781eed78756 100755 --- a/usr.sbin/jail/tests/jail_basic_test.sh +++ b/usr.sbin/jail/tests/jail_basic_test.sh @@ -306,6 +306,25 @@ param_consistency_cleanup() fi } +atf_test_case "setaudit" +setaudit_head() +{ + atf_set descr 'Test that setaudit works in a jail when configured with allow.setaudit' + atf_set require.user root + atf_set require.progs setaudit +} + +setaudit_body() +{ + # Try to modify the audit mask within a jail without + # allow.setaudit configured. + atf_check -s not-exit:0 -o empty -e not-empty jail -c name=setaudit_jail \ + command=setaudit -m fr ls / + # The command should succeed if allow.setaudit is configured. + atf_check -s exit:0 -o ignore -e empty jail -c name=setaudit_jail \ + allow.setaudit command=setaudit -m fr ls / +} + atf_init_test_cases() { atf_add_test_case "basic" @@ -314,4 +333,5 @@ atf_init_test_cases() atf_add_test_case "commands" atf_add_test_case "jid_name_set" atf_add_test_case "param_consistency" + atf_add_test_case "setaudit" } diff --git a/usr.sbin/moused/moused/moused.8 b/usr.sbin/moused/moused/moused.8 index 96feeda336c9..2483f8a04b2a 100644 --- a/usr.sbin/moused/moused/moused.8 +++ b/usr.sbin/moused/moused/moused.8 @@ -49,7 +49,7 @@ .Op Fl m Ar N=M .Op Fl w Ar N .Op Fl z Ar target -.Op Fl t Ar mousetype +.Op Fl t Ar interfacetype .Op Fl l Ar level .Op Fl 3 Op Fl E Ar timeout .Op Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after @@ -329,9 +329,32 @@ or .Ar high . This option may not be supported by all the device. .It Fl t Ar type -Ignored. -Used for compatibiliy with legacy -.Nm . +Force the interface type of the mouse attached to the port. +You may explicitly specify a type listed below, or use +.Ar auto +to let the +.Nm +utility automatically select an appropriate protocol for the given +character device. +If you entirely omit this option in the command line, +.Fl t Ar auto +is assumed. +.Pp +Valid types for this option are listed below. +.Bl -tag -compact -width systemmouse +.It Ar evdev +Input event device usualy residing in +.Pa /dev/input . +.It Ar sysmouse +Traditional protocol used by e.g. +.Xr ums 4 +and +.Xr psm 4 +drivers. +.El +.Pp +Note that this option restricts usage of the given port rather then gives +a hint. .It Fl q Ar config Path to configuration file. .It Fl Q Ar quirks diff --git a/usr.sbin/moused/moused/moused.c b/usr.sbin/moused/moused/moused.c index acd6e5223685..36cb8cc27eab 100644 --- a/usr.sbin/moused/moused/moused.c +++ b/usr.sbin/moused/moused/moused.c @@ -448,6 +448,7 @@ static const char *config_file = CONFDIR "/moused.conf"; #endif static const char *quirks_path = QUIRKSDIR; static struct quirks_context *quirks; +static enum device_if force_if = DEVICE_IF_UNKNOWN; static int opt_rate = 0; static int opt_resolution = MOUSE_RES_UNKNOWN; @@ -529,7 +530,8 @@ main(int argc, char *argv[]) struct rodent *r; pid_t mpid; int c; - int i; + u_int i; + int n; u_long ul; char *errstr; @@ -552,26 +554,26 @@ main(int argc, char *argv[]) break; case 'a': - i = sscanf(optarg, "%lf,%lf", &opt_accelx, &opt_accely); - if (i == 0) { + n = sscanf(optarg, "%lf,%lf", &opt_accelx, &opt_accely); + if (n == 0) { warnx("invalid linear acceleration argument " "'%s'", optarg); usage(); } - if (i == 1) + if (n == 1) opt_accely = opt_accelx; break; case 'A': opt_exp_accel = true; - i = sscanf(optarg, "%lf,%lf", &opt_expoaccel, + n = sscanf(optarg, "%lf,%lf", &opt_expoaccel, &opt_expoffset); - if (i == 0) { + if (n == 0) { warnx("invalid exponential acceleration " "argument '%s'", optarg); usage(); } - if (i == 1) + if (n == 1) opt_expoffset = 1.0; break; @@ -646,8 +648,19 @@ main(int argc, char *argv[]) break; case 't': - if (strcmp(optarg, "auto") != 0) - warnx("ignore mouse type `%s'", optarg); + if (strcmp(optarg, "auto") == 0) { + force_if = DEVICE_IF_UNKNOWN; + break; + } + for (i = 0; i < nitems(rifs); i++) + if (strcmp(optarg, rifs[i].name) == 0) { + force_if = i; + break; + } + if (i == nitems(rifs)) { + warnx("no such interface type `%s'", optarg); + usage(); + } break; case 'w': @@ -1224,7 +1237,7 @@ usage(void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", "usage: moused [-dfg] [-I file] [-F rate] [-r resolution]", " [-VH [-U threshold]] [-a X[,Y]] [-C threshold] [-m N=M] [-w N]", - " [-z N] [-t <mousetype>] [-l level] [-3 [-E timeout]]", + " [-z N] [-t <interfacetype>] [-l level] [-3 [-E timeout]]", " [-T distance[,time[,after]]] -p <port> [-q config] [-Q quirks]", " moused [-d] -i <port|if|type|model|all> -p <port>"); exit(1); @@ -1338,9 +1351,11 @@ r_identify_if(int fd) { int dummy; - if (ioctl(fd, EVIOCGVERSION, &dummy) >= 0) + if ((force_if == DEVICE_IF_UNKNOWN || force_if == DEVICE_IF_EVDEV) && + ioctl(fd, EVIOCGVERSION, &dummy) >= 0) return (DEVICE_IF_EVDEV); - if (ioctl(fd, MOUSE_GETLEVEL, &dummy) >= 0) + if ((force_if == DEVICE_IF_UNKNOWN || force_if == DEVICE_IF_SYSMOUSE) && + ioctl(fd, MOUSE_GETLEVEL, &dummy) >= 0) return (DEVICE_IF_SYSMOUSE); return (DEVICE_IF_UNKNOWN); } diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c index 6e6f40c3ff64..cbca8ec20941 100644 --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -1059,6 +1059,9 @@ ifinfo(char *ifname, int argc, char **argv) #ifdef ND6_IFF_NO_PREFER_IFACE SETFLAG("no_prefer_iface", ND6_IFF_NO_PREFER_IFACE); #endif +#ifdef ND6_IFF_STABLEADDR + SETFLAG("stableaddr", ND6_IFF_STABLEADDR); +#endif SETVALUE("basereachable", ND.basereachable); SETVALUE("retrans", ND.retrans); SETVALUE("curhlim", ND.chlim); @@ -1144,6 +1147,10 @@ ifinfo(char *ifname, int argc, char **argv) if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL)) xo_emit("{l:%s} ", "auto_linklocal"); #endif +#ifdef ND6_IFF_STABLEADDR + if ((ND.flags & ND6_IFF_STABLEADDR)) + xo_emit("{l:%s} ", "stableaddr"); +#endif #ifdef ND6_IFF_NO_PREFER_IFACE if ((ND.flags & ND6_IFF_NO_PREFER_IFACE)) xo_emit("{l:%s} ", "no_prefer_iface"); diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c index 3dee8f7c43ac..979323d64342 100644 --- a/usr.sbin/pw/cpdir.c +++ b/usr.sbin/pw/cpdir.c @@ -36,53 +36,52 @@ #include "pw.h" void -copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, +copymkdir(int rootfd, char const *dir, int skelfd, mode_t mode, uid_t uid, gid_t gid, int flags) { - char *p, lnk[MAXPATHLEN], copybuf[4096]; - int len, homefd, srcfd, destfd; + char *p, lnk[MAXPATHLEN]; + int len, srcfd, destfd; ssize_t sz; struct stat st; struct dirent *e; DIR *d; + mode_t pumask; if (*dir == '/') dir++; + pumask = umask(0); + umask(pumask); + if (mkdirat(rootfd, dir, mode) != 0) { - mode_t pumask; if (errno != EEXIST) { warn("mkdir(%s)", dir); return; } - pumask = umask(0); - umask(pumask); - if (fchmodat(rootfd, dir, mode & ~pumask, AT_SYMLINK_NOFOLLOW) == -1) warn("chmod(%s)", dir); } - if (fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW) == -1) warn("chown(%s)", dir); - if (flags > 0 && chflagsat(rootfd, dir, flags, AT_SYMLINK_NOFOLLOW) == -1) warn("chflags(%s)", dir); + metalog_emit(dir, (mode | S_IFDIR) & ~pumask, uid, gid, flags); if (skelfd == -1) return; - homefd = openat(rootfd, dir, O_DIRECTORY); if ((d = fdopendir(skelfd)) == NULL) { close(skelfd); - close(homefd); return; } while ((e = readdir(d)) != NULL) { + char path[MAXPATHLEN]; + if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; @@ -92,19 +91,32 @@ copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, if (strncmp(p, "dot.", 4) == 0) /* Conversion */ p += 3; + (void)snprintf(path, sizeof(path), "%s/%s", dir, p); if (S_ISDIR(st.st_mode)) { - copymkdir(homefd, p, openat(skelfd, e->d_name, O_DIRECTORY), - st.st_mode & _DEF_DIRMODE, uid, gid, st.st_flags); + int fd; + + fd = openat(skelfd, e->d_name, O_DIRECTORY); + if (fd == -1) { + warn("openat(%s)", e->d_name); + continue; + } + copymkdir(rootfd, path, fd, st.st_mode & _DEF_DIRMODE, + uid, gid, st.st_flags); continue; } if (S_ISLNK(st.st_mode) && - (len = readlinkat(skelfd, e->d_name, lnk, sizeof(lnk) -1)) + (len = readlinkat(skelfd, e->d_name, lnk, sizeof(lnk) - 1)) != -1) { lnk[len] = '\0'; - symlinkat(lnk, homefd, p); - fchownat(homefd, p, uid, gid, AT_SYMLINK_NOFOLLOW); + if (symlinkat(lnk, rootfd, path) != 0) + warn("symlink(%s)", path); + else if (fchownat(rootfd, path, uid, gid, + AT_SYMLINK_NOFOLLOW) != 0) + warn("chown(%s)", path); + metalog_emit_symlink(path, lnk, st.st_mode & ~pumask, + uid, gid); continue; } @@ -113,22 +125,29 @@ copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, if ((srcfd = openat(skelfd, e->d_name, O_RDONLY)) == -1) continue; - destfd = openat(homefd, p, O_RDWR | O_CREAT | O_EXCL, + destfd = openat(rootfd, path, O_RDWR | O_CREAT | O_EXCL, st.st_mode); if (destfd == -1) { close(srcfd); continue; } - while ((sz = read(srcfd, copybuf, sizeof(copybuf))) > 0) - write(destfd, copybuf, sz); + do { + sz = copy_file_range(srcfd, NULL, destfd, NULL, + SSIZE_MAX, 0); + } while (sz > 0); + if (sz < 0) + warn("copy_file_range"); close(srcfd); /* * Propagate special filesystem flags */ - fchown(destfd, uid, gid); - fchflags(destfd, st.st_flags); + if (fchown(destfd, uid, gid) != 0) + warn("chown(%s)", p); + if (fchflags(destfd, st.st_flags) != 0) + warn("chflags(%s)", p); + metalog_emit(path, st.st_mode & ~pumask, uid, gid, st.st_flags); close(destfd); } closedir(d); diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8 index 5eae810b6732..f6d9ebca6308 100644 --- a/usr.sbin/pw/pw.8 +++ b/usr.sbin/pw/pw.8 @@ -30,6 +30,7 @@ .Nd create, remove, modify & display system users and groups .Sh SYNOPSIS .Nm +.Op Fl M Ar metalog .Op Fl R Ar rootdir .Op Fl V Ar etcdir .Cm useradd @@ -464,6 +465,21 @@ option, bearing the name of the new account. This can be overridden by the .Fl d option on the command line, if desired. +.It Fl M Ar metalog +Specify a path to a +.Xr mtree 5 +metalog file. +.Nm +will add entries for all files added to a user's home directory. +This is useful when building images as a non-root user, as the +metalog can be used as input to +.Xr tar 1 +or +.Xr makefs 8 . +Note that this option must precede the +.Ql useradd +string on the command line, otherwise it will be interpreted as the mode +option. .It Fl M Ar mode Create the user's home directory with the specified .Ar mode , diff --git a/usr.sbin/pw/pw.c b/usr.sbin/pw/pw.c index a4c95258f3bb..7cb5dd160e12 100644 --- a/usr.sbin/pw/pw.c +++ b/usr.sbin/pw/pw.c @@ -132,7 +132,11 @@ main(int argc, char *argv[]) while (argc > 1) { if (*argv[1] == '-') { /* - * Special case, allow pw -V<dir> <operation> [args] for scripts etc. + * Special case, allow pw -V<dir> <operation> [args] for + * scripts etc. + * + * The -M option before the keyword is handled + * differently from -M after a keyword. */ arg = argv[1][1]; if (arg == 'V' || arg == 'R') { @@ -143,12 +147,13 @@ main(int argc, char *argv[]) optarg = &argv[1][2]; if (*optarg == '\0') { if (stat(argv[2], &st) != 0) - errx(EX_OSFILE, \ + errx(EX_OSFILE, "no such directory `%s'", argv[2]); if (!S_ISDIR(st.st_mode)) - errx(EX_OSFILE, "`%s' not a " - "directory", argv[2]); + errx(EX_OSFILE, + "`%s' not a directory", + argv[2]); optarg = argv[2]; ++argv; --argc; @@ -163,10 +168,26 @@ main(int argc, char *argv[]) "%s%s", optarg, arg == 'R' ? _PATH_PWD : ""); conf.altroot = true; + } else if (mode == -1 && which == -1 && arg == 'M') { + int fd; + + optarg = &argv[1][2]; + if (*optarg == '\0') { + optarg = argv[2]; + ++argv; + --argc; + } + fd = open(optarg, + O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, + 0644); + if (fd == -1) + errx(EX_OSERR, + "Cannot open metalog `%s'", + optarg); + conf.metalog = fdopen(fd, "ae"); } else break; - } - else if (mode == -1 && (tmp = getindex(Modes, argv[1])) != -1) + } else if (mode == -1 && (tmp = getindex(Modes, argv[1])) != -1) mode = tmp; else if (which == -1 && (tmp = getindex(Which, argv[1])) != -1) which = tmp; @@ -178,7 +199,7 @@ main(int argc, char *argv[]) } else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL) cmdhelp(mode, which); else if (which != -1 && mode != -1) - arg1 = argv[1]; + arg1 = argv[1]; else errx(EX_USAGE, "unknown keyword `%s'", argv[1]); ++argv; @@ -195,6 +216,10 @@ main(int argc, char *argv[]) if (conf.rootfd == -1) errx(EXIT_FAILURE, "Unable to open '%s'", conf.rootdir); + if (conf.metalog != NULL && (which != W_USER || mode != M_ADD)) + errx(EXIT_FAILURE, + "metalog can only be specified with 'useradd'"); + return (cmdfunc[which][mode](argc, argv, arg1)); } @@ -233,10 +258,11 @@ cmdhelp(int mode, int which) static const char *help[W_NUM][M_NUM] = { { - "usage: pw useradd [name] [switches]\n" + "usage: pw [-M metalog] useradd [name] [switches]\n" "\t-V etcdir alternate /etc location\n" "\t-R rootdir alternate root directory\n" "\t-C config configuration file\n" + "\t-M metalog mtree file, must precede 'useradd'\n" "\t-q quiet operation\n" " Adding users:\n" "\t-n name login name\n" @@ -257,8 +283,6 @@ cmdhelp(int mode, int which) "\t-Y update NIS maps\n" "\t-N no update\n" " Setting defaults:\n" - "\t-V etcdir alternate /etc location\n" - "\t-R rootdir alternate root directory\n" "\t-D set user defaults\n" "\t-b dir default home root dir\n" "\t-e period default expiry period\n" diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h index c3725693f91d..ceb843d79503 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -70,6 +70,11 @@ struct userconf *get_userconfig(const char *cfg); struct userconf *read_userconfig(char const * file); int write_userconfig(struct userconf *cnf, char const * file); +void metalog_emit(const char *path, mode_t mode, uid_t uid, gid_t gid, + int flags); +void metalog_emit_symlink(const char *path, const char *target, mode_t mode, + uid_t uid, gid_t gid); + int pw_group_add(int argc, char **argv, char *name); int pw_group_del(int argc, char **argv, char *name); int pw_group_mod(int argc, char **argv, char *name); diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index 8a9a4342f5ef..413eac4882cc 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -86,10 +86,13 @@ mkdir_home_parents(int dfd, const char *dir) { struct stat st; char *dirs, *tmp; + mode_t pumask; + + pumask = umask(0); + umask(pumask); if (*dir != '/') errx(EX_DATAERR, "invalid base directory for home '%s'", dir); - dir++; if (fstatat(dfd, dir, &st, 0) != -1) { @@ -115,7 +118,14 @@ mkdir_home_parents(int dfd, const char *dir) *tmp = '\0'; if (fstatat(dfd, dirs, &st, 0) == -1) { if (mkdirat(dfd, dirs, _DEF_DIRMODE) == -1) - err(EX_OSFILE, "'%s' (home parent) is not a directory", dirs); + err(EX_OSFILE, + "'%s' (home parent) is not a directory", + dirs); + if (fchownat(dfd, dirs, 0, 0, 0) != 0) + warn("chown(%s)", dirs); + metalog_emit(dir, + (_DEF_DIRMODE | S_IFDIR) & ~pumask, 0, 0, + 0); } *tmp = '/'; } @@ -123,7 +133,9 @@ mkdir_home_parents(int dfd, const char *dir) if (fstatat(dfd, dirs, &st, 0) == -1) { if (mkdirat(dfd, dirs, _DEF_DIRMODE) == -1) err(EX_OSFILE, "'%s' (home parent) is not a directory", dirs); - fchownat(dfd, dirs, 0, 0, 0); + if (fchownat(dfd, dirs, 0, 0, 0) != 0) + warn("chown(%s)", dirs); + metalog_emit(dirs, (_DEF_DIRMODE | S_IFDIR) & ~pumask, 0, 0, 0); } free(dirs); diff --git a/usr.sbin/pw/pw_utils.c b/usr.sbin/pw/pw_utils.c index 9be1656bcfe1..87dd421ca8a3 100644 --- a/usr.sbin/pw/pw_utils.c +++ b/usr.sbin/pw/pw_utils.c @@ -92,3 +92,49 @@ nis_update(void) { errx(i, "make exited with status %d", i); return (i); } + +static void +metalog_emit_record(const char *path, const char *target, mode_t mode, + uid_t uid, gid_t gid, int flags) +{ + const char *flagstr, *type; + int error; + + if (conf.metalog == NULL) + return; + + if (target != NULL) + type = "link"; + else if (S_ISDIR(mode)) + type = "dir"; + else if (S_ISREG(mode)) + type = "file"; + else + errx(1, "metalog_emit: unhandled file type for %s", path); + + flagstr = fflagstostr(flags & + (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)); + if (flagstr == NULL) + errx(1, "metalog_emit: fflagstostr failed"); + + error = fprintf(conf.metalog, + "./%s type=%s mode=0%03o uid=%u gid=%u%s%s%s%s\n", + path, type, mode & ACCESSPERMS, uid, gid, + target != NULL ? " link=" : "", target != NULL ? target : "", + *flagstr != '\0' ? " flags=" : "", *flagstr != '\0' ? flagstr : ""); + if (error < 0) + errx(1, "metalog_emit: write error"); +} + +void +metalog_emit(const char *path, mode_t mode, uid_t uid, gid_t gid, int flags) +{ + metalog_emit_record(path, NULL, mode, uid, gid, flags); +} + +void +metalog_emit_symlink(const char *path, const char *target, mode_t mode, + uid_t uid, gid_t gid) +{ + metalog_emit_record(path, target, mode, uid, gid, 0); +} diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index a39a022ca309..605c51dcec2a 100644 --- a/usr.sbin/pw/pwupd.h +++ b/usr.sbin/pw/pwupd.h @@ -76,6 +76,7 @@ struct userconf { struct pwconf { char rootdir[MAXPATHLEN]; char etcpath[MAXPATHLEN]; + FILE *metalog; int fd; int rootfd; bool altroot; diff --git a/usr.sbin/pw/tests/pw_useradd_test.sh b/usr.sbin/pw/tests/pw_useradd_test.sh index 6413c063d482..75e96a64ba8e 100755 --- a/usr.sbin/pw/tests/pw_useradd_test.sh +++ b/usr.sbin/pw/tests/pw_useradd_test.sh @@ -1,4 +1,3 @@ - # Import helper functions . $(atf_get_srcdir)/helper_functions.shin @@ -357,15 +356,28 @@ user_add_skel_body() { echo "c" > ${HOME}/skel/c/d/dot.c mkdir ${HOME}/home ln -sf /nonexistent ${HOME}/skel/c/foo - atf_check -s exit:0 ${RPW} useradd foo -k /skel -m + atf_check -s exit:0 ${RPW} -M METALOG useradd foo -k /skel -m test -d ${HOME}/home/foo || atf_fail "Directory not created" test -f ${HOME}/home/foo/.a || atf_fail "File not created" atf_check -o file:${HOME}/skel/.a -s exit:0 cat ${HOME}/home/foo/.a atf_check -o file:${HOME}/skel/b -s exit:0 cat ${HOME}/home/foo/b - test -d ${HOME}/home/foo/c || atf_fail "Dotted directory in skel not copied" - test -d ${HOME}/home/foo/.plop || atf_fail "Directory in skell not created" + test -d ${HOME}/home/foo/c || atf_fail "Directory in skel not copied" + test -d ${HOME}/home/foo/.plop || atf_fail "Dotted directory in skel not created" atf_check -o inline:"/nonexistent\n" -s ignore readlink -f ${HOME}/home/foo/c/foo atf_check -o file:${HOME}/skel/c/d/dot.c -s exit:0 cat ${HOME}/home/foo/c/d/.c + + cat <<__EOF__ >METALOG.expected +./home/foo type=dir mode=0755 uid=1001 gid=1001 +./home/foo/.a type=file mode=0644 uid=1001 gid=1001 +./home/foo/.plop type=dir mode=0755 uid=1001 gid=1001 +./home/foo/b type=file mode=0644 uid=1001 gid=1001 +./home/foo/c type=dir mode=0755 uid=1001 gid=1001 +./home/foo/c/d type=dir mode=0755 uid=1001 gid=1001 +./home/foo/c/d/.c type=file mode=0644 uid=1001 gid=1001 +./home/foo/c/foo type=link mode=0755 uid=1001 gid=1001 link=/nonexistent +__EOF__ + atf_check -o save:METALOG.out sort METALOG + atf_check diff METALOG.out METALOG.expected } atf_test_case user_add_uid0 diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index 81bbbbe66be8..e06464c0e749 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -1185,13 +1185,15 @@ parsemsg_rfc3164_app_name_procid(char **msg, const char **app_name, /* Split strings from input. */ app_name_begin[app_name_length] = '\0'; - m += app_name_length + 1; + m += app_name_length; if (procid_begin != NULL) { procid_begin[procid_length] = '\0'; + /* Skip "[PID]". */ m += procid_length + 2; } - *msg = m + 1; + /* Skip separator ": ". */ + *msg = m + 2; *app_name = app_name_begin; *procid = procid_begin; return; |