diff options
744 files changed, 14165 insertions, 3707 deletions
diff --git a/.github/workflows/checklist.yml b/.github/workflows/checklist.yml index f5c3ea599abf..7f7b0d51f46e 100644 --- a/.github/workflows/checklist.yml +++ b/.github/workflows/checklist.yml @@ -89,6 +89,7 @@ jobs: /* Loop for each key in "checklist". */ for (const c in checklist) msg += "- " + c + "<sup>" + checklist[c].join(", ") + "</sup>\n"; + msg += "\nPlease review CONTRIBUTING.md, then update and push your branch again.\n" comment_func({ owner: context.repo.owner, @@ -103,7 +103,7 @@ # # See src/UPDATING `COMMON ITEMS' for more complete information. # -# If TARGET=machine (e.g. powerpc, arm64, ...) is specified you can +# If TARGET=machine (e.g. powerpc64, arm64, ...) is specified you can # cross build world for other machine types using the buildworld target, # and once the world is built you can cross build a kernel using the # buildkernel target. @@ -530,8 +530,7 @@ worlds: .PHONY # Don't build rarely used, semi-supported architectures unless requested. # .if defined(EXTRA_TARGETS) -# powerpcspe excluded from main list until clang fixed -EXTRA_ARCHES_powerpc= powerpcspe +EXTRA_ARCHES_powerpc= powerpc powerpcspe .endif TARGETS?= ${TARGET_MACHINE_LIST} _UNIVERSE_TARGETS= ${TARGETS} @@ -546,8 +545,7 @@ TOOLCHAINS_amd64= amd64-${_GCC_VERSION} TOOLCHAINS_arm= armv7-${_GCC_VERSION} TOOLCHAINS_arm64= aarch64-${_GCC_VERSION} TOOLCHAINS_i386= i386-${_GCC_VERSION} -TOOLCHAINS_powerpc= powerpc-${_GCC_VERSION} powerpc64-${_GCC_VERSION} -TOOLCHAIN_powerpc64= powerpc64-${_GCC_VERSION} +TOOLCHAINS_powerpc= powerpc64-${_GCC_VERSION} TOOLCHAINS_riscv= riscv64-${_GCC_VERSION} .endif diff --git a/Makefile.inc1 b/Makefile.inc1 index d366be09f497..010f5ac2bb55 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -2130,11 +2130,10 @@ create-source-src-package: _pkgbootstrap .PHONY PKGNAME "src" \ PKGGENNAME "src" \ VERSION "${PKG_VERSION}" \ - DESC "FreeBSD Kernel Sources" \ - COMMENT "FreeBSD Userland Sources" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ PKG_WWW "${PKG_WWW}" \ + UCLFILES "${SRCDIR}/release/packages/ucl" \ ${SRCDIR}/release/packages/template.ucl \ ${SSTAGEDIR}/src.ucl ${PKG_CMD} -o ABI=${PKG_ABI} \ @@ -2155,13 +2154,12 @@ create-source-src-sys-package: _pkgbootstrap .PHONY > ${SSTAGEDIR}/src-sys.plist ${SRCDIR}/release/packages/generate-ucl.lua \ PKGNAME "src-sys" \ - PKGGENNAME "src" \ + PKGGENNAME "src-sys" \ VERSION "${PKG_VERSION}" \ - DESC "FreeBSD Kernel Sources" \ - COMMENT "FreeBSD Kernel Sources" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ PKG_WWW "${PKG_WWW}" \ + UCLFILES "${SRCDIR}/release/packages/ucl" \ ${SRCDIR}/release/packages/template.ucl \ ${SSTAGEDIR}/src-sys.ucl ${PKG_CMD} -o ABI=${PKG_ABI} \ @@ -2226,12 +2224,12 @@ create-dtb-package: @if [ -f ${KSTAGEDIR}/${DISTDIR}/dtb.plist ]; then \ ${SRCDIR}/release/packages/generate-ucl.lua \ PKGNAME "dtb" \ + PKGGENNAME "dtb" \ VERSION "${PKG_VERSION}" \ - COMMENT "FreeBSD Devicetree Blobs" \ - DESC "FreeBSD Devicetree Blobs" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ PKG_WWW "${PKG_WWW}" \ + UCLFILES "${SRCDIR}/release/packages/ucl" \ ${SRCDIR}/release/packages/template.ucl \ ${KSTAGEDIR}/${DISTDIR}/dtb.ucl ; \ awk -F\" ' \ @@ -2257,13 +2255,15 @@ create-kernel-packages-flavor${flavor:C,^""$,${_default_flavor},}: _pkgbootstrap -v kernel=yes -v _kernconf=${INSTALLKERNEL} ; \ ${SRCDIR}/release/packages/generate-ucl.lua \ PKGNAME "kernel-${INSTALLKERNEL:tl}${flavor}" \ + PKGGENNAME "kernel" \ VERSION "${PKG_VERSION}" \ KERNELDIR "kernel" \ - COMMENT "FreeBSD ${INSTALLKERNEL} kernel ${flavor}" \ - DESC "FreeBSD ${INSTALLKERNEL} kernel ${flavor}" \ + KERNEL_NAME "${INSTALLKERNEL}" \ + KERNEL_FLAVOR "${flavor}" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ PKG_WWW "${PKG_WWW}" \ + UCLFILES "${SRCDIR}/release/packages/ucl" \ ${SRCDIR}/release/packages/template.ucl \ ${KSTAGEDIR}/${DISTDIR}/kernel.${INSTALLKERNEL}${flavor}.ucl ; \ awk -F\" ' \ @@ -2296,14 +2296,14 @@ create-kernel-packages-extra-flavor${flavor:C,^""$,${_default_flavor},}-${_kerne PKGNAME "kernel-${_kernel:tl}${flavor}" \ PKGGENNAME "kernel" \ FORCEINCLUDE "kernel${flavor}" \ - UCLFILES "${SRCDIR}/release/packages/" \ VERSION "${PKG_VERSION}" \ + KERNEL_NAME "${_kernel:tl}" \ + KERNEL_FLAVOR "${flavor}" \ KERNELDIR "kernel.${_kernel}" \ - DESC "FreeBSD ${_kernel} kernel ${flavor}" \ - COMMENT "FreeBSD ${_kernel} kernel ${flavor}" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ PKG_WWW "${PKG_WWW}" \ + UCLFILES "${SRCDIR}/release/packages/ucl" \ ${SRCDIR}/release/packages/template.ucl \ ${KSTAGEDIR}/kernel.${_kernel}/kernel.${_kernel}${flavor}.ucl ; \ awk -F\" ' \ diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index a5e41d9ac6d6..e5a3da94e127 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,9 @@ # xargs -n1 | sort | uniq -d; # done +# 20250716: Remove an old manual page, vn(4) was removed in FreeBSD 5.0 +OLD_FILES+=usr/share/man/man4/vn.4.gz + # 20250710: share: Delete bitrotted make_*_driver.sh scripts OLD_FILES+=usr/share/examples/drivers/README OLD_FILES+=usr/share/examples/drivers/make_device_driver.sh @@ -10,6 +10,11 @@ newline. Entries should be separated by a newline. Changes to this file should not be MFCed. +1349a733cf28: + Add a driver supporting a new storage controller interface, + Universal Flash Storage Host Controller Interface, supporting + version 4.1 and earlier, via ufshci(4). + f1f230439fa4: FreeBSD now implements the inotify(2) family of system calls. @@ -27,6 +27,17 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.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".) +20250721: + WITH_MITKRB5 is now enabled by default. MIT KRB5 has replaced + Heimdal in base. Ports that use USES=gssapi must be rebuilt. + A clean buildworld is required. + +20250719: + Commits 392a82b225 and c00baac0ab both changed the + internal API between the NFS modules. As such, all + these modules need to be rebuilt from sources. + __FreeBSD_version was bumped to 1500053 for this. + 20250710: The shar(1) utility has been removed from base. The sysutils/freebsd-shar port was created to maintain this version of diff --git a/bin/df/df.1 b/bin/df/df.1 index ceb1bb45babf..2de72e4e3bb2 100644 --- a/bin/df/df.1 +++ b/bin/df/df.1 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 29, 2023 +.Dd July 16, 2025 .Dt DF 1 .Os .Sh NAME @@ -65,7 +65,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl a Show all mount points, including those that were mounted with the @@ -264,7 +264,7 @@ each file or directory name or disk label .Xr getmntinfo 3 , .Xr libxo 3 , .Xr localeconv 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr fstab 5 , .Xr mount 8 , .Xr pstat 8 , diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 1c964157f53f..542004453658 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -33,7 +33,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 06, 2025 +.Dd July 16, 2025 .Dt PS 1 .Os .Sh NAME @@ -194,7 +194,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. The default is the traditional text style output. .It Fl A @@ -925,7 +925,7 @@ Display information on all system processes: .Xr kvm 3 , .Xr libxo 3 , .Xr strftime 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr mac 4 , .Xr procfs 4 , .Xr pstat 8 , diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 index f3d7a49e0e78..da8cbd9ffe50 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 +++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 @@ -20,7 +20,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 14, 2025 +.Dd July 16, 2025 .Dt DTRACE 1 .Os .Sh NAME @@ -617,6 +617,52 @@ Same as the flag. .It Sy dynvarsize Ns = Ns Ar size Size of the dynamic variable space. +.Sm off +.It Sy evaltime = Cm exec | preinit | postinit | main +.Sm on +Process create mode. +When using +.Fl c Ar cmd +to start a command, +.Nm +will first stop the newly started +.Ar cmd , +evaluate the +.Xr d 7 +program, +and then resume the +.Ar cmd . +The +.Cm evaltime +option controls the exact moment when this happens. +.Pp +The following table describes supported modes. +.Bl -column -offset indent "postinit" "D Program Evaluation Time" +.It Sy Mode Ta Sy D Program Evaluation Time +.It Cm exec Ta +Right at the first instruction of the command +.Ar cmd +execution. +.It Cm preinit Ta +Before +.Xr elf 5 Ap s +.Dq .init +sections. +.It Cm postinit Ta +After +.Xr elf 5 Ap s +.Dq .init +sections. +Default on +.Fx . +.It Cm main Ta +Before the first instruction of the +.Fn main +function. +.El +.Pp +Usually, there is no reason to change the default mode, +but it might be handy in situations such as shared library tracing. .It Sy flowindent Turn on flow indentation. Same as the @@ -1224,11 +1270,13 @@ Invalid command line options or arguments were specified. .Xr dwatch 1 , .Xr dtrace_audit 4 , .Xr dtrace_dtrace 4 , +.Xr dtrace_fbt 4 , .Xr dtrace_io 4 , .Xr dtrace_ip 4 , .Xr dtrace_kinst 4 , .Xr dtrace_lockstat 4 , .Xr dtrace_proc 4 , +.Xr dtrace_profile 4 , .Xr dtrace_sched 4 , .Xr dtrace_sctp 4 , .Xr dtrace_tcp 4 , diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d new file mode 100644 index 000000000000..4061db9858c1 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2025 Mark Johnston <markj@FreeBSD.org> + */ + +/* + * For 10s, verify that the value of `ticks goes up by `hz each second. + */ + +#pragma D option quiet + +BEGIN +{ + i = 0; +} + +tick-1s +{ + if (i == 0) { + t = *(int *)&`ticks; + i++; + } else { + u = *(int *)&`ticks; + if (u - t != `hz) { + printf("ticks: %d, expected %d\n", u - t, `hz); + exit(1); + } + t = u; + i++; + if (i == 10) { + exit(0); + } + } +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c index d1ebaa8791da..8cc504856567 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c @@ -1918,6 +1918,14 @@ dt_node_op1(int op, dt_node_t *cp) return (cp); } + /* + * When applying the addressof operator to an identifier, it's okay if + * we can't find type information for the identifier, so flag the node + * to ensure that we don't raise an error. + */ + if (op == DT_TOK_ADDROF && cp->dn_kind == DT_NODE_IDENT) + cp->dn_flags |= DT_NF_IDENTADDR; + dnp = dt_node_alloc(DT_NODE_OP1); assert(op <= USHRT_MAX); dnp->dn_op = (ushort_t)op; @@ -2786,10 +2794,21 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) dt_module_modelname(dtp->dt_ddefs)); } - xyerror(D_SYM_NOTYPES, + /* + * If we're taking the address of an identifier that + * doesn't have type info, try to make it a void *. + * This lets us use identifiers that are defined in + * assembly and don't have type information. + */ + if ((dnp->dn_flags & DT_NF_IDENTADDR) == 0 || + dtrace_lookup_by_type(dtp, DTRACE_OBJ_CDEFS, + "void", &dtt) != 0) { + xyerror(D_SYM_NOTYPES, "no symbolic type information is available for " - "%s%s%s: %s\n", dts.dts_object, mark, dts.dts_name, - dtrace_errmsg(dtp, dtrace_errno(dtp))); + "%s%s%s: %s\n", dts.dts_object, mark, + dts.dts_name, + dtrace_errmsg(dtp, dtrace_errno(dtp))); + } } idp = dt_ident_create(name, DT_IDENT_SYMBOL, 0, 0, @@ -4506,30 +4525,30 @@ dt_cook_none(dt_node_t *dnp, uint_t idflags) return (dnp); } -static dt_node_t *(*dt_cook_funcs[])(dt_node_t *, uint_t) = { - dt_cook_none, /* DT_NODE_FREE */ - dt_cook_none, /* DT_NODE_INT */ - dt_cook_none, /* DT_NODE_STRING */ - dt_cook_ident, /* DT_NODE_IDENT */ - dt_cook_var, /* DT_NODE_VAR */ - dt_cook_none, /* DT_NODE_SYM */ - dt_cook_none, /* DT_NODE_TYPE */ - dt_cook_func, /* DT_NODE_FUNC */ - dt_cook_op1, /* DT_NODE_OP1 */ - dt_cook_op2, /* DT_NODE_OP2 */ - dt_cook_op3, /* DT_NODE_OP3 */ - dt_cook_statement, /* DT_NODE_DEXPR */ - dt_cook_statement, /* DT_NODE_DFUNC */ - dt_cook_aggregation, /* DT_NODE_AGG */ - dt_cook_none, /* DT_NODE_PDESC */ - dt_cook_clause, /* DT_NODE_CLAUSE */ - dt_cook_inline, /* DT_NODE_INLINE */ - dt_cook_member, /* DT_NODE_MEMBER */ - dt_cook_xlator, /* DT_NODE_XLATOR */ - dt_cook_none, /* DT_NODE_PROBE */ - dt_cook_provider, /* DT_NODE_PROVIDER */ - dt_cook_none, /* DT_NODE_PROG */ - dt_cook_none, /* DT_NODE_IF */ +static dt_node_t *(* const dt_cook_funcs[])(dt_node_t *, uint_t) = { + [DT_NODE_FREE] = dt_cook_none, + [DT_NODE_INT] = dt_cook_none, + [DT_NODE_STRING] = dt_cook_none, + [DT_NODE_IDENT] = dt_cook_ident, + [DT_NODE_VAR] = dt_cook_var, + [DT_NODE_SYM] = dt_cook_none, + [DT_NODE_TYPE] = dt_cook_none, + [DT_NODE_FUNC] = dt_cook_func, + [DT_NODE_OP1] = dt_cook_op1, + [DT_NODE_OP2] = dt_cook_op2, + [DT_NODE_OP3] = dt_cook_op3, + [DT_NODE_DEXPR] = dt_cook_statement, + [DT_NODE_DFUNC] = dt_cook_statement, + [DT_NODE_AGG] = dt_cook_aggregation, + [DT_NODE_PDESC] = dt_cook_none, + [DT_NODE_CLAUSE] = dt_cook_clause, + [DT_NODE_INLINE] = dt_cook_inline, + [DT_NODE_MEMBER] = dt_cook_member, + [DT_NODE_XLATOR] = dt_cook_xlator, + [DT_NODE_PROBE] = dt_cook_none, + [DT_NODE_PROVIDER] = dt_cook_provider, + [DT_NODE_PROG] = dt_cook_none, + [DT_NODE_IF] = dt_cook_none, }; /* diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h index 3a146c5d2592..1d2f33beee0f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h @@ -182,6 +182,7 @@ typedef struct dt_node { #define DT_NF_WRITABLE 0x10 /* node is writable (can be modified) */ #define DT_NF_BITFIELD 0x20 /* node is an integer bitfield */ #define DT_NF_USERLAND 0x40 /* data is a userland address */ +#define DT_NF_IDENTADDR 0x80 /* node is an identifier address */ #define DT_TYPE_NAMELEN 128 /* reasonable size for ctf_type_name() */ diff --git a/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile b/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile index 84f4706b61ee..ceb52fcf5bd0 100644 --- a/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile @@ -37,6 +37,7 @@ ${PACKAGE}FILES= \ tst.profileusec.d \ tst.profileusec.d.out \ tst.sym.ksh \ + tst.ticks.d \ tst.ufunc.ksh \ tst.ufuncsort.ksh \ tst.ufuncsort.ksh.out \ diff --git a/contrib/bmake/ChangeLog b/contrib/bmake/ChangeLog index 0a5eced2d439..5a1c30a95750 100644 --- a/contrib/bmake/ChangeLog +++ b/contrib/bmake/ChangeLog @@ -1,3 +1,30 @@ +2025-07-07 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20250707 + Merge with NetBSD make, pick up + o cond.c: improve debug log message for 'exists' function. + complain about unfinished escape sequences or string literals. + +2025-07-04 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20250704 + Merge with NetBSD make, pick up + o make.1: add a DIAGNOSTICS section for make to reference. + o main.c: simplify the warning for invalid -J by refering to + manual page. + +2025-06-30 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20250630 + Merge with NetBSD make, pick up + o consistently use double quotes in error messages + o cond.c: if a condition is erroneous, skip the whole .if/.endif + o make_malloc.c: in cleanup mode, initialize freshly allocated memory + o str.c: error out on an ":M" modifier whose pattern ends with + backslash + o var.c: fix parsing of modifier parts for :gmtime and :localtime + add POSIX $^ support + 2025-06-18 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250618 diff --git a/contrib/bmake/FILES b/contrib/bmake/FILES index 8bed07d546a3..1cec16b73ef4 100644 --- a/contrib/bmake/FILES +++ b/contrib/bmake/FILES @@ -76,6 +76,8 @@ unit-tests/archive-suffix.exp unit-tests/archive-suffix.mk unit-tests/archive.exp unit-tests/archive.mk +unit-tests/char-005c-reverse-solidus.exp +unit-tests/char-005c-reverse-solidus.mk unit-tests/check-expect.lua unit-tests/cmd-errors-jobs.exp unit-tests/cmd-errors-jobs.mk @@ -602,8 +604,6 @@ unit-tests/shell-ksh.exp unit-tests/shell-ksh.mk unit-tests/shell-sh.exp unit-tests/shell-sh.mk -unit-tests/suff.exp -unit-tests/suff.mk unit-tests/suff-add-later.exp unit-tests/suff-add-later.mk unit-tests/suff-clear-regular.exp @@ -634,6 +634,8 @@ unit-tests/suff-transform-select.exp unit-tests/suff-transform-select.mk unit-tests/suff-use.exp unit-tests/suff-use.mk +unit-tests/suff.exp +unit-tests/suff.mk unit-tests/sunshcmd.exp unit-tests/sunshcmd.mk unit-tests/ternary.exp @@ -780,6 +782,8 @@ unit-tests/varmod-unique.exp unit-tests/varmod-unique.mk unit-tests/varmod.exp unit-tests/varmod.mk +unit-tests/varname-circumflex.exp +unit-tests/varname-circumflex.mk unit-tests/varname-dollar.exp unit-tests/varname-dollar.mk unit-tests/varname-dot-alltargets.exp diff --git a/contrib/bmake/VERSION b/contrib/bmake/VERSION index 1467403891f1..eef1ef4b8ba9 100644 --- a/contrib/bmake/VERSION +++ b/contrib/bmake/VERSION @@ -1,2 +1,2 @@ # keep this compatible with sh and make -_MAKE_VERSION=20250618 +_MAKE_VERSION=20250707 diff --git a/contrib/bmake/arch.c b/contrib/bmake/arch.c index 77ac7f3c5707..87e2b128ae00 100644 --- a/contrib/bmake/arch.c +++ b/contrib/bmake/arch.c @@ -1,4 +1,4 @@ -/* $NetBSD: arch.c,v 1.222 2024/08/06 17:46:01 rillig Exp $ */ +/* $NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -147,7 +147,7 @@ struct ar_hdr { #include "dir.h" /* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: arch.c,v 1.222 2024/08/06 17:46:01 rillig Exp $"); +MAKE_RCSID("$NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 rillig Exp $"); typedef struct List ArchList; typedef struct ListNode ArchListNode; @@ -314,7 +314,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope) if (*cp == '\0') { Parse_Error(PARSE_FATAL, - "Missing ')' in archive specification"); + "Missing \")\" in archive specification"); return false; } diff --git a/contrib/bmake/bmake.1 b/contrib/bmake/bmake.1 index 92ed9e201ea5..01f173bc1a69 100644 --- a/contrib/bmake/bmake.1 +++ b/contrib/bmake/bmake.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.385 2025/06/13 03:51:18 rillig Exp $ +.\" $NetBSD: make.1,v 1.387 2025/07/02 17:11:56 rillig Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd June 12, 2025 +.Dd July 2, 2025 .Dt BMAKE 1 .Os .Sh NAME @@ -785,11 +785,13 @@ Is redundant with respect to global variables, which have already been expanded. .El .Pp -The seven built-in local variables are: +The built-in local variables are: .Bl -tag -width ".Va .ARCHIVE" -offset indent .It Va .ALLSRC The list of all sources for this target; also known as -.Sq Va \&> . +.Sq Va \&> +or +.Sq Va \&^ . .It Va .ARCHIVE The name of the archive file; also known as .Sq Va \&! . @@ -823,6 +825,7 @@ in archive member rules. The shorter forms .Po .Sq Va \&> , +.Sq Va \&^ , .Sq Va \&! , .Sq Va \&< , .Sq Va \&% , @@ -2714,6 +2717,8 @@ If the environment variable is set to .Dq yes , any stack traces include the call chain of the parent processes. +.\" .Sh EXIT STATUS +.\" .Sh ENVIRONMENT .Sh FILES .Bl -tag -width /usr/share/mk -compact .It .depend @@ -2727,6 +2732,68 @@ system makefile .It /usr/share/mk system makefile directory .El +.\" .Sh EXAMPLES +.Sh DIAGNOSTICS +.Bl -tag +.It Dv Invalid internal option \(dq-J\(dq in \(dq Ns Ar directory Ns Dv \(dq +The internal +.Fl J +option coordinates the main +.Nm +process with the sub-make processes to limit +the number of jobs that run in parallel. +The option is passed to all child processes via the +.Ev MAKEFLAGS +environment variable. +To become valid, +this option requires that the target running the sub-make is marked with the +.Dv .MAKE +special source, +or that one of the target's commands directly contains the word +.Dq make +or one of the expressions +.Dq ${MAKE} , +.Dq ${.MAKE} , +.Dq $(MAKE) , +.Dq $(.MAKE) . +If that's not the case, +make issues the above warning and falls back to compat mode. +.Pp +To see the chain of sub-makes that leads to the invalid option, set the +.Ev MAKE_STACK_TRACE +environment variable to +.Dq yes . +.Pp +To run the sub-make in parallel mode, even in dry-run mode (see the +.Fl n +option), add the +.Dv .MAKE +pseudo source to the target. +This is appropriate when the sub-make runs the same target in a subdirectory. +.Pp +To run the sub-make in parallel mode but not in dry-mode, +add a +.Dq ${:D make} +marker to one of the target's commands. +This marker expands to an empty string +and thus does not affect the executed commands. +.\" The marker can even be added before any of the "@+-" modifiers, +.\" so no need to mention this explicitly. +.Pp +To run the sub-make in compat mode, add the +.Fl B +option to its invocation. +This is appropriate when the sub-make is only used to print a variable's +value using the +.Fl v +or +.Fl V +options. +.Pp +To make the sub-make independent from the parent make, unset the +.Ev MAKEFLAGS +environment variable in the target's commands. +.El .Sh COMPATIBILITY The basic make syntax is compatible between different make variants; however the special variables, variable modifiers and conditionals are not. @@ -2813,6 +2880,7 @@ not trying to chain transformations together, etc.) is also reasonably portable. .Sh SEE ALSO .Xr mkdep 1 +.\" .Sh STANDARDS .Sh HISTORY .Nm is derived from NetBSD @@ -2837,6 +2905,8 @@ has been used to FoRCe rebuilding (since the target/dependency does not exist ... unless someone creates an .Pa FRC file). +.\" .Sh AUTHORS +.\" .Sh CAVEATS .Sh BUGS The .Nm @@ -2858,3 +2928,4 @@ using that token pool to abort the build and exit with error code 6. Sometimes the attempt to suppress a cascade of unnecessary errors, can result in a seemingly unexplained .Ql *** Error code 6 +.\" .Sh SECURITY CONSIDERATIONS diff --git a/contrib/bmake/bmake.cat1 b/contrib/bmake/bmake.cat1 index 667c80898def..950437a8db9c 100644 --- a/contrib/bmake/bmake.cat1 +++ b/contrib/bmake/bmake.cat1 @@ -507,10 +507,10 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS ::== Is redundant with respect to global variables, which have already been expanded. - The seven built-in local variables are: + The built-in local variables are: _._A_L_L_S_R_C The list of all sources for this target; also known as - `_>'. + `_>' or `_^'. _._A_R_C_H_I_V_E The name of the archive file; also known as `_!'. @@ -531,9 +531,9 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS compatibility with other makes this is an alias for _._A_R_C_H_I_V_E in archive member rules. - The shorter forms (`_>', `_!', `_<', `_%', `_?', `_*', and `_@') are permitted - for backward compatibility with historical makefiles and legacy POSIX - make and are not recommended. + The shorter forms (`_>', `_^', `_!', `_<', `_%', `_?', `_*', and `_@') are + permitted for backward compatibility with historical makefiles and legacy + POSIX make and are not recommended. Variants of these variables with the punctuation followed immediately by `D' or `F', e.g. `$(@D)', are legacy forms equivalent to using the `:H' @@ -1748,6 +1748,39 @@ FFIILLEESS sys.mk system makefile /usr/share/mk system makefile directory +DDIIAAGGNNOOSSTTIICCSS + Invalid internal option "-J" in "_d_i_r_e_c_t_o_r_y" + The internal --JJ option coordinates the main bbmmaakkee process with + the sub-make processes to limit the number of jobs that run in + parallel. The option is passed to all child processes via the + MAKEFLAGS environment variable. To become valid, this option + requires that the target running the sub-make is marked with the + .MAKE special source, or that one of the target's commands + directly contains the word "make" or one of the expressions + "${MAKE}", "${.MAKE}", "$(MAKE)", "$(.MAKE)". If that's not the + case, make issues the above warning and falls back to compat + mode. + + To see the chain of sub-makes that leads to the invalid option, + set the MAKE_STACK_TRACE environment variable to "yes". + + To run the sub-make in parallel mode, even in dry-run mode (see + the --nn option), add the .MAKE pseudo source to the target. This + is appropriate when the sub-make runs the same target in a + subdirectory. + + To run the sub-make in parallel mode but not in dry-mode, add a + "${:D make}" marker to one of the target's commands. This marker + expands to an empty string and thus does not affect the executed + commands. + + To run the sub-make in compat mode, add the --BB option to its + invocation. This is appropriate when the sub-make is only used + to print a variable's value using the --vv or --VV options. + + To make the sub-make independent from the parent make, unset the + MAKEFLAGS environment variable in the target's commands. + CCOOMMPPAATTIIBBIILLIITTYY The basic make syntax is compatible between different make variants; however the special variables, variable modifiers and conditionals are @@ -1831,4 +1864,4 @@ BBUUGGSS attempt to suppress a cascade of unnecessary errors, can result in a seemingly unexplained `*** Error code 6' -FreeBSD 14.2-RELEASE-p1 June 12, 2025 FreeBSD 14.2-RELEASE-p1 +FreeBSD 14.2-RELEASE-p1 July 2, 2025 FreeBSD 14.2-RELEASE-p1 diff --git a/contrib/bmake/compat.c b/contrib/bmake/compat.c index 7a51a99be4ba..f32213bf67e5 100644 --- a/contrib/bmake/compat.c +++ b/contrib/bmake/compat.c @@ -1,4 +1,4 @@ -/* $NetBSD: compat.c,v 1.267 2025/06/13 03:51:18 rillig Exp $ */ +/* $NetBSD: compat.c,v 1.268 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -97,7 +97,7 @@ #include "pathnames.h" /* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: compat.c,v 1.267 2025/06/13 03:51:18 rillig Exp $"); +MAKE_RCSID("$NetBSD: compat.c,v 1.268 2025/07/06 07:11:31 rillig Exp $"); static GNode *curTarg; static pid_t compatChild; @@ -334,11 +334,8 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln) if (useShell) { static const char *shargv[5]; - if (Cmd_Argv(cmd, cmd_len, shargv, 5, - cmd_file, sizeof(cmd_file), - errCheck && shellErrFlag != NULL, - DEBUG(SHELL)) < 0) - Fatal("cannot run \"%s\"", cmd); + Cmd_Argv(cmd, cmd_len, shargv, cmd_file, sizeof(cmd_file), + errCheck && shellErrFlag != NULL, DEBUG(SHELL)); av = shargv; bp = NULL; mav = NULL; diff --git a/contrib/bmake/cond.c b/contrib/bmake/cond.c index f83163cbb50e..b3613bbadf5d 100644 --- a/contrib/bmake/cond.c +++ b/contrib/bmake/cond.c @@ -1,4 +1,4 @@ -/* $NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $ */ +/* $NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -77,9 +77,8 @@ * '.if <cond>', '.elifnmake <cond>', '.else', '.endif'. * * Cond_EvalCondition - * Evaluate the conditional, which is either the argument - * of one of the .if directives or the condition in a - * ':?then:else' variable modifier. + * Evaluate a condition, either from one of the .if + * directives, or from a ':?then:else' modifier. * * Cond_EndFile At the end of reading a makefile, ensure that the * conditional directives are well-balanced. @@ -91,14 +90,14 @@ #include "dir.h" /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $"); +MAKE_RCSID("$NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $"); /* * Conditional expressions conform to this grammar: * Or -> And ('||' And)* * And -> Term ('&&' Term)* * Term -> Function '(' Argument ')' - * Term -> Leaf Operator Leaf + * Term -> Leaf ComparisonOp Leaf * Term -> Leaf * Term -> '(' Or ')' * Term -> '!' Term @@ -106,7 +105,7 @@ MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $"); * Leaf -> Number * Leaf -> VariableExpression * Leaf -> BareWord - * Operator -> '==' | '!=' | '>' | '<' | '>=' | '<=' + * ComparisonOp -> '==' | '!=' | '>' | '<' | '>=' | '<=' * * BareWord is an unquoted string literal, its evaluation depends on the kind * of '.if' directive. @@ -156,12 +155,12 @@ typedef struct CondParser { * been an expression or a plain word. * * In conditional directives like '.if', the left-hand side must - * either be an expression, a quoted string or a number. + * either be a defined expression, a quoted string or a number. */ bool leftUnquotedOK; const char *p; /* The remaining condition to parse */ - Token curr; /* Single push-back token used in parsing */ + Token curr; /* The push-back token, or TOK_NONE */ } CondParser; static CondResult CondParser_Or(CondParser *, bool); @@ -255,7 +254,7 @@ ParseFuncArg(const char **pp, bool doEval, const char *func) len++; Parse_Error(PARSE_FATAL, - "Missing ')' after argument '%.*s' for '%.*s'", + "Missing \")\" after argument \"%.*s\" for \"%.*s\"", (int)(argEnd - argStart), argStart, len, func); free(res); return NULL; @@ -284,7 +283,8 @@ FuncMake(const char *targetPattern) if (res.error != NULL && !warned) { warned = true; Parse_Error(PARSE_WARNING, - "%s in pattern argument '%s' to function 'make'", + "%s in pattern argument \"%s\" " + "to function \"make\"", res.error, targetPattern); } if (res.matched) @@ -301,14 +301,16 @@ FuncExists(const char *file) char *path; path = Dir_FindFile(file, &dirSearchPath); - DEBUG2(COND, "exists(%s) result is \"%s\"\n", - file, path != NULL ? path : ""); result = path != NULL; + if (result) + DEBUG2(COND, "\"%s\" exists in \"%s\"\n", file, path); + else + DEBUG1(COND, "\"%s\" does not exist\n", file); free(path); return result; } -/* See if the given node exists and is an actual target. */ +/* See if the given node is an actual target. */ static bool FuncTarget(const char *node) { @@ -316,10 +318,7 @@ FuncTarget(const char *node) return gn != NULL && GNode_IsTarget(gn); } -/* - * See if the given node exists and is an actual target with commands - * associated with it. - */ +/* See if the given node is an actual target with commands. */ static bool FuncCommands(const char *node) { @@ -374,38 +373,37 @@ is_separator(char ch) * * Return whether to continue parsing the leaf. * - * Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX} + * Examples: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX} */ static bool CondParser_StringExpr(CondParser *par, const char *start, bool doEval, bool quoted, - Buffer *buf, FStr *inout_str) + Buffer *buf, FStr *out_str) { VarEvalMode emode; const char *p; - bool atStart; /* true means an expression outside quotes */ + bool outsideQuotes; emode = doEval && quoted ? VARE_EVAL : doEval ? VARE_EVAL_DEFINED_LOUD : VARE_PARSE; p = par->p; - atStart = p == start; - *inout_str = Var_Parse(&p, SCOPE_CMDLINE, emode); - /* TODO: handle errors */ - if (inout_str->str == var_Error) { - FStr_Done(inout_str); - *inout_str = FStr_InitRefer(NULL); + outsideQuotes = p == start; + *out_str = Var_Parse(&p, SCOPE_CMDLINE, emode); + if (out_str->str == var_Error) { + FStr_Done(out_str); + *out_str = FStr_InitRefer(NULL); return false; } par->p = p; - if (atStart && is_separator(par->p[0])) + if (outsideQuotes && is_separator(par->p[0])) return false; - Buf_AddStr(buf, inout_str->str); - FStr_Done(inout_str); - *inout_str = FStr_InitRefer(NULL); /* not finished yet */ + Buf_AddStr(buf, out_str->str); + FStr_Done(out_str); + *out_str = FStr_InitRefer(NULL); /* not finished yet */ return true; } @@ -414,7 +412,7 @@ CondParser_StringExpr(CondParser *par, const char *start, * on the left-hand and right-hand sides of comparisons. * * Return the string without any enclosing quotes, or NULL on error. - * Sets out_quoted if the leaf was a quoted string literal. + * Set out_quoted if the leaf was a quoted string literal. */ static FStr CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK, @@ -439,12 +437,14 @@ CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK, if (par->p[0] != '\0') { Buf_AddByte(&buf, par->p[0]); par->p++; - } + } else + Parse_Error(PARSE_FATAL, + "Unfinished backslash escape sequence"); continue; case '"': par->p++; if (quoted) - goto return_buf; /* skip the closing quote */ + goto return_buf; Buf_AddByte(&buf, '"'); continue; case ')': /* see is_separator */ @@ -475,6 +475,9 @@ CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK, continue; } } + if (quoted) + Parse_Error(PARSE_FATAL, + "Unfinished string literal \"%s\"", start); return_buf: str = FStr_InitOwn(buf.data); buf.data = NULL; @@ -528,8 +531,8 @@ EvalCompareStr(const char *lhs, ComparisonOp op, const char *rhs) { if (op != EQ && op != NE) { Parse_Error(PARSE_FATAL, - "Comparison with '%s' requires both operands " - "'%s' and '%s' to be numeric", + "Comparison with \"%s\" requires both operands " + "\"%s\" and \"%s\" to be numeric", opname[op], lhs, rhs); return TOK_ERROR; } @@ -603,7 +606,7 @@ CondParser_Comparison(CondParser *par, bool doEval) if (par->p[0] == '\0') { Parse_Error(PARSE_FATAL, - "Missing right-hand side of operator '%s'", opname[op]); + "Missing right-hand side of operator \"%s\"", opname[op]); goto done_lhs; } @@ -768,7 +771,7 @@ CondParser_Token(CondParser *par, bool doEval) if (par->p[0] == '|') par->p++; else { - Parse_Error(PARSE_FATAL, "Unknown operator '|'"); + Parse_Error(PARSE_FATAL, "Unknown operator \"|\""); return TOK_ERROR; } return TOK_OR; @@ -778,7 +781,7 @@ CondParser_Token(CondParser *par, bool doEval) if (par->p[0] == '&') par->p++; else { - Parse_Error(PARSE_FATAL, "Unknown operator '&'"); + Parse_Error(PARSE_FATAL, "Unknown operator \"&\""); return TOK_ERROR; } return TOK_AND; @@ -825,7 +828,7 @@ CondParser_Skip(CondParser *par, Token t) /* * Term -> '(' Or ')' * Term -> '!' Term - * Term -> Leaf Operator Leaf + * Term -> Leaf ComparisonOp Leaf * Term -> Leaf */ static CondResult @@ -923,8 +926,10 @@ CondEvalExpression(const char *cond, bool plain, if (par.curr != TOK_EOF) rval = CR_ERROR; - if (rval == CR_ERROR && eprint && parseErrors == parseErrorsBefore) - Parse_Error(PARSE_FATAL, "Malformed conditional '%s'", cond); + if (parseErrors != parseErrorsBefore) + rval = CR_ERROR; + else if (rval == CR_ERROR && eprint) + Parse_Error(PARSE_FATAL, "Malformed conditional \"%s\"", cond); return rval; } diff --git a/contrib/bmake/for.c b/contrib/bmake/for.c index 438fb4e84de0..904853107db8 100644 --- a/contrib/bmake/for.c +++ b/contrib/bmake/for.c @@ -1,4 +1,4 @@ -/* $NetBSD: for.c,v 1.185 2025/04/22 19:28:50 rillig Exp $ */ +/* $NetBSD: for.c,v 1.186 2025/06/28 22:39:27 rillig Exp $ */ /* * Copyright (c) 1992, The Regents of the University of California. @@ -58,7 +58,7 @@ #include "make.h" /* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: for.c,v 1.185 2025/04/22 19:28:50 rillig Exp $"); +MAKE_RCSID("$NetBSD: for.c,v 1.186 2025/06/28 22:39:27 rillig Exp $"); typedef struct ForLoop { @@ -153,7 +153,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp) for (;;) { cpp_skip_whitespace(&p); if (*p == '\0') { - Parse_Error(PARSE_FATAL, "missing `in' in for"); + Parse_Error(PARSE_FATAL, + "Missing \"in\" in .for loop"); goto cleanup; } @@ -168,7 +169,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp) } if (f->vars.len == 0) { - Parse_Error(PARSE_FATAL, "no iteration variables in for"); + Parse_Error(PARSE_FATAL, + "Missing iteration variables in .for loop"); return; } @@ -177,7 +179,7 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp) invalid_variable_name: Parse_Error(PARSE_FATAL, - "invalid character '%c' in .for loop variable name", *p); + "Invalid character \"%c\" in .for loop variable name", *p); cleanup: while (f->vars.len > 0) free(*(char **)Vector_Pop(&f->vars)); diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c index 582870088f2d..0c54e710afeb 100644 --- a/contrib/bmake/job.c +++ b/contrib/bmake/job.c @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.516 2025/06/13 06:13:19 rillig Exp $ */ +/* $NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -89,7 +89,7 @@ * define the shell that is used for the creation * commands in jobs mode. * - * Job_Finish Make the .END target. Must only be called when the + * Job_MakeDotEnd Make the .END target. Must only be called when the * job table is empty. * * Job_AbortAll Kill all currently running jobs, in an emergency. @@ -137,7 +137,7 @@ #include "trace.h" /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: job.c,v 1.516 2025/06/13 06:13:19 rillig Exp $"); +MAKE_RCSID("$NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $"); #ifdef USE_SELECT @@ -599,7 +599,7 @@ Job_Pid(Job *job) } static void -DumpJobs(const char *where) +JobTable_Dump(const char *where) { const Job *job; char flags[4]; @@ -663,6 +663,13 @@ SetNonblocking(int fd) } static void +SetCloseOnExec(int fd) +{ + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + Punt("SetCloseOnExec: %s", strerror(errno)); +} + +static void JobCreatePipe(Job *job, int minfd) { int i; @@ -683,10 +690,8 @@ JobCreatePipe(Job *job, int minfd) job->inPipe = pipe_fds[0]; job->outPipe = pipe_fds[1]; - if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1) - Punt("SetCloseOnExec: %s", strerror(errno)); - if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1) - Punt("SetCloseOnExec: %s", strerror(errno)); + SetCloseOnExec(job->inPipe); + SetCloseOnExec(job->outPipe); /* * We mark the input side of the pipe non-blocking; we poll(2) the @@ -822,7 +827,7 @@ JobFindPid(int pid, enum JobStatus status, bool isJobs) return job; } if (DEBUG(JOB) && isJobs) - DumpJobs("no pid"); + JobTable_Dump("no pid"); return NULL; } @@ -1624,7 +1629,7 @@ JobExec(Job *job, char **argv) debug_printf( "JobExec: target %s, pid %d added to jobs table\n", job->node->name, job->pid); - DumpJobs("job started"); + JobTable_Dump("job started"); } JobsTable_Unlock(&mask); } @@ -2433,7 +2438,6 @@ static void JobInterrupt(bool runINTERRUPT, int signo) { Job *job; - GNode *interrupt; sigset_t mask; aborting = ABORT_INTERRUPT; @@ -2460,10 +2464,10 @@ JobInterrupt(bool runINTERRUPT, int signo) JobsTable_Unlock(&mask); if (runINTERRUPT && !opts.touch) { - interrupt = Targ_FindNode(".INTERRUPT"); - if (interrupt != NULL) { + GNode *dotInterrupt = Targ_FindNode(".INTERRUPT"); + if (dotInterrupt != NULL) { opts.ignoreErrors = false; - JobRun(interrupt); + JobRun(dotInterrupt); } } Trace_Log(MAKEINTR, NULL); @@ -2472,15 +2476,15 @@ JobInterrupt(bool runINTERRUPT, int signo) /* Make the .END target, returning the number of job-related errors. */ int -Job_Finish(void) +Job_MakeDotEnd(void) { - GNode *endNode = Targ_GetEndNode(); - if (!Lst_IsEmpty(&endNode->commands) || - !Lst_IsEmpty(&endNode->children)) { + GNode *dotEnd = Targ_GetEndNode(); + if (!Lst_IsEmpty(&dotEnd->commands) || + !Lst_IsEmpty(&dotEnd->children)) { if (job_errors != 0) Error("Errors reported so .END ignored"); else - JobRun(endNode); + JobRun(dotEnd); } return job_errors; } diff --git a/contrib/bmake/job.h b/contrib/bmake/job.h index 901be0eef1dd..2b4b5e59c37e 100644 --- a/contrib/bmake/job.h +++ b/contrib/bmake/job.h @@ -1,4 +1,4 @@ -/* $NetBSD: job.h,v 1.84 2025/04/22 19:28:50 rillig Exp $ */ +/* $NetBSD: job.h,v 1.85 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -101,7 +101,7 @@ void Job_CatchOutput(void); void Job_Make(GNode *); void Job_Init(void); bool Job_ParseShell(char *) MAKE_ATTR_USE; -int Job_Finish(void); +int Job_MakeDotEnd(void); #ifdef CLEANUP void Job_End(void); #endif diff --git a/contrib/bmake/main.c b/contrib/bmake/main.c index d020ba85f16b..a773b44f42c4 100644 --- a/contrib/bmake/main.c +++ b/contrib/bmake/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.659 2025/06/13 05:41:36 rillig Exp $ */ +/* $NetBSD: main.c,v 1.661 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -111,7 +111,7 @@ #include "trace.h" /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: main.c,v 1.659 2025/06/13 05:41:36 rillig Exp $"); +MAKE_RCSID("$NetBSD: main.c,v 1.661 2025/07/06 07:11:31 rillig Exp $"); #if defined(MAKE_NATIVE) __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " "The Regents of the University of California. " @@ -1221,23 +1221,8 @@ InitMaxJobs(void) if (bogusJflag && !opts.compatMake) { opts.compatMake = true; Parse_Error(PARSE_WARNING, - "internal option \"-J\" in \"%s\" " - "refers to unopened file descriptors; " - "falling back to compat mode.\n" - "\t" - "To run the target even in -n mode, " - "add the .MAKE pseudo-source to the target.\n" - "\t" - "To run the target in default mode only, " - "add a ${:D make} marker to a target's command. " - "(This marker expression expands to an empty string.)\n" - "\t" - "To make the sub-make run in compat mode, add -B to " - "its invocation.\n" - "\t" - "To make the sub-make independent from the parent make, " - "unset the MAKEFLAGS environment variable in the " - "target's commands.", + "Invalid internal option \"-J\" in \"%s\"; " + "see the manual page", curdir); PrintStackTrace(true); return; @@ -1734,11 +1719,10 @@ found: } /* populate av for Cmd_Exec and Compat_RunCommand */ -int -Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz, +void +Cmd_Argv(const char *cmd, size_t cmd_len, const char *av[5], char *cmd_file, size_t cmd_filesz, bool eflag, bool xflag) { - int ac = 0; int cmd_fd = -1; if (shellPath == NULL) @@ -1764,23 +1748,19 @@ Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz, cmd_file[0] = '\0'; } - if (avsz < 4 || (eflag && avsz < 5)) - return -1; - /* The following works for any of the builtin shell specs. */ - av[ac++] = shellPath; + *av++ = shellPath; if (eflag) - av[ac++] = shellErrFlag; + *av++ = shellErrFlag; if (cmd_fd >= 0) { if (xflag) - av[ac++] = "-x"; - av[ac++] = cmd_file; + *av++ = "-x"; + *av++ = cmd_file; } else { - av[ac++] = xflag ? "-xc" : "-c"; - av[ac++] = cmd; + *av++ = xflag ? "-xc" : "-c"; + *av++ = cmd; } - av[ac] = NULL; - return ac; + *av = NULL; } /* @@ -1790,7 +1770,7 @@ Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz, char * Cmd_Exec(const char *cmd, char **error) { - const char *args[4]; /* Arguments for invoking the shell */ + const char *args[5]; /* Arguments for invoking the shell */ int pipefds[2]; int cpid; /* Child PID */ int pid; /* PID from wait() */ @@ -1804,8 +1784,8 @@ Cmd_Exec(const char *cmd, char **error) DEBUG1(VAR, "Capturing the output of command \"%s\"\n", cmd); - if (Cmd_Argv(cmd, 0, args, 4, cmd_file, sizeof(cmd_file), false, false) < 0 - || pipe(pipefds) == -1) { + Cmd_Argv(cmd, 0, args, cmd_file, sizeof(cmd_file), false, false); + if (pipe(pipefds) == -1) { *error = str_concat3( "Couldn't create pipe for \"", cmd, "\""); return bmake_strdup(""); @@ -2083,7 +2063,7 @@ shouldDieQuietly(GNode *gn, int bf) else if (bf >= 0) quietly = bf; else - quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0; + quietly = gn != NULL && gn->type & OP_MAKE ? 1 : 0; } return quietly != 0; } diff --git a/contrib/bmake/make.1 b/contrib/bmake/make.1 index f05653af7e31..de67759290c4 100644 --- a/contrib/bmake/make.1 +++ b/contrib/bmake/make.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.385 2025/06/13 03:51:18 rillig Exp $ +.\" $NetBSD: make.1,v 1.387 2025/07/02 17:11:56 rillig Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd June 12, 2025 +.Dd July 2, 2025 .Dt MAKE 1 .Os .Sh NAME @@ -785,11 +785,13 @@ Is redundant with respect to global variables, which have already been expanded. .El .Pp -The seven built-in local variables are: +The built-in local variables are: .Bl -tag -width ".Va .ARCHIVE" -offset indent .It Va .ALLSRC The list of all sources for this target; also known as -.Sq Va \&> . +.Sq Va \&> +or +.Sq Va \&^ . .It Va .ARCHIVE The name of the archive file; also known as .Sq Va \&! . @@ -823,6 +825,7 @@ in archive member rules. The shorter forms .Po .Sq Va \&> , +.Sq Va \&^ , .Sq Va \&! , .Sq Va \&< , .Sq Va \&% , @@ -2725,6 +2728,8 @@ If the environment variable is set to .Dq yes , any stack traces include the call chain of the parent processes. +.\" .Sh EXIT STATUS +.\" .Sh ENVIRONMENT .Sh FILES .Bl -tag -width /usr/share/mk -compact .It .depend @@ -2738,6 +2743,68 @@ system makefile .It /usr/share/mk system makefile directory .El +.\" .Sh EXAMPLES +.Sh DIAGNOSTICS +.Bl -tag +.It Dv Invalid internal option \(dq-J\(dq in \(dq Ns Ar directory Ns Dv \(dq +The internal +.Fl J +option coordinates the main +.Nm +process with the sub-make processes to limit +the number of jobs that run in parallel. +The option is passed to all child processes via the +.Ev MAKEFLAGS +environment variable. +To become valid, +this option requires that the target running the sub-make is marked with the +.Dv .MAKE +special source, +or that one of the target's commands directly contains the word +.Dq make +or one of the expressions +.Dq ${MAKE} , +.Dq ${.MAKE} , +.Dq $(MAKE) , +.Dq $(.MAKE) . +If that's not the case, +make issues the above warning and falls back to compat mode. +.Pp +To see the chain of sub-makes that leads to the invalid option, set the +.Ev MAKE_STACK_TRACE +environment variable to +.Dq yes . +.Pp +To run the sub-make in parallel mode, even in dry-run mode (see the +.Fl n +option), add the +.Dv .MAKE +pseudo source to the target. +This is appropriate when the sub-make runs the same target in a subdirectory. +.Pp +To run the sub-make in parallel mode but not in dry-mode, +add a +.Dq ${:D make} +marker to one of the target's commands. +This marker expands to an empty string +and thus does not affect the executed commands. +.\" The marker can even be added before any of the "@+-" modifiers, +.\" so no need to mention this explicitly. +.Pp +To run the sub-make in compat mode, add the +.Fl B +option to its invocation. +This is appropriate when the sub-make is only used to print a variable's +value using the +.Fl v +or +.Fl V +options. +.Pp +To make the sub-make independent from the parent make, unset the +.Ev MAKEFLAGS +environment variable in the target's commands. +.El .Sh COMPATIBILITY The basic make syntax is compatible between different make variants; however the special variables, variable modifiers and conditionals are not. @@ -2825,6 +2892,7 @@ portable. .Sh SEE ALSO .Xr mkdep 1 , .Xr style.Makefile 5 +.\" .Sh STANDARDS .Sh HISTORY A .Nm @@ -2844,6 +2912,8 @@ has been used to FoRCe rebuilding (since the target/dependency does not exist ... unless someone creates an .Pa FRC file). +.\" .Sh AUTHORS +.\" .Sh CAVEATS .Sh BUGS The .Nm @@ -2865,3 +2935,4 @@ using that token pool to abort the build and exit with error code 6. Sometimes the attempt to suppress a cascade of unnecessary errors, can result in a seemingly unexplained .Ql *** Error code 6 +.\" .Sh SECURITY CONSIDERATIONS diff --git a/contrib/bmake/make.c b/contrib/bmake/make.c index 3826c4d4e6a1..811f6e0849c4 100644 --- a/contrib/bmake/make.c +++ b/contrib/bmake/make.c @@ -1,4 +1,4 @@ -/* $NetBSD: make.c,v 1.272 2025/05/18 07:02:00 rillig Exp $ */ +/* $NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -107,7 +107,7 @@ #endif /* "@(#)make.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: make.c,v 1.272 2025/05/18 07:02:00 rillig Exp $"); +MAKE_RCSID("$NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $"); /* Sequence # to detect recursion. */ static unsigned checked_seqno = 1; @@ -1404,7 +1404,7 @@ Make_MakeParallel(GNodeList *targets) (void)MakeStartJobs(); } - errors = Job_Finish(); + errors = Job_MakeDotEnd(); DEBUG1(MAKE, "done: errors %d\n", errors); if (errors == 0) { diff --git a/contrib/bmake/make.h b/contrib/bmake/make.h index 405f03144b69..6b2b215592dd 100644 --- a/contrib/bmake/make.h +++ b/contrib/bmake/make.h @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.360 2025/06/13 18:31:08 rillig Exp $ */ +/* $NetBSD: make.h,v 1.361 2025/07/06 07:11:31 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -884,7 +884,8 @@ void JobReapChild(pid_t, int, bool); #endif /* main.c */ void Main_ParseArgLine(const char *); -int Cmd_Argv(const char *, size_t, const char **, size_t, char *, size_t, bool, bool); +void Cmd_Argv(const char *, size_t, const char *[5], char *, size_t, + bool, bool); char *Cmd_Exec(const char *, char **) MAKE_ATTR_USE; void Var_ExportStackTrace(const char *, const char *); void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); diff --git a/contrib/bmake/make_malloc.c b/contrib/bmake/make_malloc.c index d7a735b8b08e..86e339de5dd2 100644 --- a/contrib/bmake/make_malloc.c +++ b/contrib/bmake/make_malloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: make_malloc.c,v 1.27 2025/06/12 18:51:05 rillig Exp $ */ +/* $NetBSD: make_malloc.c,v 1.28 2025/06/29 09:37:58 rillig Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ #include "make.h" -MAKE_RCSID("$NetBSD: make_malloc.c,v 1.27 2025/06/12 18:51:05 rillig Exp $"); +MAKE_RCSID("$NetBSD: make_malloc.c,v 1.28 2025/06/29 09:37:58 rillig Exp $"); #ifndef USE_EMALLOC @@ -50,6 +50,9 @@ bmake_malloc(size_t len) if ((p = malloc(len)) == NULL) enomem(); +#ifdef CLEANUP + memset(p, 'Z', len); +#endif return p; } diff --git a/contrib/bmake/mk/ChangeLog b/contrib/bmake/mk/ChangeLog index 1822f917a138..db524d2343b6 100644 --- a/contrib/bmake/mk/ChangeLog +++ b/contrib/bmake/mk/ChangeLog @@ -1,3 +1,7 @@ +2025-07-04 Simon J Gerraty <sjg@beast.crufty.net> + + * prog.mk: .MADE is a special source not a target! + 2025-05-28 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20250528 diff --git a/contrib/bmake/mk/prog.mk b/contrib/bmake/mk/prog.mk index 119645c49859..a7ced7b15d31 100644 --- a/contrib/bmake/mk/prog.mk +++ b/contrib/bmake/mk/prog.mk @@ -1,4 +1,4 @@ -# $Id: prog.mk,v 1.45 2024/12/12 19:56:36 sjg Exp $ +# $Id: prog.mk,v 1.46 2025/07/05 16:43:03 sjg Exp $ # should be set properly in sys.mk _this ?= ${.PARSEFILE:S,bsd.,,} @@ -27,11 +27,11 @@ CFLAGS+= -mcmodel=medlow .if ${OBJECT_FMT} == "ELF" .ifndef LIBCRTBEGIN LIBCRTBEGIN= ${DESTDIR}/usr/lib/crtbegin.o -.MADE: ${LIBCRTBEGIN} +${LIBCRTBEGIN}: .MADE .endif .ifndef LIBCRTEND LIBCRTEND= ${DESTDIR}/usr/lib/crtend.o -.MADE: ${LIBCRTEND} +${LIBCRTEND}: .MADE .endif _SHLINKER= ${SHLINKDIR}/ld.elf_so .else @@ -42,7 +42,7 @@ _SHLINKER= ${SHLINKDIR}/ld.so .ifndef LIBCRT0 LIBCRT0= ${DESTDIR}/usr/lib/crt0.o -.MADE: ${LIBCRT0} +${LIBCRT0}: .MADE .endif .endif # NetBSD diff --git a/contrib/bmake/parse.c b/contrib/bmake/parse.c index 844d4db207ca..ecc77366d2d7 100644 --- a/contrib/bmake/parse.c +++ b/contrib/bmake/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.752 2025/06/16 18:20:00 rillig Exp $ */ +/* $NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -110,7 +110,7 @@ #include "pathnames.h" /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: parse.c,v 1.752 2025/06/16 18:20:00 rillig Exp $"); +MAKE_RCSID("$NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $"); /* Detects a multiple-inclusion guard in a makefile. */ typedef enum { @@ -954,10 +954,10 @@ InvalidLineType(const char *line, const char *unexpanded_line) Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"", (int)(dirend - dirstart), dirstart); } else if (strcmp(line, unexpanded_line) == 0) - Parse_Error(PARSE_FATAL, "Invalid line '%s'", line); + Parse_Error(PARSE_FATAL, "Invalid line \"%s\"", line); else Parse_Error(PARSE_FATAL, - "Invalid line '%s', expanded to '%s'", + "Invalid line \"%s\", expanded to \"%s\"", unexpanded_line, line); } @@ -1063,7 +1063,7 @@ HandleDependencyTargetPath(const char *suffixName, path = Suff_GetPath(suffixName); if (path == NULL) { Parse_Error(PARSE_FATAL, - "Suffix '%s' not defined (yet)", suffixName); + "Suffix \"%s\" not defined (yet)", suffixName); return false; } @@ -1159,7 +1159,7 @@ SkipExtraTargets(char **pp, const char *lstart) if (warning) { const char *start = *pp; cpp_skip_whitespace(&start); - Parse_Error(PARSE_WARNING, "Extra target '%.*s' ignored", + Parse_Error(PARSE_WARNING, "Extra target \"%.*s\" ignored", (int)(p - start), start); } @@ -1446,7 +1446,8 @@ ApplyDependencyTarget(char *name, char *nameEnd, ParseSpecial *inout_special, if (*inout_special == SP_NOT && *name != '\0') HandleDependencyTargetMundane(name); else if (*inout_special == SP_PATH && *name != '.' && *name != '\0') - Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", name); + Parse_Error(PARSE_WARNING, "Extra target \"%s\" ignored", + name); *nameEnd = savedNameEnd; return true; @@ -2066,7 +2067,7 @@ ParseInclude(char *directive) if (*p != '"' && *p != '<') { Parse_Error(PARSE_FATAL, - ".include filename must be delimited by '\"' or '<'"); + ".include filename must be delimited by \"\" or <>"); return; } @@ -2078,7 +2079,7 @@ ParseInclude(char *directive) if (*p != endc) { Parse_Error(PARSE_FATAL, - "Unclosed .include filename. '%c' expected", endc); + "Unclosed .include filename, \"%c\" expected", endc); return; } diff --git a/contrib/bmake/str.c b/contrib/bmake/str.c index f705b0deb874..e66cdbc8682e 100644 --- a/contrib/bmake/str.c +++ b/contrib/bmake/str.c @@ -1,4 +1,4 @@ -/* $NetBSD: str.c,v 1.105 2024/07/07 07:50:57 rillig Exp $ */ +/* $NetBSD: str.c,v 1.106 2025/06/28 21:09:43 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -71,7 +71,7 @@ #include "make.h" /* "@(#)str.c 5.8 (Berkeley) 6/1/90" */ -MAKE_RCSID("$NetBSD: str.c,v 1.105 2024/07/07 07:50:57 rillig Exp $"); +MAKE_RCSID("$NetBSD: str.c,v 1.106 2025/06/28 21:09:43 rillig Exp $"); static HashTable interned_strings; @@ -363,8 +363,11 @@ match_fixed_length: continue; } - if (*pat == '\\') /* match the next character exactly */ + if (*pat == '\\') { /* match the next character exactly */ pat++; + if (*pat == '\0') + res.error = "Unfinished backslash at the end"; + } if (*pat != *str) { if (asterisk && str == fixed_str) { while (*str != '\0' && *str != *pat) diff --git a/contrib/bmake/unit-tests/Makefile b/contrib/bmake/unit-tests/Makefile index 618a5959e304..4e639056815a 100644 --- a/contrib/bmake/unit-tests/Makefile +++ b/contrib/bmake/unit-tests/Makefile @@ -1,6 +1,6 @@ -# $Id: Makefile,v 1.239 2025/06/15 21:32:16 sjg Exp $ +# $Id: Makefile,v 1.240 2025/06/30 18:40:54 sjg Exp $ # -# $NetBSD: Makefile,v 1.367 2025/06/13 20:23:16 rillig Exp $ +# $NetBSD: Makefile,v 1.369 2025/06/29 09:40:13 rillig Exp $ # # Unit tests for make(1) # @@ -58,6 +58,7 @@ rm-tmpdir: .NOMETA # src/tests/usr.bin/make/t_make.sh as well. #TESTS+= archive #TESTS+= archive-suffix +TESTS+= char-005c-reverse-solidus TESTS+= cmd-errors TESTS+= cmd-errors-jobs TESTS+= cmd-errors-lint @@ -413,6 +414,7 @@ TESTS+= varmod-to-upper TESTS+= varmod-undefined TESTS+= varmod-unique TESTS+= varname +TESTS+= varname-circumflex TESTS+= varname-dollar TESTS+= varname-dot-alltargets TESTS+= varname-dot-curdir @@ -541,7 +543,6 @@ TESTS:= ${TESTS:${BROKEN_TESTS:S,^,N,:ts:}} # Ideas for more tests: # char-0020-space.mk -# char-005C-backslash.mk # escape-cond-str.mk # escape-cond-func-arg.mk # escape-varmod.mk diff --git a/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp b/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp new file mode 100644 index 000000000000..351ef95040e5 --- /dev/null +++ b/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp @@ -0,0 +1,13 @@ +make: char-005c-reverse-solidus.mk:57: Unclosed expression, expecting "}" for modifier "Mx\}" + while evaluating variable "BACKSLASH" with value "" +make: char-005c-reverse-solidus.mk:64: Unclosed expression, expecting "}" for modifier "Mx\\}" + while evaluating variable "BACKSLASH" with value "" +make: char-005c-reverse-solidus.mk:71: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}" + while evaluating variable "BACKSLASH" with value "" +make: char-005c-reverse-solidus.mk:100: Unfinished backslash at the end in pattern "\" of modifier ":M" + while evaluating variable "BACKSLASH" with value "\" +make: char-005c-reverse-solidus.mk:111: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\"" + while evaluating variable "BACKSLASH" with value "" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk b/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk new file mode 100644 index 000000000000..7a151ac46322 --- /dev/null +++ b/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk @@ -0,0 +1,131 @@ +# $NetBSD: char-005c-reverse-solidus.mk,v 1.2 2025/06/29 11:27:21 rillig Exp $ +# +# Tests for the character U+005C "REVERSE SOLIDUS". +# +# See also: +# TODO +# TODO +# TODO + +# TODO: Where is this character used normally? +# TODO: What are the edge cases? + +# TODO: escape '#' in lines +# TODO: escape '#' in comments +# TODO: escape ':' in modifiers +# TODO: escape any character in condition strings + +# begin https://gnats.netbsd.org/46139 + +# Too see the details of parsing, uncomment the following line. +#.MAKEFLAGS: -dcpv + +# This backslash is treated as a line continuation. +# It does not end up in the variable value. +LINE_CONTINUATION=foo\ +# This line is still part of the variable assignment +.if ${LINE_CONTINUATION:C,[^a-z],<>,gW} != "foo" +. error +.endif + +# The variable value contains two backslashes. +TWO_BACKSLASHES_AT_EOL=foo\\ +.if ${TWO_BACKSLASHES_AT_EOL:C,[^a-z],<>,gW} != "foo<><>" +. error +.endif + +TRAILING_WHITESPACE=foo\ # trailing space +.if ${TRAILING_WHITESPACE:C,[^a-z],<>,gW} != "foo<><>" +. error +.endif + +# The simplest was to produce a single backslash is the :U modifier. +BACKSLASH= ${:U\\} +.if ${BACKSLASH} != "\\" +. error +.endif +BACKSLASH_C= ${:U1:C,.,\\,} +.if ${BACKSLASH_C} != "\\" +. error +.endif + +# expect+5: Unclosed expression, expecting "}" for modifier "Mx\}" +# At the point where the unclosed expression is detected, the ":M" modifier +# has been applied to the expression. Its pattern is "x}", which doesn't +# match the single backslash. +# expect: while evaluating variable "BACKSLASH" with value "" +.if ${BACKSLASH:Mx\} +. error +.else +. error +.endif + +# expect+1: Unclosed expression, expecting "}" for modifier "Mx\\}" +.if ${BACKSLASH:Mx\\} +. error +.else +. error +.endif + +# expect+1: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}" +.if ${BACKSLASH:Mx\\\\\\\\} +. error +.else +. error +.endif + +# Adding more text after the backslash adds to the pattern, as the backslash +# serves to escape the ":" that is otherwise used to separate the modifiers. +# The result is a single ":M" modifier with the pattern "x:Nzzz". +.if ${BACKSLASH:Mx\:Nzzz} != "" +. error +.endif + +# The pattern ends up as "x\:Nzzz". Only the sequence "\:" is unescaped, all +# others, including "\\", are left as-is. +.if ${BACKSLASH:Mx\\:Nzzz} != "" +. error +.endif + +# The pattern for the ":M" modifier ends up as "x\\\\\\\:Nzzz". Only the +# sequence "\:" is unescaped, all others, including "\\", are left as-is. +.if ${BACKSLASH:Mx\\\\\\\\:Nzzz} != "" +. error +.endif + +# The ":M" modifier is parsed differently than the other modifiers. To +# circumvent the peculiarities of that parser, the pattern can be passed via +# an expression. There, the usual escaping rules for modifiers apply. +# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M" +.if ${BACKSLASH:M${BACKSLASH}} != "\\" +. error +.else +. error +.endif + +# Trying to bypass the parser by using a direct expression doesn't work, as +# the parser for the ":M" modifier does not parse the subexpression like in +# all other places, but instead counts the braces and tries to decode the +# escaping, which fails in this case. +# expect+1: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\"" +.if ${BACKSLASH:M${:U\\\\}} != "\\" +. error +.else +. error +.endif + +# Matching a backslash with the pattern matching characters works. +.if ${BACKSLASH:M?} != "\\" +. error +.endif +.if ${BACKSLASH:M*} != "\\" +. error +.endif +.if ${BACKSLASH:M[Z-a]} != "\\" +. error +.endif +.if ${BACKSLASH:M[\\]} != "\\" +. error +.endif + +# end https://gnats.netbsd.org/46139 diff --git a/contrib/bmake/unit-tests/check-expect.lua b/contrib/bmake/unit-tests/check-expect.lua index 218056fbc021..2f3adf49baa6 100644 --- a/contrib/bmake/unit-tests/check-expect.lua +++ b/contrib/bmake/unit-tests/check-expect.lua @@ -1,5 +1,5 @@ #! /usr/bin/lua --- $NetBSD: check-expect.lua,v 1.13 2025/04/13 09:29:32 rillig Exp $ +-- $NetBSD: check-expect.lua,v 1.17 2025/07/01 05:03:18 rillig Exp $ --[[ @@ -9,29 +9,32 @@ Check that the various 'expect' comments in the .mk files produce the expected text in the corresponding .exp file. # expect: <line> - All of these lines must occur in the .exp file, in the same order as - in the .mk file. - -# expect-reset - Search the following 'expect:' comments from the top of the .exp - file again. + Each <line> must occur in the .exp file. + The order in the .mk file must be the same as in the .exp file. # expect[+-]offset: <message> - Each message must occur in the .exp file and refer back to the + Each <message> must occur in the .exp file and refer back to the source line in the .mk file. + Each such line in the .exp file must have a corresponding expect line + in the .mk file. + The order in the .mk file must be the same as in the .exp file. + +# expect-reset + Search the following "expect:" and "expect[+-]offset:" comments + from the top of the .exp file again. # expect-not: <substring> - The substring must not occur as part of any line of the .exp file. + The <substring> must not occur as part of any line in the .exp file. # expect-not-matches: <pattern> - The pattern (see https://lua.org/manual/5.4/manual.html#6.4.1) - must not occur as part of any line of the .exp file. + The <pattern> (see https://lua.org/manual/5.4/manual.html#6.4.1) + must not occur as part of any line in the .exp file. ]] local had_errors = false ---@param fmt string -function print_error(fmt, ...) +local function print_error(fmt, ...) print(fmt:format(...)) had_errors = true end @@ -42,7 +45,9 @@ local function load_lines(fname) local lines = {} local f = io.open(fname, "r") - if f == nil then return nil end + if f == nil then + return nil + end for line in f:lines() do table.insert(lines, line) @@ -53,135 +58,129 @@ local function load_lines(fname) end ----@param exp_lines string[] -local function collect_lineno_diagnostics(exp_lines) - ---@type table<string, string[]> - local by_location = {} +--- @shape ExpLine +--- @field filename string | nil +--- @field lineno number | nil +--- @field text string - for _, line in ipairs(exp_lines) do - ---@type string | nil, string, string - local l_fname, l_lineno, l_msg = - line:match('^make: ([^:]+):(%d+): (.*)') - if l_fname ~= nil then - local location = ("%s:%d"):format(l_fname, l_lineno) - if by_location[location] == nil then - by_location[location] = {} - end - table.insert(by_location[location], l_msg) + +--- @param lines string[] +--- @return ExpLine[] +local function parse_exp(lines) + local exp_lines = {} + for _, line in ipairs(lines) do + local l_filename, l_lineno, l_text = + line:match('^make: ([^:]+%.mk):(%d+):%s+(.*)') + if not l_filename then + l_text = line end + l_text = l_text:gsub("^%s+", ""):gsub("%s+$", "") + table.insert(exp_lines, { + filename = l_filename, + lineno = tonumber(l_lineno), + text = l_text, + }) end - - return by_location + return exp_lines end - -local function missing(by_location) - ---@type {filename: string, lineno: number, location: string, message: string}[] - local missing_expectations = {} - - for location, messages in pairs(by_location) do - for _, message in ipairs(messages) do - if message ~= "" and location:find(".mk:") then - local filename, lineno = location:match("^(%S+):(%d+)$") - table.insert(missing_expectations, { - filename = filename, - lineno = tonumber(lineno), - location = location, - message = message - }) - end +---@param exp_lines ExpLine[] +local function detect_missing_expect_lines(exp_fname, exp_lines, s, e) + for i = s, e do + local exp_line = exp_lines[i] + if exp_line.filename then + print_error("error: %s:%d requires in %s:%d: # expect+1: %s", + exp_fname, i, exp_line.filename, exp_line.lineno, exp_line.text) end end - table.sort(missing_expectations, function(a, b) - if a.filename ~= b.filename then - return a.filename < b.filename - end - return a.lineno < b.lineno - end) - return missing_expectations end - local function check_mk(mk_fname) local exp_fname = mk_fname:gsub("%.mk$", ".exp") local mk_lines = load_lines(mk_fname) - local exp_lines = load_lines(exp_fname) - if exp_lines == nil then return end - local by_location = collect_lineno_diagnostics(exp_lines) - local prev_expect_line = 0 + local exp_raw_lines = load_lines(exp_fname) + if exp_raw_lines == nil then + return + end + local exp_lines = parse_exp(exp_raw_lines) + + local exp_it = 1 for mk_lineno, mk_line in ipairs(mk_lines) do - for text in mk_line:gmatch("#%s*expect%-not:%s*(.*)") do - local i = 1 - while i <= #exp_lines and not exp_lines[i]:find(text, 1, true) do - i = i + 1 - end - if i <= #exp_lines then - print_error("error: %s:%d: %s must not contain '%s'", - mk_fname, mk_lineno, exp_fname, text) + local function match(pattern, action) + local _, n = mk_line:gsub(pattern, action) + if n > 0 then + match = function() end end end - for text in mk_line:gmatch("#%s*expect%-not%-matches:%s*(.*)") do - local i = 1 - while i <= #exp_lines and not exp_lines[i]:find(text) do - i = i + 1 + match("^#%s+expect%-not:%s*(.*)", function(text) + for exp_lineno, exp_line in ipairs(exp_lines) do + if exp_line.text:find(text, 1, true) then + print_error("error: %s:%d: %s:%d must not contain '%s'", + mk_fname, mk_lineno, exp_fname, exp_lineno, text) + end end - if i <= #exp_lines then - print_error("error: %s:%d: %s must not match '%s'", - mk_fname, mk_lineno, exp_fname, text) + end) + + match("^#%s+expect%-not%-matches:%s*(.*)", function(pattern) + for exp_lineno, exp_line in ipairs(exp_lines) do + if exp_line.text:find(pattern) then + print_error("error: %s:%d: %s:%d must not match '%s'", + mk_fname, mk_lineno, exp_fname, exp_lineno, pattern) + end end - end + end) - for text in mk_line:gmatch("#%s*expect:%s*(.*)") do - local i = prev_expect_line - -- As of 2022-04-15, some lines in the .exp files contain trailing - -- whitespace. If possible, this should be avoided by rewriting the - -- debug logging. When done, the trailing gsub can be removed. - -- See deptgt-phony.exp lines 14 and 15. - while i < #exp_lines and text ~= exp_lines[i + 1]:gsub("^%s*", ""):gsub("%s*$", "") do + match("^#%s+expect:%s*(.*)", function(text) + local i = exp_it + while i <= #exp_lines and text ~= exp_lines[i].text do i = i + 1 end - if i < #exp_lines then - prev_expect_line = i + 1 + if i <= #exp_lines then + detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) + exp_lines[i].text = "" + exp_it = i + 1 else print_error("error: %s:%d: '%s:%d+' must contain '%s'", - mk_fname, mk_lineno, exp_fname, prev_expect_line + 1, text) + mk_fname, mk_lineno, exp_fname, exp_it, text) end - end - if mk_line:match("^#%s*expect%-reset$") then - prev_expect_line = 0 - end + end) - ---@param text string - for offset, text in mk_line:gmatch("#%s*expect([+%-]%d+):%s*(.*)") do - local location = ("%s:%d"):format(mk_fname, mk_lineno + tonumber(offset)) - - local found = false - if by_location[location] ~= nil then - for i, message in ipairs(by_location[location]) do - if message == text then - by_location[location][i] = "" - found = true - break - elseif message ~= "" then - print_error("error: %s:%d: out-of-order '%s'", - mk_fname, mk_lineno, message) - end - end + match("^#%s+expect%-reset$", function() + exp_it = 1 + end) + + match("^#%s+expect([+%-]%d+):%s*(.*)", function(offset, text) + local msg_lineno = mk_lineno + tonumber(offset) + + local i = exp_it + while i <= #exp_lines and text ~= exp_lines[i].text do + i = i + 1 end - if not found then - print_error("error: %s:%d: %s must contain '%s'", - mk_fname, mk_lineno, exp_fname, text) + if i <= #exp_lines and exp_lines[i].lineno == msg_lineno then + detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1) + exp_lines[i].text = "" + exp_it = i + 1 + elseif i <= #exp_lines then + print_error("error: %s:%d: expect%+d must be expect%+d", + mk_fname, mk_lineno, tonumber(offset), + exp_lines[i].lineno - mk_lineno) + else + print_error("error: %s:%d: %s:%d+ must contain '%s'", + mk_fname, mk_lineno, exp_fname, exp_it, text) end - end - end + end) + + match("^#%s+expect[+%-:]", function() + print_error("error: %s:%d: invalid \"expect\" line: %s", + mk_fname, mk_lineno, mk_line) + end) - for _, m in ipairs(missing(by_location)) do - print_error("missing: %s: # expect+1: %s", m.location, m.message) end + detect_missing_expect_lines(exp_fname, exp_lines, exp_it, #exp_lines) end for _, fname in ipairs(arg) do diff --git a/contrib/bmake/unit-tests/cmd-errors-jobs.exp b/contrib/bmake/unit-tests/cmd-errors-jobs.exp index bd3ae1e51332..3be1bb9b0773 100644 --- a/contrib/bmake/unit-tests/cmd-errors-jobs.exp +++ b/contrib/bmake/unit-tests/cmd-errors-jobs.exp @@ -11,7 +11,7 @@ make: Unclosed variable "UNCLOSED" in command ": unexpected $@-${UNCLOSED" in target "parse-error-unclosed-expression" in make[1] in directory "<curdir>" -make: Unclosed expression, expecting '}' +make: Unclosed expression, expecting "}" while evaluating variable "UNCLOSED" with value "" in command ": unexpected $@-${UNCLOSED:" in target "parse-error-unclosed-modifier" @@ -28,7 +28,7 @@ make: Unclosed variable "UNCLOSED" in command ": unexpected $@-${UNCLOSED" in target "parse-error-unclosed-expression" in make[1] in directory "<curdir>" -make: Unclosed expression, expecting '}' +make: Unclosed expression, expecting "}" while evaluating variable "UNCLOSED" with value "" in command ": unexpected $@-${UNCLOSED:" in target "parse-error-unclosed-modifier" diff --git a/contrib/bmake/unit-tests/cmd-errors-jobs.mk b/contrib/bmake/unit-tests/cmd-errors-jobs.mk index a29883fc6676..f6261d6ad1a8 100644 --- a/contrib/bmake/unit-tests/cmd-errors-jobs.mk +++ b/contrib/bmake/unit-tests/cmd-errors-jobs.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmd-errors-jobs.mk,v 1.15 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: cmd-errors-jobs.mk,v 1.16 2025/06/28 22:39:28 rillig Exp $ # # Demonstrate how errors in expressions affect whether the commands # are actually executed in jobs mode. @@ -50,11 +50,11 @@ parse-error-unknown-modifier: # expect-not-matches: ^: unexpected # expect: make: Unclosed variable "UNCLOSED" # expect: in command ": unexpected $@-${UNCLOSED" -# expect: make: Unclosed expression, expecting '}' +# expect: make: Unclosed expression, expecting "}" # expect: make: Unknown modifier ":Z" # expect: end parse-error-direct with status 2 # expect: make: Unclosed variable "UNCLOSED" -# expect: make: Unclosed expression, expecting '}' +# expect: make: Unclosed expression, expecting "}" # expect: make: Unknown modifier ":Z" # expect: end parse-error-indirect with status 2 diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.exp b/contrib/bmake/unit-tests/cmd-errors-lint.exp index ec7336f618b8..b08a65ff96dc 100644 --- a/contrib/bmake/unit-tests/cmd-errors-lint.exp +++ b/contrib/bmake/unit-tests/cmd-errors-lint.exp @@ -2,7 +2,7 @@ make: Unclosed variable "UNCLOSED" in command ": $@ ${UNCLOSED" in target "unclosed-expression" -make: Unclosed expression, expecting '}' +make: Unclosed expression, expecting "}" while evaluating variable "UNCLOSED" with value "" in command ": $@ ${UNCLOSED:" in target "unclosed-modifier" diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.mk b/contrib/bmake/unit-tests/cmd-errors-lint.mk index eb2ec1171545..455ef2c0cfe7 100644 --- a/contrib/bmake/unit-tests/cmd-errors-lint.mk +++ b/contrib/bmake/unit-tests/cmd-errors-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmd-errors-lint.mk,v 1.7 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: cmd-errors-lint.mk,v 1.8 2025/06/28 22:39:28 rillig Exp $ # # Demonstrate how errors in expressions affect whether the commands # are actually executed. @@ -19,7 +19,7 @@ unclosed-expression: : $@ ${UNCLOSED unclosed-modifier: -# expect: make: Unclosed expression, expecting '}' +# expect: make: Unclosed expression, expecting "}" # expect-not: : unclosed-modifier : $@ ${UNCLOSED: diff --git a/contrib/bmake/unit-tests/cmd-errors.exp b/contrib/bmake/unit-tests/cmd-errors.exp index 62da47ff42c5..2916d423029e 100644 --- a/contrib/bmake/unit-tests/cmd-errors.exp +++ b/contrib/bmake/unit-tests/cmd-errors.exp @@ -2,7 +2,7 @@ make: Unclosed variable "UNCLOSED" in command ": $@-${UNCLOSED" in target "unclosed-expression" -make: Unclosed expression, expecting '}' +make: Unclosed expression, expecting "}" while evaluating variable "UNCLOSED" with value "" in command ": $@-${UNCLOSED:" in target "unclosed-modifier" diff --git a/contrib/bmake/unit-tests/cmd-errors.mk b/contrib/bmake/unit-tests/cmd-errors.mk index 8766b6a856c7..52e314c5bd38 100644 --- a/contrib/bmake/unit-tests/cmd-errors.mk +++ b/contrib/bmake/unit-tests/cmd-errors.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmd-errors.mk,v 1.12 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: cmd-errors.mk,v 1.13 2025/06/28 22:39:28 rillig Exp $ # # Demonstrate how errors in expressions affect whether the commands # are actually executed in compat mode. @@ -17,7 +17,7 @@ unclosed-expression: : $@-${UNCLOSED unclosed-modifier: -# expect: make: Unclosed expression, expecting '}' +# expect: make: Unclosed expression, expecting "}" # expect-not: : unclosed-modifier- : $@-${UNCLOSED: diff --git a/contrib/bmake/unit-tests/cmdline-undefined.exp b/contrib/bmake/unit-tests/cmdline-undefined.exp index 12fc45e50822..ae0b35dac420 100644 --- a/contrib/bmake/unit-tests/cmdline-undefined.exp +++ b/contrib/bmake/unit-tests/cmdline-undefined.exp @@ -1,17 +1,17 @@ The = assignment operator -make: cmdline-undefined.mk:31: From the command line: Undefined is . -make: cmdline-undefined.mk:34: From .MAKEFLAGS '=': Undefined is . -make: cmdline-undefined.mk:37: From .MAKEFLAGS ':=': Undefined is . -make: cmdline-undefined.mk:43: From the command line: Undefined is now defined. -make: cmdline-undefined.mk:46: From .MAKEFLAGS '=': Undefined is now defined. +make: cmdline-undefined.mk:41: From the command line: Undefined is . +make: cmdline-undefined.mk:42: From .MAKEFLAGS '=': Undefined is . +make: cmdline-undefined.mk:43: From .MAKEFLAGS ':=': Undefined is . +make: cmdline-undefined.mk:47: From the command line: Undefined is now defined. +make: cmdline-undefined.mk:48: From .MAKEFLAGS '=': Undefined is now defined. make: cmdline-undefined.mk:49: From .MAKEFLAGS ':=': Undefined is now defined. The := assignment operator -make: cmdline-undefined.mk:31: From the command line: Undefined is . -make: cmdline-undefined.mk:34: From .MAKEFLAGS '=': Undefined is . -make: cmdline-undefined.mk:37: From .MAKEFLAGS ':=': Undefined is . -make: cmdline-undefined.mk:43: From the command line: Undefined is now defined. -make: cmdline-undefined.mk:46: From .MAKEFLAGS '=': Undefined is now defined. +make: cmdline-undefined.mk:41: From the command line: Undefined is . +make: cmdline-undefined.mk:42: From .MAKEFLAGS '=': Undefined is . +make: cmdline-undefined.mk:43: From .MAKEFLAGS ':=': Undefined is . +make: cmdline-undefined.mk:47: From the command line: Undefined is now defined. +make: cmdline-undefined.mk:48: From .MAKEFLAGS '=': Undefined is now defined. make: cmdline-undefined.mk:49: From .MAKEFLAGS ':=': Undefined is now defined. exit status 0 diff --git a/contrib/bmake/unit-tests/cmdline-undefined.mk b/contrib/bmake/unit-tests/cmdline-undefined.mk index e7c0400ad1e1..2deb944b1fab 100644 --- a/contrib/bmake/unit-tests/cmdline-undefined.mk +++ b/contrib/bmake/unit-tests/cmdline-undefined.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmdline-undefined.mk,v 1.5 2024/04/23 22:51:28 rillig Exp $ +# $NetBSD: cmdline-undefined.mk,v 1.6 2025/06/30 21:44:39 rillig Exp $ # # Tests for undefined variables in expressions in the command line. @@ -8,6 +8,12 @@ all: # (which probably occurs rarely in practice, if at all), but their # variable value is not expanded, as usual. # +# expect+30: From the command line: Undefined is . +# expect+30: From .MAKEFLAGS '=': Undefined is . +# expect+30: From .MAKEFLAGS ':=': Undefined is . +# expect+33: From the command line: Undefined is now defined. +# expect+33: From .MAKEFLAGS '=': Undefined is now defined. +# expect+33: From .MAKEFLAGS ':=': Undefined is now defined. @echo 'The = assignment operator' @${.MAKE} -f ${MAKEFILE} print-undefined \ CMDLINE='Undefined is $${UNDEFINED}.' @@ -16,6 +22,12 @@ all: # The interesting case is using the ':=' assignment operator, which # expands its right-hand side. But only those variables that are # defined. +# expect+16: From the command line: Undefined is . +# expect+16: From .MAKEFLAGS '=': Undefined is . +# expect+16: From .MAKEFLAGS ':=': Undefined is . +# expect+19: From the command line: Undefined is now defined. +# expect+19: From .MAKEFLAGS '=': Undefined is now defined. +# expect+19: From .MAKEFLAGS ':=': Undefined is now defined. @echo 'The := assignment operator' @${.MAKE} -f ${MAKEFILE} print-undefined \ CMDLINE:='Undefined is $${UNDEFINED}.' @@ -26,26 +38,14 @@ all: .MAKEFLAGS: MAKEFLAGS_ASSIGN='Undefined is $${UNDEFINED}.' .MAKEFLAGS: MAKEFLAGS_SUBST:='Undefined is $${UNDEFINED}.' -# expect+2: From the command line: Undefined is . -# expect+1: From the command line: Undefined is . .info From the command line: ${CMDLINE} -# expect+2: From .MAKEFLAGS '=': Undefined is . -# expect+1: From .MAKEFLAGS '=': Undefined is . .info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} -# expect+2: From .MAKEFLAGS ':=': Undefined is . -# expect+1: From .MAKEFLAGS ':=': Undefined is . .info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} UNDEFINED?= now defined -# expect+2: From the command line: Undefined is now defined. -# expect+1: From the command line: Undefined is now defined. .info From the command line: ${CMDLINE} -# expect+2: From .MAKEFLAGS '=': Undefined is now defined. -# expect+1: From .MAKEFLAGS '=': Undefined is now defined. .info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} -# expect+2: From .MAKEFLAGS ':=': Undefined is now defined. -# expect+1: From .MAKEFLAGS ':=': Undefined is now defined. .info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} print-undefined: diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp index 1a386d53dbef..81c73d887c18 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp +++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp @@ -1,5 +1,5 @@ -make: cond-cmp-numeric-eq.mk:68: Malformed conditional '!(12345 = 12345)' -make: cond-cmp-numeric-eq.mk:76: Malformed conditional '!(12345 === 12345)' +make: cond-cmp-numeric-eq.mk:68: Malformed conditional "!(12345 = 12345)" +make: cond-cmp-numeric-eq.mk:76: Malformed conditional "!(12345 === 12345)" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk index a8630cb37f1f..ea60f6f7b18d 100755 --- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk +++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-numeric-eq.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $ +# $NetBSD: cond-cmp-numeric-eq.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $ # # Tests for numeric comparisons with the == operator in .if conditions. @@ -64,7 +64,7 @@ .endif # There is no = operator for numbers. -# expect+1: Malformed conditional '!(12345 = 12345)' +# expect+1: Malformed conditional "!(12345 = 12345)" .if !(12345 = 12345) . error .else @@ -72,7 +72,7 @@ .endif # There is no === operator for numbers either. -# expect+1: Malformed conditional '!(12345 === 12345)' +# expect+1: Malformed conditional "!(12345 === 12345)" .if !(12345 === 12345) . error .else diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.exp b/contrib/bmake/unit-tests/cond-cmp-numeric.exp index 0945bef72300..2959ad99716c 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric.exp +++ b/contrib/bmake/unit-tests/cond-cmp-numeric.exp @@ -1,15 +1,15 @@ CondParser_Eval: !(${:UINF} > 1e100) -make: cond-cmp-numeric.mk:15: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric +make: cond-cmp-numeric.mk:15: Comparison with ">" requires both operands "INF" and "1e100" to be numeric CondParser_Eval: ${:UNaN} > NaN -make: cond-cmp-numeric.mk:21: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric +make: cond-cmp-numeric.mk:21: Comparison with ">" requires both operands "NaN" and "NaN" to be numeric CondParser_Eval: !(${:UNaN} == NaN) Comparing "NaN" == "NaN" CondParser_Eval: 123 ! 123 -make: cond-cmp-numeric.mk:38: Malformed conditional '123 ! 123' +make: cond-cmp-numeric.mk:38: Malformed conditional "123 ! 123" CondParser_Eval: ${:U 123} < 124 Comparing 123.000000 < 124.000000 CondParser_Eval: ${:U123 } < 124 -make: cond-cmp-numeric.mk:54: Comparison with '<' requires both operands '123 ' and '124' to be numeric +make: cond-cmp-numeric.mk:54: Comparison with "<" requires both operands "123 " and "124" to be numeric make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.mk b/contrib/bmake/unit-tests/cond-cmp-numeric.mk index 63a3bff8d560..abe5cc4cce9c 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric.mk +++ b/contrib/bmake/unit-tests/cond-cmp-numeric.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-numeric.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $ +# $NetBSD: cond-cmp-numeric.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $ # # Tests for numeric comparisons in .if conditions. # @@ -11,13 +11,13 @@ # Even if strtod(3) parses "INF" as +Infinity, make does not accept this # since it is not really a number; see TryParseNumber. -# expect+1: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric +# expect+1: Comparison with ">" requires both operands "INF" and "1e100" to be numeric .if !(${:UINF} > 1e100) . error .endif # Neither is NaN a number; see TryParseNumber. -# expect+1: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric +# expect+1: Comparison with ">" requires both operands "NaN" and "NaN" to be numeric .if ${:UNaN} > NaN . error .endif @@ -34,7 +34,7 @@ # whether the operator is valid, leaving the rest of the work to the # evaluation functions EvalCompareNum and EvalCompareStr. Ensure that this # parse error is properly reported. -# expect+1: Malformed conditional '123 ! 123' +# expect+1: Malformed conditional "123 ! 123" .if 123 ! 123 . error .else @@ -50,7 +50,7 @@ # Trailing spaces are NOT allowed for numbers. # See EvalCompare and TryParseNumber. -# expect+1: Comparison with '<' requires both operands '123 ' and '124' to be numeric +# expect+1: Comparison with "<" requires both operands "123 " and "124" to be numeric .if ${:U123 } < 124 . error .else diff --git a/contrib/bmake/unit-tests/cond-cmp-string.exp b/contrib/bmake/unit-tests/cond-cmp-string.exp index b55f30182442..8291d5300c3b 100644 --- a/contrib/bmake/unit-tests/cond-cmp-string.exp +++ b/contrib/bmake/unit-tests/cond-cmp-string.exp @@ -1,11 +1,11 @@ -make: cond-cmp-string.mk:19: Malformed conditional 'str != str' -make: cond-cmp-string.mk:44: Malformed conditional '"string" != "str""ing"' -make: cond-cmp-string.mk:52: Malformed conditional '!("value" = "value")' -make: cond-cmp-string.mk:60: Malformed conditional '!("value" === "value")' -make: cond-cmp-string.mk:118: Comparison with '<' requires both operands 'string' and 'string' to be numeric -make: cond-cmp-string.mk:126: Comparison with '<=' requires both operands 'string' and 'string' to be numeric -make: cond-cmp-string.mk:134: Comparison with '>' requires both operands 'string' and 'string' to be numeric -make: cond-cmp-string.mk:142: Comparison with '>=' requires both operands 'string' and 'string' to be numeric +make: cond-cmp-string.mk:19: Malformed conditional "str != str" +make: cond-cmp-string.mk:44: Malformed conditional ""string" != "str""ing"" +make: cond-cmp-string.mk:52: Malformed conditional "!("value" = "value")" +make: cond-cmp-string.mk:60: Malformed conditional "!("value" === "value")" +make: cond-cmp-string.mk:118: Comparison with "<" requires both operands "string" and "string" to be numeric +make: cond-cmp-string.mk:126: Comparison with "<=" requires both operands "string" and "string" to be numeric +make: cond-cmp-string.mk:134: Comparison with ">" requires both operands "string" and "string" to be numeric +make: cond-cmp-string.mk:142: Comparison with ">=" requires both operands "string" and "string" to be numeric make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-string.mk b/contrib/bmake/unit-tests/cond-cmp-string.mk index a913750a017f..56427bda11d0 100644 --- a/contrib/bmake/unit-tests/cond-cmp-string.mk +++ b/contrib/bmake/unit-tests/cond-cmp-string.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-string.mk,v 1.20 2024/08/06 18:00:16 rillig Exp $ +# $NetBSD: cond-cmp-string.mk,v 1.21 2025/06/28 22:39:28 rillig Exp $ # # Tests for string comparisons in .if conditions. @@ -15,7 +15,7 @@ # The left-hand side of the comparison must be enclosed in quotes. # This one is not enclosed in quotes and thus generates an error message. -# expect+1: Malformed conditional 'str != str' +# expect+1: Malformed conditional "str != str" .if str != str . error .endif @@ -40,7 +40,7 @@ # It is not possible to concatenate two string literals to form a single # string. In C, Python and the shell this is possible, but not in make. -# expect+1: Malformed conditional '"string" != "str""ing"' +# expect+1: Malformed conditional ""string" != "str""ing"" .if "string" != "str""ing" . error .else @@ -48,7 +48,7 @@ .endif # There is no = operator for strings. -# expect+1: Malformed conditional '!("value" = "value")' +# expect+1: Malformed conditional "!("value" = "value")" .if !("value" = "value") . error .else @@ -56,7 +56,7 @@ .endif # There is no === operator for strings either. -# expect+1: Malformed conditional '!("value" === "value")' +# expect+1: Malformed conditional "!("value" === "value")" .if !("value" === "value") . error .else @@ -114,7 +114,7 @@ .endif # Strings cannot be compared relationally, only for equality. -# expect+1: Comparison with '<' requires both operands 'string' and 'string' to be numeric +# expect+1: Comparison with "<" requires both operands "string" and "string" to be numeric .if "string" < "string" . error .else @@ -122,7 +122,7 @@ .endif # Strings cannot be compared relationally, only for equality. -# expect+1: Comparison with '<=' requires both operands 'string' and 'string' to be numeric +# expect+1: Comparison with "<=" requires both operands "string" and "string" to be numeric .if "string" <= "string" . error .else @@ -130,7 +130,7 @@ .endif # Strings cannot be compared relationally, only for equality. -# expect+1: Comparison with '>' requires both operands 'string' and 'string' to be numeric +# expect+1: Comparison with ">" requires both operands "string" and "string" to be numeric .if "string" > "string" . error .else @@ -138,7 +138,7 @@ .endif # Strings cannot be compared relationally, only for equality. -# expect+1: Comparison with '>=' requires both operands 'string' and 'string' to be numeric +# expect+1: Comparison with ">=" requires both operands "string" and "string" to be numeric .if "string" >= "string" . error .else diff --git a/contrib/bmake/unit-tests/cond-eof.exp b/contrib/bmake/unit-tests/cond-eof.exp index 44e481745a24..fb23e248178e 100644 --- a/contrib/bmake/unit-tests/cond-eof.exp +++ b/contrib/bmake/unit-tests/cond-eof.exp @@ -1,6 +1,6 @@ -make: cond-eof.mk:17: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}' -make: cond-eof.mk:20: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}' -make: cond-eof.mk:23: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}' +make: cond-eof.mk:17: Malformed conditional "0 ${SIDE_EFFECT} ${SIDE_EFFECT2}" +make: cond-eof.mk:20: Malformed conditional "1 ${SIDE_EFFECT} ${SIDE_EFFECT2}" +make: cond-eof.mk:23: Malformed conditional "(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-eof.mk b/contrib/bmake/unit-tests/cond-eof.mk index 706a7deebd1a..04d79d0783ad 100644 --- a/contrib/bmake/unit-tests/cond-eof.mk +++ b/contrib/bmake/unit-tests/cond-eof.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-eof.mk,v 1.7 2024/08/06 18:00:16 rillig Exp $ +# $NetBSD: cond-eof.mk,v 1.8 2025/06/28 22:39:28 rillig Exp $ # # Tests for parsing the end of '.if' conditions, which are represented as the # token TOK_EOF. @@ -13,12 +13,12 @@ SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!} # These syntax errors are an edge case that does not occur during normal # operation. Still, it is easy to avoid evaluating these expressions, just in # case they have side effects. -# expect+1: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}' +# expect+1: Malformed conditional "0 ${SIDE_EFFECT} ${SIDE_EFFECT2}" .if 0 ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif -# expect+1: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}' +# expect+1: Malformed conditional "1 ${SIDE_EFFECT} ${SIDE_EFFECT2}" .if 1 ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif -# expect+1: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}' +# expect+1: Malformed conditional "(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}" .if (0) ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif diff --git a/contrib/bmake/unit-tests/cond-func-defined.exp b/contrib/bmake/unit-tests/cond-func-defined.exp index ea3ced9398e8..04b57061f803 100644 --- a/contrib/bmake/unit-tests/cond-func-defined.exp +++ b/contrib/bmake/unit-tests/cond-func-defined.exp @@ -1,5 +1,5 @@ -make: cond-func-defined.mk:24: Missing ')' after argument 'A' for 'defined' -make: cond-func-defined.mk:34: Missing ')' after argument 'DEF' for 'defined' +make: cond-func-defined.mk:24: Missing ")" after argument "A" for "defined" +make: cond-func-defined.mk:34: Missing ")" after argument "DEF" for "defined" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-func-defined.mk b/contrib/bmake/unit-tests/cond-func-defined.mk index 66f95f3380c1..52eeaec8ccfc 100644 --- a/contrib/bmake/unit-tests/cond-func-defined.mk +++ b/contrib/bmake/unit-tests/cond-func-defined.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-defined.mk,v 1.14 2025/01/10 23:00:38 rillig Exp $ +# $NetBSD: cond-func-defined.mk,v 1.15 2025/06/28 22:39:28 rillig Exp $ # # Tests for the defined() function in .if conditions. @@ -20,7 +20,7 @@ ${:UA B}= variable name with spaces .endif # The argument of a function must not directly contain whitespace. -# expect+1: Missing ')' after argument 'A' for 'defined' +# expect+1: Missing ")" after argument "A" for "defined" .if !defined(A B) . error .endif @@ -30,7 +30,7 @@ ${:UA B}= variable name with spaces . error .endif -# expect+1: Missing ')' after argument 'DEF' for 'defined' +# expect+1: Missing ")" after argument "DEF" for "defined" .if defined(DEF . error .else diff --git a/contrib/bmake/unit-tests/cond-func-make.exp b/contrib/bmake/unit-tests/cond-func-make.exp index 4d493b3c3ccb..ab25dfc5b553 100644 --- a/contrib/bmake/unit-tests/cond-func-make.exp +++ b/contrib/bmake/unit-tests/cond-func-make.exp @@ -1,4 +1,4 @@ -make: cond-func-make.mk:24: warning: Unfinished character list in pattern argument '[' to function 'make' +make: cond-func-make.mk:24: warning: Unfinished character list in pattern argument "[" to function "make" : via-cmdline : via-dot-makeflags exit status 0 diff --git a/contrib/bmake/unit-tests/cond-func-make.mk b/contrib/bmake/unit-tests/cond-func-make.mk index 1a14fd320a3c..8903f9c0e723 100644 --- a/contrib/bmake/unit-tests/cond-func-make.mk +++ b/contrib/bmake/unit-tests/cond-func-make.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-make.mk,v 1.6 2025/01/10 23:00:38 rillig Exp $ +# $NetBSD: cond-func-make.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $ # # Tests for the make() function in .if conditions, which tests whether # the argument has been passed as a target via the command line or later @@ -20,7 +20,7 @@ . error .endif -# expect+1: warning: Unfinished character list in pattern argument '[' to function 'make' +# expect+1: warning: Unfinished character list in pattern argument "[" to function "make" .if make([) . error .endif diff --git a/contrib/bmake/unit-tests/cond-func.exp b/contrib/bmake/unit-tests/cond-func.exp index c80f95f39c0b..77f65e77d46c 100644 --- a/contrib/bmake/unit-tests/cond-func.exp +++ b/contrib/bmake/unit-tests/cond-func.exp @@ -1,13 +1,13 @@ -make: cond-func.mk:37: Missing ')' after argument 'A' for 'defined' -make: cond-func.mk:53: Missing ')' after argument 'A' for 'defined' -make: cond-func.mk:57: Missing ')' after argument 'A' for 'defined' -make: cond-func.mk:91: Unknown operator '&' +make: cond-func.mk:37: Missing ")" after argument "A" for "defined" +make: cond-func.mk:53: Missing ")" after argument "A" for "defined" +make: cond-func.mk:57: Missing ")" after argument "A" for "defined" +make: cond-func.mk:91: Unknown operator "&" make: cond-func.mk:107: A plain function name is parsed as defined(...). make: cond-func.mk:115: A plain function name is parsed as defined(...). make: cond-func.mk:126: Symbols may start with a function name. make: cond-func.mk:132: Symbols may start with a function name. -make: cond-func.mk:138: Missing ')' after argument '' for 'defined' -make: cond-func.mk:145: Missing ')' after argument '${:UVARNAME}.param' for 'defined' +make: cond-func.mk:138: Missing ")" after argument "" for "defined" +make: cond-func.mk:145: Missing ")" after argument "${:UVARNAME}.param" for "defined" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-func.mk b/contrib/bmake/unit-tests/cond-func.mk index 3e4f8a9f151f..50b3f83cd4cb 100644 --- a/contrib/bmake/unit-tests/cond-func.mk +++ b/contrib/bmake/unit-tests/cond-func.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func.mk,v 1.18 2024/08/07 05:48:45 rillig Exp $ +# $NetBSD: cond-func.mk,v 1.19 2025/06/28 22:39:28 rillig Exp $ # # Tests for those parts of the functions in .if conditions that are common # among several functions. @@ -33,7 +33,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces .endif # The argument of a function must not directly contain whitespace. -# expect+1: Missing ')' after argument 'A' for 'defined' +# expect+1: Missing ")" after argument "A" for "defined" .if !defined(A B) . error .endif @@ -49,11 +49,11 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces # # It's not entirely clear why these characters are forbidden. # The most plausible reason seems to be typo detection. -# expect+1: Missing ')' after argument 'A' for 'defined' +# expect+1: Missing ")" after argument "A" for "defined" .if !defined(A&B) . error .endif -# expect+1: Missing ')' after argument 'A' for 'defined' +# expect+1: Missing ")" after argument "A" for "defined" .if !defined(A|B) . error .endif @@ -87,7 +87,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces # interpreted as defined(A) && defined(B). Each kind of .if directive has a # default function that is called when a bare word is parsed. For the plain # .if directive, this function is 'defined'; see "struct If ifs" in cond.c. -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if A&B . error .endif @@ -134,14 +134,14 @@ defined-var= # defined but empty . error .endif -# expect+1: Missing ')' after argument '' for 'defined' +# expect+1: Missing ")" after argument "" for "defined" .if defined( . error .else . error .endif -# expect+1: Missing ')' after argument '${:UVARNAME}.param' for 'defined' +# expect+1: Missing ")" after argument "${:UVARNAME}.param" for "defined" .if defined(${:UVARNAME}.param extra) . error .else diff --git a/contrib/bmake/unit-tests/cond-late.exp b/contrib/bmake/unit-tests/cond-late.exp index 13846e8c822a..e4b3fdac85f4 100644 --- a/contrib/bmake/unit-tests/cond-late.exp +++ b/contrib/bmake/unit-tests/cond-late.exp @@ -1,4 +1,4 @@ -make: cond-late.mk:38: Bad condition +make: cond-late.mk:29: Bad condition while evaluating condition " != "no"" while evaluating variable "VAR" with value "${${UNDEF} != "no":?:}" in make[1] in directory "<curdir>" diff --git a/contrib/bmake/unit-tests/cond-late.mk b/contrib/bmake/unit-tests/cond-late.mk index a8f381590a6e..154617f4f2b2 100644 --- a/contrib/bmake/unit-tests/cond-late.mk +++ b/contrib/bmake/unit-tests/cond-late.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-late.mk,v 1.9 2024/08/29 20:20:35 rillig Exp $ +# $NetBSD: cond-late.mk,v 1.10 2025/06/30 21:44:39 rillig Exp $ # # Using the :? modifier, expressions can contain conditional # expressions that are evaluated late, at expansion time. @@ -23,6 +23,13 @@ parse-time: .PHONY COND.true= "yes" == "yes" COND.false= "yes" != "yes" +.if make(do-parse-time) +VAR= ${${UNDEF} != "no":?:} +# expect+1: Bad condition +. if empty(VAR:Mpattern) +. endif +.endif + # If the order of evaluation were to change to first parse the condition # and then expand the variables, the output would change from the # current "yes no" to "yes yes", since both variables are non-empty. @@ -31,10 +38,3 @@ COND.false= "yes" != "yes" cond-literal: @echo ${ ${COND.true} :?yes:no} @echo ${ ${COND.false} :?yes:no} - -.if make(do-parse-time) -VAR= ${${UNDEF} != "no":?:} -# expect+1: Bad condition -. if empty(VAR:Mpattern) -. endif -.endif diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.exp b/contrib/bmake/unit-tests/cond-op-and-lint.exp index 8896fea5c9b6..74ac32e205e6 100644 --- a/contrib/bmake/unit-tests/cond-op-and-lint.exp +++ b/contrib/bmake/unit-tests/cond-op-and-lint.exp @@ -1,4 +1,4 @@ -make: cond-op-and-lint.mk:10: Unknown operator '&' +make: cond-op-and-lint.mk:10: Unknown operator "&" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.mk b/contrib/bmake/unit-tests/cond-op-and-lint.mk index bac4566314b0..0daa3a728f86 100644 --- a/contrib/bmake/unit-tests/cond-op-and-lint.mk +++ b/contrib/bmake/unit-tests/cond-op-and-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-and-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: cond-op-and-lint.mk,v 1.3 2025/06/28 22:39:28 rillig Exp $ # # Tests for the && operator in .if conditions, in lint mode. @@ -6,7 +6,7 @@ # The '&' operator is not allowed in lint mode. # It is not used in practice anyway. -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if 0 & 0 . error .else diff --git a/contrib/bmake/unit-tests/cond-op-and.exp b/contrib/bmake/unit-tests/cond-op-and.exp index 1ada96a00bdd..b3e45ea1767e 100644 --- a/contrib/bmake/unit-tests/cond-op-and.exp +++ b/contrib/bmake/unit-tests/cond-op-and.exp @@ -1,11 +1,11 @@ make: cond-op-and.mk:36: Variable "UNDEF" is undefined make: cond-op-and.mk:41: Variable "UNDEF" is undefined make: cond-op-and.mk:44: Variable "UNDEF" is undefined -make: cond-op-and.mk:60: Unknown operator '&' -make: cond-op-and.mk:66: Unknown operator '&' -make: cond-op-and.mk:72: Unknown operator '&' -make: cond-op-and.mk:78: Unknown operator '&' -make: cond-op-and.mk:87: Unknown operator '&' +make: cond-op-and.mk:60: Unknown operator "&" +make: cond-op-and.mk:66: Unknown operator "&" +make: cond-op-and.mk:72: Unknown operator "&" +make: cond-op-and.mk:78: Unknown operator "&" +make: cond-op-and.mk:87: Unknown operator "&" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-and.mk b/contrib/bmake/unit-tests/cond-op-and.mk index 5d7f8a06800a..cb84e39e9217 100644 --- a/contrib/bmake/unit-tests/cond-op-and.mk +++ b/contrib/bmake/unit-tests/cond-op-and.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-and.mk,v 1.12 2025/01/11 21:21:33 rillig Exp $ +# $NetBSD: cond-op-and.mk,v 1.13 2025/06/28 22:39:28 rillig Exp $ # # Tests for the && operator in .if conditions. @@ -56,25 +56,25 @@ DEF= defined # The && operator may be abbreviated as &. This is not widely known though # and is also not documented in the manual page. -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if 0 & 0 . error .else . error .endif -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if 1 & 0 . error .else . error .endif -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if 0 & 1 . error .else . error .endif -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if !(1 & 1) . error .else @@ -83,7 +83,7 @@ DEF= defined # There is no operator '&&&'. The first two '&&' form an operator, the third # '&' forms the next (incomplete) token. -# expect+1: Unknown operator '&' +# expect+1: Unknown operator "&" .if 0 &&& 0 . error .else diff --git a/contrib/bmake/unit-tests/cond-op-not.exp b/contrib/bmake/unit-tests/cond-op-not.exp index 63aa928eabc3..f0dfb3b757b1 100644 --- a/contrib/bmake/unit-tests/cond-op-not.exp +++ b/contrib/bmake/unit-tests/cond-op-not.exp @@ -3,7 +3,7 @@ make: cond-op-not.mk:39: Not space evaluates to false. make: cond-op-not.mk:44: Not 0 evaluates to true. make: cond-op-not.mk:53: Not 1 evaluates to false. make: cond-op-not.mk:60: Not word evaluates to false. -make: cond-op-not.mk:65: Malformed conditional '!' +make: cond-op-not.mk:65: Malformed conditional "!" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-not.mk b/contrib/bmake/unit-tests/cond-op-not.mk index 4565b60b115d..393d68675fca 100644 --- a/contrib/bmake/unit-tests/cond-op-not.mk +++ b/contrib/bmake/unit-tests/cond-op-not.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-not.mk,v 1.9 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: cond-op-not.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $ # # Tests for the ! operator in .if conditions, which negates its argument. @@ -61,7 +61,7 @@ .endif # A single exclamation mark is a parse error. -# expect+1: Malformed conditional '!' +# expect+1: Malformed conditional "!" .if ! . error .else diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.exp b/contrib/bmake/unit-tests/cond-op-or-lint.exp index 1c5837a9aca6..32d39dead9a1 100644 --- a/contrib/bmake/unit-tests/cond-op-or-lint.exp +++ b/contrib/bmake/unit-tests/cond-op-or-lint.exp @@ -1,4 +1,4 @@ -make: cond-op-or-lint.mk:10: Unknown operator '|' +make: cond-op-or-lint.mk:10: Unknown operator "|" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.mk b/contrib/bmake/unit-tests/cond-op-or-lint.mk index 9ece9d5c9af6..1efc5d94cbf2 100644 --- a/contrib/bmake/unit-tests/cond-op-or-lint.mk +++ b/contrib/bmake/unit-tests/cond-op-or-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-or-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: cond-op-or-lint.mk,v 1.3 2025/06/28 22:39:28 rillig Exp $ # # Tests for the || operator in .if conditions, in lint mode. @@ -6,7 +6,7 @@ # The '|' operator is not allowed in lint mode. # It is not used in practice anyway. -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if 0 | 0 . error .else diff --git a/contrib/bmake/unit-tests/cond-op-or.exp b/contrib/bmake/unit-tests/cond-op-or.exp index 6213759c24f7..fe42ffd6b310 100644 --- a/contrib/bmake/unit-tests/cond-op-or.exp +++ b/contrib/bmake/unit-tests/cond-op-or.exp @@ -1,11 +1,11 @@ make: cond-op-or.mk:36: Variable "UNDEF" is undefined make: cond-op-or.mk:41: Variable "UNDEF" is undefined make: cond-op-or.mk:44: Variable "UNDEF" is undefined -make: cond-op-or.mk:60: Unknown operator '|' -make: cond-op-or.mk:66: Unknown operator '|' -make: cond-op-or.mk:72: Unknown operator '|' -make: cond-op-or.mk:78: Unknown operator '|' -make: cond-op-or.mk:87: Unknown operator '|' +make: cond-op-or.mk:60: Unknown operator "|" +make: cond-op-or.mk:66: Unknown operator "|" +make: cond-op-or.mk:72: Unknown operator "|" +make: cond-op-or.mk:78: Unknown operator "|" +make: cond-op-or.mk:87: Unknown operator "|" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-or.mk b/contrib/bmake/unit-tests/cond-op-or.mk index 381516499093..1c6e081dcac1 100644 --- a/contrib/bmake/unit-tests/cond-op-or.mk +++ b/contrib/bmake/unit-tests/cond-op-or.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-or.mk,v 1.14 2025/01/11 21:21:33 rillig Exp $ +# $NetBSD: cond-op-or.mk,v 1.15 2025/06/28 22:39:28 rillig Exp $ # # Tests for the || operator in .if conditions. @@ -56,25 +56,25 @@ DEF= defined # The || operator may be abbreviated as |. This is not widely known though # and is also not documented in the manual page. -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if 0 | 0 . error .else . error .endif -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if !(1 | 0) . error .else . error .endif -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if !(0 | 1) . error .else . error .endif -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if !(1 | 1) . error .else @@ -83,7 +83,7 @@ DEF= defined # There is no operator '|||'. The first two '||' form an operator, the third # '|' forms the next (incomplete) token. -# expect+1: Unknown operator '|' +# expect+1: Unknown operator "|" .if 0 ||| 0 . error .else diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.exp b/contrib/bmake/unit-tests/cond-op-parentheses.exp index a4091226ec34..f8f9efc00772 100644 --- a/contrib/bmake/unit-tests/cond-op-parentheses.exp +++ b/contrib/bmake/unit-tests/cond-op-parentheses.exp @@ -1,7 +1,7 @@ -make: cond-op-parentheses.mk:22: Comparison with '>' requires both operands '3' and '(2' to be numeric -make: cond-op-parentheses.mk:25: Malformed conditional '(3) > 2' -make: cond-op-parentheses.mk:44: Malformed conditional '(' -make: cond-op-parentheses.mk:58: Malformed conditional ')' +make: cond-op-parentheses.mk:22: Comparison with ">" requires both operands "3" and "(2" to be numeric +make: cond-op-parentheses.mk:25: Malformed conditional "(3) > 2" +make: cond-op-parentheses.mk:44: Malformed conditional "(" +make: cond-op-parentheses.mk:58: Malformed conditional ")" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.mk b/contrib/bmake/unit-tests/cond-op-parentheses.mk index 17d5d767cd41..17d6504ede9e 100644 --- a/contrib/bmake/unit-tests/cond-op-parentheses.mk +++ b/contrib/bmake/unit-tests/cond-op-parentheses.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-parentheses.mk,v 1.8 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: cond-op-parentheses.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $ # # Tests for parentheses in .if conditions, which group expressions to override # the precedence of the operators '!', '&&' and '||'. Parentheses cannot be @@ -18,10 +18,10 @@ # # XXX: It's inconsistent that the right operand has unbalanced parentheses. # -# expect+1: Comparison with '>' requires both operands '3' and '(2' to be numeric +# expect+1: Comparison with ">" requires both operands "3" and "(2" to be numeric .if 3 > (2) .endif -# expect+1: Malformed conditional '(3) > 2' +# expect+1: Malformed conditional "(3) > 2" .if (3) > 2 .endif @@ -40,7 +40,7 @@ .endif # An unbalanced opening parenthesis is a parse error. -# expect+1: Malformed conditional '(' +# expect+1: Malformed conditional "(" .if ( . error .else @@ -54,7 +54,7 @@ # TOK_TRUE, TOK_FALSE or TOK_ERROR. In cond.c 1.241, the return type of that # function was changed to a properly restricted enum type, to prevent this bug # from occurring again. -# expect+1: Malformed conditional ')' +# expect+1: Malformed conditional ")" .if ) . error .else diff --git a/contrib/bmake/unit-tests/cond-op.exp b/contrib/bmake/unit-tests/cond-op.exp index 1125a35fa3b3..692698b91a96 100644 --- a/contrib/bmake/unit-tests/cond-op.exp +++ b/contrib/bmake/unit-tests/cond-op.exp @@ -1,7 +1,7 @@ -make: cond-op.mk:51: Malformed conditional '"!word" == !word' -make: cond-op.mk:72: Malformed conditional '0 ${ERR::=evaluated}' +make: cond-op.mk:51: Malformed conditional ""!word" == !word" +make: cond-op.mk:72: Malformed conditional "0 ${ERR::=evaluated}" make: cond-op.mk:77: A misplaced expression after 0 is not evaluated. -make: cond-op.mk:82: Malformed conditional '1 ${ERR::=evaluated}' +make: cond-op.mk:82: Malformed conditional "1 ${ERR::=evaluated}" make: cond-op.mk:87: A misplaced expression after 1 is not evaluated. make: cond-op.mk:93: A B C => (A || B) && C A || B && C A || (B && C) make: cond-op.mk:108: 0 0 0 => 0 0 0 @@ -12,10 +12,10 @@ make: cond-op.mk:108: 1 0 0 => 0 1 1 make: cond-op.mk:108: 1 0 1 => 1 1 1 make: cond-op.mk:108: 1 1 0 => 0 1 1 make: cond-op.mk:108: 1 1 1 => 1 1 1 -make: cond-op.mk:120: Malformed conditional '1 &&' -make: cond-op.mk:129: Malformed conditional '0 &&' -make: cond-op.mk:138: Malformed conditional '1 ||' -make: cond-op.mk:148: Malformed conditional '0 ||' +make: cond-op.mk:120: Malformed conditional "1 &&" +make: cond-op.mk:129: Malformed conditional "0 &&" +make: cond-op.mk:138: Malformed conditional "1 ||" +make: cond-op.mk:148: Malformed conditional "0 ||" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op.mk b/contrib/bmake/unit-tests/cond-op.mk index 6493d887c806..974cb938065c 100644 --- a/contrib/bmake/unit-tests/cond-op.mk +++ b/contrib/bmake/unit-tests/cond-op.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op.mk,v 1.17 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: cond-op.mk,v 1.18 2025/06/28 22:39:28 rillig Exp $ # # Tests for operators like &&, ||, ! in .if conditions. # @@ -47,7 +47,7 @@ # appear unquoted. If any, it must be enclosed in quotes. # In any case, it is not interpreted as a negation of an unquoted string. # See CondParser_String. -# expect+1: Malformed conditional '"!word" == !word' +# expect+1: Malformed conditional ""!word" == !word" .if "!word" == !word . error .endif @@ -68,7 +68,7 @@ # next token, even though in this position of the condition, only comparison # operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed. .undef ERR -# expect+1: Malformed conditional '0 ${ERR::=evaluated}' +# expect+1: Malformed conditional "0 ${ERR::=evaluated}" .if 0 ${ERR::=evaluated} . error .endif @@ -78,7 +78,7 @@ .endif .undef ERR -# expect+1: Malformed conditional '1 ${ERR::=evaluated}' +# expect+1: Malformed conditional "1 ${ERR::=evaluated}" .if 1 ${ERR::=evaluated} . error .endif @@ -116,7 +116,7 @@ # This condition is obviously malformed. It is properly detected and also # was properly detected before 2021-01-19, but only because the left hand # side of the '&&' evaluated to true. -# expect+1: Malformed conditional '1 &&' +# expect+1: Malformed conditional "1 &&" .if 1 && . error .else @@ -125,7 +125,7 @@ # This obviously malformed condition was not detected as such before cond.c # 1.238 from 2021-01-19. -# expect+1: Malformed conditional '0 &&' +# expect+1: Malformed conditional "0 &&" .if 0 && . error .else @@ -134,7 +134,7 @@ # This obviously malformed condition was not detected as such before cond.c # 1.238 from 2021-01-19. -# expect+1: Malformed conditional '1 ||' +# expect+1: Malformed conditional "1 ||" .if 1 || . error .else @@ -144,7 +144,7 @@ # This condition is obviously malformed. It is properly detected and also # was properly detected before 2021-01-19, but only because the left hand # side of the '||' evaluated to false. -# expect+1: Malformed conditional '0 ||' +# expect+1: Malformed conditional "0 ||" .if 0 || . error .else diff --git a/contrib/bmake/unit-tests/cond-short.exp b/contrib/bmake/unit-tests/cond-short.exp index 19c7ef3d0b89..4100e6e5ef2b 100644 --- a/contrib/bmake/unit-tests/cond-short.exp +++ b/contrib/bmake/unit-tests/cond-short.exp @@ -7,7 +7,7 @@ expected M pattern expected or expected or exists expected or empty -make: cond-short.mk:231: Comparison with '<' requires both operands '' and '42' to be numeric +make: cond-short.mk:231: Comparison with "<" requires both operands "" and "42" to be numeric make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-short.mk b/contrib/bmake/unit-tests/cond-short.mk index bcdf372ca6e6..8c4c4140596e 100644 --- a/contrib/bmake/unit-tests/cond-short.mk +++ b/contrib/bmake/unit-tests/cond-short.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-short.mk,v 1.23 2023/11/19 22:32:44 rillig Exp $ +# $NetBSD: cond-short.mk,v 1.24 2025/06/28 22:39:28 rillig Exp $ # # Demonstrates that in conditions, the right-hand side of an && or || # is only evaluated if it can actually influence the result. @@ -227,7 +227,7 @@ VAR= ${VAR${:U1}} # Due to the quotes around the left-hand side of the '<', the operand is # marked as a string, thus preventing a numerical comparison. # -# expect+1: Comparison with '<' requires both operands '' and '42' to be numeric +# expect+1: Comparison with "<" requires both operands "" and "42" to be numeric .if "${INDIR_UNDEF}" < ${NUMBER} . info yes .else diff --git a/contrib/bmake/unit-tests/cond-token-number.exp b/contrib/bmake/unit-tests/cond-token-number.exp index 401f8a2364b7..a3b53c2dcd44 100644 --- a/contrib/bmake/unit-tests/cond-token-number.exp +++ b/contrib/bmake/unit-tests/cond-token-number.exp @@ -1,7 +1,7 @@ -make: cond-token-number.mk:16: Malformed conditional '-0' -make: cond-token-number.mk:27: Malformed conditional '+0' -make: cond-token-number.mk:38: Malformed conditional '!-1' -make: cond-token-number.mk:49: Malformed conditional '!+1' +make: cond-token-number.mk:16: Malformed conditional "-0" +make: cond-token-number.mk:27: Malformed conditional "+0" +make: cond-token-number.mk:38: Malformed conditional "!-1" +make: cond-token-number.mk:49: Malformed conditional "!+1" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-token-number.mk b/contrib/bmake/unit-tests/cond-token-number.mk index 329a51d73b2a..1d0f8d20287e 100644 --- a/contrib/bmake/unit-tests/cond-token-number.mk +++ b/contrib/bmake/unit-tests/cond-token-number.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-number.mk,v 1.11 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: cond-token-number.mk,v 1.12 2025/06/28 22:39:28 rillig Exp $ # # Tests for number tokens in .if conditions. # @@ -12,7 +12,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. -# expect+1: Malformed conditional '-0' +# expect+1: Malformed conditional "-0" .if -0 . error .else @@ -23,7 +23,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. -# expect+1: Malformed conditional '+0' +# expect+1: Malformed conditional "+0" .if +0 . error .else @@ -34,7 +34,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. -# expect+1: Malformed conditional '!-1' +# expect+1: Malformed conditional "!-1" .if !-1 . error .else @@ -45,7 +45,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. -# expect+1: Malformed conditional '!+1' +# expect+1: Malformed conditional "!+1" .if !+1 . error .else diff --git a/contrib/bmake/unit-tests/cond-token-plain.exp b/contrib/bmake/unit-tests/cond-token-plain.exp index 52d7e6fcddaa..0b430eba7d39 100644 --- a/contrib/bmake/unit-tests/cond-token-plain.exp +++ b/contrib/bmake/unit-tests/cond-token-plain.exp @@ -1,10 +1,12 @@ CondParser_Eval: ${:Uvalue} != value Comparing "value" != "value" CondParser_Eval: ${:U} != " +make: cond-token-plain.mk:19: Unfinished string literal """ Comparing "" != "" CondParser_Eval: ${:U#hash} != "#hash" Comparing "#hash" != "#hash" CondParser_Eval: ${:U\\} != "\\ +make: cond-token-plain.mk:43: Unfinished string literal ""\\" Comparing "\" != "\" CondParser_Eval: ${:U#hash} != #hash Comparing "#hash" != "#hash" @@ -39,9 +41,9 @@ make: cond-token-plain.mk:139: Numbers can be composed from literals and express CondParser_Eval: 0${:Ux01} make: cond-token-plain.mk:144: Numbers can be composed from literals and expressions. CondParser_Eval: "" == -make: cond-token-plain.mk:151: Missing right-hand side of operator '==' +make: cond-token-plain.mk:151: Missing right-hand side of operator "==" CondParser_Eval: == "" -make: cond-token-plain.mk:160: Malformed conditional '== ""' +make: cond-token-plain.mk:160: Malformed conditional "== """ CondParser_Eval: \\ make: cond-token-plain.mk:176: The variable '\\' is not defined. CondParser_Eval: \\ @@ -49,15 +51,23 @@ make: cond-token-plain.mk:182: Now the variable '\\' is defined. CondParser_Eval: "unquoted\"quoted" != unquoted"quoted Comparing "unquoted"quoted" != "unquoted"quoted" CondParser_Eval: $$$$$$$$ != "" -make: cond-token-plain.mk:197: Malformed conditional '$$$$$$$$ != ""' +make: cond-token-plain.mk:197: Malformed conditional "$$$$$$$$ != """ CondParser_Eval: left == right -make: cond-token-plain.mk:206: Malformed conditional 'left == right' +make: cond-token-plain.mk:206: Malformed conditional "left == right" CondParser_Eval: ${0:?:} || left == right CondParser_Eval: 0 -make: cond-token-plain.mk:212: Malformed conditional '${0:?:} || left == right' +make: cond-token-plain.mk:212: Malformed conditional "${0:?:} || left == right" CondParser_Eval: left == right || ${0:?:} -make: cond-token-plain.mk:217: Malformed conditional 'left == right || ${0:?:}' -make: cond-token-plain.mk:236: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""' +make: cond-token-plain.mk:217: Malformed conditional "left == right || ${0:?:}" +make: cond-token-plain.mk:236: Malformed conditional "VAR.${IF_COUNT::+=1} != """ +make: cond-token-plain.mk:272: Unfinished backslash escape sequence + while evaluating condition " str == str\" +make: cond-token-plain.mk:282: Unfinished backslash escape sequence + while evaluating condition " str == "str\" +make: cond-token-plain.mk:282: Unfinished string literal ""str\" + while evaluating condition " str == "str\" +make: cond-token-plain.mk:289: Unfinished string literal ""str" + while evaluating condition " str == "str" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-token-plain.mk b/contrib/bmake/unit-tests/cond-token-plain.mk index 4509c1feca80..400af22f92d7 100644 --- a/contrib/bmake/unit-tests/cond-token-plain.mk +++ b/contrib/bmake/unit-tests/cond-token-plain.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-plain.mk,v 1.20 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: cond-token-plain.mk,v 1.23 2025/07/06 07:56:16 rillig Exp $ # # Tests for plain tokens (that is, string literals without quotes) # in .if conditions. These are also called bare words. @@ -14,8 +14,8 @@ # condition since comment parsing is done in an early phase and removes the # '#' and everything after it long before the condition parser gets to see it. # -# XXX: The error message is missing for this malformed condition. -# The right-hand side of the comparison is just a '"', before unescaping. +# +# expect+1: Unfinished string literal """ .if ${:U} != "#hash" . error .endif @@ -38,8 +38,8 @@ # comments are stripped in an earlier phase. See "case '#'" in # CondParser_Token. # -# XXX: Missing error message for the malformed condition. The right-hand -# side before unescaping is double-quotes, backslash, backslash. +# +# expect+1: Unfinished string literal ""\\" .if ${:U\\} != "\\#hash" . error .endif @@ -147,7 +147,7 @@ VAR= defined .endif # If the right-hand side is missing, it's a parse error. -# expect+1: Missing right-hand side of operator '==' +# expect+1: Missing right-hand side of operator "==" .if "" == . error .else @@ -156,7 +156,7 @@ VAR= defined # If the left-hand side is missing, it's a parse error as well, but without # a specific error message. -# expect+1: Malformed conditional '== ""' +# expect+1: Malformed conditional "== """ .if == "" . error .else @@ -193,7 +193,7 @@ ${:U\\\\}= backslash # FIXME: In CondParser_String, Var_Parse returns var_Error without a # corresponding error message. -# expect+1: Malformed conditional '$$$$$$$$ != ""' +# expect+1: Malformed conditional "$$$$$$$$ != """ .if $$$$$$$$ != "" . error .else @@ -202,18 +202,18 @@ ${:U\\\\}= backslash # In a condition in an .if directive, the left-hand side must not be an # unquoted string literal. -# expect+1: Malformed conditional 'left == right' +# expect+1: Malformed conditional "left == right" .if left == right .endif # Before cond.c 1.276 from 2021-09-21, an expression containing the # modifier ':?:' allowed unquoted string literals for the rest of the # condition. This was an unintended implementation mistake. -# expect+1: Malformed conditional '${0:?:} || left == right' +# expect+1: Malformed conditional "${0:?:} || left == right" .if ${0:?:} || left == right .endif # This affected only the comparisons after the expression, so the following # was still a syntax error. -# expect+1: Malformed conditional 'left == right || ${0:?:}' +# expect+1: Malformed conditional "left == right || ${0:?:}" .if left == right || ${0:?:} .endif @@ -232,7 +232,7 @@ ${:U\\\\}= backslash # for the second time. The right-hand side of a comparison may be a bare # word, but that side has no risk of being parsed more than once. # -# expect+1: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""' +# expect+1: Malformed conditional "VAR.${IF_COUNT::+=1} != """ .if VAR.${IF_COUNT::+=1} != "" . error .else @@ -265,3 +265,29 @@ COND= VAR.$${MOD_COUNT::+=1} . error .endif #.MAKEFLAGS: -d0 + + +# A trailing backslash in a bare word does not escape anything. +# expect+1: Unfinished backslash escape sequence +.if ${${:U str == str\\}:?yes:no} +. error +.else +. error +.endif + +# A trailing backslash in an unfinished string literal word does not escape +# anything. +# expect+2: Unfinished backslash escape sequence +# expect+1: Unfinished string literal ""str\" +.if ${${:U str == "str\\}:?yes:no} +. error +.else +. error +.endif + +# expect+1: Unfinished string literal ""str" +.if ${${:U str == "str}:?yes:no} +. error +.else +. error +.endif diff --git a/contrib/bmake/unit-tests/cond-token-string.exp b/contrib/bmake/unit-tests/cond-token-string.exp index d0a5a25f2aa4..d31c0abda17d 100644 --- a/contrib/bmake/unit-tests/cond-token-string.exp +++ b/contrib/bmake/unit-tests/cond-token-string.exp @@ -1,7 +1,7 @@ make: cond-token-string.mk:14: Unknown modifier ":Z" while evaluating "${:Uvalue:Z}"" with value "value" make: cond-token-string.mk:24: xvalue is not defined. -make: cond-token-string.mk:31: Malformed conditional 'x${:Uvalue} == ""' +make: cond-token-string.mk:31: Malformed conditional "x${:Uvalue} == """ make: cond-token-string.mk:41: Expected. CondParser_Eval: "UNDEF" make: cond-token-string.mk:51: The string literal "UNDEF" is not empty. diff --git a/contrib/bmake/unit-tests/cond-token-string.mk b/contrib/bmake/unit-tests/cond-token-string.mk index fb069f830582..9afe64dca821 100644 --- a/contrib/bmake/unit-tests/cond-token-string.mk +++ b/contrib/bmake/unit-tests/cond-token-string.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-string.mk,v 1.16 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: cond-token-string.mk,v 1.17 2025/06/28 22:39:28 rillig Exp $ # # Tests for quoted string literals in .if conditions. # @@ -27,7 +27,7 @@ # The 'x' produces a "Malformed conditional" since the left-hand side of a # comparison in an .if directive must be either an expression, a # quoted string literal or a number that starts with a digit. -# expect+1: Malformed conditional 'x${:Uvalue} == ""' +# expect+1: Malformed conditional "x${:Uvalue} == """ .if x${:Uvalue} == "" . error .else diff --git a/contrib/bmake/unit-tests/cond-token-var.exp b/contrib/bmake/unit-tests/cond-token-var.exp index 1bf61e79ca61..b63d606c7e5a 100644 --- a/contrib/bmake/unit-tests/cond-token-var.exp +++ b/contrib/bmake/unit-tests/cond-token-var.exp @@ -6,11 +6,11 @@ make: cond-token-var.mk:64: Variable "U" is undefined make: cond-token-var.mk:69: Variable "U" is undefined make: cond-token-var.mk:78: Variable "U" is undefined Var_Parse: ${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3} (eval) -make: cond-token-var.mk:106: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}' +make: cond-token-var.mk:106: Malformed conditional "x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}" Var_Parse: ${DEF}y == "${UNDEF2}" || 0x${UNDEF3} (eval) -make: cond-token-var.mk:111: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}' +make: cond-token-var.mk:111: Malformed conditional "x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}" Var_Parse: ${DEF}y == "${DEF}" || 0x${UNDEF3} (eval) -make: cond-token-var.mk:116: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}' +make: cond-token-var.mk:116: Malformed conditional "x${DEF}y == "${DEF}" || 0x${UNDEF3}" Global: VAR.param = value of VAR.param Var_Parse: ${VAR.param$U} (eval-defined-loud) Var_Parse: $U} (eval) diff --git a/contrib/bmake/unit-tests/cond-token-var.mk b/contrib/bmake/unit-tests/cond-token-var.mk index 8da8a2436390..842ca4d2cb12 100644 --- a/contrib/bmake/unit-tests/cond-token-var.mk +++ b/contrib/bmake/unit-tests/cond-token-var.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-var.mk,v 1.13 2025/04/04 18:57:01 rillig Exp $ +# $NetBSD: cond-token-var.mk,v 1.14 2025/06/28 22:39:28 rillig Exp $ # # Tests for expressions in .if conditions. # @@ -102,17 +102,17 @@ DEF= defined .MAKEFLAGS: -dv # The left-hand side of a comparison must not be an unquoted word. -# expect+1: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}' +# expect+1: Malformed conditional "x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}" .if x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3} .endif # The left-hand side of a comparison must not be an unquoted word. -# expect+1: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}' +# expect+1: Malformed conditional "x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}" .if x${DEF}y == "${UNDEF2}" || 0x${UNDEF3} .endif # The left-hand side of a comparison must not be an unquoted word. -# expect+1: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}' +# expect+1: Malformed conditional "x${DEF}y == "${DEF}" || 0x${UNDEF3}" .if x${DEF}y == "${DEF}" || 0x${UNDEF3} .endif diff --git a/contrib/bmake/unit-tests/dep-op-missing.exp b/contrib/bmake/unit-tests/dep-op-missing.exp index 8521dbf79792..7c03092e09be 100644 --- a/contrib/bmake/unit-tests/dep-op-missing.exp +++ b/contrib/bmake/unit-tests/dep-op-missing.exp @@ -1,4 +1,4 @@ -make: dep-op-missing.tmp:1: Invalid line 'target' +make: dep-op-missing.tmp:1: Invalid line "target" in make[1] in directory "<curdir>" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/contrib/bmake/unit-tests/deptgt-begin.exp b/contrib/bmake/unit-tests/deptgt-begin.exp index bf6f61a51e72..5aa673e33d30 100644 --- a/contrib/bmake/unit-tests/deptgt-begin.exp +++ b/contrib/bmake/unit-tests/deptgt-begin.exp @@ -1,5 +1,5 @@ make: deptgt-begin.mk:19: warning: duplicate script for target ".BEGIN" ignored -make: deptgt-begin.mk:9: warning: using previous script for ".BEGIN" defined here +make: deptgt-begin.mk:8: warning: using previous script for ".BEGIN" defined here : parse time : Making before-begin before .BEGIN. : .BEGIN diff --git a/contrib/bmake/unit-tests/deptgt-begin.mk b/contrib/bmake/unit-tests/deptgt-begin.mk index 8b9842641a2d..a29155cb5fc2 100644 --- a/contrib/bmake/unit-tests/deptgt-begin.mk +++ b/contrib/bmake/unit-tests/deptgt-begin.mk @@ -1,10 +1,9 @@ -# $NetBSD: deptgt-begin.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: deptgt-begin.mk,v 1.8 2025/06/30 21:44:39 rillig Exp $ # # Tests for the special target .BEGIN in dependency declarations, # which is a container for commands that are run before any other # commands from the shell lines. -# expect+2: warning: using previous script for ".BEGIN" defined here .BEGIN: : $@ @@ -14,7 +13,8 @@ # add its commands after this. # # There are several ways to resolve this situation, which are detailed below. -# expect+2: warning: duplicate script for target ".BEGIN" ignored +# expect+3: warning: duplicate script for target ".BEGIN" ignored +# expect-9: warning: using previous script for ".BEGIN" defined here .BEGIN: : Making another $@. diff --git a/contrib/bmake/unit-tests/deptgt-path-suffix.exp b/contrib/bmake/unit-tests/deptgt-path-suffix.exp index 6294d8a39dc0..e1c67daa8787 100644 --- a/contrib/bmake/unit-tests/deptgt-path-suffix.exp +++ b/contrib/bmake/unit-tests/deptgt-path-suffix.exp @@ -1,4 +1,4 @@ -make: deptgt-path-suffix.mk:8: Suffix '.c' not defined (yet) +make: deptgt-path-suffix.mk:8: Suffix ".c" not defined (yet) make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/deptgt-path-suffix.mk b/contrib/bmake/unit-tests/deptgt-path-suffix.mk index 494a076a5520..68bb27036b68 100644 --- a/contrib/bmake/unit-tests/deptgt-path-suffix.mk +++ b/contrib/bmake/unit-tests/deptgt-path-suffix.mk @@ -1,10 +1,10 @@ -# $NetBSD: deptgt-path-suffix.mk,v 1.3 2021/12/13 23:38:54 rillig Exp $ +# $NetBSD: deptgt-path-suffix.mk,v 1.4 2025/06/28 22:39:28 rillig Exp $ # # Tests for the special target .PATH.suffix in dependency declarations. # TODO: Implementation -# expect+1: Suffix '.c' not defined (yet) +# expect+1: Suffix ".c" not defined (yet) .PATH.c: .. .SUFFIXES: .c diff --git a/contrib/bmake/unit-tests/deptgt.exp b/contrib/bmake/unit-tests/deptgt.exp index 4c7cb4e50ddc..230fa497fcbd 100644 --- a/contrib/bmake/unit-tests/deptgt.exp +++ b/contrib/bmake/unit-tests/deptgt.exp @@ -1,4 +1,4 @@ -make: deptgt.mk:11: warning: Extra target '.PHONY' ignored +make: deptgt.mk:11: warning: Extra target ".PHONY" ignored make: deptgt.mk:30: Unassociated shell command ": command3 # parse error, since targets == NULL" Parsing deptgt.mk:36: ${:U}: empty-source ParseDependency(: empty-source) @@ -18,8 +18,8 @@ make: deptgt.mk:51: Unknown modifier ":Z" while evaluating "${:U:Z}:" with value "" make: deptgt.mk:55: Unknown modifier ":Z" while parsing "${:U:Z}:" -make: deptgt.mk:58: warning: Extra target 'ordinary' ignored -make: deptgt.mk:61: warning: Extra target (ordinary) ignored +make: deptgt.mk:58: warning: Extra target "ordinary" ignored +make: deptgt.mk:61: warning: Extra target "ordinary" ignored make: deptgt.mk:64: warning: Special and mundane targets don't mix. Mundane ones ignored make: Fatal errors encountered -- cannot continue make: stopped making "target1" in unit-tests diff --git a/contrib/bmake/unit-tests/deptgt.mk b/contrib/bmake/unit-tests/deptgt.mk index 779a1faf7115..fd7a716e3ebc 100644 --- a/contrib/bmake/unit-tests/deptgt.mk +++ b/contrib/bmake/unit-tests/deptgt.mk @@ -1,4 +1,4 @@ -# $NetBSD: deptgt.mk,v 1.23 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: deptgt.mk,v 1.24 2025/06/28 22:39:28 rillig Exp $ # # Tests for special targets like .BEGIN or .SUFFIXES in dependency # declarations. @@ -7,7 +7,7 @@ # Just in case anyone tries to compile several special targets in a single # dependency line: That doesn't work, and make immediately rejects it. -# expect+1: warning: Extra target '.PHONY' ignored +# expect+1: warning: Extra target ".PHONY" ignored .SUFFIXES .PHONY: .c.o # The following lines demonstrate how 'targets' is set and reset during @@ -54,10 +54,10 @@ ${:U:Z}: # expect+1: Unknown modifier ":Z" $${:U:Z}: -# expect+1: warning: Extra target 'ordinary' ignored +# expect+1: warning: Extra target "ordinary" ignored .END ordinary: -# expect+1: warning: Extra target (ordinary) ignored +# expect+1: warning: Extra target "ordinary" ignored .PATH ordinary: # expect+1: warning: Special and mundane targets don't mix. Mundane ones ignored diff --git a/contrib/bmake/unit-tests/directive-dinclude.exp b/contrib/bmake/unit-tests/directive-dinclude.exp index 5f5fec4d403e..55f1f77fbfde 100755 --- a/contrib/bmake/unit-tests/directive-dinclude.exp +++ b/contrib/bmake/unit-tests/directive-dinclude.exp @@ -1,4 +1,4 @@ -make: directive-dinclude-error.inc:1: Invalid line 'syntax error' +make: directive-dinclude-error.inc:1: Invalid line "syntax error" in directive-dinclude.mk:21 make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests diff --git a/contrib/bmake/unit-tests/directive-dinclude.mk b/contrib/bmake/unit-tests/directive-dinclude.mk index c363209579ad..da063083235f 100755 --- a/contrib/bmake/unit-tests/directive-dinclude.mk +++ b/contrib/bmake/unit-tests/directive-dinclude.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-dinclude.mk,v 1.4 2025/03/30 09:51:50 rillig Exp $ +# $NetBSD: directive-dinclude.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $ # # Tests for the .dinclude directive, which includes another file, # silently skipping it if it cannot be opened. This is primarily used for @@ -16,7 +16,7 @@ .dinclude "${MAKEFILE}/subdir" # Errors that are not related to opening the file are still reported. -# expect: make: directive-dinclude-error.inc:1: Invalid line 'syntax error' +# expect: make: directive-dinclude-error.inc:1: Invalid line "syntax error" _!= echo 'syntax error' > directive-dinclude-error.inc .dinclude "${.CURDIR}/directive-dinclude-error.inc" _!= rm directive-dinclude-error.inc diff --git a/contrib/bmake/unit-tests/directive-export-gmake.exp b/contrib/bmake/unit-tests/directive-export-gmake.exp index f7bb07ab9da2..2c2875d669d2 100644 --- a/contrib/bmake/unit-tests/directive-export-gmake.exp +++ b/contrib/bmake/unit-tests/directive-export-gmake.exp @@ -1,4 +1,4 @@ -make: directive-export-gmake.mk:71: Invalid line 'export VAR=${:U1}', expanded to 'export VAR=1' +make: directive-export-gmake.mk:71: Invalid line "export VAR=${:U1}", expanded to "export VAR=1" in .for loop from directive-export-gmake.mk:67 with value = 1 make: directive-export-gmake.mk:85: 16:00:00 make: directive-export-gmake.mk:92: Variable/Value missing from "export" diff --git a/contrib/bmake/unit-tests/directive-export-gmake.mk b/contrib/bmake/unit-tests/directive-export-gmake.mk index de79470bf305..6e1d57c6a62d 100644 --- a/contrib/bmake/unit-tests/directive-export-gmake.mk +++ b/contrib/bmake/unit-tests/directive-export-gmake.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-export-gmake.mk,v 1.9 2023/12/17 09:44:00 rillig Exp $ +# $NetBSD: directive-export-gmake.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $ # # Tests for the export directive (without leading dot), as in GNU make. @@ -67,7 +67,7 @@ export VAR=an ${UNDEF} variable .for value in 1 # XXX: The ':' in this line is inside an expression and should thus not be # interpreted as a dependency operator. -# expect+1: Invalid line 'export VAR=${:U1}', expanded to 'export VAR=1' +# expect+1: Invalid line "export VAR=${:U1}", expanded to "export VAR=1" export VAR=${value} .endfor diff --git a/contrib/bmake/unit-tests/directive-for-errors.exp b/contrib/bmake/unit-tests/directive-for-errors.exp index 39929864314d..1bae631b967a 100644 --- a/contrib/bmake/unit-tests/directive-for-errors.exp +++ b/contrib/bmake/unit-tests/directive-for-errors.exp @@ -4,10 +4,10 @@ make: directive-for-errors.mk:13: for-less endfor make: directive-for-errors.mk:25: Unknown directive "for" make: directive-for-errors.mk:27: warning: <> make: directive-for-errors.mk:29: for-less endfor -make: directive-for-errors.mk:44: invalid character '$' in .for loop variable name -make: directive-for-errors.mk:52: no iteration variables in for +make: directive-for-errors.mk:44: Invalid character "$" in .for loop variable name +make: directive-for-errors.mk:52: Missing iteration variables in .for loop make: directive-for-errors.mk:64: Wrong number of words (5) in .for substitution list with 3 variables -make: directive-for-errors.mk:78: missing `in' in for +make: directive-for-errors.mk:78: Missing "in" in .for loop make: directive-for-errors.mk:85: Unknown modifier ":Z" while evaluating "${:U3:Z} 4" with value "3" make: Fatal errors encountered -- cannot continue diff --git a/contrib/bmake/unit-tests/directive-for-errors.mk b/contrib/bmake/unit-tests/directive-for-errors.mk index a58b8294289b..2571b600bf38 100644 --- a/contrib/bmake/unit-tests/directive-for-errors.mk +++ b/contrib/bmake/unit-tests/directive-for-errors.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-errors.mk,v 1.17 2025/05/03 08:18:33 rillig Exp $ +# $NetBSD: directive-for-errors.mk,v 1.18 2025/06/28 22:39:28 rillig Exp $ # # Tests for error handling in .for loops. @@ -40,7 +40,7 @@ # error everywhere outside a .for loop. ${:U\$}= dollar # see whether the "variable" '$' is local ${:U\\}= backslash # see whether the "variable" '\' is local -# expect+1: invalid character '$' in .for loop variable name +# expect+1: Invalid character "$" in .for loop variable name .for a b $ \ in 1 2 3 4 . info Dollar $$ ${$} $($) and backslash $\ ${\} $(\). .endfor @@ -48,7 +48,7 @@ ${:U\\}= backslash # see whether the "variable" '\' is local # If there are no variables, there is no point in expanding the .for loop # since this would end up in an endless loop, consuming 0 of the 3 values in # each iteration. -# expect+1: no iteration variables in for +# expect+1: Missing iteration variables in .for loop .for in 1 2 3 # XXX: This should not be reached. It should be skipped, as already done # when the number of values is not a multiple of the number of variables, @@ -74,7 +74,7 @@ ${:U\\}= backslash # see whether the "variable" '\' is local # A missing 'in' parses the .for loop but skips the body. -# expect+1: missing `in' in for +# expect+1: Missing "in" in .for loop .for i over k . error .endfor diff --git a/contrib/bmake/unit-tests/directive-for-escape.exp b/contrib/bmake/unit-tests/directive-for-escape.exp index 6ab8a333a10f..78cc57a738a2 100644 --- a/contrib/bmake/unit-tests/directive-for-escape.exp +++ b/contrib/bmake/unit-tests/directive-for-escape.exp @@ -1,14 +1,14 @@ For: end for 1 For: loop body with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~: . info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} -make: directive-for-escape.mk:21: Unclosed expression, expecting '}' for modifier "U!"" +make: directive-for-escape.mk:21: Unclosed expression, expecting "}" for modifier "U!"" while evaluating "${:U!"" with value "!"" in .for loop from directive-for-escape.mk:20 with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ make: directive-for-escape.mk:21: !" For: end for 1 For: loop body with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~: . info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} -make: directive-for-escape.mk:33: Unclosed expression, expecting '}' for modifier "U!"\\\\" +make: directive-for-escape.mk:33: Unclosed expression, expecting "}" for modifier "U!"\\\\" while evaluating "${:U!"\\\\" with value "!"\\" in .for loop from directive-for-escape.mk:32 with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ make: directive-for-escape.mk:33: !"\\ @@ -69,9 +69,9 @@ For: end for 1 For: loop body with i = $: . info ${:U\$} make: directive-for-escape.mk:147: $ -make: directive-for-escape.mk:155: invalid character ':' in .for loop variable name +make: directive-for-escape.mk:155: Invalid character ":" in .for loop variable name For: end for 1 -make: directive-for-escape.mk:165: invalid character '}' in .for loop variable name +make: directive-for-escape.mk:165: Invalid character "}" in .for loop variable name For: end for 1 For: end for 1 For: loop body with i = inner: @@ -89,7 +89,7 @@ For: end for 1 For: loop body with i = inner: . info ${i2} ${i,} ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner} make: directive-for-escape.mk:187: two comma innerinnerinnerinner -make: directive-for-escape.mk:196: invalid character '$' in .for loop variable name +make: directive-for-escape.mk:196: Invalid character "$" in .for loop variable name For: end for 1 make: directive-for-escape.mk:208: eight and no cents. For: end for 1 diff --git a/contrib/bmake/unit-tests/directive-for-escape.mk b/contrib/bmake/unit-tests/directive-for-escape.mk index e688ce98f258..913d61831c46 100644 --- a/contrib/bmake/unit-tests/directive-for-escape.mk +++ b/contrib/bmake/unit-tests/directive-for-escape.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-escape.mk,v 1.29 2024/08/29 20:20:36 rillig Exp $ +# $NetBSD: directive-for-escape.mk,v 1.30 2025/06/28 22:39:28 rillig Exp $ # # Test escaping of special characters in the iteration values of a .for loop. # These values get expanded later using the :U variable modifier, and this @@ -15,7 +15,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ # XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of # the loop. Not only would it need the escaping for the variable modifier # ':U' but also the escaping for the line-end comment. -# expect+3: Unclosed expression, expecting '}' for modifier "U!"" +# expect+3: Unclosed expression, expecting "}" for modifier "U!"" # expect+2: !" .for chars in ${ASCII} . info ${chars} @@ -27,7 +27,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ # This means that a '#' sign cannot be passed in the value of a .for loop # at all. ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ -# expect+3: Unclosed expression, expecting '}' for modifier "U!"\\\\" +# expect+3: Unclosed expression, expecting "}" for modifier "U!"\\\\" # expect+2: !"\\ .for chars in ${ASCII.2020-12-31} . info ${chars} @@ -151,7 +151,7 @@ VALUES= begin<$${UNDEF:Ufallback:N{{{}}}}>end # could contain colons, which affected expressions having this exact # modifier. This possibility was neither intended nor documented. NUMBERS= one two three -# expect+1: invalid character ':' in .for loop variable name +# expect+1: Invalid character ":" in .for loop variable name .for NUMBERS:M*e in replaced . info ${NUMBERS} ${NUMBERS:M*e} .endfor @@ -161,7 +161,7 @@ NUMBERS= one two three # expressions. This possibility was neither intended nor documented. BASENAME= one EXT= .c -# expect+1: invalid character '}' in .for loop variable name +# expect+1: Invalid character "}" in .for loop variable name .for BASENAME}${EXT in replaced . info ${BASENAME}${EXT} .endfor @@ -192,7 +192,7 @@ i,= comma # skipped "stupid" variable names though, but ForLoop_SubstVarLong naively # parsed the body of the loop, substituting each '${$}' with an actual # '${:Udollar}'. -# expect+1: invalid character '$' in .for loop variable name +# expect+1: Invalid character "$" in .for loop variable name .for $ in dollar . info eight $$$$$$$$ and no cents. . info eight ${$}${$}${$}${$} and no cents. diff --git a/contrib/bmake/unit-tests/directive-for-lines.exp b/contrib/bmake/unit-tests/directive-for-lines.exp index bf5b2b8b1209..23227122ffd3 100644 --- a/contrib/bmake/unit-tests/directive-for-lines.exp +++ b/contrib/bmake/unit-tests/directive-for-lines.exp @@ -1,9 +1,9 @@ -make: directive-for-lines.mk:27: expect 23 -make: directive-for-lines.mk:27: expect 23 -make: directive-for-lines.mk:36: expect 30 -make: directive-for-lines.mk:27: expect 23 -make: directive-for-lines.mk:27: expect 23 -make: directive-for-lines.mk:36: expect 30 +make: directive-for-lines.mk:31: This is line 31. +make: directive-for-lines.mk:31: This is line 31. +make: directive-for-lines.mk:38: This is line 38. +make: directive-for-lines.mk:31: This is line 31. +make: directive-for-lines.mk:31: This is line 31. +make: directive-for-lines.mk:38: This is line 38. make: no target to make. make: stopped in unit-tests diff --git a/contrib/bmake/unit-tests/directive-for-lines.mk b/contrib/bmake/unit-tests/directive-for-lines.mk index cae4e0a38897..898a1960e76a 100644 --- a/contrib/bmake/unit-tests/directive-for-lines.mk +++ b/contrib/bmake/unit-tests/directive-for-lines.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-lines.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: directive-for-lines.mk,v 1.6 2025/06/30 21:44:39 rillig Exp $ # # Tests for the line numbers that are reported in .for loops. # @@ -7,6 +7,14 @@ # messages inside .for loops had been wrong since ParseGetLine skipped empty # lines, even when collecting the lines for the .for loop body. +# expect+21: This is line 31. +# expect+20: This is line 31. +# expect+26: This is line 38. + +# expect+17: This is line 31. +# expect+16: This is line 31. +# expect+22: This is line 38. + .for outer in a b # comment \ @@ -20,19 +28,13 @@ VAR= \ multi-line -# expect+4: expect 23 -# expect+3: expect 23 -# expect+2: expect 23 -# expect+1: expect 23 -.info expect 23 +.info This is line 31. .endfor # comment \ # continued comment -# expect+2: expect 30 -# expect+1: expect 30 -.info expect 30 +.info This is line 38. .endfor diff --git a/contrib/bmake/unit-tests/directive-for.exp b/contrib/bmake/unit-tests/directive-for.exp index cf87e6ea8569..d1c1064f0ef5 100755 --- a/contrib/bmake/unit-tests/directive-for.exp +++ b/contrib/bmake/unit-tests/directive-for.exp @@ -14,16 +14,16 @@ make: directive-for.mk:158: {{}} {{}} {{}} make: directive-for.mk:158: )( )( )( make: directive-for.mk:158: ][ ][ ][ make: directive-for.mk:158: }{ }{ }{ -make: directive-for.mk:166: invalid character ':' in .for loop variable name -make: directive-for.mk:173: invalid character '$' in .for loop variable name -make: directive-for.mk:185: invalid character '$' in .for loop variable name -make: directive-for.mk:207: no iteration variables in for -make: directive-for.mk:233: 1 open conditional - in .for loop from directive-for.mk:231 with var = value -make: directive-for.mk:249: for-less endfor -make: directive-for.mk:250: if-less endif -make: directive-for.mk:258: if-less endif - in .for loop from directive-for.mk:257 with var = value +make: directive-for.mk:166: Invalid character ":" in .for loop variable name +make: directive-for.mk:173: Invalid character "$" in .for loop variable name +make: directive-for.mk:185: Invalid character "$" in .for loop variable name +make: directive-for.mk:208: Missing iteration variables in .for loop +make: directive-for.mk:234: 1 open conditional + in .for loop from directive-for.mk:232 with var = value +make: directive-for.mk:252: for-less endfor +make: directive-for.mk:254: if-less endif +make: directive-for.mk:263: if-less endif + in .for loop from directive-for.mk:261 with var = value For: new loop 2 For: end for 2 For: end for 1 @@ -34,7 +34,7 @@ For: loop body with outer = o: endfor For: end for 1 For: loop body with inner = i: -make: directive-for.mk:307: newline-item=(a) +make: directive-for.mk:312: newline-item=(a) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/directive-for.mk b/contrib/bmake/unit-tests/directive-for.mk index 2f989f54f228..72ffaa142ad6 100755 --- a/contrib/bmake/unit-tests/directive-for.mk +++ b/contrib/bmake/unit-tests/directive-for.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for.mk,v 1.30 2025/03/30 16:43:10 rillig Exp $ +# $NetBSD: directive-for.mk,v 1.32 2025/07/01 04:24:20 rillig Exp $ # # Tests for the .for directive. # @@ -162,14 +162,14 @@ EXPANSION${plus}= value # except for whitespace, allowing for creative side effects, as usual for # arbitrary code injection. var= outer -# expect+1: invalid character ':' in .for loop variable name +# expect+1: Invalid character ":" in .for loop variable name .for var:Q in value "quoted" . info <${var}> <${var:Q}> <${var:Q:Q}> .endfor # Before 2023-05-09, when variable names could contain '$', the short # expression '$$' was preserved, the long expressions were substituted. -# expect+1: invalid character '$' in .for loop variable name +# expect+1: Invalid character "$" in .for loop variable name .for $ in value . info <$$> <${$}> <$($)> .endfor @@ -181,7 +181,7 @@ var= outer # possibility, therefore the variable names are restricted to using harmless # characters only. INDIRECT= direct -# expect+1: invalid character '$' in .for loop variable name +# expect+1: Invalid character "$" in .for loop variable name .for $(INDIRECT) in value # If the variable name could be chosen dynamically, the iteration variable # might have been 'direct', thereby expanding the expression '${direct}'. @@ -204,7 +204,8 @@ INDIRECT= ${DIRECT} # An empty list of variables to the left of the 'in' is a parse error. -.for in value # expect+0: no iteration variables in for +# expect+1: Missing iteration variables in .for loop +.for in value . error .endfor @@ -230,7 +231,8 @@ INDIRECT= ${DIRECT} # is processed. .for var in value . if 0 -.endfor # expect+0: 1 open conditional +.endfor +# expect-1: 1 open conditional # If there are no iteration values, the loop body is not processed, and the # check for mismatched conditionals is not performed. @@ -246,8 +248,10 @@ INDIRECT= ${DIRECT} .if 0 . for var in value # does not need a corresponding .endfor .endif -.endfor # expect+0: for-less endfor -.endif # expect+0: if-less endif +# expect+1: for-less endfor +.endfor +# expect+1: if-less endif +.endif # When a .for without the corresponding .endfor occurs in an active branch of @@ -255,7 +259,8 @@ INDIRECT= ${DIRECT} # without looking at any other directives. .if 1 . for var in value -. endif # expect+0: if-less endif +# expect+1: if-less endif +. endif . endfor # no 'for-less endfor' .endif # no 'if-less endif' diff --git a/contrib/bmake/unit-tests/directive-hyphen-include.exp b/contrib/bmake/unit-tests/directive-hyphen-include.exp index 3f17f0c41f0b..d1d37e783ca9 100755 --- a/contrib/bmake/unit-tests/directive-hyphen-include.exp +++ b/contrib/bmake/unit-tests/directive-hyphen-include.exp @@ -1,4 +1,4 @@ -make: directive-hyphen-include-error.inc:1: Invalid line 'syntax error' +make: directive-hyphen-include-error.inc:1: Invalid line "syntax error" in directive-hyphen-include.mk:20 make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests diff --git a/contrib/bmake/unit-tests/directive-hyphen-include.mk b/contrib/bmake/unit-tests/directive-hyphen-include.mk index ad596f4c47db..de438dfaffac 100755 --- a/contrib/bmake/unit-tests/directive-hyphen-include.mk +++ b/contrib/bmake/unit-tests/directive-hyphen-include.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-hyphen-include.mk,v 1.4 2025/03/30 09:51:50 rillig Exp $ +# $NetBSD: directive-hyphen-include.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $ # # Tests for the .-include directive, which includes another file, # silently skipping it if it cannot be opened. @@ -15,7 +15,7 @@ .-include "${MAKEFILE}/subdir" # Errors that are not related to opening the file are still reported. -# expect: make: directive-hyphen-include-error.inc:1: Invalid line 'syntax error' +# expect: make: directive-hyphen-include-error.inc:1: Invalid line "syntax error" _!= echo 'syntax error' > directive-hyphen-include-error.inc .-include "${.CURDIR}/directive-hyphen-include-error.inc" _!= rm directive-hyphen-include-error.inc diff --git a/contrib/bmake/unit-tests/directive-if.exp b/contrib/bmake/unit-tests/directive-if.exp index 0d4a7ea16d34..634c9ee6b1df 100644 --- a/contrib/bmake/unit-tests/directive-if.exp +++ b/contrib/bmake/unit-tests/directive-if.exp @@ -5,7 +5,7 @@ make: directive-if.mk:45: This is not conditional. make: directive-if.mk:47: if-less else make: directive-if.mk:49: This is not conditional. make: directive-if.mk:51: if-less endif -make: directive-if.mk:55: Malformed conditional '' +make: directive-if.mk:55: Malformed conditional "" make: directive-if.mk:66: Quotes in plain words are probably a mistake. make: directive-if.mk:76: Don't do this, always put a space after a directive. make: directive-if.mk:81: Don't do this, always put a space after a directive. diff --git a/contrib/bmake/unit-tests/directive-if.mk b/contrib/bmake/unit-tests/directive-if.mk index 7ff04da0755b..5d1232d245a9 100644 --- a/contrib/bmake/unit-tests/directive-if.mk +++ b/contrib/bmake/unit-tests/directive-if.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-if.mk,v 1.13 2024/08/06 18:00:17 rillig Exp $ +# $NetBSD: directive-if.mk,v 1.14 2025/06/28 22:39:28 rillig Exp $ # # Tests for the .if directive. # @@ -51,7 +51,7 @@ .endif # Missing condition. -# expect+1: Malformed conditional '' +# expect+1: Malformed conditional "" .if . error .else diff --git a/contrib/bmake/unit-tests/directive-include.exp b/contrib/bmake/unit-tests/directive-include.exp index 71f39c57e807..361389cf1cad 100755 --- a/contrib/bmake/unit-tests/directive-include.exp +++ b/contrib/bmake/unit-tests/directive-include.exp @@ -8,7 +8,7 @@ make: directive-include.mk:56: Unknown modifier ":Z" while evaluating "${:U123:Z}.mk" with value "123" make: directive-include.mk:56: Could not find nonexistent.mk make: directive-include.mk:61: Cannot open /nonexistent -make: directive-include.mk:66: Invalid line 'include' +make: directive-include.mk:66: Invalid line "include" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/directive-include.mk b/contrib/bmake/unit-tests/directive-include.mk index 42cdd97c43c7..ad6936ab2f3c 100755 --- a/contrib/bmake/unit-tests/directive-include.mk +++ b/contrib/bmake/unit-tests/directive-include.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-include.mk,v 1.19 2025/03/30 09:51:50 rillig Exp $ +# $NetBSD: directive-include.mk,v 1.20 2025/06/28 22:39:28 rillig Exp $ # # Tests for the .include directive, which includes another file. @@ -62,7 +62,7 @@ include /nonexistent # comment sinclude /nonexistent # comment include ${:U/dev/null} # comment include /dev/null /dev/null -# expect+1: Invalid line 'include' +# expect+1: Invalid line "include" include # XXX: trailing whitespace in diagnostic, missing quotes around filename diff --git a/contrib/bmake/unit-tests/directive-misspellings.exp b/contrib/bmake/unit-tests/directive-misspellings.exp index b918d05a2683..c551d73d5f98 100644 --- a/contrib/bmake/unit-tests/directive-misspellings.exp +++ b/contrib/bmake/unit-tests/directive-misspellings.exp @@ -1,6 +1,6 @@ make: directive-misspellings.mk:13: Unknown directive "dinclud" make: directive-misspellings.mk:16: Unknown directive "dincludx" -make: directive-misspellings.mk:18: .include filename must be delimited by '"' or '<' +make: directive-misspellings.mk:18: .include filename must be delimited by "" or <> make: directive-misspellings.mk:21: Unknown directive "erro" make: directive-misspellings.mk:23: Unknown directive "errox" make: directive-misspellings.mk:28: Unknown directive "expor" @@ -13,18 +13,18 @@ make: directive-misspellings.mk:46: Unknown directive "export-literax" make: directive-misspellings.mk:48: Unknown directive "export-literally" make: directive-misspellings.mk:51: Unknown directive "-includ" make: directive-misspellings.mk:54: Unknown directive "-includx" -make: directive-misspellings.mk:56: .include filename must be delimited by '"' or '<' +make: directive-misspellings.mk:56: .include filename must be delimited by "" or <> make: directive-misspellings.mk:59: Unknown directive "includ" make: directive-misspellings.mk:61: Could not find file make: directive-misspellings.mk:63: Unknown directive "includx" -make: directive-misspellings.mk:65: .include filename must be delimited by '"' or '<' +make: directive-misspellings.mk:65: .include filename must be delimited by "" or <> make: directive-misspellings.mk:68: Unknown directive "inf" make: directive-misspellings.mk:70: msg make: directive-misspellings.mk:72: Unknown directive "infx" make: directive-misspellings.mk:74: Unknown directive "infos" make: directive-misspellings.mk:77: Unknown directive "sinclud" make: directive-misspellings.mk:80: Unknown directive "sincludx" -make: directive-misspellings.mk:82: .include filename must be delimited by '"' or '<' +make: directive-misspellings.mk:82: .include filename must be delimited by "" or <> make: directive-misspellings.mk:85: Unknown directive "unde" make: directive-misspellings.mk:88: Unknown directive "undex" make: directive-misspellings.mk:90: Unknown directive "undefs" diff --git a/contrib/bmake/unit-tests/directive-misspellings.mk b/contrib/bmake/unit-tests/directive-misspellings.mk index 0014076d041f..cd6222b378f5 100644 --- a/contrib/bmake/unit-tests/directive-misspellings.mk +++ b/contrib/bmake/unit-tests/directive-misspellings.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-misspellings.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: directive-misspellings.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $ # # Tests for misspelled directives. # @@ -14,7 +14,7 @@ .dinclude "file" # expect+1: Unknown directive "dincludx" .dincludx "file" -# expect+1: .include filename must be delimited by '"' or '<' +# expect+1: .include filename must be delimited by "" or <> .dincludes "file" # XXX: the 's' is not meant to be a filename # expect+1: Unknown directive "erro" @@ -52,7 +52,7 @@ .-include "file" # expect+1: Unknown directive "-includx" .-includx "file" -# expect+1: .include filename must be delimited by '"' or '<' +# expect+1: .include filename must be delimited by "" or <> .-includes "file" # XXX: the 's' is not meant to be a filename # expect+1: Unknown directive "includ" @@ -61,7 +61,7 @@ .include "file" # expect+1: Unknown directive "includx" .includx "file" -# expect+1: .include filename must be delimited by '"' or '<' +# expect+1: .include filename must be delimited by "" or <> .includex "file" # XXX: the 's' is not meant to be a filename # expect+1: Unknown directive "inf" @@ -78,7 +78,7 @@ .sinclude "file" # expect+1: Unknown directive "sincludx" .sincludx "file" -# expect+1: .include filename must be delimited by '"' or '<' +# expect+1: .include filename must be delimited by "" or <> .sincludes "file" # XXX: the 's' is not meant to be a filename # expect+1: Unknown directive "unde" diff --git a/contrib/bmake/unit-tests/directive-sinclude.exp b/contrib/bmake/unit-tests/directive-sinclude.exp index b7503e18c9b5..74db51227f07 100755 --- a/contrib/bmake/unit-tests/directive-sinclude.exp +++ b/contrib/bmake/unit-tests/directive-sinclude.exp @@ -1,4 +1,4 @@ -make: directive-include-error.inc:1: Invalid line 'syntax error' +make: directive-include-error.inc:1: Invalid line "syntax error" in directive-sinclude.mk:20 make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests diff --git a/contrib/bmake/unit-tests/directive-sinclude.mk b/contrib/bmake/unit-tests/directive-sinclude.mk index d40915fa86d5..4c856d22be4f 100755 --- a/contrib/bmake/unit-tests/directive-sinclude.mk +++ b/contrib/bmake/unit-tests/directive-sinclude.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-sinclude.mk,v 1.6 2025/03/30 09:51:50 rillig Exp $ +# $NetBSD: directive-sinclude.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $ # # Tests for the .sinclude directive, which includes another file, # silently skipping it if it cannot be opened. @@ -15,7 +15,7 @@ .sinclude "${MAKEFILE}/subdir" # Errors that are not related to opening the file are still reported. -# expect: make: directive-include-error.inc:1: Invalid line 'syntax error' +# expect: make: directive-include-error.inc:1: Invalid line "syntax error" _!= echo 'syntax error' > directive-include-error.inc .sinclude "${.CURDIR}/directive-include-error.inc" _!= rm directive-include-error.inc diff --git a/contrib/bmake/unit-tests/directive-unexport.exp b/contrib/bmake/unit-tests/directive-unexport.exp index 1be4b03e3874..25bab7d7fd35 100644 --- a/contrib/bmake/unit-tests/directive-unexport.exp +++ b/contrib/bmake/unit-tests/directive-unexport.exp @@ -1,5 +1,5 @@ make: directive-unexport.mk:19: UT_A=a UT_B=b UT_C=c make: directive-unexport.mk:21: UT_A UT_B UT_C make: directive-unexport.mk:30: UT_A=a UT_B=b UT_C=c -make: directive-unexport.mk:31: +make: directive-unexport.mk:32: exit status 0 diff --git a/contrib/bmake/unit-tests/directive-unexport.mk b/contrib/bmake/unit-tests/directive-unexport.mk index e759fe3e35f2..3c10ffa07d6a 100644 --- a/contrib/bmake/unit-tests/directive-unexport.mk +++ b/contrib/bmake/unit-tests/directive-unexport.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-unexport.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ +# $NetBSD: directive-unexport.mk,v 1.9 2025/06/30 21:44:39 rillig Exp $ # # Tests for the .unexport directive. # @@ -28,6 +28,7 @@ UT_C= c # expect+1: UT_A=a UT_B=b UT_C=c .info ${:!env|sort|grep '^UT_'!} +# expect+1: .info ${.MAKE.EXPORTED} .unexport # oops: missing argument diff --git a/contrib/bmake/unit-tests/directive-warning.exp b/contrib/bmake/unit-tests/directive-warning.exp index 2dd4e8ceb7f9..250e32583847 100644 --- a/contrib/bmake/unit-tests/directive-warning.exp +++ b/contrib/bmake/unit-tests/directive-warning.exp @@ -3,9 +3,9 @@ make: directive-warning.mk:12: Unknown directive "warn" make: directive-warning.mk:14: Unknown directive "warnin" make: directive-warning.mk:16: Unknown directive "warnin" make: directive-warning.mk:18: Missing argument for ".warning" -make: directive-warning.mk:19: warning: message -make: directive-warning.mk:21: Unknown directive "warnings" -make: directive-warning.mk:23: Unknown directive "warnings" +make: directive-warning.mk:20: warning: message +make: directive-warning.mk:22: Unknown directive "warnings" +make: directive-warning.mk:24: Unknown directive "warnings" make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/directive-warning.mk b/contrib/bmake/unit-tests/directive-warning.mk index bf0683f8911f..50666487c13f 100644 --- a/contrib/bmake/unit-tests/directive-warning.mk +++ b/contrib/bmake/unit-tests/directive-warning.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-warning.mk,v 1.9 2023/12/17 09:44:00 rillig Exp $ +# $NetBSD: directive-warning.mk,v 1.10 2025/07/01 04:24:20 rillig Exp $ # # Tests for the .warning directive. # @@ -16,7 +16,8 @@ .warnin message # misspelled # expect+1: Missing argument for ".warning" .warning # "Missing argument" -.warning message # expect+0: warning: message +# expect+1: warning: message +.warning message # expect+1: Unknown directive "warnings" .warnings # misspelled # expect+1: Unknown directive "warnings" diff --git a/contrib/bmake/unit-tests/directive.exp b/contrib/bmake/unit-tests/directive.exp index 2f1da18cdbb5..dce759abfe52 100644 --- a/contrib/bmake/unit-tests/directive.exp +++ b/contrib/bmake/unit-tests/directive.exp @@ -7,8 +7,8 @@ Global: .info = value make: directive.mk:31: := value Global: .MAKEFLAGS = -r -k -d v -d Global: .MAKEFLAGS = -r -k -d v -d 0 -make: directive.mk:40: Invalid line 'target-without-colon' -make: directive.mk:43: Invalid line 'target-without-colon another-target' +make: directive.mk:40: Invalid line "target-without-colon" +make: directive.mk:43: Invalid line "target-without-colon another-target" make: Fatal errors encountered -- cannot continue make: stopped making ".target" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/directive.mk b/contrib/bmake/unit-tests/directive.mk index 61938360dfc7..5f5be5aa0fab 100644 --- a/contrib/bmake/unit-tests/directive.mk +++ b/contrib/bmake/unit-tests/directive.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive.mk,v 1.9 2023/11/19 22:32:44 rillig Exp $ +# $NetBSD: directive.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $ # # Tests for the preprocessing directives, such as .if or .info. @@ -36,8 +36,8 @@ # Not even the space after the '.info' can change anything about this. .${:Uinfo} : source -# expect+1: Invalid line 'target-without-colon' +# expect+1: Invalid line "target-without-colon" target-without-colon -# expect+1: Invalid line 'target-without-colon another-target' +# expect+1: Invalid line "target-without-colon another-target" target-without-colon another-target diff --git a/contrib/bmake/unit-tests/moderrs.exp b/contrib/bmake/unit-tests/moderrs.exp index 08aa2582f6be..4758294f0993 100644 --- a/contrib/bmake/unit-tests/moderrs.exp +++ b/contrib/bmake/unit-tests/moderrs.exp @@ -7,11 +7,11 @@ make: Unknown modifier ":Z" while evaluating variable "VAR" with value "TheVariable" in command "@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'" in target "mod-unknown-indirect" -make: Unclosed expression, expecting '}' for modifier "S,V,v," +make: Unclosed expression, expecting "}" for modifier "S,V,v," while evaluating variable "VAR" with value "Thevariable" in command "@echo VAR:S,V,v,=${VAR:S,V,v," in target "unclosed-direct" -make: Unclosed expression after indirect modifier, expecting '}' +make: Unclosed expression after indirect modifier, expecting "}" while evaluating variable "VAR" with value "Thevariable" in command "@echo VAR:${MOD_TERM},=${VAR:${MOD_S}" in target "unclosed-indirect" @@ -29,7 +29,7 @@ make: Unfinished modifier after "...}", expecting "@" in command "@echo ${UNDEF:U1 2 3:@var@...}" in target "unfinished-loop-2" 1 2 3 -make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@" +make: Unclosed expression, expecting "}" for modifier "@var@${var}}...@" while evaluating variable "UNDEF" with value "1}... 2}... 3}..." in command "@echo ${UNDEF:U1 2 3:@var@${var}}...@" in target "loop-close-1" @@ -55,7 +55,7 @@ make: Unfinished modifier after "=exclam}", expecting "!" while evaluating variable "!" with value "!" in command "@echo ${!:L:!=exclam}" in target "exclam-2" -make: Missing delimiter for modifier ':S' +make: Missing delimiter for modifier ":S" while evaluating variable "VAR" with value "TheVariable" in command "@echo 1: ${VAR:S" in target "mod-subst-delimiter-1" @@ -75,12 +75,12 @@ make: Unfinished modifier after "to", expecting "," while evaluating variable "VAR" with value "TheVariable" in command "@echo 5: ${VAR:S,from,to" in target "mod-subst-delimiter-5" -make: Unclosed expression, expecting '}' for modifier "S,from,to," +make: Unclosed expression, expecting "}" for modifier "S,from,to," while evaluating variable "VAR" with value "TheVariable" in command "@echo 6: ${VAR:S,from,to," in target "mod-subst-delimiter-6" 7: TheVariable -make: Missing delimiter for modifier ':C' +make: Missing delimiter for modifier ":C" while evaluating variable "VAR" with value "TheVariable" in command "@echo 1: ${VAR:C" in target "mod-regex-delimiter-1" @@ -100,7 +100,7 @@ make: Unfinished modifier after "to", expecting "," while evaluating variable "VAR" with value "TheVariable" in command "@echo 5: ${VAR:C,from,to" in target "mod-regex-delimiter-5" -make: Unclosed expression, expecting '}' for modifier "C,from,to," +make: Unclosed expression, expecting "}" for modifier "C,from,to," while evaluating variable "VAR" with value "TheVariable" in command "@echo 6: ${VAR:C,from,to," in target "mod-regex-delimiter-6" diff --git a/contrib/bmake/unit-tests/moderrs.mk b/contrib/bmake/unit-tests/moderrs.mk index ca5cc082e6b8..c2ee320e2df2 100644 --- a/contrib/bmake/unit-tests/moderrs.mk +++ b/contrib/bmake/unit-tests/moderrs.mk @@ -1,4 +1,4 @@ -# $NetBSD: moderrs.mk,v 1.46 2025/03/30 00:35:52 rillig Exp $ +# $NetBSD: moderrs.mk,v 1.47 2025/06/28 22:39:29 rillig Exp $ # # various modifier error tests @@ -33,11 +33,11 @@ mod-unknown-indirect: @echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after' unclosed-direct: -# expect: make: Unclosed expression, expecting '}' for modifier "S,V,v," +# expect: make: Unclosed expression, expecting "}" for modifier "S,V,v," @echo VAR:S,V,v,=${VAR:S,V,v, unclosed-indirect: -# expect: make: Unclosed expression after indirect modifier, expecting '}' +# expect: make: Unclosed expression after indirect modifier, expecting "}" @echo VAR:${MOD_TERM},=${VAR:${MOD_S} unfinished-indirect: @@ -60,7 +60,7 @@ unfinished-loop-3: # This is also contrary to the SysV modifier, where only the actually # used delimiter (either braces or parentheses) must be balanced. loop-close-1: -# expect: make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@" +# expect: make: Unclosed expression, expecting "}" for modifier "@var@${var}}...@" @echo ${UNDEF:U1 2 3:@var@${var}}...@ loop-close-2: @echo ${UNDEF:U1 2 3:@var@${var}}...@} @@ -107,7 +107,7 @@ exclam-2: @echo ${!:L:!=exclam} mod-subst-delimiter-1: -# expect: make: Missing delimiter for modifier ':S' +# expect: make: Missing delimiter for modifier ":S" @echo 1: ${VAR:S mod-subst-delimiter-2: # expect: make: Unfinished modifier after "", expecting "," @@ -122,13 +122,13 @@ mod-subst-delimiter-5: # expect: make: Unfinished modifier after "to", expecting "," @echo 5: ${VAR:S,from,to mod-subst-delimiter-6: -# expect: make: Unclosed expression, expecting '}' for modifier "S,from,to," +# expect: make: Unclosed expression, expecting "}" for modifier "S,from,to," @echo 6: ${VAR:S,from,to, mod-subst-delimiter-7: @echo 7: ${VAR:S,from,to,} mod-regex-delimiter-1: -# expect: make: Missing delimiter for modifier ':C' +# expect: make: Missing delimiter for modifier ":C" @echo 1: ${VAR:C mod-regex-delimiter-2: # expect: make: Unfinished modifier after "", expecting "," @@ -143,7 +143,7 @@ mod-regex-delimiter-5: # expect: make: Unfinished modifier after "to", expecting "," @echo 5: ${VAR:C,from,to mod-regex-delimiter-6: -# expect: make: Unclosed expression, expecting '}' for modifier "C,from,to," +# expect: make: Unclosed expression, expecting "}" for modifier "C,from,to," @echo 6: ${VAR:C,from,to, mod-regex-delimiter-7: @echo 7: ${VAR:C,from,to,} diff --git a/contrib/bmake/unit-tests/opt-debug-file.exp b/contrib/bmake/unit-tests/opt-debug-file.exp index 1059351188e4..4a497f3011d9 100644 --- a/contrib/bmake/unit-tests/opt-debug-file.exp +++ b/contrib/bmake/unit-tests/opt-debug-file.exp @@ -1,6 +1,6 @@ -make: opt-debug-file.mk:44: This goes to stderr only, once. -make: opt-debug-file.mk:47: This goes to stderr only, once. -make: opt-debug-file.mk:50: This goes to stderr, and in addition to the debug log. +make: opt-debug-file.mk:54: This goes to stderr only, once. +make: opt-debug-file.mk:57: This goes to stderr only, once. +make: opt-debug-file.mk:60: This goes to stderr, and in addition to the debug log. CondParser_Eval: ${:!cat opt-debug-file.debuglog!:Maddition:[#]} != 1 Comparing 1.000000 != 1.000000 make: Unterminated quoted string [make 'This goes to stdout only, once.] diff --git a/contrib/bmake/unit-tests/opt-debug-file.mk b/contrib/bmake/unit-tests/opt-debug-file.mk index 33a35e0a458a..d107f177dae3 100644 --- a/contrib/bmake/unit-tests/opt-debug-file.mk +++ b/contrib/bmake/unit-tests/opt-debug-file.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-file.mk,v 1.11 2024/06/30 15:21:24 rillig Exp $ +# $NetBSD: opt-debug-file.mk,v 1.12 2025/07/06 08:48:34 rillig Exp $ # # Tests for the -dF command line option, which redirects the debug log # to a file instead of writing it to stderr. @@ -27,7 +27,9 @@ DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!} .endif # To get the unexpanded text that was actually written to the debug log -# file, the content of that log file must not be stored in a variable. +# file, the content of that log file must not be stored in a variable +# directly. Instead, it can be processed in a single expression by a chain +# of modifiers. # # XXX: In the :M modifier, a dollar is escaped using '$$', not '\$'. This # escaping scheme unnecessarily differs from all other modifiers. @@ -35,6 +37,14 @@ DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!} . error .endif +# To get the unexpanded text that was actually written to the debug log +# file, the content of that log file must not be stored in a variable +# directly. Instead, each dollar sign must be escaped first. +DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!:S,\$,\$\$,g} +.if ${DEBUG_OUTPUT:M*Uexpanded*} != "\${:Uexpanded}" +. error +.endif + .MAKEFLAGS: -d0 diff --git a/contrib/bmake/unit-tests/opt-debug-lint.exp b/contrib/bmake/unit-tests/opt-debug-lint.exp index 8e7339fcd2e9..7173ec476ec5 100644 --- a/contrib/bmake/unit-tests/opt-debug-lint.exp +++ b/contrib/bmake/unit-tests/opt-debug-lint.exp @@ -1,8 +1,8 @@ make: opt-debug-lint.mk:20: Variable "X" is undefined make: opt-debug-lint.mk:43: Variable "UNDEF" is undefined -make: opt-debug-lint.mk:65: Missing delimiter ':' after modifier "L" +make: opt-debug-lint.mk:65: Missing delimiter ":" after modifier "L" while evaluating variable "value" with value "value" -make: opt-debug-lint.mk:65: Missing delimiter ':' after modifier "P" +make: opt-debug-lint.mk:65: Missing delimiter ":" after modifier "P" while evaluating variable "value" with value "value" make: opt-debug-lint.mk:74: Unknown modifier ":${" while evaluating variable "value" with value "" diff --git a/contrib/bmake/unit-tests/opt-debug-lint.mk b/contrib/bmake/unit-tests/opt-debug-lint.mk index 59cd36fb05e9..2f73c9bf645c 100644 --- a/contrib/bmake/unit-tests/opt-debug-lint.mk +++ b/contrib/bmake/unit-tests/opt-debug-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-lint.mk,v 1.24 2025/04/04 18:57:01 rillig Exp $ +# $NetBSD: opt-debug-lint.mk,v 1.25 2025/06/28 22:39:29 rillig Exp $ # # Tests for the -dL command line option, which runs additional checks # to catch common mistakes, such as unclosed expressions. @@ -60,8 +60,8 @@ ${UNDEF}: ${UNDEF} # Since 2020-10-03, in lint mode the variable modifier must be separated # by colons. See varparse-mod.mk. -# expect+2: Missing delimiter ':' after modifier "L" -# expect+1: Missing delimiter ':' after modifier "P" +# expect+2: Missing delimiter ":" after modifier "L" +# expect+1: Missing delimiter ":" after modifier "P" .if ${value:LPL} != "value" . error .endif diff --git a/contrib/bmake/unit-tests/opt-jobs-internal.exp b/contrib/bmake/unit-tests/opt-jobs-internal.exp index e3e8ee498224..61c96256a2e4 100644 --- a/contrib/bmake/unit-tests/opt-jobs-internal.exp +++ b/contrib/bmake/unit-tests/opt-jobs-internal.exp @@ -1,25 +1,13 @@ direct: mode=parallel make: error: invalid internal option "-J garbage" in "<curdir>" -make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode. - To run the target even in -n mode, add the .MAKE pseudo-source to the target. - To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.) - To make the sub-make run in compat mode, add -B to its invocation. - To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands. +make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page in make[2] in directory "<curdir>" direct-open: mode=compat -make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode. - To run the target even in -n mode, add the .MAKE pseudo-source to the target. - To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.) - To make the sub-make run in compat mode, add -B to its invocation. - To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands. +make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page in make[2] in directory "<curdir>" indirect-open: mode=compat indirect-expr: mode=parallel -make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode. - To run the target even in -n mode, add the .MAKE pseudo-source to the target. - To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.) - To make the sub-make run in compat mode, add -B to its invocation. - To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands. +make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page in make[2] in directory "<curdir>" indirect-comment: mode=compat indirect-silent-comment: mode=parallel diff --git a/contrib/bmake/unit-tests/parse.exp b/contrib/bmake/unit-tests/parse.exp index 86d12effb5c7..4f97a9350550 100644 --- a/contrib/bmake/unit-tests/parse.exp +++ b/contrib/bmake/unit-tests/parse.exp @@ -1,6 +1,6 @@ -make: parse.mk:7: Invalid line '<<<<<< old' -make: parse.mk:14: Invalid line '>>>>>> new' -make: parse.mk:25: Invalid line 'one-target ${:U }', expanded to 'one-target ' +make: parse.mk:7: Invalid line "<<<<<< old" +make: parse.mk:14: Invalid line ">>>>>> new" +make: parse.mk:25: Invalid line "one-target ${:U }", expanded to "one-target " make: Fatal errors encountered -- cannot continue make: stopped making "Try_to_crash_FreeBSD.xxxxxxxxxxxxxxxxxx" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/parse.mk b/contrib/bmake/unit-tests/parse.mk index 80a51f2de11e..fb959a4a5e1b 100644 --- a/contrib/bmake/unit-tests/parse.mk +++ b/contrib/bmake/unit-tests/parse.mk @@ -1,16 +1,16 @@ -# $NetBSD: parse.mk,v 1.7 2023/08/19 11:09:02 rillig Exp $ +# $NetBSD: parse.mk,v 1.8 2025/06/28 22:39:29 rillig Exp $ # # Test those parts of the parsing that do not belong in any of the other # categories. -# expect+1: Invalid line '<<<<<< old' +# expect+1: Invalid line "<<<<<< old" <<<<<< old # No diagnostic since the following line is parsed as a variable assignment, # even though the variable name is empty. See also varname-empty.mk. ====== middle -# expect+1: Invalid line '>>>>>> new' +# expect+1: Invalid line ">>>>>> new" >>>>>> new @@ -21,7 +21,7 @@ # the expanded line's terminating '\0'. # # https://bugs.freebsd.org/265119 -# expect+1: Invalid line 'one-target ${:U }', expanded to 'one-target ' +# expect+1: Invalid line "one-target ${:U }", expanded to "one-target " one-target ${:U } diff --git a/contrib/bmake/unit-tests/var-op-assign.exp b/contrib/bmake/unit-tests/var-op-assign.exp index 4e287e518eb7..83459de4184d 100644 --- a/contrib/bmake/unit-tests/var-op-assign.exp +++ b/contrib/bmake/unit-tests/var-op-assign.exp @@ -1,5 +1,5 @@ this will be evaluated later -make: var-op-assign.mk:60: Invalid line 'VARIABLE NAME= variable value' +make: var-op-assign.mk:60: Invalid line "VARIABLE NAME= variable value" make: var-op-assign.mk:95: Parsing still continues until here. make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests diff --git a/contrib/bmake/unit-tests/var-op-assign.mk b/contrib/bmake/unit-tests/var-op-assign.mk index a900c28a918d..a218dbfdac0a 100644 --- a/contrib/bmake/unit-tests/var-op-assign.mk +++ b/contrib/bmake/unit-tests/var-op-assign.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-assign.mk,v 1.11 2023/11/19 21:47:52 rillig Exp $ +# $NetBSD: var-op-assign.mk,v 1.12 2025/06/28 22:39:29 rillig Exp $ # # Tests for the = variable assignment operator, which overwrites an existing # variable or creates it. @@ -56,7 +56,7 @@ VAR= ${:! echo 'this will be evaluated later' 1>&2 !} # In a variable assignment, the variable name must consist of a single word. # The following line therefore generates a parse error. -# expect+1: Invalid line 'VARIABLE NAME= variable value' +# expect+1: Invalid line "VARIABLE NAME= variable value" VARIABLE NAME= variable value # But if the whitespace appears inside parentheses or braces, everything is diff --git a/contrib/bmake/unit-tests/var-op-expand.exp b/contrib/bmake/unit-tests/var-op-expand.exp index 105d2f50acc8..5e2c3d1936d7 100644 --- a/contrib/bmake/unit-tests/var-op-expand.exp +++ b/contrib/bmake/unit-tests/var-op-expand.exp @@ -1,22 +1,20 @@ make: var-op-expand.mk:274: Unknown modifier ":s,value,replaced," while evaluating variable "later" with value "" while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}" -make: var-op-expand.mk:278: warning: XXX Neither branch should be taken. -make: var-op-expand.mk:283: Unknown modifier ":s,value,replaced," +make: var-op-expand.mk:282: Unknown modifier ":s,value,replaced," while evaluating variable "later" with value "lowercase-value" while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}" -make: var-op-expand.mk:285: warning: XXX Neither branch should be taken. -make: var-op-expand.mk:297: Bad condition +make: var-op-expand.mk:295: Bad condition while evaluating condition " < 0 " -make: var-op-expand.mk:297: Unknown modifier ":Z1" +make: var-op-expand.mk:295: Unknown modifier ":Z1" while parsing "${:Z1}:${:Z2}}" while evaluating then-branch of condition " < 0 " -make: var-op-expand.mk:297: Unknown modifier ":Z2" +make: var-op-expand.mk:295: Unknown modifier ":Z2" while parsing "${:Z2}}" while evaluating else-branch of condition " < 0 " -make: var-op-expand.mk:297: Unknown modifier ":Z1" +make: var-op-expand.mk:295: Unknown modifier ":Z1" while evaluating "${:Z1}:${:Z2}}" with value "" -make: var-op-expand.mk:297: Unknown modifier ":Z2" +make: var-op-expand.mk:295: Unknown modifier ":Z2" while evaluating "${:Z2}}" with value "" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/contrib/bmake/unit-tests/var-op-expand.mk b/contrib/bmake/unit-tests/var-op-expand.mk index 6a49648f0618..fb9e1713438b 100644 --- a/contrib/bmake/unit-tests/var-op-expand.mk +++ b/contrib/bmake/unit-tests/var-op-expand.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-expand.mk,v 1.24 2025/04/30 06:01:07 rillig Exp $ +# $NetBSD: var-op-expand.mk,v 1.25 2025/06/29 11:27:21 rillig Exp $ # # Tests for the := variable assignment operator, which expands its # right-hand side. @@ -274,15 +274,13 @@ indirect:= ${INDIRECT:tl} .if ${indirect} != " ok " . error .else -# expect+1: warning: XXX Neither branch should be taken. -. warning XXX Neither branch should be taken. +. error .endif LATER= uppercase-value later= lowercase-value # expect+1: Unknown modifier ":s,value,replaced," .if ${indirect} != "uppercase-replaced ok uppercase-sysv" -# expect+1: warning: XXX Neither branch should be taken. -. warning XXX Neither branch should be taken. +. error .else . error .endif diff --git a/contrib/bmake/unit-tests/varmisc.exp b/contrib/bmake/unit-tests/varmisc.exp index 509dbcc5e689..44b3c8e759cb 100644 --- a/contrib/bmake/unit-tests/varmisc.exp +++ b/contrib/bmake/unit-tests/varmisc.exp @@ -57,7 +57,7 @@ make: Unclosed variable "PATTERN" while evaluating variable "UNCLOSED" with value "" in command "@echo ${UNCLOSED:M${PATTERN" in target "varerror-unclosed-5" -make: Unclosed expression, expecting '}' for modifier "M${PATTERN" +make: Unclosed expression, expecting "}" for modifier "M${PATTERN" while evaluating variable "UNCLOSED" with value "" in command "@echo ${UNCLOSED:M${PATTERN" in target "varerror-unclosed-5" diff --git a/contrib/bmake/unit-tests/varmisc.mk b/contrib/bmake/unit-tests/varmisc.mk index b067742e9ac4..e36396633dc2 100644 --- a/contrib/bmake/unit-tests/varmisc.mk +++ b/contrib/bmake/unit-tests/varmisc.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig Exp $ +# $NetBSD: varmisc.mk,v 1.38 2025/06/28 22:39:29 rillig Exp $ # # Miscellaneous variable tests. @@ -200,7 +200,7 @@ varerror-unclosed-4: # expect: make: Unclosed variable "UNCLOSED" @echo ${UNCLOSED varerror-unclosed-5: -# expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN" +# expect: make: Unclosed expression, expecting "}" for modifier "M${PATTERN" @echo ${UNCLOSED:M${PATTERN varerror-unclosed-6: # expect: make: Unclosed variable "param" diff --git a/contrib/bmake/unit-tests/varmod-edge.exp b/contrib/bmake/unit-tests/varmod-edge.exp index 2b41623bb66c..b80380fb702c 100644 --- a/contrib/bmake/unit-tests/varmod-edge.exp +++ b/contrib/bmake/unit-tests/varmod-edge.exp @@ -1,8 +1,8 @@ -make: varmod-edge.mk:60: Unclosed expression, expecting '}' for modifier "U*)" +make: varmod-edge.mk:60: Unclosed expression, expecting "}" for modifier "U*)" while evaluating "${:U*)" with value "*)" while evaluating variable "INP" with value "(parentheses)" while evaluating variable "MOD" with value "${INP:M${:U*)}}" -make: varmod-edge.mk:88: Unfinished character list in pattern '[[' of modifier ':M' +make: varmod-edge.mk:88: Unfinished character list in pattern "[[" of modifier ":M" while evaluating variable "INP" with value "[ [[ [[[" while evaluating variable "MOD" with value "${INP:M${:U[[}}" make: varmod-edge.mk:178: Unfinished modifier after "a\=b}", expecting "=" diff --git a/contrib/bmake/unit-tests/varmod-edge.mk b/contrib/bmake/unit-tests/varmod-edge.mk index 473c7ad171e5..b5f879372afd 100644 --- a/contrib/bmake/unit-tests/varmod-edge.mk +++ b/contrib/bmake/unit-tests/varmod-edge.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-edge.mk,v 1.36 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: varmod-edge.mk,v 1.37 2025/06/28 22:39:29 rillig Exp $ # # Tests for edge cases in variable modifiers. # @@ -56,7 +56,7 @@ EXP= \(\{}\): INP= (parentheses) MOD= ${INP:M${:U*)}} EXP= (parentheses)} -# expect+1: Unclosed expression, expecting '}' for modifier "U*)" +# expect+1: Unclosed expression, expecting "}" for modifier "U*)" .if ${MOD} != ${EXP} . warning expected "${EXP}", got "${MOD}" .endif @@ -84,7 +84,7 @@ EXP= [ INP= [ [[ [[[ MOD= ${INP:M${:U[[}} EXP= [ -# expect+1: Unfinished character list in pattern '[[' of modifier ':M' +# expect+1: Unfinished character list in pattern "[[" of modifier ":M" .if ${MOD} != ${EXP} . warning expected "${EXP}", got "${MOD}" .endif diff --git a/contrib/bmake/unit-tests/varmod-ifelse.exp b/contrib/bmake/unit-tests/varmod-ifelse.exp index 039f0fd0b9a7..bf642c86fc8c 100644 --- a/contrib/bmake/unit-tests/varmod-ifelse.exp +++ b/contrib/bmake/unit-tests/varmod-ifelse.exp @@ -12,26 +12,25 @@ Comparing 1.000000 == 0.000000 make: varmod-ifelse.mk:94: Bad condition while evaluating condition "1 == == 2" Comparing "" != "" -make: varmod-ifelse.mk:98: warning: Oops, the parse error should have been propagated. CondParser_Eval: ${ ${:U\$}{VAR} == value:?ok:bad} != "ok" CondParser_Eval: ${VAR} == value Comparing "value" == "value" Comparing "ok" != "ok" -make: varmod-ifelse.mk:160: no. -make: varmod-ifelse.mk:163: Comparison with '>=' requires both operands 'no' and '10' to be numeric +make: varmod-ifelse.mk:159: no. +make: varmod-ifelse.mk:162: Comparison with ">=" requires both operands "no" and "10" to be numeric while evaluating condition "string == "literal" || no >= 10" -make: varmod-ifelse.mk:163: . -make: varmod-ifelse.mk:170: Bad condition +make: varmod-ifelse.mk:162: . +make: varmod-ifelse.mk:169: Bad condition while evaluating condition "string == "literal" && >= 10" -make: varmod-ifelse.mk:170: . -make: varmod-ifelse.mk:173: Bad condition +make: varmod-ifelse.mk:169: . +make: varmod-ifelse.mk:172: Bad condition while evaluating condition "string == "literal" || >= 10" -make: varmod-ifelse.mk:173: . -make: varmod-ifelse.mk:181: <true> -make: varmod-ifelse.mk:184: <false> -make: varmod-ifelse.mk:188: Bad condition +make: varmod-ifelse.mk:172: . +make: varmod-ifelse.mk:180: <true> +make: varmod-ifelse.mk:183: <false> +make: varmod-ifelse.mk:187: Bad condition while evaluating condition " " -make: varmod-ifelse.mk:188: <> +make: varmod-ifelse.mk:187: <> CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated" CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1" CondParser_Eval: 0 @@ -41,31 +40,31 @@ CondParser_Eval: 1 Comparing "then2" != "then2" CondParser_Eval: ${DELAYED} == "one" Comparing "two" == "one" -make: varmod-ifelse.mk:284: no +make: varmod-ifelse.mk:283: no CondParser_Eval: ${DELAYED} == "two" Comparing "two" == "two" -make: varmod-ifelse.mk:286: yes +make: varmod-ifelse.mk:285: yes CondParser_Eval: ${DELAYED} == "one" Comparing "two" == "one" -make: varmod-ifelse.mk:289: no +make: varmod-ifelse.mk:288: no CondParser_Eval: ${DELAYED} == "two" Comparing "two" == "two" -make: varmod-ifelse.mk:292: yes -make: varmod-ifelse.mk:314: Unknown modifier ":X-then" +make: varmod-ifelse.mk:291: yes +make: varmod-ifelse.mk:313: Unknown modifier ":X-then" while evaluating "${:X-then}:${:X-else}}" with value "" while evaluating then-branch of condition "1" -make: varmod-ifelse.mk:314: Unknown modifier ":X-else" +make: varmod-ifelse.mk:313: Unknown modifier ":X-else" while parsing "${:X-else}}" while evaluating else-branch of condition "1" -make: varmod-ifelse.mk:322: Bad condition +make: varmod-ifelse.mk:321: Bad condition while evaluating condition " < 0 " -make: varmod-ifelse.mk:322: Unknown modifier ":Z1" +make: varmod-ifelse.mk:321: Unknown modifier ":Z1" while parsing "${:Z1}:${:Z2}}>" while evaluating then-branch of condition " < 0 " -make: varmod-ifelse.mk:322: Unknown modifier ":Z2" +make: varmod-ifelse.mk:321: Unknown modifier ":Z2" while parsing "${:Z2}}>" while evaluating else-branch of condition " < 0 " -make: varmod-ifelse.mk:322: <> +make: varmod-ifelse.mk:321: <> make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/varmod-ifelse.mk b/contrib/bmake/unit-tests/varmod-ifelse.mk index 986524330a97..fcd483d0c497 100644 --- a/contrib/bmake/unit-tests/varmod-ifelse.mk +++ b/contrib/bmake/unit-tests/varmod-ifelse.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-ifelse.mk,v 1.39 2025/04/30 06:01:07 rillig Exp $ +# $NetBSD: varmod-ifelse.mk,v 1.41 2025/06/29 11:27:21 rillig Exp $ # # Tests for the ${cond:?then:else} variable modifier, which evaluates either # the then-expression or the else-expression, depending on the condition. @@ -73,9 +73,9 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} . error .endif -# If the "Bad conditional expression" appears in a quoted string literal, the +# If the "Bad condition" appears in a quoted string literal, the # error message "Malformed conditional" is not printed, leaving only the "Bad -# conditional expression". +# condition". # # XXX: The left-hand side is enclosed in quotes. This results in Var_Parse # being called without VARE_EVAL_DEFINED. When ApplyModifier_IfElse @@ -94,8 +94,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} .if "${1 == == 2:?yes:no}" != "" . error .else -# expect+1: warning: Oops, the parse error should have been propagated. -. warning Oops, the parse error should have been propagated. +. error .endif .MAKEFLAGS: -d0 @@ -158,7 +157,7 @@ STRING= string NUMBER= no # not really a number # expect+1: no. .info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}. -# expect+2: Comparison with '>=' requires both operands 'no' and '10' to be numeric +# expect+2: Comparison with ">=" requires both operands "no" and "10" to be numeric # expect+1: . .info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}. diff --git a/contrib/bmake/unit-tests/varmod-match-escape.exp b/contrib/bmake/unit-tests/varmod-match-escape.exp index 25d78226345c..42e470310d4c 100755 --- a/contrib/bmake/unit-tests/varmod-match-escape.exp +++ b/contrib/bmake/unit-tests/varmod-match-escape.exp @@ -33,14 +33,18 @@ Comparing ":" != "::" make: varmod-match-escape.mk:43: warning: XXX: Oops Global: .MAKEFLAGS = -r -k -d cv -d Global: .MAKEFLAGS = -r -k -d cv -d 0 -make: varmod-match-escape.mk:69: Dollar followed by nothing +make: varmod-match-escape.mk:63: Unfinished backslash at the end in pattern "\" of modifier ":M" while evaluating "${:U\$:M\$} != """ with value "$" -make: varmod-match-escape.mk:110: Unfinished character list in pattern '[A-]' of modifier ':M' +make: varmod-match-escape.mk:71: Dollar followed by nothing + while evaluating "${:U\$:M\$} != """ with value "$" +make: varmod-match-escape.mk:71: Unfinished backslash at the end in pattern "\" of modifier ":M" + while evaluating "${:U\$:M\$} != """ with value "$" +make: varmod-match-escape.mk:112: Unfinished character list in pattern "[A-]" of modifier ":M" while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]" - in .for loop from varmod-match-escape.mk:107 with pattern = [A-] -make: varmod-match-escape.mk:110: Unfinished character list in pattern '[^A-]' of modifier ':M' + in .for loop from varmod-match-escape.mk:109 with pattern = [A-] +make: varmod-match-escape.mk:112: Unfinished character list in pattern "[^A-]" of modifier ":M" while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]" - in .for loop from varmod-match-escape.mk:107 with pattern = [^A-] + in .for loop from varmod-match-escape.mk:109 with pattern = [^A-] make: Fatal errors encountered -- cannot continue make: stopped making "all" in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/varmod-match-escape.mk b/contrib/bmake/unit-tests/varmod-match-escape.mk index d9e2009f9b60..5c492d9d1f72 100755 --- a/contrib/bmake/unit-tests/varmod-match-escape.mk +++ b/contrib/bmake/unit-tests/varmod-match-escape.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-match-escape.mk,v 1.18 2024/08/29 20:20:36 rillig Exp $ +# $NetBSD: varmod-match-escape.mk,v 1.20 2025/06/28 22:39:29 rillig Exp $ # # As of 2020-08-01, the :M and :N modifiers interpret backslashes differently, # depending on whether there was an expression somewhere before the @@ -59,13 +59,15 @@ VALUES= : :: :\: # '\{' nor '\}'. But the text is expanded, and a lonely '$' at the end # is silently discarded. The resulting expanded pattern is thus '\', that # is a single backslash. +# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M" .if ${:U\$:M\$} != "" . error .endif # In lint mode, the case of a lonely '$' is covered with an error message. .MAKEFLAGS: -dL -# expect+1: Dollar followed by nothing +# expect+2: Dollar followed by nothing +# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M" .if ${:U\$:M\$} != "" . error .endif @@ -105,8 +107,8 @@ EXP.[^A-]]= a EXP.[^A-]]]= a] .for pattern in [A-] [A-]] [A-]]] [^A-] [^A-]] [^A-]]] -# expect+2: Unfinished character list in pattern '[A-]' of modifier ':M' -# expect+1: Unfinished character list in pattern '[^A-]' of modifier ':M' +# expect+2: Unfinished character list in pattern "[A-]" of modifier ":M" +# expect+1: Unfinished character list in pattern "[^A-]" of modifier ":M" . if ${WORDS:M${pattern}} != ${EXP.${pattern}} . warning ${pattern}: ${WORDS:M${pattern}} != ${EXP.${pattern}} . endif diff --git a/contrib/bmake/unit-tests/varmod-match.exp b/contrib/bmake/unit-tests/varmod-match.exp index 14eb7862d815..7bccc4283e32 100644 --- a/contrib/bmake/unit-tests/varmod-match.exp +++ b/contrib/bmake/unit-tests/varmod-match.exp @@ -1,22 +1,22 @@ -make: varmod-match.mk:289: Unfinished character list in pattern 'a[' of modifier ':M' +make: varmod-match.mk:293: Unfinished character list in pattern "a[" of modifier ":M" while evaluating variable "WORDS" with value "a a[" -make: varmod-match.mk:297: Unfinished character list in pattern 'a[^' of modifier ':M' +make: varmod-match.mk:301: Unfinished character list in pattern "a[^" of modifier ":M" while evaluating variable "WORDS" with value "a a[ aX" -make: varmod-match.mk:305: Unfinished character list in pattern '[-x1-3' of modifier ':M' +make: varmod-match.mk:309: Unfinished character list in pattern "[-x1-3" of modifier ":M" while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3" -make: varmod-match.mk:313: Unfinished character list in pattern '*[-x1-3' of modifier ':M' +make: varmod-match.mk:317: Unfinished character list in pattern "*[-x1-3" of modifier ":M" while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3" -make: varmod-match.mk:322: Unfinished character list in pattern '[^-x1-3' of modifier ':M' +make: varmod-match.mk:326: Unfinished character list in pattern "[^-x1-3" of modifier ":M" while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3" -make: varmod-match.mk:336: Unfinished character list in pattern '?[\' of modifier ':M' +make: varmod-match.mk:340: Unfinished character list in pattern "?[\" of modifier ":M" while evaluating variable "WORDS" with value "\\ \a x\" -make: varmod-match.mk:344: Unfinished character range in pattern '[x-' of modifier ':M' +make: varmod-match.mk:348: Unfinished character range in pattern "[x-" of modifier ":M" while evaluating variable "WORDS" with value "[x- x x- y" -make: varmod-match.mk:356: Unfinished character range in pattern '[^x-' of modifier ':M' +make: varmod-match.mk:360: Unfinished character range in pattern "[^x-" of modifier ":M" while evaluating variable "WORDS" with value "[x- x x- y yyyyy" -make: varmod-match.mk:363: Unfinished character list in pattern '[' of modifier ':M' +make: varmod-match.mk:367: Unfinished character list in pattern "[" of modifier ":M" while evaluating variable " : :: " with value " : :: " -make: varmod-match.mk:363: Unknown modifier ":]" +make: varmod-match.mk:367: Unknown modifier ":]" while evaluating variable " : :: " with value "" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/contrib/bmake/unit-tests/varmod-match.mk b/contrib/bmake/unit-tests/varmod-match.mk index 99184989fb83..5894196c9cd5 100644 --- a/contrib/bmake/unit-tests/varmod-match.mk +++ b/contrib/bmake/unit-tests/varmod-match.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-match.mk,v 1.30 2025/03/29 19:08:52 rillig Exp $ +# $NetBSD: varmod-match.mk,v 1.32 2025/06/29 09:40:13 rillig Exp $ # # Tests for the ':M' modifier, which keeps only those words that match the # given pattern. @@ -13,8 +13,12 @@ # 6. Error handling # 7. Historical bugs # -# See ApplyModifier_Match, ParseModifier_Match, ModifyWord_Match and -# Str_Match. +# See also: +# char-005c-reverse-solidus.mk +# ApplyModifier_Match +# ParseModifier_Match +# ModifyWord_Match +# Str_Match # 1. Pattern characters '*', '?' and '\' @@ -285,7 +289,7 @@ ${:U*}= asterisk # [ Incomplete empty character list, never matches. WORDS= a a[ -# expect+1: Unfinished character list in pattern 'a[' of modifier ':M' +# expect+1: Unfinished character list in pattern "a[" of modifier ":M" .if ${WORDS:Ma[} != "" . error .endif @@ -293,7 +297,7 @@ WORDS= a a[ # [^ Incomplete negated empty character list, matches any single # character. WORDS= a a[ aX -# expect+1: Unfinished character list in pattern 'a[^' of modifier ':M' +# expect+1: Unfinished character list in pattern "a[^" of modifier ":M" .if ${WORDS:Ma[^} != "a[ aX" . error .endif @@ -301,7 +305,7 @@ WORDS= a a[ aX # [-x1-3 Incomplete character list, matches those elements that can be # parsed without lookahead. WORDS= - + x xx 0 1 2 3 4 [x1-3 -# expect+1: Unfinished character list in pattern '[-x1-3' of modifier ':M' +# expect+1: Unfinished character list in pattern "[-x1-3" of modifier ":M" .if ${WORDS:M[-x1-3} != "- x 1 2 3" . error .endif @@ -309,7 +313,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3 # *[-x1-3 Incomplete character list after a wildcard, matches those # words that end with one of the characters from the list. WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3 -# expect+1: Unfinished character list in pattern '*[-x1-3' of modifier ':M' +# expect+1: Unfinished character list in pattern "*[-x1-3" of modifier ":M" .if ${WORDS:M*[-x1-3} != "- x xx 1 2 3 01 11 001 011 101 111 [x1-3" . warning ${WORDS:M*[-x1-3} .endif @@ -318,7 +322,7 @@ WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3 # Incomplete negated character list, matches any character # except those elements that can be parsed without lookahead. WORDS= - + x xx 0 1 2 3 4 [x1-3 -# expect+1: Unfinished character list in pattern '[^-x1-3' of modifier ':M' +# expect+1: Unfinished character list in pattern "[^-x1-3" of modifier ":M" .if ${WORDS:M[^-x1-3} != "+ 0 4" . error .endif @@ -332,7 +336,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3 # '\', as there is no following space that could be escaped. WORDS= \\ \a ${:Ux\\} PATTERN= ${:U?[\\} -# expect+1: Unfinished character list in pattern '?[\' of modifier ':M' +# expect+1: Unfinished character list in pattern "?[\" of modifier ":M" .if ${WORDS:M${PATTERN}} != "\\\\ x\\" . error .endif @@ -340,7 +344,7 @@ PATTERN= ${:U?[\\} # [x- Incomplete character list containing an incomplete character # range, matches only the 'x'. WORDS= [x- x x- y -# expect+1: Unfinished character range in pattern '[x-' of modifier ':M' +# expect+1: Unfinished character range in pattern "[x-" of modifier ":M" .if ${WORDS:M[x-} != "x" . error .endif @@ -352,13 +356,13 @@ WORDS= [x- x x- y # XXX: Even matches strings that are longer than a single # character. WORDS= [x- x x- y yyyyy -# expect+1: Unfinished character range in pattern '[^x-' of modifier ':M' +# expect+1: Unfinished character range in pattern "[^x-" of modifier ":M" .if ${WORDS:M[^x-} != "[x- y yyyyy" . error .endif # [:] matches never since the ':' starts the next modifier -# expect+2: Unfinished character list in pattern '[' of modifier ':M' +# expect+2: Unfinished character list in pattern "[" of modifier ":M" # expect+1: Unknown modifier ":]" .if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":" . error diff --git a/contrib/bmake/unit-tests/varmod-mtime.exp b/contrib/bmake/unit-tests/varmod-mtime.exp index 9960dd877768..53b86b99b867 100644 --- a/contrib/bmake/unit-tests/varmod-mtime.exp +++ b/contrib/bmake/unit-tests/varmod-mtime.exp @@ -1,12 +1,12 @@ -make: varmod-mtime.mk:46: Invalid argument '123x' for modifier ':mtime' +make: varmod-mtime.mk:46: Invalid argument "123x" for modifier ":mtime" while evaluating variable "no/such/file" with value "no/such/file" make: varmod-mtime.mk:68: Cannot determine mtime for "no/such/file1": <ENOENT> while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2" make: varmod-mtime.mk:68: Cannot determine mtime for "no/such/file2": <ENOENT> while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2" -make: varmod-mtime.mk:78: Invalid argument 'errorhandler-no' for modifier ':mtime' +make: varmod-mtime.mk:78: Invalid argument "errorhandler-no" for modifier ":mtime" while evaluating variable "MAKEFILE" with value "varmod-mtime.mk" -make: varmod-mtime.mk:86: Invalid argument 'warn' for modifier ':mtime' +make: varmod-mtime.mk:86: Invalid argument "warn" for modifier ":mtime" while evaluating variable "MAKEFILE" with value "varmod-mtime.mk" make: varmod-mtime.mk:110: Unknown modifier ":mtim" while evaluating variable "anything" with value "anything" diff --git a/contrib/bmake/unit-tests/varmod-mtime.mk b/contrib/bmake/unit-tests/varmod-mtime.mk index ec33cd698b41..aed7024efd6b 100644 --- a/contrib/bmake/unit-tests/varmod-mtime.mk +++ b/contrib/bmake/unit-tests/varmod-mtime.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-mtime.mk,v 1.16 2025/06/12 18:51:05 rillig Exp $ +# $NetBSD: varmod-mtime.mk,v 1.17 2025/06/28 22:39:29 rillig Exp $ # # Tests for the ':mtime' variable modifier, which maps each word of the # expression to that file's modification time. @@ -42,7 +42,7 @@ not_found_mtime:= ${no/such/file:L:mtime} # The fallback timestamp must only be an integer, without trailing characters. -# expect+1: Invalid argument '123x' for modifier ':mtime' +# expect+1: Invalid argument "123x" for modifier ":mtime" .if ${no/such/file:L:mtime=123x} . error .else @@ -74,7 +74,7 @@ _!= rm -f ${COOKIE} # Only the word 'error' is a special argument to the ':mtime' modifier, all # other words result in a parse error. -# expect+1: Invalid argument 'errorhandler-no' for modifier ':mtime' +# expect+1: Invalid argument "errorhandler-no" for modifier ":mtime" .if ${MAKEFILE:mtime=errorhandler-no} > 0 .else . error @@ -82,7 +82,7 @@ _!= rm -f ${COOKIE} # Only the word 'error' can be used as a fallback argument to the modifier. -# expect+1: Invalid argument 'warn' for modifier ':mtime' +# expect+1: Invalid argument "warn" for modifier ":mtime" .if ${MAKEFILE:mtime=warn} > 0 . error .else diff --git a/contrib/bmake/unit-tests/varmod-order.exp b/contrib/bmake/unit-tests/varmod-order.exp index f48256c6ae0e..fd18f0e11ee1 100644 --- a/contrib/bmake/unit-tests/varmod-order.exp +++ b/contrib/bmake/unit-tests/varmod-order.exp @@ -2,11 +2,11 @@ make: varmod-order.mk:14: Unknown modifier ":OX" while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten" make: varmod-order.mk:17: Unknown modifier ":OxXX" while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten" -make: varmod-order.mk:20: Unclosed expression, expecting '}' for modifier "O" +make: varmod-order.mk:20: Unclosed expression, expecting "}" for modifier "O" while evaluating variable "WORDS" with value "eight five four nine one seven six ten three two" -make: varmod-order.mk:22: Unclosed expression, expecting '}' for modifier "On" +make: varmod-order.mk:22: Unclosed expression, expecting "}" for modifier "On" while evaluating variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10" -make: varmod-order.mk:24: Unclosed expression, expecting '}' for modifier "Onr" +make: varmod-order.mk:24: Unclosed expression, expecting "}" for modifier "Onr" while evaluating variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1" make: varmod-order.mk:30: Unknown modifier ":Oxn" while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2" diff --git a/contrib/bmake/unit-tests/varmod-order.mk b/contrib/bmake/unit-tests/varmod-order.mk index c8386ef951dc..f4fa5d10cdf8 100644 --- a/contrib/bmake/unit-tests/varmod-order.mk +++ b/contrib/bmake/unit-tests/varmod-order.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-order.mk,v 1.19 2025/03/29 23:50:07 rillig Exp $ +# $NetBSD: varmod-order.mk,v 1.20 2025/06/28 22:39:29 rillig Exp $ # # Tests for the :O variable modifier and its variants, which either sort the # words of the value or shuffle them. @@ -16,11 +16,11 @@ _:= ${WORDS:OX} # expect+1: Unknown modifier ":OxXX" _:= ${WORDS:OxXX} -# expect+1: Unclosed expression, expecting '}' for modifier "O" +# expect+1: Unclosed expression, expecting "}" for modifier "O" _:= ${WORDS:O -# expect+1: Unclosed expression, expecting '}' for modifier "On" +# expect+1: Unclosed expression, expecting "}" for modifier "On" _:= ${NUMBERS:On -# expect+1: Unclosed expression, expecting '}' for modifier "Onr" +# expect+1: Unclosed expression, expecting "}" for modifier "Onr" _:= ${NUMBERS:Onr # Shuffling numerically doesn't make sense, so don't allow 'x' and 'n' to be diff --git a/contrib/bmake/unit-tests/varmod-range.exp b/contrib/bmake/unit-tests/varmod-range.exp index 768ba9ac2f2d..b98865a4084a 100644 --- a/contrib/bmake/unit-tests/varmod-range.exp +++ b/contrib/bmake/unit-tests/varmod-range.exp @@ -1,6 +1,6 @@ make: varmod-range.mk:43: Variable "" is undefined while evaluating "${:range=5} != """ with value "1 2 3 4 5" -make: varmod-range.mk:66: Invalid number "x}Rest" != "Rest"" for ':range' modifier +make: varmod-range.mk:66: Invalid number "x}Rest" != "Rest"" for modifier ":range" while evaluating "${:U:range=x}Rest" != "Rest"" with value "" make: varmod-range.mk:76: Unknown modifier ":x0" while evaluating "${:U:range=0x0}Rest" != "Rest"" with value "1" diff --git a/contrib/bmake/unit-tests/varmod-range.mk b/contrib/bmake/unit-tests/varmod-range.mk index 7a60bcc23d86..69dcf6ad1a7d 100644 --- a/contrib/bmake/unit-tests/varmod-range.mk +++ b/contrib/bmake/unit-tests/varmod-range.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-range.mk,v 1.18 2025/04/04 18:57:01 rillig Exp $ +# $NetBSD: varmod-range.mk,v 1.19 2025/06/28 22:39:29 rillig Exp $ # # Tests for the :range variable modifier, which generates sequences # of integers from the given range. @@ -62,7 +62,7 @@ # # Since 2020-11-01, the parser issues a more precise "Invalid number" error # instead. -# expect+1: Invalid number "x}Rest" != "Rest"" for ':range' modifier +# expect+1: Invalid number "x}Rest" != "Rest"" for modifier ":range" .if "${:U:range=x}Rest" != "Rest" . error .else diff --git a/contrib/bmake/unit-tests/varmod.exp b/contrib/bmake/unit-tests/varmod.exp index 09c922aa16bd..022181d05cf1 100644 --- a/contrib/bmake/unit-tests/varmod.exp +++ b/contrib/bmake/unit-tests/varmod.exp @@ -1,47 +1,54 @@ make: varmod.mk:111: To escape a dollar, use \$, not $$, at "$$:L} != """ -make: varmod.mk:111: Invalid variable name ':', at "$:L} != """ +make: varmod.mk:111: Invalid variable name ":", at "$:L} != """ make: varmod.mk:117: Dollar followed by nothing while evaluating "${:Uword:@word@${word}$@} != "word"" with value "word" -make: varmod.mk:127: Missing delimiter ':' after modifier "P" +make: varmod.mk:125: Missing delimiter ":" after modifier "P" while evaluating variable "VAR" with value "VAR" -make: varmod.mk:129: Missing argument for ".error" -make: varmod.mk:135: Invalid modifier ":[99333000222000111000]" +make: varmod.mk:134: Invalid modifier ":[99333000222000111000]" while evaluating variable "word" with value "word" -make: varmod.mk:138: Invalid modifier ":[2147483648]" +make: varmod.mk:137: Invalid modifier ":[2147483648]" while evaluating variable "word" with value "word" -make: varmod.mk:144: Invalid number "99333000222000111000}" for ':range' modifier +make: varmod.mk:143: Invalid number "99333000222000111000}" for modifier ":range" while evaluating variable "word" with value "word" -make: varmod.mk:151: Invalid time value "\" +make: varmod.mk:150: Invalid time value "\" while evaluating indirect modifiers "gmtime=\" while evaluating "${:${:Ugmtime=\\}}" with value "" -make: varmod.mk:166: Dollar followed by nothing +make: varmod.mk:165: Dollar followed by nothing while evaluating variable "VAR" with value "value$" -make: varmod.mk:172: Dollar followed by nothing +make: varmod.mk:171: Dollar followed by nothing while evaluating variable "VAR" with value "value$" -make: varmod.mk:172: Dollar followed by nothing +make: varmod.mk:171: Dollar followed by nothing while evaluating variable "VAR" with value "value$ appended$" -make: varmod.mk:182: Dollar followed by nothing +make: varmod.mk:181: Dollar followed by nothing while evaluating variable "word" with value "word" -make: varmod.mk:186: Invalid modifier ":[$]" +make: varmod.mk:185: Invalid modifier ":[$]" while evaluating variable "word" with value "" -make: varmod.mk:203: Dollar followed by nothing +make: varmod.mk:202: Dollar followed by nothing while evaluating variable "VAR" with value "value$ appended$" -make: varmod.mk:203: Invalid variable name '}', at "$} != "set"" +make: varmod.mk:202: Invalid variable name "}", at "$} != "set"" while evaluating variable "VAR" with value "value<space>appended" -make: varmod.mk:207: Invalid variable name '}', at "$} != "fallback"" +make: varmod.mk:206: Invalid variable name "}", at "$} != "fallback"" while evaluating "${:Ufallback$} != "fallback"" with value "" -make: varmod.mk:211: Invalid time value "1000$" +make: varmod.mk:210: Invalid time value "1000$" while evaluating variable "%y" with value "%y" -make: varmod.mk:217: Invalid time value "1000$" +make: varmod.mk:216: Invalid time value "1000$" while evaluating variable "%y" with value "%y" -make: varmod.mk:223: Dollar followed by nothing +make: varmod.mk:222: Dollar followed by nothing while evaluating variable "word" with value "word" -make: varmod.mk:227: Dollar followed by nothing +make: varmod.mk:226: Dollar followed by nothing while evaluating variable "word" with value "word" -make: varmod.mk:231: Invalid argument 'fallback$' for modifier ':mtime' +make: varmod.mk:230: Invalid argument "fallback$" for modifier ":mtime" while evaluating variable "." with value "." -make: varmod.mk:245: Missing delimiter ':' after modifier "L" +make: varmod.mk:244: Missing delimiter ":" after modifier "L" while evaluating variable "VAR" with value "VAR" +make: varmod.mk:256: Invalid time value " : } \ $ ) \) ( " + while evaluating variable "%Y" with value "%Y" +make: varmod.mk:263: Invalid time value " : \) \ $ " + while evaluating variable "%Y" with value "%Y" +make: varmod.mk:268: Invalid time value " : } \ $ ) \) ( " + while evaluating variable "%Y" with value "%Y" +make: varmod.mk:273: Invalid time value " : \) \ $ " + while evaluating variable "%Y" with value "%Y" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/varmod.mk b/contrib/bmake/unit-tests/varmod.mk index cc7b08c447e9..af976f9d0086 100644 --- a/contrib/bmake/unit-tests/varmod.mk +++ b/contrib/bmake/unit-tests/varmod.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod.mk,v 1.26 2025/03/30 01:27:13 rillig Exp $ +# $NetBSD: varmod.mk,v 1.30 2025/06/29 11:27:21 rillig Exp $ # # Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback. # @@ -107,7 +107,7 @@ DOLLAR2= ${:U\$} # Should it? .MAKEFLAGS: -dL # expect+2: To escape a dollar, use \$, not $$, at "$$:L} != """ -# expect+1: Invalid variable name ':', at "$:L} != """ +# expect+1: Invalid variable name ":", at "$:L} != """ .if ${$$:L} != "" . error .endif @@ -118,14 +118,13 @@ DOLLAR2= ${:U\$} . error .endif -# The variable modifier :P does not fall back to the SysV modifier. +# The modifier :P does not fall back to the SysV modifier. # Therefore the modifier :P=RE generates a parse error. -# XXX: The .error should not be reached since the expression is -# malformed, and this error should be propagated up to Cond_EvalLine. VAR= STOP -# expect+1: Missing delimiter ':' after modifier "P" +# expect+1: Missing delimiter ":" after modifier "P" .if ${VAR:P=RE} != "STORE" -# expect+1: Missing argument for ".error" +. error +.else . error .endif @@ -140,7 +139,7 @@ VAR= STOP # Test the range generation modifier ':range=n' with a very large number that # is larger than SIZE_MAX for any supported platform. -# expect+1: Invalid number "99333000222000111000}" for ':range' modifier +# expect+1: Invalid number "99333000222000111000}" for modifier ":range" .if ${word:L:range=99333000222000111000} .endif @@ -199,11 +198,11 @@ VAR_DOLLAR= VAR$$ . error .endif # expect+2: Dollar followed by nothing -# expect+1: Invalid variable name '}', at "$} != "set"" +# expect+1: Invalid variable name "}", at "$} != "set"" .if ${VAR:Dset$} != "set" . error .endif -# expect+1: Invalid variable name '}', at "$} != "fallback"" +# expect+1: Invalid variable name "}", at "$} != "fallback"" .if ${:Ufallback$} != "fallback" . error .endif @@ -227,7 +226,7 @@ VAR_DOLLAR= VAR$$ .if ${word:L:NX*$} != "word" . error .endif -# expect+1: Invalid argument 'fallback$' for modifier ':mtime' +# expect+1: Invalid argument "fallback$" for modifier ":mtime" .if ${.:L:mtime=fallback$} . error .else @@ -241,10 +240,36 @@ VAR_DOLLAR= VAR$$ .endif .undef VAR -# expect+1: Missing delimiter ':' after modifier "L" +# expect+1: Missing delimiter ":" after modifier "L" .if ${VAR:LAR=ALUE} != "VALUE" . error .endif .if ${VAR:L:AR=ALUE} != "VALUE" . error .endif + + +# When an expression has the usual form ${...} with braces, +# in the part of a modifier, ":}\$" can be escaped using a backslash. +# All other characters are passed through unmodified. +# expect+1: Invalid time value " : } \ $ ) \) ( " +.if ${%Y:L:localtime= \: \} \\ \$ ) \) ( :M*} != ": } \\ \$ ) \\) (" +. error +.endif +# When an expression has the unusual form $(...) with parentheses, +# in the part of a modifier, ":)\$" can be escaped using a backslash. +# All other characters are passed through unmodified. +# expect+1: Invalid time value " : \) \ $ " +.if ${%Y:L:localtime= \: \) \\ \$ } \} { :M*} != ": ) \\ \$ } \\} {" +. error +.endif +# Same when the modifier is the last modifier in an expression. +# expect+1: Invalid time value " : } \ $ ) \) ( " +.if ${%Y:L:localtime= \: \} \\ \$ ) \) ( } != " : } \\ \$ ) \\) ( " +. error +.endif +# Same when the modifier is the last modifier in an expression. +# expect+1: Invalid time value " : \) \ $ " +.if ${%Y:L:localtime= \: \) \\ \$ } \} { } != " : ) \\ \$ } \\} { " +. error +.endif diff --git a/contrib/bmake/unit-tests/varname-circumflex.exp b/contrib/bmake/unit-tests/varname-circumflex.exp new file mode 100644 index 000000000000..184b021fd5e5 --- /dev/null +++ b/contrib/bmake/unit-tests/varname-circumflex.exp @@ -0,0 +1,9 @@ +no_prerequisites: +prerequisite: file1.o +unique: file1.o file2.o file3.o +duplicate: file1.o file2.o file3.o +dir_part: /usr/include /usr/include . +file_part: stdio.h unistd.h foo.h +implicit.tout: implicit.tin +wait: file1.o .WAIT_1 file2.o +exit status 0 diff --git a/contrib/bmake/unit-tests/varname-circumflex.mk b/contrib/bmake/unit-tests/varname-circumflex.mk new file mode 100644 index 000000000000..270f7123781b --- /dev/null +++ b/contrib/bmake/unit-tests/varname-circumflex.mk @@ -0,0 +1,47 @@ +# $NetBSD: varname-circumflex.mk,v 1.1 2025/06/27 20:20:56 rillig Exp $ +# +# Tests for the target-local variable "^", which is required by POSIX 2024 +# and provided by GNU make. + +# TODO: Support $^. + +all: .PHONY +all: no_prerequisites prerequisite +all: unique duplicate +all: dir_part file_part +all: implicit.tout +all: wait + +.if defined(^) +. error +.endif + +no_prerequisites: + @echo $@: $^ + +prerequisite: file1.o + @echo $@: $^ + +unique: file1.o file2.o file3.o + @echo $@: $^ + +duplicate: file1.o file2.o file3.o file3.o + @echo $@: $^ + +dir_part: /usr/include/stdio.h /usr/include/unistd.h foo.h + @echo $@: $(^D) + +file_part: /usr/include/stdio.h /usr/include/unistd.h foo.h + @echo $@: ${^F} + +wait: file1.o .WAIT file2.o + @echo $@: $^ + +.SUFFIXES: +.SUFFIXES: .tin .tout + +.tin.tout: + @echo $@: $^ + +file1.o file2.o file3.o: +/usr/include/stdio.h /usr/include/unistd.h foo.h implicit.tin: diff --git a/contrib/bmake/unit-tests/varname-vpath.exp b/contrib/bmake/unit-tests/varname-vpath.exp index bf7a3036e99d..a750957b92ac 100644 --- a/contrib/bmake/unit-tests/varname-vpath.exp +++ b/contrib/bmake/unit-tests/varname-vpath.exp @@ -1,12 +1,12 @@ CondParser_Eval: !defined(TEST_MAIN) CondParser_Eval: exists(file-in-subdirectory) -exists(file-in-subdirectory) result is "" +"file-in-subdirectory" does not exist CondParser_Eval: exists(file2-in-subdirectory) -exists(file2-in-subdirectory) result is "" +"file2-in-subdirectory" does not exist CondParser_Eval: exists(file-in-subdirectory) -exists(file-in-subdirectory) result is "varname-vpath.dir/file-in-subdirectory" +"file-in-subdirectory" exists in "varname-vpath.dir/file-in-subdirectory" : yes 1 CondParser_Eval: exists(file2-in-subdirectory) -exists(file2-in-subdirectory) result is "varname-vpath.dir2/file2-in-subdirectory" +"file2-in-subdirectory" exists in "varname-vpath.dir2/file2-in-subdirectory" : yes 2 exit status 0 diff --git a/contrib/bmake/unit-tests/varname.exp b/contrib/bmake/unit-tests/varname.exp index d173d2025e9f..454e40cdf9cf 100644 --- a/contrib/bmake/unit-tests/varname.exp +++ b/contrib/bmake/unit-tests/varname.exp @@ -5,13 +5,13 @@ Var_Parse: ${VARNAME} (eval) Global: VAR((( = 3 open parentheses Var_Parse: ${VAR(((}}}}" != "3 open parentheses}}}" (eval) Global: .ALLTARGETS = VAR(((=) -make: varname.mk:31: Missing ')' in archive specification +make: varname.mk:31: Missing ")" in archive specification make: varname.mk:31: Error in archive specification: "VAR" Var_Parse: ${:UVAR\(\(\(}= try2 (eval) Evaluating modifier ${:U...} on value "" (eval, undefined) Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (eval, defined) Global: .ALLTARGETS = VAR(((=) VAR\(\(\(= -make: varname.mk:37: Invalid line '${:UVAR\(\(\(}= try2', expanded to 'VAR\(\(\(= try2' +make: varname.mk:37: Invalid line "${:UVAR\(\(\(}= try2", expanded to "VAR\(\(\(= try2" Var_Parse: ${VARNAME} (eval) Global: VAR((( = try3 Global: .MAKEFLAGS = -r -k -d v -d diff --git a/contrib/bmake/unit-tests/varname.mk b/contrib/bmake/unit-tests/varname.mk index ae18819aa19e..17f29da7ef4c 100644 --- a/contrib/bmake/unit-tests/varname.mk +++ b/contrib/bmake/unit-tests/varname.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname.mk,v 1.17 2025/06/12 04:33:00 rillig Exp $ +# $NetBSD: varname.mk,v 1.18 2025/06/28 22:39:29 rillig Exp $ # # Tests for variable names. @@ -26,14 +26,14 @@ ${VARNAME}= 3 open parentheses # This is not a variable assignment since the parentheses and braces are not # balanced. At the end of the line, there are still 3 levels open, which # means the variable name is not finished. -# expect+2: Missing ')' in archive specification +# expect+2: Missing ")" in archive specification # expect+1: Error in archive specification: "VAR" ${:UVAR(((}= try1 # On the left-hand side of a variable assignments, the backslash is not parsed # as an escape character, therefore the parentheses still count to the nesting # level, which at the end of the line is still 3. Therefore this is not a # variable assignment as well. -# expect+1: Invalid line '${:UVAR\(\(\(}= try2', expanded to 'VAR\(\(\(= try2' +# expect+1: Invalid line "${:UVAR\(\(\(}= try2", expanded to "VAR\(\(\(= try2" ${:UVAR\(\(\(}= try2 # To assign to a variable with an arbitrary name, the variable name has to # come from an external source, not the text that is parsed in the assignment diff --git a/contrib/bmake/unit-tests/varparse-errors.exp b/contrib/bmake/unit-tests/varparse-errors.exp index d4d01c96627e..2a9be069075f 100644 --- a/contrib/bmake/unit-tests/varparse-errors.exp +++ b/contrib/bmake/unit-tests/varparse-errors.exp @@ -12,33 +12,33 @@ make: varparse-errors.mk:73: Unknown modifier ":OX" make: varparse-errors.mk:73: Unknown modifier ":OX" while evaluating "${:OX}" with value "" while evaluating variable "IND" with value "${:OX}" -make: varparse-errors.mk:81: Unclosed expression, expecting '}' for modifier "Q" +make: varparse-errors.mk:81: Unclosed expression, expecting "}" for modifier "Q" while evaluating "${:U:Q" with value "" -make: varparse-errors.mk:83: Unclosed expression, expecting '}' for modifier "sh" +make: varparse-errors.mk:83: Unclosed expression, expecting "}" for modifier "sh" while evaluating "${:U:sh" with value "" -make: varparse-errors.mk:85: Unclosed expression, expecting '}' for modifier "tA" +make: varparse-errors.mk:85: Unclosed expression, expecting "}" for modifier "tA" while evaluating "${:U:tA" with value "" -make: varparse-errors.mk:87: Unclosed expression, expecting '}' for modifier "tsX" +make: varparse-errors.mk:87: Unclosed expression, expecting "}" for modifier "tsX" while evaluating "${:U:tsX" with value "" -make: varparse-errors.mk:89: Unclosed expression, expecting '}' for modifier "ts" +make: varparse-errors.mk:89: Unclosed expression, expecting "}" for modifier "ts" while evaluating "${:U:ts" with value "" -make: varparse-errors.mk:91: Unclosed expression, expecting '}' for modifier "ts\040" +make: varparse-errors.mk:91: Unclosed expression, expecting "}" for modifier "ts\040" while evaluating "${:U:ts\040" with value "" -make: varparse-errors.mk:93: Unclosed expression, expecting '}' for modifier "u" +make: varparse-errors.mk:93: Unclosed expression, expecting "}" for modifier "u" while evaluating "${:U:u" with value "" -make: varparse-errors.mk:95: Unclosed expression, expecting '}' for modifier "H" +make: varparse-errors.mk:95: Unclosed expression, expecting "}" for modifier "H" while evaluating "${:U:H" with value "." -make: varparse-errors.mk:97: Unclosed expression, expecting '}' for modifier "[1]" +make: varparse-errors.mk:97: Unclosed expression, expecting "}" for modifier "[1]" while evaluating "${:U:[1]" with value "" -make: varparse-errors.mk:99: Unclosed expression, expecting '}' for modifier "hash" +make: varparse-errors.mk:99: Unclosed expression, expecting "}" for modifier "hash" while evaluating "${:U:hash" with value "b2af338b" -make: varparse-errors.mk:101: Unclosed expression, expecting '}' for modifier "range" +make: varparse-errors.mk:101: Unclosed expression, expecting "}" for modifier "range" while evaluating "${:U:range" with value "1" -make: varparse-errors.mk:103: Unclosed expression, expecting '}' for modifier "_" +make: varparse-errors.mk:103: Unclosed expression, expecting "}" for modifier "_" while evaluating "${:U:_" with value "" -make: varparse-errors.mk:105: Unclosed expression, expecting '}' for modifier "gmtime" +make: varparse-errors.mk:105: Unclosed expression, expecting "}" for modifier "gmtime" while evaluating "${:U:gmtime" with value "<timestamp>" -make: varparse-errors.mk:107: Unclosed expression, expecting '}' for modifier "localtime" +make: varparse-errors.mk:107: Unclosed expression, expecting "}" for modifier "localtime" while evaluating "${:U:localtime" with value "<timestamp>" make: varparse-errors.tmp:1: Unknown modifier ":Z" while evaluating "${:Z}" with value "" diff --git a/contrib/bmake/unit-tests/varparse-errors.mk b/contrib/bmake/unit-tests/varparse-errors.mk index 2d1142fbb65c..bd74c442e789 100644 --- a/contrib/bmake/unit-tests/varparse-errors.mk +++ b/contrib/bmake/unit-tests/varparse-errors.mk @@ -1,4 +1,4 @@ -# $NetBSD: varparse-errors.mk,v 1.25 2025/05/03 08:18:33 rillig Exp $ +# $NetBSD: varparse-errors.mk,v 1.26 2025/06/28 22:39:29 rillig Exp $ # Tests for parsing and evaluating all kinds of expressions. # @@ -77,33 +77,33 @@ _:= ${:U:OX:U${IND}} ${:U:OX:U${IND}} # Before var.c 1.032 from 2022-08-24, make complained about 'Unknown modifier' # or 'Bad modifier' when in fact the modifier was entirely correct, it was # just not delimited by either ':' or '}' but instead by '\0'. -# expect+1: Unclosed expression, expecting '}' for modifier "Q" +# expect+1: Unclosed expression, expecting "}" for modifier "Q" UNCLOSED:= ${:U:Q -# expect+1: Unclosed expression, expecting '}' for modifier "sh" +# expect+1: Unclosed expression, expecting "}" for modifier "sh" UNCLOSED:= ${:U:sh -# expect+1: Unclosed expression, expecting '}' for modifier "tA" +# expect+1: Unclosed expression, expecting "}" for modifier "tA" UNCLOSED:= ${:U:tA -# expect+1: Unclosed expression, expecting '}' for modifier "tsX" +# expect+1: Unclosed expression, expecting "}" for modifier "tsX" UNCLOSED:= ${:U:tsX -# expect+1: Unclosed expression, expecting '}' for modifier "ts" +# expect+1: Unclosed expression, expecting "}" for modifier "ts" UNCLOSED:= ${:U:ts -# expect+1: Unclosed expression, expecting '}' for modifier "ts\040" +# expect+1: Unclosed expression, expecting "}" for modifier "ts\040" UNCLOSED:= ${:U:ts\040 -# expect+1: Unclosed expression, expecting '}' for modifier "u" +# expect+1: Unclosed expression, expecting "}" for modifier "u" UNCLOSED:= ${:U:u -# expect+1: Unclosed expression, expecting '}' for modifier "H" +# expect+1: Unclosed expression, expecting "}" for modifier "H" UNCLOSED:= ${:U:H -# expect+1: Unclosed expression, expecting '}' for modifier "[1]" +# expect+1: Unclosed expression, expecting "}" for modifier "[1]" UNCLOSED:= ${:U:[1] -# expect+1: Unclosed expression, expecting '}' for modifier "hash" +# expect+1: Unclosed expression, expecting "}" for modifier "hash" UNCLOSED:= ${:U:hash -# expect+1: Unclosed expression, expecting '}' for modifier "range" +# expect+1: Unclosed expression, expecting "}" for modifier "range" UNCLOSED:= ${:U:range -# expect+1: Unclosed expression, expecting '}' for modifier "_" +# expect+1: Unclosed expression, expecting "}" for modifier "_" UNCLOSED:= ${:U:_ -# expect+1: Unclosed expression, expecting '}' for modifier "gmtime" +# expect+1: Unclosed expression, expecting "}" for modifier "gmtime" UNCLOSED:= ${:U:gmtime -# expect+1: Unclosed expression, expecting '}' for modifier "localtime" +# expect+1: Unclosed expression, expecting "}" for modifier "localtime" UNCLOSED:= ${:U:localtime diff --git a/contrib/bmake/var.c b/contrib/bmake/var.c index 55d20bd324ac..66b18f769371 100644 --- a/contrib/bmake/var.c +++ b/contrib/bmake/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1168 2025/06/13 18:31:08 rillig Exp $ */ +/* $NetBSD: var.c,v 1.1171 2025/06/29 11:02:17 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -143,7 +143,7 @@ #endif /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.1168 2025/06/13 18:31:08 rillig Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.1171 2025/06/29 11:02:17 rillig Exp $"); /* * Variables are defined using one of the VAR=value assignments. Their @@ -452,6 +452,8 @@ VarNew(FStr name, const char *value, static Substring CanonicalVarname(Substring name) { + if (Substring_Equals(name, "^")) + return Substring_InitStr(ALLSRC); if (!(Substring_Length(name) > 0 && name.start[0] == '.')) return name; @@ -471,8 +473,6 @@ CanonicalVarname(Substring name) if (Substring_Equals(name, ".TARGET")) return Substring_InitStr(TARGET); - /* GNU make has an additional alias $^ == ${.ALLSRC}. */ - if (Substring_Equals(name, ".SHELL") && shellPath == NULL) Shell_Init(); @@ -2134,16 +2134,16 @@ typedef enum ApplyModifierResult { } ApplyModifierResult; /* - * Allow backslashes to escape the delimiter, $, and \, but don't touch other + * Allow backslashes to escape the delimiters, $, and \, but don't touch other * backslashes. */ static bool -IsEscapedModifierPart(const char *p, char delim, +IsEscapedModifierPart(const char *p, char end1, char end2, struct ModifyWord_SubstArgs *subst) { if (p[0] != '\\' || p[1] == '\0') return false; - if (p[1] == delim || p[1] == '\\' || p[1] == '$') + if (p[1] == end1 || p[1] == end2 || p[1] == '\\' || p[1] == '$') return true; return p[1] == '&' && subst != NULL; } @@ -2236,7 +2236,7 @@ ParseModifierPart( LazyBuf_Init(part, p); while (*p != '\0' && *p != end1 && *p != end2) { - if (IsEscapedModifierPart(p, end2, subst)) { + if (IsEscapedModifierPart(p, end1, end2, subst)) { LazyBuf_Add(part, p[1]); p += 2; } else if (*p != '$') { /* Unescaped, simple text */ @@ -2703,7 +2703,7 @@ ApplyModifier_Range(const char **pp, ModChain *ch) const char *p = mod + 6; if (!TryParseSize(&p, &n)) { Parse_Error(PARSE_FATAL, - "Invalid number \"%s\" for ':range' modifier", + "Invalid number \"%s\" for modifier \":range\"", mod + 6); return AMR_CLEANUP; } @@ -2834,7 +2834,7 @@ ModifyWord_Match(Substring word, SepBuf *buf, void *data) if (res.error != NULL && !args->error_reported) { args->error_reported = true; Parse_Error(PARSE_FATAL, - "%s in pattern '%s' of modifier '%s'", + "%s in pattern \"%s\" of modifier \"%s\"", res.error, args->pattern, args->neg ? ":N" : ":M"); } if (res.matched != args->neg) @@ -2927,7 +2927,7 @@ ApplyModifier_Mtime(const char **pp, ModChain *ch) invalid_argument: Parse_Error(PARSE_FATAL, - "Invalid argument '%.*s' for modifier ':mtime'", + "Invalid argument \"%.*s\" for modifier \":mtime\"", (int)strcspn(*pp + 1, ":{}()"), *pp + 1); return AMR_CLEANUP; } @@ -2965,7 +2965,7 @@ ApplyModifier_Subst(const char **pp, ModChain *ch) char delim = (*pp)[1]; if (delim == '\0') { Parse_Error(PARSE_FATAL, - "Missing delimiter for modifier ':S'"); + "Missing delimiter for modifier \":S\""); (*pp)++; return AMR_CLEANUP; } @@ -3017,7 +3017,7 @@ ApplyModifier_Regex(const char **pp, ModChain *ch) char delim = (*pp)[1]; if (delim == '\0') { Parse_Error(PARSE_FATAL, - "Missing delimiter for modifier ':C'"); + "Missing delimiter for modifier \":C\""); (*pp)++; return AMR_CLEANUP; } @@ -3995,7 +3995,7 @@ ApplyModifiersIndirect(ModChain *ch, const char **pp) else if (*p == '\0' && ch->endc != '\0') { Parse_Error(PARSE_FATAL, "Unclosed expression after indirect modifier, " - "expecting '%c'", + "expecting \"%c\"", ch->endc); *pp = p; return AMIR_OUT; @@ -4051,14 +4051,14 @@ ApplySingleModifier(const char **pp, ModChain *ch) if (*p == '\0' && ch->endc != '\0') { Parse_Error(PARSE_FATAL, - "Unclosed expression, expecting '%c' for " + "Unclosed expression, expecting \"%c\" for " "modifier \"%.*s\"", ch->endc, (int)(p - mod), mod); } else if (*p == ':') { p++; } else if (opts.strict && *p != '\0' && *p != ch->endc) { Parse_Error(PARSE_FATAL, - "Missing delimiter ':' after modifier \"%.*s\"", + "Missing delimiter \":\" after modifier \"%.*s\"", (int)(p - mod), mod); /* * TODO: propagate parse error to the enclosing @@ -4106,7 +4106,7 @@ ApplyModifiers( if (*p == '\0' && endc != '\0') { Parse_Error(PARSE_FATAL, - "Unclosed expression, expecting '%c'", ch.endc); + "Unclosed expression, expecting \"%c\"", ch.endc); goto cleanup; } @@ -4263,7 +4263,7 @@ IsShortVarnameValid(char varname, const char *start) Parse_Error(PARSE_FATAL, "Dollar followed by nothing"); else if (save_dollars) Parse_Error(PARSE_FATAL, - "Invalid variable name '%c', at \"%s\"", varname, start); + "Invalid variable name \"%c\", at \"%s\"", varname, start); return false; } @@ -4330,7 +4330,7 @@ FindLocalLegacyVar(Substring varname, GNode *scope, return NULL; if (varname.start[1] != 'F' && varname.start[1] != 'D') return NULL; - if (strchr("@%?*!<>", varname.start[0]) == NULL) + if (strchr("@%?*!<>^", varname.start[0]) == NULL) return NULL; v = VarFindSubstring(Substring_Init(varname.start, varname.start + 1), diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c index b312a37ed3ed..d5d4af998a0c 100644 --- a/contrib/bsnmp/lib/snmpclient.c +++ b/contrib/bsnmp/lib/snmpclient.c @@ -981,14 +981,8 @@ open_client_local(const char *path) char *ptr; int stype; - if (snmp_client.chost == NULL) { - if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_LOCAL))) - == NULL) { - seterr(&snmp_client, "%s", strerror(errno)); - return (-1); - } - strcpy(snmp_client.chost, DEFAULT_LOCAL); - } + if (snmp_client.chost == NULL && path == NULL) + path = SNMP_DEFAULT_LOCAL; if (path != NULL) { if ((ptr = malloc(1 + strlen(path))) == NULL) { seterr(&snmp_client, "%s", strerror(errno)); @@ -1012,7 +1006,7 @@ open_client_local(const char *path) snprintf(snmp_client.local_path, sizeof(snmp_client.local_path), "%s", SNMP_LOCAL_PATH); - if (mkstemp(snmp_client.local_path) == -1) { + if (mktemp(snmp_client.local_path) == NULL) { seterr(&snmp_client, "%s", strerror(errno)); (void)close(snmp_client.fd); snmp_client.fd = -1; diff --git a/contrib/bsnmp/lib/snmpclient.h b/contrib/bsnmp/lib/snmpclient.h index a19bdb2ea653..662dc7c4a204 100644 --- a/contrib/bsnmp/lib/snmpclient.h +++ b/contrib/bsnmp/lib/snmpclient.h @@ -40,6 +40,7 @@ #define SNMP_STRERROR_LEN 200 +#define SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock" #define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX" diff --git a/contrib/bsnmp/lib/snmppriv.h b/contrib/bsnmp/lib/snmppriv.h index 5b66992ca985..6ed51cf39369 100644 --- a/contrib/bsnmp/lib/snmppriv.h +++ b/contrib/bsnmp/lib/snmppriv.h @@ -44,4 +44,3 @@ enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *); #define DEFAULT_HOST "localhost" #define DEFAULT_PORT "snmp" -#define DEFAULT_LOCAL "/var/run/snmp.sock" diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c index 928b84121f82..c77572934d24 100644 --- a/contrib/bsnmp/snmpd/main.c +++ b/contrib/bsnmp/snmpd/main.c @@ -42,6 +42,7 @@ #include <sys/un.h> #include <sys/ucred.h> #include <sys/uio.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -1509,7 +1510,7 @@ main(int argc, char *argv[]) { int opt; FILE *fp; - int background = 1; + bool background = true; struct tport *p; const char *prefix = "snmpd"; struct lmodule *m; @@ -1526,11 +1527,6 @@ main(int argc, char *argv[]) NULL }; - snmp_printf = snmp_printf_func; - snmp_error = snmp_error_func; - snmp_debug = snmp_debug_func; - asn_error = asn_error_func; - while ((opt = getopt(argc, argv, "c:dD:e:hI:l:m:p:")) != EOF) switch (opt) { @@ -1539,7 +1535,7 @@ main(int argc, char *argv[]) break; case 'd': - background = 0; + background = false; break; case 'D': @@ -1601,6 +1597,13 @@ main(int argc, char *argv[]) break; } + if (background) { + snmp_printf = snmp_printf_func; + snmp_error = snmp_error_func; + snmp_debug = snmp_debug_func; + asn_error = asn_error_func; + } + openlog(prefix, LOG_PID | (background ? 0 : LOG_PERROR), LOG_USER); setlogmask(LOG_UPTO(debug.logpri - 1)); diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c index fa3bd34d14f0..ca2311be7cc3 100644 --- a/contrib/bsnmp/snmpd/trans_lsock.c +++ b/contrib/bsnmp/snmpd/trans_lsock.c @@ -417,7 +417,7 @@ lsock_send(struct tport *tp, const u_char *buf, size_t len, } } - return (sendto(peer->input.fd, buf, len, 0, addr, addrlen)); + return (sendto(peer->input.fd, buf, len, MSG_NOSIGNAL, addr, addrlen)); } static void diff --git a/contrib/elftoolchain/libelf/elf_open.3 b/contrib/elftoolchain/libelf/elf_open.3 index 054036a24935..896bf8455ae5 100644 --- a/contrib/elftoolchain/libelf/elf_open.3 +++ b/contrib/elftoolchain/libelf/elf_open.3 @@ -23,11 +23,12 @@ .\" .\" $Id: elf_open.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd June 12, 2019 +.Dd July 15, 2025 .Dt ELF_OPEN 3 .Os .Sh NAME -.Nm elf_open +.Nm elf_open , +.Nm elf_openmemory .Nd open ELF objects and ar(1) archives .Sh LIBRARY .Lb libelf diff --git a/contrib/elftoolchain/libelf/gelf_xlatetof.3 b/contrib/elftoolchain/libelf/gelf_xlatetof.3 index 2e5ee0fe15e0..4a7b25c99b5a 100644 --- a/contrib/elftoolchain/libelf/gelf_xlatetof.3 +++ b/contrib/elftoolchain/libelf/gelf_xlatetof.3 @@ -23,13 +23,16 @@ .\" .\" $Id: gelf_xlatetof.3 3639 2018-10-14 14:07:02Z jkoshy $ .\" -.Dd October 11, 2018 +.Dd July 15, 2025 .Dt GELF_XLATETOF 3 .Os .Sh NAME -.Nm elf32_xlate , -.Nm elf64_xlate , -.Nm gelf_xlate +.Nm elf32_xlatetof , +.Nm elf32_xlatetom , +.Nm elf64_xlatetof , +.Nm elf64_xlatetom , +.Nm gelf_xlatetof , +.Nm gelf_xlatetom .Nd translate data between files and memory .Sh LIBRARY .Lb libelf diff --git a/contrib/less/NEWS b/contrib/less/NEWS index 5767ded21a00..cdc8196a5f16 100644 --- a/contrib/less/NEWS +++ b/contrib/less/NEWS @@ -11,6 +11,16 @@ ====================================================================== + Major changes between "less" versions 678 and 679 + +* Fix bad parsing of lesskey file an env var is a prefix of another + env var (github #626). + +* Fix unexpected exit using -K if a key press is received while reading + the input file (github #628). + +====================================================================== + Major changes between "less" versions 668 and 678 * Treat -r in LESS environment variable as -R. diff --git a/contrib/less/decode.c b/contrib/less/decode.c index 2942a30863cb..8e451d1810c9 100644 --- a/contrib/less/decode.c +++ b/contrib/less/decode.c @@ -750,7 +750,7 @@ static int cmd_search(constant char *cmd, constant unsigned char *table, constan { action = taction; *extra = textra; - } else if (match > 0) /* cmd is a prefix of this table entry */ + } else if (match > 0 && action == A_INVALID) /* cmd is a prefix of this table entry */ { action = A_PREFIX; } diff --git a/contrib/less/help.c b/contrib/less/help.c index 81e0943fe4e2..5d8ba9a1b0fe 100644 --- a/contrib/less/help.c +++ b/contrib/less/help.c @@ -1,4 +1,4 @@ -/* This file was generated by mkhelp.pl from less.hlp at 20:41 on 2025/5/1 */ +/* This file was generated by mkhelp.pl from less.hlp at 19:46 on 2025/5/28 */ #include "less.h" constant char helpdata[] = { '\n', diff --git a/contrib/less/less.h b/contrib/less/less.h index 94a3e2235906..7b2d2c25bfc6 100644 --- a/contrib/less/less.h +++ b/contrib/less/less.h @@ -575,10 +575,11 @@ typedef enum { #endif #endif -#define S_INTERRUPT 01 -#define S_STOP 02 -#define S_WINCH 04 -#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) +#define S_INTERRUPT (1<<0) +#define S_SWINTERRUPT (1<<1) +#define S_STOP (1<<2) +#define S_WINCH (1<<3) +#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_SWINTERRUPT|S_STOP)) #ifdef EXIT_SUCCESS #define QUIT_OK EXIT_SUCCESS diff --git a/contrib/less/less.nro b/contrib/less/less.nro index 6b74ec5f161b..25a9869a9c59 100644 --- a/contrib/less/less.nro +++ b/contrib/less/less.nro @@ -1,5 +1,5 @@ '\" t -.TH LESS 1 "Version 678: 01 May 2025" +.TH LESS 1 "Version 679: 28 May 2025" .SH NAME less \- display the contents of a file in a terminal .SH SYNOPSIS diff --git a/contrib/less/lessecho.nro b/contrib/less/lessecho.nro index 696fcb13b214..f0cccc4de6da 100644 --- a/contrib/less/lessecho.nro +++ b/contrib/less/lessecho.nro @@ -1,4 +1,4 @@ -.TH LESSECHO 1 "Version 678: 01 May 2025" +.TH LESSECHO 1 "Version 679: 28 May 2025" .SH NAME lessecho \- expand metacharacters .SH SYNOPSIS diff --git a/contrib/less/lesskey.nro b/contrib/less/lesskey.nro index 61ba056b04c6..0a17c9deff71 100644 --- a/contrib/less/lesskey.nro +++ b/contrib/less/lesskey.nro @@ -1,5 +1,5 @@ '\" t -.TH LESSKEY 1 "Version 678: 01 May 2025" +.TH LESSKEY 1 "Version 679: 28 May 2025" .SH NAME lesskey \- customize key bindings for less .SH "SYNOPSIS (deprecated)" diff --git a/contrib/less/os.c b/contrib/less/os.c index 98a7ecf70c3c..357cbb356a16 100644 --- a/contrib/less/os.c +++ b/contrib/less/os.c @@ -275,7 +275,7 @@ start: if (ret != 0) { if (ret == READ_INTR) - sigs |= S_INTERRUPT; + sigs |= S_SWINTERRUPT; reading = FALSE; return (ret); } @@ -287,7 +287,7 @@ start: int c; c = WIN32getch(); - sigs |= S_INTERRUPT; + sigs |= S_SWINTERRUPT; reading = FALSE; if (c != CONTROL('C') && c != intr_char) WIN32ungetch((char) c); @@ -348,7 +348,7 @@ public int iopen(constant char *filename, int flags) while (!opening && SET_JUMP(open_label)) { opening = FALSE; - if (sigs & S_INTERRUPT) + if (sigs & (S_INTERRUPT|S_SWINTERRUPT)) { sigs = 0; #if HAVE_SETTABLE_ERRNO diff --git a/contrib/less/version.c b/contrib/less/version.c index 9a97f1658940..68a42a6272fa 100644 --- a/contrib/less/version.c +++ b/contrib/less/version.c @@ -1047,6 +1047,8 @@ v675 4/3/25 Add ESC-b. v676 4/16/25 Fix two OSC 8 display bugs. v677 4/27/25 Fix & filtering bug. v678 5/1/25 Don't change stty tab setting. +v679 5/28/25 Fix lesskey parsing bug when env var is prefix of another; + fix unexpected exit when using -K. */ -char version[] = "678"; +char version[] = "679"; diff --git a/contrib/libbegemot/rpoll.c b/contrib/libbegemot/rpoll.c index c61b84057eba..f5ce43140205 100644 --- a/contrib/libbegemot/rpoll.c +++ b/contrib/libbegemot/rpoll.c @@ -285,8 +285,8 @@ poll_register(int fd, poll_f func, void *arg, int mask) poll_unblocksig(); if(rpoll_trace) - fprintf(stderr, "poll_register(%d, %p, %p, %#x)->%tu", - fd, (void *)func, (void *)arg, mask, p - regs); + fprintf(stderr, "%s(%d, %p, %p, %#x)->%tu\n", __func__, fd, + (void *)func, (void *)arg, mask, p - regs); return p - regs; } @@ -297,7 +297,7 @@ void poll_unregister(int handle) { if(rpoll_trace) - fprintf(stderr, "poll_unregister(%d)", handle); + fprintf(stderr, "%s(%d)\n", __func__, handle); poll_blocksig(); @@ -399,8 +399,8 @@ poll_start_utimer(unsigned long long usecs, int repeat, timer_f func, void *arg) resort = 1; if(rpoll_trace) - fprintf(stderr, "poll_start_utimer(%llu, %d, %p, %p)->%tu", - usecs, repeat, (void *)func, (void *)arg, p - tims); + fprintf(stderr, "%s(%llu, %d, %p, %p)->%tu\n", __func__, usecs, + repeat, (void *)func, (void *)arg, p - tims); return p - tims; } @@ -418,7 +418,7 @@ poll_stop_timer(int handle) u_int i; if(rpoll_trace) - fprintf(stderr, "poll_stop_timer(%d)", handle); + fprintf(stderr, "%s(%d)\n", __func__, handle); tims[handle].func = NULL; tims_used--; @@ -597,9 +597,10 @@ poll_dispatch(int wait) if(mask) { if(rpoll_trace) - fprintf(stderr, "poll_dispatch() -- " - "file %d/%d %x", - regs[idx].fd, idx, mask); + fprintf(stderr, + "%s() -- file %d/%d %x\n", + __func__, regs[idx].fd, + idx, mask); (*regs[idx].func)(regs[idx].fd, mask, regs[idx].arg); } } @@ -617,7 +618,8 @@ poll_dispatch(int wait) if(tims[tfd[i]].when > now) break; if(rpoll_trace) - fprintf(stderr, "rpoll_dispatch() -- timeout %d",tfd[i]); + fprintf(stderr, "%s() -- timeout %d\n", + __func__, tfd[i]); (*tims[tfd[i]].func)(tfd[i], tims[tfd[i]].arg); if(tfd[i] < 0) continue; diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h index 7bfdaaae45a9..a59a9342341d 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h @@ -13052,12 +13052,19 @@ public: /// ForConstraintInstantiation indicates we should continue looking when /// encountering a lambda generic call operator, and continue looking for /// arguments on an enclosing class template. + /// + /// \param SkipForSpecialization when specified, any template specializations + /// in a traversal would be ignored. + /// \param ForDefaultArgumentSubstitution indicates we should continue looking + /// when encountering a specialized member function template, rather than + /// returning immediately. MultiLevelTemplateArgumentList getTemplateInstantiationArgs( const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt, bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, bool ForConstraintInstantiation = false, - bool SkipForSpecialization = false); + bool SkipForSpecialization = false, + bool ForDefaultArgumentSubstitution = false); /// RAII object to handle the state changes required to synthesize /// a function body. diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp index a09e3be83c45..c2e8ed0c602e 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -269,7 +269,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec, Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, MultiLevelTemplateArgumentList &Result, const FunctionDecl *Pattern, bool RelativeToPrimary, - bool ForConstraintInstantiation) { + bool ForConstraintInstantiation, + bool ForDefaultArgumentSubstitution) { // Add template arguments from a function template specialization. if (!RelativeToPrimary && Function->getTemplateSpecializationKindForInstantiation() == @@ -299,7 +300,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, // If this function was instantiated from a specialized member that is // a function template, we're done. assert(Function->getPrimaryTemplate() && "No function template?"); - if (Function->getPrimaryTemplate()->isMemberSpecialization()) + if (!ForDefaultArgumentSubstitution && + Function->getPrimaryTemplate()->isMemberSpecialization()) return Response::Done(); // If this function is a generic lambda specialization, we are done. @@ -465,7 +467,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( const NamedDecl *ND, const DeclContext *DC, bool Final, std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary, const FunctionDecl *Pattern, bool ForConstraintInstantiation, - bool SkipForSpecialization) { + bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) { assert((ND || DC) && "Can't find arguments for a decl if one isn't provided"); // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; @@ -507,7 +509,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( SkipForSpecialization); } else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) { R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary, - ForConstraintInstantiation); + ForConstraintInstantiation, + ForDefaultArgumentSubstitution); } else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) { R = HandleRecordDecl(*this, Rec, Result, Context, ForConstraintInstantiation); @@ -3231,7 +3234,6 @@ bool Sema::SubstDefaultArgument( // default argument expression appears. ContextRAII SavedContext(*this, FD); std::unique_ptr<LocalInstantiationScope> LIS; - MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs; if (ForCallExpr) { // When instantiating a default argument due to use in a call expression, @@ -3244,19 +3246,10 @@ bool Sema::SubstDefaultArgument( /*ForDefinition*/ false); if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs)) return true; - const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); - if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) { - TemplateArgumentList *CurrentTemplateArgumentList = - TemplateArgumentList::CreateCopy(getASTContext(), - TemplateArgs.getInnermost()); - NewTemplateArgs = getTemplateInstantiationArgs( - FD, FD->getDeclContext(), /*Final=*/false, - CurrentTemplateArgumentList->asArray(), /*RelativeToPrimary=*/true); - } } runWithSufficientStackSpace(Loc, [&] { - Result = SubstInitializer(PatternExpr, NewTemplateArgs, + Result = SubstInitializer(PatternExpr, TemplateArgs, /*DirectInit*/ false); }); } diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a12d2eff1d2c..614e6ea12541 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4659,10 +4659,12 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, // // template<typename T> // A<T> Foo(int a = A<T>::FooImpl()); - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true); + MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( + FD, FD->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false, + /*ForDefaultArgumentSubstitution=*/true); if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true)) return true; diff --git a/contrib/tzcode/localtime.c b/contrib/tzcode/localtime.c index f5814a43da54..a6ec3d8e4e21 100644 --- a/contrib/tzcode/localtime.c +++ b/contrib/tzcode/localtime.c @@ -18,6 +18,7 @@ #ifndef DETECT_TZ_CHANGES_INTERVAL #define DETECT_TZ_CHANGES_INTERVAL 61 #endif +int __tz_change_interval = DETECT_TZ_CHANGES_INTERVAL; #include <sys/stat.h> #endif #include <fcntl.h> @@ -408,10 +409,8 @@ change_in_tz(const char *name) static char old_name[PATH_MAX]; static struct stat old_sb; struct stat sb; - int error; - error = stat(name, &sb); - if (error != 0) + if (stat(name, &sb) != 0) return -1; if (strcmp(name, old_name) != 0) { @@ -510,13 +509,13 @@ tzloadbody(char const *name, struct state *sp, bool doextend, * 'doextend' to ignore TZDEFRULES; the change_in_tz() * function can only keep state for a single file. */ - int ret = change_in_tz(name); - if (ret <= 0) { - /* - * Returns an errno value if there was an error, - * and 0 if the timezone had not changed. - */ + switch (change_in_tz(name)) { + case -1: return errno; + case 0: + return 0; + case 1: + break; } } fid = _open(name, O_RDONLY | O_BINARY); @@ -1376,22 +1375,13 @@ recheck_tzdata() { static time_t last_checked; struct timespec now; - time_t current_time; - int error; - /* - * We want to recheck the timezone file every 61 sec. - */ - error = clock_gettime(CLOCK_MONOTONIC, &now); - if (error < 0) { - /* XXX: Can we somehow report this? */ + if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) return 0; - } - current_time = now.tv_sec; - if ((current_time - last_checked > DETECT_TZ_CHANGES_INTERVAL) || - (last_checked > current_time)) { - last_checked = current_time; + if ((now.tv_sec - last_checked >= __tz_change_interval) || + (last_checked > now.tv_sec)) { + last_checked = now.tv_sec; return 1; } diff --git a/include/rpc/des.h b/include/rpc/des.h index 5056e4b1545c..df4ab75d9bf0 100644 --- a/include/rpc/des.h +++ b/include/rpc/des.h @@ -56,26 +56,6 @@ struct desparams { # define des_buf UDES.UDES_buf /* otherwise, pointer to data */ }; -#ifdef notdef - -/* - * These ioctls are only implemented in SunOS. Maybe someday - * if somebody writes a driver for DES hardware that works - * with FreeBSD, we can being that back. - */ - -/* - * Encrypt an arbitrary sized buffer - */ -#define DESIOCBLOCK _IOWR('d', 6, struct desparams) - -/* - * Encrypt of small amount of data, quickly - */ -#define DESIOCQUICK _IOWR('d', 7, struct desparams) - -#endif - /* * Software DES. */ diff --git a/krb5/include/Makefile b/krb5/include/Makefile index 0a2ceaebb689..c7b3f0f10a99 100644 --- a/krb5/include/Makefile +++ b/krb5/include/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-lib .include <src.opts.mk> diff --git a/krb5/lib/Makefile.inc b/krb5/lib/Makefile.inc index 8df7b76410a2..6d86e7a35146 100644 --- a/krb5/lib/Makefile.inc +++ b/krb5/lib/Makefile.inc @@ -9,6 +9,8 @@ .include "../Makefile.inc" +PACKAGE?= kerberos-lib + KRB5_KRB5LIBDIR= ${KRB5_SRCLIBDIR}/krb5 KRB5_K5CRYPTODIR= ${KRB5_SRCLIBDIR}/crypto diff --git a/krb5/lib/apputils/Makefile b/krb5/lib/apputils/Makefile index 62ef36f0615e..cf430eb3cd27 100644 --- a/krb5/lib/apputils/Makefile +++ b/krb5/lib/apputils/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5-lib - .include <src.opts.mk> .include "../Makefile.inc" diff --git a/krb5/lib/crypto/Makefile b/krb5/lib/crypto/Makefile index 5087a2fb559b..ed1cd7764012 100644 --- a/krb5/lib/crypto/Makefile +++ b/krb5/lib/crypto/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= k5crypto # SHLIB_MAJOR= 3 LDFLAGS=-Wl,--no-undefined LIBADD= com_err krb5support crypto +VERSION_MAP= ${.CURDIR}/version.map # XXX The following doesn't work. Even though the pathnames are the same # XXX we need to use the alternative .include statements. diff --git a/krb5/lib/crypto/version.map b/krb5/lib/crypto/version.map new file mode 100644 index 000000000000..bd4c2c1cd23f --- /dev/null +++ b/krb5/lib/crypto/version.map @@ -0,0 +1,108 @@ +KRB5_CRYPTO_1.0 { + global: + krb5_c_make_random_key; + krb5_c_encrypt_length; + krb5_process_key; + krb5_string_to_cksumtype; + krb5_c_valid_enctype; + krb5_c_valid_cksumtype; + krb5_string_to_key; + krb5_c_encrypt_iov; + krb5_c_checksum_length; + is_keyed_cksum; + krb5_c_padding_length; + is_coll_proof_cksum; + krb5_init_random_key; + krb5_c_string_to_key_with_params; + krb5_c_random_make_octets; + krb5_c_random_os_entropy; + krb5_c_decrypt; + krb5_c_crypto_length; + krb5_c_block_size; + krb5_cksumtype_to_string; + krb5_c_keyed_checksum_types; + krb5_c_is_keyed_cksum; + krb5_c_crypto_length_iov; + valid_cksumtype; + krb5_c_random_seed; + krb5_c_random_to_key; + krb5_verify_checksum; + krb5_c_free_state; + krb5_c_verify_checksum; + krb5_c_random_add_entropy; + krb5_c_decrypt_iov; + krb5_c_make_checksum; + krb5_checksum_size; + krb5_free_cksumtypes; + krb5_finish_key; + krb5_encrypt_size; + krb5_c_keylengths; + krb5_c_prf; + krb5_encrypt; + krb5_string_to_enctype; + krb5_c_is_coll_proof_cksum; + krb5_c_init_state; + krb5_eblock_enctype; + krb5_decrypt; + krb5_c_encrypt; + krb5_c_enctype_compare; + krb5_c_verify_checksum_iov; + valid_enctype; + krb5_enctype_to_string; + krb5_enctype_to_name; + krb5_c_make_checksum_iov; + krb5_calculate_checksum; + krb5_c_string_to_key; + krb5_use_enctype; + krb5_random_key; + krb5_finish_random_key; + krb5_c_prf_length; + krb5int_c_mandatory_cksumtype; + krb5_c_fx_cf2_simple; + krb5int_c_weak_enctype; + krb5_encrypt_data; + krb5int_c_copy_keyblock; + krb5int_c_copy_keyblock_contents; + krb5int_c_free_keyblock_contents; + krb5int_c_free_keyblock; + krb5int_c_init_keyblock; + krb5int_hash_md4; + krb5int_hash_md5; + krb5int_hash_sha256; + krb5int_hash_sha384; + krb5int_enc_arcfour; + krb5int_hmac; + krb5_k_create_key; + krb5_k_decrypt; + krb5_k_decrypt_iov; + krb5_k_encrypt; + krb5_k_encrypt_iov; + krb5_k_free_key; + krb5_k_key_enctype; + krb5_k_key_keyblock; + krb5_k_make_checksum; + krb5_k_make_checksum_iov; + krb5_k_prf; + krb5_k_reference_key; + krb5_k_verify_checksum; + krb5_k_verify_checksum_iov; + krb5int_aes_encrypt; + krb5int_aes_decrypt; + krb5int_enc_des3; + krb5int_arcfour_gsscrypt; + krb5int_camellia_encrypt; + krb5int_cmac_checksum; + krb5int_enc_aes128; + krb5int_enc_aes256; + krb5int_enc_camellia128; + krb5int_enc_camellia256; + krb5int_derive_key; + krb5int_derive_random; + k5_sha256; + krb5int_nfold; + k5_allow_weak_pbkdf2iter; + krb5_c_prfplus; + krb5_c_derive_prfplus; + k5_enctype_to_ssf; + krb5int_c_deprecated_enctype; +}; diff --git a/krb5/lib/gssapi/Makefile b/krb5/lib/gssapi/Makefile index 51ed6f162d65..63e4d7df4bed 100644 --- a/krb5/lib/gssapi/Makefile +++ b/krb5/lib/gssapi/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= gssapi_krb5 # SHLIB_MAJOR= 2 LDFLAGS=-Wl,--no-undefined LIBADD= krb5 k5crypto com_err krb5profile krb5support +VERSION_MAP= ${.CURDIR}/version.map # This is a contcatonation of: # crypto/krb5/src/lib/gssapi/libgssapi_krb5.exports diff --git a/krb5/lib/gssapi/version.map b/krb5/lib/gssapi/version.map new file mode 100644 index 000000000000..afdfe9a0a83a --- /dev/null +++ b/krb5/lib/gssapi/version.map @@ -0,0 +1,172 @@ +KRB5_GSSAPI_1.0 { + global: + GSS_C_ATTR_LOCAL_LOGIN_USER; + GSS_C_INQ_NEGOEX_KEY; + GSS_C_INQ_NEGOEX_VERIFY_KEY; + GSS_C_INQ_SSPI_SESSION_KEY; + GSS_C_MA_AUTH_INIT; + GSS_C_MA_AUTH_INIT_ANON; + GSS_C_MA_AUTH_INIT_INIT; + GSS_C_MA_AUTH_TARG; + GSS_C_MA_AUTH_TARG_ANON; + GSS_C_MA_AUTH_TARG_INIT; + GSS_C_MA_CBINDINGS; + GSS_C_MA_COMPRESS; + GSS_C_MA_CONF_PROT; + GSS_C_MA_CTX_TRANS; + GSS_C_MA_DELEG_CRED; + GSS_C_MA_DEPRECATED; + GSS_C_MA_INTEG_PROT; + GSS_C_MA_ITOK_FRAMED; + GSS_C_MA_MECH_COMPOSITE; + GSS_C_MA_MECH_CONCRETE; + GSS_C_MA_MECH_GLUE; + GSS_C_MA_MECH_NEGO; + GSS_C_MA_MECH_PSEUDO; + GSS_C_MA_MIC; + GSS_C_MA_NEGOEX_AND_SPNEGO; + GSS_C_MA_NOT_DFLT_MECH; + GSS_C_MA_NOT_MECH; + GSS_C_MA_OOS_DET; + GSS_C_MA_PFS; + GSS_C_MA_PROT_READY; + GSS_C_MA_REPLAY_DET; + GSS_C_MA_WRAP; + GSS_C_NT_ANONYMOUS; + GSS_C_NT_COMPOSITE_EXPORT; + GSS_C_NT_EXPORT_NAME; + GSS_C_NT_HOSTBASED_SERVICE; + GSS_C_NT_HOSTBASED_SERVICE_X; + GSS_C_NT_MACHINE_UID_NAME; + GSS_C_NT_STRING_UID_NAME; + GSS_C_NT_USER_NAME; + GSS_C_SEC_CONTEXT_SASL_SSF; + GSS_KRB5_CRED_NO_CI_FLAGS_X; + GSS_KRB5_GET_CRED_IMPERSONATOR; + GSS_KRB5_NT_ENTERPRISE_NAME; + GSS_KRB5_NT_PRINCIPAL_NAME; + GSS_KRB5_NT_X509_CERT; + gss_accept_sec_context; + gss_acquire_cred; + gss_acquire_cred_from; + gss_acquire_cred_impersonate_name; + gss_acquire_cred_with_password; + gss_add_buffer_set_member; + gss_add_cred; + gss_add_cred_from; + gss_add_cred_impersonate_name; + gss_add_cred_with_password; + gss_add_oid_set_member; + gss_authorize_localname; + gss_canonicalize_name; + gss_compare_name; + gss_complete_auth_token; + gss_context_time; + gss_create_empty_buffer_set; + gss_create_empty_oid_set; + gss_decapsulate_token; + gss_delete_name_attribute; + gss_delete_sec_context; + gss_display_mech_attr; + gss_display_name; + gss_display_name_ext; + gss_display_status; + gss_duplicate_name; + gss_encapsulate_token; + gss_export_cred; + gss_export_name; + gss_export_name_composite; + gss_export_sec_context; + gss_get_mic; + gss_get_mic_iov; + gss_get_mic_iov_length; + gss_get_name_attribute; + gss_import_cred; + gss_import_name; + gss_import_sec_context; + gss_indicate_mechs; + gss_indicate_mechs_by_attrs; + gss_init_sec_context; + gss_inquire_attrs_for_mech; + gss_inquire_context; + gss_inquire_cred; + gss_inquire_cred_by_mech; + gss_inquire_cred_by_oid; + gss_inquire_mech_for_saslname; + gss_inquire_mechs_for_name; + gss_inquire_name; + gss_inquire_names_for_mech; + gss_inquire_saslname_for_mech; + gss_inquire_sec_context_by_oid; + gss_krb5_ccache_name; + gss_krb5_copy_ccache; + gss_krb5_export_lucid_sec_context; + gss_krb5_free_lucid_sec_context; + gss_krb5_get_tkt_flags; + gss_krb5_import_cred; + gss_krb5_set_allowable_enctypes; + gss_krb5_set_cred_rcache; + gss_krb5int_make_seal_token_v3; + gss_krb5int_unseal_token_v3; + gss_localname; + gss_map_name_to_any; + gss_mech_iakerb; + gss_mech_krb5; + gss_mech_krb5_old; + gss_mech_krb5_wrong; + gss_mech_set_krb5; + gss_mech_set_krb5_both; + gss_mech_set_krb5_old; + gss_nt_exported_name; + gss_nt_krb5_name; + gss_nt_krb5_principal; + gss_nt_machine_uid_name; + gss_nt_service_name; + gss_nt_service_name_v2; + gss_nt_string_uid_name; + gss_nt_user_name; + gss_oid_equal; + gss_oid_to_str; + gss_pname_to_uid; + gss_process_context_token; + gss_pseudo_random; + gss_release_any_name_mapping; + gss_release_buffer; + gss_release_buffer_set; + gss_release_cred; + gss_release_iov_buffer; + gss_release_name; + gss_release_oid; + gss_release_oid_set; + gss_seal; + gss_set_cred_option; + gss_set_name_attribute; + gss_set_neg_mechs; + gss_set_sec_context_option; + gss_sign; + gss_store_cred; + gss_store_cred_into; + gss_str_to_oid; + gss_test_oid_set_member; + gss_unseal; + gss_unwrap; + gss_unwrap_aead; + gss_unwrap_iov; + gss_userok; + gss_verify; + gss_verify_mic; + gss_verify_mic_iov; + gss_wrap; + gss_wrap_aead; + gss_wrap_iov; + gss_wrap_iov_length; + gss_wrap_size_limit; + gssint_g_seqstate_init; + gsskrb5_extract_authtime_from_sec_context; + gsskrb5_extract_authz_data_from_sec_context; + gssspi_mech_invoke; + gssspi_set_cred_option; + krb5_gss_dbg_client_expcreds; + krb5_gss_register_acceptor_identity; + krb5_gss_use_kdc_context; +}; diff --git a/krb5/lib/kadm5clnt/Makefile b/krb5/lib/kadm5clnt/Makefile index ddb9b0e9fec5..22d78d7ae2f1 100644 --- a/krb5/lib/kadm5clnt/Makefile +++ b/krb5/lib/kadm5clnt/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= kadm5clnt_mit # SHLIB_MAJOR= 12 LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile gssrpc gssapi_krb5 krb5 k5crypto krb5support com_err +VERSION_MAP= ${.CURDIR}/version.map SRCS= alt_prof.c \ chpass_util.c \ diff --git a/krb5/lib/kadm5clnt/version.map b/krb5/lib/kadm5clnt/version.map new file mode 100644 index 000000000000..9743c7cf6140 --- /dev/null +++ b/krb5/lib/kadm5clnt/version.map @@ -0,0 +1,118 @@ +KRB5_KADM5_CLNT_1.0 { + global: + _kadm5_check_handle; + _kadm5_chpass_principal_util; + kadm5_chpass_principal; + kadm5_chpass_principal_3; + kadm5_chpass_principal_util; + kadm5_create_policy; + kadm5_create_principal; + kadm5_create_principal_3; + kadm5_decrypt_key; + kadm5_delete_policy; + kadm5_delete_principal; + kadm5_destroy; + kadm5_flush; + kadm5_free_config_params; + kadm5_free_kadm5_key_data; + kadm5_free_key_data; + kadm5_free_name_list; + kadm5_free_policy_ent; + kadm5_free_principal_ent; + kadm5_free_strings; + kadm5_get_admin_service_name; + kadm5_get_config_params; + kadm5_get_policies; + kadm5_get_policy; + kadm5_get_principal; + kadm5_get_principal_keys; + kadm5_get_principals; + kadm5_get_privs; + kadm5_get_strings; + kadm5_init; + kadm5_init_anonymous; + kadm5_init_krb5_context; + kadm5_init_with_creds; + kadm5_init_with_password; + kadm5_init_with_skey; + kadm5_lock; + kadm5_modify_policy; + kadm5_modify_principal; + kadm5_purgekeys; + kadm5_randkey_principal; + kadm5_randkey_principal_3; + kadm5_rename_principal; + kadm5_set_string; + kadm5_setkey_principal; + kadm5_setkey_principal_3; + kadm5_setkey_principal_4; + kadm5_unlock; + krb5_aprof_get_boolean; + krb5_aprof_get_deltat; + krb5_aprof_get_int32; + krb5_aprof_get_string; + krb5_aprof_getvals; + krb5_flagnum_to_string; + krb5_flagspec_to_mask; + krb5_flags_to_strings; + krb5_free_key_data_contents; + krb5_keysalt_is_present; + krb5_keysalt_iterate; + krb5_klog_close; + krb5_klog_init; + krb5_klog_reopen; + krb5_klog_set_context; + krb5_klog_syslog; + krb5_string_to_keysalts; + xdr_chpass3_arg; + xdr_chpass_arg; + xdr_chrand3_arg; + xdr_chrand_arg; + xdr_chrand_ret; + xdr_cpol_arg; + xdr_cprinc3_arg; + xdr_cprinc_arg; + xdr_dpol_arg; + xdr_dprinc_arg; + xdr_generic_ret; + xdr_getpkeys_arg; + xdr_getpkeys_ret; + xdr_getprivs_ret; + xdr_gpol_arg; + xdr_gpol_ret; + xdr_gpols_arg; + xdr_gpols_ret; + xdr_gprinc_arg; + xdr_gprinc_ret; + xdr_gprincs_arg; + xdr_gprincs_ret; + xdr_kadm5_key_data; + xdr_kadm5_policy_ent_rec; + xdr_kadm5_principal_ent_rec; + xdr_kadm5_ret_t; + xdr_krb5_deltat; + xdr_krb5_enctype; + xdr_krb5_flags; + xdr_krb5_int16; + xdr_krb5_key_data_nocontents; + xdr_krb5_key_salt_tuple; + xdr_krb5_keyblock; + xdr_krb5_kvno; + xdr_krb5_octet; + xdr_krb5_principal; + xdr_krb5_salttype; + xdr_krb5_timestamp; + xdr_krb5_tl_data; + xdr_krb5_ui_2; + xdr_krb5_ui_4; + xdr_mpol_arg; + xdr_mprinc_arg; + xdr_nullstring; + xdr_nulltype; + xdr_rprinc_arg; + xdr_setkey3_arg; + xdr_setkey4_arg; + xdr_setkey_arg; + xdr_ui_4; + kadm5_init_iprop; +}; diff --git a/krb5/lib/kadm5srv/Makefile b/krb5/lib/kadm5srv/Makefile index f716dfcdaedc..50f1e859f17b 100644 --- a/krb5/lib/kadm5srv/Makefile +++ b/krb5/lib/kadm5srv/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= kadm5srv_mit # SHLIB_MAJOR= 12 LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile gssrpc gssapi_krb5 kdb5 krb5 k5crypto krb5support com_err +VERSION_MAP= ${.CURDIR}/version.map INCSDIR= ${INCLUDEDIR}/kadm5 diff --git a/krb5/lib/kadm5srv/version.map b/krb5/lib/kadm5srv/version.map new file mode 100644 index 000000000000..a0e9da6daef2 --- /dev/null +++ b/krb5/lib/kadm5srv/version.map @@ -0,0 +1,137 @@ +KRB5_KADM5_SRV_1.0 { + global: + _kadm5_check_handle; + _kadm5_chpass_principal_util; + hist_princ; + kadm5_chpass_principal; + kadm5_chpass_principal_3; + kadm5_chpass_principal_util; + kadm5_create_policy; + kadm5_create_principal; + kadm5_create_principal_3; + kadm5_decrypt_key; + kadm5_delete_policy; + kadm5_delete_principal; + kadm5_destroy; + kadm5_flush; + kadm5_free_config_params; + kadm5_free_kadm5_key_data; + kadm5_free_key_data; + kadm5_free_name_list; + kadm5_free_policy_ent; + kadm5_free_principal_ent; + kadm5_free_strings; + kadm5_get_config_params; + kadm5_get_policies; + kadm5_get_policy; + kadm5_get_principal; + kadm5_get_principal_keys; + kadm5_get_principals; + kadm5_get_privs; + kadm5_get_strings; + kadm5_init; + kadm5_init_anonymous; + kadm5_init_krb5_context; + kadm5_init_with_creds; + kadm5_init_with_password; + kadm5_init_with_skey; + kadm5_lock; + kadm5_modify_policy; + kadm5_modify_principal; + kadm5_purgekeys; + kadm5_randkey_principal; + kadm5_randkey_principal_3; + kadm5_rename_principal; + kadm5_set_string; + kadm5_setkey_principal; + kadm5_setkey_principal_3; + kadm5_setkey_principal_4; + kadm5_unlock; + kdb_delete_entry; + kdb_free_entry; + kdb_init_hist; + kdb_init_master; + kdb_iter_entry; + kdb_put_entry; + krb5_aprof_get_boolean; + krb5_aprof_get_deltat; + krb5_aprof_get_int32; + krb5_aprof_get_string; + krb5_aprof_get_string_all; + krb5_aprof_getvals; + krb5_copy_key_data_contents; + krb5_flagnum_to_string; + krb5_flagspec_to_mask; + krb5_flags_to_strings; + krb5_free_key_data_contents; + krb5_keysalt_is_present; + krb5_keysalt_iterate; + krb5_klog_close; + krb5_klog_init; + krb5_klog_reopen; + krb5_klog_set_context; + krb5_klog_syslog; + krb5_string_to_keysalts; + master_db; + master_princ; + osa_free_princ_ent; + passwd_check; + xdr_chpass3_arg; + xdr_chpass_arg; + xdr_chrand3_arg; + xdr_chrand_arg; + xdr_chrand_ret; + xdr_cpol_arg; + xdr_cprinc3_arg; + xdr_cprinc_arg; + xdr_dpol_arg; + xdr_dprinc_arg; + xdr_generic_ret; + xdr_getpkeys_arg; + xdr_getpkeys_ret; + xdr_getprivs_ret; + xdr_gpol_arg; + xdr_gpol_ret; + xdr_gpols_arg; + xdr_gpols_ret; + xdr_gprinc_arg; + xdr_gprinc_ret; + xdr_gprincs_arg; + xdr_gprincs_ret; + xdr_gstrings_arg; + xdr_gstrings_ret; + xdr_kadm5_policy_ent_rec; + xdr_kadm5_principal_ent_rec; + xdr_kadm5_ret_t; + xdr_krb5_deltat; + xdr_krb5_enctype; + xdr_krb5_flags; + xdr_krb5_int16; + xdr_krb5_key_data; + xdr_krb5_key_data_nocontents; + xdr_krb5_key_salt_tuple; + xdr_krb5_keyblock; + xdr_krb5_kvno; + xdr_krb5_octet; + xdr_krb5_principal; + xdr_krb5_salttype; + xdr_krb5_string_attr; + xdr_krb5_timestamp; + xdr_krb5_tl_data; + xdr_krb5_ui_2; + xdr_krb5_ui_4; + xdr_mpol_arg; + xdr_mprinc_arg; + xdr_nullstring; + xdr_nulltype; + xdr_osa_princ_ent_rec; + xdr_osa_pw_hist_ent; + xdr_purgekeys_arg; + xdr_rprinc_arg; + xdr_setkey3_arg; + xdr_setkey4_arg; + xdr_setkey_arg; + xdr_sstring_arg; + xdr_ui_4; + kadm5_init_iprop; +}; diff --git a/krb5/lib/kdb/Makefile b/krb5/lib/kdb/Makefile index ac7f058a7f11..ff17900fb7ec 100644 --- a/krb5/lib/kdb/Makefile +++ b/krb5/lib/kdb/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= kdb5 # SHLIB_MAJOR= 10 LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile gssrpc krb5 k5crypto com_err krb5support gssapi_krb5 +VERSION_MAP= ${.CURDIR}/version.map SRCS= decrypt_key.c \ encrypt_key.c \ diff --git a/krb5/lib/kdb/version.map b/krb5/lib/kdb/version.map new file mode 100644 index 000000000000..9522af1e9edd --- /dev/null +++ b/krb5/lib/kdb/version.map @@ -0,0 +1,111 @@ +KRB5_KDB5_1.0 { + global: + krb5_db_setup_lib_handle; + krb5_db_open; + krb5_db_inited; + krb5_db_alloc; + krb5_db_free; + krb5_db_allowed_to_delegate_from; + krb5_db_audit_as_req; + krb5_db_check_allowed_to_delegate; + krb5_db_get_s4u_x509_principal; + krb5_db_check_policy_as; + krb5_db_check_policy_tgs; + krb5_db_check_transited_realms; + krb5_db_create; + krb5_db_delete_principal; + krb5_db_destroy; + krb5_db_fetch_mkey; + krb5_db_fetch_mkey_list; + krb5_db_fini; + krb5_db_free_principal; + krb5_db_get_age; + krb5_db_get_key_data_kvno; + krb5_db_get_context; + krb5_db_get_principal; + krb5_db_issue_pac; + krb5_db_iterate; + krb5_db_lock; + krb5_db_mkey_list_alias; + krb5_db_put_principal; + krb5_db_refresh_config; + krb5_db_rename_principal; + krb5_db_set_context; + krb5_db_setup_mkey_name; + krb5_db_unlock; + krb5_db_store_master_key; + krb5_db_store_master_key_list; + krb5_dbe_apw; + krb5_dbe_ark; + krb5_dbe_cpw; + krb5_dbe_create_key_data; + krb5_dbe_crk; + krb5_dbe_find_act_mkey; + krb5_dbe_fetch_act_key_list; + krb5_dbe_find_enctype; + krb5_dbe_find_mkey; + krb5_dbe_free_actkvno_list; + krb5_dbe_free_key_data_contents; + krb5_dbe_free_mkey_aux_list; + krb5_dbe_free_key_list; + krb5_dbe_free_string; + krb5_dbe_free_strings; + krb5_dbe_get_mkvno; + krb5_dbe_get_string; + krb5_dbe_get_strings; + krb5_dbe_compute_salt; + krb5_dbe_lookup_last_admin_unlock; + krb5_dbe_lookup_last_pwd_change; + krb5_dbe_lookup_actkvno; + krb5_dbe_lookup_mkey_aux; + krb5_dbe_lookup_mkvno; + krb5_dbe_lookup_mod_princ_data; + krb5_dbe_lookup_tl_data; + krb5_dbe_search_enctype; + krb5_dbe_set_string; + krb5_dbe_specialize_salt; + krb5_dbe_update_actkvno; + krb5_dbe_update_last_admin_unlock; + krb5_dbe_update_last_pwd_change; + krb5_dbe_update_mkey_aux; + krb5_dbe_update_mkvno; + krb5_dbe_update_mod_princ_data; + krb5_dbe_update_tl_data; + krb5_db_update_tl_data; + krb5_dbe_def_encrypt_key_data; + krb5_dbe_def_decrypt_key_data; + krb5_dbe_decrypt_key_data; + krb5_dbe_encrypt_key_data; + krb5_kt_kdb_ops; + krb5_ktkdb_close; + krb5_ktkdb_get_entry; + krb5_ktkdb_resolve; + krb5_ktkdb_set_context; + krb5_mkey_pwd_prompt1; + krb5_mkey_pwd_prompt2; + krb5_db_create_policy; + krb5_db_get_policy; + krb5_db_put_policy; + krb5_db_iter_policy; + krb5_db_delete_policy; + krb5_db_free_policy; + krb5_def_store_mkey_list; + krb5_db_promote; + krb5_db_register_keytab; + ulog_add_update; + ulog_init_header; + ulog_map; + ulog_set_role; + ulog_free_entries; + xdr_kdb_last_t; + xdr_kdb_incr_result_t; + xdr_kdb_fullresync_result_t; + ulog_fini; + ulog_get_entries; + ulog_get_last; + ulog_get_sno_status; + ulog_replay; + ulog_set_last; + xdr_kdb_incr_update_t; + krb5_dbe_sort_key_data; +}; diff --git a/krb5/lib/krad/Makefile b/krb5/lib/krad/Makefile index 4b18af482207..0bc74e8318f8 100644 --- a/krb5/lib/krad/Makefile +++ b/krb5/lib/krad/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5-lib - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= krad # SHLIB_MAJOR= 0 LDFLAGS=-Wl,--no-undefined LIBADD= krb5 k5crypto com_err krb5profile krb5support verto +VERSION_MAP= ${.CURDIR}/version.map SRCS= attr.c \ attrset.c \ diff --git a/krb5/lib/krad/version.map b/krb5/lib/krad/version.map new file mode 100644 index 000000000000..7e058d9bd494 --- /dev/null +++ b/krb5/lib/krad/version.map @@ -0,0 +1,26 @@ +KRB5_KRAD_1.0 { + global: + krad_code_name2num; + krad_code_num2name; + krad_attr_name2num; + krad_attr_num2name; + krad_attrset_new; + krad_attrset_copy; + krad_attrset_free; + krad_attrset_add; + krad_attrset_add_number; + krad_attrset_del; + krad_attrset_get; + krad_packet_bytes_needed; + krad_packet_free; + krad_packet_new_request; + krad_packet_new_response; + krad_packet_decode_request; + krad_packet_decode_response; + krad_packet_encode; + krad_packet_get_code; + krad_packet_get_attr; + krad_client_new; + krad_client_free; + krad_client_send; +}; diff --git a/krb5/lib/krb5/Makefile b/krb5/lib/krb5/Makefile index bf90c7fc80f7..163005b6abf3 100644 --- a/krb5/lib/krb5/Makefile +++ b/krb5/lib/krb5/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= krb5 LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile k5crypto com_err krb5support # SHLIB_MAJOR= 3 +VERSION_MAP= ${.CURDIR}/version.map SRCS= krb5_libinit.c diff --git a/krb5/lib/krb5/version.map b/krb5/lib/krb5/version.map new file mode 100644 index 000000000000..3f37ce0dce31 --- /dev/null +++ b/krb5/lib/krb5/version.map @@ -0,0 +1,617 @@ +KRB5_KRB5_1.0 { + global: + _krb5_conf_boolean; + decode_krb5_ad_kdcissued; + decode_krb5_ap_rep; + decode_krb5_ap_rep_enc_part; + decode_krb5_ap_req; + decode_krb5_as_rep; + decode_krb5_as_req; + decode_krb5_authdata; + decode_krb5_authenticator; + decode_krb5_cammac; + decode_krb5_cred; + decode_krb5_enc_cred_part; + decode_krb5_enc_data; + decode_krb5_enc_kdc_rep_part; + decode_krb5_enc_priv_part; + decode_krb5_enc_sam_response_enc_2; + decode_krb5_enc_tkt_part; + decode_krb5_encryption_key; + decode_krb5_error; + decode_krb5_etype_info; + decode_krb5_etype_info2; + decode_krb5_fast_req; + decode_krb5_fast_response; + decode_krb5_iakerb_finished; + decode_krb5_iakerb_header; + decode_krb5_kdc_req_body; + decode_krb5_otp_tokeninfo; + decode_krb5_kkdcp_message; + decode_krb5_pa_enc_ts; + decode_krb5_pa_for_user; + decode_krb5_pa_fx_fast_reply; + decode_krb5_pa_fx_fast_request; + decode_krb5_pa_otp_challenge; + decode_krb5_pa_otp_req; + decode_krb5_pa_otp_enc_req; + decode_krb5_pa_pac_options; + decode_krb5_pa_pac_req; + decode_krb5_pa_s4u_x509_user; + decode_krb5_pa_spake; + decode_krb5_padata_sequence; + decode_krb5_priv; + decode_krb5_safe; + decode_krb5_sam_challenge_2; + decode_krb5_sam_challenge_2_body; + decode_krb5_sam_response_2; + decode_krb5_secure_cookie; + decode_krb5_setpw_req; + decode_krb5_spake_factor; + decode_krb5_tgs_rep; + decode_krb5_tgs_req; + decode_krb5_ticket; + decode_krb5_typed_data; + decode_utf8_strings; + encode_krb5_ad_kdcissued; + encode_krb5_ap_rep; + encode_krb5_ap_rep_enc_part; + encode_krb5_ap_req; + encode_krb5_as_rep; + encode_krb5_as_req; + encode_krb5_authdata; + encode_krb5_authenticator; + encode_krb5_cammac; + encode_krb5_checksum; + encode_krb5_cred; + encode_krb5_enc_cred_part; + encode_krb5_enc_data; + encode_krb5_enc_kdc_rep_part; + encode_krb5_enc_priv_part; + encode_krb5_enc_sam_response_enc_2; + encode_krb5_enc_tkt_part; + encode_krb5_encryption_key; + encode_krb5_error; + encode_krb5_etype_info; + encode_krb5_etype_info2; + encode_krb5_fast_response; + encode_krb5_iakerb_finished; + encode_krb5_iakerb_header; + encode_krb5_kdc_req_body; + encode_krb5_otp_tokeninfo; + encode_krb5_kkdcp_message; + encode_krb5_pa_enc_ts; + encode_krb5_pa_for_user; + encode_krb5_pa_fx_fast_reply; + encode_krb5_pa_otp_challenge; + encode_krb5_pa_otp_req; + encode_krb5_pa_otp_enc_req; + encode_krb5_pa_pac_options; + encode_krb5_pa_s4u_x509_user; + encode_krb5_pa_spake; + encode_krb5_padata_sequence; + encode_krb5_pkinit_supp_pub_info; + encode_krb5_priv; + encode_krb5_s4u_userid; + encode_krb5_safe; + encode_krb5_sam_challenge_2; + encode_krb5_sam_challenge_2_body; + encode_krb5_sam_response_2; + encode_krb5_secure_cookie; + encode_krb5_sp80056a_other_info; + encode_krb5_spake_factor; + encode_krb5_tgs_rep; + encode_krb5_tgs_req; + encode_krb5_ticket; + encode_krb5_typed_data; + encode_utf8_strings; + k5_add_empty_pa_data; + k5_add_pa_data_element; + k5_add_pa_data_from_data; + k5_alloc_pa_data; + k5_authind_decode; + k5_build_conf_principals; + k5_cc_store_primary_cred; + k5_ccselect_free_context; + k5_change_error_message_code; + k5_etypes_contains; + k5_expand_path_tokens; + k5_expand_path_tokens_extra; + k5_externalize_auth_context; + k5_externalize_authdata; + k5_externalize_authdata_context; + k5_externalize_context; + k5_externalize_keyblock; + k5_externalize_principal; + k5_free_algorithm_identifier; + k5_free_cammac; + k5_free_data_ptr_list; + k5_free_otp_tokeninfo; + k5_free_kkdcp_message; + k5_free_pa_data_element; + k5_free_pa_otp_challenge; + k5_free_pa_otp_req; + k5_free_secure_cookie; + k5_free_pa_spake; + k5_free_serverlist; + k5_free_spake_factor; + k5_hostrealm_free_context; + k5_init_trace; + k5_internalize_auth_context; + k5_internalize_authdata; + k5_internalize_authdata_context; + k5_internalize_context; + k5_internalize_keyblock; + k5_internalize_principal; + k5_is_string_numeric; + k5_kt_get_principal; + k5_kt_have_match; + k5_localauth_free_context; + k5_locate_kdc; + k5_marshal_cred; + k5_marshal_princ; + k5_os_free_context; + k5_os_init_context; + k5_parse_host_string; + k5_plugin_free_modules; + k5_plugin_load; + k5_plugin_load_all; + k5_plugin_register; + k5_plugin_register_dyn; + k5_rc_close; + k5_rc_get_name; + k5_rc_resolve; + k5_rc_store; + k5_size_auth_context; + k5_size_authdata; + k5_size_authdata_context; + k5_size_context; + k5_size_keyblock; + k5_size_principal; + k5_sname_compare; + k5_unmarshal_cred; + k5_unmarshal_princ; + k5_unwrap_cammac_svc; + k5_zapfree_pa_data; + krb524_convert_creds_kdc; + krb524_init_ets; + krb5_425_conv_principal; + krb5_524_conv_principal; + krb5_524_convert_creds; + krb5_address_compare; + krb5_address_order; + krb5_address_search; + krb5_allow_weak_crypto; + krb5_aname_to_localname; + krb5_anonymous_principal; + krb5_anonymous_realm; + krb5_appdefault_boolean; + krb5_appdefault_string; + krb5_auth_con_free; + krb5_auth_con_genaddrs; + krb5_auth_con_get_checksum_func; + krb5_auth_con_get_authdata_context; + krb5_auth_con_getaddrs; + krb5_auth_con_getauthenticator; + krb5_auth_con_getflags; + krb5_auth_con_getivector; + krb5_auth_con_getkey; + krb5_auth_con_getkey_k; + krb5_auth_con_getlocalseqnumber; + krb5_auth_con_getlocalsubkey; + krb5_auth_con_getpermetypes; + krb5_auth_con_getrcache; + krb5_auth_con_getrecvsubkey; + krb5_auth_con_getrecvsubkey_k; + krb5_auth_con_getremoteseqnumber; + krb5_auth_con_getremotesubkey; + krb5_auth_con_getsendsubkey; + krb5_auth_con_getsendsubkey_k; + krb5_auth_con_init; + krb5_auth_con_initivector; + krb5_auth_con_set_authdata_context; + krb5_auth_con_set_checksum_func; + krb5_auth_con_set_req_cksumtype; + krb5_auth_con_set_safe_cksumtype; + krb5_auth_con_setaddrs; + krb5_auth_con_setflags; + krb5_auth_con_setivector; + krb5_auth_con_setpermetypes; + krb5_auth_con_setports; + krb5_auth_con_setrcache; + krb5_auth_con_setrecvsubkey; + krb5_auth_con_setrecvsubkey_k; + krb5_auth_con_setsendsubkey; + krb5_auth_con_setsendsubkey_k; + krb5_auth_con_setuseruserkey; + krb5_authdata_context_copy; + krb5_authdata_context_free; + krb5_authdata_context_init; + krb5_authdata_delete_attribute; + krb5_authdata_get_attribute_types; + krb5_authdata_get_attribute; + krb5_authdata_set_attribute; + krb5_authdata_export_attributes; + krb5_authdata_export_authdata; + krb5_authdata_export_internal; + krb5_authdata_free_internal; + krb5_authdata_import_attributes; + krb5_build_principal; + krb5_build_principal_alloc_va; + krb5_build_principal_ext; + krb5_build_principal_va; + krb5_cc_cache_match; + krb5_cc_close; + krb5_cc_copy_creds; + krb5_cc_default; + krb5_cc_default_name; + krb5_cc_destroy; + krb5_cc_dfl_ops; + krb5_cc_dup; + krb5_cc_end_seq_get; + krb5_cc_file_ops; + krb5_cc_gen_new; + krb5_cc_get_config; + krb5_cc_get_full_name; + krb5_cc_get_name; + krb5_cc_get_principal; + krb5_cc_get_type; + krb5_cc_move; + krb5_cc_initialize; + krb5_cc_new_unique; + krb5_cc_next_cred; + krb5_cc_register; + krb5_cc_remove_cred; + krb5_cc_resolve; + krb5_cc_retrieve_cred; + krb5_cc_select; + krb5_cc_set_config; + krb5_cc_set_default_name; + krb5_cc_set_flags; + krb5_cc_start_seq_get; + krb5_cc_store_cred; + krb5_cc_support_switch; + krb5_cc_switch; + krb5_cccol_cursor_free; + krb5_cccol_cursor_new; + krb5_cccol_cursor_next; + krb5_cccol_have_content; + krb5_change_cache; + krb5_change_password; + krb5_check_clockskew; + krb5_check_transited_list; + krb5_chpw_message; + krb5_chpw_result_code_string; + krb5_clear_error_message; + krb5_copy_addr; + krb5_copy_addresses; + krb5_copy_authdata; + krb5_copy_authenticator; + krb5_copy_checksum; + krb5_copy_context; + krb5_copy_creds; + krb5_copy_data; + krb5_copy_error_message; + krb5_copy_keyblock; + krb5_copy_keyblock_contents; + krb5_copy_principal; + krb5_copy_ticket; + krb5_crypto_us_timeofday; + krb5_decode_authdata_container; + krb5_decode_ticket; + krb5_decrypt_tkt_part; + krb5_deltat_to_string; + krb5_encode_authdata_container; + krb5_encode_kdc_rep; + krb5_encrypt_helper; + krb5_encrypt_tkt_part; + krb5_expand_hostname; + krb5_fcc_ops; + krb5_find_authdata; + krb5_free_ad_kdcissued; + krb5_free_address; + krb5_free_addresses; + krb5_free_ap_rep; + krb5_free_ap_rep_enc_part; + krb5_free_ap_req; + krb5_free_authdata; + krb5_free_authenticator; + krb5_free_authenticator_contents; + krb5_free_checksum; + krb5_free_checksum_contents; + krb5_free_config_files; + krb5_free_context; + krb5_free_cred; + krb5_free_cred_contents; + krb5_free_cred_enc_part; + krb5_free_creds; + krb5_free_data; + krb5_free_data_contents; + krb5_free_default_realm; + krb5_free_enc_data; + krb5_free_enc_kdc_rep_part; + krb5_free_enc_sam_response_enc_2; + krb5_free_enc_sam_response_enc_2_contents; + krb5_free_enc_tkt_part; + krb5_free_enctypes; + krb5_free_error; + krb5_free_error_message; + krb5_free_etype_info; + krb5_free_fast_armored_req; + krb5_free_fast_req; + krb5_free_fast_response; + krb5_free_host_realm; + krb5_free_iakerb_finished; + krb5_free_iakerb_header; + krb5_free_kdc_rep; + krb5_free_kdc_req; + krb5_free_keyblock; + krb5_free_keyblock_contents; + krb5_free_keytab_entry_contents; + krb5_free_last_req; + krb5_free_octet_data; + krb5_free_pa_data; + krb5_free_pa_enc_ts; + krb5_free_pa_for_user; + krb5_free_pa_pac_req; + krb5_free_pa_s4u_x509_user; + krb5_free_principal; + krb5_free_priv; + krb5_free_priv_enc_part; + krb5_free_realm_tree; + krb5_free_safe; + krb5_free_sam_challenge_2; + krb5_free_sam_challenge_2_body; + krb5_free_sam_challenge_2_body_contents; + krb5_free_sam_challenge_2_contents; + krb5_free_sam_response_2; + krb5_free_sam_response_2_contents; + krb5_free_string; + krb5_free_tgt_creds; + krb5_free_ticket; + krb5_free_tickets; + krb5_free_tkt_authent; + krb5_free_unparsed_name; + krb5_fwd_tgt_creds; + krb5_gen_portaddr; + krb5_gen_replay_name; + krb5_generate_seq_number; + krb5_generate_subkey; + krb5_get_cred_via_tkt; + krb5_get_credentials; + krb5_get_credentials_for_proxy; + krb5_get_credentials_for_user; + krb5_get_credentials_renew; + krb5_get_credentials_validate; + krb5_get_default_config_files; + krb5_get_default_in_tkt_ktypes; + krb5_get_default_realm; + krb5_get_error_message; + krb5_get_etype_info; + krb5_get_fallback_host_realm; + krb5_get_host_realm; + krb5_get_in_tkt_with_keytab; + krb5_get_in_tkt_with_password; + krb5_get_in_tkt_with_skey; + krb5_get_init_creds_keytab; + krb5_get_init_creds_opt_alloc; + krb5_get_init_creds_opt_free; + krb5_get_init_creds_opt_free_pa; + krb5_get_init_creds_opt_get_fast_flags; + krb5_get_init_creds_opt_get_pa; + krb5_get_init_creds_opt_init; + krb5_get_init_creds_opt_set_address_list; + krb5_get_init_creds_opt_set_anonymous; + krb5_get_init_creds_opt_set_canonicalize; + krb5_get_init_creds_opt_set_change_password_prompt; + krb5_get_init_creds_opt_set_etype_list; + krb5_get_init_creds_opt_set_expire_callback; + krb5_get_init_creds_opt_set_fast_ccache; + krb5_get_init_creds_opt_set_fast_ccache_name; + krb5_get_init_creds_opt_set_fast_flags; + krb5_get_init_creds_opt_set_forwardable; + krb5_get_init_creds_opt_set_in_ccache; + krb5_get_init_creds_opt_set_out_ccache; + krb5_get_init_creds_opt_set_pa; + krb5_get_init_creds_opt_set_pac_request; + krb5_get_init_creds_opt_set_preauth_list; + krb5_get_init_creds_opt_set_proxiable; + krb5_get_init_creds_opt_set_renew_life; + krb5_get_init_creds_opt_set_responder; + krb5_get_init_creds_opt_set_salt; + krb5_get_init_creds_opt_set_tkt_life; + krb5_get_init_creds_password; + krb5_get_notification_message; + krb5_get_permitted_enctypes; + krb5_get_profile; + krb5_get_prompt_types; + krb5_get_realm_domain; + krb5_get_renewed_creds; + krb5_get_server_rcache; + krb5_get_tgs_ktypes; + krb5_get_time_offsets; + krb5_get_validated_creds; + krb5_init_context; + krb5_init_context_profile; + krb5_init_creds_free; + krb5_init_creds_get; + krb5_init_creds_get_creds; + krb5_init_creds_get_error; + krb5_init_creds_get_times; + krb5_init_creds_init; + krb5_init_creds_set_keytab; + krb5_init_creds_set_password; + krb5_init_creds_set_service; + krb5_init_creds_step; + krb5_init_keyblock; + krb5_init_secure_context; + krb5_is_config_principal; + krb5_is_permitted_enctype; + krb5_is_referral_realm; + krb5_is_thread_safe; + krb5_kdc_rep_decrypt_proc; + krb5_kdc_sign_ticket; + krb5_kdc_verify_ticket; + krb5_kt_add_entry; + krb5_kt_client_default; + krb5_kt_close; + krb5_kt_default; + krb5_kt_default_name; + krb5_kt_dfl_ops; + krb5_kt_dup; + krb5_kt_end_seq_get; + krb5_kt_free_entry; + krb5_kt_get_entry; + krb5_kt_get_name; + krb5_kt_get_type; + krb5_kt_have_content; + krb5_kt_next_entry; + krb5_kt_read_service_key; + krb5_kt_register; + krb5_kt_remove_entry; + krb5_kt_resolve; + krb5_kt_start_seq_get; + krb5_ktf_ops; + krb5_ktf_writable_ops; + krb5_kuserok; + krb5_lock_file; + krb5_make_authdata_kdc_issued; + krb5_make_full_ipaddr; + krb5_make_fulladdr; + krb5_marshal_credentials; + krb5_mcc_ops; + krb5_merge_authdata; + krb5_mk_1cred; + krb5_mk_error; + krb5_mk_ncred; + krb5_mk_priv; + krb5_mk_rep; + krb5_mk_rep_dce; + krb5_mk_req; + krb5_mk_req_extended; + krb5_mk_safe; + krb5_net_read; + krb5_net_write; + krb5_os_localaddr; + krb5_overridekeyname; + krb5_pac_add_buffer; + krb5_pac_free; + krb5_pac_get_buffer; + krb5_pac_get_types; + krb5_pac_init; + krb5_pac_parse; + krb5_pac_sign; + krb5_pac_sign_ext; + krb5_pac_verify; + krb5_pac_verify_ext; + krb5_pac_get_client_info; + krb5_parse_name; + krb5_parse_name_flags; + krb5_prepend_error_message; + krb5_principal2salt; + krb5_principal2salt_norealm; + krb5_principal_compare; + krb5_principal_compare_any_realm; + krb5_principal_compare_flags; + krb5_prompter_posix; + krb5_rc_default; + krb5_rc_destroy; + krb5_rc_get_lifespan; + krb5_rc_initialize; + krb5_rd_cred; + krb5_rd_error; + krb5_rd_priv; + krb5_rd_rep; + krb5_rd_rep_dce; + krb5_rd_req; + krb5_rd_req_decoded; + krb5_rd_req_decoded_anyflag; + krb5_rd_safe; + krb5_read_message; + krb5_read_password; + krb5_realm_compare; + krb5_recvauth; + krb5_recvauth_version; + krb5_responder_get_challenge; + krb5_responder_list_questions; + krb5_responder_set_answer; + krb5_responder_otp_get_challenge; + krb5_responder_otp_set_answer; + krb5_responder_otp_challenge_free; + krb5_responder_pkinit_get_challenge; + krb5_responder_pkinit_set_answer; + krb5_responder_pkinit_challenge_free; + krb5_salttype_to_string; + krb5_sendauth; + krb5_sendto_kdc; + krb5_ser_pack_bytes; + krb5_ser_pack_int32; + krb5_ser_pack_int64; + krb5_ser_unpack_bytes; + krb5_ser_unpack_int32; + krb5_ser_unpack_int64; + krb5_server_decrypt_ticket_keytab; + krb5_set_config_files; + krb5_set_debugging_time; + krb5_set_default_realm; + krb5_set_default_tgs_enctypes; + krb5_set_default_tgs_ktypes; + krb5_set_error_message; + krb5_set_password; + krb5_set_password_using_ccache; + krb5_set_principal_realm; + krb5_set_real_time; + krb5_set_kdc_send_hook; + krb5_set_kdc_recv_hook; + krb5_set_time_offsets; + krb5_set_trace_callback; + krb5_set_trace_filename; + krb5_sname_match; + krb5_sname_to_principal; + krb5_string_to_deltat; + krb5_string_to_salttype; + krb5_string_to_timestamp; + krb5int_tgtname; + krb5_tkt_creds_free; + krb5_tkt_creds_get; + krb5_tkt_creds_get_creds; + krb5_tkt_creds_get_times; + krb5_tkt_creds_init; + krb5_tkt_creds_step; + krb5_timeofday; + krb5_timestamp_to_sfstring; + krb5_timestamp_to_string; + krb5_unlock_file; + krb5_unmarshal_credentials; + krb5_unpack_full_ipaddr; + krb5_unparse_name; + krb5_unparse_name_ext; + krb5_unparse_name_flags; + krb5_unparse_name_flags_ext; + krb5_us_timeofday; + krb5_use_natural_time; + krb5_verify_authdata_kdc_issued; + krb5_verify_init_creds; + krb5_verify_init_creds_opt_init; + krb5_verify_init_creds_opt_set_ap_req_nofail; + krb5_vprepend_error_message; + krb5_vset_error_message; + krb5_vwrap_error_message; + krb5_walk_realm_tree; + krb5_wrap_error_message; + krb5_write_message; + krb5int_accessor; + krb5int_cc_default; + krb5int_cleanup_library; + krb5int_copy_data_contents; + krb5int_copy_data_contents_add0; + krb5int_find_pa_data; + krb5int_foreach_localaddr; + krb5int_free_data_list; + krb5int_get_authdata_containee_types; + krb5int_init_context_kdc; + krb5int_initialize_library; + krb5int_parse_enctype_list; + krb5int_random_string; + krb5int_trace; +}; diff --git a/krb5/lib/rpc/Makefile b/krb5/lib/rpc/Makefile index 13499b184d30..3bcd7ff7d9d3 100644 --- a/krb5/lib/rpc/Makefile +++ b/krb5/lib/rpc/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= gssrpc # SHLIB_MAJOR= 4 LDFLAGS=-Wl,--no-undefined LIBADD= gssapi_krb5 krb5 k5crypto com_err krb5support +VERSION_MAP= ${.CURDIR}/version.map SRCS= auth_gss.c \ auth_gssapi.c \ diff --git a/krb5/lib/rpc/version.map b/krb5/lib/rpc/version.map new file mode 100644 index 000000000000..4a5052b71536 --- /dev/null +++ b/krb5/lib/rpc/version.map @@ -0,0 +1,147 @@ +KRB5_RPC_1.0 { + global: + gssrpc_auth_debug_gss; + gssrpc_auth_debug_gssapi; + gssrpc_auth_gssapi_create; + gssrpc_auth_gssapi_create_default; + gssrpc_auth_gssapi_display_status; + gssrpc_auth_gssapi_seal_seq; + gssrpc_auth_gssapi_unseal_seq; + gssrpc_auth_gssapi_unwrap_data; + gssrpc_auth_gssapi_wrap_data; + gssrpc_authgss_create; + gssrpc_authgss_create_default; + gssrpc_authgss_get_private_data; + gssrpc_authgss_service; + gssrpc_authnone_create; + gssrpc_authunix_create; + gssrpc_authunix_create_default; + gssrpc_bindresvport; + gssrpc_bindresvport_sa; + gssrpc_callrpc; + gssrpc_clnt_broadcast; + gssrpc_clnt_create; + gssrpc_clnt_pcreateerror; + gssrpc_clnt_perrno; + gssrpc_clnt_perror; + gssrpc_clnt_spcreateerror; + gssrpc_clnt_sperrno; + gssrpc_clnt_sperror; + gssrpc_clntraw_create; + gssrpc_clnttcp_create; + gssrpc_clntudp_bufcreate; + gssrpc_clntudp_create; + gssrpc_get_myaddress; + gssrpc_getrpcport; + gssrpc_log_debug; + gssrpc_log_hexdump; + gssrpc_log_status; + gssrpc_misc_debug_gss; + gssrpc_misc_debug_gssapi; + gssrpc_pmap_getmaps; + gssrpc_pmap_getport; + gssrpc_pmap_rmtcall; + gssrpc_pmap_set; + gssrpc_pmap_unset; + gssrpc_registerrpc; + gssrpc_rpc_createrr; + gssrpc_svc_auth_gss_ops; + gssrpc_svc_auth_gssapi_ops; + gssrpc_svc_auth_none; + gssrpc_svc_auth_none_ops; + gssrpc_svc_debug_gss; + gssrpc_svc_debug_gssapi; + gssrpc_svc_fdset; + gssrpc_svc_fdset_init; + gssrpc_svc_getreq; + gssrpc_svc_getreqset; + gssrpc_svc_maxfd; + gssrpc_svc_register; + gssrpc_svc_run; + gssrpc_svc_sendreply; + gssrpc_svc_unregister; + gssrpc_svcauth_gss_get_principal; + gssrpc_svcauth_gss_set_log_badauth_func; + gssrpc_svcauth_gss_set_log_badauth2_func; + gssrpc_svcauth_gss_set_log_badverf_func; + gssrpc_svcauth_gss_set_log_miscerr_func; + gssrpc_svcauth_gss_set_svc_name; + gssrpc_svcauth_gssapi_set_log_badauth_func; + gssrpc_svcauth_gssapi_set_log_badauth2_func; + gssrpc_svcauth_gssapi_set_log_badverf_func; + gssrpc_svcauth_gssapi_set_log_miscerr_func; + gssrpc_svcauth_gssapi_set_names; + gssrpc_svcauth_gssapi_unset_names; + gssrpc_svcerr_auth; + gssrpc_svcerr_decode; + gssrpc_svcerr_noproc; + gssrpc_svcerr_noprog; + gssrpc_svcerr_progvers; + gssrpc_svcerr_systemerr; + gssrpc_svcerr_weakauth; + gssrpc_svcfd_create; + gssrpc_svcraw_create; + gssrpc_svctcp_create; + gssrpc_svcudp_bufcreate; + gssrpc_svcudp_create; + gssrpc_svcudp_enablecache; + gssrpc_xdr_accepted_reply; + gssrpc_xdr_array; + gssrpc_xdr_authgssapi_creds; + gssrpc_xdr_authgssapi_init_arg; + gssrpc_xdr_authgssapi_init_res; + gssrpc_xdr_authunix_parms; + gssrpc_xdr_bool; + gssrpc_xdr_bytes; + gssrpc_xdr_callhdr; + gssrpc_xdr_callmsg; + gssrpc_xdr_char; + gssrpc_xdr_des_block; + gssrpc_xdr_enum; + gssrpc_xdr_free; + gssrpc_xdr_gss_buf; + gssrpc_xdr_int; + gssrpc_xdr_int32; + gssrpc_xdr_long; + gssrpc_xdr_netobj; + gssrpc_xdr_opaque; + gssrpc_xdr_opaque_auth; + gssrpc_xdr_pmap; + gssrpc_xdr_pmaplist; + gssrpc_xdr_pointer; + gssrpc_xdr_reference; + gssrpc_xdr_rejected_reply; + gssrpc_xdr_replymsg; + gssrpc_xdr_rmtcall_args; + gssrpc_xdr_rmtcallres; + gssrpc_xdr_rpc_gss_buf; + gssrpc_xdr_rpc_gss_cred; + gssrpc_xdr_rpc_gss_data; + gssrpc_xdr_rpc_gss_init_args; + gssrpc_xdr_rpc_gss_init_res; + gssrpc_xdr_rpc_gss_unwrap_data; + gssrpc_xdr_rpc_gss_wrap_data; + gssrpc_xdr_short; + gssrpc_xdr_sizeof; + gssrpc_xdr_string; + gssrpc_xdr_u_char; + gssrpc_xdr_u_int; + gssrpc_xdr_u_int32; + gssrpc_xdr_u_long; + gssrpc_xdr_u_short; + gssrpc_xdr_union; + gssrpc_xdr_vector; + gssrpc_xdr_void; + gssrpc_xdr_wrapstring; + gssrpc_xdralloc_create; + gssrpc_xdralloc_getdata; + gssrpc_xdralloc_release; + gssrpc_xdrmem_create; + gssrpc_xdrrec_create; + gssrpc_xdrrec_endofrecord; + gssrpc_xdrrec_eof; + gssrpc_xdrrec_skiprecord; + gssrpc_xdrstdio_create; + gssrpc_xprt_register; + gssrpc_xprt_unregister; +}; diff --git a/krb5/libexec/Makefile.inc b/krb5/libexec/Makefile.inc index bcc6d4b1c21e..6ce709d08304 100644 --- a/krb5/libexec/Makefile.inc +++ b/krb5/libexec/Makefile.inc @@ -9,4 +9,5 @@ .include "../Makefile.inc" +PACKAGE?= kerberos-kdc BINDIR?= /usr/libexec diff --git a/krb5/libexec/kadmind/Makefile b/krb5/libexec/kadmind/Makefile index bb572a32445f..a845851f708e 100644 --- a/krb5/libexec/kadmind/Makefile +++ b/krb5/libexec/kadmind/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include "../Makefile.inc" PROG= kadmind diff --git a/krb5/libexec/kdc/Makefile b/krb5/libexec/kdc/Makefile index a990666d9338..ac5ada19eb37 100644 --- a/krb5/libexec/kdc/Makefile +++ b/krb5/libexec/kdc/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include "../Makefile.inc" PROG= krb5kdc diff --git a/krb5/libexec/kprop/Makefile b/krb5/libexec/kprop/Makefile index 74a56232f6bb..1294d9014ee4 100644 --- a/krb5/libexec/kprop/Makefile +++ b/krb5/libexec/kprop/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include "../Makefile.inc" PROG= kprop diff --git a/krb5/libexec/kpropd/Makefile b/krb5/libexec/kpropd/Makefile index 2fb2bfdff228..e7ffe5a26016 100644 --- a/krb5/libexec/kpropd/Makefile +++ b/krb5/libexec/kpropd/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kpropd LIBADD= kprop_util kdb5 kadm5clnt_mit gssrpc gssapi_krb5 krb5 k5crypto \ diff --git a/krb5/libexec/kproplog/Makefile b/krb5/libexec/kproplog/Makefile index 533b6fdaa5c2..81405260a06e 100644 --- a/krb5/libexec/kproplog/Makefile +++ b/krb5/libexec/kproplog/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kproplog LIBADD= kadm5srv_mit kdb5 gssrpc gssapi_krb5 krb5 k5crypto com_err \ krb5support sys diff --git a/krb5/plugins/Makefile.inc b/krb5/plugins/Makefile.inc index 846770a801e0..e888f79acd49 100644 --- a/krb5/plugins/Makefile.inc +++ b/krb5/plugins/Makefile.inc @@ -7,6 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # +PACKAGE?= kerberos-kdc MK_INSTALLLIB= no SHLIB_NAME?= ${LIB}.so.${SHLIB_MAJOR} PLUGINSDIR= ${LIBDIR_BASE}/krb5/plugins diff --git a/krb5/plugins/audit/Makefile b/krb5/plugins/audit/Makefile index 507cde261300..f85e5d1a81a5 100644 --- a/krb5/plugins/audit/Makefile +++ b/krb5/plugins/audit/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -16,6 +14,7 @@ PACKAGE= krb5 LIB= kdc_j_encode LIBDIR= ${PLUGINSDIR}/audit LDFLAGS=-Wl,--no-undefined +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/plugins/audit diff --git a/krb5/plugins/audit/version.map b/krb5/plugins/audit/version.map new file mode 100644 index 000000000000..b6d3368df002 --- /dev/null +++ b/krb5/plugins/audit/version.map @@ -0,0 +1,10 @@ +KRB5_AUDIT_1.0 { + global: + kau_j_kdc_stop; + kau_j_kdc_start; + kau_j_as_req; + kau_j_tgs_req; + kau_j_tgs_s4u2self; + kau_j_tgs_s4u2proxy; + kau_j_tgs_u2u; +}; diff --git a/krb5/plugins/k5tls/Makefile b/krb5/plugins/k5tls/Makefile index 8af5efb06b80..30738a70e71d 100644 --- a/krb5/plugins/k5tls/Makefile +++ b/krb5/plugins/k5tls/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -18,6 +16,7 @@ SHLIBDIR= ${LIBDIR} LIB= k5tls LDFLAGS=-Wl,--no-undefined LIBADD= krb5 krb5profile krb5support ssl crypto k5crypto com_err sys +VERSION_MAP= ${.CURDIR}/version.map SRCS= notls.c \ openssl.c diff --git a/krb5/plugins/k5tls/version.map b/krb5/plugins/k5tls/version.map new file mode 100644 index 000000000000..802628aaaf63 --- /dev/null +++ b/krb5/plugins/k5tls/version.map @@ -0,0 +1,4 @@ +KRB5_K5TLS_1.0 { + global: + tls_k5tls_initvt; +}; diff --git a/krb5/plugins/kdb/db2/Makefile b/krb5/plugins/kdb/db2/Makefile index 7526283f37be..e9429bc03de1 100644 --- a/krb5/plugins/kdb/db2/Makefile +++ b/krb5/plugins/kdb/db2/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -18,6 +16,7 @@ SHLIBDIR= ${LIBDIR} LIB= db2 LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile krb5 com_err k5crypto kadm5srv_mit kdb5 gssrpc gssapi_krb5 krb5support +VERSION_MAP= ${.CURDIR}/version.map SRCS= \ adb_openclose.c \ diff --git a/krb5/plugins/kdb/db2/version.map b/krb5/plugins/kdb/db2/version.map new file mode 100644 index 000000000000..aa524e506fb8 --- /dev/null +++ b/krb5/plugins/kdb/db2/version.map @@ -0,0 +1,109 @@ +KRB5_DB2_1.0 { + global: + __default_hash; + __kdb2_add_bigpage; + __kdb2_add_ovflpage; + __kdb2_addel; + __kdb2_big_delete; + __kdb2_big_insert; + __kdb2_big_keydata; + __kdb2_big_return; + __kdb2_bt_close; + __kdb2_bt_cmp; + __kdb2_bt_defcmp; + __kdb2_bt_defpfx; + __kdb2_bt_deleaf; + __kdb2_bt_delete; + __kdb2_bt_dmpage; + __kdb2_bt_dnpage; + __kdb2_bt_dpage; + __kdb2_bt_dump; + __kdb2_bt_fd; + __kdb2_bt_free; + __kdb2_bt_get; + __kdb2_bt_new; + __kdb2_bt_open; + __kdb2_bt_pgin; + __kdb2_bt_pgout; + __kdb2_bt_put; + __kdb2_bt_relink; + __kdb2_bt_ret; + __kdb2_bt_search; + __kdb2_bt_seq; + __kdb2_bt_setcur; + __kdb2_bt_split; + __kdb2_bt_stat; + __kdb2_bt_sync; + __kdb2_call_hash; + __kdb2_cursor_creat; + __kdb2_dbpanic; + __kdb2_delete_page; + __kdb2_delpair; + __kdb2_expand_table; + __kdb2_find_bigpair; + __kdb2_free_ovflpage; + __kdb2_get_bigkey; + __kdb2_get_item; + __kdb2_get_item_done; + __kdb2_get_item_first; + __kdb2_get_item_next; + __kdb2_get_item_reset; + __kdb2_get_page; + __kdb2_hash_open; + __kdb2_ibitmap; + __kdb2_log2; + __kdb2_new_page; + __kdb2_ovfl_delete; + __kdb2_ovfl_get; + __kdb2_ovfl_put; + __kdb2_pgin_routine; + __kdb2_pgout_routine; + __kdb2_put_page; + __kdb2_rec_close; + __kdb2_rec_delete; + __kdb2_rec_dleaf; + __kdb2_rec_fd; + __kdb2_rec_fmap; + __kdb2_rec_fpipe; + __kdb2_rec_get; + __kdb2_rec_iput; + __kdb2_rec_open; + __kdb2_rec_put; + __kdb2_rec_ret; + __kdb2_rec_search; + __kdb2_rec_seq; + __kdb2_rec_sync; + __kdb2_rec_vmap; + __kdb2_rec_vpipe; + __kdb2_split_page; + kdb2_dbm_clearerr; + kdb2_dbm_close; + kdb2_dbm_delete; + kdb2_dbm_dirfno; + kdb2_dbm_error; + kdb2_dbm_fetch; + kdb2_dbm_firstkey; + kdb2_dbm_nextkey; + kdb2_dbm_open; + kdb2_dbm_store; + kdb2_dbminit; + kdb2_dbopen; + kdb2_delete; + kdb2_fetch; + kdb2_firstkey; + kdb2_hcreate; + kdb2_hdestroy; + kdb2_hsearch; + kdb2_mpool_close; + kdb2_mpool_delete; + kdb2_mpool_filter; + kdb2_mpool_get; + kdb2_mpool_new; + kdb2_mpool_open; + kdb2_mpool_put; + kdb2_mpool_stat; + kdb2_mpool_sync; + kdb2_nextkey; + kdb2_store; + kdb_function_table; +}; diff --git a/krb5/plugins/preauth/Makefile.inc b/krb5/plugins/preauth/Makefile.inc index aecd360f50e7..8a713e4d0856 100644 --- a/krb5/plugins/preauth/Makefile.inc +++ b/krb5/plugins/preauth/Makefile.inc @@ -7,6 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # +PACKAGE?= kerberos-kdc LIBDIR= ${PLUGINSDIR}/preauth SHLIBDIR= ${LIBDIR} diff --git a/krb5/plugins/preauth/otp/Makefile b/krb5/plugins/preauth/otp/Makefile index 9222f9785a80..48fc35db0727 100644 --- a/krb5/plugins/preauth/otp/Makefile +++ b/krb5/plugins/preauth/otp/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= otp LIBDIR= ${PLUGINSDIR}/preauth LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile krad verto krb5 k5crypto com_err krb5support m +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/plugins/preauth/otp diff --git a/krb5/plugins/preauth/otp/version.map b/krb5/plugins/preauth/otp/version.map new file mode 100644 index 000000000000..9d2ee5ea7213 --- /dev/null +++ b/krb5/plugins/preauth/otp/version.map @@ -0,0 +1,4 @@ +KRB5_PREAUTH_OTP { + global: + kdcpreauth_otp_initvt; +}; diff --git a/krb5/plugins/preauth/pkinit/Makefile b/krb5/plugins/preauth/pkinit/Makefile index f2a76d1e33da..7d227aca5420 100644 --- a/krb5/plugins/preauth/pkinit/Makefile +++ b/krb5/plugins/preauth/pkinit/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= pkinit LIBDIR= ${PLUGINSDIR}/preauth LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile krb5 com_err k5crypto crypto krb5support +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/plugins/preauth/pkinit diff --git a/krb5/plugins/preauth/pkinit/version.map b/krb5/plugins/preauth/pkinit/version.map new file mode 100644 index 000000000000..39a9f81f83ef --- /dev/null +++ b/krb5/plugins/preauth/pkinit/version.map @@ -0,0 +1,5 @@ +KRB5_PREAUTH_PKINIT_1.0 { + global: + clpreauth_pkinit_initvt; + kdcpreauth_pkinit_initvt; +}; diff --git a/krb5/plugins/preauth/spake/Makefile b/krb5/plugins/preauth/spake/Makefile index a5d9179f8adc..3aa375cb5100 100644 --- a/krb5/plugins/preauth/spake/Makefile +++ b/krb5/plugins/preauth/spake/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= spake LIBDIR= ${PLUGINSDIR}/preauth LDFLAGS=-Wl,--no-undefined LIBADD= krb5profile krb5 k5crypto com_err krb5support crypto sys +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/plugins/preauth/spake diff --git a/krb5/plugins/preauth/spake/version.map b/krb5/plugins/preauth/spake/version.map new file mode 100644 index 000000000000..7763f289c80d --- /dev/null +++ b/krb5/plugins/preauth/spake/version.map @@ -0,0 +1,5 @@ +KRB5_PLUGINS_SPAKE_1.0 { + global: + clpreauth_spake_initvt; + kdcpreauth_spake_initvt; +}; diff --git a/krb5/plugins/preauth/test/Makefile b/krb5/plugins/preauth/test/Makefile index 71b7200b2039..99f632c0cb17 100644 --- a/krb5/plugins/preauth/test/Makefile +++ b/krb5/plugins/preauth/test/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - .include <src.opts.mk> .include "../Makefile.inc" @@ -17,6 +15,7 @@ LIB= test LIBDIR= ${PLUGINSDIR}/preauth LDFLAGS=-Wl,--no-undefined LIBADD= krb5 k5crypto com_err krb5support +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/plugins/preauth/test diff --git a/krb5/plugins/preauth/test/version.map b/krb5/plugins/preauth/test/version.map new file mode 100644 index 000000000000..e27e14869833 --- /dev/null +++ b/krb5/plugins/preauth/test/version.map @@ -0,0 +1,5 @@ +KRB5_PREAUTH_TEST_1.0 { + global: + clpreauth_test_initvt; + kdcpreauth_test_initvt; +}; diff --git a/krb5/usr.bin/Makefile.inc b/krb5/usr.bin/Makefile.inc index ea8e5ee805bb..f27bd78cd54c 100644 --- a/krb5/usr.bin/Makefile.inc +++ b/krb5/usr.bin/Makefile.inc @@ -9,4 +9,5 @@ .include "../Makefile.inc" +PACKAGE?= kerberos BINDIR?= /usr/bin diff --git a/krb5/usr.bin/gss-client/Makefile b/krb5/usr.bin/gss-client/Makefile index f2b5285ac3bb..acd67f9c17c6 100644 --- a/krb5/usr.bin/gss-client/Makefile +++ b/krb5/usr.bin/gss-client/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= gss-client LIBADD= gssapi_krb5 krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/kadmin/Makefile b/krb5/usr.bin/kadmin/Makefile index 95fcea307827..36b7378dee11 100644 --- a/krb5/usr.bin/kadmin/Makefile +++ b/krb5/usr.bin/kadmin/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kadmin LIBADD= kadmin_common edit kadm5clnt_mit gssrpc gssapi_krb5 krb5 k5crypto \ diff --git a/krb5/usr.bin/kdestroy/Makefile b/krb5/usr.bin/kdestroy/Makefile index 4ec2ef4a1392..e3f493ffdc60 100644 --- a/krb5/usr.bin/kdestroy/Makefile +++ b/krb5/usr.bin/kdestroy/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kdestroy LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/kinit/Makefile b/krb5/usr.bin/kinit/Makefile index 8aff9af3687b..3d1285137f85 100644 --- a/krb5/usr.bin/kinit/Makefile +++ b/krb5/usr.bin/kinit/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kinit LIBADD= kadm5srv_mit kdb5 gssrpc gssapi_krb5 krb5 k5crypto com_err \ diff --git a/krb5/usr.bin/klist/Makefile b/krb5/usr.bin/klist/Makefile index a5d6cecbaddb..3094a3b69d4b 100644 --- a/krb5/usr.bin/klist/Makefile +++ b/krb5/usr.bin/klist/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= klist LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/kpasswd/Makefile b/krb5/usr.bin/kpasswd/Makefile index 431cf239928e..e4d7d1e8ab84 100644 --- a/krb5/usr.bin/kpasswd/Makefile +++ b/krb5/usr.bin/kpasswd/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kpasswd LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/ksu/Makefile b/krb5/usr.bin/ksu/Makefile index 4ddfa8096773..37a4c166aec6 100644 --- a/krb5/usr.bin/ksu/Makefile +++ b/krb5/usr.bin/ksu/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= ksu .if defined(ENABLE_SUID_K5SU) BINMODE=4555 diff --git a/krb5/usr.bin/kswitch/Makefile b/krb5/usr.bin/kswitch/Makefile index 1e9853012ae5..10298f34a9d4 100644 --- a/krb5/usr.bin/kswitch/Makefile +++ b/krb5/usr.bin/kswitch/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kswitch LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/ktutil/Makefile b/krb5/usr.bin/ktutil/Makefile index abe02965de4d..6bcb4877ed6f 100644 --- a/krb5/usr.bin/ktutil/Makefile +++ b/krb5/usr.bin/ktutil/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= ktutil LIBADD= edit krb5 k5crypto com_err krb5profile krb5support krb5ss tinfow sys diff --git a/krb5/usr.bin/kvno/Makefile b/krb5/usr.bin/kvno/Makefile index 203839624414..0a43765e53f4 100644 --- a/krb5/usr.bin/kvno/Makefile +++ b/krb5/usr.bin/kvno/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= kvno LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/sclient/Makefile b/krb5/usr.bin/sclient/Makefile index f27dad42fa08..8a3cc38fe3b6 100644 --- a/krb5/usr.bin/sclient/Makefile +++ b/krb5/usr.bin/sclient/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= sclient LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.bin/sim_client/Makefile b/krb5/usr.bin/sim_client/Makefile index ecdf9ac8885e..3e5ea72407bc 100644 --- a/krb5/usr.bin/sim_client/Makefile +++ b/krb5/usr.bin/sim_client/Makefile @@ -7,8 +7,6 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 - PROG= sim_client LIBADD= krb5 k5crypto com_err krb5profile krb5support sys diff --git a/krb5/usr.sbin/gss-server/Makefile b/krb5/usr.sbin/gss-server/Makefile index 9e80b466d427..c42740045ac4 100644 --- a/krb5/usr.sbin/gss-server/Makefile +++ b/krb5/usr.sbin/gss-server/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos PROG= gss-server diff --git a/krb5/usr.sbin/kadmin.local/Makefile b/krb5/usr.sbin/kadmin.local/Makefile index 7e89d0953683..4b99f490bd7b 100644 --- a/krb5/usr.sbin/kadmin.local/Makefile +++ b/krb5/usr.sbin/kadmin.local/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-kdc PROG= kadmin.local diff --git a/krb5/usr.sbin/kdb5_util/Makefile b/krb5/usr.sbin/kdb5_util/Makefile index 6a7b66dc205c..5b3d3ecc3410 100644 --- a/krb5/usr.sbin/kdb5_util/Makefile +++ b/krb5/usr.sbin/kdb5_util/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-kdc PROG= kdb5_util diff --git a/krb5/usr.sbin/sim_server/Makefile b/krb5/usr.sbin/sim_server/Makefile index 793a6ad421b1..adaf8d1f087f 100644 --- a/krb5/usr.sbin/sim_server/Makefile +++ b/krb5/usr.sbin/sim_server/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos PROG= sim_server diff --git a/krb5/usr.sbin/sserver/Makefile b/krb5/usr.sbin/sserver/Makefile index 3b205b490a5f..e4e85b28157e 100644 --- a/krb5/usr.sbin/sserver/Makefile +++ b/krb5/usr.sbin/sserver/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos PROG= sserver diff --git a/krb5/util/build-tools/Makefile b/krb5/util/build-tools/Makefile index c33d47f70c8f..1a6a373f0e7f 100644 --- a/krb5/util/build-tools/Makefile +++ b/krb5/util/build-tools/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-lib .include "../Makefile.inc" diff --git a/krb5/util/compile_et/Makefile b/krb5/util/compile_et/Makefile index 57eb2f614802..03446f2d7d1c 100644 --- a/krb5/util/compile_et/Makefile +++ b/krb5/util/compile_et/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos .include "../Makefile.inc" diff --git a/krb5/util/et/Makefile b/krb5/util/et/Makefile index 4457cd199801..5d0c2a3e3ca5 100644 --- a/krb5/util/et/Makefile +++ b/krb5/util/et/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5-lib +PACKAGE= kerberos-lib .include <src.opts.mk> @@ -18,6 +18,7 @@ LIB= com_err LDFLAGS=-Wl,--no-undefined INCSDIR=${INCLUDEDIR} LIBADD= krb5support +VERSION_MAP= ${.CURDIR}/version.map SRCS= com_err.c \ diff --git a/krb5/util/et/version.map b/krb5/util/et/version.map new file mode 100644 index 000000000000..be846b139ebc --- /dev/null +++ b/krb5/util/et/version.map @@ -0,0 +1,12 @@ +KRB5_ET_1.0 { + global: + add_error_table; + com_err; + com_err_va; + error_message; + error_table_name; + error_table_name_r; + remove_error_table; + reset_com_err_hook; + set_com_err_hook; +}; diff --git a/krb5/util/profile/Makefile b/krb5/util/profile/Makefile index 24e06e8c5024..a921e29150bb 100644 --- a/krb5/util/profile/Makefile +++ b/krb5/util/profile/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-lib .include <src.opts.mk> @@ -15,6 +15,7 @@ PACKAGE= krb5 LIB= krb5profile LIBADD= com_err krb5support +VERSION_MAP= ${.CURDIR}/version.map SRCS= prof_file.c \ prof_get.c \ diff --git a/krb5/util/profile/version.map b/krb5/util/profile/version.map new file mode 100644 index 000000000000..d7fd0059983d --- /dev/null +++ b/krb5/util/profile/version.map @@ -0,0 +1,33 @@ +KRB5_PROFILE_1.0 { + global: + et_prof_error_table; + initialize_prof_error_table; + profile_abandon; + profile_add_relation; + profile_clear_relation; + profile_flush; + profile_free_list; + profile_get_boolean; + profile_get_integer; + profile_get_relation_names; + profile_get_string; + profile_get_subsection_names; + profile_get_values; + profile_init; + profile_init_flags; + profile_init_path; + profile_init_vtable; + profile_iterator; + profile_iterator_create; + profile_iterator_free; + profile_release; + profile_release_string; + profile_rename_section; + profile_ser_externalize; + profile_ser_internalize; + profile_ser_size; + profile_update_relation; + profile_flush_to_file; + profile_flush_to_buffer; + profile_free_buffer; +}; diff --git a/krb5/util/ss/Makefile b/krb5/util/ss/Makefile index 600d125a7853..e7e025184284 100644 --- a/krb5/util/ss/Makefile +++ b/krb5/util/ss/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-lib .include <src.opts.mk> diff --git a/krb5/util/support/Makefile b/krb5/util/support/Makefile index 9ba1b8169d8e..bba65bcd89c1 100644 --- a/krb5/util/support/Makefile +++ b/krb5/util/support/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5-lib +PACKAGE= kerberos-lib .include <src.opts.mk> @@ -16,6 +16,7 @@ PACKAGE= krb5-lib LIB= krb5support # SHLIB_MAJOR= 0 LDFLAGS=-Wl,--no-undefined +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/util/support diff --git a/krb5/util/support/version.map b/krb5/util/support/version.map new file mode 100644 index 000000000000..f4de213d33d9 --- /dev/null +++ b/krb5/util/support/version.map @@ -0,0 +1,102 @@ +KRB5_SUPPORT_1.0 { + global: + k5_base64_decode; + k5_base64_encode; + k5_bcmp; + k5_buf_init_fixed; + k5_buf_init_dynamic; + k5_buf_init_dynamic_zap; + k5_buf_add; + k5_buf_add_len; + k5_buf_add_fmt; + k5_buf_add_vfmt; + k5_buf_cstring; + k5_buf_get_space; + k5_buf_truncate; + k5_buf_status; + k5_buf_free; + k5_set_error; + k5_vset_error; + k5_get_error; + k5_free_error; + k5_clear_error; + k5_set_error_info_callout_fn; + k5_hashtab_add; + k5_hashtab_create; + k5_hashtab_free; + k5_hashtab_get; + k5_hashtab_remove; + k5_hex_decode; + k5_hex_encode; + k5_json_array_add; + k5_json_array_create; + k5_json_array_fmt; + k5_json_array_get; + k5_json_array_length; + k5_json_array_set; + k5_json_bool_create; + k5_json_bool_value; + k5_json_decode; + k5_json_encode; + k5_json_get_tid; + k5_json_null_create; + k5_json_null_create_val; + k5_json_number_create; + k5_json_number_value; + k5_json_object_count; + k5_json_object_create; + k5_json_object_get; + k5_json_object_iterate; + k5_json_object_set; + k5_json_release; + k5_json_retain; + k5_json_string_create; + k5_json_string_create_base64; + k5_json_string_create_len; + k5_json_string_unbase64; + k5_json_string_utf8; + k5_os_mutex_init; + k5_os_mutex_destroy; + k5_os_mutex_lock; + k5_os_mutex_unlock; + k5_once; + k5_path_isabs; + k5_path_join; + k5_path_split; + k5_siphash24; + k5_strerror_r; + k5_utf8_to_utf16le; + k5_utf16le_to_utf8; + k5_dir_filenames; + k5_free_filenames; + krb5int_key_register; + krb5int_key_delete; + krb5int_getspecific; + krb5int_setspecific; + krb5int_getaddrinfo; + krb5int_freeaddrinfo; + krb5int_gai_strerror; + krb5int_getnameinfo; + krb5int_in6addr_any; + krb5int_pthread_loaded; + krb5int_open_plugin; + krb5int_close_plugin; + krb5int_get_plugin_data; + krb5int_get_plugin_func; + krb5int_open_plugin_dirs; + krb5int_close_plugin_dirs; + krb5int_get_plugin_dir_data; + krb5int_get_plugin_dir_func; + krb5int_free_plugin_dir_data; + krb5int_free_plugin_dir_func; + krb5int_mutex_alloc; + krb5int_mutex_free; + krb5int_mutex_lock; + krb5int_mutex_unlock; + krb5int_gmt_mktime; + krb5int_ucs4_to_utf8; + krb5int_utf8_to_ucs4; + krb5int_utf8_lentab; + krb5int_utf8_mintab; + krb5int_zap; +}; diff --git a/krb5/util/verto/Makefile b/krb5/util/verto/Makefile index 57367e5284e0..8f02d5f897f4 100644 --- a/krb5/util/verto/Makefile +++ b/krb5/util/verto/Makefile @@ -7,7 +7,7 @@ # under sponsorship from the FreeBSD Foundation. # -PACKAGE= krb5 +PACKAGE= kerberos-lib .include <src.opts.mk> @@ -15,6 +15,7 @@ PACKAGE= krb5 LIB= verto # SHLIB_MAJOR= 0 +VERSION_MAP= ${.CURDIR}/version.map .PATH: ${KRB5_DIR}/util/verto diff --git a/krb5/util/verto/libverto.exports b/krb5/util/verto/libverto.exports new file mode 100644 index 000000000000..3745d5014653 --- /dev/null +++ b/krb5/util/verto/libverto.exports @@ -0,0 +1,33 @@ +verto_add_child +verto_add_idle +verto_add_io +verto_add_signal +verto_add_timeout +verto_break +verto_cleanup +verto_convert_module +verto_default +verto_del +verto_fire +verto_free +verto_get_ctx +verto_get_fd +verto_get_fd_state +verto_get_flags +verto_get_interval +verto_get_private +verto_get_proc +verto_get_proc_status +verto_get_signal +verto_get_supported_types +verto_get_type +verto_new +verto_reinitialize +verto_run +verto_run_once +verto_set_allocator +verto_set_default +verto_set_fd_state +verto_set_flags +verto_set_private +verto_set_proc_status diff --git a/krb5/util/verto/version.map b/krb5/util/verto/version.map new file mode 100644 index 000000000000..5fc734e25d3a --- /dev/null +++ b/krb5/util/verto/version.map @@ -0,0 +1,36 @@ +KRB5_VERTO_1.0 { + global: + verto_add_child; + verto_add_idle; + verto_add_io; + verto_add_signal; + verto_add_timeout; + verto_break; + verto_cleanup; + verto_convert_module; + verto_default; + verto_del; + verto_fire; + verto_free; + verto_get_ctx; + verto_get_fd; + verto_get_fd_state; + verto_get_flags; + verto_get_interval; + verto_get_private; + verto_get_proc; + verto_get_proc_status; + verto_get_signal; + verto_get_supported_types; + verto_get_type; + verto_new; + verto_reinitialize; + verto_run; + verto_run_once; + verto_set_allocator; + verto_set_default; + verto_set_fd_state; + verto_set_flags; + verto_set_private; + verto_set_proc_status; +}; diff --git a/lib/libc/gen/fdopendir.c b/lib/libc/gen/fdopendir.c index df6709fbcb85..9393cbe28f85 100644 --- a/lib/libc/gen/fdopendir.c +++ b/lib/libc/gen/fdopendir.c @@ -48,8 +48,16 @@ DIR * fdopendir(int fd) { + int flags, rc; - if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + flags = _fcntl(fd, F_GETFD, 0); + if (flags == -1) return (NULL); + + if ((flags & FD_CLOEXEC) == 0) { + rc = _fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + if (rc == -1) + return (NULL); + } return (__opendir_common(fd, DTF_HIDEW | DTF_NODUP, true)); } diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index b29fa1cdd845..216fc9bcf9a4 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -74,8 +74,10 @@ #define SPRINTF(x) ((size_t)sprintf x) +#ifdef DEBUG static const char AskedForGot[] = "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; +#endif #ifdef RESOLVSORT static void addrsort(char **, int, res_state); @@ -299,8 +301,10 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, switch (type) { case T_PTR: if (strcasecmp(tname, bp) != 0) { +#ifdef DEBUG syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, qname, bp); +#endif cp += n; continue; /* XXX - had_error++ ? */ } @@ -347,8 +351,10 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, case T_A: case T_AAAA: if (strcasecmp(he->h_name, bp) != 0) { +#ifdef DEBUG syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, he->h_name, bp); +#endif cp += n; continue; /* XXX - had_error++ ? */ } diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h index f049d6817b7a..39a1b5f1486f 100644 --- a/lib/libc/net/res_config.h +++ b/lib/libc/net/res_config.h @@ -1,5 +1,5 @@ -#define DEBUG 1 /* enable debugging code (needed for dig) */ +//#define DEBUG /* enable debugging code */ #define RESOLVSORT /* allow sorting of addresses in gethostbyname */ -#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DON'T NEED IT */ +//#define SUNSECURITY /* verify gethostbyaddr() calls */ #define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */ diff --git a/lib/libc/resolv/res_debug.h b/lib/libc/resolv/res_debug.h index dd048116fb49..ccae03e625aa 100644 --- a/lib/libc/resolv/res_debug.h +++ b/lib/libc/resolv/res_debug.h @@ -23,7 +23,7 @@ #ifndef DEBUG # define Dprint(cond, args) /*empty*/ # define DprintQ(cond, args, query, size) /*empty*/ -# define Aerror(statp, file, string, error, address) /*empty*/ +# define Aerror(statp, file, string, error, address, alen) /*empty*/ # define Perror(statp, file, string, error) /*empty*/ #else # define Dprint(cond, args) if (cond) {fprintf args;} else {} diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c index 70d6bc6d3bf2..71ab2dcb7038 100644 --- a/lib/libc/resolv/res_init.c +++ b/lib/libc/resolv/res_init.c @@ -108,12 +108,6 @@ #include "res_private.h" -/*% Options. Should all be left alone. */ -#define RESOLVSORT -#ifndef DEBUG -#define DEBUG -#endif - #ifdef SOLARIS2 #include <sys/systeminfo.h> #endif diff --git a/lib/libc/resolv/res_mkquery.c b/lib/libc/resolv/res_mkquery.c index 0c15def5d117..f6767a92375c 100644 --- a/lib/libc/resolv/res_mkquery.c +++ b/lib/libc/resolv/res_mkquery.c @@ -76,11 +76,6 @@ #include <string.h> #include "port_after.h" -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif - extern const char *_res_opcodes[]; /*% diff --git a/lib/libc/resolv/res_mkupdate.c b/lib/libc/resolv/res_mkupdate.c index e5a3cb702cda..3f595dc4ec08 100644 --- a/lib/libc/resolv/res_mkupdate.c +++ b/lib/libc/resolv/res_mkupdate.c @@ -48,10 +48,6 @@ #include "port_after.h" -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif #define MAXPORT 1024 static int getnum_str(u_char **, u_char *); diff --git a/lib/libc/resolv/res_query.c b/lib/libc/resolv/res_query.c index e9c628ad8d47..f26d59e522b4 100644 --- a/lib/libc/resolv/res_query.c +++ b/lib/libc/resolv/res_query.c @@ -81,11 +81,6 @@ #include <unistd.h> #include "port_after.h" -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif - #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else diff --git a/lib/libc/resolv/res_send.c b/lib/libc/resolv/res_send.c index 3fb627b83d55..08c3aed7f934 100644 --- a/lib/libc/resolv/res_send.c +++ b/lib/libc/resolv/res_send.c @@ -112,10 +112,6 @@ #include "un-namespace.h" -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif #include "res_debug.h" #include "res_private.h" @@ -138,15 +134,12 @@ static int send_dg(res_state, const u_char *, int, u_char *, int, int *, int, int, int *, int *); +#ifdef DEBUG static void Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *, int); static void Perror(const res_state, FILE *, const char *, int); -static int sock_eq(struct sockaddr *, struct sockaddr *); -#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) -static int pselect(int, void *, void *, void *, - struct timespec *, - const sigset_t *); #endif +static int sock_eq(struct sockaddr *, struct sockaddr *); void res_pquery(const res_state, const u_char *, int, FILE *); static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; @@ -302,7 +295,9 @@ res_nsend(res_state statp, #ifdef USE_KQUEUE int kq; #endif +#ifdef DEBUG char abuf[NI_MAXHOST]; +#endif /* No name servers or res_init() failure */ if (statp->nscount == 0 || EXT(statp).ext == NULL) { @@ -418,10 +413,10 @@ res_nsend(res_state statp, */ for (tries = 0; tries < statp->retry; tries++) { for (ns = 0; ns < statp->nscount; ns++) { - struct sockaddr *nsap; - int nsaplen; - nsap = get_nsaddr(statp, ns); - nsaplen = get_salen(nsap); + struct sockaddr *nsap = get_nsaddr(statp, ns); +#ifdef DEBUG + int nsaplen = get_salen(nsap); +#endif statp->_flags &= ~RES_F_LASTMASK; statp->_flags |= (ns << RES_F_LASTSHIFT); same_ns: @@ -1088,6 +1083,7 @@ send_dg(res_state statp, return (resplen); } +#ifdef DEBUG static void Aerror(const res_state statp, FILE *file, const char *string, int error, const struct sockaddr *address, int alen) @@ -1119,6 +1115,7 @@ Perror(const res_state statp, FILE *file, const char *string, int error) { string, strerror(error)); errno = save; } +#endif static int sock_eq(struct sockaddr *a, struct sockaddr *b) { @@ -1145,29 +1142,3 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) { return 0; } } - -#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) -/* XXX needs to move to the porting library. */ -static int -pselect(int nfds, void *rfds, void *wfds, void *efds, - struct timespec *tsp, const sigset_t *sigmask) -{ - struct timeval tv, *tvp; - sigset_t sigs; - int n; - - if (tsp) { - tvp = &tv; - tv = evTimeVal(*tsp); - } else - tvp = NULL; - if (sigmask) - sigprocmask(SIG_SETMASK, sigmask, &sigs); - n = select(nfds, rfds, wfds, efds, tvp); - if (sigmask) - sigprocmask(SIG_SETMASK, &sigs, NULL); - if (tsp) - *tsp = evTimeSpec(tv); - return (n); -} -#endif diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c index a0d7b71df782..49ec97eda39d 100644 --- a/lib/libc/stdio/fdopen.c +++ b/lib/libc/stdio/fdopen.c @@ -46,7 +46,7 @@ FILE * fdopen(int fd, const char *mode) { FILE *fp; - int flags, oflags, fdflags, tmp; + int flags, oflags, fdflags, rc, tmp; /* * File descriptors are a full int, but _file is only a short. @@ -76,9 +76,19 @@ fdopen(int fd, const char *mode) if ((fp = __sfp()) == NULL) return (NULL); - if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { - fp->_flags = 0; - return (NULL); + if ((oflags & O_CLOEXEC) != 0) { + tmp = _fcntl(fd, F_GETFD, 0); + if (tmp == -1) { + fp->_flags = 0; + return (NULL); + } + if ((tmp & FD_CLOEXEC) == 0) { + rc = _fcntl(fd, F_SETFD, tmp | FD_CLOEXEC); + if (rc == -1) { + fp->_flags = 0; + return (NULL); + } + } } fp->_flags = flags; diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index f0732b6d6741..048fd30b3193 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -55,7 +55,7 @@ freopen(const char * __restrict file, const char * __restrict mode, FILE * __restrict fp) { int f; - int dflags, flags, isopen, oflags, sverrno, wantfd; + int dflags, fdflags, flags, isopen, oflags, sverrno, wantfd; if ((flags = __sflags(mode, &oflags)) == 0) { sverrno = errno; @@ -113,8 +113,12 @@ freopen(const char * __restrict file, const char * __restrict mode, (void) ftruncate(fp->_file, (off_t)0); if (!(oflags & O_APPEND)) (void) _sseek(fp, (fpos_t)0, SEEK_SET); - if (oflags & O_CLOEXEC) - (void) _fcntl(fp->_file, F_SETFD, FD_CLOEXEC); + if ((oflags & O_CLOEXEC) != 0) { + fdflags = _fcntl(fp->_file, F_GETFD, 0); + if (fdflags != -1 && (fdflags & FD_CLOEXEC) == 0) + (void) _fcntl(fp->_file, F_SETFD, + fdflags | FD_CLOEXEC); + } f = fp->_file; isopen = 0; wantfd = -1; diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc index 5d0ce7765b63..647cbe6f40ba 100644 --- a/lib/libc/stdtime/Makefile.inc +++ b/lib/libc/stdtime/Makefile.inc @@ -18,6 +18,7 @@ CFLAGS.${src}+= -I${LIBC_SRCTOP}/stdtime CFLAGS.localtime.c+= -DALL_STATE -DTHREAD_SAFE .if ${MK_DETECT_TZ_CHANGES} != "no" CFLAGS.localtime.c+= -DDETECT_TZ_CHANGES +CFLAGS.Version.map+= -DDETECT_TZ_CHANGES .endif MAN+= ctime.3 strftime.3 strptime.3 time2posix.3 tzset.3 diff --git a/lib/libc/stdtime/Symbol.map b/lib/libc/stdtime/Symbol.map index 669d4d47907b..6a34cd3ea590 100644 --- a/lib/libc/stdtime/Symbol.map +++ b/lib/libc/stdtime/Symbol.map @@ -35,3 +35,9 @@ FBSD_1.8 { daylight; timezone; }; + +FBSDprivate_1.0 { +#ifdef DETECT_TZ_CHANGES + __tz_change_interval; +#endif +}; diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3 index f5d1fe5d5c7f..65617a117371 100644 --- a/lib/libc/string/memchr.3 +++ b/lib/libc/string/memchr.3 @@ -52,7 +52,10 @@ locates the first occurrence of (converted to an .Vt "unsigned char" ) in string -.Fa b . +.Fa b , +limited to at most +.Fa len +characters. .Pp The .Fn memrchr @@ -61,15 +64,18 @@ function behaves like except that it locates the last occurrence of .Fa c in string -.Fa b . +.Fa b , +limited to the first +.Fa len +characters. .Sh RETURN VALUES The .Fn memchr and .Fn memrchr -functions -return a pointer to the byte located, -or NULL if no such byte exists within +functions return a pointer to the byte located, or +.Dv NULL +if no such byte exists within .Fa len bytes. .Sh SEE ALSO diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile index c7a7f5b9436f..adb883cc5b9a 100644 --- a/lib/libc/tests/stdtime/Makefile +++ b/lib/libc/tests/stdtime/Makefile @@ -1,6 +1,9 @@ -.include <bsd.own.mk> +.include <src.opts.mk> ATF_TESTS_C+= strptime_test +.if ${MK_DETECT_TZ_CHANGES} != "no" +ATF_TESTS_C+= detect_tz_changes_test +.endif TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c new file mode 100644 index 000000000000..9722546747fd --- /dev/null +++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> +#include <sys/wait.h> + +#include <dlfcn.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#include <atf-c.h> + +static const time_t then = 1751328000; /* 2025-07-01 00:00:00 UTC */ +static const char *tz_change_interval_sym = "__tz_change_interval"; +static int *tz_change_interval_p; +static const int tz_change_interval = 3; +static int tz_change_timeout = 90; + +static bool debugging; + +static void +debug(const char *fmt, ...) +{ + va_list ap; + + if (debugging) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); + } +} + +static void +change_tz(const char *tzn) +{ + static const char *zfn = "/usr/share/zoneinfo"; + static const char *tfn = "root/etc/.localtime"; + static const char *dfn = "root/etc/localtime"; + ssize_t clen; + int zfd, sfd, dfd; + + ATF_REQUIRE((zfd = open(zfn, O_DIRECTORY | O_SEARCH)) >= 0); + ATF_REQUIRE((sfd = openat(zfd, tzn, O_RDONLY)) >= 0); + ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY)) >= 0); + do { + clen = copy_file_range(sfd, NULL, dfd, NULL, SSIZE_MAX, 0); + ATF_REQUIRE_MSG(clen != -1, "failed to copy %s/%s: %m", + zfn, tzn); + } while (clen > 0); + ATF_CHECK_EQ(0, close(dfd)); + ATF_CHECK_EQ(0, close(sfd)); + ATF_CHECK_EQ(0, close(zfd)); + ATF_REQUIRE_EQ(0, rename(tfn, dfn)); + debug("time zone %s installed", tzn); +} + +/* + * Test time zone change detection. + * + * The parent creates a chroot containing only /etc/localtime, initially + * set to UTC. It then forks a child which enters the chroot, repeatedly + * checks the current time zone, and prints it to stdout if it changes + * (including once on startup). Meanwhile, the parent waits for output + * from the child. Every time it receives a line of text from the child, + * it checks that it is as expected, then changes /etc/localtime within + * the chroot to the next case in the list. Once it reaches the end of + * the list, it closes a pipe to notify the child, which terminates. + * + * Note that ATF and / or Kyua may have set the timezone before the test + * case starts (even unintentionally). Therefore, we start the test only + * after we've received and discarded the first report from the child, + * which should come almost immediately on startup. + */ +ATF_TC(detect_tz_changes); +ATF_TC_HEAD(detect_tz_changes, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test timezone change detection"); + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "timeout", "600"); +} +ATF_TC_BODY(detect_tz_changes, tc) +{ + static const struct tzcase { + const char *tzfn; + const char *expect; + } tzcases[] = { + /* + * A handful of time zones and the expected result of + * strftime("%z (%Z)", tm) when that time zone is active + * and tm represents a date in the summer of 2025. + */ + { "America/Vancouver", "-0700 (PDT)" }, + { "America/New_York", "-0400 (EDT)" }, + { "Europe/London", "+0100 (BST)" }, + { "Europe/Paris", "+0200 (CEST)" }, + { "Asia/Kolkata", "+0530 (IST)" }, + { "Asia/Tokyo", "+0900 (JST)" }, + { "Australia/Canberra", "+1000 (AEST)" }, + { "UTC", "+0000 (UTC)" }, + { 0 }, + }; + char obuf[1024] = ""; + char ebuf[1024] = ""; + struct pollfd fds[3]; + int opd[2], epd[2], spd[2]; + time_t changed, now; + const struct tzcase *tzcase = NULL; + struct tm *tm; + size_t olen = 0, elen = 0; + ssize_t rlen; + long curoff = LONG_MIN; + pid_t pid; + int nfds, status; + + /* speed up the test if possible */ + tz_change_interval_p = dlsym(RTLD_SELF, tz_change_interval_sym); + if (tz_change_interval_p != NULL && + *tz_change_interval_p > tz_change_interval) { + debug("reducing detection interval from %d to %d", + *tz_change_interval_p, tz_change_interval); + *tz_change_interval_p = tz_change_interval; + tz_change_timeout = tz_change_interval * 3; + } + /* prepare chroot */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + change_tz("UTC"); + time(&changed); + /* output, error, sync pipes */ + if (pipe(opd) != 0 || pipe(epd) != 0 || pipe(spd) != 0) + atf_tc_fail("failed to pipe"); + /* fork child */ + if ((pid = fork()) < 0) + atf_tc_fail("failed to fork"); + if (pid == 0) { + /* child */ + dup2(opd[1], STDOUT_FILENO); + close(opd[0]); + close(opd[1]); + dup2(epd[1], STDERR_FILENO); + close(epd[0]); + close(epd[1]); + close(spd[0]); + unsetenv("TZ"); + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + fds[0].fd = spd[1]; + fds[0].events = POLLIN; + for (;;) { + ATF_REQUIRE(poll(fds, 1, 100) >= 0); + if (fds[0].revents & POLLHUP) { + /* parent closed sync pipe */ + _exit(0); + } + ATF_REQUIRE((tm = localtime(&then)) != NULL); + if (tm->tm_gmtoff == curoff) + continue; + olen = strftime(obuf, sizeof(obuf), "%z (%Z)", tm); + ATF_REQUIRE(olen > 0); + fprintf(stdout, "%s\n", obuf); + fflush(stdout); + curoff = tm->tm_gmtoff; + } + _exit(2); + } + /* parent */ + close(opd[1]); + close(epd[1]); + close(spd[1]); + /* receive output until child terminates */ + fds[0].fd = opd[0]; + fds[0].events = POLLIN; + fds[1].fd = epd[0]; + fds[1].events = POLLIN; + fds[2].fd = spd[0]; + fds[2].events = POLLIN; + nfds = 3; + for (;;) { + ATF_REQUIRE(poll(fds, 3, 1000) >= 0); + time(&now); + if (fds[0].revents & POLLIN && olen < sizeof(obuf)) { + rlen = read(opd[0], obuf + olen, sizeof(obuf) - olen); + ATF_REQUIRE(rlen >= 0); + olen += rlen; + } + if (olen > 0) { + ATF_REQUIRE_EQ('\n', obuf[olen - 1]); + obuf[--olen] = '\0'; + /* tzcase will be NULL at first */ + if (tzcase != NULL) { + debug("%s", obuf); + ATF_REQUIRE_STREQ(tzcase->expect, obuf); + debug("change to %s detected after %d s", + tzcase->tzfn, (int)(now - changed)); + if (tz_change_interval_p != NULL) { + ATF_CHECK((int)(now - changed) >= + *tz_change_interval_p - 1); + ATF_CHECK((int)(now - changed) <= + *tz_change_interval_p + 1); + } + } + olen = 0; + /* first / next test case */ + if (tzcase == NULL) + tzcase = tzcases; + else + tzcase++; + if (tzcase->tzfn == NULL) { + /* test is over */ + break; + } + change_tz(tzcase->tzfn); + changed = now; + } + if (fds[1].revents & POLLIN && elen < sizeof(ebuf)) { + rlen = read(epd[0], ebuf + elen, sizeof(ebuf) - elen); + ATF_REQUIRE(rlen >= 0); + elen += rlen; + } + if (elen > 0) { + ATF_REQUIRE_EQ(elen, fwrite(ebuf, 1, elen, stderr)); + elen = 0; + } + if (nfds > 2 && fds[2].revents & POLLHUP) { + /* child closed sync pipe */ + break; + } + /* + * The timeout for this test case is set to 10 minutes, + * because it can take that long to run with the default + * 61-second interval. However, each individual tzcase + * entry should not take much longer than the detection + * interval to test, so we can detect a problem long + * before Kyua terminates us. + */ + if ((now - changed) > tz_change_timeout) { + close(spd[0]); + if (tz_change_interval_p == NULL && + tzcase == tzcases) { + /* + * The most likely explanation in this + * case is that libc was built without + * time zone change detection. + */ + atf_tc_skip("time zone change detection " + "does not appear to be enabled"); + } + atf_tc_fail("timed out waiting for change to %s " + "to be detected", tzcase->tzfn); + } + } + close(opd[0]); + close(epd[0]); + close(spd[0]); /* this will wake up and terminate the child */ + if (olen > 0) + ATF_REQUIRE_EQ(olen, fwrite(obuf, 1, olen, stdout)); + if (elen > 0) + ATF_REQUIRE_EQ(elen, fwrite(ebuf, 1, elen, stderr)); + ATF_REQUIRE_EQ(pid, waitpid(pid, &status, 0)); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(0, WEXITSTATUS(status)); +} + +ATF_TP_ADD_TCS(tp) +{ + debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") && + isatty(STDERR_FILENO); + ATF_TP_ADD_TC(tp, detect_tz_changes); + return (atf_no_error()); +} diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index 0d85ed468284..786d5647d993 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -277,13 +277,16 @@ conn_t * fetch_reopen(int sd) { conn_t *conn; + int flags; int opt = 1; /* allocate and fill connection structure */ if ((conn = calloc(1, sizeof(*conn))) == NULL) return (NULL); - fcntl(sd, F_SETFD, FD_CLOEXEC); - setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt); + flags = fcntl(sd, F_GETFD); + if (flags != -1 && (flags & FD_CLOEXEC) == 0) + (void)fcntl(sd, F_SETFD, flags | FD_CLOEXEC); + (void)setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); conn->sd = sd; ++conn->ref; return (conn); diff --git a/lib/libpam/modules/pam_krb5/Makefile b/lib/libpam/modules/pam_krb5/Makefile index b537bf37b7f3..c1792b5fb61d 100644 --- a/lib/libpam/modules/pam_krb5/Makefile +++ b/lib/libpam/modules/pam_krb5/Makefile @@ -32,7 +32,7 @@ SRCDIR= ${SRCTOP}/contrib/pam-krb5 ${SRCDIR}/pam-util \ ${SRCDIR} -PACKAGE= krb5 +PACKAGE= kerberos LIB= pam_krb5 LIBADD= com_err krb5 diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index e4123fe02211..d8e60075e103 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -3348,6 +3348,11 @@ pfctl_clear_tstats(struct pfctl_handle *h, const struct pfr_table *filter, return (e.error); } +static struct snl_attr_parser ap_clr_addrs[] = { + { .type = PF_T_NBR_DELETED, .off = 0, .cb = snl_attr_get_uint64 }, +}; +SNL_DECLARE_PARSER(clr_addrs_parser, struct genlmsghdr, snl_f_p_empty, ap_clr_addrs); + int pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter, int *ndel, int flags) @@ -3380,7 +3385,7 @@ pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter, return (ENXIO); while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { - if (!snl_parse_nlmsg(&h->ss, hdr, &tstats_clr_parser, &del)) + if (!snl_parse_nlmsg(&h->ss, hdr, &clr_addrs_parser, &del)) continue; if (ndel) *ndel = (uint32_t)del; diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h index 017558536825..d32df9594332 100644 --- a/lib/libsecureboot/h/libsecureboot.h +++ b/lib/libsecureboot/h/libsecureboot.h @@ -29,6 +29,7 @@ #include <sys/param.h> #ifdef _STANDALONE +#define _DEBUG_LEVEL_VAR DebugVe #include <stand.h> #else #include <sys/types.h> diff --git a/lib/libsys/fhopen.2 b/lib/libsys/fhopen.2 index aba53f1dd907..b281ac3d8949 100644 --- a/lib/libsys/fhopen.2 +++ b/lib/libsys/fhopen.2 @@ -31,7 +31,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 6, 2025 +.Dd July 20, 2025 .Dt FHOPEN 2 .Os .Sh NAME @@ -140,7 +140,7 @@ is no longer valid. .Xr fstatfs 2 , .Xr getfh 2 , .Xr open 2 , -.Xr named_attribute 9 +.Xr named_attribute 7 .Sh HISTORY The .Fn fhopen , diff --git a/lib/libsys/mkdir.2 b/lib/libsys/mkdir.2 index e1f1624cebc4..100f44d1dcf9 100644 --- a/lib/libsys/mkdir.2 +++ b/lib/libsys/mkdir.2 @@ -176,4 +176,4 @@ system call appeared in The .Fn mkdir system call appeared in -.At v1 . +.Bx 4.2 . diff --git a/lib/libsys/statfs.2 b/lib/libsys/statfs.2 index 49e8b5120558..ab65def11ebb 100644 --- a/lib/libsys/statfs.2 +++ b/lib/libsys/statfs.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 7, 2025 +.Dd July 20, 2025 .Dt STATFS 2 .Os .Sh NAME @@ -127,7 +127,7 @@ Mandatory Access Control (MAC) support for individual objects .Xr mac 4 ) . .It Dv MNT_NAMEDATTR The file system supports named attributes as described in -.Xr named_attribute 9 . +.Xr named_attribute 7 . .It Dv MNT_NFS4ACLS ACLs in NFSv4 variant are supported. .It Dv MNT_NOATIME @@ -264,7 +264,7 @@ each file or directory name or disk label .Sh SEE ALSO .Xr fhstatfs 2 , .Xr getfsstat 2 , -.Xr named_attribute 9 +.Xr named_attribute 7 .Sh HISTORY The .Fn statfs diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3 index 74b85d4aa17e..9dc752f0fd7b 100644 --- a/lib/libusb/libusb.3 +++ b/lib/libusb/libusb.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 13, 2025 +.Dd July 9, 2025 .Dt LIBUSB 3 .Os .Sh NAME @@ -366,6 +366,23 @@ argument is non-zero the feature is enabled. Else disabled. Returns 0 on success and a LIBUSB_ERROR code on failure. +.Pp +.Ft unsigned char * +.Fn libusb_dev_mem_alloc "libusb_device_handle *devh" +This function attempts to allocate a DMA memory block from the given +.Fa devh +so that we can enjoy the zero-copy transfer from kernel. +This function is provided for compatibility and is currently unimplemented and always returns NULL. +.Pp +.Ft int +.Fn libusb_dev_mem_free "libusb_device_handle *devh" "unsigned char *buffer" "size_t size" +This function frees the DMA memory in +.Fa devh +from the given +.Fa buffer +with +.Fa size . +This function is unimplemented and always returns LIBUSB_ERROR_NOT_SUPPORTED. .Sh USB DESCRIPTORS .Ft int .Fn libusb_get_device_descriptor "libusb_device *dev" "libusb_device_descriptor *desc" @@ -775,6 +792,17 @@ argument can be either of LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED or LIBUSB_HOTPLUG_ .Ft void .Fn libusb_hotplug_deregister_callback "libusb_context *ctx" "libusb_hotplug_callback_handle handle" This function unregisters a hotplug filter. +.Pp +.Ft void +.Fn libusb_free_pollfds "const struct libusb_pollfd **pollfds" +This function releases the memory storage in +.Fa pollfds , +and is safe to call when the argument is NULL. +.Pp void * +.Fn libusb_hotplug_get_user_data "struct libusb_context *ctx" "libusb_hotplug_callback_handle callback_handle" +This function returns the user data from the opaque +.Fa callback_handle , +or returns NULL if no matching handle is found. .Sh LIBUSB VERSION 0.1 COMPATIBILITY The library is also compliant with LibUSB version 0.1.12. .Pp diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h index 6fb1c19fad13..1803ff637738 100644 --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -122,6 +122,7 @@ enum libusb_transfer_type { LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, LIBUSB_TRANSFER_TYPE_BULK = 2, LIBUSB_TRANSFER_TYPE_INTERRUPT = 3, + LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, }; enum libusb_standard_request { @@ -513,6 +514,9 @@ int libusb_detach_kernel_driver(libusb_device_handle * devh, int interface); int libusb_attach_kernel_driver(libusb_device_handle * devh, int interface); int libusb_set_auto_detach_kernel_driver(libusb_device_handle *dev, int enable); int libusb_set_interface_alt_setting(libusb_device_handle * devh, int interface_number, int alternate_setting); +unsigned char *libusb_dev_mem_alloc(libusb_device_handle *devh); +int libusb_dev_mem_free(libusb_device_handle *devh, unsigned char *buffer, + size_t size); /* USB Descriptors */ @@ -573,7 +577,8 @@ int libusb_handle_events(libusb_context * ctx); int libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv); int libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv); void libusb_set_pollfd_notifiers(libusb_context * ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data); -const struct libusb_pollfd **libusb_get_pollfds(libusb_context * ctx); +const struct libusb_pollfd **libusb_get_pollfds(libusb_context *ctx); +void libusb_free_pollfds(const struct libusb_pollfd **pollfds); /* Synchronous device I/O */ @@ -593,6 +598,8 @@ typedef int (*libusb_hotplug_callback_fn)(libusb_context *ctx, int libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_event events, libusb_hotplug_flag flags, int vendor_id, int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *handle); void libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle handle); +void *libusb_hotplug_get_user_data(struct libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); /* Streams support */ diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c index 6f1ca877fc28..5c116b39ea17 100644 --- a/lib/libusb/libusb10.c +++ b/lib/libusb/libusb10.c @@ -1530,6 +1530,7 @@ found: libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy); break; case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: case LIBUSB_TRANSFER_TYPE_INTERRUPT: libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy); break; @@ -1904,3 +1905,16 @@ libusb_setlocale(const char *locale) return (LIBUSB_ERROR_INVALID_PARAM); } + +unsigned char * +libusb_dev_mem_alloc(libusb_device_handle *devh) +{ + return (NULL); +} + +int +libusb_dev_mem_free(libusb_device_handle *devh, unsigned char *buffer, + size_t size) +{ + return (LIBUSB_ERROR_NOT_SUPPORTED); +} diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c index 369539d4512e..9c46d4926bfa 100644 --- a/lib/libusb/libusb10_hotplug.c +++ b/lib/libusb/libusb10_hotplug.c @@ -414,3 +414,21 @@ void libusb_hotplug_deregister_callback(libusb_context *ctx, free(handle); } + +void * +libusb_hotplug_get_user_data(struct libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle) +{ + libusb_hotplug_callback_handle handle; + + ctx = GET_CONTEXT(ctx); + + HOTPLUG_LOCK(ctx); + TAILQ_FOREACH(handle, &ctx->hotplug_cbh, entry) { + if (handle == callback_handle) + break; + } + HOTPLUG_UNLOCK(ctx); + + return (handle); +} diff --git a/lib/libusb/libusb10_io.c b/lib/libusb/libusb10_io.c index dd541b09caa6..c99586ff650d 100644 --- a/lib/libusb/libusb10_io.c +++ b/lib/libusb/libusb10_io.c @@ -781,6 +781,19 @@ libusb_fill_interrupt_transfer(struct libusb_transfer *transfer, } void +libusb_fill_bulk_stream_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + uint32_t stream_id, unsigned char *buffer, int length, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, + length, callback, user_data, timeout); + transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; + + libusb_transfer_set_stream_id(transfer, stream_id); +} + +void libusb_fill_iso_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, int npacket, libusb_transfer_cb_fn callback, @@ -842,3 +855,12 @@ libusb_transfer_get_stream_id(struct libusb_transfer *transfer) /* get stream ID */ return (sxfer->stream_id); } + +void +libusb_free_pollfds(const struct libusb_pollfd **pollfds) +{ + if (pollfds == NULL) + return; + + free(pollfds); +} diff --git a/lib/ncurses/tinfo/Makefile b/lib/ncurses/tinfo/Makefile index 920bd6e5559c..476df54bb72a 100644 --- a/lib/ncurses/tinfo/Makefile +++ b/lib/ncurses/tinfo/Makefile @@ -259,10 +259,18 @@ term.h: MKterm.h.awk edit_cfg.sh Caps Caps-ncurses sh ${NCURSES_DIR}/include/edit_cfg.sh ${NCURSES_CFG_H} $@.new mv -f $@.new $@ +# Avoid hard-coding absolute source paths if requested. +.if ${MK_REPRODUCIBLE_BUILD} != "no" +NCURSES_SRCTOP=/usr/src +.else +NCURSES_SRCTOP=${SRCTOP} +.endif + curses.h: curses.head MKkey_defs.sh Caps Caps-ncurses cat curses.head > $@.new AWK=${AWK} _POSIX2_VERSION=199209 sh ${NCURSES_DIR}/include/MKkey_defs.sh \ ${NCURSES_DIR}/include/Caps ${NCURSES_DIR}/include/Caps-ncurses >> $@.new + sed -i '' 's|${SRCTOP}|${NCURSES_SRCTOP}|g' $@.new cat ${NCURSES_DIR}/include/curses.wide >> $@.new cat ${NCURSES_DIR}/include/curses.tail >> $@.new mv -f $@.new $@ @@ -387,6 +395,7 @@ unctrl.h: unctrl.h.in terminfo.5: MKterminfo.sh terminfo.head Caps sh ${NCURSES_DIR}/man/MKterminfo.sh ${NCURSES_DIR}/man/terminfo.head \ ${NCURSES_DIR}/include/Caps ${NCURSES_DIR}/man/terminfo.tail >$@ + sed -i '' 's|${SRCTOP}|${NCURSES_SRCTOP}|g' $@ CLEANFILES+= terminfo.5 diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 00f4b718bfad..d502361eca37 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -694,7 +694,7 @@ entropy_file="/entropy" # Set to NO to disable late (used when going multi-user) entropy_dir="/var/db/entropy" # Set to NO to disable caching entropy via cron. entropy_save_sz="4096" # Size of the entropy cache files. entropy_save_num="8" # Number of entropy cache files to save. -harvest_mask="511" # Entropy device harvests all but the very invasive sources. +harvest_mask="4607" # Entropy device harvests all but the very invasive sources. # (See 'sysctl kern.random.harvest' and random(4)) osrelease_enable="YES" # Update /var/run/os-release on boot (or NO). osrelease_file="/var/run/os-release" # File to update for os-release. diff --git a/libexec/rc/rc.d/mountd b/libexec/rc/rc.d/mountd index 8c0aa87e1d13..dfd2431f9c35 100755 --- a/libexec/rc/rc.d/mountd +++ b/libexec/rc/rc.d/mountd @@ -70,6 +70,8 @@ mountd_precmd() } load_rc_config $name +load_rc_config nfsd +load_rc_config zfs # precmd is not compatible with svcj mountd_svcj="NO" diff --git a/libexec/rc/rc.d/pf b/libexec/rc/rc.d/pf index 0b4c086db22b..46fb085e5175 100755 --- a/libexec/rc/rc.d/pf +++ b/libexec/rc/rc.d/pf @@ -38,7 +38,7 @@ pf_fallback() $pf_program -f "$pf_fallback_rules_file" $pf_flags else warn "Loading fallback rules: $pf_fallback_rules" - echo $pf_fallback_rules | $pf_program -f - $pf_flags + echo "$pf_fallback_rules" | $pf_program -f - $pf_flags fi } diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index 04d17072af77..c6a98b50a165 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -337,7 +337,7 @@ map_object(int fd, const char *path, const struct stat *sb, bool ismain) obj->tlsalign = phtls->p_align; obj->tlspoffset = phtls->p_offset; obj->tlsinitsize = phtls->p_filesz; - obj->tlsinit = mapbase + phtls->p_vaddr; + obj->tlsinit = obj->relocbase + phtls->p_vaddr; } obj->stack_flags = stack_flags; if (note_start < note_end) diff --git a/release/Makefile b/release/Makefile index 84f29983b6c7..b6a9aa42c2e2 100644 --- a/release/Makefile +++ b/release/Makefile @@ -162,7 +162,8 @@ kernel.txz: # Also (if enabled) kernel-dbg.txz. src.txz: mkdir -p ${DISTDIR}/usr - ln -fs ${WORLDDIR} ${DISTDIR}/usr/src + rm -f ${DISTDIR}/usr/src + ln -s ${WORLDDIR} ${DISTDIR}/usr/src ( cd ${DISTDIR} && ${TAR_XZ_CMD} -cLvf ${.OBJDIR}/src.txz \ --exclude .svn --exclude .zfs \ --exclude .git --exclude @ --exclude usr/src/release/dist \ @@ -170,7 +171,8 @@ src.txz: ports.txz: mkdir -p ${DISTDIR}/usr - ln -fs ${PORTSDIR} ${DISTDIR}/usr/ports + rm -f ${DISTDIR}/usr/ports + ln -s ${PORTSDIR} ${DISTDIR}/usr/ports ( cd ${DISTDIR} && ${TAR_XZ_CMD} -cLvf ${.OBJDIR}/ports.txz \ --exclude .git --exclude .svn \ --exclude usr/ports/distfiles --exclude usr/ports/packages \ @@ -276,6 +278,7 @@ bootonly: .if ${.MAKE.OS} == "FreeBSD" && (!defined(NOPKG) || empty(NOPKG)) # Install packages onto release media. ${PKG_INSTALL} pkg || true + ${PKG_INSTALL} wifi-firmware-iwlwifi-kmod wifi-firmware-rtw88-kmod || true ${PKG_CLEAN} || true .endif # Set up installation environment @@ -340,8 +343,8 @@ dvd: ${PKGBASE_REPO} echo hostid_enable=\"NO\" >> ${.TARGET}/etc/rc.conf echo debug.witness.trace=0 >> ${.TARGET}/etc/sysctl.conf echo vfs.mountroot.timeout=\"10\" >> ${.TARGET}/boot/loader.conf - echo loader_brand=\"install\" >> ${.TARGET}/boot/loader.conf echo kernels_autodetect=\"NO\" >> ${.TARGET}/boot/loader.conf + echo loader_brand=\"install\" >> ${.TARGET}/boot/loader.conf echo loader_menu_multi_user_prompt=\"Installer\" >> ${.TARGET}/boot/loader.conf cp ${.CURDIR}/rc.local ${.TARGET}/etc echo "./etc/resolv.conf type=link uname=root gname=wheel mode=0644 link=/tmp/bsdinstall_etc/resolv.conf" >> ${.TARGET}/METALOG diff --git a/release/amd64/make-memstick.sh b/release/amd64/make-memstick.sh index cbb80e971343..cec4b27b5b96 100755 --- a/release/amd64/make-memstick.sh +++ b/release/amd64/make-memstick.sh @@ -12,6 +12,7 @@ set -e scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh if [ "$(uname -s)" = "FreeBSD" ]; then @@ -51,7 +52,7 @@ if [ -n "${METALOG}" ]; then echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} MAKEFSARG=${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} +${MAKEFS} -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} rm ${BASEBITSDIR}/etc/fstab rm ${BASEBITSDIR}/etc/rc.conf.local if [ -n "${METALOG}" ]; then @@ -67,10 +68,10 @@ else make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi fi -mkimg -s mbr \ +${MKIMG} -s mbr \ -b ${BASEBITSDIR}/boot/mbr \ -p efi:=${espfilename} \ - -p freebsd:-"mkimg -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \ + -p freebsd:-"${MKIMG} -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \ -a 2 \ -o ${2} rm ${espfilename} diff --git a/release/amd64/mkisoimages.sh b/release/amd64/mkisoimages.sh index 245beb660c3f..8f7163e05261 100644 --- a/release/amd64/mkisoimages.sh +++ b/release/amd64/mkisoimages.sh @@ -25,20 +25,9 @@ set -e scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh -if [ -z $ETDUMP ]; then - ETDUMP=etdump -fi - -if [ -z $MAKEFS ]; then - MAKEFS=makefs -fi - -if [ -z $MKIMG ]; then - MKIMG=mkimg -fi - if [ "$1" = "-b" ]; then MAKEFSARG="$4" else diff --git a/release/arm64/make-memstick.sh b/release/arm64/make-memstick.sh index 90ff98b394c7..0da59c29635b 100755 --- a/release/arm64/make-memstick.sh +++ b/release/arm64/make-memstick.sh @@ -17,6 +17,7 @@ if [ "$(uname -s)" = "FreeBSD" ]; then fi scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh if [ $# -ne 2 ]; then @@ -51,7 +52,7 @@ if [ -n "${METALOG}" ]; then echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} MAKEFSARG=${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} +${MAKEFS} -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} rm ${BASEBITSDIR}/etc/fstab rm ${BASEBITSDIR}/etc/rc.conf.local if [ -n "${METALOG}" ]; then @@ -62,7 +63,7 @@ fi espfilename=$(mktemp /tmp/efiboot.XXXXXX) make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi -mkimg -s gpt \ +${MKIMG} -s gpt \ -p efi:=${espfilename} \ -p freebsd-ufs:=${2}.part \ -o ${2} diff --git a/release/arm64/mkisoimages.sh b/release/arm64/mkisoimages.sh index cb58178ed4b9..46b16f0ce08d 100644 --- a/release/arm64/mkisoimages.sh +++ b/release/arm64/mkisoimages.sh @@ -21,20 +21,9 @@ set -e scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh -if [ -z $ETDUMP ]; then - ETDUMP=etdump -fi - -if [ -z $MAKEFS ]; then - MAKEFS=makefs -fi - -if [ -z $MKIMG ]; then - MKIMG=mkimg -fi - if [ "$1" = "-b" ]; then MAKEFSARG="$4" else diff --git a/release/i386/make-memstick.sh b/release/i386/make-memstick.sh index 7a20be20c026..ad2126b0a8f8 100755 --- a/release/i386/make-memstick.sh +++ b/release/i386/make-memstick.sh @@ -11,6 +11,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr + if [ "$(uname -s)" = "FreeBSD" ]; then PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH @@ -48,16 +51,16 @@ if [ -n "${METALOG}" ]; then echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} MAKEFSARG=${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} +${MAKEFS} -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} rm ${BASEBITSDIR}/etc/fstab rm ${BASEBITSDIR}/etc/rc.conf.local if [ -n "${METALOG}" ]; then rm ${metalogfilename} fi -mkimg -s mbr \ +${MKIMG} -s mbr \ -b ${BASEBITSDIR}/boot/mbr \ - -p freebsd:-"mkimg -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \ + -p freebsd:-"${MKIMG} -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \ -o ${2} rm ${2}.part diff --git a/release/i386/mkisoimages.sh b/release/i386/mkisoimages.sh index 8f000aae3b17..1918b36eeb44 100644 --- a/release/i386/mkisoimages.sh +++ b/release/i386/mkisoimages.sh @@ -24,6 +24,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr + if [ "$1" = "-b" ]; then MAKEFSARG="$4" else @@ -67,7 +70,7 @@ if [ -n "${METALOG}" ]; then echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} MAKEFSARG=${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@" +${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 "${METALOG}" ]; then rm ${metalogfilename} diff --git a/release/packages/Makefile.package b/release/packages/Makefile.package deleted file mode 100644 index c2427aa16945..000000000000 --- a/release/packages/Makefile.package +++ /dev/null @@ -1,193 +0,0 @@ -# -# - -acct_COMMENT= System Accounting Utilities -acct_DESC= System Accounting Utilities -acpi_COMMENT= ACPI Utilities -acpi_DESC= ACPI Utilities -amd_COMMENT= AMD Utilities -amd_DESC= AMD Utilities -apm_COMMENT= APM Utilities -apm_DESC= APM Utilities -at_COMMENT= AT Utilities -at_DESC= AT Utilities -audit_COMMENT= OpenBSM auditing utilities -audit_DESC= OpenBSM auditing utilities -autofs_COMMENT= Autofs Utilities -autofs_DESC= Autofs Utilities -bhyve_COMMENT= Bhyve Utilities -bhyve_DESC= Bhyve Utilities -blocklist_COMMENT= Blocklist Utilities -blocklist_DESC= Blocklist Utilities -bluetooth_COMMENT= Bluetooth Utilities -bluetooth_DESC= Bluetooth Utilities -bootloader_COMMENT= Bootloader -bootloader_DESC= Bootloader and configuration files -bsdinstall_COMMENT= BSDInstall Utilities -bsdinstall_DESC= BSDInstall Utilities -bsnmp_COMMENT= BSNMP Utilities -bsnmp_DESC= BSNMP Utilities -caroot_COMMENT= SSL Certificates -caroot_DESC= SSL Certificates -clang_COMMENT= Clang Utilities -clang_DESC= Clang Utilities -clibs_COMMENT= Core C Libraries -clibs_DESC= Core C Libraries -certctl_COMMENT= SSL Certificate Utility -certctl_DESC= SSL Certificate Utility -console-tools_COMMENT= Console Utilities -console-tools_DESC= Console Utilities -cron_COMMENT= cron(8) and crontab(1) -cron_DESC= cron(8) and crontab(1) -csh_COMMENT= C Shell -csh_DESC= C Shell -ctf-tools_COMMENT= CTF Utilities -ctf-tools_DESC= CTF Utilities -cxgbe-tools_COMMENT= Chelsio cxbge Utilities -cxgbe-tools_DESC= Chelsio cxbge Utilities -devd_COMMENT= Devd Utility and scripts -devd_DESC= Devd Utility and scripts -devmatch_COMMENT= Devmatch Utility -devmatch_DESC= Devmatch Utility -dhclient_COMMENT= DHCP Client -dhclient_DESC= DHCP Client -dma_COMMENT= DMA Mail Agent Utilities -dma_DESC= DMA Mail Agent Utilities -docs_COMMENT= Documentation -docs_DESC= Documentation -dtrace_COMMENT= Dtrace Utilities -dtrace_DESC= Dtrace Utilities -dwatch_COMMENT= Dwatch Utilities -dwatch_DESC= Dwatch Utilities -ee_COMMENT= Easy Editor Utilities -ee_DESC= Easy Editor Utilities -efi-tools_COMMENT= UEFI Utilities -efi-tools_DESC= UEFI Utilities -examples_COMMENT= Examples in /usr/share/examples -examples_DESC= Examples in /usr/share/examples -fd_COMMENT= Floppy disk support -fd_DESC= Floppy disk support -fetch_COMMENT= Fetch Utility -fetch_DESC= Fetch Utility -firmware-iwm_DESC= iwm(4) firmwares -firmware-iwm_COMMENT= iwm(4) firmwares -ftp_COMMENT= FTP Utilities -ftp_DESC= FTP Utilities -ftpd_COMMENT= FTP Daemon -ftpd_DESC= FTP Daemon -fwget_COMMENT= FWGET Utility -fwget_DESC= FWGET Utility -games_COMMENT= Games -games_DESC= Games -geom_COMMENT= GEOM Utilitites -geom_DESC= GEOM Utilitites -ggate_COMMENT= GEOM Gate Utilities -ggate_DESC= GEOM Gate Utilities -hast_COMMENT= Highly Available Storage daemon -hast_DESC= Highly Available Storage daemon -hostapd_COMMENT= 802.11 Access Point Daemon an Utilities -hostapd_DESC= 802.11 Access Point Daemon an Utilities -hyperv-tools_COMMENT= Microsoft HyperV Utilities -hyperv-tools_DESC= Microsoft HyperV Utilities -inetd_COMMENT= Internet super-server -inetd_DESC= Internet super-server -jail_COMMENT= Jail Utilities -jail_DESC= Jail Utilities -jail-debug_DESCR= Debugging Symbols -jail-development_DESCR=Development Files -jail-profile_DESCR= Profiling Libraries -jail-lib32_DESCR= 32-bit Libraries -jail-lib32-debug_DESCR=32-bit Debugging Symbols -jail-lib32-development_DESCR=32-bit Development Files -jail-lib32-profile_DESCR=32-bit Profiling Libraries -kerberos_COMMENT= Kerberos Utilities -kerberos_DESC= Kerberos Utilities -kerberos-lib_COMMENT= Kerberos Libraries -kerberos-lib_DESC= Kerberos Libraries -kernel_COMMENT= FreeBSD Kernel -kernel_DESC= FreeBSD Kernel -lp_COMMENT= Printer subsystem -lp_DESC= Printer subsystem -manuals_COMMENT= Manual Pages -manuals_DESC= Manual Pages -mlx-tools_COMMENT= Mellanox Utilities -mlx-tools_DESC= Mellanox Utilities -mtree_COMMENT= MTREE Files -mtree_DESC= MTREE Files -netmap_COMMENT= Netmap Library and Utilities -netmap_DESC= Netmap Library and Utilities -newsyslog_COMMENT= Newsyslog Utility -newsyslog_DESC= Newsyslog Utility -nfs_COMMENT= NFS Utilities -nfs_DESC= NFS Utilities -ntp_COMMENT= Network Time Protocol server and client -ntp_DESC= Network Time Protocol server and client -nuageinit_COMMENT= CloudInit support scripts -nuageinit_DESC= CloudInit support scripts -nvme-tools_COMMENT= NVME Utilities -nvme-tools_DESC= NVME Utilities -openssl_COMMENT= OpenSSL Utility -openssl_DESC= OpenSSL Utility -openssl-lib_COMMENT= OpenSSL Libraries -openssl-lib_DESC= OpenSSL Libraries -pkg-bootstrap_COMMENT= pkg bootstrap Utility -pkg-bootstrap_DESC= pkg bootstrap Utility -periodic_COMMENT= Periodic Utility -periodic_DESC= Periodic Utility -rc_COMMENT= RC Scripts -rc_DESC= RC Scripts -rcmds_COMMENT= BSD/SunOS remote status commands -rcmds_DESC=\ -The BSD/SunOS remote status commands, which can be used to query or interact\ -with remote hosts over the network. This includes the command-line utilities\ -rwho, ruptime, rup, rusers and rwall and the daemons rwhod, rpc.rstatd,\ -rpc.rusersd, and rpc.rwalld. -rdma_COMMENT= RDMA Utilities -rdma_DESC= RDMA Utilities -rescue_COMMENT= Rescue Utilities -rescue_DESC= Rescue Utilities -resolvconf_COMMENT= Resolvconf Utility and scripts -resolvconf_DESC= Resolvconf Utility and scripts -runtime_COMMENT= FreeBSD Base System -runtime_DESC= FreeBSD Base System -runtime-debug_DESCR= Debugging Symbols -runtime-development_DESCR=Development Files -runtime-profile_DESCR= Profiling Libraries -runtime-lib32_DESCR= 32-bit Libraries -runtime-lib32-debug_DESCR=32-bit Debugging Symbols -runtime-lib32-development_DESCR=32-bit Development Files -runtime-lib32-profile_DESCR=32-bit Profiling Libraries -sendmail_COMMENT= Sendmail Utilities -sendmail_DESC= Sendmail Utilities -smbutils_COMMENT= SMB Utilities -smbutils_DESC= SMB Utilities -ssh_COMMENT= Secure Shell Utilities -ssh_DESC= Secure Shell Utilities -syscons_COMMENT= Syscons Console -syscons_DESC= Syscons Console -syslogd_COMMENT= Syslog Daemon -syslogd_DESC= Syslog Daemon -tcpd_COMMENT= TCP Wrapper utilities -tcpd_DESC= TCP Wrapper utilities -telnet_COMMENT= Telnet client -telnet_DESC= Telnet client -tests_COMMENT= Test Suite -tests_DESC= Test Suite -toolchain_COMMENT= Utilities for program development -toolchain_DESC= Utilities for program development -ufs_COMMENT= UFS Libraries and Utilities -ufs_DESC= UFS Libraries and Utilities -unbound_COMMENT= Unbound DNS Resolver -unbound_DESC= Unbound DNS Resolver -utilities_COMMENT= Non-vital programs and libraries -utilities_DESC= Non-vital programs and libraries -vi_COMMENT= Vi Editor -vi_DESC= Vi Editor -vt_COMMENT= VT fonts and keyboard files -vt_DESC= VT fonts and keyboard files -wpa_COMMENT= 802.11 Supplicant -wpa_DESC= 802.11 Supplicant -yp_COMMENT= Yellow Pages programs -yp_DESC= Yellow Pages programs -zfs_COMMENT= ZFS Libraries and Utilities -zfs_DESC= ZFS Libraries and Utilities diff --git a/release/packages/certctl.ucl b/release/packages/certctl.ucl deleted file mode 100644 index 664a6d139585..000000000000 --- a/release/packages/certctl.ucl +++ /dev/null @@ -1,9 +0,0 @@ -scripts: { - # XXX If pkg picks up a mechanism to detect in the post-install script - # files being added or removed, we should use it instead to gate the - # rehash. - post-install = <<EOD - [ -x /usr/sbin/certctl ] && env DESTDIR=${PKG_ROOTDIR} \ - /usr/sbin/certctl rehash -EOD -} diff --git a/release/packages/clang-all.ucl b/release/packages/clang-all.ucl deleted file mode 100644 index 41a697ebe53d..000000000000 --- a/release/packages/clang-all.ucl +++ /dev/null @@ -1 +0,0 @@ -licenses = [ NCSA ] diff --git a/release/packages/generate-ucl.lua b/release/packages/generate-ucl.lua index ae6ee58dd84a..3d91d11bc42f 100755 --- a/release/packages/generate-ucl.lua +++ b/release/packages/generate-ucl.lua @@ -3,33 +3,174 @@ --[[ usage: generare-ucl.lua [<variablename> <variablevalue>]... <sourceucl> <destucl> -In the <destucl> files the variable <variablename> (in the form ${variablename} -in the <sourceucl>) will be expanded to <variablevalue>. - -The undefined variables will reamin unmofifier "${variablename}" +Build a package's UCL configuration by loading the template UCL file +<sourceucl>, replacing any $VARIABLES in the UCL based on the provided +variables, then writing the result to <destucl>. ]]-- local ucl = require("ucl") +-- Give subpackages a special comment and description suffix to indicate what +-- they contain, so e.g. "foo-man" has " (manual pages)" appended to its +-- comment. This avoids having to create a separate ucl files for every +-- subpackage just to set this. +-- +-- Note that this is not a key table because the order of the pattern matches +-- is important. +pkg_suffixes = { + { + "%-dev%-lib32$", "(32-bit development files)", + "This package contains development files for compiling ".. + "32-bit applications on a 64-bit host." + }, + { + "%-dbg%-lib32$", "(32-bit debugging symbols)", + "This package contains 32-bit external debugging symbols ".. + "for use with a source-level debugger.", + }, + { + "%-man%-lib32$", "(32-bit manual pages)", + "This package contains the online manual pages for 32-bit ".. + "components on a 64-bit host.", + }, + { + "%-lib32$", "(32-bit libraries)", + "This package contains 32-bit libraries for running 32-bit ".. + "applications on a 64-bit host.", + }, + { + "%-dev$", "(development files)", + "This package contains development files for ".. + "compiling applications." + }, + { + "%-man$", "(manual pages)", + "This package contains the online manual pages." + }, + { + "%-dbg$", "(debugging symbols)", + "This package contains external debugging symbols for use ".. + "with a source-level debugger.", + }, +} + +function add_suffixes(obj) + local pkgname = obj["name"] + for _,pattern in pairs(pkg_suffixes) do + if pkgname:match(pattern[1]) ~= nil then + obj["comment"] = obj["comment"] .. " " .. pattern[2] + obj["desc"] = obj["desc"] .. "\n\n" .. pattern[3] + return + end + end +end + +-- Hardcode a list of packages which don't get the automatic pkggenname +-- dependency because the base package doesn't exist. We should have a better +-- way to handle this. +local no_gen_deps = { + ["libcompat-dev"] = true, + ["libcompat-dev-lib32"] = true, + ["libcompat-man"] = true, + ["libcompiler_rt-dev"] = true, + ["libcompiler_rt-dev-lib32"] = true, + ["liby-dev"] = true, + ["liby-dev-lib32"] = true, +} + +-- Return true if the package 'pkgname' should have a dependency on the package +-- pkggenname. +function add_gen_dep(pkgname, pkggenname) + if pkgname == pkggenname then + return false + end + if pkgname == nil or pkggenname == nil then + return false + end + if no_gen_deps[pkgname] ~= nil then + return false + end + if pkggenname == "kernel" then + return false + end + + return true +end + +local pkgname = nil +local pkggenname = nil +local pkgprefix = nil +local pkgversion = nil + +-- This parser is the output UCL we want to build. +local parser = ucl.parser() + +-- Set any $VARIABLES from the command line in the parser. This causes ucl to +-- automatically replace them when we load the source ucl. if #arg < 2 or #arg % 2 ~= 0 then io.stderr:write(arg[0] .. ": expected an even number of arguments, got " .. #arg) os.exit(1) end -local parser = ucl.parser() for i = 2, #arg - 2, 2 do - parser:register_variable(arg[i - 1], arg[i]) + local varname = arg[i - 1] + local varvalue = arg[i] + + if varname == "PKGNAME" and #varvalue > 0 then + pkgname = varvalue + elseif varname == "PKGGENNAME" and #varvalue > 0 then + pkggenname = varvalue + elseif varname == "VERSION" and #varvalue > 0 then + pkgversion = varvalue + elseif varname == "PKG_NAME_PREFIX" and #varvalue > 0 then + pkgprefix = varvalue + end + + parser:register_variable(varname, varvalue) end + +-- Load the source ucl file. local res,err = parser:parse_file(arg[#arg - 1]) if not res then io.stderr:write(arg[0] .. ": fail to parse("..arg[#arg - 1].."): "..err) os.exit(1) end + +local obj = parser:get_object() + +-- If pkgname is different from pkggenname, add a dependency on pkggenname. +-- This means that e.g. -dev packages depend on their respective base package. +if add_gen_dep(pkgname, pkggenname) then + if obj["deps"] == nil then + obj["deps"] = {} + end + obj["deps"][pkggenname] = { + ["version"] = pkgversion, + ["origin"] = "base" + } +end + +-- 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 +-- keys. +if pkgprefix ~= nil and obj["deps"] ~= nil then + newdeps = {} + for dep, opts in pairs(obj["deps"]) do + local newdep = pkgprefix .. "-" .. dep + newdeps[newdep] = opts + end + obj["deps"] = newdeps +end + +-- Add comment and desc suffix. +add_suffixes(obj) + +-- Write the output file. local f,err = io.open(arg[#arg], "w") if not f then io.stderr:write(arg[0] .. ": fail to open("..arg[#arg].."): ".. err) os.exit(1) end -local obj = parser:get_object() + f:write(ucl.to_format(obj, 'ucl', true)) f:close() diff --git a/release/packages/generate-ucl.sh b/release/packages/generate-ucl.sh index b7d7bad35023..3078185a3c4e 100755 --- a/release/packages/generate-ucl.sh +++ b/release/packages/generate-ucl.sh @@ -3,8 +3,8 @@ # main() { - desc= - comment= + outname="" + origname="" debug= uclsource= while getopts "do:s:u:" arg; do @@ -31,73 +31,26 @@ main() { shift $(( ${OPTIND} - 1 )) case "${outname}" in - bootloader) - pkgdeps="" - ;; - certctl) - pkgdeps="caroot openssl" - ;; - clang) - pkgdeps="lld libcompiler_rt-dev" - ;; - periodic) - pkgdeps="cron" - ;; - rcmds) - # the RPC daemons require rpcbind - pkgdeps="utilities" - ;; - - # -dev packages that have no corresponding non-dev package - # as a dependency. - libcompat-dev|libcompiler_rt-dev|liby-dev) - outname=${outname%%-dev} - _descr="Development Files" - ;; - libcompat-lib32_dev|libcompiler_rt-lib32_dev|liby-lib32_dev) - outname=${outname%%-lib32_dev} - _descr="32-bit Libraries, Development Files" - ;; - libcompat-man|libelftc-man) - outname=${outname%%-man} - _descr="Manual Pages" + *-dev) + outname="${outname%%-dev}" ;; - utilities) - uclfile="${uclfile}" + *-dbg) + outname="${outname%%-dbg}" ;; - runtime) - outname="runtime" - _descr="$(make -C ${srctree}/release/packages -f Makefile.package -V ${outname}_DESCR)" + *-dev-lib32) + outname="${outname%%-dev-lib32}" ;; - *-lib32_dev) - outname="${outname%%-lib32_dev}" - _descr="32-bit Libraries, Development Files" - pkgdeps="${outname}" + *-dbg-lib32) + outname="${outname%%-dbg-lib32}" ;; - *-lib32_dbg) - outname="${outname%%-lib32_dbg}" - _descr="32-bit Libraries, Debugging Symbols" - pkgdeps="${outname}" + *-man-lib32) + outname="${outname%%-man-lib32}" ;; *-lib32) outname="${outname%%-lib32}" - _descr="32-bit Libraries" - pkgdeps="${outname}" - ;; - *-dev) - outname="${outname%%-dev}" - _descr="Development Files" - pkgdeps="${outname}" - ;; - *-dbg) - outname="${outname%%-dbg}" - _descr="Debugging Symbols" - pkgdeps="${outname}" ;; *-man) outname="${outname%%-man}" - _descr="Manual Pages" - pkgdeps="${outname}" ;; ${origname}) ;; @@ -107,22 +60,16 @@ main() { ;; esac - desc="$(make -C ${srctree}/release/packages -f Makefile.package -V ${outname}_DESC)" - comment="$(make -C ${srctree}/release/packages -f Makefile.package -V ${outname}_COMMENT)" - uclsource="${srctree}/release/packages/template.ucl" if [ -n "${debug}" ]; then echo "" echo "===============================================================" echo "DEBUG:" - echo "_descr=${_descr}" echo "outname=${outname}" echo "origname=${origname}" echo "srctree=${srctree}" echo "uclfile=${uclfile}" - echo "desc=${desc}" - echo "comment=${comment}" echo "vital=${vital}" echo "cp ${uclsource} -> ${uclfile}" echo "===============================================================" @@ -131,38 +78,17 @@ main() { echo "" fi - [ -z "${comment}" ] && comment="${outname} package" - [ -n "${_descr}" ] && comment="${comment} (${_descr})" - [ -z "${desc}" ] && desc="${outname} package" - - cp "${uclsource}" "${uclfile}" - if [ -n "${pkgdeps}" ]; then - echo 'deps: {' >> ${uclfile} - for dep in ${pkgdeps}; do - cat <<EOF >> ${uclfile} - ${PKG_NAME_PREFIX}-${dep}: { - origin: "base", - version: "${PKG_VERSION}" - } -EOF - done - echo '}' >> ${uclfile} - fi cap_arg="$( make -f ${srctree}/share/mk/bsd.endian.mk -VCAP_MKDB_ENDIAN )" ${srctree}/release/packages/generate-ucl.lua \ VERSION "${PKG_VERSION}" \ PKGNAME "${origname}" \ PKGGENNAME "${outname}" \ PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \ - COMMENT "${comment}" \ - DESC "${desc}" \ CAP_MKDB_ENDIAN "${cap_arg}" \ PKG_WWW "${PKG_WWW}" \ PKG_MAINTAINER "${PKG_MAINTAINER}" \ - UCLFILES "${srctree}/release/packages/" \ - ${uclfile} ${uclfile} - - return 0 + UCLFILES "${srctree}/release/packages/ucl" \ + ${uclsource} ${uclfile} } main "${@}" diff --git a/release/packages/lld-all.ucl b/release/packages/lld-all.ucl deleted file mode 100644 index 41a697ebe53d..000000000000 --- a/release/packages/lld-all.ucl +++ /dev/null @@ -1 +0,0 @@ -licenses = [ NCSA ] diff --git a/release/packages/lldb-all.ucl b/release/packages/lldb-all.ucl deleted file mode 100644 index 41a697ebe53d..000000000000 --- a/release/packages/lldb-all.ucl +++ /dev/null @@ -1 +0,0 @@ -licenses = [ NCSA ] diff --git a/release/packages/ssh-all.ucl b/release/packages/ssh-all.ucl deleted file mode 100644 index 4f78d80fa68e..000000000000 --- a/release/packages/ssh-all.ucl +++ /dev/null @@ -1 +0,0 @@ -licenses = [ ISCL ] diff --git a/release/packages/template.ucl b/release/packages/template.ucl index a65f58868118..faa48effe1ad 100644 --- a/release/packages/template.ucl +++ b/release/packages/template.ucl @@ -4,7 +4,7 @@ name = "${PKG_NAME_PREFIX}-${PKGNAME}" origin = "base" version = "${VERSION}" -comment = "${COMMENT}" +comment = "${PKGNAME} package" categories = [ base ] maintainer = "${PKG_MAINTAINER}" www = "${PKG_WWW}" @@ -12,8 +12,8 @@ prefix = "/" licenselogic = "single" licenses = [ BSD2CLAUSE ] desc = <<EOD -${DESC} +${PKGNAME} package EOD -.include(try=true,duplicate=rewrite) "${UCLFILES}/${PKGGENNAME}-all.ucl" +.include(try=false,duplicate=rewrite) "${UCLFILES}/${PKGGENNAME}-all.ucl" .include(try=true,duplicate=rewrite) "${UCLFILES}/${PKGNAME}.ucl" .include(try=true,duplicate=rewrite) "${UCLFILES}/${FORCEINCLUDE}.ucl" diff --git a/release/packages/ucl/acct-all.ucl b/release/packages/ucl/acct-all.ucl new file mode 100644 index 000000000000..ac4bd8868511 --- /dev/null +++ b/release/packages/ucl/acct-all.ucl @@ -0,0 +1,4 @@ +comment = "System Accounting Utilities" +desc = <<EOD +System Accounting Utilities +EOD diff --git a/release/packages/ucl/acpi-all.ucl b/release/packages/ucl/acpi-all.ucl new file mode 100644 index 000000000000..70ea39fc3862 --- /dev/null +++ b/release/packages/ucl/acpi-all.ucl @@ -0,0 +1,4 @@ +comment = "ACPI Utilities" +desc = <<EOD +ACPI Utilities +EOD diff --git a/release/packages/ucl/amd-all.ucl b/release/packages/ucl/amd-all.ucl new file mode 100644 index 000000000000..e2bc7cfc1b2a --- /dev/null +++ b/release/packages/ucl/amd-all.ucl @@ -0,0 +1,4 @@ +comment = "AMD Utilities" +desc = <<EOD +AMD Utilities +EOD diff --git a/release/packages/ucl/apm-all.ucl b/release/packages/ucl/apm-all.ucl new file mode 100644 index 000000000000..bf1b40000805 --- /dev/null +++ b/release/packages/ucl/apm-all.ucl @@ -0,0 +1,4 @@ +comment = "APM Utilities" +desc = <<EOD +APM Utilities +EOD diff --git a/release/packages/ucl/at-all.ucl b/release/packages/ucl/at-all.ucl new file mode 100644 index 000000000000..c15642737b36 --- /dev/null +++ b/release/packages/ucl/at-all.ucl @@ -0,0 +1,4 @@ +comment = "AT Utilities" +desc = <<EOD +AT Utilities +EOD diff --git a/release/packages/ucl/audit-all.ucl b/release/packages/ucl/audit-all.ucl new file mode 100644 index 000000000000..e0f3d4bf1675 --- /dev/null +++ b/release/packages/ucl/audit-all.ucl @@ -0,0 +1,4 @@ +comment = "OpenBSM auditing utilities" +desc = <<EOD +OpenBSM auditing utilities +EOD diff --git a/release/packages/ucl/autofs-all.ucl b/release/packages/ucl/autofs-all.ucl new file mode 100644 index 000000000000..0e3e8d2336ca --- /dev/null +++ b/release/packages/ucl/autofs-all.ucl @@ -0,0 +1,4 @@ +comment = "Autofs Utilities" +desc = <<EOD +Autofs Utilities +EOD diff --git a/release/packages/ucl/bhyve-all.ucl b/release/packages/ucl/bhyve-all.ucl new file mode 100644 index 000000000000..2b20ca9a716f --- /dev/null +++ b/release/packages/ucl/bhyve-all.ucl @@ -0,0 +1,4 @@ +comment = "Bhyve Utilities" +desc = <<EOD +Bhyve Utilities +EOD diff --git a/release/packages/ucl/blocklist-all.ucl b/release/packages/ucl/blocklist-all.ucl new file mode 100644 index 000000000000..03330a417af9 --- /dev/null +++ b/release/packages/ucl/blocklist-all.ucl @@ -0,0 +1,4 @@ +comment = "Blocklist Utilities" +desc = <<EOD +Blocklist Utilities +EOD diff --git a/release/packages/ucl/bluetooth-all.ucl b/release/packages/ucl/bluetooth-all.ucl new file mode 100644 index 000000000000..c139d9056a14 --- /dev/null +++ b/release/packages/ucl/bluetooth-all.ucl @@ -0,0 +1,4 @@ +comment = "Bluetooth Utilities" +desc = <<EOD +Bluetooth Utilities +EOD diff --git a/release/packages/ucl/bootloader-all.ucl b/release/packages/ucl/bootloader-all.ucl new file mode 100644 index 000000000000..c5690e85c7ba --- /dev/null +++ b/release/packages/ucl/bootloader-all.ucl @@ -0,0 +1,4 @@ +comment = "Bootloader" +desc = <<EOD +Bootloader and configuration files +EOD diff --git a/release/packages/ucl/bsdinstall-all.ucl b/release/packages/ucl/bsdinstall-all.ucl new file mode 100644 index 000000000000..4c4586dcc702 --- /dev/null +++ b/release/packages/ucl/bsdinstall-all.ucl @@ -0,0 +1,4 @@ +comment = "BSDInstall Utilities" +desc = <<EOD +BSDInstall Utilities +EOD diff --git a/release/packages/ucl/bsnmp-all.ucl b/release/packages/ucl/bsnmp-all.ucl new file mode 100644 index 000000000000..9b80310c0617 --- /dev/null +++ b/release/packages/ucl/bsnmp-all.ucl @@ -0,0 +1,4 @@ +comment = "BSNMP Utilities" +desc = <<EOD +BSNMP Utilities +EOD diff --git a/release/packages/ucl/caroot-all.ucl b/release/packages/ucl/caroot-all.ucl new file mode 100644 index 000000000000..151c1f18ae39 --- /dev/null +++ b/release/packages/ucl/caroot-all.ucl @@ -0,0 +1,4 @@ +comment = "SSL Certificates" +desc = <<EOD +SSL Certificates +EOD diff --git a/release/packages/ucl/caroot.ucl b/release/packages/ucl/caroot.ucl new file mode 100644 index 000000000000..4d2b52d300fc --- /dev/null +++ b/release/packages/ucl/caroot.ucl @@ -0,0 +1,10 @@ +deps { + "certctl": { + version = "${VERSION}" + origin = "base" + } +} +scripts: { + post-install = "/usr/sbin/certctl -D${PKG_ROOTDIR}/ rehash" + post-uninstall = "/usr/sbin/certctl -D${PKG_ROOTDIR}/ rehash" +} diff --git a/release/packages/ucl/ccdconfig-all.ucl b/release/packages/ucl/ccdconfig-all.ucl new file mode 100644 index 000000000000..76ba9d64db61 --- /dev/null +++ b/release/packages/ucl/ccdconfig-all.ucl @@ -0,0 +1,5 @@ +comment = "Concatenated disk driver (ccd) configuration utility" +desc = <<EOD +ccdconfig(8) is used to configure the concatenated disk driver, ccd(4). +ccdconfig(8) may also be started on boot using the "ccd" rc(8) service. +EOD diff --git a/release/packages/ucl/certctl-all.ucl b/release/packages/ucl/certctl-all.ucl new file mode 100644 index 000000000000..b4bc5ae261c5 --- /dev/null +++ b/release/packages/ucl/certctl-all.ucl @@ -0,0 +1,4 @@ +comment = "SSL Certificate Utility" +desc = <<EOD +SSL Certificate Utility +EOD diff --git a/release/packages/ucl/certctl.ucl b/release/packages/ucl/certctl.ucl new file mode 100644 index 000000000000..7f7adec83159 --- /dev/null +++ b/release/packages/ucl/certctl.ucl @@ -0,0 +1,6 @@ +deps { + "openssl": { + version = "${VERSION}" + origin = "base" + } +} diff --git a/release/packages/ucl/clang-all.ucl b/release/packages/ucl/clang-all.ucl new file mode 100644 index 000000000000..3f79f0acb229 --- /dev/null +++ b/release/packages/ucl/clang-all.ucl @@ -0,0 +1,5 @@ +comment = "Clang Utilities" +desc = <<EOD +Clang Utilities +EOD +licenses = [ NCSA ] diff --git a/release/packages/ucl/clang.ucl b/release/packages/ucl/clang.ucl new file mode 100644 index 000000000000..956b769a1ee7 --- /dev/null +++ b/release/packages/ucl/clang.ucl @@ -0,0 +1,11 @@ +deps { + "lld" { + version = "${VERSION}" + origin = "base" + } + + "libcompiler_rt-dev" { + version = "${VERSION}" + origin = "base" + } +} diff --git a/release/packages/ucl/clibs-all.ucl b/release/packages/ucl/clibs-all.ucl new file mode 100644 index 000000000000..69ae018d4d1f --- /dev/null +++ b/release/packages/ucl/clibs-all.ucl @@ -0,0 +1,4 @@ +comment = "Core C Libraries" +desc = <<EOD +Core C Libraries +EOD diff --git a/release/packages/clibs.ucl b/release/packages/ucl/clibs.ucl index 093fbb60248a..093fbb60248a 100644 --- a/release/packages/clibs.ucl +++ b/release/packages/ucl/clibs.ucl diff --git a/release/packages/ucl/console-tools-all.ucl b/release/packages/ucl/console-tools-all.ucl new file mode 100644 index 000000000000..53f31b2a9937 --- /dev/null +++ b/release/packages/ucl/console-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "Console Utilities" +desc = <<EOD +Console Utilities +EOD diff --git a/release/packages/ucl/cron-all.ucl b/release/packages/ucl/cron-all.ucl new file mode 100644 index 000000000000..d9edf6bfde52 --- /dev/null +++ b/release/packages/ucl/cron-all.ucl @@ -0,0 +1,4 @@ +comment = "cron(8) and crontab(1)" +desc = <<EOD +cron(8) and crontab(1) +EOD diff --git a/release/packages/ucl/csh-all.ucl b/release/packages/ucl/csh-all.ucl new file mode 100644 index 000000000000..df4dc71f8dd5 --- /dev/null +++ b/release/packages/ucl/csh-all.ucl @@ -0,0 +1,4 @@ +comment = "C Shell" +desc = <<EOD +C Shell +EOD diff --git a/release/packages/ucl/ctf-tools-all.ucl b/release/packages/ucl/ctf-tools-all.ucl new file mode 100644 index 000000000000..38ca769f6109 --- /dev/null +++ b/release/packages/ucl/ctf-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "CTF Utilities" +desc = <<EOD +CTF Utilities +EOD diff --git a/release/packages/ucl/ctl-all.ucl b/release/packages/ucl/ctl-all.ucl new file mode 100644 index 000000000000..d24ffabea1a0 --- /dev/null +++ b/release/packages/ucl/ctl-all.ucl @@ -0,0 +1,4 @@ +comment = "CAM Target Layer" +desc = <<EOD +The CAM Target Layer allows CAM to export storage targets, e.g. via iSCSI. +EOD diff --git a/release/packages/ucl/cxgbe-tools-all.ucl b/release/packages/ucl/cxgbe-tools-all.ucl new file mode 100644 index 000000000000..e2f6132f7ef9 --- /dev/null +++ b/release/packages/ucl/cxgbe-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "Chelsio cxbge Utilities" +desc = <<EOD +Chelsio cxbge Utilities +EOD diff --git a/release/packages/ucl/devd-all.ucl b/release/packages/ucl/devd-all.ucl new file mode 100644 index 000000000000..dc7d162a1930 --- /dev/null +++ b/release/packages/ucl/devd-all.ucl @@ -0,0 +1,4 @@ +comment = "Devd Utility and scripts" +desc = <<EOD +Devd Utility and scripts +EOD diff --git a/release/packages/ucl/devmatch-all.ucl b/release/packages/ucl/devmatch-all.ucl new file mode 100644 index 000000000000..02dc903fd422 --- /dev/null +++ b/release/packages/ucl/devmatch-all.ucl @@ -0,0 +1,4 @@ +comment = "Devmatch Utility" +desc = <<EOD +Devmatch Utility +EOD diff --git a/release/packages/ucl/dhclient-all.ucl b/release/packages/ucl/dhclient-all.ucl new file mode 100644 index 000000000000..6785366aea5e --- /dev/null +++ b/release/packages/ucl/dhclient-all.ucl @@ -0,0 +1,4 @@ +comment = "DHCP Client" +desc = <<EOD +DHCP Client +EOD diff --git a/release/packages/ucl/dma-all.ucl b/release/packages/ucl/dma-all.ucl new file mode 100644 index 000000000000..e8824acf7a36 --- /dev/null +++ b/release/packages/ucl/dma-all.ucl @@ -0,0 +1,4 @@ +comment = "DMA Mail Agent Utilities" +desc = <<EOD +DMA Mail Agent Utilities +EOD diff --git a/release/packages/ucl/docs-all.ucl b/release/packages/ucl/docs-all.ucl new file mode 100644 index 000000000000..7159d3f8f4ec --- /dev/null +++ b/release/packages/ucl/docs-all.ucl @@ -0,0 +1,4 @@ +comment = "Documentation" +desc = <<EOD +Documentation +EOD diff --git a/release/packages/ucl/dtb-all.ucl b/release/packages/ucl/dtb-all.ucl new file mode 100644 index 000000000000..cc5c1c60f062 --- /dev/null +++ b/release/packages/ucl/dtb-all.ucl @@ -0,0 +1,4 @@ +comment = "FreeBSD Devicetree Blobs" +desc = <<EOD +FreeBSD Devicetree Blobs +EOD diff --git a/release/packages/ucl/dtrace-all.ucl b/release/packages/ucl/dtrace-all.ucl new file mode 100644 index 000000000000..fb36816123c5 --- /dev/null +++ b/release/packages/ucl/dtrace-all.ucl @@ -0,0 +1,4 @@ +comment = "Dtrace Utilities" +desc = <<EOD +Dtrace Utilities +EOD diff --git a/release/packages/ucl/dwatch-all.ucl b/release/packages/ucl/dwatch-all.ucl new file mode 100644 index 000000000000..5f7e0fb764ce --- /dev/null +++ b/release/packages/ucl/dwatch-all.ucl @@ -0,0 +1,4 @@ +comment = "Dwatch Utilities" +desc = <<EOD +Dwatch Utilities +EOD diff --git a/release/packages/ucl/ee-all.ucl b/release/packages/ucl/ee-all.ucl new file mode 100644 index 000000000000..c003942ad3a9 --- /dev/null +++ b/release/packages/ucl/ee-all.ucl @@ -0,0 +1,4 @@ +comment = "Easy Editor Utilities" +desc = <<EOD +Easy Editor Utilities +EOD diff --git a/release/packages/ucl/efi-tools-all.ucl b/release/packages/ucl/efi-tools-all.ucl new file mode 100644 index 000000000000..51d5e12189dd --- /dev/null +++ b/release/packages/ucl/efi-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "UEFI Utilities" +desc = <<EOD +UEFI Utilities +EOD diff --git a/release/packages/ucl/examples-all.ucl b/release/packages/ucl/examples-all.ucl new file mode 100644 index 000000000000..93f0aee16187 --- /dev/null +++ b/release/packages/ucl/examples-all.ucl @@ -0,0 +1,4 @@ +comment = "Examples in /usr/share/examples" +desc = <<EOD +Examples in /usr/share/examples +EOD diff --git a/release/packages/ucl/fd-all.ucl b/release/packages/ucl/fd-all.ucl new file mode 100644 index 000000000000..7092449174e3 --- /dev/null +++ b/release/packages/ucl/fd-all.ucl @@ -0,0 +1,4 @@ +comment = "Floppy disk support" +desc = <<EOD +Utilities for formatting and managing floppy disks supported by fdc(4). +EOD diff --git a/release/packages/ucl/fetch-all.ucl b/release/packages/ucl/fetch-all.ucl new file mode 100644 index 000000000000..f9a3e03e6fa4 --- /dev/null +++ b/release/packages/ucl/fetch-all.ucl @@ -0,0 +1,4 @@ +comment = "Fetch Utility" +desc = <<EOD +Fetch Utility +EOD diff --git a/release/packages/ucl/firmware-iwm-all.ucl b/release/packages/ucl/firmware-iwm-all.ucl new file mode 100644 index 000000000000..6fec27c15351 --- /dev/null +++ b/release/packages/ucl/firmware-iwm-all.ucl @@ -0,0 +1,4 @@ +comment = "iwm(4) firmwares" +desc = <<EOD +iwm(4) firmwares +EOD diff --git a/release/packages/ucl/ftp-all.ucl b/release/packages/ucl/ftp-all.ucl new file mode 100644 index 000000000000..6275bc46e657 --- /dev/null +++ b/release/packages/ucl/ftp-all.ucl @@ -0,0 +1,4 @@ +comment = "FTP Utilities" +desc = <<EOD +FTP Utilities +EOD diff --git a/release/packages/ucl/ftpd-all.ucl b/release/packages/ucl/ftpd-all.ucl new file mode 100644 index 000000000000..cbaa078123d5 --- /dev/null +++ b/release/packages/ucl/ftpd-all.ucl @@ -0,0 +1,4 @@ +comment = "FTP Daemon" +desc = <<EOD +FTP Daemon +EOD diff --git a/release/packages/ucl/fwget-all.ucl b/release/packages/ucl/fwget-all.ucl new file mode 100644 index 000000000000..7a6f9dff5cc9 --- /dev/null +++ b/release/packages/ucl/fwget-all.ucl @@ -0,0 +1,4 @@ +comment = "FWGET Utility" +desc = <<EOD +FWGET Utility +EOD diff --git a/release/packages/ucl/games-all.ucl b/release/packages/ucl/games-all.ucl new file mode 100644 index 000000000000..747638fe6a8f --- /dev/null +++ b/release/packages/ucl/games-all.ucl @@ -0,0 +1,4 @@ +comment = "Games" +desc = <<EOD +Games +EOD diff --git a/release/packages/ucl/geom-all.ucl b/release/packages/ucl/geom-all.ucl new file mode 100644 index 000000000000..6d80b4458f64 --- /dev/null +++ b/release/packages/ucl/geom-all.ucl @@ -0,0 +1,4 @@ +comment = "GEOM Utilitites" +desc = <<EOD +GEOM Utilitites +EOD diff --git a/release/packages/ucl/ggate-all.ucl b/release/packages/ucl/ggate-all.ucl new file mode 100644 index 000000000000..0d0b984b440e --- /dev/null +++ b/release/packages/ucl/ggate-all.ucl @@ -0,0 +1,4 @@ +comment = "GEOM Gate Utilities" +desc = <<EOD +GEOM Gate Utilities +EOD diff --git a/release/packages/ucl/hast-all.ucl b/release/packages/ucl/hast-all.ucl new file mode 100644 index 000000000000..b2441ddb6866 --- /dev/null +++ b/release/packages/ucl/hast-all.ucl @@ -0,0 +1,4 @@ +comment = "Highly Available Storage daemon" +desc = <<EOD +Highly Available Storage daemon +EOD diff --git a/release/packages/ucl/hostapd-all.ucl b/release/packages/ucl/hostapd-all.ucl new file mode 100644 index 000000000000..c2e0d0c0bd11 --- /dev/null +++ b/release/packages/ucl/hostapd-all.ucl @@ -0,0 +1,4 @@ +comment = "802.11 Access Point Daemon an Utilities" +desc = <<EOD +802.11 Access Point Daemon an Utilities +EOD diff --git a/release/packages/ucl/hyperv-tools-all.ucl b/release/packages/ucl/hyperv-tools-all.ucl new file mode 100644 index 000000000000..e16fd5b4b053 --- /dev/null +++ b/release/packages/ucl/hyperv-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "Microsoft HyperV Utilities" +desc = <<EOD +Microsoft HyperV Utilities +EOD diff --git a/release/packages/ucl/inetd-all.ucl b/release/packages/ucl/inetd-all.ucl new file mode 100644 index 000000000000..731769bdc399 --- /dev/null +++ b/release/packages/ucl/inetd-all.ucl @@ -0,0 +1,4 @@ +comment = "Internet super-server" +desc = <<EOD +Internet super-server +EOD diff --git a/release/packages/ucl/ipf-all.ucl b/release/packages/ucl/ipf-all.ucl new file mode 100644 index 000000000000..bd1bec5232de --- /dev/null +++ b/release/packages/ucl/ipf-all.ucl @@ -0,0 +1,4 @@ +comment = "IP Filter (ipf) packet filter management tools" +desc = <<EOD +IP Filter (ipf) is a stateful packet filter for IPv4 and IPv6 networks. +EOD diff --git a/release/packages/ucl/ipfw-all.ucl b/release/packages/ucl/ipfw-all.ucl new file mode 100644 index 000000000000..0884d48aa071 --- /dev/null +++ b/release/packages/ucl/ipfw-all.ucl @@ -0,0 +1,4 @@ +comment = "ipfw (IP firewall) management utilities" +desc = <<EOD +ipfw provides stateful packet filtering, NAT and traffic shaping for IP traffic. +EOD diff --git a/release/packages/ucl/iscsi-all.ucl b/release/packages/ucl/iscsi-all.ucl new file mode 100644 index 000000000000..e81961cb40a5 --- /dev/null +++ b/release/packages/ucl/iscsi-all.ucl @@ -0,0 +1,6 @@ +comment = "iSCSI target, initiator, and management tools" +desc = <<EOD +iSCSI allows a block device to be exported from one system to another over a +network. This package provides the iSCSI target and initiator and associated +management tools. +EOD diff --git a/release/packages/ucl/jail-all.ucl b/release/packages/ucl/jail-all.ucl new file mode 100644 index 000000000000..da844b500ad5 --- /dev/null +++ b/release/packages/ucl/jail-all.ucl @@ -0,0 +1,4 @@ +comment = "Jail Utilities" +desc = <<EOD +Jail Utilities +EOD diff --git a/release/packages/ucl/kerberos-all.ucl b/release/packages/ucl/kerberos-all.ucl new file mode 100644 index 000000000000..bf82040da3d0 --- /dev/null +++ b/release/packages/ucl/kerberos-all.ucl @@ -0,0 +1,4 @@ +comment = "Kerberos utilities" +desc = <<EOD +The Kerberos command-line utilities, including kinit and kadmin. +EOD diff --git a/release/packages/ucl/kerberos-kdc-all.ucl b/release/packages/ucl/kerberos-kdc-all.ucl new file mode 100644 index 000000000000..068d2f26bc8d --- /dev/null +++ b/release/packages/ucl/kerberos-kdc-all.ucl @@ -0,0 +1,5 @@ +comment = "Kerberos key distribution center" +desc = <<EOD +The Kerberos KDC, which manages the Kerberos database and issues tickets +to clients. +EOD diff --git a/release/packages/ucl/kerberos-lib-all.ucl b/release/packages/ucl/kerberos-lib-all.ucl new file mode 100644 index 000000000000..b524563a976d --- /dev/null +++ b/release/packages/ucl/kerberos-lib-all.ucl @@ -0,0 +1,4 @@ +comment = "Kerberos libraries" +desc = <<EOD +Libraries requires to run programs that use Kerberos. +EOD diff --git a/release/packages/ucl/kernel-all.ucl b/release/packages/ucl/kernel-all.ucl new file mode 100644 index 000000000000..31671602a947 --- /dev/null +++ b/release/packages/ucl/kernel-all.ucl @@ -0,0 +1,4 @@ +comment = "FreeBSD ${KERNEL_NAME} Kernel ${KERNEL_FLAVOR}" +desc = <<EOD +FreeBSD ${KERNEL_NAME} Kernel ${KERNEL_FLAVOR} +EOD diff --git a/release/packages/ucl/lib9p-all.ucl b/release/packages/ucl/lib9p-all.ucl new file mode 100644 index 000000000000..76a5b8de4596 --- /dev/null +++ b/release/packages/ucl/lib9p-all.ucl @@ -0,0 +1,5 @@ +comment = "9P network protocol library" +desc = <<EOD +lib9p implements the server side of the 9p2000, 9p2000.u and 9p2000.L revisions +of the 9P protocol +EOD diff --git a/release/packages/ucl/libarchive-all.ucl b/release/packages/ucl/libarchive-all.ucl new file mode 100644 index 000000000000..9b98404b3235 --- /dev/null +++ b/release/packages/ucl/libarchive-all.ucl @@ -0,0 +1,4 @@ +comment = "Archive handling library" +desc = <<EOD +libarchive allows applications to read and write archive files of various types. +EOD diff --git a/release/packages/ucl/libbegemot-all.ucl b/release/packages/ucl/libbegemot-all.ucl new file mode 100644 index 000000000000..7a2f19df8e0e --- /dev/null +++ b/release/packages/ucl/libbegemot-all.ucl @@ -0,0 +1,5 @@ +comment = "rpoll(3) interface for event-driven I/O" +desc = <<EOD +libbegemot provides rpoll(3), a simplified interface for handling event-driven +I/O programming. +EOD diff --git a/release/packages/ucl/libblocksruntime-all.ucl b/release/packages/ucl/libblocksruntime-all.ucl new file mode 100644 index 000000000000..818c32174a6c --- /dev/null +++ b/release/packages/ucl/libblocksruntime-all.ucl @@ -0,0 +1,4 @@ +comment = "LLVM BlocksRuntime library" +desc = <<EOD +The LLVM libBlocksRuntime library. +EOD diff --git a/release/packages/ucl/libbsdstat-all.ucl b/release/packages/ucl/libbsdstat-all.ucl new file mode 100644 index 000000000000..4db0059827a0 --- /dev/null +++ b/release/packages/ucl/libbsdstat-all.ucl @@ -0,0 +1,5 @@ +comment = "Periodic statistics library" +desc = <<EOD +libbsdstat is a library for managing and display periodically collected +statistics. +EOD diff --git a/release/packages/ucl/libbsm-all.ucl b/release/packages/ucl/libbsm-all.ucl new file mode 100644 index 000000000000..0a60ada09075 --- /dev/null +++ b/release/packages/ucl/libbsm-all.ucl @@ -0,0 +1,6 @@ +comment = "Basic Security Module (BSM) audit library" +desc = <<EOD +The libbsm library routines provide an interface to BSM audit record streams, +allowing both the parsing of existing audit streams, as well as the creation of +new audit records and streams. +EOD diff --git a/release/packages/ucl/libbz2-all.ucl b/release/packages/ucl/libbz2-all.ucl new file mode 100644 index 000000000000..c8141bcb1d11 --- /dev/null +++ b/release/packages/ucl/libbz2-all.ucl @@ -0,0 +1,5 @@ +comment = "bzip2 compression library" +desc = <<EOD +libbz2 allows applications to compress and decompress data using the bzip2 +compression algorithm. +EOD diff --git a/release/packages/ucl/libcasper-all.ucl b/release/packages/ucl/libcasper-all.ucl new file mode 100644 index 000000000000..b25a82a32050 --- /dev/null +++ b/release/packages/ucl/libcasper-all.ucl @@ -0,0 +1,5 @@ +comment = "Casper library" +desc = <<EOD +The libcasper library provides for the control of application capabilities +through the casper process. +EOD diff --git a/release/packages/ucl/libcompat-all.ucl b/release/packages/ucl/libcompat-all.ucl new file mode 100644 index 000000000000..a562f155dc5f --- /dev/null +++ b/release/packages/ucl/libcompat-all.ucl @@ -0,0 +1,4 @@ +comment = "Compatibility library" +desc = <<EOD +libcompat provides implementations of some obsolete library functions. +EOD diff --git a/release/packages/ucl/libcompiler_rt-all.ucl b/release/packages/ucl/libcompiler_rt-all.ucl new file mode 100644 index 000000000000..f21e629ac88c --- /dev/null +++ b/release/packages/ucl/libcompiler_rt-all.ucl @@ -0,0 +1,4 @@ +comment = "LLVM compiler_rt library" +desc = <<EOD +The libcompiler_rt library from LLVM. +EOD diff --git a/release/packages/ucl/libcuse-all.ucl b/release/packages/ucl/libcuse-all.ucl new file mode 100644 index 000000000000..de972d4b8d3a --- /dev/null +++ b/release/packages/ucl/libcuse-all.ucl @@ -0,0 +1,5 @@ +comment = "Userland character device library" +desc = <<EOD +The libcuse library contains functions to create a character device in +userspace. +EOD diff --git a/release/packages/ucl/libdwarf-all.ucl b/release/packages/ucl/libdwarf-all.ucl new file mode 100644 index 000000000000..4226dbfee592 --- /dev/null +++ b/release/packages/ucl/libdwarf-all.ucl @@ -0,0 +1,6 @@ +comment = "DWARF access library" +desc = <<EOD +The DWARF Access Library provides functions that allow an application to read +and write debugging information in object files. The format of debugging +information accessible through this API is defined by the DWARF standard. +EOD diff --git a/release/packages/ucl/libevent1-all.ucl b/release/packages/ucl/libevent1-all.ucl new file mode 100644 index 000000000000..511e077233d2 --- /dev/null +++ b/release/packages/ucl/libevent1-all.ucl @@ -0,0 +1,4 @@ +comment = "Private libevent1 library" +desc = <<EOD +A private library used by applications in the base system. +EOD diff --git a/release/packages/ucl/libexecinfo-all.ucl b/release/packages/ucl/libexecinfo-all.ucl new file mode 100644 index 000000000000..8a0c110381be --- /dev/null +++ b/release/packages/ucl/libexecinfo-all.ucl @@ -0,0 +1,5 @@ +comment = "NetBSD stack backtrace library" +desc = <<EOD +libexecinfo provides the backtrace(3) interface to allow an application to +examine its current call stack. +EOD diff --git a/release/packages/ucl/libipt-all.ucl b/release/packages/ucl/libipt-all.ucl new file mode 100644 index 000000000000..eb0ef6a32d40 --- /dev/null +++ b/release/packages/ucl/libipt-all.ucl @@ -0,0 +1,6 @@ +comment = "Intel(R) Processor Trace decoder library" +desc = <<EOD +The Intel Processor Trace (Intel PT) Decoder Library is Intel's reference +implementation for decoding Intel PT. It can be used as a standalone library +or it can be partially or fully integrated into your tool. +EOD diff --git a/release/packages/ucl/libldns-all.ucl b/release/packages/ucl/libldns-all.ucl new file mode 100644 index 000000000000..55de2701bbb8 --- /dev/null +++ b/release/packages/ucl/libldns-all.ucl @@ -0,0 +1,6 @@ +comment="NLnet Labs LDNS library" +desc = <<EOD +The goal of ldns is to simplify DNS programming in C. ldns supports all +low-level DNS and DNSSEC operations. It also defines a higher level API which +allows a programmer to for instance create or sign packets. +EOD diff --git a/release/packages/ucl/liblzma-all.ucl b/release/packages/ucl/liblzma-all.ucl new file mode 100644 index 000000000000..0b1bfcbcecc6 --- /dev/null +++ b/release/packages/ucl/liblzma-all.ucl @@ -0,0 +1,5 @@ +comment = "XZ LZMA library" +desc = <<EOD +liblzma allows applications to compress and decompress data using the XZ +compression algorithm. +EOD diff --git a/release/packages/ucl/libmagic-all.ucl b/release/packages/ucl/libmagic-all.ucl new file mode 100644 index 000000000000..2a29aacb260d --- /dev/null +++ b/release/packages/ucl/libmagic-all.ucl @@ -0,0 +1,5 @@ +comment = "Magic number recognition library" +desc = <<EOD +libmagic allows an application to identity data using the magic(5) magic number +database. +EOD diff --git a/release/packages/ucl/libopencsd-all.ucl b/release/packages/ucl/libopencsd-all.ucl new file mode 100644 index 000000000000..af46292dceed --- /dev/null +++ b/release/packages/ucl/libopencsd-all.ucl @@ -0,0 +1,5 @@ +comment = "ARM CoreSight Trace Decode Library" +desc = <<EOD +This library provides an API suitable for the decode of ARM CoreSight +trace streams. +EOD diff --git a/release/packages/ucl/libpathconv-all.ucl b/release/packages/ucl/libpathconv-all.ucl new file mode 100644 index 000000000000..872d34a24e6a --- /dev/null +++ b/release/packages/ucl/libpathconv-all.ucl @@ -0,0 +1,5 @@ +comment = "Library for handling relative and absolute pathnames" +desc = <<EOD +libpathconv provides the abs2rel() and rel2abs() functions to convert between +absolute and relative pathnames. +EOD diff --git a/release/packages/ucl/librpcsec_gss-all.ucl b/release/packages/ucl/librpcsec_gss-all.ucl new file mode 100644 index 000000000000..67f481e9e9b5 --- /dev/null +++ b/release/packages/ucl/librpcsec_gss-all.ucl @@ -0,0 +1,5 @@ +comment = "RPC GSS-API authentication library" +desc = <<EOD +librpcsec_gss provides an API to allow applications to interact with the +RPCSEC_GSS security mechanism. +EOD diff --git a/release/packages/ucl/librss-all.ucl b/release/packages/ucl/librss-all.ucl new file mode 100644 index 000000000000..3c09025356a8 --- /dev/null +++ b/release/packages/ucl/librss-all.ucl @@ -0,0 +1,5 @@ +comment = "Receive-side scaling library" +desc = <<EOD +The librss library and the functions it provides are used for both fetching the +system RSS configuration and interacting with RSS aware sockets. +EOD diff --git a/release/packages/ucl/libsdp-all.ucl b/release/packages/ucl/libsdp-all.ucl new file mode 100644 index 000000000000..31f04e089470 --- /dev/null +++ b/release/packages/ucl/libsdp-all.ucl @@ -0,0 +1,5 @@ +comment = "Bluetooth Service Discovery Protocol library" +desc = <<EOD +libsdp allows applications to interact with the Bluetooth Service Discovery +Protocol. +EOD diff --git a/release/packages/ucl/libsqlite3-all.ucl b/release/packages/ucl/libsqlite3-all.ucl new file mode 100644 index 000000000000..55ac00863bf1 --- /dev/null +++ b/release/packages/ucl/libsqlite3-all.ucl @@ -0,0 +1,4 @@ +comment = "Private SQLite library" +desc = <<EOD +A private version of SQLite for use by applications in the base system. +EOD diff --git a/release/packages/ucl/libstdbuf-all.ucl b/release/packages/ucl/libstdbuf-all.ucl new file mode 100644 index 000000000000..d85f2d3b70f2 --- /dev/null +++ b/release/packages/ucl/libstdbuf-all.ucl @@ -0,0 +1,6 @@ +comment = "Preloaded library to change standard streams initial buffering" +desc = <<EOD +The libstdbuf library is meant to be preloaded with the LD_PRELOAD environment +variable to as to change the initial buffering of standard input, standard +output and standard error streams. +EOD diff --git a/release/packages/ucl/libstdthreads-all.ucl b/release/packages/ucl/libstdthreads-all.ucl new file mode 100644 index 000000000000..5af147ea5ca7 --- /dev/null +++ b/release/packages/ucl/libstdthreads-all.ucl @@ -0,0 +1,4 @@ +comment = "C11 threading library" +desc = <<EOD +libstdthreads provides the thread-control interface defined in the C99 standard. +EOD diff --git a/release/packages/ucl/libthread_db-all.ucl b/release/packages/ucl/libthread_db-all.ucl new file mode 100644 index 000000000000..ba2164a3f211 --- /dev/null +++ b/release/packages/ucl/libthread_db-all.ucl @@ -0,0 +1,5 @@ +comment = "Library for interacting with threaded processes" +desc = <<EOD +libthread_db is used by the debugger to examine and interact with a +multithreaded process being debugger. +EOD diff --git a/release/packages/ucl/libucl-all.ucl b/release/packages/ucl/libucl-all.ucl new file mode 100644 index 000000000000..d04c2109df06 --- /dev/null +++ b/release/packages/ucl/libucl-all.ucl @@ -0,0 +1,5 @@ +comment = "Private Universal Configuration Library (UCL) library" +desc = <<EOD +A private library for reading and writing UCL files, for used by applications +in the base system. +EOD diff --git a/release/packages/ucl/libufs-all.ucl b/release/packages/ucl/libufs-all.ucl new file mode 100644 index 000000000000..d86a84bbd637 --- /dev/null +++ b/release/packages/ucl/libufs-all.ucl @@ -0,0 +1,8 @@ +comment = "Low-level access to UFS filesystems" +desc = <<EOD +The libufs library and the functions it provides are used for implementing +utilities which need to access a UFS file system at a low level from userland. +Facilities provided are used to implement utilities such as newfs(8) and +dumpfs(8). The libufs library is designed to be simple, and to provide +functions that are traditionally useful to have. +EOD diff --git a/release/packages/ucl/libvgl-all.ucl b/release/packages/ucl/libvgl-all.ucl new file mode 100644 index 000000000000..fea63d807de0 --- /dev/null +++ b/release/packages/ucl/libvgl-all.ucl @@ -0,0 +1,13 @@ +comment = "Video Graphics Library" +desc = <<EOD +libvgl is a library that enables the programmer access to the graphics modes +supported by the console driver (syscons). The library takes care of +programming the actual video hardware, and provides a number of simple +functions to do various graphic operations. There is also support for a mouse +via the standard mouse system in FreeBSD, including the ability to +transparently have a mouse pointer superimposed on the graphic image currently +being worked on. The library takes care of screen switching by storing the +current image in memory before switching to another virtual console, and +restoring when the user switches back. This allows several graphic +applications at once, but on different virtual consoles. +EOD diff --git a/release/packages/ucl/libvmmapi-all.ucl b/release/packages/ucl/libvmmapi-all.ucl new file mode 100644 index 000000000000..976fb1bfce47 --- /dev/null +++ b/release/packages/ucl/libvmmapi-all.ucl @@ -0,0 +1,4 @@ +comment = "Front-end to vmm(4) virtualization driver" +desc = <<EOD +libvmmapi provides an interface for applications to access the vmm(4) driver. +EOD diff --git a/release/packages/ucl/liby-all.ucl b/release/packages/ucl/liby-all.ucl new file mode 100644 index 000000000000..575aeda0a1ef --- /dev/null +++ b/release/packages/ucl/liby-all.ucl @@ -0,0 +1,5 @@ +comment = "YACC library" +desc = <<EOD +liby provides default implementations of main() and yyerror() for use with +applications which use yacc(1). +EOD diff --git a/release/packages/ucl/libyaml-all.ucl b/release/packages/ucl/libyaml-all.ucl new file mode 100644 index 000000000000..f98a5a39362f --- /dev/null +++ b/release/packages/ucl/libyaml-all.ucl @@ -0,0 +1,5 @@ +comment = "Private YAML library" +desc = <<EOD +The libprivateyaml library is used by the FreeBSD base system to parse YAML +files. This library is not intended for use outside of the base system. +EOD diff --git a/release/packages/ucl/libzfs-all.ucl b/release/packages/ucl/libzfs-all.ucl new file mode 100644 index 000000000000..bd53521f3aa0 --- /dev/null +++ b/release/packages/ucl/libzfs-all.ucl @@ -0,0 +1,5 @@ +comment = "ZFS filesystem library" +desc = <<EOD +libzfs allows applications to manage ZFS pools and filesystems. Several +libraries which libzfs requires are also provided. +EOD diff --git a/release/packages/ucl/lld-all.ucl b/release/packages/ucl/lld-all.ucl new file mode 100644 index 000000000000..03daf1b235e6 --- /dev/null +++ b/release/packages/ucl/lld-all.ucl @@ -0,0 +1,6 @@ +comment = "ELF linker from the LLVM project" +desc = <<EOD +ld.lld is the ELF linker provided by LLVM. +EOD + +licenses = [ NCSA ] diff --git a/release/packages/ucl/lldb-all.ucl b/release/packages/ucl/lldb-all.ucl new file mode 100644 index 000000000000..da481c026981 --- /dev/null +++ b/release/packages/ucl/lldb-all.ucl @@ -0,0 +1,6 @@ +comment = "LLVM debugger" +desc = <<EOD +lldb is a source-level debugger from the LLVM project. +EOD + +licenses = [ NCSA ] diff --git a/release/packages/ucl/locales-all.ucl b/release/packages/ucl/locales-all.ucl new file mode 100644 index 000000000000..6fc53ab10fca --- /dev/null +++ b/release/packages/ucl/locales-all.ucl @@ -0,0 +1,4 @@ +comment = "Locale definitions" +desc = <<EOD +Provides the locale definitions (LC_*) for supported locales. +EOD diff --git a/release/packages/ucl/lp-all.ucl b/release/packages/ucl/lp-all.ucl new file mode 100644 index 000000000000..c400038458d0 --- /dev/null +++ b/release/packages/ucl/lp-all.ucl @@ -0,0 +1,4 @@ +comment = "Printer subsystem" +desc = <<EOD +Printer subsystem +EOD diff --git a/release/packages/ucl/manuals-all.ucl b/release/packages/ucl/manuals-all.ucl new file mode 100644 index 000000000000..9acfd90159ae --- /dev/null +++ b/release/packages/ucl/manuals-all.ucl @@ -0,0 +1,4 @@ +comment = "Manual Pages" +desc = <<EOD +Manual Pages +EOD diff --git a/release/packages/ucl/mlx-tools-all.ucl b/release/packages/ucl/mlx-tools-all.ucl new file mode 100644 index 000000000000..4af47252c71d --- /dev/null +++ b/release/packages/ucl/mlx-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "Mellanox Utilities" +desc = <<EOD +Mellanox Utilities +EOD diff --git a/release/packages/ucl/mtree-all.ucl b/release/packages/ucl/mtree-all.ucl new file mode 100644 index 000000000000..b921c51a6afb --- /dev/null +++ b/release/packages/ucl/mtree-all.ucl @@ -0,0 +1,4 @@ +comment = "MTREE Files" +desc = <<EOD +MTREE Files +EOD diff --git a/release/packages/ucl/natd-all.ucl b/release/packages/ucl/natd-all.ucl new file mode 100644 index 000000000000..db5103c1d591 --- /dev/null +++ b/release/packages/ucl/natd-all.ucl @@ -0,0 +1,4 @@ +comment = "Network Address Translation (NAT) daemon for ipfw" +desc = <<EOD +natd provides userland NAT support for ipfw using divert(4) sockets. +EOD diff --git a/release/packages/ucl/netmap-all.ucl b/release/packages/ucl/netmap-all.ucl new file mode 100644 index 000000000000..e0c0c65b8fb8 --- /dev/null +++ b/release/packages/ucl/netmap-all.ucl @@ -0,0 +1,4 @@ +comment = "Netmap Library and Utilities" +desc = <<EOD +Netmap Library and Utilities +EOD diff --git a/release/packages/ucl/newsyslog-all.ucl b/release/packages/ucl/newsyslog-all.ucl new file mode 100644 index 000000000000..e52b34dbdcba --- /dev/null +++ b/release/packages/ucl/newsyslog-all.ucl @@ -0,0 +1,4 @@ +comment = "Newsyslog Utility" +desc = <<EOD +Newsyslog Utility +EOD diff --git a/release/packages/ucl/nfs-all.ucl b/release/packages/ucl/nfs-all.ucl new file mode 100644 index 000000000000..a53d2f028975 --- /dev/null +++ b/release/packages/ucl/nfs-all.ucl @@ -0,0 +1,4 @@ +comment = "NFS Utilities" +desc = <<EOD +NFS Utilities +EOD diff --git a/release/packages/ucl/ntp-all.ucl b/release/packages/ucl/ntp-all.ucl new file mode 100644 index 000000000000..c01ae91c31cf --- /dev/null +++ b/release/packages/ucl/ntp-all.ucl @@ -0,0 +1,4 @@ +comment = "Network Time Protocol server and client" +desc = <<EOD +Network Time Protocol server and client +EOD diff --git a/release/packages/ucl/nuageinit-all.ucl b/release/packages/ucl/nuageinit-all.ucl new file mode 100644 index 000000000000..4d510b799fa7 --- /dev/null +++ b/release/packages/ucl/nuageinit-all.ucl @@ -0,0 +1,4 @@ +comment = "CloudInit support scripts" +desc = <<EOD +CloudInit support scripts +EOD diff --git a/release/packages/ucl/nvme-tools-all.ucl b/release/packages/ucl/nvme-tools-all.ucl new file mode 100644 index 000000000000..5863af2d5e34 --- /dev/null +++ b/release/packages/ucl/nvme-tools-all.ucl @@ -0,0 +1,4 @@ +comment = "NVME Utilities" +desc = <<EOD +NVME Utilities +EOD diff --git a/release/packages/ucl/openssl-all.ucl b/release/packages/ucl/openssl-all.ucl new file mode 100644 index 000000000000..8dd2da021f0a --- /dev/null +++ b/release/packages/ucl/openssl-all.ucl @@ -0,0 +1,4 @@ +comment = "OpenSSL Utility" +desc = <<EOD +OpenSSL Utility +EOD diff --git a/release/packages/ucl/openssl-lib-all.ucl b/release/packages/ucl/openssl-lib-all.ucl new file mode 100644 index 000000000000..c81dd44855cd --- /dev/null +++ b/release/packages/ucl/openssl-lib-all.ucl @@ -0,0 +1,4 @@ +comment = "OpenSSL Libraries" +desc = <<EOD +OpenSSL Libraries +EOD diff --git a/release/packages/ucl/periodic-all.ucl b/release/packages/ucl/periodic-all.ucl new file mode 100644 index 000000000000..569bf8d829c4 --- /dev/null +++ b/release/packages/ucl/periodic-all.ucl @@ -0,0 +1,4 @@ +comment = "Periodic Utility" +desc = <<EOD +Periodic Utility +EOD diff --git a/release/packages/ucl/periodic.ucl b/release/packages/ucl/periodic.ucl new file mode 100644 index 000000000000..6f85d2ab744b --- /dev/null +++ b/release/packages/ucl/periodic.ucl @@ -0,0 +1,6 @@ +deps { + "cron" { + version = "${VERSION}" + origin = "base" + } +} diff --git a/release/packages/ucl/pf-all.ucl b/release/packages/ucl/pf-all.ucl new file mode 100644 index 000000000000..4b58fa4f6364 --- /dev/null +++ b/release/packages/ucl/pf-all.ucl @@ -0,0 +1,4 @@ +comment = "OpenBSD packet filter" +desc = <<EOD +pf is an advanced stateful packet filter developed by the OpenBSD project. +EOD diff --git a/release/packages/ucl/pkg-bootstrap-all.ucl b/release/packages/ucl/pkg-bootstrap-all.ucl new file mode 100644 index 000000000000..9ca6ccd2af58 --- /dev/null +++ b/release/packages/ucl/pkg-bootstrap-all.ucl @@ -0,0 +1,4 @@ +comment = "pkg bootstrap Utility" +desc = <<EOD +pkg bootstrap Utility +EOD diff --git a/release/packages/ucl/ppp-all.ucl b/release/packages/ucl/ppp-all.ucl new file mode 100644 index 000000000000..454e54b7b872 --- /dev/null +++ b/release/packages/ucl/ppp-all.ucl @@ -0,0 +1,5 @@ +comment = "Userland PPP implementation" +desc = <<EOD +ppp(8) is a userland implementations of the Point to Point Protocol for serial +lines and Ethernet (PPPoE). +EOD diff --git a/release/packages/ucl/quotacheck-all.ucl b/release/packages/ucl/quotacheck-all.ucl new file mode 100644 index 000000000000..18b2c3d9bd5c --- /dev/null +++ b/release/packages/ucl/quotacheck-all.ucl @@ -0,0 +1,8 @@ +comment = "Filesystem quota consistency checker" +desc = <<EOD +The quotacheck utility examines each file system, builds a table of current +disk usage, and compares this table against that recorded in the disk quota +file for the file system. If any inconsistencies are detected, both the quota +file and the current system copy of the incorrect quotas are updated (the +latter only occurs if an active file system is checked). +EOD diff --git a/release/packages/ucl/rc-all.ucl b/release/packages/ucl/rc-all.ucl new file mode 100644 index 000000000000..04ed0dafacf0 --- /dev/null +++ b/release/packages/ucl/rc-all.ucl @@ -0,0 +1,4 @@ +comment = "RC Scripts" +desc = <<EOD +RC Scripts +EOD diff --git a/release/packages/ucl/rcmds-all.ucl b/release/packages/ucl/rcmds-all.ucl new file mode 100644 index 000000000000..db51d52ed246 --- /dev/null +++ b/release/packages/ucl/rcmds-all.ucl @@ -0,0 +1,7 @@ +comment = "BSD/SunOS remote status commands" +desc = <<EOD +The BSD/SunOS remote status commands, which can be used to query or interact +with remote hosts over the network. This includes the command-line utilities +rwho, ruptime, rup, rusers and rwall and the daemons rwhod, rpc.rstatd, +rpc.rusersd, and rpc.rwalld. +EOD diff --git a/release/packages/ucl/rcmds.ucl b/release/packages/ucl/rcmds.ucl new file mode 100644 index 000000000000..88a4916675dc --- /dev/null +++ b/release/packages/ucl/rcmds.ucl @@ -0,0 +1,8 @@ +deps { + # The RPC daemons require rpcbind. + "utilities" { + version = "${VERSION}" + origin = "base" + } +} + diff --git a/release/packages/ucl/rdma-all.ucl b/release/packages/ucl/rdma-all.ucl new file mode 100644 index 000000000000..313c2b7d17e0 --- /dev/null +++ b/release/packages/ucl/rdma-all.ucl @@ -0,0 +1 @@ +comment = "RDMA Utilities" diff --git a/release/packages/ucl/rescue-all.ucl b/release/packages/ucl/rescue-all.ucl new file mode 100644 index 000000000000..da870079bbb7 --- /dev/null +++ b/release/packages/ucl/rescue-all.ucl @@ -0,0 +1,4 @@ +comment = "Rescue Utilities" +desc = <<EOD +Rescue Utilities +EOD diff --git a/release/packages/ucl/resolvconf-all.ucl b/release/packages/ucl/resolvconf-all.ucl new file mode 100644 index 000000000000..a2d2e0debfa1 --- /dev/null +++ b/release/packages/ucl/resolvconf-all.ucl @@ -0,0 +1,4 @@ +comment = "Resolvconf Utility and scripts" +desc = <<EOD +Resolvconf Utility and scripts +EOD diff --git a/release/packages/ucl/runtime-all.ucl b/release/packages/ucl/runtime-all.ucl new file mode 100644 index 000000000000..f614a3ef3d43 --- /dev/null +++ b/release/packages/ucl/runtime-all.ucl @@ -0,0 +1,4 @@ +comment = "FreeBSD Base System" +desc = <<EOD +FreeBSD Base System +EOD diff --git a/release/packages/runtime.ucl b/release/packages/ucl/runtime.ucl index b04bc32f33cc..b04bc32f33cc 100644 --- a/release/packages/runtime.ucl +++ b/release/packages/ucl/runtime.ucl diff --git a/release/packages/ucl/sendmail-all.ucl b/release/packages/ucl/sendmail-all.ucl new file mode 100644 index 000000000000..2711e33a31a8 --- /dev/null +++ b/release/packages/ucl/sendmail-all.ucl @@ -0,0 +1,4 @@ +comment = "Sendmail Utilities" +desc = <<EOD +Sendmail Utilities +EOD diff --git a/release/packages/ucl/smbutils-all.ucl b/release/packages/ucl/smbutils-all.ucl new file mode 100644 index 000000000000..779179ca3875 --- /dev/null +++ b/release/packages/ucl/smbutils-all.ucl @@ -0,0 +1,4 @@ +comment = "SMB Utilities" +desc = <<EOD +SMB Utilities +EOD diff --git a/release/packages/ucl/src-all.ucl b/release/packages/ucl/src-all.ucl new file mode 100644 index 000000000000..15b2b7d5b29d --- /dev/null +++ b/release/packages/ucl/src-all.ucl @@ -0,0 +1,5 @@ +comment = "System userland source code" +desc = <<EOD +The source code used to rebuild the system, located in /usr/src. +This package includes everything except the kernel source code. +EOD diff --git a/release/packages/ucl/src-sys-all.ucl b/release/packages/ucl/src-sys-all.ucl new file mode 100644 index 000000000000..9b1c5b64bfbb --- /dev/null +++ b/release/packages/ucl/src-sys-all.ucl @@ -0,0 +1,5 @@ +comment = "System kernel source code" +desc = <<EOD +The source code used to rebuild the system, located in /usr/src. +This package includes the kernel source code. +EOD diff --git a/release/packages/ucl/ssh-all.ucl b/release/packages/ucl/ssh-all.ucl new file mode 100644 index 000000000000..8159391eab08 --- /dev/null +++ b/release/packages/ucl/ssh-all.ucl @@ -0,0 +1,5 @@ +comment = "Secure Shell Utilities" +desc = <<EOD +Secure Shell Utilities +EOD +licenses = [ ISCL ] diff --git a/release/packages/ucl/syscons-data-all.ucl b/release/packages/ucl/syscons-data-all.ucl new file mode 100644 index 000000000000..9f59bfd60588 --- /dev/null +++ b/release/packages/ucl/syscons-data-all.ucl @@ -0,0 +1,4 @@ +comment = "syscons(4) fonts and keymaps" +desc = <<EOD +Fonts and keymaps for use with the legacy syscons(4) video console driver. +EOD diff --git a/release/packages/ucl/syslogd-all.ucl b/release/packages/ucl/syslogd-all.ucl new file mode 100644 index 000000000000..0f82c31fdf0f --- /dev/null +++ b/release/packages/ucl/syslogd-all.ucl @@ -0,0 +1,4 @@ +comment = "Syslog Daemon" +desc = <<EOD +Syslog Daemon +EOD diff --git a/release/packages/ucl/tcpd-all.ucl b/release/packages/ucl/tcpd-all.ucl new file mode 100644 index 000000000000..13b7449af267 --- /dev/null +++ b/release/packages/ucl/tcpd-all.ucl @@ -0,0 +1,4 @@ +comment = "TCP Wrapper utilities" +desc = <<EOD +TCP Wrapper utilities +EOD diff --git a/release/packages/ucl/telnet-all.ucl b/release/packages/ucl/telnet-all.ucl new file mode 100644 index 000000000000..e235b0d776eb --- /dev/null +++ b/release/packages/ucl/telnet-all.ucl @@ -0,0 +1,4 @@ +comment = "Telnet client" +desc = <<EOD +Telnet client +EOD diff --git a/release/packages/ucl/tests-all.ucl b/release/packages/ucl/tests-all.ucl new file mode 100644 index 000000000000..39bd365bee5b --- /dev/null +++ b/release/packages/ucl/tests-all.ucl @@ -0,0 +1,4 @@ +comment = "Test Suite" +desc = <<EOD +Test Suite +EOD diff --git a/release/packages/ucl/toolchain-all.ucl b/release/packages/ucl/toolchain-all.ucl new file mode 100644 index 000000000000..dd6517745722 --- /dev/null +++ b/release/packages/ucl/toolchain-all.ucl @@ -0,0 +1,4 @@ +comment = "Utilities for program development" +desc = <<EOD +Utilities for program development. +EOD diff --git a/release/packages/ucl/ufs-all.ucl b/release/packages/ucl/ufs-all.ucl new file mode 100644 index 000000000000..48f9975e0dbd --- /dev/null +++ b/release/packages/ucl/ufs-all.ucl @@ -0,0 +1,4 @@ +comment = "UFS Libraries and Utilities" +desc = <<EOD +UFS Libraries and Utilities +EOD diff --git a/release/packages/ucl/unbound-all.ucl b/release/packages/ucl/unbound-all.ucl new file mode 100644 index 000000000000..700c9e4cf9d0 --- /dev/null +++ b/release/packages/ucl/unbound-all.ucl @@ -0,0 +1,5 @@ +comment = "Unbound DNS Resolver" +desc = <<EOD +Unbound DNS Resolver +EOD +licenses = [ BSD4CLAUSE ] diff --git a/release/packages/ucl/utilities-all.ucl b/release/packages/ucl/utilities-all.ucl new file mode 100644 index 000000000000..aeb82b0cfed5 --- /dev/null +++ b/release/packages/ucl/utilities-all.ucl @@ -0,0 +1,4 @@ +comment = "Non-vital programs and libraries" +desc = <<EOD +Non-vital programs and libraries +EOD diff --git a/release/packages/utilities.ucl b/release/packages/ucl/utilities.ucl index 4eb98cae292a..4eb98cae292a 100644 --- a/release/packages/utilities.ucl +++ b/release/packages/ucl/utilities.ucl diff --git a/release/packages/ucl/vi-all.ucl b/release/packages/ucl/vi-all.ucl new file mode 100644 index 000000000000..c2ad2f8e95eb --- /dev/null +++ b/release/packages/ucl/vi-all.ucl @@ -0,0 +1,4 @@ +comment = "Vi Editor" +desc = <<EOD +Vi Editor +EOD diff --git a/release/packages/ucl/vt-data-all.ucl b/release/packages/ucl/vt-data-all.ucl new file mode 100644 index 000000000000..4142b2eeae70 --- /dev/null +++ b/release/packages/ucl/vt-data-all.ucl @@ -0,0 +1,4 @@ +comment = "vt(4) fonts and keymaps" +desc = <<EOD +Fonts and keymaps for use with the vt(4) video console driver. +EOD diff --git a/release/packages/ucl/wpa-all.ucl b/release/packages/ucl/wpa-all.ucl new file mode 100644 index 000000000000..e5ad7f36db95 --- /dev/null +++ b/release/packages/ucl/wpa-all.ucl @@ -0,0 +1,4 @@ +comment = "802.11 Supplicant" +desc = <<EOD +802.11 Supplicant +EOD diff --git a/release/packages/ucl/yp-all.ucl b/release/packages/ucl/yp-all.ucl new file mode 100644 index 000000000000..9e17cd108d84 --- /dev/null +++ b/release/packages/ucl/yp-all.ucl @@ -0,0 +1,7 @@ +comment = "Yellow Pages (YP) / Network Information Service (NIS)" +desc = <<EOD +YP, also called NIS, is a network protocol for sharing name service +information across machines on a network. This packages contains the YP +server, YP management utilities, the YP-LDAP gateway (ypldap), YP client +utilities and a sample Makefile for building the YP database. +EOD diff --git a/release/packages/ucl/zfs-all.ucl b/release/packages/ucl/zfs-all.ucl new file mode 100644 index 000000000000..f4178acc481c --- /dev/null +++ b/release/packages/ucl/zfs-all.ucl @@ -0,0 +1,4 @@ +comment = "ZFS Libraries and Utilities" +desc = <<EOD +ZFS Libraries and Utilities +EOD diff --git a/release/packages/ucl/zoneinfo-all.ucl b/release/packages/ucl/zoneinfo-all.ucl new file mode 100644 index 000000000000..39991bf144e6 --- /dev/null +++ b/release/packages/ucl/zoneinfo-all.ucl @@ -0,0 +1,5 @@ +comment = "Timezone database" +desc = <<EOD +The timezone database allows applications to convert dates and times between +UTC and local timezones. +EOD diff --git a/release/packages/unbound-all.ucl b/release/packages/unbound-all.ucl deleted file mode 100644 index 78bb1f284ff2..000000000000 --- a/release/packages/unbound-all.ucl +++ /dev/null @@ -1 +0,0 @@ -licenses = [ BSD4CLAUSE ] diff --git a/release/powerpc/mkisoimages.sh b/release/powerpc/mkisoimages.sh index ba7c32f87bee..9d83390f1a4e 100644 --- a/release/powerpc/mkisoimages.sh +++ b/release/powerpc/mkisoimages.sh @@ -24,6 +24,9 @@ set -e +scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr + if [ "$1" = "-b" ]; then MAKEFSARG="$4" else @@ -107,7 +110,7 @@ echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab" if [ -n "${METALOG}" ]; then echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@" +${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 rm $BOOTBLOCK diff --git a/release/riscv/make-memstick.sh b/release/riscv/make-memstick.sh index 90ff98b394c7..0da59c29635b 100755 --- a/release/riscv/make-memstick.sh +++ b/release/riscv/make-memstick.sh @@ -17,6 +17,7 @@ if [ "$(uname -s)" = "FreeBSD" ]; then fi scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh if [ $# -ne 2 ]; then @@ -51,7 +52,7 @@ if [ -n "${METALOG}" ]; then echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename} MAKEFSARG=${metalogfilename} fi -makefs -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} +${MAKEFS} -D -N ${BASEBITSDIR}/etc -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG} rm ${BASEBITSDIR}/etc/fstab rm ${BASEBITSDIR}/etc/rc.conf.local if [ -n "${METALOG}" ]; then @@ -62,7 +63,7 @@ fi espfilename=$(mktemp /tmp/efiboot.XXXXXX) make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi -mkimg -s gpt \ +${MKIMG} -s gpt \ -p efi:=${espfilename} \ -p freebsd-ufs:=${2}.part \ -o ${2} diff --git a/release/riscv/mkisoimages.sh b/release/riscv/mkisoimages.sh index cb58178ed4b9..46b16f0ce08d 100644 --- a/release/riscv/mkisoimages.sh +++ b/release/riscv/mkisoimages.sh @@ -21,20 +21,9 @@ set -e scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh -if [ -z $ETDUMP ]; then - ETDUMP=etdump -fi - -if [ -z $MAKEFS ]; then - MAKEFS=makefs -fi - -if [ -z $MKIMG ]; then - MKIMG=mkimg -fi - if [ "$1" = "-b" ]; then MAKEFSARG="$4" else diff --git a/release/scripts/make-oci-image.sh b/release/scripts/make-oci-image.sh index cc599c76bd51..8a620e9d8973 100644 --- a/release/scripts/make-oci-image.sh +++ b/release/scripts/make-oci-image.sh @@ -22,16 +22,16 @@ echo "Building OCI freebsd${major}-${image} image for ${abi}" init_repo() { local workdir=$1; shift local abi=$1; shift + local srcdir=$(realpath ${curdir}/..) mkdir -p ${workdir}/repos cat > ${workdir}/repos/base.conf <<EOF FreeBSD-base: { - url: "file:///usr/obj/usr/src/repo/${abi}/latest" + url: "file:///usr/obj${srcdir}/repo/${abi}/latest" signature_type: "none" fingerprints: "none" } EOF - cp /etc/pkg/FreeBSD.conf ${workdir}/repos } # Install packages using pkg(8) into a container with rootfs at $3 diff --git a/release/scripts/tools.subr b/release/scripts/tools.subr new file mode 100644 index 000000000000..e818f0a55410 --- /dev/null +++ b/release/scripts/tools.subr @@ -0,0 +1,13 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 The FreeBSD Foundation +# +# This software was developed by Klara, Inc. +# under sponsorship from the FreeBSD Foundation. +# + +: ${ETDUMP:=etdump} +: ${MAKEFS:=makefs} +: ${MKIMG:=mkimg} diff --git a/release/tools/oci-image-static.conf b/release/tools/oci-image-static.conf index 753a03af653b..8e642d9defce 100644 --- a/release/tools/oci-image-static.conf +++ b/release/tools/oci-image-static.conf @@ -14,7 +14,7 @@ oci_image_build() { mtree -deU -p $m/usr -f ${srcdir}/etc/mtree/BSD.usr.dist > /dev/null mtree -deU -p $m/usr/include -f ${srcdir}/etc/mtree/BSD.include.dist > /dev/null mtree -deU -p $m/usr/lib -f ${srcdir}/etc/mtree/BSD.debug.dist > /dev/null - install_packages ${abi} ${workdir} FreeBSD-caroot FreeBSD-zoneinfo + install_packages ${abi} ${workdir} FreeBSD-zoneinfo cp ${srcdir}/etc/master.passwd $m/etc pwd_mkdb -p -d $m/etc $m/etc/master.passwd || return $? cp ${srcdir}/etc/group $m/etc || return $? @@ -22,7 +22,10 @@ oci_image_build() { # working directory to OBJDIR/release cp ../etc/termcap/termcap.small $m/etc/termcap.small || return $? cp ../etc/termcap/termcap.small $m/usr/share/misc/termcap || return $? - env DESTDIR=$m /usr/sbin/certctl rehash + env DESTDIR=$m \ + TRUSTPATH=${srcdir}/secure/caroot/trusted \ + UNTRUSTPATH=${srcdir}/secure/caroot/untrusted \ + certctl -c rehash # Generate a suitable repo config for pkgbase case ${branch} in CURRENT|STABLE|BETA*) diff --git a/release/tools/vmimage.subr b/release/tools/vmimage.subr index ce0ea03c096c..eb816018e9d3 100644 --- a/release/tools/vmimage.subr +++ b/release/tools/vmimage.subr @@ -6,6 +6,7 @@ # scriptdir=$(dirname $(realpath $0)) +. ${scriptdir}/../scripts/tools.subr . ${scriptdir}/../../tools/boot/install-boot.sh export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" @@ -209,11 +210,11 @@ buildfs() { case "${VMFS}" in ufs) - cd ${DESTDIR} && makefs ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ + cd ${DESTDIR} && ${MAKEFS} ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ ${VMBASE} .${NO_ROOT:+/METALOG} ;; zfs) - cd ${DESTDIR} && makefs -t zfs ${MAKEFSARGS} \ + cd ${DESTDIR} && ${MAKEFS} -t zfs ${MAKEFSARGS} \ -o poolname=zroot -o bootfs=zroot/ROOT/default -o rootpath=/ \ -o fs=zroot\;mountpoint=none \ -o fs=zroot/ROOT\;mountpoint=none \ @@ -342,7 +343,7 @@ vm_create_disk() { buildfs echo "Building final disk image... Please wait." - mkimg -s ${PARTSCHEME} -f ${VMFORMAT} \ + ${MKIMG} -s ${PARTSCHEME} -f ${VMFORMAT} \ ${BOOTPARTS} \ ${SWAPOPT} \ ${CONFIG_DRIVE} \ diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index d7a3fee57870..1ff405244cde 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -153,6 +153,8 @@ static volatile sig_atomic_t romeo_must_die = 0; static const char *configfile = CF; +static char vm_guest[80]; + static void devdlog(int priority, const char* message, ...) __printflike(2, 3); static void event_loop(void); @@ -867,6 +869,8 @@ process_event(char *buffer) cfg.set_variable("timestamp", timestr); free(timestr); + cfg.set_variable("vm_guest", vm_guest); + // Match doesn't have a device, and the format is a little // different, so handle it separately. switch (type) { @@ -1107,6 +1111,14 @@ event_loop(void) err(1, "select"); } else if (rv == 0) check_clients(); + /* + * Aside from the socket type, both sockets use the same + * protocol, so we can process clients the same way. + */ + if (FD_ISSET(stream_fd, &fds)) + new_client(stream_fd, SOCK_STREAM); + if (FD_ISSET(seqpacket_fd, &fds)) + new_client(seqpacket_fd, SOCK_SEQPACKET); if (FD_ISSET(fd, &fds)) { rv = read(fd, buffer, sizeof(buffer) - 1); if (rv > 0) { @@ -1135,14 +1147,6 @@ event_loop(void) break; } } - if (FD_ISSET(stream_fd, &fds)) - new_client(stream_fd, SOCK_STREAM); - /* - * Aside from the socket type, both sockets use the same - * protocol, so we can process clients the same way. - */ - if (FD_ISSET(seqpacket_fd, &fds)) - new_client(seqpacket_fd, SOCK_SEQPACKET); } cfg.remove_pidfile(); close(seqpacket_fd); @@ -1322,6 +1326,7 @@ int main(int argc, char **argv) { int ch; + size_t len; check_devd_enabled(); while ((ch = getopt(argc, argv, "df:l:nq")) != -1) { @@ -1346,6 +1351,12 @@ main(int argc, char **argv) } } + len = sizeof(vm_guest); + if (sysctlbyname("kern.vm_guest", vm_guest, &len, NULL, 0) < 0) { + devdlog(LOG_ERR, + "sysctlbyname(kern.vm_guest) failed: %d\n", errno); + } + cfg.parse(); if (!no_daemon && daemonize_quick) { cfg.open_pidfile(); diff --git a/sbin/devd/hyperv.conf b/sbin/devd/hyperv.conf index 13695a0c75b6..70108ac36e54 100644 --- a/sbin/devd/hyperv.conf +++ b/sbin/devd/hyperv.conf @@ -103,5 +103,6 @@ notify 10 { notify 10 { match "system" "ETHERNET"; match "type" "IFATTACH"; + match "vm_guest" "hv"; action "/usr/libexec/hyperv/hyperv_vfattach $subsystem 0"; }; diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 6c61af48abec..b6e7d3ff2c63 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 July 11, 2025 +.Dd July 14, 2025 .Dt IFCONFIG 8 .Os .Sh NAME @@ -2878,13 +2878,25 @@ interfaces previously configured with Another name for the .Fl tunnel parameter. +.It Cm noclamp +This flag prevents the MTU from being clamped to 1280 bytes, the +minimum MTU for IPv6, when the outer protocol is IPv6. When the +flag is set, the MTU value configured on the interface will be +used instead of the fixed length of 1280 bytes. For more details, +please refer to the +.Ar MTU Configuration and Path MTU Discovery +section in +.Xr gif 4 . +.It Cm -noclamp +Clear the flag +.Cm noclamp . .It Cm ignore_source Set a flag to accept encapsulated packets destined to this host independently from source address. This may be useful for hosts, that receive encapsulated packets from the load balancers. .It Cm -ignore_source -Clear a flag +Clear the flag .Cm ignore_source . .El .Ss GRE Tunnel Parameters diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c index 991cf110678f..9b8be210a59e 100644 --- a/sbin/ifconfig/ifgif.c +++ b/sbin/ifconfig/ifgif.c @@ -49,6 +49,7 @@ #include "ifconfig.h" static const char *GIFBITS[] = { + [0] = "NOCLAMP", [1] = "IGNORE_SOURCE", }; @@ -90,6 +91,8 @@ setgifopts(if_ctx *ctx, const char *val __unused, int d) } static struct cmd gif_cmds[] = { + DEF_CMD("noclamp", GIF_NOCLAMP, setgifopts), + DEF_CMD("-noclamp", -GIF_NOCLAMP, setgifopts), DEF_CMD("ignore_source", GIF_IGNORE_SOURCE, setgifopts), DEF_CMD("-ignore_source", -GIF_IGNORE_SOURCE, setgifopts), }; diff --git a/sbin/kldstat/kldstat.c b/sbin/kldstat/kldstat.c index 79c647576440..3a90f1c97eb4 100644 --- a/sbin/kldstat/kldstat.c +++ b/sbin/kldstat/kldstat.c @@ -35,7 +35,7 @@ #include <libutil.h> #include <stdio.h> #include <stdlib.h> -#include <strings.h> +#include <string.h> #include <unistd.h> #define PTR_WIDTH ((int)(sizeof(void *) * 2 + 2)) @@ -51,7 +51,7 @@ printmod(int modid) { struct module_stat stat; - bzero(&stat, sizeof(stat)); + memset(&stat, 0, sizeof(stat)); stat.version = sizeof(struct module_stat); if (modstat(modid, &stat) < 0) { warn("can't stat module id %d", modid); diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index b584d71ea567..7bfc21ea41d5 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 30, 2025 +.Dd July 16, 2025 .Dt MOUNT 8 .Os .Sh NAME @@ -80,7 +80,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl a All the file systems described in @@ -573,7 +573,7 @@ support for a particular file system might be provided either on a static .Xr acl 3 , .Xr getmntinfo 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr cd9660 4 , .Xr devfs 4 , .Xr ext2fs 4 , diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 9a917d1d8464..358fa909fc50 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -367,6 +367,7 @@ static struct node_fairq_opts fairq_opts; static struct node_state_opt *keep_state_defaults = NULL; static struct pfctl_watermarks syncookie_opts; +int validate_range(uint8_t, uint16_t, uint16_t); int disallow_table(struct node_host *, const char *); int disallow_urpf_failed(struct node_host *, const char *); int disallow_alias(struct node_host *, const char *); @@ -3231,8 +3232,7 @@ logopts : logopt { $$ = $1; } logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; } - | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } - | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } + | USER { $$.log = PF_LOG_USER; $$.logif = 0; } | TO string { const char *errstr; u_int i; @@ -3825,9 +3825,14 @@ port_item : portrange { err(1, "port_item: calloc"); $$->port[0] = $1.a; $$->port[1] = $1.b; - if ($1.t) + if ($1.t) { $$->op = PF_OP_RRG; - else + if (validate_range($$->op, $$->port[0], + $$->port[1])) { + yyerror("invalid port range"); + YYERROR; + } + } else $$->op = PF_OP_EQ; $$->next = NULL; $$->tail = $$; @@ -3844,6 +3849,10 @@ port_item : portrange { $$->port[0] = $2.a; $$->port[1] = $2.b; $$->op = $1; + if (validate_range($$->op, $$->port[0], $$->port[1])) { + yyerror("invalid port range"); + YYERROR; + } $$->next = NULL; $$->tail = $$; } @@ -3859,6 +3868,10 @@ port_item : portrange { $$->port[0] = $1.a; $$->port[1] = $3.a; $$->op = $2; + if (validate_range($$->op, $$->port[0], $$->port[1])) { + yyerror("invalid port range"); + YYERROR; + } $$->next = NULL; $$->tail = $$; } @@ -5197,6 +5210,19 @@ yyerror(const char *fmt, ...) } int +validate_range(uint8_t op, uint16_t p1, uint16_t p2) +{ + uint16_t a = ntohs(p1); + uint16_t b = ntohs(p2); + + if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */ + (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */ + (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */ + return 1; + return 0; +} + +int disallow_table(struct node_host *h, const char *fmt) { for (; h != NULL; h = h->next) @@ -5324,6 +5350,10 @@ filter_consistent(struct pfctl_rule *r, int anchor_call) "synproxy state or modulate state"); problems++; } + if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN)) + fprintf(stderr, "%s:%d: warning: " + "synproxy used for inbound rules only, " + "ignored for outbound\n", file->name, yylval.lineno); if (r->rule_flag & PFRULE_AFTO && r->rt) { if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) { yyerror("dup-to " @@ -6014,8 +6044,14 @@ apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec if (!rs->rport.b && rs->rport.t) { rpool->proxy_port[1] = ntohs(rs->rport.a) + (ntohs(r->dst.port[1]) - ntohs(r->dst.port[0])); - } else + } else { + if (validate_range(rs->rport.t, rs->rport.a, + rs->rport.b)) { + yyerror("invalid rdr-to port range"); + return (1); + } r->rdr.proxy_port[1] = ntohs(rs->rport.b); + } if (rs->pool_opts.staticport) { yyerror("the 'static-port' option is only valid with nat rules"); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 271286deeda7..2015e0a09549 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -131,8 +131,8 @@ int pfctl_walk_get(int, struct pfioc_ruleset *, void *); int pfctl_walk_anchors(int, int, const char *, int(*)(int, struct pfioc_ruleset *, void *), void *); struct pfr_anchors * - pfctl_get_anchors(int, char *, int); -int pfctl_recurse(int, int, char *, + pfctl_get_anchors(int, const char *, int); +int pfctl_recurse(int, int, const char *, int(*)(int, int, struct pfr_anchoritem *)); int pfctl_call_clearrules(int, int, struct pfr_anchoritem *); int pfctl_call_cleartables(int, int, struct pfr_anchoritem *); @@ -2988,20 +2988,23 @@ pfctl_show_anchors(int dev, int opts, char *anchor) } struct pfr_anchors * -pfctl_get_anchors(int dev, char *anchor, int opts) +pfctl_get_anchors(int dev, const char *anchor, int opts) { struct pfioc_ruleset pr; static struct pfr_anchors anchors; + char anchorbuf[PATH_MAX]; char *n; SLIST_INIT(&anchors); memset(&pr, 0, sizeof(pr)); if (*anchor != '\0') { - n = dirname(anchor); + strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); + n = dirname(anchorbuf); if (n[0] != '.' && n[1] != '\0') strlcpy(pr.path, n, sizeof(pr.path)); - n = basename(anchor); + strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); + n = basename(anchorbuf); if (n != NULL) strlcpy(pr.name, n, sizeof(pr.name)); } @@ -3051,7 +3054,7 @@ pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra) } int -pfctl_recurse(int dev, int opts, char *anchorname, +pfctl_recurse(int dev, int opts, const char *anchorname, int(*walkf)(int, int, struct pfr_anchoritem *)) { int rv = 0; diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index bd2c10c8080f..f2eb75135609 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -928,7 +928,7 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer printf("%sall", count++ ? ", " : ""); if (r->log & PF_LOG_MATCHES) printf("%smatches", count++ ? ", " : ""); - if (r->log & PF_LOG_SOCKET_LOOKUP) + if (r->log & PF_LOG_USER) printf("%suser", count++ ? ", " : ""); if (r->logif) printf("%sto pflog%u", count++ ? ", " : "", @@ -1483,7 +1483,8 @@ ifa_load(void) err(1, "getifaddrs"); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (!(ifa->ifa_addr->sa_family == AF_INET || + if (ifa->ifa_addr == NULL || + !(ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6 || ifa->ifa_addr->sa_family == AF_LINK)) continue; diff --git a/sbin/pfctl/tests/files/pf0088.in b/sbin/pfctl/tests/files/pf0088.in index 4700b6916b7e..a85aa84a30bb 100644 --- a/sbin/pfctl/tests/files/pf0088.in +++ b/sbin/pfctl/tests/files/pf0088.in @@ -16,7 +16,7 @@ pass to 10.0.0.2 keep state block from 10.0.0.3 to 10.0.0.2 pass to 10.0.0.2 modulate state block from 10.0.0.3 to 10.0.0.2 -pass to 10.0.0.2 synproxy state +pass in to 10.0.0.2 synproxy state pass out proto tcp from 10.0.0.4 to 10.0.0.5 keep state diff --git a/sbin/pfctl/tests/files/pf0088.ok b/sbin/pfctl/tests/files/pf0088.ok index 47251a4503dd..801056a4ab46 100644 --- a/sbin/pfctl/tests/files/pf0088.ok +++ b/sbin/pfctl/tests/files/pf0088.ok @@ -11,7 +11,7 @@ pass inet from any to 10.0.0.2 flags S/SA keep state block drop inet from 10.0.0.3 to 10.0.0.2 pass inet from any to 10.0.0.2 flags S/SA modulate state block drop inet from 10.0.0.3 to 10.0.0.2 -pass inet from any to 10.0.0.2 flags S/SA synproxy state +pass in inet from any to 10.0.0.2 flags S/SA synproxy state pass out inet proto tcp from 10.0.0.4 to 10.0.0.5 flags S/SA keep state pass out inet proto tcp from 10.0.0.4 to 10.0.0.5 port = http flags S/SA keep state pass out all flags S/SA keep state diff --git a/sbin/pfctl/tests/files/pf1072.fail b/sbin/pfctl/tests/files/pf1072.fail new file mode 100644 index 000000000000..06ef5ae457e5 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1072.fail @@ -0,0 +1 @@ +invalid port range diff --git a/sbin/pfctl/tests/files/pf1072.in b/sbin/pfctl/tests/files/pf1072.in new file mode 100644 index 000000000000..e09e92388ce1 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1072.in @@ -0,0 +1 @@ +pass in proto tcp from any port 500:100 to any diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc index 51729bc9adad..3a68cc06ec74 100644 --- a/sbin/pfctl/tests/pfctl_test_list.inc +++ b/sbin/pfctl/tests/pfctl_test_list.inc @@ -180,3 +180,4 @@ PFCTL_TEST(1068, "max-pkt-rate") PFCTL_TEST(1069, "max-pkt-size") PFCTL_TEST_FAIL(1070, "include line number") PFCTL_TEST(1071, "mask length on (lo0)") +PFCTL_TEST_FAIL(1072, "Invalid port range") diff --git a/sbin/reboot/reboot.8 b/sbin/reboot/reboot.8 index 0ddcee643244..1bbc39d52be4 100644 --- a/sbin/reboot/reboot.8 +++ b/sbin/reboot/reboot.8 @@ -110,6 +110,15 @@ Care should be taken if .Va value contains any characters that are special to the shell or loader's configuration parsing code. +.It Fl f +Force reboot. +Normally, +.Nm +checks for the presence of the next kernel, +and absence of the +.Pa /var/run/noshutdown +file. +Without this flag, reboot is denied if one of the conditions failed. .It Fl k Ar kname Boot the specified kernel .Ar kname diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c index 9825d4f96319..f6065e80fb66 100644 --- a/sbin/reboot/reboot.c +++ b/sbin/reboot/reboot.c @@ -40,6 +40,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <paths.h> #include <pwd.h> #include <signal.h> #include <spawn.h> @@ -222,6 +223,7 @@ main(int argc, char *argv[]) { struct utmpx utx; const struct passwd *pw; + struct stat st; int ch, howto = 0, i, sverrno; bool Dflag, fflag, lflag, Nflag, nflag, qflag; uint64_t pageins; @@ -294,6 +296,11 @@ main(int argc, char *argv[]) if (argc != 0) usage(); + if (!donextboot && !fflag && stat(_PATH_NOSHUTDOWN, &st) == 0) { + errx(1, "Reboot cannot be done, " _PATH_NOSHUTDOWN + " is present"); + } + if (Dflag && ((howto & ~RB_HALT) != 0 || kernel != NULL)) errx(1, "cannot delete existing nextboot config and do anything else"); if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT)) diff --git a/sbin/recoverdisk/recoverdisk.1 b/sbin/recoverdisk/recoverdisk.1 index 2999ac6ec409..9f1deb4c0c23 100644 --- a/sbin/recoverdisk/recoverdisk.1 +++ b/sbin/recoverdisk/recoverdisk.1 @@ -27,7 +27,7 @@ .Os .Sh NAME .Nm recoverdisk -.Nd recover data from hard disk or optical media +.Nd recover data from disk-like devices. .Sh SYNOPSIS .Nm .Op Fl b Ar bigsize @@ -41,79 +41,101 @@ .Sh DESCRIPTION The .Nm -utility reads data from the +utility reads all data from the .Ar source -file until all blocks could be successfully read. +and retries read operations until they succeed. If .Ar destination -was specified all data is being written to that file. -It starts reading in multiples of the sector size. -Whenever a block fails, it is put to the end of the working queue and will be -read again, possibly with a smaller read size. +is specified all data read be written there. .Pp -By default it uses block sizes of roughly 1 MB, 32kB, and the native -sector size (usually 512 bytes). -These figures are adjusted slightly, for devices whose sectorsize is not a -power of 2, e.g., audio CDs with a sector size of 2352 bytes. +The internal work-list can be saved and loaded so that +.Nm +sessions can be resumed, for instance when a marginal +source hard-disk shuts down. +.Pp +The work-list is initialized with a single item which covers the entire +.Ar source +and +.Nm +always chips away at the first item on the work-list. + +When a read succeeds, that part of the current chunk is eliminated +from the work-list. + +When a read fails, that part of the item is appended to the worklist +as a separate item, and will be retried in due order. +If +.Ar destination +is specified, the corresponding range is filled with '_UNREAD_'. +.Pp +The first pass attempts to read everything in "big-size" chunks, +the second pass reads in "medium-size" chunks and third and subsequent +passes read in "small-size" chunks. This three stage process is +an attempt to optimize the case where only a few bad blocks exist +on +.Ar source . +If too many read-errors are encountered, +.Nm +will fall back to smaller sizes sooner. +.Pp +The three sizes default to 128kB (or less if the sector size does +not divide 128kB cleanly, for instance audio CD media), and the +reported +.Dv DIOCGSTRIPESIZE +and +.Dv DIOCGSECTORSIZE +respectively. .Pp The options are as follows: .Bl -tag -width indent .It Fl b Ar bigsize -The size of reads attempted first. -The middle pass is roughly the logarithmic average of the bigsize and -the sectorsize. -.It Fl r Ar readlist -Read the list of blocks and block sizes to read from the specified file. -.It Fl s Ar interval -How often we should update the writelist file while things go OK. -The default is 60 and the unit is "progress messages" so if things -go well, this is the same as once per minute. +The size of reads attempted in first pass. +.It Fl m Ar mediumsize +The size of reads attempted in second pass. +.It Fl s Ar smallsize +The size of reads attempted in third and subsequent passes. +.It Fl r Ar work-list-file +Read the work-list from a file. +.It Fl w Ar work-list-file +Write the work-list to a file when a read succeed, but at most once +every minute. +.It Fl l Ar log-file +Each successful read is logged with timestamp, offset and length. +.It Fl t Ar totalsize +How many bytes should be recovered. The default is what +.Dv DIOCGMEDIASIZE +reports for character and block devices or +.Dv st_size +if +.Ar source +is a regular file. +.It Fl p Ar pause +.Xr sleep 3 +this long whenever a read fails. This makes the +.Ar source +device look less sick to the operating system. .It Fl u Ar pattern -By default blocks which encounter read errors will be filled with -the pattern +By default blocks which cannot be read are filled with the pattern .Ql _UNREAD_ -in the output file. -This option can be -used to specify another pattern. -Nothing gets written if the string is empty. +in the output file. This option can be used to specify a different +pattern. If the pattern is the empty string, nothing is written. .It Fl v -Enables nicer status report using ANSI escapes and UTF-8. -.It Fl w Ar writelist -Write the list of remaining blocks to read to the specified file if -.Nm -is aborted via -.Dv SIGINT . +Produce a detailed progress report with ANSI escapes and UTF-8. .El .Pp -The -.Fl r -and -.Fl w -options can be specified together. -Especially, they can point to the same file, which will be updated on abort. -.Sh OUTPUT -The .Nm -utility -prints several columns, detailing the progress -.Bl -tag -width remaining -.It Va start -Starting offset of the current block. -.It Va size -Read size of the current block. -.It Va len -Length of the current block. -.It Va state -Is increased for every failed read. -.It Va done -Number of bytes already read. -.It Va remaining -Number of bytes remaining. -.It Va "% done" -Percent complete. -.El +can be aborted with +.Dv SIGINT , +but with a sick +.Ar source +it may take up to several minutes before the current read operation +returns from the kernel. +.Pp .Sh EXAMPLES .Bd -literal +# check if all sectors can be read on a USB stick: +recoverdisk /dev/da0 + # recover data from failing hard drive ada3 recoverdisk /dev/ada3 /data/disk.img @@ -129,10 +151,72 @@ recoverdisk -r worklist -w worklist /dev/cd0 /data/cd.iso # recover a single file from the unreadable media recoverdisk /cdrom/file.avi file.avi -# If the disk hangs the system on read-errors try: -recoverdisk -b 0 /dev/ada3 /somewhere - .Ed +.Sh PRACTICAL ADVICE +In Datamuseum.dk +.Nm +has been used to recover all sorts of data-media for two decades, +here are some things we have learned: +.Bl -bullet +.It +Interacting with failing hardware has a tendency to crash machines, +so it is always a good idea to use the +.Fl -w work-list-file +so that it is possible to continue. +.It +When attempting to recover hard to read data from failing hard disks, +it pays to pamper the drive as much as possible: +.It +It is generally best to keep the drive in it's usual physical orientation, +but it can also help to try other orientations. +.It +Insulate the drive from external vibrations. +.It +Keep the drive cool with a fan. +.It +If possible, power the drive from a laboratory power supply. +.It +Do not loose patience: Let +.Nm +run as long as possible. +.It +(S)ATA controllers do not handle failing disks well, if this +is a problem, use a USB-(S)ATA adapter instead. +.It +The +.Nm +source code is deliberately written to be easily portable to +older versions of +.Fx +and to other operating systems. +.It +If you need to read ST-506, RLL or ESDI drives +.Fx 3.5.1 +is a good compromise. +.It +Sometimes forcing the disk to step between reads helps. +Since +.Nm +process the work-list in the order it is read, this +can be accomplished by sorting the work-list with +something like: +.Dl % sort +0.5 +.It +By default the +.Xr CAM +layer will retry failing read operations, but that +will get stuck on the bad sectors for long time +and delay recovering what actually can be read from +a rapidly failing drive. +In that situation, set the appropriate +.Dl kern.cam.*.retry_count +sysctl to zero. +.It +For floppies and un-zoned hard disks (ST-506 to +early IDE) set +.Fl b Ar bigsize +to the size of a track. +.El .Sh SEE ALSO .Xr dd 1 , .Xr ada 4 , @@ -143,7 +227,8 @@ recoverdisk -b 0 /dev/ada3 /somewhere The .Nm utility first appeared in -.Fx 7.0 . +.Fx 7.0 +because Somebodyâ„¢ forgot to make a backup copy. .Sh AUTHORS .An -nosplit The original implementation was done by @@ -151,34 +236,29 @@ The original implementation was done by with minor improvements from .An Ulrich Sp\(:orlein Aq Mt uqs@FreeBSD.org . .Pp -This manual page was written by +This manual page was originally written by .An Ulrich Sp\(:orlein . .Sh BUGS -Reading from media where the sectorsize is not a power of 2 will make all -1 MB reads fail. -This is due to the DMA reads being split up into blocks of at most 128kB. -These reads then fail if the sectorsize is not a divisor of 128kB. -When reading a full raw audio CD, this leads to roughly 700 error messages -flying by. -This is harmless and can be avoided by setting -.Fl b -to no more than 128kB. +If a failing device causes the machine to crash, there is +a risk that a chunk might have been successfully read +and removed from the work-list, but not yet flushed to +the +.Ar destination . .Pp .Nm -needs to know about read errors as fast as possible, i.e., retries by lower -layers will usually slow down the operation. -When using -.Xr cam 4 -attached drives, you may want to set kern.cam.XX.retry_count to zero, e.g.: -.Bd -literal -# sysctl kern.cam.ada.retry_count=0 -# sysctl kern.cam.cd.retry_count=0 -# sysctl kern.cam.da.retry_count=0 -.Ed -.\".Pp -.\"When reading from optical media, a bug in the GEOM framework will -.\"prevent it from seeing that the media has been removed. -.\"The device can still be opened, but all reads will fail. -.\"This is usually harmless, but will send -.\".Nm -.\"into an infinite loop. +calls +.Xr fdatasync 3 +on the destination before writing the work-list to a +temporary file, and calls it again on the temporary +file before renaming it to the specified +.Fl w Ar work-file-list +filename. +But even then things dont always work out. +.Pp +.Nm +should have an option for reconstructing the work-list +from the +.Ar destination +by enumerating the +.Fl u Ar pattern +filled ranges. diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c index 446266c36d50..e1b283e54a93 100644 --- a/sbin/recoverdisk/recoverdisk.c +++ b/sbin/recoverdisk/recoverdisk.c @@ -8,6 +8,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- */ + #include <sys/param.h> #include <sys/queue.h> #include <sys/disk.h> @@ -27,18 +28,10 @@ #include <time.h> #include <unistd.h> -/* Safe printf into a fixed-size buffer */ -#define bprintf(buf, fmt, ...) \ - do { \ - int ibprintf; \ - ibprintf = snprintf(buf, sizeof buf, fmt, __VA_ARGS__); \ - assert(ibprintf >= 0 && ibprintf < (int)sizeof buf); \ - } while (0) - struct lump { - off_t start; - off_t len; - int state; + uint64_t start; + uint64_t len; + unsigned pass; TAILQ_ENTRY(lump) list; }; @@ -46,25 +39,32 @@ struct period { time_t t0; time_t t1; char str[20]; - off_t bytes_read; + uint64_t bytes_read; TAILQ_ENTRY(period) list; }; TAILQ_HEAD(period_head, period); static volatile sig_atomic_t aborting = 0; static int verbose = 0; -static size_t bigsize = 1024 * 1024; -static size_t medsize; -static size_t minsize = 512; -static off_t tot_size; -static off_t done_size; +static uint64_t big_read; +static uint64_t medium_read; +static uint64_t small_read; +static uint64_t total_size; +static uint64_t done_size; static char *input; -static char *wworklist = NULL; -static char *rworklist = NULL; +static char *write_worklist_file = NULL; +static char *read_worklist_file = NULL; static const char *unreadable_pattern = "_UNREAD_"; -static const int write_errors_are_fatal = 1; -static int fdr, fdw; - +static int write_errors_are_fatal = 1; +static int read_fd, write_fd; +static FILE *log_file = NULL; +static char *work_buf; +static char *pattern_buf; +static double error_pause; + +static unsigned nlumps; +static double n_reads, n_good_reads; +static time_t t_first; static TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); static struct period_head minute = TAILQ_HEAD_INITIALIZER(minute); static struct period_head quarter = TAILQ_HEAD_INITIALIZER(quarter); @@ -74,7 +74,8 @@ static struct period_head day = TAILQ_HEAD_INITIALIZER(quarter); /**********************************************************************/ static void -report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt) +account_good_read_period(time_t now, uint64_t bytes, + struct period_head *ph, time_t dt) { struct period *pp; const char *fmt; @@ -82,7 +83,7 @@ report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt) pp = TAILQ_FIRST(ph); if (pp == NULL || pp->t1 < now) { - pp = calloc(1, sizeof(*pp)); + pp = calloc(1UL, sizeof(*pp)); assert(pp != NULL); pp->t0 = (now / dt) * dt; pp->t1 = (now / dt + 1) * dt; @@ -98,13 +99,13 @@ report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt) } static void -report_good_read(time_t now, size_t bytes) +account_good_read(time_t now, uint64_t bytes) { - report_good_read2(now, bytes, &minute, 60L); - report_good_read2(now, bytes, &quarter, 900L); - report_good_read2(now, bytes, &hour, 3600L); - report_good_read2(now, bytes, &day, 86400L); + account_good_read_period(now, bytes, &minute, 60L); + account_good_read_period(now, bytes, &quarter, 900L); + account_good_read_period(now, bytes, &hour, 3600L); + account_good_read_period(now, bytes, &day, 86400L); } static void @@ -114,20 +115,18 @@ report_one_period(const char *period, struct period_head *ph) int n; n = 0; - printf("%s \xe2\x94\x82", period); + printf("%s ", period); TAILQ_FOREACH(pp, ph, list) { - if (n == 3) { + if (++n == 4) { TAILQ_REMOVE(ph, pp, list); free(pp); break; } - if (n++) - printf(" \xe2\x94\x82"); - printf(" %s %14jd", pp->str, pp->bytes_read); + printf("\xe2\x94\x82 %s %14ju ", + pp->str, (uintmax_t)pp->bytes_read); } for (; n < 3; n++) { - printf(" \xe2\x94\x82"); - printf(" %5s %14s", "", ""); + printf("\xe2\x94\x82 %5s %14s ", "", ""); } printf("\x1b[K\n"); } @@ -146,27 +145,23 @@ report_periods(void) static void set_verbose(void) { - struct winsize wsz; - if (!isatty(STDIN_FILENO) || ioctl(STDIN_FILENO, TIOCGWINSZ, &wsz)) - return; verbose = 1; } static void -report_header(int eol) +report_header(const char *term) { - printf("%13s %7s %13s %5s %13s %13s %9s", + printf("%13s %7s %13s %5s %13s %13s %9s%s", "start", "size", "block-len", "pass", "done", "remaining", - "% done"); - if (eol) - printf("\x1b[K"); - putchar('\n'); + "% done", + term + ); } #define REPORTWID 79 @@ -186,20 +181,20 @@ report_hline(const char *how) printf("\x1b[K\n"); } -static off_t hist[REPORTWID]; -static off_t last_done = -1; +static uint64_t hist[REPORTWID]; +static uint64_t prev_done = ~0UL; static void -report_histogram(const struct lump *lp) +report_histogram(uint64_t start) { - off_t j, bucket, fp, fe, k, now; + uint64_t j, bucket, fp, fe, k, now; double a; struct lump *lp2; - bucket = tot_size / REPORTWID; - if (tot_size > bucket * REPORTWID) + bucket = total_size / REPORTWID; + if (total_size > bucket * REPORTWID) bucket += 1; - if (done_size != last_done) { + if (done_size != prev_done) { memset(hist, 0, sizeof hist); TAILQ_FOREACH(lp2, &lumps, list) { fp = lp2->start; @@ -213,9 +208,9 @@ report_histogram(const struct lump *lp) fp += k; } } - last_done = done_size; + prev_done = done_size; } - now = lp->start / bucket; + now = start / bucket; for (j = 0; j < REPORTWID; j++) { a = round(8 * (double)hist[j] / bucket); assert (a >= 0 && a < 9); @@ -228,7 +223,7 @@ report_histogram(const struct lump *lp) } else { putchar(0xe2); putchar(0x96); - putchar(0x80 + (int)a); + putchar(0x80 + (char)a); } if (j == now) printf("\x1b[0m"); @@ -237,34 +232,40 @@ report_histogram(const struct lump *lp) } static void -report(const struct lump *lp, size_t sz) +report(uint64_t sz) { struct winsize wsz; + const struct lump *lp = TAILQ_FIRST(&lumps); int j; - - assert(lp != NULL); + unsigned pass = 0; + uintmax_t start = 0, length = 0; + time_t t_now = time(NULL); + + if (lp != NULL) { + pass = lp->pass; + start = lp->start; + length = lp->len; + } if (verbose) { printf("\x1b[H%s\x1b[K\n", input); - report_header(1); - } else { - putchar('\r'); + report_header("\x1b[K\n"); } - printf("%13jd %7zu %13jd %5d %13jd %13jd %9.4f", - (intmax_t)lp->start, - sz, - (intmax_t)lp->len, - lp->state, - (intmax_t)done_size, - (intmax_t)(tot_size - done_size), - 100*(double)done_size/(double)tot_size + printf("%13ju %7ju %13ju %5u %13ju %13ju %9.4f", + start, + (uintmax_t)sz, + length, + pass, + (uintmax_t)done_size, + (uintmax_t)(total_size - done_size), + 100*(double)done_size/(double)total_size ); if (verbose) { printf("\x1b[K\n"); report_hline(NULL); - report_histogram(lp); + report_histogram(start); if (TAILQ_EMPTY(&minute)) { report_hline(NULL); } else { @@ -272,27 +273,36 @@ report(const struct lump *lp, size_t sz) report_periods(); report_hline("\xe2\x94\xb4"); } + printf("Missing: %u", nlumps); + printf(" Success: %.0f/%.0f =", n_good_reads, n_reads); + printf(" %.4f%%", 100 * n_good_reads / n_reads); + printf(" Duration: %.3fs", (t_now - t_first) / n_reads); + printf("\x1b[K\n"); + report_hline(NULL); j = ioctl(STDIN_FILENO, TIOCGWINSZ, &wsz); if (!j) printf("\x1b[%d;1H", wsz.ws_row); + } else { + printf("\n"); } - fflush(stdout); } /**********************************************************************/ static void -new_lump(off_t start, off_t len, int state) +new_lump(uint64_t start, uint64_t len, unsigned pass) { struct lump *lp; + assert(len > 0); lp = malloc(sizeof *lp); if (lp == NULL) err(1, "Malloc failed"); lp->start = start; lp->len = len; - lp->state = state; + lp->pass = pass; TAILQ_INSERT_TAIL(&lumps, lp, list); + nlumps += 1; } /********************************************************************** @@ -306,98 +316,100 @@ save_worklist(void) struct lump *llp; char buf[PATH_MAX]; - if (fdw >= 0 && fdatasync(fdw)) + if (write_fd >= 0 && fdatasync(write_fd)) err(1, "Write error, probably disk full"); - if (wworklist != NULL) { - bprintf(buf, "%s.tmp", wworklist); - (void)fprintf(stderr, "\nSaving worklist ..."); - (void)fflush(stderr); + if (write_worklist_file != NULL) { + snprintf(buf, sizeof(buf), "%s.tmp", write_worklist_file); + fprintf(stderr, "\nSaving worklist ..."); file = fopen(buf, "w"); if (file == NULL) err(1, "Error opening file %s", buf); - TAILQ_FOREACH(llp, &lumps, list) - fprintf(file, "%jd %jd %d\n", - (intmax_t)llp->start, (intmax_t)llp->len, - llp->state); - (void)fflush(file); + TAILQ_FOREACH(llp, &lumps, list) { + assert (llp->len > 0); + fprintf(file, "%ju %ju %u\n", + (uintmax_t)llp->start, + (uintmax_t)llp->len, + llp->pass); + } + fflush(file); if (ferror(file) || fdatasync(fileno(file)) || fclose(file)) err(1, "Error writing file %s", buf); - if (rename(buf, wworklist)) - err(1, "Error renaming %s to %s", buf, wworklist); - (void)fprintf(stderr, " done.\n"); + if (rename(buf, write_worklist_file)) + err(1, "Error renaming %s to %s", + buf, write_worklist_file); + fprintf(stderr, " done.\n"); } } /* Read the worklist if -r was given */ -static off_t -read_worklist(off_t t) +static uint64_t +read_worklist(void) { - off_t s, l, d; - int state, lines; + uintmax_t start, length; + uint64_t missing = 0; + unsigned pass, lines; FILE *file; - (void)fprintf(stderr, "Reading worklist ..."); - (void)fflush(stderr); - file = fopen(rworklist, "r"); + fprintf(stderr, "Reading worklist ..."); + file = fopen(read_worklist_file, "r"); if (file == NULL) - err(1, "Error opening file %s", rworklist); + err(1, "Error opening file %s", read_worklist_file); lines = 0; - d = t; for (;;) { ++lines; - if (3 != fscanf(file, "%jd %jd %d\n", &s, &l, &state)) { + if (3 != fscanf(file, "%ju %ju %u\n", &start, &length, &pass)) { if (!feof(file)) - err(1, "Error parsing file %s at line %d", - rworklist, lines); + err(1, "Error parsing file %s at line %u", + read_worklist_file, lines); else break; } - new_lump(s, l, state); - d -= l; + if (length > 0) { + new_lump(start, length, pass); + missing += length; + } } if (fclose(file)) - err(1, "Error closing file %s", rworklist); - (void)fprintf(stderr, " done.\n"); + err(1, "Error closing file %s", read_worklist_file); + fprintf(stderr, " done.\n"); /* - * Return the number of bytes already read - * (at least not in worklist). + * Return the number of bytes outstanding */ - return (d); + return (missing); } /**********************************************************************/ static void -write_buf(int fd, const void *buf, ssize_t len, off_t where) +write_buf(int fd, const void *buf, uint64_t length, uint64_t where) { - ssize_t i; + int64_t i; - i = pwrite(fd, buf, len, where); - if (i == len) + i = pwrite(fd, buf, length, (off_t)where); + if (i > 0 && (uint64_t)i == length) return; - printf("\nWrite error at %jd/%zu\n\t%s\n", - where, i, strerror(errno)); + printf("\nWrite error at %ju/%ju: %jd (%s)\n", + (uintmax_t)where, + (uintmax_t)length, + (intmax_t)i, strerror(errno)); save_worklist(); if (write_errors_are_fatal) exit(3); } static void -fill_buf(char *buf, ssize_t len, const char *pattern) +fill_buf(char *buf, int64_t len, const char *pattern) { - ssize_t sz = strlen(pattern); - ssize_t i, j; + int64_t sz = strlen(pattern); + int64_t i; for (i = 0; i < len; i += sz) { - j = len - i; - if (j > sz) - j = sz; - memcpy(buf + i, pattern, j); + memcpy(buf + i, pattern, MIN(len - i, sz)); } } @@ -406,45 +418,334 @@ fill_buf(char *buf, ssize_t len, const char *pattern) static void usage(void) { - (void)fprintf(stderr, "usage: recoverdisk [-b bigsize] [-r readlist] " + fprintf(stderr, "usage: recoverdisk [-b big_read] [-r readlist] " "[-s interval] [-w writelist] source [destination]\n"); /* XXX update */ exit(1); } static void -sighandler(__unused int sig) +sighandler(int sig) { + (void)sig; aborting = 1; } +/**********************************************************************/ + +static int64_t +attempt_one_lump(time_t t_now) +{ + struct lump *lp; + uint64_t sz; + int64_t retval; + int error; + + lp = TAILQ_FIRST(&lumps); + if (lp == NULL) + return(0); + + if (lp->pass == 0) { + sz = MIN(lp->len, big_read); + } else if (lp->pass == 1) { + sz = MIN(lp->len, medium_read); + } else { + sz = MIN(lp->len, small_read); + } + + assert(sz != 0); + + n_reads += 1; + retval = pread(read_fd, work_buf, sz, lp->start); + +#if 0 /* enable this when testing */ + if (!(random() & 0xf)) { + retval = -1; + errno = EIO; + usleep(20000); + } else { + usleep(2000); + } +#endif + + error = errno; + if (retval > 0) { + n_good_reads += 1; + sz = retval; + done_size += sz; + if (write_fd >= 0) { + write_buf(write_fd, work_buf, sz, lp->start); + } + if (log_file != NULL) { + fprintf(log_file, "%jd %ju %ju\n", + (intmax_t)t_now, + (uintmax_t)lp->start, + (uintmax_t)sz + ); + fflush(log_file); + } + } else { + printf("%14ju %7ju read error %d: (%s)", + (uintmax_t)lp->start, + (uintmax_t)sz, error, strerror(error)); + if (error_pause > 1) { + printf(" (Pausing %g s)", error_pause); + } + printf("\n"); + + if (write_fd >= 0 && pattern_buf != NULL) { + write_buf(write_fd, pattern_buf, sz, lp->start); + } + new_lump(lp->start, sz, lp->pass + 1); + retval = -sz; + } + lp->start += sz; + lp->len -= sz; + if (lp->len == 0) { + TAILQ_REMOVE(&lumps, lp, list); + nlumps -= 1; + free(lp); + } + errno = error; + return (retval); +} + + +/**********************************************************************/ + +static void +determine_total_size(void) +{ + struct stat sb; + int error; + + if (total_size != 0) + return; + + error = fstat(read_fd, &sb); + if (error < 0) + err(1, "fstat failed"); + + if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { +#ifdef DIOCGMEDIASIZE + off_t mediasize; + error = ioctl(read_fd, DIOCGMEDIASIZE, &mediasize); + if (error == 0 && mediasize > 0) { + total_size = mediasize; + printf("# Got total_size from DIOCGMEDIASIZE: %ju\n", + (uintmax_t)total_size); + return; + } +#endif + } else if (S_ISREG(sb.st_mode) && sb.st_size > 0) { + total_size = sb.st_size; + printf("# Got total_size from stat(2): %ju\n", + (uintmax_t)total_size); + return; + } else { + errx(1, "Input must be device or regular file"); + } + fprintf(stderr, "Specify total size with -t option\n"); + exit(1); +} + +static void +determine_read_sizes(void) +{ + int error; + u_int sectorsize; + off_t stripesize; + + determine_total_size(); + +#ifdef DIOCGSECTORSIZE + if (small_read == 0) { + error = ioctl(read_fd, DIOCGSECTORSIZE, §orsize); + if (error >= 0 && sectorsize > 0) { + small_read = sectorsize; + printf("# Got small_read from DIOCGSECTORSIZE: %ju\n", + (uintmax_t)small_read + ); + } + } +#endif + + if (small_read == 0) { + printf("Assuming 512 for small_read\n"); + small_read = 512; + } + + if (medium_read && (medium_read % small_read)) { + errx(1, + "medium_read (%ju) is not a multiple of small_read (%ju)\n", + (uintmax_t)medium_read, (uintmax_t)small_read + ); + } + + if (big_read != 0 && (big_read % small_read)) { + errx(1, + "big_read (%ju) is not a multiple of small_read (%ju)\n", + (uintmax_t)big_read, (uintmax_t)small_read + ); + } + +#ifdef DIOCGSTRIPESIZE + if (medium_read == 0) { + error = ioctl(read_fd, DIOCGSTRIPESIZE, &stripesize); + if (error < 0 || stripesize < 0) { + // nope + } else if ((uint64_t)stripesize < small_read) { + // nope + } else if (stripesize % small_read) { + // nope + } else if (0 < stripesize && stripesize < (128<<10)) { + medium_read = stripesize; + printf("# Got medium_read from DIOCGSTRIPESIZE: %ju\n", + (uintmax_t)medium_read + ); + } + } +#endif +#if defined(DIOCGFWSECTORS) && defined(DIOCGFWHEADS) + if (medium_read == 0) { + u_int fwsectors = 0, fwheads = 0; + error = ioctl(read_fd, DIOCGFWSECTORS, &fwsectors); + if (error) + fwsectors = 0; + error = ioctl(read_fd, DIOCGFWHEADS, &fwheads); + if (error) + fwheads = 0; + if (fwsectors && fwheads) { + medium_read = fwsectors * fwheads * small_read; + printf( + "# Got medium_read from DIOCGFW{SECTORS,HEADS}: %ju\n", + (uintmax_t)medium_read + ); + } + } +#endif + + if (big_read == 0 && medium_read != 0) { + if (medium_read > (64<<10)) { + big_read = medium_read; + } else { + big_read = 128 << 10; + big_read -= big_read % medium_read; + } + printf("# Got big_read from medium_read: %ju\n", + (uintmax_t)big_read + ); + } + + if (big_read == 0) { + big_read = 128 << 10; + printf("# Defaulting big_read to %ju\n", + (uintmax_t)big_read + ); + } + + if (medium_read == 0) { + /* + * We do not want to go directly to single sectors, but + * we also dont want to waste time doing multi-sector + * reads with high failure probability. + */ + uint64_t h = big_read; + uint64_t l = small_read; + while (h > l) { + h >>= 2; + l <<= 1; + } + medium_read = h; + printf("# Got medium_read from small_read & big_read: %ju\n", + (uintmax_t)medium_read + ); + } + fprintf(stderr, + "# Bigsize = %ju, medium_read = %ju, small_read = %ju\n", + (uintmax_t)big_read, (uintmax_t)medium_read, (uintmax_t)small_read); + +} + + +/**********************************************************************/ + +static void +monitor_read_sizes(uint64_t failed_size) +{ + + if (failed_size == big_read && medium_read != small_read) { + if (n_reads < n_good_reads + 3) + return; + fprintf( + stderr, + "Too many failures for big reads." + " (%.0f bad of %.0f)" + " Shifting to medium_reads.\n", + n_reads - n_good_reads, n_reads + ); + big_read = medium_read; + medium_read = small_read; + return; + } + + if (failed_size > small_read) { + if (n_reads < n_good_reads + 100) + return; + fprintf( + stderr, + "Too many failures." + " (%.0f bad of %.0f)" + " Shifting to small_reads.\n", + n_reads - n_good_reads, n_reads + ); + big_read = small_read; + medium_read = small_read; + return; + } +} + +/**********************************************************************/ + int main(int argc, char * const argv[]) { int ch; - size_t sz, j; + int64_t sz; int error; - char *buf; - u_int sectorsize; - off_t stripesize; - time_t t1, t2; - struct stat sb; - u_int n, snapshot = 60; - static struct lump *lp; + time_t t_now, t_report, t_save; + unsigned snapshot = 60, unsaved; + setbuf(stdout, NULL); + setbuf(stderr, NULL); - while ((ch = getopt(argc, argv, "b:r:w:s:u:v")) != -1) { + while ((ch = getopt(argc, argv, "b:l:p:m:r:w:s:t:u:v")) != -1) { switch (ch) { case 'b': - bigsize = strtoul(optarg, NULL, 0); + big_read = strtoul(optarg, NULL, 0); + break; + case 'l': + log_file = fopen(optarg, "a"); + if (log_file == NULL) { + err(1, "Could not open logfile for append"); + } + break; + case 'p': + error_pause = strtod(optarg, NULL); + break; + case 'm': + medium_read = strtoul(optarg, NULL, 0); break; case 'r': - rworklist = strdup(optarg); - if (rworklist == NULL) + read_worklist_file = strdup(optarg); + if (read_worklist_file == NULL) err(1, "Cannot allocate enough memory"); break; case 's': - snapshot = strtoul(optarg, NULL, 0); + small_read = strtoul(optarg, NULL, 0); + break; + case 't': + total_size = strtoul(optarg, NULL, 0); break; case 'u': unreadable_pattern = optarg; @@ -453,8 +754,8 @@ main(int argc, char * const argv[]) set_verbose(); break; case 'w': - wworklist = strdup(optarg); - if (wworklist == NULL) + write_worklist_file = strdup(optarg); + if (write_worklist_file == NULL) err(1, "Cannot allocate enough memory"); break; default: @@ -469,149 +770,106 @@ main(int argc, char * const argv[]) usage(); input = argv[0]; - fdr = open(argv[0], O_RDONLY); - if (fdr < 0) + read_fd = open(argv[0], O_RDONLY); + if (read_fd < 0) err(1, "Cannot open read descriptor %s", argv[0]); - error = fstat(fdr, &sb); - if (error < 0) - err(1, "fstat failed"); - if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { - error = ioctl(fdr, DIOCGSECTORSIZE, §orsize); - if (error < 0) - err(1, "DIOCGSECTORSIZE failed"); - - error = ioctl(fdr, DIOCGSTRIPESIZE, &stripesize); - if (error == 0 && stripesize < sectorsize) - sectorsize = stripesize; + determine_read_sizes(); - minsize = sectorsize; - bigsize = rounddown(bigsize, sectorsize); + work_buf = malloc(big_read); + assert (work_buf != NULL); - error = ioctl(fdr, DIOCGMEDIASIZE, &tot_size); - if (error < 0) - err(1, "DIOCGMEDIASIZE failed"); + if (argc > 1) { + write_fd = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE); + if (write_fd < 0) + err(1, "Cannot open write descriptor %s", argv[1]); + if (ftruncate(write_fd, (off_t)total_size) < 0) + err(1, "Cannot truncate output %s to %ju bytes", + argv[1], (uintmax_t)total_size); } else { - tot_size = sb.st_size; + write_fd = -1; } - if (bigsize < minsize) - bigsize = minsize; - - for (ch = 0; (bigsize >> ch) > minsize; ch++) - continue; - medsize = bigsize >> (ch / 2); - medsize = rounddown(medsize, minsize); - - fprintf(stderr, "Bigsize = %zu, medsize = %zu, minsize = %zu\n", - bigsize, medsize, minsize); - - buf = malloc(bigsize); - if (buf == NULL) - err(1, "Cannot allocate %zu bytes buffer", bigsize); + if (strlen(unreadable_pattern)) { + pattern_buf = malloc(big_read); + assert(pattern_buf != NULL); + fill_buf(pattern_buf, big_read, unreadable_pattern); + } - if (argc > 1) { - fdw = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE); - if (fdw < 0) - err(1, "Cannot open write descriptor %s", argv[1]); - if (ftruncate(fdw, tot_size) < 0) - err(1, "Cannot truncate output %s to %jd bytes", - argv[1], (intmax_t)tot_size); - } else - fdw = -1; - - if (rworklist != NULL) { - done_size = read_worklist(tot_size); + if (read_worklist_file != NULL) { + done_size = total_size - read_worklist(); } else { - new_lump(0, tot_size, 0); + new_lump(0UL, total_size, 0UL); done_size = 0; } - if (wworklist != NULL) + if (write_worklist_file != NULL) signal(SIGINT, sighandler); - t1 = time(NULL); sz = 0; if (!verbose) - report_header(0); + report_header("\n"); else printf("\x1b[2J"); - n = 0; - for (;;) { - lp = TAILQ_FIRST(&lumps); - if (lp == NULL) - break; - while (lp->len > 0) { - if (lp->state == 0) - sz = MIN(lp->len, (off_t)bigsize); - else if (lp->state == 1) - sz = MIN(lp->len, (off_t)medsize); - else - sz = MIN(lp->len, (off_t)minsize); - assert(sz != 0); - - t2 = time(NULL); - if (t1 != t2 || lp->len < (off_t)bigsize) { - t1 = t2; - if (++n == snapshot) { - save_worklist(); - n = 0; - } - report(lp, sz); - } + t_first = time(NULL); + t_report = t_first; + t_save = t_first; + unsaved = 0; + while (!aborting) { + t_now = time(NULL); + sz = attempt_one_lump(t_now); + error = errno; - j = pread(fdr, buf, sz, lp->start); -#if 0 -if (!(random() & 0xf)) { - j = -1; - errno = EIO; -} -#endif - if (j == sz) { - done_size += sz; - if (fdw >= 0) - write_buf(fdw, buf, sz, lp->start); - lp->start += sz; - lp->len -= sz; - if (verbose && lp->state > 2) - report_good_read(t2, sz); - continue; - } - error = errno; - - printf("%jd %zu %d read error (%s)\n", - lp->start, sz, lp->state, strerror(error)); - if (verbose) - report(lp, sz); - if (fdw >= 0 && strlen(unreadable_pattern)) { - fill_buf(buf, sz, unreadable_pattern); - write_buf(fdw, buf, sz, lp->start); + if (sz == 0) { + break; + } + + if (sz > 0) { + unsaved += 1; + } + if (unsaved && (t_save + snapshot) < t_now) { + save_worklist(); + unsaved = 0; + t_save = t_now; + if (!verbose) { + report_header("\n"); + t_report = t_now; } - new_lump(lp->start, sz, lp->state + 1); - lp->start += sz; - lp->len -= sz; - if (error == EINVAL) { - printf("Try with -b 131072 or lower ?\n"); - aborting = 1; - break; + } + if (sz > 0) { + if (verbose) { + account_good_read(t_now, sz); } - if (error == ENXIO) { - printf("Input device probably detached...\n"); - aborting = 1; - break; + if (t_report != t_now) { + report(sz); + t_report = t_now; } + continue; } - if (aborting) - save_worklist(); - if (aborting || !TAILQ_NEXT(lp, list)) - report(lp, sz); - if (aborting) + + monitor_read_sizes(-sz); + + if (error == EINVAL) { + printf("Try with -b 131072 or lower ?\n"); + aborting = 1; break; - assert(lp->len == 0); - TAILQ_REMOVE(&lumps, lp, list); - free(lp); + } + if (error == ENXIO) { + printf("Input device probably detached...\n"); + aborting = 1; + break; + } + report(-sz); + t_report = t_now; + if (error_pause > 0) { + usleep((unsigned long)(1e6 * error_pause)); + } } + save_worklist(); + free(work_buf); + if (pattern_buf != NULL) + free(pattern_buf); printf("%s", aborting ? "Aborted\n" : "Completed\n"); - free(buf); - return (0); + report(0UL); + return (0); // XXX } diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c index 631c2860b547..ba22a2ec1e22 100644 --- a/sbin/route/route_netlink.c +++ b/sbin/route/route_netlink.c @@ -738,6 +738,7 @@ print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct snl_msg_info *cinf print_nlmsg_generic(h, hdr, cinfo); } + fflush(stdout); snl_clear_lb(&h->ss_cmd); } diff --git a/sbin/savecore/savecore.8 b/sbin/savecore/savecore.8 index 53d2360719dd..1fb79c51f98d 100644 --- a/sbin/savecore/savecore.8 +++ b/sbin/savecore/savecore.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 4, 2022 +.Dd July 16, 2025 .Dt SAVECORE 8 .Os .Sh NAME @@ -69,7 +69,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl C Check to see if a dump exists, @@ -193,7 +193,7 @@ is meant to be called near the end of the initialization file .Xr zstd 1 , .Xr getbootfile 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr mem 4 , .Xr textdump 4 , .Xr tar 5 , diff --git a/share/examples/oci/Containerfile.pkg b/share/examples/oci/Containerfile.pkg index 074c470affc9..f6699c79af71 100644 --- a/share/examples/oci/Containerfile.pkg +++ b/share/examples/oci/Containerfile.pkg @@ -6,7 +6,7 @@ ARG version=14.snap # Select freebsd-runtime as our starting point. -FROM localhost/freebsd-runtime:${version} +FROM ghcr.io/freebsd/freebsd-runtime:${version} # A list of package(s) to install ARG packages @@ -15,7 +15,10 @@ ARG packages # use for downloading pkg since the freebsd-runtime image has both FreeBSD and # FreeBSD-base pkg repo configs installed and FreeBSD-base does not contain the # pkg package. -RUN env ASSUME_ALWAYS_YES=yes pkg bootstrap -r FreeBSD && pkg update +# +# Set IGNORE_OSVERSION to allow building e.g. FreeBSD-14 images on +# FreeBSD-15 hosts. +RUN pkg bootstrap -y -r FreeBSD && pkg -o IGNORE_OSVERSION=yes update -f # Install some package(s). RUN pkg install -y ${packages} diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 5648fd2c1a84..505e83a67369 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -594,6 +594,7 @@ MAN= aac.4 \ tws.4 \ udp.4 \ udplite.4 \ + ${_ufshci.4} \ unionfs.4 \ ure.4 \ vale.4 \ @@ -746,7 +747,6 @@ MLINKS+=lge.4 if_lge.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=malo.4 if_malo.4 -MLINKS+=md.4 vn.4 MLINKS+=mem.4 kmem.4 MLINKS+=mfi.4 mfi_linux.4 \ mfi.4 mfip.4 @@ -938,6 +938,10 @@ MLINKS+=hwt.4 spe.4 .endif .endif +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64" +_ufshci.4= ufshci.4 +.endif + .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" || \ ${MACHINE_CPUARCH} == "aarch64" _gve.4= gve.4 @@ -981,11 +985,13 @@ _ccd.4= ccd.4 .if ${MK_CDDL} != "no" _dtrace_provs= dtrace_audit.4 \ dtrace_dtrace.4 \ + dtrace_fbt.4 \ dtrace_io.4 \ dtrace_ip.4 \ dtrace_kinst.4 \ dtrace_lockstat.4 \ dtrace_proc.4 \ + dtrace_profile.4 \ dtrace_sched.4 \ dtrace_sctp.4 \ dtrace_tcp.4 \ diff --git a/share/man/man4/dtrace_fbt.4 b/share/man/man4/dtrace_fbt.4 new file mode 100644 index 000000000000..3e35bb8c5bbc --- /dev/null +++ b/share/man/man4/dtrace_fbt.4 @@ -0,0 +1,332 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Mateusz Piotrowski <0mp@FreeBSD.org> +.\" +.Dd July 16, 2025 +.Dt DTRACE_FBT 4 +.Os +.Sh NAME +.Nm dtrace_fbt +.Nd a DTrace provider for dynamic kernel tracing based on function boundaries +.Sh SYNOPSIS +.Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:entry +.Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:return +.Sh DESCRIPTION +The Function Boundary Tracing +.Pq Nm fbt +provider instruments the entry and return of almost every kernel function +corresponding to an +.Xr elf 5 +symbol in the kernel and loaded kernel modules. +.Pp +.Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:entry +fires whenever the +.Ar function +is called. +.Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:return +fires when the +.Ar function +returns. +.Pp +The +.Ar module +in the probe description is either the name of the loaded kernel module +or +.Ql kernel +for functions compiled into the kernel. +.Ss Function Boundary Instrumentation +The +.Nm fbt +will always instrument a function's entry, but +its return will be intsrumented so long as it can find a +.Ql ret +instruction. +.Pp +In some cases, +.Nm fbt +cannot instrument a function's entry and/or return. +Refer to subsection +.Sx Frame Pointer +for more details. +.Ss Probe Arguments +The arguments of the entry probe +.Pq Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:entry +are the arguments of the traced function call. +.Bl -column -offset indent "Entry Probe Argument" "Definition" +.It Sy Entry Probe Argument Ta Sy Definition +.It Fa args[0] Ta Function's first argument, typed +.Pq e.g., Xr malloc 9 Ap s Ft size_t Fa size +.It Fa args[1] Ta Function's second argument, typed +.Pq e.g., Xr malloc 9 Ap s Ft struct malloc_type Fa *type +.It Fa args[2] Ta Function's third argument, typed +.Pq e.g., Xr malloc 9 Ap s Ft int Fa flags +.It Fa ... Ta ... +.El +.Pp +The arguments of the return probe +.Pq Nm fbt Ns Cm \&: Ns Ar module Ns Cm \&: Ns Ar function Ns Cm \&:return +are +.Fa args[0] +.Po +the offset of the firing return instruction within the function; +useful to tell apart two different return statements in a single function +.Pc +and +.Fa args[1] +.Pq the return value, if any . +.Bl -column -offset indent "Return Probe Argument" "Definition" +.It Sy Return Probe Argument Ta Sy Definition +.It Fa args[0] Ta Offset of the traced return instruction +.It Fa args[1] Ta Function's return value +.Po e.g., a kernel virtual address if returning from a successful +.Xr malloc 9 +.Pc +.El +.Pp +Subsection +.Sx Example 2 : Getting Details About Probe's Arguments +shows how to get probe's argument count and types directly with +.Xr dtrace 1 +without having to resort to the reading function's source code +or documentation. +.Sh EXAMPLES +.Ss Example 1 : Listing Available FBT Probes +The following example shows how to list all the available +.Nm fbt +probes. +.Bd -literal -offset 2n +# dtrace -l -P fbt + ID PROVIDER MODULE FUNCTION NAME +[...] +31868 fbt kernel hammer_time entry +31869 fbt kernel hammer_time return +[...] +.Ed +.Pp +Since +.Fn hammer_time +is a part of the kernel and not a separate loaded module, the +.Ar module +column displays +.Ql kernel . +.Ss Example 2 : Getting Details About Probe's Arguments +The following example shows how to generate a program stability report of +.Xr malloc 9 Ap s +entry and return probes. +Those reports are useful to view +the probe's number of arguments and their types. +.Bd -literal -offset 2n +# dtrace -l -v -n fbt::malloc:entry +[...] + Argument Types + args[0]: size_t + args[1]: struct malloc_type * + args[2]: int +.Ed +.Pp +The count and types of +.Nm fbt Ns Cm \&::malloc:entry +arguments +match the function signature of +.Xr malloc 9 : +.Va args[0] +is +.Ft size_t , +.Va args[1] +is +.Ft "struct malloc_type *" , +and +.Va "args[2]" +is +.Ft int . +.Bd -literal -offset 2n +# dtrace -l -v -n fbt::malloc:return +[...] + Argument Types + args[0]: int + args[1]: void * +.Ed +.Pp +The +.Cm return +probe reports two arguments and their types: +the return instruction offset +.Pq the usual Ft int +and the function's return value, which in this case is +.Ft void * , +as +.Xr malloc 9 +returns a kernel virtual address. +.Ss Example 3 : Counting Kernel Slab Memory Allocation by Function +.Bd -literal -offset 2n +# dtrace -n 'fbt::kmem*:entry { @[probefunc] = count(); }' +dtrace: description 'fbt::kmem*:entry ' matched 47 probes +^C + kmem_alloc_contig 1 + kmem_alloc_contig_domainset 1 + kmem_cache_reap_active 1 + kmem_alloc_contig_pages 2 + kmem_free 2 + kmem_std_destructor 19 + kmem_std_constructor 26 + kmem_cache_free 151 + kmem_cache_alloc 181 +.Ed +.Ss Example 4 : Counting Kernel Slab Memory Allocation by Calling Function +.Bd -literal -offset 2n +# dtrace -q -n 'fbt::kmem*:entry { @[caller] = count(); } END { printa("%40a %@16d\en", @); }' +^C + kernel`contigmalloc+0x33 1 + kernel`free+0xd3 1 + kernel`kmem_alloc_contig+0x29 1 +kernel`kmem_alloc_contig_domainset+0x19a 1 + zfs.ko`arc_reap_cb_check+0x16 1 +.Ed +.Ss Example 5 : Counting Kernel malloc()'s by Calling Function +.Bd -literal -offset 2n +# dtrace -q -n 'fbt::malloc:entry { @[caller] = count(); } END { printa("%45a %@16d\en", @); }' +^C + kernel`devclass_get_devices+0xa8 1 + kernel`sys_ioctl+0xb7 1 + dtrace.ko`dtrace_ioctl+0x15c1 1 + dtrace.ko`dtrace_ioctl+0x972 2 + dtrace.ko`dtrace_dof_create+0x35 2 + kernel`kern_poll_kfds+0x2f0 4 + kernel`kern_poll_kfds+0x28a 19 +.Ed +.Ss Example 6 : Counting Kernel malloc()'s by Kernel Stack Trace +.Bd -literal -offset 2n +# dtrace -q -n 'fbt::malloc:entry { @[stack()] = count(); }' +^C + dtrace.ko`dtrace_dof_create+0x35 + dtrace.ko`dtrace_ioctl+0x827 + kernel`devfs_ioctl+0xd1 + kernel`VOP_IOCTL_APV+0x2a + kernel`vn_ioctl+0xb6 + kernel`devfs_ioctl_f+0x1e + kernel`kern_ioctl+0x286 + kernel`sys_ioctl+0x12f + kernel`amd64_syscall+0x169 + kernel`0xffffffff81092b0b + 2 +.Ed +.Ss Example 7 : Summarizing vmem_alloc()'s by Arena Name and Size Distribution +.Bd -literal -offset 2n +# dtrace -q -n 'fbt::vmem_alloc:entry { @[args[0]->vm_name] = quantize(arg1); }' +^C + + kernel arena dom + value ------------- Distribution ------------- count + 2048 | 0 + 4096 |@@@@@@@@@@@@@@@@@@@@@@@@@@@ 4 + 8192 |@@@@@@@@@@@@@ 2 + 16384 | 0 +.Ed +.Ss Example 8 : Measuring Total Time Spent Executing a Function +This DTrace script measures the total time spent in +.Fn vm_page* +kernel functions. +The +.Fn quantize +aggregation organizes the measurements into power-of-two buckets, +providing a time distribution in nanoseconds for each function. +.Bd -literal -offset 2n +fbt::vm_page*:entry { + self->start = timestamp; +} + +fbt::vm_page*:return /self->start/ { + @[probefunc] = quantize(timestamp - self->start); + self->start = 0; +} +.Ed +.Sh SEE ALSO +.Xr dtrace 1 , +.Xr dtrace_kinst 4 , +.Xr tracing 7 +.Rs +.%A Brendan Gregg +.%A Jim Mauro +.%B DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD +.%I Prentice Hall +.%P pp. 898\(en903 +.%D 2011 +.%U https://www.brendangregg.com/dtracebook/ +.Re +.Rs +.%B The illumos Dynamic Tracing Guide +.%O Chapter fbt Provider +.%D 2008 +.%U https://illumos.org/books/dtrace/chp-fbt.html#chp-fbt +.Re +.Sh AUTHORS +This manual page was written by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . +.Sh CAVEATS +.Ss Stability and Portability +.Nm fbt +probes are by definition tightly coupled to kernel code; if the code underlying +a script changes, the script may fail to run or may produce incorrect results. +Scripts written for one version of +.Fx +might not work on others, +and almost certainly will not work on other operating systems. +.Pp +Individual +.Nm fbt +probes often do not correspond nicely to logical system events. +For example, consider a DTrace script which prints the destination +address of every IP packet as the kernel hands them over +to the network card driver (NIC). +An +.Nm fbt Ns -based +implementation of such a script is a discouragingly difficult task: +it involves instrumenting at least four different functions in different parts +of the IPv4 and IPv6 code. +At the same time, with the +.Xr dtrace_ip 4 +provider the script is a simple one-liner: +.Dl dtrace -n 'ip:::send {printf("%s", args[2]->ip_daddr);}' +.Pp +Make sure to review available +.Xr dtrace 1 +providers first +before implementing a custom script with the +.Nm fbt +provider. +If none of the DTrace providers offer the desired probes, +consider adding new statically-defined tracing probes +.Pq Xr SDT 9 . +.Ss Frame Pointer +Inline functions are not instrumentable by +.Nm fbt +as they lack a frame pointer. +A developer might explicitly disable inlining by adding the +.Ql __noinline +attribute to a function definition, +but of course this requires a recompilation of the kernel. +Building the kernel with +.Fl fno-omit-frame-pointer +is another way of preserving frame pointers. +Note, that sometimes compilers will omit the frame pointer in leaf functions, +even when configured with +.Fl fno-omit-frame-pointer . +.Pp +Function returns via a tail call are also not instrumentable by +.Nm fbt . +As a result, +a function might have an entry probe +and a mix of instrumented and uninstrumentable returns. +.Pp +Use +.Xr dtrace_kinst 4 +to trace arbitrary instructions inside kernel functions +and work around some of the +limitations +of +.Nm fbt . +.Ss Tracing DTrace +The +.Nm fbt +provider cannot attach to functions inside DTrace provider kernel modules. diff --git a/share/man/man4/dtrace_kinst.4 b/share/man/man4/dtrace_kinst.4 index 9debbc1bd106..c2187689749b 100644 --- a/share/man/man4/dtrace_kinst.4 +++ b/share/man/man4/dtrace_kinst.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 27, 2023 +.Dd July 16, 2025 .Dt DTRACE_KINST 4 .Os .Sh NAME @@ -43,10 +43,13 @@ creates probes on-demand, meaning it searches for and parses the function's instructions each time .Xr dtrace 1 is run, and not at module load time. -This is in contrast to FBT's load-time parsing, since +This is in contrast to +.Xr dtrace_fbt 4 Ap s +load-time parsing, since .Nm kinst can potentially create thousands of probes for just a single function, instead -of up to two (entry and return) in the case of FBT. +of up to two (entry and return) in the case of +.Xr dtrace_fbt 4 . A result of this is that .Cm dtrace -l -P kinst will not match any probes. @@ -79,7 +82,8 @@ Trace all instructions in # dtrace -n 'kinst::amd64_syscall:' .Ed .Sh SEE ALSO -.Xr dtrace 1 +.Xr dtrace 1 , +.Xr dtrace_fbt 4 .Sh HISTORY The .Nm kinst diff --git a/share/man/man4/dtrace_profile.4 b/share/man/man4/dtrace_profile.4 new file mode 100644 index 000000000000..07f86663d60a --- /dev/null +++ b/share/man/man4/dtrace_profile.4 @@ -0,0 +1,129 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Mateusz Piotrowski <0mp@FreeBSD.org> +.\" +.Dd July 14, 2025 +.Dt DTRACE_PROFILE 4 +.Os +.Sh NAME +.Nm dtrace_profile +.Nd a DTrace provider for firing probes at a given time interval +.Sh SYNOPSIS +.Nm profile Ns Cm :::profile- Ns Ar rate Ns Op Ar unit +.Nm profile Ns Cm :::tick- Ns Ar rate Ns Op Ar unit +.Sh DESCRIPTION +The +.Nm profile +provider implements three special probes related to the life cycle of the +DTrace program itself. +.Ss Probes +The +.Nm profile Ns Cm :::profile +probes fire on all CPUs and are suitable for measuring the whole system +periodically. +.Pp +The +.Nm profile Ns Cm :::tick +probes fire on a single CPU, potentially a different one every time. +They are useful, e.g., for printing partial results periodically. +.Ss Rate and Time Units +The +.Nm profile +provider probes will fire at the specified +.Ar rate . +.Pp +The default unit is +.Cm hz . +The +.Nm profile +provider supports the following time units: +.Bl -column -offset indent "ns, nsec" "Definition" +.It Sy Time Unit Ta Sy Definition +.It Cm ns , nsec Ta nanoseconds +.It Cm us , usec Ta microseconds +.It Cm ms , msec Ta milliseconds +.It Cm s , sec Ta seconds +.It Cm m , min Ta minutes +.It Cm h , hour Ta hours +.It Cm d , day Ta days +.It Cm hz Ta Hertz (frequency per second) +.El +.Ss Probe Arguments +The arguments of the +.Nm profile +provider probes +are: +.Bl -tag -width arg0 +.It Va arg0 +The PC (program counter) in the kernel when the probe triggered, +or 0 if the process was not in the kernel at that time. +.It Va arg1 +The PC in the user process when the probe triggered, +or 0 if the process was in the kernel when the probe triggered. +.El +.Pp +Use arguments +.Va arg0 +and +.Va arg1 +to tell if the +.Nm profile +provider probe fired in the kernel or in the userspace context. +.Sh IMPLEMENTATION NOTES +The +.Xr sysctl 8 +variable +.Va kern.dtrace.profile.aframes +controls the number of skipped artificial frames for +the +.Nm profile +provider. +.Sh EXAMPLES +.Ss Example 1 : Profiling On-CPU Kernel Stack Traces +The following DTrace one-liner uses the +.Nm profile +provider to collect stack traces over 60 seconds. +.\" XXX: Keep on one line for easier copy-pasting. +.Bd -literal -offset indent +dtrace -x stackframes=100 -n 'profile-197 /arg0/ {@[stack()] = count();} tick-60s {exit(0);} +.Ed +.Pp +The system is profiled at the 197 Hz to avoid sampling in lockstep +with other periodic activities. +This unnatural frequency minimizes the chance of overlapping with other events. +.Pp +Option +.Fl x Cm stackframes=100 +increases the maximum number of kernel stack frames to unwind during +.Fn stack . +.Pp +Checking if +.Ar arg0 +is not zero makes sure that profiling happens +when the program is in the kernel context. +.Pp +Refer to +.Lk https://www.brendangregg.com/flamegraphs.html +to learn about generating flame graphs from the obtained stack traces. +.Sh SEE ALSO +.Xr dtrace 1 , +.Xr tracing 7 +.Rs +.%B The illumos Dynamic Tracing Guide +.%O Chapter profile Provider +.%D 2008 +.%U https://www.illumos.org/books/dtrace/chp-profile.html +.Re +.Rs +.%A Brendan Gregg +.%A Jim Mauro +.%B DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD +.%I Prentice Hall +.%P pp. 24\(en25 +.%D 2011 +.%U https://www.brendangregg.com/dtracebook/ +.Re +.Sh AUTHORS +This manual page was written by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . diff --git a/share/man/man4/gif.4 b/share/man/man4/gif.4 index 959510451011..ad33d5d21e81 100644 --- a/share/man/man4/gif.4 +++ b/share/man/man4/gif.4 @@ -1,6 +1,7 @@ .\" $KAME: gif.4,v 1.28 2001/05/18 13:15:56 itojun Exp $ .\" .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +.\" Copyright (C) 2024 Hiroki Sato <hrs@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -27,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 21, 2018 +.Dd July 14, 2025 .Dt GIF 4 .Os .Sh NAME @@ -67,8 +68,8 @@ variable in .Pp To use .Nm , -the administrator needs to configure the protocol and addresses used for the outer -header. +the administrator needs to configure the protocol and addresses used for +the outer header. This can be done by using .Xr ifconfig 8 .Cm tunnel , @@ -79,8 +80,7 @@ The administrator also needs to configure the protocol and addresses for the inner header, with .Xr ifconfig 8 . Note that IPv6 link-local addresses -(those that start with -.Li fe80:: ) +.Pq those that start with Li fe80\&:\&: will be automatically configured whenever possible. You may need to remove IPv6 link-local addresses manually using .Xr ifconfig 8 , @@ -89,12 +89,139 @@ if you want to disable the use of IPv6 as the inner header Finally, you must modify the routing table to route the packets through the .Nm interface. +.Ss MTU Configuration and Path MTU Discovery +The +.Nm +interface uses the fixed length, +.Li 1280 , +to determine whether the outgoing IPv6 packets are split. +This means the MTU value configured on the interface will be ignored +when the outer protocol is IPv6. +When the +.Dv NOCLAMP +interface flag is set, +.Nm +uses the same configured value as IPv4 communications. +This behavior prevents potential issues when the path MTU is +smaller than the interface MTU. +This section describes the reason why the default behavior is different. +The +.Dv NOCLAMP +interface flag can be set using the following command: +.Pp +.Dl ifconfig Ar gif0 Cm noclamp +.Pp +and clear the flag using the following: +.Pp +.Dl ifconfig Ar gif0 Cm -noclamp +.Pp +where +.Ar gif0 +is the actual interface name. +.Pp +A tunnel interface always has an implicit smaller MTU for the inner protocol +than the outer protocol because of the additional header. +Note that the interface MTU on a +.Nm +interface, +the default value is +.Li 1280 , +is used as MTU for the outer protocol. +This means that the MTU for the inner protocol varies depending on the +outer protocol header length. +If an outgoing packet bigger than the inner protocol MTU arrives at a +.Nm +interface for encapsulation, +it will be split into fragments. +Specifically, +if IPv4 is used as the outer protocol, +the inner is 20 octets smaller than the interface MTU. +In the case of the default interface MTU, +.Li 1280 , +inner packets bigger than +.Li 1260 +will be fragmented. +In the case of IPv6, +the inner is 40 octets smaller than the outer. +.Pp +This fragmentation is not harmful though it can degrade the +performance. +Note that while an increased MTU on +.Nm +interface helps to mitigate this reduced performance issue, +it can also cause packet losses on the intermediate narrowest path +between the two communication endpoints in IPv6. +IPv6 allows fragmentation only on the sender, +not on the routers in the communication path. +A big outgoing packet will be dropped on a router with a smaller MTU. .Pp +In normal IPv6 communication, +an ICMPv6 Packet Too Big error will be sent back to the sender, +who can adjust the packet length and re-send it. +This process is performed in the upper protocols than L3, +such as TCP, +and makes the packet length shorter so that packets go through +the path without fragmentation. +This behavior is known as path MTU discovery. +.Pp +When using a +.Nm +interface, +the Packet Too Big message is generated for the outer protocol. +Since the +.Nm +interface does not translate this error to the inner protocol, +the inner protocol sees it just as a packet loss with no useful +information to adjust the length of the next packets. +In this situation, +path MTU discovery does not work, +and communications of the inner protocol +become stalled. +.Pp +In order to avoid this, +a +.Nm +interface silently splits a packet of over 1240 octets into fragments to make +the outer protocol packets equal or shorter than 1280 octets, +even when the interface MTU is configured as larger than 1280. +Note that this occurs only when the outer protocol is IPv6. +.Li 1280 +is the smallest MTU in IPv6 and guarantees no packet loss occurs +on intermediate routers. +.Pp +As mentioned earlier, +the performance is sub-optimal if the actual path MTU is larger than +.Li 1280 . +A typical confusing scenario is as follows. The .Nm -device can be configured to be ECN friendly. -This can be configured by -.Dv IFF_LINK1 . +interface can have Ethernet, +whose MTU is usually 1500, +as the inner protocol. +It is called an EtherIP tunnel, +and can be configured by adding the +.Nm +interface as a member of +.Xr if_bridge 4 +interface. +The +.Xr if_bridge 4 +interface forcibly changes the MTU of the +.Nm +interface with those for the other member interfaces, +which are likely 1500. +In this case, +a situation in which the MTU of the +.Nm +interface is 1500 but fragmentation in 1280 octets always occurs. +.Pp +The default behavior is most conservative to prevent confusing packet loss. +Depending on the network configuration, +enabling the +.Dv NOCLAMP +interface flag might be helpful for better performance. +It is crucial to ensure that the path MTU is equal to or larger than +the interface MTU when enabling this flag. .Ss ECN friendly behavior The .Nm @@ -169,6 +296,7 @@ variable to the desired level of nesting. .Sh SEE ALSO .Xr gre 4 , +.Xr if_bridge 4 , .Xr inet 4 , .Xr inet6 4 , .Xr ifconfig 8 @@ -199,7 +327,8 @@ There are many tunnelling protocol specifications, all defined differently from each other. The .Nm -device may not interoperate with peers which are based on different specifications, +device may not interoperate with peers which are based on different +specifications, and are picky about outer header fields. For example, you cannot usually use .Nm @@ -219,11 +348,14 @@ to 1240 or smaller, when the outer header is IPv6 and the inner header is IPv4. .Pp The .Nm -device does not translate ICMP messages for the outer header into the inner header. +device does not translate ICMP messages for the outer header into the inner +header. .Pp In the past, .Nm had a multi-destination behavior, configurable via -.Dv IFF_LINK0 +.Dv NOCLAMP flag. The behavior is obsolete and is no longer supported. +This flag is now used to determine whether performing fragmentation when +the outer protocol is IPv6. diff --git a/share/man/man4/md.4 b/share/man/man4/md.4 index 0c99d61f8392..1da26ddda037 100644 --- a/share/man/man4/md.4 +++ b/share/man/man4/md.4 @@ -5,7 +5,7 @@ .\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp .\" ---------------------------------------------------------------------------- .\" -.Dd January 8, 2020 +.Dd July 16, 2025 .Dt MD 4 .Os .Sh NAME @@ -158,7 +158,7 @@ installation process. The .Nm driver did a hostile takeover of the -.Xr vn 4 +.Sy vn driver in .Fx 5.0 . .Sh AUTHORS diff --git a/share/man/man4/mtw.4 b/share/man/man4/mtw.4 index 17722be73203..6aa59d848d36 100644 --- a/share/man/man4/mtw.4 +++ b/share/man/man4/mtw.4 @@ -24,23 +24,41 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 03, 2025 +.Dd May 3, 2025 .Dt MTW 4 .Os .Sh NAME -.Nm if_mtw -.Nd "Mediatek MT7601U" -.Ed +.Nm mtw +.Nd MediaTek MT7601U USB IEEE 802.11n wireless network driver +.Sh SYNOPSIS +.Cd device usb +.Cd device mtw +.Cd device wlan +.Pp +In +.Xr rc.conf 5 : +.Cd kld_list="if_mtw" .Sh DESCRIPTION -This module provides support for Mediatek MT7601U with the firmware from net/wifi-firmware-mtw-kmod - +This module provides support for +MediaTek MT7601U USB wireless network adapters. +If the appropriate hardware is detected, +the driver will be automatically loaded with +.Xr devmatch 8 . +If driver autoloading is explicitly disabled, enable the module in +.Xr rc.conf 5 . +The +.Nm +driver can be configured at runtime with +.Xr ifconfig 8 +or at boot with +.Xr rc.conf 5 . .Sh HARDWARE The .Nm -driver supports Mediatek MT7601U -based USB wireless network adapters including (but not all of them tested): +driver supports MediaTek MT7601U based USB wireless network adapters +including (but not all of them tested): .Pp -.Bl -column -compact +.Bl -bullet -compact .It ASUS USB-N10 v2 .It @@ -58,17 +76,43 @@ TP-LINK TL-WN727N v4 (tested working) .It Yealink WF40 .El +.Sh FILES +The +.Nm +driver requires firmware from +.Pa ports/net/wifi-firmware-mt7601u-kmod . +This firmware package will be installed automatically with +.Xr fwget 8 +if the appropriate hardware is detected at installation or runtime. .Sh SEE ALSO -.Xr usb 4 -.Sh BUGS +.Xr usb 4 , +.Xr wlan 4 , +.Xr networking 7 , +.Xr fwget 8 , +.Xr wpa_supplicant 8 +.Sh HISTORY The .Nm -only works in station mode and monitor mode. The firmware does not always reinitialize when reloading the module, or when rebooting, without first unplugging the device. -.Sh History -The mtw driver first appeared in OpenBSD 7.1. The mtw driver was ported to FreeBSD in FreeBSD 15.0. +driver first appeared in +.Ox 7.1 +and +.Fx 15.0 . .Sh AUTHORS .An -nosplit -The mtw driver was written by +The +.Nm +driver was written by .An James Hastings Aq Mt hastings@openbsd.org -ported to FreeBSD by -.An Jesper Schmitz Mouridsen Aq Mt jsm@FreeBSD.org +and ported to +.Fx +by +.An Jesper Schmitz Mouridsen Aq Mt jsm@FreeBSD.org . +.Sh BUGS +.Nm +only works in +.Cm station +mode and +.Cm monitor +mode. +The firmware does not always reinitialize when reloading the module, +or when rebooting, without first unplugging the device. diff --git a/share/man/man4/sa.4 b/share/man/man4/sa.4 index 96b11ebe5360..699a940a34d1 100644 --- a/share/man/man4/sa.4 +++ b/share/man/man4/sa.4 @@ -457,7 +457,8 @@ One EOM notification will be sent, BPEW status will be set for one position query, and then the driver state will be reset to normal. .Sh SEE ALSO .Xr mt 1 , -.Xr cam 4 +.Xr cam 4 , +.Xr mtio 4 .Sh AUTHORS .An -nosplit The diff --git a/share/man/man4/snd_uaudio.4 b/share/man/man4/snd_uaudio.4 index 00329a6d8e40..7193c85fa4f0 100644 --- a/share/man/man4/snd_uaudio.4 +++ b/share/man/man4/snd_uaudio.4 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" $NetBSD: uaudio.4,v 1.15 2002/02/12 19:53:57 jdolecek Exp $ .\" .\" Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -27,32 +30,30 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 15, 2025 +.Dd July 17, 2025 .Dt SND_UAUDIO 4 .Os .Sh NAME .Nm snd_uaudio .Nd USB audio and MIDI device driver .Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent .Cd "device sound" .Cd "device usb" .Cd "device snd_uaudio" -.Ed .Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -snd_uaudio_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for USB audio class devices and USB MIDI class devices. +In +.Xr rc.conf 5 : +.Cd kld_list="snd_uaudio" .Pp +In +.Xr sysctl.conf 5 : +.Cd hw.usb.uaudio.buffer_ms +.Cd hw.usb.uaudio.default_bits +.Cd hw.usb.uaudio.default_channels +.Cd hw.usb.uaudio.default_rate +.Cd hw.usb.uaudio.handle_hid +.Cd hw.usb.uaudio.debug +.Sh DESCRIPTION A USB audio device consists of a number of components: input terminals (e.g.\& USB digital input), output terminals (e.g.\& speakers), and a number of units in between (e.g.\& volume control). @@ -68,6 +69,11 @@ sample rate and sample size. Refer to the .Ql USB Audio Class Specification for more information. +.Sh HARDWARE +The +.Nm +driver provides support for USB audio class devices and +USB MIDI class devices. .Sh SYSCTL VARIABLES The following settings can be entered at the .Xr loader 8 diff --git a/share/man/man4/ufshci.4 b/share/man/man4/ufshci.4 new file mode 100644 index 000000000000..d722c9902b98 --- /dev/null +++ b/share/man/man4/ufshci.4 @@ -0,0 +1,181 @@ +.\" +.\" Copyright (c) 2025, Samsung Electronics Co., Ltd. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" ufshci driver man page. +.\" +.\" Author: Jaeyoon Choi <j_yoon.choi@samsung.com> +.\" +.Dd July 17, 2025 +.Dt UFSHCI 4 +.Os +.Sh NAME +.Nm ufshci +.Nd Universal Flash Storage Host Controller Interface driver +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following line in the kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ufshci" +.Ed +.Pp +Or, to load the driver as a module at boot, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +ufshci_load="YES" +.Ed +.Sh DESCRIPTION +Universal Flash Storage (UFS) is a low-power, high-performance storage +standard composed of a host controller and a single target device. +.Pp +The driver currently provides: +.Bl -bullet +.It +Initialization of the host controller and the target device +.It +Handling of UFS Interconnect (UIC) commands +.It +Support for UTP Transfer Requests (UTR) and UTP Task Management Requests (UTMR) +.It +Support for the SCSI command set +.It +Operation in the legacy single-doorbell queue mode +.It +Support for the PCI Express bus +.El +.Pp +After initialization, the controller is registered with the +.Xr cam 4 +subsystem and its logical unit appears as the device node +.Pa /dev/daX . +.Pp +The driver is under active development; upcoming work includes full +UFS 4.1 feature coverage, additional power-management modes, and +ACPI/FDT-based attach support. +.Sh HARDWARE +The +.Nm +driver supports both host controllers and devices implementing the +Universal Flash Storage Host Controller Interface 4.1 and earlier. +.Sh CONFIGURATION +The +.Nm +driver currently operates with a single doorbell (one I/O-queue), so any +tunables that change the queue count are ignored. +When Multi-Circular Queue (MCQ) support is added and multiple queues +become available, the following queue count tunable values will take effect: +.Pp +To force a single I/O queue pair shared by all CPUs, set the following +tunable value in loader.conf(5): +.Bd -literal -offset indent +hw.ufshci.per_cpu_io_queues=0 +.Ed +.Pp +To assign more than one CPU per I/O queue pair, thereby reducing the +number of MSI-X vectors consumed by the device, set the following tunable +value in loader.conf(5): +.Bd -literal -offset indent +hw.ufshci.min_cpus_per_ioq=X +.Ed +.Pp +To change the I/O command timeout value (in seconds), set the following tunable +value in loader.conf(5): +.Bd -literal -offset indent +hw.ufshci.timeout_period=X +.Ed +.Pp +To change the I/O command retry count, set the following tunable value in +loader.conf(5): +.Bd -literal -offset indent +hw.ufshci.retry_count=X +.Ed +.Pp +To force the driver to use legacy INTx interrupts, set the following tunable +value in loader.conf(5): +.br +(Note: until MCQ support is available the driver always uses legacy INTx, so +this value effectively remains 1) +.Bd -literal -offset indent +hw.ufshci.force_intx=1 +.Ed +.Sh SYSCTL VARIABLES +The following controller-level +.Xr sysctl 8 +nodes are currently implemented: +.Bl -tag -width indent +.It Va dev.ufshci.0.num_failures +(R) Number of command failures for the entire controller. +.It Va dev.ufshci.0.num_retries +(R) Number of command retries for the entire controller. +.It Va dev.ufshci.0.num_intr_handler_calls +(R) Number of times the interrupt handler has been called. +.It Va dev.ufshci.0.num_cmds +(R) Total number of commands issued by the controller. +.It Va dev.ufshci.0.timeout_period +(RW) Configured timeout period (in seconds). +.It Va dev.ufshci.0.cap +(R) Host controller capabilities register value. +.It Va dev.ufshci.0.num_io_queues +(R) Number of I/O-queue pairs. +.It Va dev.ufshci.0.io_queue_mode +(R) Indicates single doorbell mode or multi circular queue mode. +.It Va dev.ufshci.0.minor_version +(R) Host controller minor version. +.It Va dev.ufshci.0.major_version +(R) Host controller major version. +.It Va dev.ufshci.0.utmrq.num_failures +(R) Number of failed UTP task-management requests. +.It Va dev.ufshci.0.utmrq.ioq.num_retries +(R) Number of retried UTP task-management requests. +.It Va dev.ufshci.0.utmrq.num_intr_handler_calls +(R) Number of interrupt handler calls caused by UTP task-management requests. +.It Va dev.ufshci.0.utmrq.num_cmds +(R) Number of UTP task-management requests issued. +.It Va dev.ufshci.0.utmrq.cq_head +(R) Current location of the UTP task-management completion queue head. +.It Va dev.ufshci.0.utmrq.sq_tail +(R) Current location of the UTP task-management submission queue tail. +.It Va dev.ufshci.0.utmrq.sq_head +(R) Current location of the UTP task-management submission queue head. +.It Va dev.ufshci.0.utmrq.num_trackers +(R) Number of trackers in the UTP task-management queue. +.It Va dev.ufshci.0.utmrq.num_entries +(R) Number of entries in the UTP task-management queue. +.It Va dev.ufshci.0.ioq.0.num_failures +(R) Number of failed UTP transfer requests. +.It Va dev.ufshci.0.ioq.0.num_retries +(R) Number of retried UTP transfer requests. +.It Va dev.ufshci.0.ioq.0.num_intr_handler_calls +(R) Number of interrupt-handler calls caused by UTP transfer requests. +.It Va dev.ufshci.0.ioq.0.num_cmds +(R) Number of UTP transfer requests issued. +.It Va dev.ufshci.0.ioq.0.cq_head +(R) Current location of the UTP transfer completion queue head. +.It Va dev.ufshci.0.ioq.0.sq_tail +(R) Current location of the UTP transfer submission queue tail. +.It Va dev.ufshci.0.ioq.0.sq_head +(R) Current location of the UTP transfer submission queue head. +.It Va dev.ufshci.0.ioq.0.num_trackers +(R) Number of trackers in the UTP transfer queue. +.It Va dev.ufshci.0.ioq.0.num_entries +(R) Number of entries in the UTP transfer queue. +.El +.Sh SEE ALSO +.Xr cam 4 , +.Xr pci 4 , +.Xr disk 9 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 15.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was developed by Samsung Electronics and originally written by +.An Jaeyoon Choi Aq Mt j_yoon.choi@samsung.com . +.Pp +This manual page was written by +.An Jaeyoon Choi Aq Mt j_yoon.choi@samsung.com . diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index b5843d67e106..8954e872c231 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 7, 2025 +.Dd July 9, 2025 .Dt PF.CONF 5 .Os .Sh NAME @@ -365,7 +365,7 @@ set timeout { adaptive.start 60000, adaptive.end 120000 } set limit states 100000 .Ed .Pp -With 9000 state table entries, the timeout values are scaled to 50% +With 90000 state table entries, the timeout values are scaled to 50% (tcp.first 60, tcp.established 43200). .It Ar set loginterface Enable collection of packet and byte count statistics for the given @@ -1387,7 +1387,7 @@ part of the new destination address according to the specified subnet. It is possible to embed a complete IPv4 address into an IPv6 address using a network prefix of /96 or smaller. .Pp -When a destination address is not specified it is assumed that the host +When a destination address is not specified, it is assumed that the host part is 32-bit long. For IPv6 to IPv4 translation this would mean using only the lower 32 bits of the original IPv6 destination address. @@ -2122,10 +2122,10 @@ options, or scrubbed with will also not be recoverable from intermediate packets. Such connections will stall and time out. .It Xo Ar icmp-type Aq Ar type -.Ar code Aq Ar code +.Ar Op code Aq Ar code .Xc .It Xo Ar icmp6-type Aq Ar type -.Ar code Aq Ar code +.Ar Op code Aq Ar code .Xc This rule only applies to ICMP or ICMPv6 packets with the specified type and code. @@ -2574,6 +2574,7 @@ will not work if .Xr pf 4 operates on a .Xr bridge 4 . +Also they act on incoming SYN packets only. .Pp Example: .Bd -literal -offset indent @@ -2783,8 +2784,8 @@ This means that it will not work on other protocols and will not match a currently established connection. .Pp Caveat: operating system fingerprints are occasionally wrong. -There are three problems: an attacker can trivially craft his packets to -appear as any operating system he chooses; +There are three problems: an attacker can trivially craft packets to +appear as any operating system; an operating system patch could change the stack behavior and no fingerprints will match it until the database is updated; and multiple operating systems may have the same fingerprint. @@ -3111,7 +3112,7 @@ rule can also contain a filter ruleset in a brace-delimited block. In that case, no separate loading of rules into the anchor is required. Brace delimited blocks may contain rules or other brace-delimited blocks. -When an anchor is populated this way the anchor name becomes optional. +When an anchor is populated this way, the anchor name becomes optional. .Bd -literal -offset indent anchor "external" on $ext_if { block diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 2fd63e4f743d..de2181d638d1 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 21, 2025 +.Dd July 15, 2025 .Dt RC.CONF 5 .Os .Sh NAME @@ -1164,8 +1164,8 @@ and is not found. Multiple rules can be set as follows: .Bd -literal -pf_fallback_rules="\\ - block drop log all\\ +pf_fallback_rules=" + block drop log all pass in quick on em0" .Pp .Ed diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 63e9f471f1f1..a3db00aed42f 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,5 +1,5 @@ .\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman. -.Dd July 5, 2025 +.Dd July 14, 2025 .Dt SRC.CONF 5 .Os .Sh NAME @@ -493,7 +493,7 @@ Do not build .Xr cxgbetool 8 .Pp This is a default setting on -arm/armv7, powerpc/powerpc and riscv/riscv64. +arm/armv7 and riscv/riscv64. .It Va WITH_CXGBETOOL Build .Xr cxgbetool 8 @@ -655,7 +655,7 @@ and .Xr efivar 8 . .Pp This is a default setting on -i386/i386, powerpc/powerpc, powerpc/powerpc64 and powerpc/powerpc64le. +i386/i386, powerpc/powerpc64 and powerpc/powerpc64le. .It Va WITH_EFI Build .Xr efivar 3 @@ -687,7 +687,7 @@ Build Flattened Device Tree support as part of the base system. This includes the device tree compiler (dtc) and libfdt support library. .Pp This is a default setting on -arm/armv7, arm64/aarch64, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. +arm/armv7, arm64/aarch64, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. .It Va WITHOUT_FILE Do not build .Xr file 1 @@ -750,7 +750,7 @@ Do not build HTML docs. Do not build or install HyperV utilities. .Pp This is a default setting on -arm/armv7, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. +arm/armv7, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. .It Va WITH_HYPERV Build or install HyperV utilities. .Pp @@ -916,7 +916,7 @@ On 64-bit platforms, do not build 32-bit library set and a runtime linker. .Pp This is a default setting on -arm/armv7, i386/i386, powerpc/powerpc, powerpc/powerpc64le and riscv/riscv64. +arm/armv7, i386/i386, powerpc/powerpc64le and riscv/riscv64. .It Va WITH_LIB32 On 64-bit platforms, build the 32-bit library set and a .Nm ld-elf32.so.1 @@ -935,7 +935,7 @@ arm/armv7 and riscv/riscv64. Build the LLDB debugger. .Pp This is a default setting on -amd64/amd64, arm64/aarch64, i386/i386, powerpc/powerpc, powerpc/powerpc64 and powerpc/powerpc64le. +amd64/amd64, arm64/aarch64, i386/i386, powerpc/powerpc64 and powerpc/powerpc64le. .It Va WITHOUT_LLD_BOOTSTRAP Do not build the LLD linker during the bootstrap phase of the build. @@ -1038,7 +1038,7 @@ with support for verification based on certificates obtained from UEFI. Disable inclusion of GELI crypto support in the boot chain binaries. .Pp This is a default setting on -powerpc/powerpc, powerpc/powerpc64 and powerpc/powerpc64le. +powerpc/powerpc64 and powerpc/powerpc64le. .It Va WITH_LOADER_GELI Build GELI bootloader support. .Pp @@ -1048,7 +1048,7 @@ amd64/amd64, arm/armv7, arm64/aarch64, i386/i386 and riscv/riscv64. Do not build the 32-bit UEFI loader. .Pp This is a default setting on -arm/armv7, arm64/aarch64, i386/i386, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. +arm/armv7, arm64/aarch64, i386/i386, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. .It Va WITH_LOADER_IA32 Build the 32-bit UEFI loader. .Pp @@ -1058,7 +1058,7 @@ amd64/amd64. Do not build kboot, a linuxboot environment loader .Pp This is a default setting on -arm/armv7, i386/i386, powerpc/powerpc, powerpc/powerpc64le and riscv/riscv64. +arm/armv7, i386/i386, powerpc/powerpc64le and riscv/riscv64. .It Va WITH_LOADER_KBOOT Build kboot, a linuxboot environment loader .Pp @@ -1068,7 +1068,7 @@ amd64/amd64, arm64/aarch64 and powerpc/powerpc64. Do not build LUA bindings for the boot loader. .Pp This is a default setting on -powerpc/powerpc, powerpc/powerpc64 and powerpc/powerpc64le. +powerpc/powerpc64 and powerpc/powerpc64le. .It Va WITH_LOADER_LUA Build LUA bindings for the boot loader. .Pp @@ -1083,7 +1083,7 @@ amd64/amd64, arm/armv7, arm64/aarch64, i386/i386 and riscv/riscv64. Build openfirmware bootloader components. .Pp This is a default setting on -powerpc/powerpc, powerpc/powerpc64 and powerpc/powerpc64le. +powerpc/powerpc64 and powerpc/powerpc64le. .It Va WITHOUT_LOADER_PXEBOOT Do not build pxeboot on i386/amd64. When the pxeboot is too large, or unneeded, it may be disabled with this option. @@ -1104,7 +1104,7 @@ amd64/amd64, arm64/aarch64, i386/i386, powerpc/powerpc64le and riscv/riscv64. Build ubldr. .Pp This is a default setting on -arm/armv7, powerpc/powerpc and powerpc/powerpc64. +arm/armv7 and powerpc/powerpc64. .It Va WITH_LOADER_VERBOSE Build with extra verbose debugging in the loader. May explode already nearly too large loader over the limit. @@ -1309,7 +1309,7 @@ Do not build .Xr mlx5tool 8 .Pp This is a default setting on -arm/armv7, powerpc/powerpc and riscv/riscv64. +arm/armv7 and riscv/riscv64. .It Va WITH_MLX5TOOL Build .Xr mlx5tool 8 @@ -1401,7 +1401,7 @@ Build the InfiniBand software stack, including kernel modules and userspace libraries. .Pp This is a default setting on -amd64/amd64, arm64/aarch64, i386/i386, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. +amd64/amd64, arm64/aarch64, i386/i386, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64. .It Va WITH_OFED_EXTRA Build the non-essential components of the .Dq "OpenFabrics Enterprise Distribution" @@ -1412,7 +1412,7 @@ Enable building LDAP support for kerberos using an openldap client from ports. Do not build LLVM's OpenMP runtime. .Pp This is a default setting on -arm/armv7 and powerpc/powerpc. +arm/armv7. .It Va WITH_OPENMP Build LLVM's OpenMP runtime. .Pp @@ -1465,7 +1465,7 @@ is set explicitly) Do not include kernel TLS support in OpenSSL. .Pp This is a default setting on -arm/armv7, i386/i386, powerpc/powerpc and riscv/riscv64. +arm/armv7, i386/i386 and riscv/riscv64. .It Va WITH_OPENSSL_KTLS Include kernel TLS support in OpenSSL. .Pp @@ -1502,7 +1502,7 @@ Do not build dynamically linked binaries as Position-Independent Executable (PIE). .Pp This is a default setting on -arm/armv7, i386/i386 and powerpc/powerpc. +arm/armv7 and i386/i386. .It Va WITH_PIE Build dynamically linked binaries as Position-Independent Executable (PIE). diff --git a/share/man/man5/style.Makefile.5 b/share/man/man5/style.Makefile.5 index cc5d2f6bb28a..fe8754924575 100644 --- a/share/man/man5/style.Makefile.5 +++ b/share/man/man5/style.Makefile.5 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 2002-2003, 2023 David O'Brien <obrien@FreeBSD.org> .\" All rights reserved. .\" @@ -30,10 +33,7 @@ .Os .Sh NAME .Nm style.Makefile -.Nd -.Fx -.Pa Makefile -file style guide +.Nd FreeBSD Makefile style guide .Sh DESCRIPTION This file specifies the preferred style for makefiles in the .Fx diff --git a/share/man/man7/arch.7 b/share/man/man7/arch.7 index 91f6953370d9..fe4e8055a8b1 100644 --- a/share/man/man7/arch.7 +++ b/share/man/man7/arch.7 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 12, 2025 +.Dd July 14, 2025 .Dt ARCH 7 .Os .Sh NAME @@ -67,8 +67,7 @@ and should be avoided. .Pp On some architectures, e.g., -.Dv powerpc -and AIM variants of +AIM variants of .Dv powerpc64 , the kernel uses a separate address space. On other architectures, kernel and a user mode process share a @@ -88,9 +87,6 @@ release to support each architecture. .It aarch64 Ta 11.0 .It amd64 Ta 5.1 .It armv7 Ta 12.0 -.It i386 Ta 1.0 -.It powerpc Ta 6.0 -.It powerpcspe Ta 12.0 .It powerpc64 Ta 9.0 .It powerpc64le Ta 13.0 .It riscv64 Ta 12.0 @@ -104,6 +100,7 @@ Discontinued architectures are shown in the following table. .It armeb Ta 8.0 Ta 11.4 .It armv6 Ta 10.0 Ta 14.x .It ia64 Ta 5.0 Ta 10.4 +.It i386 Ta 1.0 Ta 14.x .It mips Ta 8.0 Ta 13.5 .It mipsel Ta 9.0 Ta 13.5 .It mipselhf Ta 12.0 Ta 13.5 @@ -114,6 +111,8 @@ Discontinued architectures are shown in the following table. .It mips64elhf Ta 12.0 Ta 13.5 .It mips64hf Ta 12.0 Ta 13.5 .It pc98 Ta 2.2 Ta 11.4 +.It powerpc Ta 6.0 Ta 14.x +.It powerpcspe Ta 12.0 Ta 14.x .It riscv64sf Ta 12.0 Ta 13.5 .It sparc64 Ta 5.0 Ta 12.4 .El diff --git a/share/man/man7/d.7 b/share/man/man7/d.7 index 30efb0249a77..f4686d98b1d1 100644 --- a/share/man/man7/d.7 +++ b/share/man/man7/d.7 @@ -3,7 +3,7 @@ .\" .\" Copyright (c) 2025 Mateusz Piotrowski <0mp@FreeBSD.org> .\" -.Dd July 14, 2025 +.Dd June 14, 2025 .Dt D 7 .Os .Sh NAME diff --git a/share/man/man7/tracing.7 b/share/man/man7/tracing.7 index f3e3a5bf98c4..7085bac78385 100644 --- a/share/man/man7/tracing.7 +++ b/share/man/man7/tracing.7 @@ -8,7 +8,7 @@ .Os .Sh NAME .Nm tracing -.Nd introduction to tracing and performance monitoring facilities on FreeBSD +.Nd introduction to FreeBSD tracing and performance monitoring .Sh DESCRIPTION .Fx features a large variety of tracing and performance monitoring facilities. diff --git a/share/man/man8/nanobsd.8 b/share/man/man8/nanobsd.8 index 2ba072541ada..838f9ddc9afa 100644 --- a/share/man/man8/nanobsd.8 +++ b/share/man/man8/nanobsd.8 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 2006 Daniel Gerzo <danger@FreeBSD.org> .\" All rights reserved. .\" @@ -22,13 +25,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 10, 2024 +.Dd July 14, 2025 .Dt NANOBSD 8 .Os .Sh NAME .Nm nanobsd.sh -.Nd utility used to create a FreeBSD system image suitable for embedded -applications +.Nd create an embedded FreeBSD system image .Sh SYNOPSIS .Nm .Op Fl BbfhIiKknqvWwX diff --git a/share/man/man9/vnode.9 b/share/man/man9/vnode.9 index 5dd087725e92..d17492668298 100644 --- a/share/man/man9/vnode.9 +++ b/share/man/man9/vnode.9 @@ -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 October 9, 2024 +.Dd July 15, 2025 .Dt VNODE 9 .Os .Sh NAME @@ -113,7 +113,7 @@ The function declarations and definitions are generated from .Pa sys/kern/vnode_if.src by the -.Pa sys/tools/vndoe_if.awk +.Pa sys/tools/vnode_if.awk script. The interfaces are documented in their respective manual pages like .Xr VOP_READ 9 diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index 313f40ad8e51..0f9f8242c5c2 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -299,6 +299,7 @@ nork [label="Norikatsu Shigemura\nnork@FreeBSD.org\n2009/06/09"] np [label="Navdeep Parhar\nnp@FreeBSD.org\n2009/06/05"] nwhitehorn [label="Nathan Whitehorn\nnwhitehorn@FreeBSD.org\n2008/07/03"] n_hibma [label="Nick Hibma\nn_hibma@FreeBSD.org\n1998/11/26"] +obiwac [label="Aymeric Wibo\nobiwac@FreeBSD.org\n2025/07/15"] obrien [label="David E. O'Brien\nobrien@FreeBSD.org\n1996/10/29"] oh [label="Oskar Holmlund\noh@FreeBSD.org\n2021/04/21"] olce [label="Olivier Certner\nolce@FreeBSD.org\n2023/12/01"] @@ -711,6 +712,8 @@ joerg -> schweikh jtl -> ngie jtl -> thj +jrm -> obiwac + julian -> glebius julian -> davidxu julian -> archie @@ -799,6 +802,8 @@ mav -> eugen mav -> freqlabs mav -> ram +mckusick -> obiwac + mdf -> gleb mdodd -> jake diff --git a/share/mk/bsd.subdir.mk b/share/mk/bsd.subdir.mk index cf19c9d66201..289e3d591c8c 100644 --- a/share/mk/bsd.subdir.mk +++ b/share/mk/bsd.subdir.mk @@ -76,13 +76,14 @@ obj: .PHONY .endif .if !defined(NEED_SUBDIR) +.if ${MK_DIRDEPS_BUILD} == "yes" +# ignore this +_SUBDIR: # .MAKE.DEPENDFILE==/dev/null is set by bsd.dep.mk to avoid reading # Makefile.depend -.if ${.MAKE.LEVEL} == 0 && ${MK_DIRDEPS_BUILD} == "yes" && !empty(SUBDIR) && \ - ${.MAKE.DEPENDFILE} != "/dev/null" +.if ${.MAKE.LEVEL} == 0 && !empty(SUBDIR) && ${.MAKE.DEPENDFILE} != "/dev/null" .include <meta.subdir.mk> -# ignore this -_SUBDIR: +.endif .endif .endif diff --git a/share/mk/local.sys.machine.mk b/share/mk/local.sys.machine.mk index 5e40dfe805f9..961362cb048a 100644 --- a/share/mk/local.sys.machine.mk +++ b/share/mk/local.sys.machine.mk @@ -7,9 +7,9 @@ TARGET_MACHINE_LIST?= amd64 arm arm64 i386 powerpc riscv MACHINE_ARCH_host?= ${_HOST_ARCH} MACHINE_ARCH_host32?= ${_HOST_ARCH32} -MACHINE_ARCH_LIST_arm?= armv7 ${EXTRA_ARCHES_arm} +MACHINE_ARCH_LIST_arm?= armv7 MACHINE_ARCH_LIST_arm64?= aarch64 -MACHINE_ARCH_LIST_powerpc?= powerpc powerpc64 powerpc64le ${EXTRA_ARCHES_powerpc} +MACHINE_ARCH_LIST_powerpc?= powerpc64 powerpc64le ${EXTRA_ARCHES_powerpc} MACHINE_ARCH_LIST_riscv?= riscv64 .for m in ${TARGET_MACHINE_LIST} diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 387e570f8518..ef43d3c939b2 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -143,6 +143,7 @@ __DEFAULT_YES_OPTIONS = \ MAIL \ MAILWRAPPER \ MAKE \ + MITKRB5 \ MLX5TOOL \ NETCAT \ NETGRAPH \ @@ -211,7 +212,6 @@ __DEFAULT_NO_OPTIONS = \ LOADER_VERIEXEC_PASS_MANIFEST \ LLVM_FULL_DEBUGINFO \ MALLOC_PRODUCTION \ - MITKRB5 \ OFED_EXTRA \ OPENLDAP \ REPRODUCIBLE_BUILD \ diff --git a/share/termcap/termcap b/share/termcap/termcap index 46b89d0b3ddf..44704653045d 100644 --- a/share/termcap/termcap +++ b/share/termcap/termcap @@ -4705,14 +4705,14 @@ xterm-termite|VTE-based terminal:\ :ti=\E[?1049h:ts=\E]2;:u6=\E[%i%d;%dR:u7=\E[6n:ue=\E[24m:\ :up=\E[A:us=\E[4m:ve=\E[?25h:vi=\E[?25l: -# Termcap for st terminal taken from the st-0.8 sources -st|simpleterm:\ +# Termcap for st terminal taken from the st-0.9.2 sources +st-mono|simpleterm monocolor:\ :am:hs:mi:ms:xn:\ :co#80:it#8:li#24:\ :AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\ :K1=\E[1~:K2=\EOu:K3=\E[5~:K4=\E[4~:K5=\E[6~:LE=\E[%dD:\ - :RI=\E[%dC:SF=\E[%dS:UP=\E[%dA:ae=\E(B:al=\E[L:as=\E(0:\ - :bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\ + :RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:UP=\E[%dA:ae=\E(B:al=\E[L:\ + :as=\E(0:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\ :cm=\E[%i%d;%dH:cr=\r:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:\ :dl=\E[M:do=\n:ec=\E[%dX:ei=\E[4l:fs=^G:ho=\E[H:im=\E[4h:\ :is=\E[4l\E>\E[?1034l:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\ @@ -4725,6 +4725,14 @@ st|simpleterm:\ :ue=\E[24m:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:\ :ve=\E[?12l\E[?25h:vi=\E[?25l:vs=\E[?25h: +st|simpleterm:\ + :Co#8:\ + :AB=\E[4%dm:AF=\E[3%dm:\ + :..Sb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m:\ + :..Sf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m:\ + :..sa=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m:\ + :tc=st-mono: + st-256color|simpleterm with 256 colors:\ :cc:\ :Co#256:pa#32767:\ @@ -4742,6 +4750,12 @@ st-meta-256color|simpleterm with meta key and 256 colors:\ :is=\E[4l\E>\E[?1034h:mm=\E[?1034h:mo=\E[?1034l:\ :rs=\E[4l\E>\E[?1034h:tc=st-256color: +st-bs|simpleterm with backspace as backspace:\ + :kD=\177:kb=^H:tc=st: + +st-bs-256color|simpleterm with backspace as backspace and 256colors:\ + :kD=\177:kb=^H:tc=st-256color: + # From version 0.13.3 xterm-kitty|KovId's TTY:\ diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h index dca0cf6bb2d5..17887919089c 100644 --- a/stand/common/bootstrap.h +++ b/stand/common/bootstrap.h @@ -372,6 +372,8 @@ extern struct arch_switch archsw; /* This must be provided by the MD code, but should it be in the archsw? */ void delay(int delay); +int setprint_delay(struct env_var *ev, int flags, const void *value); + /* common code to set currdev variable. */ int gen_setcurrdev(struct env_var *ev, int flags, const void *value); int mount_currdev(struct env_var *, int, const void *); diff --git a/stand/common/console.c b/stand/common/console.c index 82cb552b4ef2..65ab7ffad622 100644 --- a/stand/common/console.c +++ b/stand/common/console.c @@ -44,6 +44,8 @@ static int twiddle_set(struct env_var *ev, int flags, const void *value); #endif int module_verbose = MODULE_VERBOSE; +static uint32_t print_delay_usec = 0; + static int module_verbose_set(struct env_var *ev, int flags, const void *value) { @@ -66,6 +68,23 @@ module_verbose_set(struct env_var *ev, int flags, const void *value) } /* + * Hook to set the print delay + */ +int +setprint_delay(struct env_var *ev, int flags, const void *value) +{ + char *end; + int usec = strtol(value, &end, 10); + + if (*(char *)value == '\0' || *end != '\0') + return (EINVAL); + if (usec < 0) + return (EINVAL); + print_delay_usec = usec; + return (0); +} + +/* * Detect possible console(s) to use. If preferred console(s) have been * specified, mark them as active. Else, mark the first probed console * as active. Also create the console variable. @@ -178,6 +197,10 @@ putchar(int c) (C_PRESENTOUT | C_ACTIVEOUT)) consoles[cons]->c_out(c); } + + /* Pause after printing newline character if a print delay is set */ + if (print_delay_usec != 0 && c == '\n') + delay(print_delay_usec); } /* diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c index fc6b43ec7a40..964fa514cac5 100644 --- a/stand/common/dev_net.c +++ b/stand/common/dev_net.c @@ -66,10 +66,6 @@ #include "dev_net.h" #include "bootstrap.h" -#ifdef NETIF_DEBUG -int debug = 0; -#endif - static char *netdev_name; static int netdev_sock = -1; static int netdev_opens; @@ -143,11 +139,8 @@ net_open(struct open_file *f, ...) return (ENXIO); } netdev_name = strdup(devname); -#ifdef NETIF_DEBUG - if (debug) - printf("%s: netif_open() succeeded\n", - __func__); -#endif + DEBUG_PRINTF(1,("%s: netif_open() succeeded %#x\n", + __func__, rootip.s_addr)); } /* * If network params were not set by netif_open(), try to get @@ -200,10 +193,7 @@ net_close(struct open_file *f) { struct devdesc *dev; -#ifdef NETIF_DEBUG - if (debug) - printf("%s: opens=%d\n", __func__, netdev_opens); -#endif + DEBUG_PRINTF(1,("%s: opens=%d\n", __func__, netdev_opens)); dev = f->f_devdata; dev->d_opendata = NULL; @@ -216,10 +206,7 @@ net_cleanup(void) { if (netdev_sock >= 0) { -#ifdef NETIF_DEBUG - if (debug) - printf("%s: calling netif_close()\n", __func__); -#endif + DEBUG_PRINTF(1,("%s: calling netif_close()\n", __func__)); rootip.s_addr = 0; free(netdev_name); netif_close(netdev_sock); @@ -271,10 +258,7 @@ net_getparams(int sock) bootp(sock); if (myip.s_addr != 0) goto exit; -#ifdef NETIF_DEBUG - if (debug) - printf("%s: BOOTP failed, trying RARP/RPC...\n", __func__); -#endif + DEBUG_PRINTF(1,("%s: BOOTP failed, trying RARP/RPC...\n", __func__)); #endif /* @@ -292,10 +276,7 @@ net_getparams(int sock) printf("%s: bootparam/whoami RPC failed\n", __func__); return (EIO); } -#ifdef NETIF_DEBUG - if (debug) - printf("%s: client name: %s\n", __func__, hostname); -#endif + DEBUG_PRINTF(1,("%s: client name: %s\n", __func__, hostname)); /* * Ignore the gateway from whoami (unreliable). @@ -309,16 +290,12 @@ net_getparams(int sock) } if (smask) { netmask = smask; -#ifdef NETIF_DEBUG - if (debug) - printf("%s: subnet mask: %s\n", __func__, - intoa(netmask)); -#endif + DEBUG_PRINTF(1,("%s: subnet mask: %s\n", __func__, + intoa(netmask))); } -#ifdef NETIF_DEBUG - if (gateip.s_addr && debug) - printf("%s: net gateway: %s\n", __func__, inet_ntoa(gateip)); -#endif + if (gateip.s_addr) + DEBUG_PRINTF(1,("%s: net gateway: %s\n", __func__, + inet_ntoa(gateip))); /* Get the root server and pathname. */ if (bp_getfile(sock, "root", &rootip, rootpath)) { @@ -329,12 +306,10 @@ exit: if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) rootip.s_addr = rootaddr; -#ifdef NETIF_DEBUG - if (debug) { - printf("%s: server addr: %s\n", __func__, inet_ntoa(rootip)); - printf("%s: server path: %s\n", __func__, rootpath); - } -#endif + DEBUG_PRINTF(1,("%s: proto: %d\n", __func__, netproto)); + DEBUG_PRINTF(1,("%s: server addr: %s\n", __func__, inet_ntoa(rootip))); + DEBUG_PRINTF(1,("%s: server port: %d\n", __func__, rootport)); + DEBUG_PRINTF(1,("%s: server path: %s\n", __func__, rootpath)); return (0); } @@ -410,6 +385,8 @@ net_parse_rootpath(void) (void)strsep(&ptr, ":"); if (ptr != NULL) { addr = inet_addr(rootpath); + DEBUG_PRINTF(1,("rootpath=%s addr=%#x\n", + rootpath, addr)); bcopy(ptr, rootpath, strlen(ptr) + 1); } } else { diff --git a/stand/common/install.c b/stand/common/install.c index 249eca1648f3..d07c4c6fc620 100644 --- a/stand/common/install.c +++ b/stand/common/install.c @@ -137,7 +137,9 @@ read_metatags(int fd) } *p++ = '\0'; - if (strcmp(tag, "KERNEL") == 0) + if (strncmp(tag, "ENV_", 4) == 0) + setenv(&tag[4], val, 1); + else if (strcmp(tag, "KERNEL") == 0) error = setpath(&inst_kernel, val); else if (strcmp(tag, "MODULES") == 0) error = setmultipath(&inst_modules, val); diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf index 1834e3ba3b34..f0843f3e930b 100644 --- a/stand/defaults/loader.conf +++ b/stand/defaults/loader.conf @@ -95,6 +95,8 @@ audit_event_type="etc_security_audit_event" # Default is unset and disabled (no delay). #autoboot_delay="10" # Delay in seconds before autobooting, # -1 for no user interrupts, NO to disable +#print_delay="1000000" # Slow printing of loader messages, useful for + # debugging. Given in microseconds. #password="" # Prevent changes to boot options #bootlock_password="" # Prevent booting (see check-password.4th(8)) #geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5 index 021f68f2309e..dc1c8f7f44e0 100644 --- a/stand/defaults/loader.conf.5 +++ b/stand/defaults/loader.conf.5 @@ -21,7 +21,7 @@ .\" 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 June 5, 2025 +.Dd June 12, 2025 .Dt LOADER.CONF 5 .Os .Sh NAME @@ -116,6 +116,10 @@ option in this manner, .Va beastie_disable must be set to .Dq Li YES . +.It Ar print_delay +Add a delay in microseconds after printing each line. +Default +.Dq Li 0 . .It Ar boot_* See list in .Xr loader.efi 8 diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 3ef418d20df3..436676368447 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -1241,6 +1241,9 @@ main(int argc, CHAR16 *argv[]) #endif cons_probe(); + /* Set print_delay variable to have hooks in place. */ + env_setenv("print_delay", EV_VOLATILE, "", setprint_delay, env_nounset); + /* Set up currdev variable to have hooks in place. */ env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset); diff --git a/stand/fdt/fdt_loader_cmd.c b/stand/fdt/fdt_loader_cmd.c index 226812a5d2a6..161c2435c410 100644 --- a/stand/fdt/fdt_loader_cmd.c +++ b/stand/fdt/fdt_loader_cmd.c @@ -1240,13 +1240,6 @@ fdt_cmd_ls(int argc, char *argv[]) return (CMD_OK); } -static __inline int -isprint(int c) -{ - - return (c >= ' ' && c <= 0x7e); -} - static int fdt_isprint(const void *data, int len, int *count) { diff --git a/stand/i386/libi386/Makefile b/stand/i386/libi386/Makefile index 038557c6a826..7205d3a61988 100644 --- a/stand/i386/libi386/Makefile +++ b/stand/i386/libi386/Makefile @@ -7,6 +7,7 @@ SRCS+= bio.c SRCS+= biosacpi.c SRCS+= biosdisk.c SRCS+= biosmem.c +SRCS+= biosmemdisk.c SRCS+= biospci.c SRCS+= biospnp.c SRCS+= biossmap.c diff --git a/stand/i386/libi386/biosmemdisk.c b/stand/i386/libi386/biosmemdisk.c new file mode 100644 index 000000000000..208ae289950a --- /dev/null +++ b/stand/i386/libi386/biosmemdisk.c @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2020 Richard Russo <russor@ruka.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * Source of information: https://repo.or.cz/syslinux.git + * + * Implements the MEMDISK protocol from syslinux, found in doc/memdisk.txt + * (search MEMDISK info structure). Since we validate the pointer to the mBFT, a + * minimum version of 3.85 is needed. Note: All this could be done in the + * kernel, since we don't have hooks to use this inside the boot loader. The + * details of these structures can be found in memdisk/memdisk.inc (search + * for mBFT). + * + * The kernel could just grab the mBFT table, but instead relies on us finding + * it and setting the right env variables. + */ +#include <stand.h> +#include <machine/stdarg.h> +#include <bootstrap.h> +#include <btxv86.h> +#include "libi386.h" + +#include "platform/acfreebsd.h" +#include "acconfig.h" +#define ACPI_SYSTEM_XFACE +#include "actypes.h" +#include "actbl.h" + +struct memdisk_info { + uint32_t mdi_13h_hook_ptr; /* not included in mdi_length! */ + uint16_t mdi_length; + uint8_t mdi_minor; + uint8_t mdi_major; + uint32_t mdi_disk_ptr; + uint32_t mdi_disk_sectors; + uint32_t mdi_far_ptr_cmdline; + uint32_t mdi_old_int13h; + uint32_t mdi_old_int15h; + uint16_t mdi_dos_mem_before; + uint8_t mdi_boot_loader_id; + uint8_t mdi_sector_size; /* Code below assumes this is last */ +} __attribute__((packed)); + +struct safe_13h_hook { + char sh_jmp[3]; + char sh_id[8]; + char sh_vendor[8]; + uint16_t sh_next_offset; + uint16_t sh_next_segment; + uint32_t sh_flags; + uint32_t sh_mbft; +} __attribute__((packed)); + +/* + * Maximum length of INT 13 entries we'll chase. Real disks are on this list, + * potentially, so we may have to look through them to find the memdisk. + */ +#define MEMDISK_MAX 32 + +/* + * Scan for MEMDISK virtual block devices + */ +void +biosmemdisk_detect(void) +{ + char line[80], scratch[80]; + int hook = 0, count = 0, sector_size; + uint16_t segment, offset; + struct safe_13h_hook *probe; + ACPI_TABLE_HEADER *mbft; + uint8_t *cp, sum; + struct memdisk_info *mdi; + + /* + * Walk through the int13 handler linked list, looking for possible + * MEMDISKs. + * + * The max is arbitrary to ensure termination. + */ + offset = *(uint16_t *)PTOV(0x13 * 4); + segment = *(uint16_t *)PTOV(0x13 * 4 + 2); + while (hook < MEMDISK_MAX && !(segment == 0 && offset == 0)) { + /* + * Walk the linked list, making sure each node has the right + * signature and only looking at MEMDISK nodes. + */ + probe = (struct safe_13h_hook *)PTOV(segment * 16 + offset); + if (memcmp(probe->sh_id, "$INT13SF", sizeof(probe->sh_id)) != 0) { + printf("Found int 13h unsafe hook at %p (%x:%x)\n", + probe, segment, offset); + break; + } + if (memcmp(probe->sh_vendor, "MEMDISK ", sizeof(probe->sh_vendor)) != 0) + goto end_of_loop; + + /* + * If it is a memdisk, make sure the mBFT signature is correct + * and its checksum is right. + */ + mbft = (ACPI_TABLE_HEADER *)PTOV(probe->sh_mbft); + if (memcmp(mbft->Signature, "mBFT", sizeof(mbft->Signature)) != 0) + goto end_of_loop; + sum = 0; + cp = (uint8_t *)mbft; + for (int idx = 0; idx < mbft->Length; ++idx) + sum += *(cp + idx); + if (sum != 0) + goto end_of_loop; + + /* + * The memdisk info follows the ACPI_TABLE_HEADER in the mBFT + * section. If the sector size is present and non-zero use it + * otherwise assume 512. + */ + mdi = (struct memdisk_info *)PTOV(probe->sh_mbft + sizeof(*mbft)); + sector_size = 512; + if (mdi->mdi_length + sizeof(mdi->mdi_13h_hook_ptr) >= sizeof(*mdi) && + mdi->mdi_sector_size != 0) + sector_size = 1 << mdi->mdi_sector_size; + + printf("memdisk %d.%d disk at %#x (%d sectors = %d bytes)\n", + mdi->mdi_major, mdi->mdi_minor, mdi->mdi_disk_ptr, + mdi->mdi_disk_sectors, mdi->mdi_disk_sectors * sector_size); + + snprintf(line, sizeof(line), "hint.md.%d.physaddr", count); + snprintf(scratch, sizeof(scratch), "0x%08x", mdi->mdi_disk_ptr); + setenv(line, scratch, 1); + snprintf(line, sizeof(line), "hint.md.%d.len", count); + snprintf(scratch, sizeof(scratch), "%d", mdi->mdi_disk_sectors * sector_size); + setenv(line, scratch, 1); + count++; +end_of_loop: + hook++; + offset = probe->sh_next_offset; + segment = probe->sh_next_segment; + } +} diff --git a/stand/i386/libi386/libi386.h b/stand/i386/libi386/libi386.h index d456ef58d7c2..caf565dd0656 100644 --- a/stand/i386/libi386/libi386.h +++ b/stand/i386/libi386/libi386.h @@ -149,3 +149,5 @@ int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend, int add_smap); void pxe_enable(void *pxeinfo); + +void biosmemdisk_detect(void); diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c index a7dfb2dde762..fd95cf5243cf 100644 --- a/stand/i386/loader/main.c +++ b/stand/i386/loader/main.c @@ -251,6 +251,9 @@ main(void) initial_bootinfo->bi_extmem = bios_extmem / 1024; } + /* detect MEMDISK virtual disks */ + biosmemdisk_detect(); + /* detect SMBIOS for future reference */ smbios_detect(NULL); diff --git a/stand/libsa/bootp.c b/stand/libsa/bootp.c index d919bb59e843..ac37553c6d34 100644 --- a/stand/libsa/bootp.c +++ b/stand/libsa/bootp.c @@ -42,7 +42,6 @@ #include <string.h> -#define BOOTP_DEBUGxx #define SUPPORT_DHCP #define DHCP_ENV_NOVENDOR 1 /* do not parse vendor options */ @@ -130,10 +129,7 @@ bootp(int sock) } wbuf; struct bootp *rbootp; -#ifdef BOOTP_DEBUG - if (debug) - printf("bootp: socket=%d\n", sock); -#endif + DEBUG_PRINTF(1, ("bootp: socket=%d\n", sock)); if (!bot) bot = getsecs(); @@ -141,10 +137,7 @@ bootp(int sock) printf("bootp: bad socket. %d\n", sock); return; } -#ifdef BOOTP_DEBUG - if (debug) - printf("bootp: d=%lx\n", (long)d); -#endif + DEBUG_PRINTF(1, ("bootp: socktodesc=%lx\n", (long)d)); bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); @@ -225,31 +218,20 @@ bootp(int sock) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); -#ifdef BOOTP_DEBUG - if (debug) - printf("'native netmask' is %s\n", intoa(netmask)); -#endif + DEBUG_PRINTF(1, ("'native netmask' is %s\n", intoa(netmask))); } -#ifdef BOOTP_DEBUG - if (debug) - printf("mask: %s\n", intoa(netmask)); -#endif + DEBUG_PRINTF(1,("rootip: %s\n", inet_ntoa(rootip))); + DEBUG_PRINTF(1,("mask: %s\n", intoa(netmask))); /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { -#ifdef BOOTP_DEBUG - if (debug) - printf("need gateway for root ip\n"); -#endif + DEBUG_PRINTF(1,("need gateway for root ip\n")); } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { -#ifdef BOOTP_DEBUG - if (debug) - printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); -#endif + DEBUG_PRINTF(1,("gateway ip (%s) bad\n", inet_ntoa(gateip))); gateip.s_addr = 0; } @@ -264,18 +246,11 @@ bootpsend(struct iodesc *d, void *pkt, size_t len) { struct bootp *bp; -#ifdef BOOTP_DEBUG - if (debug) - printf("bootpsend: d=%lx called.\n", (long)d); -#endif - + DEBUG_PRINTF(1,("bootpsend: d=%lx called.\n", (long)d)); bp = pkt; bp->bp_secs = htons((u_short)(getsecs() - bot)); -#ifdef BOOTP_DEBUG - if (debug) - printf("bootpsend: calling sendudp\n"); -#endif + DEBUG_PRINTF(1,("bootpsend: calling sendudp\n")); return (sendudp(d, pkt, len)); } @@ -288,34 +263,22 @@ bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft, struct bootp *bp; void *ptr; -#ifdef BOOTP_DEBUG - if (debug) - printf("bootp_recvoffer: called\n"); -#endif + DEBUG_PRINTF(1,("bootp_recvoffer: called\n")); ptr = NULL; n = readudp(d, &ptr, (void **)&bp, tleft); if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE) goto bad; -#ifdef BOOTP_DEBUG - if (debug) - printf("bootprecv: checked. bp = %p, n = %zd\n", bp, n); -#endif + DEBUG_PRINTF(1,("bootprecv: checked. bp = %p, n = %zd\n", bp, n)); + if (bp->bp_xid != htonl(d->xid)) { -#ifdef BOOTP_DEBUG - if (debug) { - printf("bootprecv: expected xid 0x%lx, got 0x%x\n", - d->xid, ntohl(bp->bp_xid)); - } -#endif + DEBUG_PRINTF(1,("bootprecv: expected xid 0x%lx, got 0x%x\n", + d->xid, ntohl(bp->bp_xid))); goto bad; } -#ifdef BOOTP_DEBUG - if (debug) - printf("bootprecv: got one!\n"); -#endif + DEBUG_PRINTF(1,("bootprecv: got one!\n")); /* Suck out vendor info */ if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) { @@ -359,10 +322,7 @@ vend_rfc1048(u_char *cp, u_int len) u_char tag; const char *val; -#ifdef BOOTP_DEBUG - if (debug) - printf("vend_rfc1048 bootp info. len=%d\n", len); -#endif + DEBUG_PRINTF(1,("vend_rfc1048 bootp info. len=%d\n", len)); ep = cp + len; /* Step over magic cookie */ @@ -443,10 +403,8 @@ vend_cmu(u_char *cp) { struct cmu_vend *vp; -#ifdef BOOTP_DEBUG - if (debug) - printf("vend_cmu bootp info.\n"); -#endif + DEBUG_PRINTF(1,("vend_cmu bootp info.\n")); + vp = (struct cmu_vend *)cp; if (vp->v_smask.s_addr != 0) { diff --git a/stand/libsa/hexdump.c b/stand/libsa/hexdump.c index 83fd5e277f1b..cce6e323c2cb 100644 --- a/stand/libsa/hexdump.c +++ b/stand/libsa/hexdump.c @@ -61,7 +61,7 @@ hexdump(caddr_t region, size_t len) for (x = 0; x < 16; x++) { if ((line + x) < (region + len)) { c = *(uint8_t *)(line + x); - if ((c < ' ') || (c > '~')) /* !isprint(c) */ + if (!isprint(c)) c = '.'; emit("%c", c); } else { diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c index 64ebdf033f14..32d488de5cfb 100644 --- a/stand/libsa/pkgfs.c +++ b/stand/libsa/pkgfs.c @@ -31,12 +31,6 @@ #include <string.h> #include <zlib.h> -#ifdef PKGFS_DEBUG -#define DBG(x) printf x -#else -#define DBG(x) -#endif - static int pkg_open(const char *, struct open_file *); static int pkg_close(struct open_file *); static int pkg_read(struct open_file *, void *, size_t, size_t *); @@ -172,6 +166,9 @@ pkgfs_init(const char *pkgname, struct fs_ops *proto) exclusive_file_system = NULL; + DEBUG_PRINTF(0, ("%s(%s: '%s') -> %d (error=%d)\n", __func__, + proto->fs_name, pkgname, fd, errno)); + if (fd == -1) return (errno); @@ -239,7 +236,7 @@ pkg_open_follow(const char *fn, struct open_file *f, int lnks) if (strcmp(fn, tf->tf_hdr.ut_name) == 0) { f->f_fsdata = tf; tf->tf_fp = 0; /* Reset the file pointer. */ - DBG(("%s: found %s type %c\n", __func__, + DEBUG_PRINTF(1, ("%s: found %s type %c\n", __func__, fn, tf->tf_hdr.ut_typeflag[0])); if (tf->tf_hdr.ut_typeflag[0] == '2') { /* we have a symlink @@ -275,6 +272,7 @@ pkg_close(struct open_file *f) /* * Free up the cache if we read all of the file. */ + DEBUG_PRINTF(1, ("%s(%s)\n", __func__, tf->tf_hdr.ut_name)); if (tf->tf_fp == tf->tf_size && tf->tf_cachesz > 0) { free(tf->tf_cache); tf->tf_cachesz = 0; @@ -297,6 +295,8 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res) return (EBADF); } + DEBUG_PRINTF(4, ("%s(%s,%zd)\n", __func__, tf->tf_hdr.ut_name, size)); + if (tf->tf_cachesz == 0) cache_data(tf, 1); @@ -334,6 +334,8 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res) tf->tf_fp = fp; if (res != NULL) *res = size; + DEBUG_PRINTF(4, ("%s(%s) res=%zd\n", __func__, tf->tf_hdr.ut_name, + (ssize_t)(tf->tf_size - tf->tf_fp))); return ((sz == -1) ? errno : 0); } @@ -377,7 +379,7 @@ pkg_seek(struct open_file *f, off_t ofs, int whence) return (tf->tf_fp); } } - DBG(("%s: negative file seek (%jd)\n", __func__, + DEBUG_PRINTF(3, ("%s: negative file seek (%jd)\n", __func__, (intmax_t)delta)); errno = ESPIPE; return (-1); @@ -511,26 +513,28 @@ cache_data(struct tarfile *tf, int force) size_t sz; if (tf == NULL) { - DBG(("%s: no file to cache data for?\n", __func__)); + DEBUG_PRINTF(5, ("%s: no file to cache data for?\n", + __func__)); errno = EINVAL; return (-1); } pkg = tf->tf_pkg; if (pkg == NULL) { - DBG(("%s: no package associated with file?\n", __func__)); + DEBUG_PRINTF(5, ("%s: no package associated with file?\n", + __func__)); errno = EINVAL; return (-1); } if (tf->tf_cachesz > 0) { - DBG(("%s: data already cached\n", __func__)); + DEBUG_PRINTF(5, ("%s: data already cached\n", __func__)); errno = EINVAL; return (-1); } if (tf->tf_ofs != pkg->pkg_ofs) { - DBG(("%s: caching after force read of file %s?\n", + DEBUG_PRINTF(5, ("%s: caching after force read of file %s?\n", __func__, tf->tf_hdr.ut_name)); errno = EINVAL; return (-1); @@ -548,7 +552,8 @@ cache_data(struct tarfile *tf, int force) tf->tf_cache = malloc(sz); if (tf->tf_cache == NULL) { - DBG(("%s: could not allocate %d bytes\n", __func__, (int)sz)); + DEBUG_PRINTF(5, ("%s: could not allocate %d bytes\n", + __func__, (int)sz)); errno = ENOMEM; return (-1); } @@ -732,7 +737,7 @@ new_package(int fd, struct package **pp) } /* - * Done parsing the ZIP header. Spkgt the inflation engine. + * Done parsing the ZIP header. Start the inflation engine. */ error = inflateInit2(&pkg->pkg_zs, -15); if (error != Z_OK) diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h index e1188fb73a26..0e99d8778fa6 100644 --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -275,6 +275,11 @@ static __inline int ispunct(int c) (c >= '[' && c <= '`') || (c >= '{' && c <= '~'); } +static __inline int isprint(int c) +{ + return (c >= ' ') && (c <= '~'); +} + static __inline int toupper(int c) { return islower(c) ? c - 'a' + 'A' : c; @@ -558,4 +563,17 @@ void tslog_getbuf(void ** buf, size_t * len); __END_DECLS +/* define _DEBUG_LEVEL n or _DEBUG_LEVEL_VAR before include */ +#ifndef DEBUG_PRINTF +# if defined(_DEBUG_LEVEL) || defined(_DEBUG_LEVEL_VAR) +# ifndef _DEBUG_LEVEL_VAR +# define _DEBUG_LEVEL_VAR _debug +static int _debug = _DEBUG_LEVEL; +# endif +# define DEBUG_PRINTF(n, args) if (_DEBUG_LEVEL_VAR >= n) printf args +# else +# define DEBUG_PRINTF(n, args) +# endif +#endif + #endif /* STAND_H */ diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index c7dc72561eff..971d71d098d3 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -1106,7 +1106,8 @@ vdev_insert(vdev_t *top_vdev, vdev_t *vdev) } static int -vdev_from_nvlist(spa_t *spa, uint64_t top_guid, const nvlist_t *nvlist) +vdev_from_nvlist(spa_t *spa, uint64_t top_guid, uint64_t txg, + const nvlist_t *nvlist) { vdev_t *top_vdev, *vdev; nvlist_t **kids = NULL; @@ -1120,6 +1121,7 @@ vdev_from_nvlist(spa_t *spa, uint64_t top_guid, const nvlist_t *nvlist) return (rc); top_vdev->v_spa = spa; top_vdev->v_top = top_vdev; + top_vdev->v_txg = txg; vdev_insert(spa->spa_root_vdev, top_vdev); } @@ -1163,7 +1165,7 @@ done: static int vdev_init_from_label(spa_t *spa, const nvlist_t *nvlist) { - uint64_t pool_guid, top_guid; + uint64_t pool_guid, top_guid, txg; nvlist_t *vdevs; int rc; @@ -1171,13 +1173,15 @@ vdev_init_from_label(spa_t *spa, const nvlist_t *nvlist) NULL, &pool_guid, NULL) || nvlist_find(nvlist, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64, NULL, &top_guid, NULL) || + nvlist_find(nvlist, ZPOOL_CONFIG_POOL_TXG, DATA_TYPE_UINT64, + NULL, &txg, NULL) != 0 || nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST, NULL, &vdevs, NULL)) { printf("ZFS: can't find vdev details\n"); return (ENOENT); } - rc = vdev_from_nvlist(spa, top_guid, vdevs); + rc = vdev_from_nvlist(spa, top_guid, txg, vdevs); nvlist_destroy(vdevs); return (rc); } @@ -1267,6 +1271,21 @@ vdev_update_from_nvlist(uint64_t top_guid, const nvlist_t *nvlist) return (rc); } +/* + * Shall not be called on root vdev, that is not linked into zfs_vdevs. + * See comment in vdev_create(). + */ +static void +vdev_free(struct vdev *vdev) +{ + struct vdev *kid, *safe; + + STAILQ_FOREACH_SAFE(kid, &vdev->v_children, v_childlink, safe) + vdev_free(kid); + STAILQ_REMOVE(&zfs_vdevs, vdev, vdev, v_alllink); + free(vdev); +} + static int vdev_init_from_nvlist(spa_t *spa, const nvlist_t *nvlist) { @@ -1313,9 +1332,10 @@ vdev_init_from_nvlist(spa_t *spa, const nvlist_t *nvlist) vdev = vdev_find(guid); /* * Top level vdev is missing, create it. + * XXXGL: how can this happen? */ if (vdev == NULL) - rc = vdev_from_nvlist(spa, guid, kids[i]); + rc = vdev_from_nvlist(spa, guid, 0, kids[i]); else rc = vdev_update_from_nvlist(guid, kids[i]); if (rc != 0) @@ -2006,8 +2026,7 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, vdev_t *vdev; nvlist_t *nvl; uint64_t val; - uint64_t guid; - uint64_t pool_txg, pool_guid; + uint64_t guid, pool_guid, top_guid, txg; const char *pool_name; int rc, namelen; @@ -2063,7 +2082,9 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, } if (nvlist_find(nvl, ZPOOL_CONFIG_POOL_TXG, DATA_TYPE_UINT64, - NULL, &pool_txg, NULL) != 0 || + NULL, &txg, NULL) != 0 || + nvlist_find(nvl, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64, + NULL, &top_guid, NULL) != 0 || nvlist_find(nvl, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64, NULL, &pool_guid, NULL) != 0 || nvlist_find(nvl, ZPOOL_CONFIG_POOL_NAME, DATA_TYPE_STRING, @@ -2098,9 +2119,22 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, nvlist_destroy(nvl); return (ENOMEM); } + } else { + struct vdev *kid; + + STAILQ_FOREACH(kid, &spa->spa_root_vdev->v_children, + v_childlink) + if (kid->v_guid == top_guid && kid->v_txg < txg) { + printf("ZFS: pool %s vdev %s ignoring stale " + "label from txg 0x%jx, using 0x%jx@0x%jx\n", + spa->spa_name, kid->v_name, + kid->v_txg, guid, txg); + STAILQ_REMOVE(&spa->spa_root_vdev->v_children, + kid, vdev, v_childlink); + vdev_free(kid); + break; + } } - if (pool_txg > spa->spa_txg) - spa->spa_txg = pool_txg; /* * Get the vdev tree and create our in-core copy of it. diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index 51d6d5e36840..99565fbb69ca 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -54,10 +54,8 @@ #include <x86/apicreg.h> #include <x86/apicvar.h> -#ifdef SMP #include <machine/smp.h> #include <machine/vmparam.h> -#endif #include <contrib/dev/acpica/include/acpi.h> @@ -73,19 +71,13 @@ extern int acpi_resume_beep; extern int acpi_reset_video; extern int acpi_susp_bounce; -#ifdef SMP extern struct susppcb **susppcbs; static cpuset_t suspcpus; -#else -static struct susppcb **susppcbs; -#endif static void acpi_stop_beep(void *); -#ifdef SMP static int acpi_wakeup_ap(struct acpi_softc *, int); static void acpi_wakeup_cpus(struct acpi_softc *); -#endif #define ACPI_WAKEPT_PAGES 7 @@ -103,7 +95,6 @@ acpi_stop_beep(void *arg) timer_spkr_release(); } -#ifdef SMP static int acpi_wakeup_ap(struct acpi_softc *sc, int cpu) { @@ -177,7 +168,6 @@ acpi_wakeup_cpus(struct acpi_softc *sc) outb(CMOS_DATA, mpbiosreason); } } -#endif int acpi_sleep_machdep(struct acpi_softc *sc, int state) @@ -190,10 +180,8 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) if (sc->acpi_wakeaddr == 0ul) return (-1); /* couldn't alloc wake memory */ -#ifdef SMP suspcpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &suspcpus); -#endif if (acpi_resume_beep != 0) timer_spkr_acquire(); @@ -208,12 +196,10 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) pcb = &susppcbs[0]->sp_pcb; if (savectx(pcb)) { fpususpend(susppcbs[0]->sp_fpususpend); -#ifdef SMP if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) { device_printf(sc->acpi_dev, "Failed to suspend APs\n"); return (0); /* couldn't sleep */ } -#endif hw_ibrs_ibpb_active = 0; hw_ssb_active = 0; cpu_stdext_feature3 = 0; @@ -278,16 +264,12 @@ acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); lapic_xapic_mode(); -#ifdef SMP if (!CPU_EMPTY(&suspcpus)) acpi_wakeup_cpus(sc); -#endif } -#ifdef SMP if (!CPU_EMPTY(&suspcpus)) resume_cpus(suspcpus); -#endif /* * Re-read cpu_stdext_feature3, which was zeroed-out diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 6e51ebff298a..e98bae9eb6c5 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -49,12 +49,6 @@ #include <machine/specialreg.h> #include <x86/apicreg.h> -#ifdef SMP -#define LK lock ; -#else -#define LK -#endif - .text SUPERALIGN_TEXT /* End Of Interrupt to APIC */ @@ -163,7 +157,6 @@ IDTVEC(spuriousint) jmp doreti #endif -#ifdef SMP /* * Global address space TLB shootdown. */ @@ -270,5 +263,3 @@ IDTVEC(justreturn) INTR_HANDLER justreturn1 call as_lapic_eoi jmp doreti - -#endif /* SMP */ diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index a053f6c70af1..d7e954f573b0 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -136,7 +136,7 @@ ctx_switch_fpusave_done: movq %r15,TD_LOCK(%r13) /* Release the old thread */ sw1: leaq TD_MD_PCB(%r12),%r8 -#if defined(SCHED_ULE) && defined(SMP) +#if defined(SCHED_ULE) movq $blocked_lock, %rdx movq TD_LOCK(%r12),%rcx cmpq %rcx, %rdx @@ -492,7 +492,7 @@ ENTRY(resumectx) END(resumectx) /* Wait for the new thread to become unblocked */ -#if defined(SCHED_ULE) && defined(SMP) +#if defined(SCHED_ULE) sw1wait: 1: pause diff --git a/sys/amd64/amd64/exec_machdep.c b/sys/amd64/amd64/exec_machdep.c index da68289e2c83..6752b716deb5 100644 --- a/sys/amd64/amd64/exec_machdep.c +++ b/sys/amd64/amd64/exec_machdep.c @@ -59,9 +59,7 @@ #include <sys/reg.h> #include <sys/rwlock.h> #include <sys/signalvar.h> -#ifdef SMP #include <sys/smp.h> -#endif #include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/sysent.h> diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index f46462b39fa3..37c7056f649c 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -38,7 +38,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "opt_atpic.h" #include "opt_cpu.h" #include "opt_ddb.h" @@ -82,9 +81,7 @@ #include <sys/rwlock.h> #include <sys/sched.h> #include <sys/signalvar.h> -#ifdef SMP #include <sys/smp.h> -#endif #include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/sysent.h> @@ -132,9 +129,7 @@ #include <machine/tss.h> #include <x86/ucode.h> #include <x86/ifunc.h> -#ifdef SMP #include <machine/smp.h> -#endif #ifdef FDT #include <x86/fdt.h> #endif @@ -149,6 +144,10 @@ #include <isa/rtc.h> #include <x86/init.h> +#ifndef SMP +#error amd64 requires options SMP +#endif + /* Sanity check for __curthread() */ CTASSERT(offsetof(struct pcpu, pc_curthread) == 0); diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c index 413b7c74890e..851f2df0e6e1 100644 --- a/sys/amd64/amd64/mem.c +++ b/sys/amd64/amd64/mem.c @@ -105,8 +105,8 @@ memrw(struct cdev *dev, struct uio *uio, int flags) * PAGE_SIZE, the uiomove() call does not * access past the end of the direct map. */ - if (v >= DMAP_MIN_ADDRESS && - v < DMAP_MIN_ADDRESS + dmaplimit) { + if (v >= kva_layout.dmap_low && + v < kva_layout.dmap_high) { error = uiomove((void *)v, c, uio); break; } diff --git a/sys/amd64/amd64/minidump_machdep.c b/sys/amd64/amd64/minidump_machdep.c index 6d0917e16099..43bf81a991bf 100644 --- a/sys/amd64/amd64/minidump_machdep.c +++ b/sys/amd64/amd64/minidump_machdep.c @@ -186,7 +186,7 @@ cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) * tables, so care must be taken to read each entry only once. */ pmapsize = 0; - for (va = VM_MIN_KERNEL_ADDRESS; va < kva_end; ) { + for (va = kva_layout.km_low; va < kva_end; ) { /* * We always write a page, even if it is zero. Each * page written corresponds to 1GB of space @@ -279,9 +279,9 @@ cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) mdhdr.msgbufsize = mbp->msg_size; mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.pmapsize = pmapsize; - mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; - mdhdr.dmapbase = DMAP_MIN_ADDRESS; - mdhdr.dmapend = DMAP_MAX_ADDRESS; + mdhdr.kernbase = kva_layout.km_low; + mdhdr.dmapbase = kva_layout.dmap_low; + mdhdr.dmapend = kva_layout.dmap_high; mdhdr.dumpavailsize = round_page(sizeof(dump_avail)); dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, @@ -323,7 +323,7 @@ cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) /* Dump kernel page directory pages */ bzero(fakepd, sizeof(fakepd)); - for (va = VM_MIN_KERNEL_ADDRESS; va < kva_end; va += NBPDP) { + for (va = kva_layout.km_low; va < kva_end; va += NBPDP) { ii = pmap_pml4e_index(va); pml4 = (uint64_t *)PHYS_TO_DMAP(KPML4phys) + ii; pdp = (uint64_t *)PHYS_TO_DMAP(*pml4 & PG_FRAME); diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index c3e3a91b20ec..8df082f6c5dc 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -162,9 +162,7 @@ #include <machine/msan.h> #include <machine/pcb.h> #include <machine/specialreg.h> -#ifdef SMP #include <machine/smp.h> -#endif #include <machine/sysarch.h> #include <machine/tss.h> @@ -415,7 +413,7 @@ SYSCTL_INT(_machdep, OID_AUTO, nkpt, CTLFLAG_RD, &nkpt, 0, static int ndmpdp; vm_paddr_t dmaplimit; -vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS; +vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS_LA48; pt_entry_t pg_nx; static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, @@ -475,11 +473,56 @@ _Static_assert(DMPML4I + NDMPML4E <= KMSANSHADPML4I, "direct map overflow"); static pml4_entry_t *kernel_pml4; static u_int64_t DMPDphys; /* phys addr of direct mapped level 2 */ static u_int64_t DMPDPphys; /* phys addr of direct mapped level 3 */ +static u_int64_t DMPML4phys; /* ... level 4, for la57 */ static int ndmpdpphys; /* number of DMPDPphys pages */ vm_paddr_t kernphys; /* phys addr of start of bootstrap data */ vm_paddr_t KERNend; /* and the end */ +struct kva_layout_s kva_layout = { + .kva_min = KV4ADDR(PML4PML4I, 0, 0, 0), + .kva_max = KV4ADDR(NPML4EPG - 1, NPDPEPG - 1, + NPDEPG - 1, NPTEPG - 1), + .dmap_low = KV4ADDR(DMPML4I, 0, 0, 0), + .dmap_high = KV4ADDR(DMPML4I + NDMPML4E, 0, 0, 0), + .lm_low = KV4ADDR(LMSPML4I, 0, 0, 0), + .lm_high = KV4ADDR(LMEPML4I + 1, 0, 0, 0), + .km_low = KV4ADDR(KPML4BASE, 0, 0, 0), + .km_high = KV4ADDR(KPML4BASE + NKPML4E - 1, NPDPEPG - 1, + NPDEPG - 1, NPTEPG - 1), + .rec_pt = KV4ADDR(PML4PML4I, 0, 0, 0), + .kasan_shadow_low = KV4ADDR(KASANPML4I, 0, 0, 0), + .kasan_shadow_high = KV4ADDR(KASANPML4I + NKASANPML4E, 0, 0, 0), + .kmsan_shadow_low = KV4ADDR(KMSANSHADPML4I, 0, 0, 0), + .kmsan_shadow_high = KV4ADDR(KMSANSHADPML4I + NKMSANSHADPML4E, + 0, 0, 0), + .kmsan_origin_low = KV4ADDR(KMSANORIGPML4I, 0, 0, 0), + .kmsan_origin_high = KV4ADDR(KMSANORIGPML4I + NKMSANORIGPML4E, + 0, 0, 0), +}; + +struct kva_layout_s kva_layout_la57 = { + .kva_min = KV5ADDR(NPML5EPG / 2, 0, 0, 0, 0), /* == rec_pt */ + .kva_max = KV5ADDR(NPML5EPG - 1, NPML4EPG - 1, NPDPEPG - 1, + NPDEPG - 1, NPTEPG - 1), + .dmap_low = KV5ADDR(DMPML5I, 0, 0, 0, 0), + .dmap_high = KV5ADDR(DMPML5I + NDMPML5E, 0, 0, 0, 0), + .lm_low = KV5ADDR(LMSPML5I, 0, 0, 0, 0), + .lm_high = KV5ADDR(LMEPML5I + 1, 0, 0, 0, 0), + .km_low = KV4ADDR(KPML4BASE, 0, 0, 0), + .km_high = KV4ADDR(KPML4BASE + NKPML4E - 1, NPDPEPG - 1, + NPDEPG - 1, NPTEPG - 1), + .rec_pt = KV5ADDR(PML5PML5I, 0, 0, 0, 0), + .kasan_shadow_low = KV4ADDR(KASANPML4I, 0, 0, 0), + .kasan_shadow_high = KV4ADDR(KASANPML4I + NKASANPML4E, 0, 0, 0), + .kmsan_shadow_low = KV4ADDR(KMSANSHADPML4I, 0, 0, 0), + .kmsan_shadow_high = KV4ADDR(KMSANSHADPML4I + NKMSANSHADPML4E, + 0, 0, 0), + .kmsan_origin_low = KV4ADDR(KMSANORIGPML4I, 0, 0, 0), + .kmsan_origin_high = KV4ADDR(KMSANORIGPML4I + NKMSANORIGPML4E, + 0, 0, 0), +}; + /* * pmap_mapdev support pre initialization (i.e. console) */ @@ -549,8 +592,8 @@ static int pmap_flags = PMAP_PDE_SUPERPAGE; /* flags for x86 pmaps */ static vmem_t *large_vmem; static u_int lm_ents; -#define PMAP_ADDRESS_IN_LARGEMAP(va) ((va) >= LARGEMAP_MIN_ADDRESS && \ - (va) < LARGEMAP_MIN_ADDRESS + NBPML4 * (u_long)lm_ents) +#define PMAP_ADDRESS_IN_LARGEMAP(va) ((va) >= kva_layout.lm_low && \ + (va) < kva_layout.lm_high) int pmap_pcid_enabled = 1; SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, @@ -1722,7 +1765,7 @@ create_pagetables(vm_paddr_t *firstaddr) { pd_entry_t *pd_p; pdp_entry_t *pdp_p; - pml4_entry_t *p4_p; + pml4_entry_t *p4_p, *p4d_p; pml5_entry_t *p5_p; uint64_t DMPDkernphys; vm_paddr_t pax; @@ -1732,7 +1775,7 @@ create_pagetables(vm_paddr_t *firstaddr) vm_offset_t kasankernbase; int kasankpdpi, kasankpdi, nkasanpte; #endif - int i, j, ndm1g, nkpdpe, nkdmpde; + int i, j, ndm1g, nkpdpe, nkdmpde, ndmpml4phys; TSENTER(); /* Allocate page table pages for the direct map */ @@ -1740,15 +1783,30 @@ create_pagetables(vm_paddr_t *firstaddr) if (ndmpdp < 4) /* Minimum 4GB of dirmap */ ndmpdp = 4; ndmpdpphys = howmany(ndmpdp, NPDPEPG); - if (ndmpdpphys > NDMPML4E) { - /* - * Each NDMPML4E allows 512 GB, so limit to that, - * and then readjust ndmpdp and ndmpdpphys. - */ - printf("NDMPML4E limits system to %d GB\n", NDMPML4E * 512); - Maxmem = atop(NDMPML4E * NBPML4); - ndmpdpphys = NDMPML4E; - ndmpdp = NDMPML4E * NPDEPG; + if (la57) { + ndmpml4phys = howmany(ndmpdpphys, NPML4EPG); + if (ndmpml4phys > NDMPML5E) { + printf("NDMPML5E limits system to %ld GB\n", + (u_long)NDMPML5E * NBPML5 / 1024 / 1024 / 1024); + Maxmem = atop(NDMPML5E * NBPML5); + ndmpml4phys = NDMPML5E; + ndmpdpphys = ndmpml4phys * NPML4EPG; + ndmpdp = ndmpdpphys * NPDEPG; + } + DMPML4phys = allocpages(firstaddr, ndmpml4phys); + } else { + if (ndmpdpphys > NDMPML4E) { + /* + * Each NDMPML4E allows 512 GB, so limit to + * that, and then readjust ndmpdp and + * ndmpdpphys. + */ + printf("NDMPML4E limits system to %d GB\n", + NDMPML4E * 512); + Maxmem = atop(NDMPML4E * NBPML4); + ndmpdpphys = NDMPML4E; + ndmpdp = NDMPML4E * NPDEPG; + } } DMPDPphys = allocpages(firstaddr, ndmpdpphys); ndm1g = 0; @@ -1773,7 +1831,13 @@ create_pagetables(vm_paddr_t *firstaddr) dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT; /* Allocate pages. */ + if (la57) { + KPML5phys = allocpages(firstaddr, 1); + p5_p = (pml5_entry_t *)KPML5phys; + } KPML4phys = allocpages(firstaddr, 1); + p4_p = (pml4_entry_t *)KPML4phys; + KPDPphys = allocpages(firstaddr, NKPML4E); #ifdef KASAN KASANPDPphys = allocpages(firstaddr, NKASANPML4E); @@ -1893,6 +1957,16 @@ create_pagetables(vm_paddr_t *firstaddr) } /* + * Connect the Direct Map slots up to the PML4. + * pml5 entries for DMAP are handled below in global pml5 loop. + */ + p4d_p = la57 ? (pml4_entry_t *)DMPML4phys : &p4_p[DMPML4I]; + for (i = 0; i < ndmpdpphys; i++) { + p4d_p[i] = (DMPDPphys + ptoa(i)) | X86_PG_RW | X86_PG_V | + pg_nx; + } + + /* * Instead of using a 1G page for the memory containing the kernel, * use 2M pages with read-only and no-execute permissions. (If using 1G * pages, this will partially overwrite the PDPEs above.) @@ -1911,11 +1985,6 @@ create_pagetables(vm_paddr_t *firstaddr) } } - /* And recursively map PML4 to itself in order to get PTmap */ - p4_p = (pml4_entry_t *)KPML4phys; - p4_p[PML4PML4I] = KPML4phys; - p4_p[PML4PML4I] |= X86_PG_RW | X86_PG_V | pg_nx; - #ifdef KASAN /* Connect the KASAN shadow map slots up to the PML4. */ for (i = 0; i < NKASANPML4E; i++) { @@ -1938,25 +2007,15 @@ create_pagetables(vm_paddr_t *firstaddr) } #endif - /* Connect the Direct Map slots up to the PML4. */ - for (i = 0; i < ndmpdpphys; i++) { - p4_p[DMPML4I + i] = DMPDPphys + ptoa(i); - p4_p[DMPML4I + i] |= X86_PG_RW | X86_PG_V | pg_nx; - } - /* Connect the KVA slots up to the PML4 */ for (i = 0; i < NKPML4E; i++) { p4_p[KPML4BASE + i] = KPDPphys + ptoa(i); p4_p[KPML4BASE + i] |= X86_PG_RW | X86_PG_V; } - kernel_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys); - if (la57) { /* XXXKIB bootstrap KPML5phys page is lost */ - KPML5phys = allocpages(firstaddr, 1); - for (i = 0, p5_p = (pml5_entry_t *)KPML5phys; i < NPML5EPG; - i++) { + for (i = 0; i < NPML5EPG; i++) { if (i == PML5PML5I) { /* * Recursively map PML5 to itself in @@ -1964,6 +2023,10 @@ create_pagetables(vm_paddr_t *firstaddr) */ p5_p[i] = KPML5phys | X86_PG_RW | X86_PG_A | X86_PG_M | X86_PG_V | pg_nx; + } else if (i >= DMPML5I && i < DMPML5I + ndmpml4phys) { + /* Connect DMAP pml4 pages to PML5. */ + p5_p[i] = (DMPML4phys + ptoa(i - DMPML5I)) | + X86_PG_RW | X86_PG_V | pg_nx; } else if (i == pmap_pml5e_index(UPT_MAX_ADDRESS)) { p5_p[i] = KPML4phys | X86_PG_RW | X86_PG_A | X86_PG_M | X86_PG_V; @@ -1971,6 +2034,10 @@ create_pagetables(vm_paddr_t *firstaddr) p5_p[i] = 0; } } + } else { + /* Recursively map PML4 to itself in order to get PTmap */ + p4_p[PML4PML4I] = KPML4phys; + p4_p[PML4PML4I] |= X86_PG_RW | X86_PG_V | pg_nx; } TSEXIT(); } @@ -2024,7 +2091,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) */ virtual_avail = (vm_offset_t)KERNSTART + round_2mpage(KERNend - (vm_paddr_t)kernphys); - virtual_end = VM_MAX_KERNEL_ADDRESS; + virtual_end = kva_layout.km_high; /* * Enable PG_G global pages, then switch to the kernel page @@ -2046,9 +2113,13 @@ pmap_bootstrap(vm_paddr_t *firstaddr) * Initialize the kernel pmap (which is statically allocated). * Count bootstrap data as being resident in case any of this data is * later unmapped (using pmap_remove()) and freed. + * + * DMAP_TO_PHYS()/PHYS_TO_DMAP() are functional only after + * kva_layout is fixed. */ PMAP_LOCK_INIT(kernel_pmap); if (la57) { + kva_layout = kva_layout_la57; vtoptem = ((1ul << (NPTEPGSHIFT + NPDEPGSHIFT + NPDPEPGSHIFT + NPML4EPGSHIFT + NPML5EPGSHIFT)) - 1) << 3; PTmap = (vm_offset_t)P5Tmap; @@ -2059,6 +2130,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) kernel_pmap->pm_cr3 = KPML5phys; pmap_pt_page_count_adj(kernel_pmap, 1); /* top-level page */ } else { + kernel_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys); kernel_pmap->pm_pmltop = kernel_pml4; kernel_pmap->pm_cr3 = KPML4phys; } @@ -2420,6 +2492,8 @@ pmap_init(void) { struct pmap_preinit_mapping *ppim; vm_page_t m, mpte; + pml4_entry_t *pml4e; + unsigned long lm_max; int error, i, ret, skz63; /* L1TF, reserve page @0 unconditionally */ @@ -2545,10 +2619,15 @@ pmap_init(void) lm_ents = 8; TUNABLE_INT_FETCH("vm.pmap.large_map_pml4_entries", &lm_ents); - if (lm_ents > LMEPML4I - LMSPML4I + 1) - lm_ents = LMEPML4I - LMSPML4I + 1; + lm_max = (kva_layout.lm_high - kva_layout.lm_low) / NBPML4; + if (lm_ents > lm_max) { + printf( + "pmap: shrinking large map from requested %d slots to %ld slots\n", + lm_ents, lm_max); + lm_ents = lm_max; + } #ifdef KMSAN - if (lm_ents > KMSANORIGPML4I - LMSPML4I) { + if (!la57 && lm_ents > KMSANORIGPML4I - LMSPML4I) { printf( "pmap: shrinking large map for KMSAN (%d slots to %ld slots)\n", lm_ents, KMSANORIGPML4I - LMSPML4I); @@ -2559,18 +2638,27 @@ pmap_init(void) printf("pmap: large map %u PML4 slots (%lu GB)\n", lm_ents, (u_long)lm_ents * (NBPML4 / 1024 / 1024 / 1024)); if (lm_ents != 0) { - large_vmem = vmem_create("large", LARGEMAP_MIN_ADDRESS, + large_vmem = vmem_create("large", kva_layout.lm_low, (vmem_size_t)lm_ents * NBPML4, PAGE_SIZE, 0, M_WAITOK); if (large_vmem == NULL) { printf("pmap: cannot create large map\n"); lm_ents = 0; } + if (la57) { + for (i = 0; i < howmany((vm_offset_t)NBPML4 * + lm_ents, NBPML5); i++) { + m = pmap_large_map_getptp_unlocked(); + kernel_pmap->pm_pmltop[LMSPML5I + i] = X86_PG_V | + X86_PG_RW | X86_PG_A | X86_PG_M | + pg_nx | VM_PAGE_TO_PHYS(m); + } + } for (i = 0; i < lm_ents; i++) { m = pmap_large_map_getptp_unlocked(); - /* XXXKIB la57 */ - kernel_pml4[LMSPML4I + i] = X86_PG_V | - X86_PG_RW | X86_PG_A | X86_PG_M | pg_nx | - VM_PAGE_TO_PHYS(m); + pml4e = pmap_pml4e(kernel_pmap, kva_layout.lm_low + + (u_long)i * NBPML4); + *pml4e = X86_PG_V | X86_PG_RW | X86_PG_A | X86_PG_M | + pg_nx | VM_PAGE_TO_PHYS(m); } } } @@ -2975,7 +3063,6 @@ pmap_update_pde_invalidate(pmap_t pmap, vm_offset_t va, pd_entry_t newpde) * XXX TODO */ -#ifdef SMP /* * Interrupt the cpus that are executing in the guest context. * This will force the vcpu to exit and the cached EPT mappings @@ -3433,168 +3520,6 @@ pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde) } sched_unpin(); } -#else /* !SMP */ -/* - * Normal, non-SMP, invalidation functions. - */ -void -pmap_invalidate_page(pmap_t pmap, vm_offset_t va) -{ - struct invpcid_descr d; - struct pmap_pcid *pcidp; - uint64_t kcr3, ucr3; - uint32_t pcid; - - if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) { - pmap->pm_eptgen++; - return; - } - KASSERT(pmap->pm_type == PT_X86, - ("pmap_invalidate_range: unknown type %d", pmap->pm_type)); - - if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap)) { - invlpg(va); - if (pmap == PCPU_GET(curpmap) && pmap_pcid_enabled && - pmap->pm_ucr3 != PMAP_NO_CR3) { - critical_enter(); - pcid = pmap_get_pcid(pmap); - if (invpcid_works) { - d.pcid = pcid | PMAP_PCID_USER_PT; - d.pad = 0; - d.addr = va; - invpcid(&d, INVPCID_ADDR); - } else { - kcr3 = pmap->pm_cr3 | pcid | CR3_PCID_SAVE; - ucr3 = pmap->pm_ucr3 | pcid | - PMAP_PCID_USER_PT | CR3_PCID_SAVE; - pmap_pti_pcid_invlpg(ucr3, kcr3, va); - } - critical_exit(); - } - } else if (pmap_pcid_enabled) { - pcidp = zpcpu_get(pmap->pm_pcidp); - pcidp->pm_gen = 0; - } -} - -void -pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) -{ - struct invpcid_descr d; - struct pmap_pcid *pcidp; - vm_offset_t addr; - uint64_t kcr3, ucr3; - uint32_t pcid; - - if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) { - pmap->pm_eptgen++; - return; - } - KASSERT(pmap->pm_type == PT_X86, - ("pmap_invalidate_range: unknown type %d", pmap->pm_type)); - - if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap)) { - for (addr = sva; addr < eva; addr += PAGE_SIZE) - invlpg(addr); - if (pmap == PCPU_GET(curpmap) && pmap_pcid_enabled && - pmap->pm_ucr3 != PMAP_NO_CR3) { - critical_enter(); - pcid = pmap_get_pcid(pmap); - if (invpcid_works) { - d.pcid = pcid | PMAP_PCID_USER_PT; - d.pad = 0; - d.addr = sva; - for (; d.addr < eva; d.addr += PAGE_SIZE) - invpcid(&d, INVPCID_ADDR); - } else { - kcr3 = pmap->pm_cr3 | pcid | CR3_PCID_SAVE; - ucr3 = pmap->pm_ucr3 | pcid | - PMAP_PCID_USER_PT | CR3_PCID_SAVE; - pmap_pti_pcid_invlrng(ucr3, kcr3, sva, eva); - } - critical_exit(); - } - } else if (pmap_pcid_enabled) { - pcidp = zpcpu_get(pmap->pm_pcidp); - pcidp->pm_gen = 0; - } -} - -void -pmap_invalidate_all(pmap_t pmap) -{ - struct invpcid_descr d; - struct pmap_pcid *pcidp; - uint64_t kcr3, ucr3; - uint32_t pcid; - - if (pmap->pm_type == PT_RVI || pmap->pm_type == PT_EPT) { - pmap->pm_eptgen++; - return; - } - KASSERT(pmap->pm_type == PT_X86, - ("pmap_invalidate_all: unknown type %d", pmap->pm_type)); - - if (pmap == kernel_pmap) { - if (pmap_pcid_enabled && invpcid_works) { - bzero(&d, sizeof(d)); - invpcid(&d, INVPCID_CTXGLOB); - } else { - invltlb_glob(); - } - } else if (pmap == PCPU_GET(curpmap)) { - if (pmap_pcid_enabled) { - critical_enter(); - pcid = pmap_get_pcid(pmap); - if (invpcid_works) { - d.pcid = pcid; - d.pad = 0; - d.addr = 0; - invpcid(&d, INVPCID_CTX); - if (pmap->pm_ucr3 != PMAP_NO_CR3) { - d.pcid |= PMAP_PCID_USER_PT; - invpcid(&d, INVPCID_CTX); - } - } else { - kcr3 = pmap->pm_cr3 | pcid; - if (pmap->pm_ucr3 != PMAP_NO_CR3) { - ucr3 = pmap->pm_ucr3 | pcid | - PMAP_PCID_USER_PT; - pmap_pti_pcid_invalidate(ucr3, kcr3); - } else - load_cr3(kcr3); - } - critical_exit(); - } else { - invltlb(); - } - } else if (pmap_pcid_enabled) { - pcidp = zpcpu_get(pmap->pm_pcidp); - pcidp->pm_gen = 0; - } -} - -void -pmap_invalidate_cache(void) -{ - - wbinvd(); -} - -static void -pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde) -{ - struct pmap_pcid *pcidp; - - pmap_update_pde_store(pmap, pde, newpde); - if (pmap == kernel_pmap || pmap == PCPU_GET(curpmap)) - pmap_update_pde_invalidate(pmap, va, newpde); - else { - pcidp = zpcpu_get(pmap->pm_pcidp); - pcidp->pm_gen = 0; - } -} -#endif /* !SMP */ static void pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va, pd_entry_t pde) @@ -3899,7 +3824,7 @@ pmap_kextract(vm_offset_t va) pd_entry_t pde; vm_paddr_t pa; - if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { + if (va >= kva_layout.dmap_low && va < kva_layout.dmap_high) { pa = DMAP_TO_PHYS(va); } else if (PMAP_ADDRESS_IN_LARGEMAP(va)) { pa = pmap_large_map_kextract(va); @@ -4040,7 +3965,7 @@ pmap_qremove(vm_offset_t sva, int count) * enough to one of those pmap_enter() calls for it to * be caught up in a promotion. */ - KASSERT(va >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", va)); + KASSERT(va >= kva_layout.km_low, ("usermode va %lx", va)); KASSERT((*vtopde(va) & X86_PG_PS) == 0, ("pmap_qremove on promoted va %#lx", va)); @@ -4328,21 +4253,13 @@ void pmap_pinit_pml5(vm_page_t pml5pg) { pml5_entry_t *pm_pml5; + int i; pm_pml5 = (pml5_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pml5pg)); - - /* - * Add pml5 entry at top of KVA pointing to existing pml4 table, - * entering all existing kernel mappings into level 5 table. - */ - pm_pml5[pmap_pml5e_index(UPT_MAX_ADDRESS)] = KPML4phys | X86_PG_V | - X86_PG_RW | X86_PG_A | X86_PG_M; - - /* - * Install self-referential address mapping entry. - */ - pm_pml5[PML5PML5I] = VM_PAGE_TO_PHYS(pml5pg) | - X86_PG_RW | X86_PG_V | X86_PG_M | X86_PG_A; + for (i = 0; i < NPML5EPG / 2; i++) + pm_pml5[i] = 0; + for (; i < NPML5EPG; i++) + pm_pml5[i] = kernel_pmap->pm_pmltop[i]; } static void @@ -4899,8 +4816,8 @@ pmap_release(pmap_t pmap) m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_pmltop)); if (pmap_is_la57(pmap)) { - pmap->pm_pmltop[pmap_pml5e_index(UPT_MAX_ADDRESS)] = 0; - pmap->pm_pmltop[PML5PML5I] = 0; + for (i = NPML5EPG / 2; i < NPML5EPG; i++) + pmap->pm_pmltop[i] = 0; } else { for (i = 0; i < NKPML4E; i++) /* KVA */ pmap->pm_pmltop[KPML4BASE + i] = 0; @@ -4942,7 +4859,7 @@ pmap_release(pmap_t pmap) static int kvm_size(SYSCTL_HANDLER_ARGS) { - unsigned long ksize = VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS; + unsigned long ksize = kva_layout.km_high - kva_layout.km_low; return sysctl_handle_long(oidp, &ksize, 0, req); } @@ -4953,7 +4870,7 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG | CTLFLAG_RD | CTLFLAG_MPSAFE, static int kvm_free(SYSCTL_HANDLER_ARGS) { - unsigned long kfree = VM_MAX_KERNEL_ADDRESS - kernel_vm_end; + unsigned long kfree = kva_layout.km_high - kernel_vm_end; return sysctl_handle_long(oidp, &kfree, 0, req); } @@ -5031,7 +4948,7 @@ pmap_page_array_startup(long pages) vm_page_array_size = pages; - start = VM_MIN_KERNEL_ADDRESS; + start = kva_layout.km_low; end = start + pages * sizeof(struct vm_page); for (va = start; va < end; va += NBPDR) { pfn = first_page + (va - start) / sizeof(struct vm_page); @@ -6045,17 +5962,18 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, if (mpte == NULL) { /* * Invalidate the 2MB page mapping and return "failure" if the - * mapping was never accessed. + * mapping was never accessed and not wired. */ if ((oldpde & PG_A) == 0) { - KASSERT((oldpde & PG_W) == 0, - ("pmap_demote_pde: a wired mapping is missing PG_A")); - pmap_demote_pde_abort(pmap, va, pde, oldpde, lockp); - return (false); - } - - mpte = pmap_remove_pt_page(pmap, va); - if (mpte == NULL) { + if ((oldpde & PG_W) == 0) { + pmap_demote_pde_abort(pmap, va, pde, oldpde, + lockp); + return (false); + } + mpte = pmap_remove_pt_page(pmap, va); + /* Fill the PTP with PTEs that have PG_A cleared. */ + mpte->valid = 0; + } else if ((mpte = pmap_remove_pt_page(pmap, va)) == NULL) { KASSERT((oldpde & PG_W) == 0, ("pmap_demote_pde: page table page for a wired mapping is missing")); @@ -6067,8 +5985,8 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, * so the direct map region is the only part of the * kernel address space that must be handled here. */ - KASSERT(!in_kernel || (va >= DMAP_MIN_ADDRESS && - va < DMAP_MAX_ADDRESS), + KASSERT(!in_kernel || (va >= kva_layout.dmap_low && + va < kva_layout.dmap_high), ("pmap_demote_pde: No saved mpte for va %#lx", va)); /* @@ -6107,7 +6025,7 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, /* * If the PTP is not leftover from an earlier promotion or it does not * have PG_A set in every PTE, then fill it. The new PTEs will all - * have PG_A set. + * have PG_A set, unless this is a wired mapping with PG_A clear. */ if (!vm_page_all_valid(mpte)) pmap_fill_ptp(firstpte, newpte); @@ -7184,7 +7102,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, PG_RW = pmap_rw_bit(pmap); va = trunc_page(va); - KASSERT(va <= VM_MAX_KERNEL_ADDRESS, ("pmap_enter: toobig")); + KASSERT(va <= kva_layout.km_high, ("pmap_enter: toobig")); KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS, ("pmap_enter: invalid to pmap_enter page table pages (va: 0x%lx)", va)); @@ -7513,6 +7431,9 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, PG_RW = pmap_rw_bit(pmap); KASSERT((newpde & (pmap_modified_bit(pmap) | PG_RW)) != PG_RW, ("pmap_enter_pde: newpde is missing PG_M")); + KASSERT((flags & (PMAP_ENTER_NOREPLACE | PMAP_ENTER_NORECLAIM)) != + PMAP_ENTER_NORECLAIM, + ("pmap_enter_pde: flags is missing PMAP_ENTER_NOREPLACE")); PG_V = pmap_valid_bit(pmap); PMAP_LOCK_ASSERT(pmap, MA_OWNED); @@ -7641,6 +7562,14 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, if (!pmap_pv_insert_pde(pmap, va, newpde, flags, lockp)) { if (pdpg != NULL) pmap_abort_ptp(pmap, va, pdpg); + else { + KASSERT(va >= VM_MAXUSER_ADDRESS && + (*pde & (PG_PS | PG_V)) == PG_V, + ("pmap_enter_pde: invalid kernel PDE")); + mt = pmap_remove_pt_page(pmap, va); + KASSERT(mt != NULL, + ("pmap_enter_pde: missing kernel PTP")); + } if (uwptpg != NULL) { mt = pmap_remove_pt_page(pmap, va); KASSERT(mt == uwptpg, @@ -9550,7 +9479,7 @@ pmap_unmapdev(void *p, vm_size_t size) va = (vm_offset_t)p; /* If we gave a direct map region in pmap_mapdev, do nothing */ - if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) + if (va >= kva_layout.dmap_low && va < kva_layout.dmap_high) return; offset = va & PAGE_MASK; size = round_page(offset + size); @@ -9729,7 +9658,7 @@ pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot) int error; /* Only supported within the kernel map. */ - if (va < VM_MIN_KERNEL_ADDRESS) + if (va < kva_layout.km_low) return (EINVAL); PMAP_LOCK(kernel_pmap); @@ -9760,7 +9689,7 @@ pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, * Only supported on kernel virtual addresses, including the direct * map but excluding the recursive map. */ - if (base < DMAP_MIN_ADDRESS) + if (base < kva_layout.dmap_low) return (EINVAL); /* @@ -9783,7 +9712,7 @@ pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, pte_bits |= X86_PG_RW; } if ((prot & VM_PROT_EXECUTE) == 0 || - va < VM_MIN_KERNEL_ADDRESS) { + va < kva_layout.km_low) { pde_bits |= pg_nx; pte_bits |= pg_nx; } @@ -9879,7 +9808,7 @@ pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, pmap_pte_props(pdpe, pde_bits, pde_mask); changed = true; } - if (tmpva >= VM_MIN_KERNEL_ADDRESS && + if (tmpva >= kva_layout.km_low && (*pdpe & PG_PS_FRAME) < dmaplimit) { if (pa_start == pa_end) { /* Start physical address run. */ @@ -9909,7 +9838,7 @@ pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, pmap_pte_props(pde, pde_bits, pde_mask); changed = true; } - if (tmpva >= VM_MIN_KERNEL_ADDRESS && + if (tmpva >= kva_layout.km_low && (*pde & PG_PS_FRAME) < dmaplimit) { if (pa_start == pa_end) { /* Start physical address run. */ @@ -9937,7 +9866,7 @@ pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, pmap_pte_props(pte, pte_bits, pte_mask); changed = true; } - if (tmpva >= VM_MIN_KERNEL_ADDRESS && + if (tmpva >= kva_layout.km_low && (*pte & PG_FRAME) < dmaplimit) { if (pa_start == pa_end) { /* Start physical address run. */ @@ -10285,17 +10214,9 @@ pmap_activate_sw(struct thread *td) return; } cpuid = PCPU_GET(cpuid); -#ifdef SMP CPU_SET_ATOMIC(cpuid, &pmap->pm_active); -#else - CPU_SET(cpuid, &pmap->pm_active); -#endif pmap_activate_sw_mode(td, pmap, cpuid); -#ifdef SMP CPU_CLR_ATOMIC(cpuid, &oldpmap->pm_active); -#else - CPU_CLR(cpuid, &oldpmap->pm_active); -#endif } void @@ -10336,11 +10257,7 @@ pmap_activate_boot(pmap_t pmap) MPASS(pmap != kernel_pmap); cpuid = PCPU_GET(cpuid); -#ifdef SMP CPU_SET_ATOMIC(cpuid, &pmap->pm_active); -#else - CPU_SET(cpuid, &pmap->pm_active); -#endif PCPU_SET(curpmap, pmap); if (pti) { kcr3 = pmap->pm_cr3; @@ -10704,19 +10621,28 @@ pmap_large_map_getptp(void) static pdp_entry_t * pmap_large_map_pdpe(vm_offset_t va) { + pml4_entry_t *pml4; vm_pindex_t pml4_idx; vm_paddr_t mphys; - pml4_idx = pmap_pml4e_index(va); - KASSERT(LMSPML4I <= pml4_idx && pml4_idx < LMSPML4I + lm_ents, - ("pmap_large_map_pdpe: va %#jx out of range idx %#jx LMSPML4I " - "%#jx lm_ents %d", - (uintmax_t)va, (uintmax_t)pml4_idx, LMSPML4I, lm_ents)); - KASSERT((kernel_pml4[pml4_idx] & X86_PG_V) != 0, - ("pmap_large_map_pdpe: invalid pml4 for va %#jx idx %#jx " - "LMSPML4I %#jx lm_ents %d", - (uintmax_t)va, (uintmax_t)pml4_idx, LMSPML4I, lm_ents)); - mphys = kernel_pml4[pml4_idx] & PG_FRAME; + KASSERT(va >= kva_layout.lm_low && va < kva_layout.lm_low + + (vm_offset_t)NBPML4 * lm_ents, ("va %#lx not in large map", va)); + if (la57) { + pml4 = pmap_pml4e(kernel_pmap, va); + mphys = *pml4 & PG_FRAME; + } else { + pml4_idx = pmap_pml4e_index(va); + + KASSERT(LMSPML4I <= pml4_idx && pml4_idx < LMSPML4I + lm_ents, + ("pmap_large_map_pdpe: va %#jx out of range idx %#jx " + "LMSPML4I %#jx lm_ents %d", + (uintmax_t)va, (uintmax_t)pml4_idx, LMSPML4I, lm_ents)); + KASSERT((kernel_pml4[pml4_idx] & X86_PG_V) != 0, + ("pmap_large_map_pdpe: invalid pml4 for va %#jx idx %#jx " + "LMSPML4I %#jx lm_ents %d", + (uintmax_t)va, (uintmax_t)pml4_idx, LMSPML4I, lm_ents)); + mphys = kernel_pml4[pml4_idx] & PG_FRAME; + } return ((pdp_entry_t *)PHYS_TO_DMAP(mphys) + pmap_pdpe_index(va)); } @@ -10909,8 +10835,8 @@ pmap_large_unmap(void *svaa, vm_size_t len) struct spglist spgf; sva = (vm_offset_t)svaa; - if (len == 0 || sva + len < sva || (sva >= DMAP_MIN_ADDRESS && - sva + len <= DMAP_MIN_ADDRESS + dmaplimit)) + if (len == 0 || sva + len < sva || (sva >= kva_layout.dmap_low && + sva + len < kva_layout.dmap_high)) return; SLIST_INIT(&spgf); @@ -11156,11 +11082,10 @@ pmap_large_map_wb(void *svap, vm_size_t len) sva = (vm_offset_t)svap; eva = sva + len; pmap_large_map_wb_fence(); - if (sva >= DMAP_MIN_ADDRESS && eva <= DMAP_MIN_ADDRESS + dmaplimit) { + if (sva >= kva_layout.dmap_low && eva < kva_layout.dmap_high) { pmap_large_map_flush_range(sva, len); } else { - KASSERT(sva >= LARGEMAP_MIN_ADDRESS && - eva <= LARGEMAP_MIN_ADDRESS + lm_ents * NBPML4, + KASSERT(sva >= kva_layout.lm_low && eva < kva_layout.lm_high, ("pmap_large_map_wb: not largemap %#lx %#lx", sva, len)); pmap_large_map_wb_large(sva, eva); } @@ -11201,8 +11126,8 @@ pmap_pti_init(void) VM_OBJECT_WLOCK(pti_obj); pml4_pg = pmap_pti_alloc_page(); pti_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pml4_pg)); - for (va = VM_MIN_KERNEL_ADDRESS; va <= VM_MAX_KERNEL_ADDRESS && - va >= VM_MIN_KERNEL_ADDRESS && va > NBPML4; va += NBPML4) { + for (va = kva_layout.km_low; va <= kva_layout.km_high && + va >= kva_layout.km_low && va > NBPML4; va += NBPML4) { pdpe = pmap_pti_pdpe(va); pmap_pti_wire_pte(pdpe); } @@ -11976,9 +11901,7 @@ sysctl_kmaps_dump(struct sbuf *sb, struct pmap_kernel_map_range *range, mode, range->pdpes, range->pdes, range->ptes); /* Reset to sentinel value. */ - range->sva = la57 ? KV5ADDR(NPML5EPG - 1, NPML4EPG - 1, NPDPEPG - 1, - NPDEPG - 1, NPTEPG - 1) : KV4ADDR(NPML4EPG - 1, NPDPEPG - 1, - NPDEPG - 1, NPTEPG - 1); + range->sva = kva_layout.kva_max; } /* @@ -12019,12 +11942,18 @@ sysctl_kmaps_reinit(struct pmap_kernel_map_range *range, vm_offset_t va, */ static void sysctl_kmaps_check(struct sbuf *sb, struct pmap_kernel_map_range *range, - vm_offset_t va, pml4_entry_t pml4e, pdp_entry_t pdpe, pd_entry_t pde, - pt_entry_t pte) + vm_offset_t va, pml5_entry_t pml5e, pml4_entry_t pml4e, pdp_entry_t pdpe, + pd_entry_t pde, pt_entry_t pte) { pt_entry_t attrs; - attrs = pml4e & (X86_PG_RW | X86_PG_U | pg_nx); + if (la57) { + attrs = pml5e & (X86_PG_RW | X86_PG_U | pg_nx); + attrs |= pml4e & pg_nx; + attrs &= pg_nx | (pml4e & (X86_PG_RW | X86_PG_U)); + } else { + attrs = pml4e & (X86_PG_RW | X86_PG_U | pg_nx); + } attrs |= pdpe & pg_nx; attrs &= pg_nx | (pdpe & (X86_PG_RW | X86_PG_U)); @@ -12057,13 +11986,15 @@ sysctl_kmaps(SYSCTL_HANDLER_ARGS) { struct pmap_kernel_map_range range; struct sbuf sbuf, *sb; + pml5_entry_t pml5e; pml4_entry_t pml4e; pdp_entry_t *pdp, pdpe; pd_entry_t *pd, pde; pt_entry_t *pt, pte; vm_offset_t sva; vm_paddr_t pa; - int error, i, j, k, l; + int error, j, k, l; + bool first; error = sysctl_wire_old_buffer(req, 0); if (error != 0) @@ -12072,9 +12003,8 @@ sysctl_kmaps(SYSCTL_HANDLER_ARGS) sbuf_new_for_sysctl(sb, NULL, PAGE_SIZE, req); /* Sentinel value. */ - range.sva = la57 ? KV5ADDR(NPML5EPG - 1, NPML4EPG - 1, NPDPEPG - 1, - NPDEPG - 1, NPTEPG - 1) : KV4ADDR(NPML4EPG - 1, NPDPEPG - 1, - NPDEPG - 1, NPTEPG - 1); + range.sva = kva_layout.kva_max; + pml5e = 0; /* no UB for la48 */ /* * Iterate over the kernel page tables without holding the kernel pmap @@ -12083,41 +12013,50 @@ sysctl_kmaps(SYSCTL_HANDLER_ARGS) * Within the large map, ensure that PDP and PD page addresses are * valid before descending. */ - for (sva = 0, i = pmap_pml4e_index(sva); i < NPML4EPG; i++) { - switch (i) { - case PML4PML4I: + for (first = true, sva = 0; sva != 0 || first; first = false) { + if (sva == kva_layout.rec_pt) sbuf_printf(sb, "\nRecursive map:\n"); - break; - case DMPML4I: + else if (sva == kva_layout.dmap_low) sbuf_printf(sb, "\nDirect map:\n"); - break; #ifdef KASAN - case KASANPML4I: + else if (sva == kva_layout.kasan_shadow_low) sbuf_printf(sb, "\nKASAN shadow map:\n"); - break; #endif #ifdef KMSAN - case KMSANSHADPML4I: + else if (sva == kva_layout.kmsan_shadow_low) sbuf_printf(sb, "\nKMSAN shadow map:\n"); - break; - case KMSANORIGPML4I: + else if (sva == kva_layout.kmsan_origin_low) sbuf_printf(sb, "\nKMSAN origin map:\n"); - break; #endif - case KPML4BASE: + else if (sva == kva_layout.km_low) sbuf_printf(sb, "\nKernel map:\n"); - break; - case LMSPML4I: + else if (sva == kva_layout.lm_low) sbuf_printf(sb, "\nLarge map:\n"); - break; - } /* Convert to canonical form. */ - if (sva == 1ul << 47) - sva |= -1ul << 48; + if (la57) { + if (sva == 1ul << 56) { + sva |= -1ul << 57; + continue; + } + } else { + if (sva == 1ul << 47) { + sva |= -1ul << 48; + continue; + } + } restart: - pml4e = kernel_pml4[i]; + if (la57) { + pml5e = *pmap_pml5e(kernel_pmap, sva); + if ((pml5e & X86_PG_V) == 0) { + sva = rounddown2(sva, NBPML5); + sysctl_kmaps_dump(sb, &range, sva); + sva += NBPML5; + continue; + } + } + pml4e = *pmap_pml4e(kernel_pmap, sva); if ((pml4e & X86_PG_V) == 0) { sva = rounddown2(sva, NBPML4); sysctl_kmaps_dump(sb, &range, sva); @@ -12138,8 +12077,8 @@ restart: pa = pdpe & PG_FRAME; if ((pdpe & PG_PS) != 0) { sva = rounddown2(sva, NBPDP); - sysctl_kmaps_check(sb, &range, sva, pml4e, pdpe, - 0, 0); + sysctl_kmaps_check(sb, &range, sva, pml5e, + pml4e, pdpe, 0, 0); range.pdpes++; sva += NBPDP; continue; @@ -12151,6 +12090,7 @@ restart: * freed. Validate the next-level address * before descending. */ + sva += NBPDP; goto restart; } pd = (pd_entry_t *)PHYS_TO_DMAP(pa); @@ -12167,7 +12107,7 @@ restart: if ((pde & PG_PS) != 0) { sva = rounddown2(sva, NBPDR); sysctl_kmaps_check(sb, &range, sva, - pml4e, pdpe, pde, 0); + pml5e, pml4e, pdpe, pde, 0); range.pdes++; sva += NBPDR; continue; @@ -12179,6 +12119,7 @@ restart: * may be freed. Validate the * next-level address before descending. */ + sva += NBPDR; goto restart; } pt = (pt_entry_t *)PHYS_TO_DMAP(pa); @@ -12192,7 +12133,7 @@ restart: continue; } sysctl_kmaps_check(sb, &range, sva, - pml4e, pdpe, pde, pte); + pml5e, pml4e, pdpe, pde, pte); range.ptes++; } } diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index c95696bbe7ef..870cd255abb7 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -934,10 +934,7 @@ ENTRY(casueword32_nosmap) ja fusufault movl %esi,%eax /* old */ -#ifdef SMP - lock -#endif - cmpxchgl %ecx,(%rdi) /* new = %ecx */ + lock cmpxchgl %ecx,(%rdi) /* new = %ecx */ setne %cl /* @@ -971,10 +968,7 @@ ENTRY(casueword32_smap) movl %esi,%eax /* old */ stac -#ifdef SMP - lock -#endif - cmpxchgl %ecx,(%rdi) /* new = %ecx */ + lock cmpxchgl %ecx,(%rdi) /* new = %ecx */ clac setne %cl @@ -1014,10 +1008,7 @@ ENTRY(casueword_nosmap) ja fusufault movq %rsi,%rax /* old */ -#ifdef SMP - lock -#endif - cmpxchgq %rcx,(%rdi) /* new = %rcx */ + lock cmpxchgq %rcx,(%rdi) /* new = %rcx */ setne %cl /* @@ -1045,10 +1036,7 @@ ENTRY(casueword_smap) movq %rsi,%rax /* old */ stac -#ifdef SMP - lock -#endif - cmpxchgq %rcx,(%rdi) /* new = %rcx */ + lock cmpxchgq %rcx,(%rdi) /* new = %rcx */ clac setne %cl diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 09ac0a67dbef..f3469ed5e2bc 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -37,7 +37,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* * AMD64 Trap and System call handling */ @@ -87,9 +86,7 @@ PMC_SOFT_DEFINE( , , page_fault, write); #include <x86/mca.h> #include <machine/md_var.h> #include <machine/pcb.h> -#ifdef SMP #include <machine/smp.h> -#endif #include <machine/stack.h> #include <machine/trap.h> #include <machine/tss.h> @@ -769,7 +766,7 @@ trap_pfault(struct trapframe *frame, bool usermode, int *signo, int *ucode) return (-1); } } - if (eva >= VM_MIN_KERNEL_ADDRESS) { + if (eva >= kva_layout.km_low) { /* * Don't allow user-mode faults in kernel address space. */ @@ -900,11 +897,9 @@ trap_diag(struct trapframe *frame, vm_offset_t eva) printf("\n\nFatal trap %d: %s while in %s mode\n", type, type < nitems(trap_msg) ? trap_msg[type] : UNKNOWN, TRAPF_USERMODE(frame) ? "user" : "kernel"); -#ifdef SMP - /* two separate prints in case of a trap on an unmapped page */ - printf("cpuid = %d; ", PCPU_GET(cpuid)); - printf("apic id = %02x\n", PCPU_GET(apic_id)); -#endif + /* Print these separately in case pcpu accesses trap. */ + printf("cpuid = %d; apic id = %02x\n", PCPU_GET(cpuid), + PCPU_GET(apic_id)); if (type == T_PAGEFLT) { printf("fault virtual address = 0x%lx\n", eva); printf("fault code = %s %s %s%s%s, %s\n", @@ -1025,11 +1020,9 @@ dblfault_handler(struct trapframe *frame) frame->tf_cs, frame->tf_ss, frame->tf_ds, frame->tf_es, frame->tf_fs, frame->tf_gs, rdmsr(MSR_FSBASE), rdmsr(MSR_GSBASE), rdmsr(MSR_KGSBASE)); -#ifdef SMP - /* two separate prints in case of a trap on an unmapped page */ - printf("cpuid = %d; ", PCPU_GET(cpuid)); - printf("apic id = %02x\n", PCPU_GET(apic_id)); -#endif + /* Print these separately in case pcpu accesses trap. */ + printf("cpuid = %d; apic id = %02x\n", PCPU_GET(cpuid), + PCPU_GET(apic_id)); panic("double fault"); } diff --git a/sys/amd64/conf/MINIMALUP b/sys/amd64/conf/MINIMALUP deleted file mode 100644 index 0dbddbe5b341..000000000000 --- a/sys/amd64/conf/MINIMALUP +++ /dev/null @@ -1,4 +0,0 @@ -include MINIMAL -ident MINIMALUP -nooptions SMP -nooptions NUMA diff --git a/sys/amd64/include/param.h b/sys/amd64/include/param.h index 8db314fa034d..5a9c3162e14c 100644 --- a/sys/amd64/include/param.h +++ b/sys/amd64/include/param.h @@ -146,11 +146,10 @@ #define amd64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define amd64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) -#define INKERNEL(va) (((va) >= DMAP_MIN_ADDRESS && (va) < DMAP_MAX_ADDRESS) \ - || ((va) >= VM_MIN_KERNEL_ADDRESS && (va) < VM_MAX_KERNEL_ADDRESS)) +#define INKERNEL(va) \ + (((va) >= kva_layout.dmap_low && (va) < kva_layout.dmap_high) || \ + ((va) >= kva_layout.km_low && (va) < kva_layout.km_high)) -#ifdef SMP #define SC_TABLESIZE 1024 /* Must be power of 2. */ -#endif #endif /* !_AMD64_INCLUDE_PARAM_H_ */ diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 7d3e91bcd9b9..e2f97442c10f 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -169,11 +169,12 @@ * the recursive page table map. */ #define NDMPML4E 8 +#define NDMPML5E 32 /* - * These values control the layout of virtual memory. The starting address - * of the direct map, which is controlled by DMPML4I, must be a multiple of - * its size. (See the PHYS_TO_DMAP() and DMAP_TO_PHYS() macros.) + * These values control the layout of virtual memory. The starting + * address of the direct map is controlled by DMPML4I on LA48 and + * DMPML5I on LA57. * * Note: KPML4I is the index of the (single) level 4 page that maps * the KVA that holds KERNBASE, while KPML4BASE is the index of the @@ -191,6 +192,7 @@ #define KPML4BASE (NPML4EPG-NKPML4E) /* KVM at highest addresses */ #define DMPML4I rounddown(KPML4BASE-NDMPML4E, NDMPML4E) /* Below KVM */ +#define DMPML5I (NPML5EPG / 2 + 1) #define KPML4I (NPML4EPG-1) #define KPDPI (NPDPEPG-2) /* kernbase at -2GB */ @@ -200,9 +202,14 @@ #define KMSANSHADPML4I (KPML4BASE - NKMSANSHADPML4E) #define KMSANORIGPML4I (DMPML4I - NKMSANORIGPML4E) -/* Large map: index of the first and max last pml4 entry */ +/* + * Large map: index of the first and max last pml4/la48 and pml5/la57 + * entry. + */ #define LMSPML4I (PML4PML4I + 1) #define LMEPML4I (KASANPML4I - 1) +#define LMSPML5I (DMPML5I + NDMPML5E) +#define LMEPML5I (LMSPML5I + 32 - 1) /* 32 slots for large map */ /* * XXX doesn't really belong here I guess... @@ -548,6 +555,25 @@ pmap_pml5e_index(vm_offset_t va) return ((va >> PML5SHIFT) & ((1ul << NPML5EPGSHIFT) - 1)); } +struct kva_layout_s { + vm_offset_t kva_min; + vm_offset_t kva_max; + vm_offset_t dmap_low; /* DMAP_MIN_ADDRESS */ + vm_offset_t dmap_high; /* DMAP_MAX_ADDRESS */ + vm_offset_t lm_low; /* LARGEMAP_MIN_ADDRESS */ + vm_offset_t lm_high; /* LARGEMAP_MAX_ADDRESS */ + vm_offset_t km_low; /* VM_MIN_KERNEL_ADDRESS */ + vm_offset_t km_high; /* VM_MAX_KERNEL_ADDRESS */ + vm_offset_t rec_pt; + vm_offset_t kasan_shadow_low; /* KASAN_MIN_ADDRESS */ + vm_offset_t kasan_shadow_high; /* KASAN_MAX_ADDRESS */ + vm_offset_t kmsan_shadow_low; /* KMSAN_SHAD_MIN_ADDRESS */ + vm_offset_t kmsan_shadow_high; /* KMSAN_SHAD_MAX_ADDRESS */ + vm_offset_t kmsan_origin_low; /* KMSAN_ORIG_MIN_ADDRESS */ + vm_offset_t kmsan_origin_high; /* KMSAN_ORIG_MAX_ADDRESS */ +}; +extern struct kva_layout_s kva_layout; + #endif /* !LOCORE */ #endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index 26eb227211da..bff92570ff82 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -13,8 +13,6 @@ #ifdef _KERNEL -#ifdef SMP - #ifndef LOCORE #include <x86/x86_smp.h> @@ -39,7 +37,6 @@ void invlop_handler(void); int start_all_aps(void); #endif /* !LOCORE */ -#endif /* SMP */ #endif /* _KERNEL */ #endif /* _MACHINE_SMP_H_ */ diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index a9c73b75213b..0b3daed4f69e 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -649,6 +649,8 @@ struct vm_inout_str { int addrsize; enum vm_reg_name seg_name; struct seg_desc seg_desc; + int cs_d; + uint64_t cs_base; }; enum task_switch_reason { diff --git a/sys/amd64/include/vmm_instruction_emul.h b/sys/amd64/include/vmm_instruction_emul.h index d5f0363cfb41..1fb0f97682a7 100644 --- a/sys/amd64/include/vmm_instruction_emul.h +++ b/sys/amd64/include/vmm_instruction_emul.h @@ -31,6 +31,31 @@ #include <sys/mman.h> +/* struct vie_op.op_type */ +enum { + VIE_OP_TYPE_NONE = 0, + VIE_OP_TYPE_MOV, + VIE_OP_TYPE_MOVSX, + VIE_OP_TYPE_MOVZX, + VIE_OP_TYPE_AND, + VIE_OP_TYPE_OR, + VIE_OP_TYPE_SUB, + VIE_OP_TYPE_TWO_BYTE, + VIE_OP_TYPE_PUSH, + VIE_OP_TYPE_CMP, + VIE_OP_TYPE_POP, + VIE_OP_TYPE_MOVS, + VIE_OP_TYPE_GROUP1, + VIE_OP_TYPE_STOS, + VIE_OP_TYPE_BITTEST, + VIE_OP_TYPE_TWOB_GRP15, + VIE_OP_TYPE_ADD, + VIE_OP_TYPE_TEST, + VIE_OP_TYPE_BEXTR, + VIE_OP_TYPE_OUTS, + VIE_OP_TYPE_LAST +}; + /* * Callback functions to read and write memory regions. */ diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h index 0cd9bb4fa7a4..d2ac3c6648b2 100644 --- a/sys/amd64/include/vmparam.h +++ b/sys/amd64/include/vmparam.h @@ -163,6 +163,7 @@ * Virtual addresses of things. Derived from the page directory and * page table indexes from pmap.h for precision. * + * LA48: * 0x0000000000000000 - 0x00007fffffffffff user map * 0x0000800000000000 - 0xffff7fffffffffff does not exist (hole) * 0xffff800000000000 - 0xffff804020100fff recursive page table (512GB slot) @@ -175,32 +176,38 @@ * 0xfffffc0000000000 - 0xfffffdffffffffff 2TB KMSAN shadow map, optional * 0xfffffe0000000000 - 0xffffffffffffffff 2TB kernel map * + * LA57: + * 0x0000000000000000 - 0x00ffffffffffffff user map + * 0x0100000000000000 - 0xf0ffffffffffffff does not exist (hole) + * 0xff00000000000000 - 0xff00ffffffffffff recursive page table (2048TB slot) + * 0xff01000000000000 - 0xff20ffffffffffff direct map (32 x 2048TB slots) + * 0xff21000000000000 - 0xff40ffffffffffff large map + * 0xff41000000000000 - 0xffff7fffffffffff unused + * 0xffff800000000000 - 0xfffff5ffffffffff unused (start of kernel pml4 entry) + * 0xfffff60000000000 - 0xfffff7ffffffffff 2TB KMSAN origin map, optional + * 0xfffff78000000000 - 0xfffff7bfffffffff 512GB KASAN shadow map, optional + * 0xfffff80000000000 - 0xfffffbffffffffff 4TB unused + * 0xfffffc0000000000 - 0xfffffdffffffffff 2TB KMSAN shadow map, optional + * 0xfffffe0000000000 - 0xffffffffffffffff 2TB kernel map + * * Within the kernel map: * * 0xfffffe0000000000 vm_page_array * 0xffffffff80000000 KERNBASE */ -#define VM_MIN_KERNEL_ADDRESS KV4ADDR(KPML4BASE, 0, 0, 0) -#define VM_MAX_KERNEL_ADDRESS KV4ADDR(KPML4BASE + NKPML4E - 1, \ - NPDPEPG-1, NPDEPG-1, NPTEPG-1) - -#define DMAP_MIN_ADDRESS KV4ADDR(DMPML4I, 0, 0, 0) -#define DMAP_MAX_ADDRESS KV4ADDR(DMPML4I + NDMPML4E, 0, 0, 0) - -#define KASAN_MIN_ADDRESS KV4ADDR(KASANPML4I, 0, 0, 0) -#define KASAN_MAX_ADDRESS KV4ADDR(KASANPML4I + NKASANPML4E, 0, 0, 0) +#define VM_MIN_KERNEL_ADDRESS_LA48 KV4ADDR(KPML4BASE, 0, 0, 0) +#define VM_MIN_KERNEL_ADDRESS kva_layout.km_low +#define VM_MAX_KERNEL_ADDRESS kva_layout.km_high -#define KMSAN_SHAD_MIN_ADDRESS KV4ADDR(KMSANSHADPML4I, 0, 0, 0) -#define KMSAN_SHAD_MAX_ADDRESS KV4ADDR(KMSANSHADPML4I + NKMSANSHADPML4E, \ - 0, 0, 0) +#define KASAN_MIN_ADDRESS (kva_layout.kasan_shadow_low) +#define KASAN_MAX_ADDRESS (kva_layout.kasan_shadow_high) -#define KMSAN_ORIG_MIN_ADDRESS KV4ADDR(KMSANORIGPML4I, 0, 0, 0) -#define KMSAN_ORIG_MAX_ADDRESS KV4ADDR(KMSANORIGPML4I + NKMSANORIGPML4E, \ - 0, 0, 0) +#define KMSAN_SHAD_MIN_ADDRESS (kva_layout.kmsan_shadow_low) +#define KMSAN_SHAD_MAX_ADDRESS (kva_layout.kmsan_shadow_high) -#define LARGEMAP_MIN_ADDRESS KV4ADDR(LMSPML4I, 0, 0, 0) -#define LARGEMAP_MAX_ADDRESS KV4ADDR(LMEPML4I + 1, 0, 0, 0) +#define KMSAN_ORIG_MIN_ADDRESS (kva_layout.kmsan_origin_low) +#define KMSAN_ORIG_MAX_ADDRESS (kva_layout.kmsan_origin_high) /* * Formally kernel mapping starts at KERNBASE, but kernel linker @@ -239,21 +246,21 @@ * vt fb startup needs to be reworked. */ #define PHYS_IN_DMAP(pa) (dmaplimit == 0 || (pa) < dmaplimit) -#define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ - (va) < (DMAP_MIN_ADDRESS + dmaplimit)) +#define VIRT_IN_DMAP(va) \ + ((va) >= kva_layout.dmap_low && (va) < kva_layout.dmap_low + dmaplimit) #define PMAP_HAS_DMAP 1 -#define PHYS_TO_DMAP(x) ({ \ +#define PHYS_TO_DMAP(x) __extension__ ({ \ KASSERT(PHYS_IN_DMAP(x), \ ("physical address %#jx not covered by the DMAP", \ (uintmax_t)x)); \ - (x) | DMAP_MIN_ADDRESS; }) + (x) + kva_layout.dmap_low; }) -#define DMAP_TO_PHYS(x) ({ \ +#define DMAP_TO_PHYS(x) __extension__ ({ \ KASSERT(VIRT_IN_DMAP(x), \ ("virtual address %#jx not covered by the DMAP", \ (uintmax_t)x)); \ - (x) & ~DMAP_MIN_ADDRESS; }) + (x) - kva_layout.dmap_low; }) /* * amd64 maps the page array into KVA so that it can be more easily @@ -274,7 +281,7 @@ */ #ifndef VM_KMEM_SIZE_MAX #define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \ - VM_MIN_KERNEL_ADDRESS + 1) * 3 / 5) + kva_layout.km_low + 1) * 3 / 5) #endif /* initial pagein size of beginning of executable file */ diff --git a/sys/amd64/pt/pt.c b/sys/amd64/pt/pt.c new file mode 100644 index 000000000000..c7b75767680a --- /dev/null +++ b/sys/amd64/pt/pt.c @@ -0,0 +1,978 @@ +/* + * Copyright (c) 2025 Bojan Novković <bnovkov@freebsd.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * hwt(4) Intel Processor Trace (PT) backend + * + * Driver Design Overview + * + * - Since PT is configured on a per-core basis, the driver uses + * 'smp_rendezvous' to start and disable tracing on each target core. + * - PT-specific resources are stored in a 'struct pt_ctx' context structure for + * each traced CPU core or thread. Upon initialization, a ToPA configuration + * is generated for each 'pt_ctx' structure using the HWT tracing buffers. + * The HWT tracing buffer is split into 4K ToPA entries. Currently, each + * 4K ToPA entry is configured to trigger an interrupt after it is filled. + * - The PT driver uses the XSAVE/XRSTOR PT extensions to load and save all + * relevant PT registers. Every time a traced thread is switched + * out or in, its state will be saved to or loaded from its corresponding + * 'pt_ctx' context. + * - When tracing starts, the PT hardware will start writing data into the + * tracing buffer. When a TOPA_INT entry is filled, it will trigger an + * interrupt before continuing. The interrupt handler will then fetch the + * last valid tracing buffer offset and enqueue a HWT_RECORD_BUFFER record. + * The driver is currently configured to use the NMI interrupt line. + * - The userspace PT backend waits for incoming HWT_RECORD_BUFFER records + * and uses the offsets to decode data from the tracing buffer. + * + * Future improvements and limitations + * + * - We currently configure the PT hardware to trigger an interrupt whenever + * a 4K ToPA entry is filled. While this is fine when tracing smaller + * functions or infrequent code paths, this will generate too much interrupt + * traffic when tracing hotter functions. A proper solution for this issue + * should estimate the amount of data generated by the current configuration + * and use it to determine interrupt frequency. + * + * - Support for more tracing options and PT features. + * + */ + +#include <sys/systm.h> +#include <sys/hwt.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/sdt.h> +#include <sys/smp.h> +#include <sys/taskqueue.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/atomic.h> +#include <machine/cpufunc.h> +#include <machine/fpu.h> +#include <machine/smp.h> +#include <machine/specialreg.h> + +#include <x86/apicvar.h> +#include <x86/x86_var.h> + +#include <dev/hwt/hwt_context.h> +#include <dev/hwt/hwt_vm.h> +#include <dev/hwt/hwt_backend.h> +#include <dev/hwt/hwt_config.h> +#include <dev/hwt/hwt_cpu.h> +#include <dev/hwt/hwt_record.h> +#include <dev/hwt/hwt_thread.h> + +#include <amd64/pt/pt.h> + +#ifdef PT_DEBUG +#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif +#define PT_SUPPORTED_FLAGS \ + (RTIT_CTL_MTCEN | RTIT_CTL_CR3FILTER | RTIT_CTL_DIS_TNT | \ + RTIT_CTL_USER | RTIT_CTL_OS | RTIT_CTL_BRANCHEN) +#define PT_XSAVE_MASK (XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE) +#define PT_XSTATE_BV (PT_XSAVE_MASK | XFEATURE_ENABLED_PT) +#define PT_MAX_IP_RANGES 2 + +#define PT_TOPA_MASK_PTRS 0x7f +#define PT_TOPA_PAGE_MASK 0xffffff80 +#define PT_TOPA_PAGE_SHIFT 7 + +#define CPUID_PT_LEAF 0x14 + +MALLOC_DEFINE(M_PT, "pt", "Intel Processor Trace"); + +SDT_PROVIDER_DEFINE(pt); +SDT_PROBE_DEFINE(pt, , , topa__intr); + +TASKQUEUE_FAST_DEFINE_THREAD(pt); + +static void pt_send_buffer_record(void *arg, int pending __unused); +static int pt_topa_intr(struct trapframe *tf); + +/* + * Intel Processor Trace XSAVE-managed state. + */ +struct pt_ext_area { + uint64_t rtit_ctl; + uint64_t rtit_output_base; + uint64_t rtit_output_mask_ptrs; + uint64_t rtit_status; + uint64_t rtit_cr3_match; + uint64_t rtit_addr0_a; + uint64_t rtit_addr0_b; + uint64_t rtit_addr1_a; + uint64_t rtit_addr1_b; +}; + +struct pt_buffer { + uint64_t *topa_hw; /* ToPA table entries. */ + size_t size; + struct mtx lock; /* Lock for fields below. */ + vm_offset_t offset; + uint64_t wrap_count; + int curpage; +}; + +struct pt_ctx { + int id; + struct pt_buffer buf; /* ToPA buffer metadata */ + struct task task; /* ToPA buffer notification task */ + struct hwt_context *hwt_ctx; + uint8_t *save_area; /* PT XSAVE area */ +}; +/* PT tracing contexts used for CPU mode. */ +static struct pt_ctx *pt_pcpu_ctx; + +enum pt_cpu_state { + PT_DISABLED = 0, + PT_STOPPED, + PT_ACTIVE +}; + +static struct pt_cpu { + struct pt_ctx *ctx; /* active PT tracing context */ + enum pt_cpu_state state; /* used as part of trace stop protocol */ +} *pt_pcpu; + +/* + * PT-related CPUID bits. + */ +static struct pt_cpu_info { + uint32_t l0_eax; + uint32_t l0_ebx; + uint32_t l0_ecx; + uint32_t l1_eax; + uint32_t l1_ebx; + size_t xsave_area_size; + size_t xstate_hdr_offset; + size_t pt_xsave_offset; +} pt_info __read_mostly; + +static bool initialized = false; +static int cpu_mode_ctr = 0; + +static __inline enum pt_cpu_state +pt_cpu_get_state(int cpu_id) +{ + return (atomic_load_int(&pt_pcpu[cpu_id].state)); +} + +static __inline void +pt_cpu_set_state(int cpu_id, enum pt_cpu_state state) +{ + atomic_store_int(&pt_pcpu[cpu_id].state, state); +} + +static __inline struct xstate_hdr * +pt_ctx_get_xstate_hdr(struct pt_ctx *ctx) +{ + return ((struct xstate_hdr *)(ctx->save_area + + pt_info.xstate_hdr_offset)); +} + + +static __inline struct pt_ext_area * +pt_ctx_get_ext_area(struct pt_ctx *ctx) +{ + return ((struct pt_ext_area *)(ctx->save_area + + pt_info.pt_xsave_offset)); +} + +/* + * Updates current trace buffer offset from the + * ToPA MSRs. Records if the trace buffer wrapped. + */ +static __inline void +pt_update_buffer(struct pt_buffer *buf) +{ + uint64_t reg; + int curpage; + + /* Update buffer offset. */ + reg = rdmsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS); + curpage = (reg & PT_TOPA_PAGE_MASK) >> PT_TOPA_PAGE_SHIFT; + mtx_lock_spin(&buf->lock); + /* Check if the output wrapped. */ + if (buf->curpage > curpage) + buf->wrap_count++; + buf->curpage = curpage; + buf->offset = reg >> 32; + mtx_unlock_spin(&buf->lock); + + dprintf("%s: wrap_cnt: %lu, curpage: %d, offset: %zu\n", __func__, + buf->wrap_count, buf->curpage, buf->offset); +} + +static __inline void +pt_fill_buffer_record(int id, struct pt_buffer *buf, + struct hwt_record_entry *rec) +{ + rec->record_type = HWT_RECORD_BUFFER; + rec->buf_id = id; + rec->curpage = buf->curpage; + rec->offset = buf->offset + (buf->wrap_count * buf->size); +} + +/* + * Enables or disables tracing on curcpu + * using the XSAVE/XRSTOR PT extensions. + */ +static void +pt_cpu_toggle_local(uint8_t *save_area, bool enable) +{ + u_long xcr0, cr0; + u_long xss; + + cr0 = rcr0(); + if (cr0 & CR0_TS) + clts(); + xcr0 = rxcr(XCR0); + if ((xcr0 & PT_XSAVE_MASK) != PT_XSAVE_MASK) + load_xcr(XCR0, xcr0 | PT_XSAVE_MASK); + xss = rdmsr(MSR_IA32_XSS); + wrmsr(MSR_IA32_XSS, xss | XFEATURE_ENABLED_PT); + + if (!enable) { + KASSERT((rdmsr(MSR_IA32_RTIT_CTL) & RTIT_CTL_TRACEEN) != 0, + ("%s: PT is disabled", __func__)); + xsaves(save_area, XFEATURE_ENABLED_PT); + } else { + KASSERT((rdmsr(MSR_IA32_RTIT_CTL) & RTIT_CTL_TRACEEN) == 0, + ("%s: PT is enabled", __func__)); + xrstors(save_area, XFEATURE_ENABLED_PT); + } + wrmsr(MSR_IA32_XSS, xss); + if ((xcr0 & PT_XSAVE_MASK) != PT_XSAVE_MASK) + load_xcr(XCR0, xcr0); + if (cr0 & CR0_TS) + load_cr0(cr0); +} + +/* + * Starts PT tracing on 'curcpu'. + */ +static void +pt_cpu_start(void *dummy) +{ + struct pt_cpu *cpu; + + cpu = &pt_pcpu[curcpu]; + MPASS(cpu->ctx != NULL); + + dprintf("%s: curcpu %d\n", __func__, curcpu); + load_cr4(rcr4() | CR4_XSAVE); + wrmsr(MSR_IA32_RTIT_STATUS, 0); + pt_cpu_set_state(curcpu, PT_ACTIVE); + pt_cpu_toggle_local(cpu->ctx->save_area, true); +} + +/* + * Stops PT tracing on 'curcpu'. + * Updates trace buffer offset to ensure + * any data generated between the last interrupt + * and the trace stop gets picked up by userspace. + */ +static void +pt_cpu_stop(void *dummy) +{ + struct pt_cpu *cpu; + struct pt_ctx *ctx; + + /* Shutdown may occur before PT gets properly configured. */ + if (pt_cpu_get_state(curcpu) == PT_DISABLED) + return; + + cpu = &pt_pcpu[curcpu]; + ctx = cpu->ctx; + MPASS(ctx != NULL); + dprintf("%s: curcpu %d\n", __func__, curcpu); + + pt_cpu_set_state(curcpu, PT_STOPPED); + pt_cpu_toggle_local(cpu->ctx->save_area, false); + pt_update_buffer(&ctx->buf); +} + +/* + * Prepares the Table of Physical Addresses (ToPA) metadata for 'pt_ctx'. + * The HWT trace buffer is split into 4K ToPA table entries and used + * as a circular buffer, meaning that the last ToPA entry points to + * the first ToPA entry. Each entry is configured to raise an + * interrupt after being filled. + */ +static int +pt_topa_prepare(struct pt_ctx *ctx, struct hwt_vm *vm) +{ + struct pt_buffer *buf; + size_t topa_size; + int i; + + topa_size = TOPA_SIZE_4K; + buf = &ctx->buf; + + KASSERT(buf->topa_hw == NULL, + ("%s: ToPA info already exists", __func__)); + buf->topa_hw = mallocarray(vm->npages + 1, sizeof(uint64_t), M_PT, + M_ZERO | M_WAITOK); + dprintf("%s: ToPA virt addr %p\n", __func__, buf->topa_hw); + buf->size = vm->npages * PAGE_SIZE; + for (i = 0; i < vm->npages; i++) { + buf->topa_hw[i] = VM_PAGE_TO_PHYS(vm->pages[i]) | topa_size; + /* + * XXX: TOPA_INT should ideally be set according to + * expected amount of incoming trace data. Too few TOPA_INT + * entries will not trigger interrupts often enough when tracing + * smaller functions. + */ + buf->topa_hw[i] |= TOPA_INT; + } + buf->topa_hw[vm->npages] = (uint64_t)vtophys(buf->topa_hw) | TOPA_END; + + return (0); +} + +/* + * Configures IP filtering for trace generation. + * A maximum of 2 ranges can be specified due to + * limitations imposed by the XSAVE/XRSTOR PT extensions. + */ +static int +pt_configure_ranges(struct pt_ctx *ctx, struct pt_cpu_config *cfg) +{ + struct pt_ext_area *pt_ext; + int nranges_supp, n, error = 0; + + pt_ext = pt_ctx_get_ext_area(ctx); + if (pt_info.l0_ebx & CPUPT_IPF) { + nranges_supp = (pt_info.l1_eax & CPUPT_NADDR_M) >> + CPUPT_NADDR_S; + + if (nranges_supp > PT_IP_FILTER_MAX_RANGES) + nranges_supp = PT_IP_FILTER_MAX_RANGES; + n = cfg->nranges; + if (n > nranges_supp) { + printf("%s: %d IP filtering ranges requested, CPU " + "supports %d, truncating\n", + __func__, n, nranges_supp); + n = nranges_supp; + } + + switch (n) { + case 2: + pt_ext->rtit_ctl |= (1UL << RTIT_CTL_ADDR_CFG_S(1)); + pt_ext->rtit_addr1_a = cfg->ip_ranges[1].start; + pt_ext->rtit_addr1_b = cfg->ip_ranges[1].end; + case 1: + pt_ext->rtit_ctl |= (1UL << RTIT_CTL_ADDR_CFG_S(0)); + pt_ext->rtit_addr0_a = cfg->ip_ranges[0].start; + pt_ext->rtit_addr0_b = cfg->ip_ranges[0].end; + break; + default: + error = (EINVAL); + break; + }; + } else + error = (ENXIO); + + return (error); +} + +static int +pt_init_ctx(struct pt_ctx *pt_ctx, struct hwt_vm *vm, int ctx_id) +{ + + dprintf("%s: ctx id %d\n", __func__, ctx_id); + + KASSERT(pt_ctx->buf.topa_hw == NULL, + ("%s: active ToPA buffer in context %p\n", __func__, pt_ctx)); + + memset(pt_ctx, 0, sizeof(struct pt_ctx)); + mtx_init(&pt_ctx->buf.lock, "pttopa", NULL, MTX_SPIN); + pt_ctx->save_area = malloc_aligned(pt_info.xsave_area_size, 64, + M_PT, M_NOWAIT | M_ZERO); + if (pt_ctx->save_area == NULL) + return (ENOMEM); + dprintf("%s: preparing ToPA buffer\n", __func__); + if (pt_topa_prepare(pt_ctx, vm) != 0) { + dprintf("%s: failed to prepare ToPA buffer\n", __func__); + free(pt_ctx->save_area, M_PT); + return (ENOMEM); + } + + pt_ctx->id = ctx_id; + TASK_INIT(&pt_ctx->task, 0, pt_send_buffer_record, pt_ctx); + + return (0); +} + +static void +pt_deinit_ctx(struct pt_ctx *pt_ctx) +{ + + if (pt_ctx->buf.topa_hw != NULL) + free(pt_ctx->buf.topa_hw, M_PT); + if (pt_ctx->save_area != NULL) + free(pt_ctx->save_area, M_PT); + memset(pt_ctx, 0, sizeof(*pt_ctx)); + pt_ctx->buf.topa_hw = NULL; +} + +/* + * HWT backend configuration method. + * + * Checks and translates the user-defined configuration to a + * set of PT tracing features. Uses the feature set to initialize + * the tracing context for the target CPU or thread. + */ +static int +pt_backend_configure(struct hwt_context *ctx, int cpu_id, int thread_id) +{ + struct hwt_cpu *hwt_cpu; + struct hwt_thread *thr; + struct pt_ctx *pt_ctx; + struct pt_cpu_config *cfg; + struct pt_ext_area *pt_ext; + struct xstate_hdr *hdr; + int error; + + dprintf("%s\n", __func__); + + cfg = (struct pt_cpu_config *)ctx->config; + pt_ctx = NULL; + + /* Clear any flags we don't support yet. */ + cfg->rtit_ctl &= PT_SUPPORTED_FLAGS; + if (cfg->rtit_ctl & RTIT_CTL_MTCEN) { + if ((pt_info.l0_ebx & CPUPT_MTC) == 0) { + printf("%s: CPU does not support generating MTC " + "packets\n", __func__); + return (ENXIO); + } + } + + if (cfg->rtit_ctl & RTIT_CTL_CR3FILTER) { + if ((pt_info.l0_ebx & CPUPT_CR3) == 0) { + printf("%s: CPU does not support CR3 filtering\n", + __func__); + return (ENXIO); + } + } + + if (cfg->rtit_ctl & RTIT_CTL_DIS_TNT) { + if ((pt_info.l0_ebx & CPUPT_DIS_TNT) == 0) { + printf("%s: CPU does not support TNT\n", __func__); + return (ENXIO); + } + } + /* TODO: support for more config bits. */ + + if (ctx->mode == HWT_MODE_CPU) { + TAILQ_FOREACH(hwt_cpu, &ctx->cpus, next) { + if (hwt_cpu->cpu_id != cpu_id) + continue; + pt_ctx = &pt_pcpu_ctx[cpu_id]; + break; + } + } else { + TAILQ_FOREACH(thr, &ctx->threads, next) { + if (thr->thread_id != thread_id) + continue; + KASSERT(thr->private != NULL, + ("%s: hwt thread private" + " not set, thr %p", + __func__, thr)); + pt_ctx = (struct pt_ctx *)thr->private; + break; + } + } + if (pt_ctx == NULL) + return (ENOENT); + + dprintf("%s: preparing MSRs\n", __func__); + pt_ext = pt_ctx_get_ext_area(pt_ctx); + hdr = pt_ctx_get_xstate_hdr(pt_ctx); + + pt_ext->rtit_ctl |= cfg->rtit_ctl; + if (cfg->nranges != 0) { + dprintf("%s: preparing IPF ranges\n", __func__); + if ((error = pt_configure_ranges(pt_ctx, cfg)) != 0) + return (error); + } + pt_ctx->hwt_ctx = ctx; + pt_ext->rtit_ctl |= RTIT_CTL_TOPA; + pt_ext->rtit_output_base = (uint64_t)vtophys(pt_ctx->buf.topa_hw); + pt_ext->rtit_output_mask_ptrs = PT_TOPA_MASK_PTRS; + hdr->xstate_bv = XFEATURE_ENABLED_PT; + hdr->xstate_xcomp_bv = XFEATURE_ENABLED_PT | + XSTATE_XCOMP_BV_COMPACT; + pt_ext->rtit_ctl |= RTIT_CTL_TRACEEN; + pt_pcpu[cpu_id].ctx = pt_ctx; + pt_cpu_set_state(cpu_id, PT_STOPPED); + + return (0); +} + +/* + * hwt backend trace start operation. CPU affine. + */ +static void +pt_backend_enable(struct hwt_context *ctx, int cpu_id) +{ + if (ctx->mode == HWT_MODE_CPU) + return; + + KASSERT(curcpu == cpu_id, + ("%s: attempting to start PT on another cpu", __func__)); + pt_cpu_start(NULL); + CPU_SET(cpu_id, &ctx->cpu_map); +} + +/* + * hwt backend trace stop operation. CPU affine. + */ +static void +pt_backend_disable(struct hwt_context *ctx, int cpu_id) +{ + struct pt_cpu *cpu; + + if (ctx->mode == HWT_MODE_CPU) + return; + + KASSERT(curcpu == cpu_id, + ("%s: attempting to disable PT on another cpu", __func__)); + pt_cpu_stop(NULL); + CPU_CLR(cpu_id, &ctx->cpu_map); + cpu = &pt_pcpu[cpu_id]; + cpu->ctx = NULL; +} + +/* + * hwt backend trace start operation for remote CPUs. + */ +static int +pt_backend_enable_smp(struct hwt_context *ctx) +{ + + dprintf("%s\n", __func__); + if (ctx->mode == HWT_MODE_CPU && + atomic_swap_32(&cpu_mode_ctr, 1) != 0) + return (-1); + + KASSERT(ctx->mode == HWT_MODE_CPU, + ("%s: should only be used for CPU mode", __func__)); + smp_rendezvous_cpus(ctx->cpu_map, NULL, pt_cpu_start, NULL, NULL); + + return (0); +} + +/* + * hwt backend trace stop operation for remote CPUs. + */ +static int +pt_backend_disable_smp(struct hwt_context *ctx) +{ + + dprintf("%s\n", __func__); + if (ctx->mode == HWT_MODE_CPU && + atomic_swap_32(&cpu_mode_ctr, 0) == 0) + return (-1); + + if (CPU_EMPTY(&ctx->cpu_map)) { + dprintf("%s: empty cpu map\n", __func__); + return (-1); + } + smp_rendezvous_cpus(ctx->cpu_map, NULL, pt_cpu_stop, NULL, NULL); + + return (0); +} + +/* + * HWT backend initialization method. + * + * Installs the ToPA interrupt handler and initializes + * the tracing contexts used for HWT_MODE_CPU. + */ +static int +pt_backend_init(struct hwt_context *ctx) +{ + struct hwt_cpu *hwt_cpu; + int error; + + dprintf("%s\n", __func__); + if (ctx->mode == HWT_MODE_CPU) { + TAILQ_FOREACH(hwt_cpu, &ctx->cpus, next) { + error = pt_init_ctx(&pt_pcpu_ctx[hwt_cpu->cpu_id], + hwt_cpu->vm, hwt_cpu->cpu_id); + if (error) + return (error); + } + } + + return (0); +} + +/* + * HWT backend teardown method. + * + * Removes the ToPA interrupt handler, stops tracing on all active CPUs, + * and releases all previously allocated ToPA metadata. + */ +static int +pt_backend_deinit(struct hwt_context *ctx) +{ + struct pt_ctx *pt_ctx; + struct hwt_thread *thr; + int cpu_id; + + dprintf("%s\n", __func__); + + pt_backend_disable_smp(ctx); + if (ctx->mode == HWT_MODE_THREAD) { + TAILQ_FOREACH(thr, &ctx->threads, next) { + KASSERT(thr->private != NULL, + ("%s: thr->private not set", __func__)); + pt_ctx = (struct pt_ctx *)thr->private; + pt_deinit_ctx(pt_ctx); + } + } else { + CPU_FOREACH(cpu_id) { + if (!CPU_ISSET(cpu_id, &ctx->cpu_map)) + continue; + if (pt_pcpu[cpu_id].ctx != NULL) { + KASSERT(pt_pcpu[cpu_id].ctx == + &pt_pcpu_ctx[cpu_id], + ("%s: CPU mode tracing with non-cpu mode PT" + "context active", + __func__)); + pt_pcpu[cpu_id].ctx = NULL; + } + pt_ctx = &pt_pcpu_ctx[cpu_id]; + pt_deinit_ctx(pt_ctx); + memset(&pt_pcpu[cpu_id], 0, sizeof(struct pt_cpu)); + } + } + + return (0); +} + +/* + * Fetches current offset into the tracing buffer. + */ +static int +pt_backend_read(struct hwt_vm *vm, int *curpage, vm_offset_t *curpage_offset, + uint64_t *data) +{ + struct pt_buffer *buf; + + if (vm->ctx->mode == HWT_MODE_THREAD) + buf = &((struct pt_ctx *)vm->thr->private)->buf; + else + buf = &pt_pcpu[vm->cpu->cpu_id].ctx->buf; + mtx_lock_spin(&buf->lock); + *curpage = buf->curpage; + *curpage_offset = buf->offset + (buf->wrap_count * vm->ctx->bufsize); + mtx_unlock_spin(&buf->lock); + + return (0); +} + +/* + * HWT thread creation hook. + * Allocates and associates a 'struct pt_ctx' for a given hwt thread. + */ +static int +pt_backend_alloc_thread(struct hwt_thread *thr) +{ + struct pt_ctx *pt_ctx; + int error; + + /* Omit M_WAITOK since this might get invoked a non-sleepable context */ + pt_ctx = malloc(sizeof(*pt_ctx), M_PT, M_NOWAIT | M_ZERO); + if (pt_ctx == NULL) + return (ENOMEM); + + error = pt_init_ctx(pt_ctx, thr->vm, thr->thread_id); + if (error) + return (error); + + thr->private = pt_ctx; + return (0); +} +/* + * HWT thread teardown hook. + */ +static void +pt_backend_free_thread(struct hwt_thread *thr) +{ + struct pt_ctx *ctx; + + ctx = (struct pt_ctx *)thr->private; + + pt_deinit_ctx(ctx); + free(ctx, M_PT); +} + +static void +pt_backend_dump(int cpu_id) +{ +} + +static struct hwt_backend_ops pt_ops = { + .hwt_backend_init = pt_backend_init, + .hwt_backend_deinit = pt_backend_deinit, + + .hwt_backend_configure = pt_backend_configure, + + .hwt_backend_enable = pt_backend_enable, + .hwt_backend_disable = pt_backend_disable, + +#ifdef SMP + .hwt_backend_enable_smp = pt_backend_enable_smp, + .hwt_backend_disable_smp = pt_backend_disable_smp, +#endif + + .hwt_backend_read = pt_backend_read, + .hwt_backend_dump = pt_backend_dump, + + .hwt_backend_thread_alloc = pt_backend_alloc_thread, + .hwt_backend_thread_free = pt_backend_free_thread, +}; + +static struct hwt_backend backend = { + .ops = &pt_ops, + .name = "pt", + .kva_req = 1, +}; + +/* + * Reads the latest valid trace buffer offset and enqueues + * a HWT_RECORD_BUFFER record. + * Used as a taskqueue routine from the ToPA interrupt handler. + */ +static void +pt_send_buffer_record(void *arg, int pending __unused) +{ + struct hwt_record_entry record; + struct pt_ctx *ctx = (struct pt_ctx *)arg; + + /* Prepare buffer record. */ + mtx_lock_spin(&ctx->buf.lock); + pt_fill_buffer_record(ctx->id, &ctx->buf, &record); + mtx_unlock_spin(&ctx->buf.lock); + hwt_record_ctx(ctx->hwt_ctx, &record, M_ZERO | M_NOWAIT); +} +static void +pt_topa_status_clear(void) +{ + uint64_t reg; + + reg = rdmsr(MSR_IA_GLOBAL_STATUS_RESET); + reg &= ~GLOBAL_STATUS_FLAG_TRACETOPAPMI; + reg |= GLOBAL_STATUS_FLAG_TRACETOPAPMI; + wrmsr(MSR_IA_GLOBAL_STATUS_RESET, reg); +} + +/* + * ToPA PMI handler. + * + * Invoked every time a ToPA entry marked with TOPA_INT is filled. + * Uses taskqueue to enqueue a buffer record for userspace. + * Re-enables the PC interrupt line as long as tracing is active. + */ +static int +pt_topa_intr(struct trapframe *tf) +{ + struct pt_buffer *buf; + struct pt_ctx *ctx; + uint64_t reg; + + SDT_PROBE0(pt, , , topa__intr); + + if (pt_cpu_get_state(curcpu) != PT_ACTIVE) { + return (0); + } + reg = rdmsr(MSR_IA_GLOBAL_STATUS); + if ((reg & GLOBAL_STATUS_FLAG_TRACETOPAPMI) == 0) { + /* ACK spurious or leftover interrupt. */ + pt_topa_status_clear(); + return (1); + } + + ctx = pt_pcpu[curcpu].ctx; + buf = &ctx->buf; + KASSERT(buf->topa_hw != NULL, + ("%s: ToPA PMI interrupt with invalid buffer", __func__)); + + pt_cpu_toggle_local(ctx->save_area, false); + pt_update_buffer(buf); + pt_topa_status_clear(); + taskqueue_enqueue_flags(taskqueue_pt, &ctx->task, + TASKQUEUE_FAIL_IF_PENDING); + + if (pt_cpu_get_state(curcpu) == PT_ACTIVE) { + pt_cpu_toggle_local(ctx->save_area, true); + lapic_reenable_pcint(); + } + return (1); +} + +/* + * Module initialization. + * + * Saves all PT-related cpuid info, registers itself as a HWT backend, + * and allocates metadata required to keep track of tracing operations + * on each CPU. + */ +static int +pt_init(void) +{ + u_int cp[4]; + int error; + + dprintf("pt: Enumerating part 1\n"); + cpuid_count(CPUID_PT_LEAF, 0, cp); + dprintf("pt: Maximum valid sub-leaf Index: %x\n", cp[0]); + dprintf("pt: ebx %x\n", cp[1]); + dprintf("pt: ecx %x\n", cp[2]); + + pt_info.l0_eax = cp[0]; + pt_info.l0_ebx = cp[1]; + pt_info.l0_ecx = cp[2]; + + dprintf("pt: Enumerating part 2\n"); + cpuid_count(CPUID_PT_LEAF, 1, cp); + dprintf("pt: eax %x\n", cp[0]); + dprintf("pt: ebx %x\n", cp[1]); + + pt_info.l1_eax = cp[0]; + pt_info.l1_ebx = cp[1]; + + error = hwt_backend_register(&backend); + if (error != 0) { + printf("pt: unable to register hwt backend, error %d\n", error); + return (error); + } + pt_pcpu = mallocarray(mp_ncpus, sizeof(struct pt_cpu), M_PT, + M_ZERO | M_WAITOK); + pt_pcpu_ctx = mallocarray(mp_ncpus, sizeof(struct pt_ctx), M_PT, + M_ZERO | M_WAITOK); + + nmi_register_handler(pt_topa_intr); + if (!lapic_enable_pcint()) { + nmi_remove_handler(pt_topa_intr); + hwt_backend_unregister(&backend); + free(pt_pcpu, M_PT); + free(pt_pcpu_ctx, M_PT); + pt_pcpu = NULL; + pt_pcpu_ctx = NULL; + printf("pt: failed to setup interrupt line\n"); + return (error); + } + initialized = true; + + return (0); +} + +/* + * Checks whether the CPU support Intel PT and + * initializes XSAVE area info. + * + * The driver relies on XSAVE/XRSTOR PT extensions, + * Table of Physical Addresses (ToPA) support, and + * support for multiple ToPA entries. + */ +static bool +pt_supported(void) +{ + u_int cp[4]; + + if ((cpu_stdext_feature & CPUID_STDEXT_PROCTRACE) == 0) { + printf("pt: CPU does not support Intel Processor Trace\n"); + return (false); + } + if ((cpu_feature2 & CPUID2_XSAVE) == 0) { + printf("pt: XSAVE is not supported\n"); + return (false); + } + if (!xsave_extfeature_supported(XFEATURE_ENABLED_PT, true)) { + printf("pt: CPU does not support managing PT state using XSAVE\n"); + return (false); + } + if (!xsave_extension_supported(CPUID_EXTSTATE_XSAVEC)) { + printf("pt: XSAVE compaction is not supported\n"); + return (false); + } + if (!xsave_extension_supported(CPUID_EXTSTATE_XSAVES)) { + printf("pt: CPU does not support XSAVES/XRSTORS\n"); + return (false); + } + + /* Require ToPA support. */ + cpuid_count(CPUID_PT_LEAF, 0, cp); + if ((cp[2] & CPUPT_TOPA) == 0) { + printf("pt: ToPA is not supported\n"); + return (false); + } + if ((cp[2] & CPUPT_TOPA_MULTI) == 0) { + printf("pt: multiple ToPA outputs are not supported\n"); + return (false); + } + + pt_info.xstate_hdr_offset = xsave_area_hdr_offset(); + pt_info.xsave_area_size = xsave_area_size(PT_XSTATE_BV, true, true); + pt_info.pt_xsave_offset = xsave_area_offset(PT_XSTATE_BV, + XFEATURE_ENABLED_PT, true, true); + + return (true); +} + +static void +pt_deinit(void) +{ + if (!initialized) + return; + nmi_remove_handler(pt_topa_intr); + lapic_disable_pcint(); + hwt_backend_unregister(&backend); + free(pt_pcpu, M_PT); + free(pt_pcpu_ctx, M_PT); + pt_pcpu = NULL; + initialized = false; +} + +static int +pt_modevent(module_t mod, int type, void *data) +{ + switch (type) { + case MOD_LOAD: + if (!pt_supported() || pt_init() != 0) { + return (ENXIO); + } + break; + case MOD_UNLOAD: + pt_deinit(); + break; + default: + break; + } + + return (0); +} + +static moduledata_t pt_mod = { "intel_pt", pt_modevent, NULL }; + +DECLARE_MODULE(intel_pt, pt_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); +MODULE_DEPEND(intel_pt, hwt, 1, 1, 1); +MODULE_VERSION(intel_pt, 1); diff --git a/sys/amd64/pt/pt.h b/sys/amd64/pt/pt.h new file mode 100644 index 000000000000..2423afdf22e9 --- /dev/null +++ b/sys/amd64/pt/pt.h @@ -0,0 +1,49 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Bojan Novković <bnovkov@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, 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 _AMD64_PT_PT_H_ +#define _AMD64_PT_PT_H_ + +#include <sys/types.h> + +#include <x86/include/specialreg.h> + +#define PT_IP_FILTER_MAX_RANGES (2) /* Intel SDM Vol. 3C, 33-29 */ + +struct pt_cpu_config { + uint64_t rtit_ctl; + register_t cr3_filter; + int nranges; + struct ipf_range { + vm_offset_t start; + vm_offset_t end; + } ip_ranges[PT_IP_FILTER_MAX_RANGES]; + uint32_t mtc_freq; + uint32_t cyc_thresh; + uint32_t psb_freq; +}; +#endif /* !_AMD64_PT_PT_H_ */ diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index 6c16daaa47c2..2fe6a5bc3584 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -317,6 +317,33 @@ svm_set_tsc_offset(struct svm_vcpu *vcpu, uint64_t offset) #define MSR_AMD7TH_START 0xC0010000UL #define MSR_AMD7TH_END 0xC0011FFFUL +static void +svm_get_cs_info(struct vmcb *vmcb, struct vm_guest_paging *paging, int *cs_d, + uint64_t *base) +{ + struct vmcb_segment seg; + int error __diagused; + + error = vmcb_seg(vmcb, VM_REG_GUEST_CS, &seg); + KASSERT(error == 0, ("%s: vmcb_seg error %d", __func__, error)); + + switch (paging->cpu_mode) { + case CPU_MODE_REAL: + *base = seg.base; + *cs_d = 0; + break; + case CPU_MODE_PROTECTED: + case CPU_MODE_COMPATIBILITY: + *cs_d = !!(seg.attrib & VMCB_CS_ATTRIB_D); + *base = seg.base; + break; + default: + *base = 0; + *cs_d = 0; + break; + } +} + /* * Get the index and bit position for a MSR in permission bitmap. * Two bits are used for each MSR: lower bit for read and higher bit for write. @@ -735,10 +762,29 @@ svm_inout_str_seginfo(struct svm_vcpu *vcpu, int64_t info1, int in, if (in) { vis->seg_name = VM_REG_GUEST_ES; - } else { - /* The segment field has standard encoding */ + } else if (decode_assist()) { + /* + * The effective segment number in EXITINFO1[12:10] is populated + * only if the processor has the DecodeAssist capability. + * + * XXX this is not specified explicitly in APMv2 but can be + * verified empirically. + */ s = (info1 >> 10) & 0x7; + + /* The segment field has standard encoding */ vis->seg_name = vm_segment_name(s); + } else { + /* + * The segment register need to be manually decoded by fetching + * the instructions near ip. However, we are unable to fetch it + * while the interrupts are disabled. Therefore, we leave the + * value unset until the generic ins/outs handler runs. + */ + vis->seg_name = VM_REG_LAST; + svm_get_cs_info(vcpu->vmcb, &vis->paging, &vis->cs_d, + &vis->cs_base); + return; } error = svm_getdesc(vcpu, vis->seg_name, &vis->seg_desc); @@ -798,16 +844,6 @@ svm_handle_io(struct svm_vcpu *vcpu, struct vm_exit *vmexit) info1 = ctrl->exitinfo1; inout_string = info1 & BIT(2) ? 1 : 0; - /* - * The effective segment number in EXITINFO1[12:10] is populated - * only if the processor has the DecodeAssist capability. - * - * XXX this is not specified explicitly in APMv2 but can be verified - * empirically. - */ - if (inout_string && !decode_assist()) - return (UNHANDLED); - vmexit->exitcode = VM_EXITCODE_INOUT; vmexit->u.inout.in = (info1 & BIT(0)) ? 1 : 0; vmexit->u.inout.string = inout_string; @@ -825,6 +861,8 @@ svm_handle_io(struct svm_vcpu *vcpu, struct vm_exit *vmexit) vis->index = svm_inout_str_index(regs, vmexit->u.inout.in); vis->count = svm_inout_str_count(regs, vmexit->u.inout.rep); vis->addrsize = svm_inout_str_addrsize(info1); + vis->cs_d = 0; + vis->cs_base = 0; svm_inout_str_seginfo(vcpu, info1, vmexit->u.inout.in, vis); } @@ -866,10 +904,9 @@ static void svm_handle_inst_emul(struct vmcb *vmcb, uint64_t gpa, struct vm_exit *vmexit) { struct vm_guest_paging *paging; - struct vmcb_segment seg; struct vmcb_ctrl *ctrl; char *inst_bytes; - int error __diagused, inst_len; + int inst_len; ctrl = &vmcb->ctrl; paging = &vmexit->u.inst_emul.paging; @@ -879,29 +916,8 @@ svm_handle_inst_emul(struct vmcb *vmcb, uint64_t gpa, struct vm_exit *vmexit) vmexit->u.inst_emul.gla = VIE_INVALID_GLA; svm_paging_info(vmcb, paging); - error = vmcb_seg(vmcb, VM_REG_GUEST_CS, &seg); - KASSERT(error == 0, ("%s: vmcb_seg(CS) error %d", __func__, error)); - - switch(paging->cpu_mode) { - case CPU_MODE_REAL: - vmexit->u.inst_emul.cs_base = seg.base; - vmexit->u.inst_emul.cs_d = 0; - break; - case CPU_MODE_PROTECTED: - case CPU_MODE_COMPATIBILITY: - vmexit->u.inst_emul.cs_base = seg.base; - - /* - * Section 4.8.1 of APM2, Default Operand Size or D bit. - */ - vmexit->u.inst_emul.cs_d = (seg.attrib & VMCB_CS_ATTRIB_D) ? - 1 : 0; - break; - default: - vmexit->u.inst_emul.cs_base = 0; - vmexit->u.inst_emul.cs_d = 0; - break; - } + svm_get_cs_info(vmcb, paging, &vmexit->u.inst_emul.cs_d, + &vmexit->u.inst_emul.cs_base); /* * Copy the instruction bytes into 'vie' if available. diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 957217ab2258..842281ab862e 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -2659,6 +2659,8 @@ vmx_exit_process(struct vmx *vmx, struct vmx_vcpu *vcpu, struct vm_exit *vmexit) vis->index = inout_str_index(vcpu, in); vis->count = inout_str_count(vcpu, vis->inout.rep); vis->addrsize = inout_str_addrsize(inst_info); + vis->cs_d = 0; + vis->cs_base = 0; inout_str_seginfo(vcpu, inst_info, in, vis); } SDT_PROBE3(vmm, vmx, exit, inout, vmx, vcpuid, vmexit); diff --git a/sys/amd64/vmm/intel/vmx_support.S b/sys/amd64/vmm/intel/vmx_support.S index f393f160b101..130130b64541 100644 --- a/sys/amd64/vmm/intel/vmx_support.S +++ b/sys/amd64/vmm/intel/vmx_support.S @@ -32,12 +32,6 @@ #include "vmx_assym.h" -#ifdef SMP -#define LK lock ; -#else -#define LK -#endif - /* Be friendly to DTrace FBT's prologue/epilogue pattern matching */ #define VENTER push %rbp ; mov %rsp,%rbp #define VLEAVE pop %rbp diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index c53e32889000..c54b6e6d0074 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -65,30 +65,6 @@ #include <x86/psl.h> #include <x86/specialreg.h> -/* struct vie_op.op_type */ -enum { - VIE_OP_TYPE_NONE = 0, - VIE_OP_TYPE_MOV, - VIE_OP_TYPE_MOVSX, - VIE_OP_TYPE_MOVZX, - VIE_OP_TYPE_AND, - VIE_OP_TYPE_OR, - VIE_OP_TYPE_SUB, - VIE_OP_TYPE_TWO_BYTE, - VIE_OP_TYPE_PUSH, - VIE_OP_TYPE_CMP, - VIE_OP_TYPE_POP, - VIE_OP_TYPE_MOVS, - VIE_OP_TYPE_GROUP1, - VIE_OP_TYPE_STOS, - VIE_OP_TYPE_BITTEST, - VIE_OP_TYPE_TWOB_GRP15, - VIE_OP_TYPE_ADD, - VIE_OP_TYPE_TEST, - VIE_OP_TYPE_BEXTR, - VIE_OP_TYPE_LAST -}; - /* struct vie_op.op_flags */ #define VIE_OP_F_IMM (1 << 0) /* 16/32-bit immediate operand */ #define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */ @@ -152,6 +128,16 @@ static const struct vie_op one_byte_opcodes[256] = { .op_byte = 0x3B, .op_type = VIE_OP_TYPE_CMP, }, + [0x6E] = { + .op_byte = 0x6E, + .op_type = VIE_OP_TYPE_OUTS, + .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION, + }, + [0x6F] = { + .op_byte = 0x6F, + .op_type = VIE_OP_TYPE_OUTS, + .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION, + }, [0x88] = { .op_byte = 0x88, .op_type = VIE_OP_TYPE_MOV, diff --git a/sys/amd64/vmm/vmm_ioport.c b/sys/amd64/vmm/vmm_ioport.c index fc1ecab9f209..8aab28f5e68e 100644 --- a/sys/amd64/vmm/vmm_ioport.c +++ b/sys/amd64/vmm/vmm_ioport.c @@ -145,9 +145,49 @@ emulate_inout_port(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu) } static int +decode_segment(struct vcpu *vcpu, enum vm_reg_name *segment) +{ + struct vm_guest_paging *paging; + struct vie vie; + struct vm_exit *vme; + int err; + int fault; + + vme = vm_exitinfo(vcpu); + paging = &vme->u.inout_str.paging; + + vie_init(&vie, NULL, 0); + err = vmm_fetch_instruction(vcpu, paging, + vme->rip + vme->u.inout_str.cs_base, VIE_INST_SIZE, &vie, &fault); + if (err || fault) + return (err); + + err = vmm_decode_instruction(vcpu, VIE_INVALID_GLA, paging->cpu_mode, + vme->u.inout_str.cs_d, &vie); + + if (err || vie.op.op_type != VIE_OP_TYPE_OUTS) + return (EINVAL); + if (vie.segment_override) + *segment = vie.segment_register; + else + *segment = VM_REG_GUEST_DS; + + return (0); +} + +static int emulate_inout_str(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu) { + int err; + *retu = true; + if (vmexit->u.inout_str.seg_name == VM_REG_LAST) { + err = decode_segment(vcpu, &vmexit->u.inout_str.seg_name); + if (err) + return (err); + return (vm_get_seg_desc(vcpu, vmexit->u.inout_str.seg_name, + &vmexit->u.inout_str.seg_desc)); + } return (0); /* Return to userspace to finish emulation */ } diff --git a/sys/arm/allwinner/aw_mmc.c b/sys/arm/allwinner/aw_mmc.c index 6bebf5e5fb5e..a8add957dc74 100644 --- a/sys/arm/allwinner/aw_mmc.c +++ b/sys/arm/allwinner/aw_mmc.c @@ -84,21 +84,26 @@ struct aw_mmc_conf { uint32_t dma_xferlen; + uint32_t dma_desc_shift; bool mask_data0; bool can_calibrate; bool new_timing; + bool zero_is_skip; }; static const struct aw_mmc_conf a10_mmc_conf = { .dma_xferlen = 0x2000, + .dma_desc_shift = 0, }; static const struct aw_mmc_conf a13_mmc_conf = { .dma_xferlen = 0x10000, + .dma_desc_shift = 0, }; static const struct aw_mmc_conf a64_mmc_conf = { .dma_xferlen = 0x10000, + .dma_desc_shift = 0, .mask_data0 = true, .can_calibrate = true, .new_timing = true, @@ -106,13 +111,24 @@ static const struct aw_mmc_conf a64_mmc_conf = { static const struct aw_mmc_conf a64_emmc_conf = { .dma_xferlen = 0x2000, + .dma_desc_shift = 0, .can_calibrate = true, }; +static const struct aw_mmc_conf d1_mmc_conf = { + .dma_xferlen = 0x1000, + .dma_desc_shift = 2, + .mask_data0 = true, + .can_calibrate = true, + .new_timing = true, + .zero_is_skip = true, +}; + static struct ofw_compat_data compat_data[] = { {"allwinner,sun4i-a10-mmc", (uintptr_t)&a10_mmc_conf}, {"allwinner,sun5i-a13-mmc", (uintptr_t)&a13_mmc_conf}, {"allwinner,sun7i-a20-mmc", (uintptr_t)&a13_mmc_conf}, + {"allwinner,sun20i-d1-mmc", (uintptr_t)&d1_mmc_conf}, {"allwinner,sun50i-a64-mmc", (uintptr_t)&a64_mmc_conf}, {"allwinner,sun50i-a64-emmc", (uintptr_t)&a64_emmc_conf}, {NULL, 0} @@ -607,16 +623,18 @@ aw_dma_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int err) dma_desc = sc->aw_dma_desc; for (i = 0; i < nsegs; i++) { - if (segs[i].ds_len == sc->aw_mmc_conf->dma_xferlen) + if ((segs[i].ds_len == sc->aw_mmc_conf->dma_xferlen) && + !sc->aw_mmc_conf->zero_is_skip) dma_desc[i].buf_size = 0; /* Size of 0 indicate max len */ else dma_desc[i].buf_size = segs[i].ds_len; - dma_desc[i].buf_addr = segs[i].ds_addr; + dma_desc[i].buf_addr = segs[i].ds_addr >> + sc->aw_mmc_conf->dma_desc_shift; dma_desc[i].config = AW_MMC_DMA_CONFIG_CH | - AW_MMC_DMA_CONFIG_OWN | AW_MMC_DMA_CONFIG_DIC; - - dma_desc[i].next = sc->aw_dma_desc_phys + - ((i + 1) * sizeof(struct aw_mmc_dma_desc)); + AW_MMC_DMA_CONFIG_OWN | AW_MMC_DMA_CONFIG_DIC; + dma_desc[i].next = (sc->aw_dma_desc_phys + + (i + 1) * sizeof(struct aw_mmc_dma_desc)) >> + sc->aw_mmc_conf->dma_desc_shift; } dma_desc[0].config |= AW_MMC_DMA_CONFIG_FD; @@ -678,7 +696,8 @@ aw_mmc_prepare_dma(struct aw_mmc_softc *sc) AW_MMC_WRITE_4(sc, AW_MMC_IDIE, val); /* Set DMA descritptor list address */ - AW_MMC_WRITE_4(sc, AW_MMC_DLBA, sc->aw_dma_desc_phys); + AW_MMC_WRITE_4(sc, AW_MMC_DLBA, sc->aw_dma_desc_phys >> + sc->aw_mmc_conf->dma_desc_shift); /* FIFO trigger level */ AW_MMC_WRITE_4(sc, AW_MMC_FWLR, AW_MMC_DMA_FTRGLEVEL); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index a09da794e77d..2152f7fcc1c6 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -5709,6 +5709,9 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags, PMAP_LOCK_ASSERT(pmap, MA_OWNED); KASSERT(ADDR_IS_CANONICAL(va), ("%s: Address not in canonical form: %lx", __func__, va)); + KASSERT((flags & (PMAP_ENTER_NOREPLACE | PMAP_ENTER_NORECLAIM)) != + PMAP_ENTER_NORECLAIM, + ("pmap_enter_l2: flags is missing PMAP_ENTER_NOREPLACE")); if ((l2 = pmap_alloc_l2(pmap, va, &l2pg, (flags & PMAP_ENTER_NOSLEEP) != 0 ? NULL : lockp)) == NULL) { @@ -5828,6 +5831,15 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags, if (!pmap_pv_insert_l2(pmap, va, new_l2, flags, lockp)) { if (l2pg != NULL) pmap_abort_ptp(pmap, va, l2pg); + else { + KASSERT(ADDR_IS_KERNEL(va) && + (pmap_load(l2) & ATTR_DESCR_MASK) == + L2_TABLE, + ("pmap_enter_l2: invalid kernel L2E")); + mt = pmap_remove_pt_page(pmap, va); + KASSERT(mt != NULL, + ("pmap_enter_l2: missing kernel PTP")); + } if (uwptpg != NULL) { mt = pmap_remove_pt_page(pmap, va); KASSERT(mt == uwptpg, @@ -8489,18 +8501,20 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, /* * Invalidate the 2MB page mapping and return "failure" if the - * mapping was never accessed. + * mapping was never accessed and not wired. */ if ((oldl2 & ATTR_AF) == 0) { - KASSERT((oldl2 & ATTR_SW_WIRED) == 0, - ("pmap_demote_l2: a wired mapping is missing ATTR_AF")); - pmap_demote_l2_abort(pmap, va, l2, lockp); - CTR2(KTR_PMAP, "pmap_demote_l2: failure for va %#lx in pmap %p", - va, pmap); - goto fail; - } - - if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) { + if ((oldl2 & ATTR_SW_WIRED) == 0) { + pmap_demote_l2_abort(pmap, va, l2, lockp); + CTR2(KTR_PMAP, + "pmap_demote_l2: failure for va %#lx in pmap %p", + va, pmap); + goto fail; + } + ml3 = pmap_remove_pt_page(pmap, va); + /* Fill the PTP with L3Es that have ATTR_AF cleared. */ + ml3->valid = 0; + } else if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) { KASSERT((oldl2 & ATTR_SW_WIRED) == 0, ("pmap_demote_l2: page table page for a wired mapping" " is missing")); @@ -8556,7 +8570,7 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, /* * If the PTP is not leftover from an earlier promotion or it does not * have ATTR_AF set in every L3E, then fill it. The new L3Es will all - * have ATTR_AF set. + * have ATTR_AF set, unless this is a wired mapping with ATTR_AF clear. * * When pmap_update_entry() clears the old L2 mapping, it (indirectly) * performs a dsb(). That dsb() ensures that the stores for filling diff --git a/sys/arm64/broadcom/genet/if_genet.c b/sys/arm64/broadcom/genet/if_genet.c index 0602f076b257..182b5582fb7c 100644 --- a/sys/arm64/broadcom/genet/if_genet.c +++ b/sys/arm64/broadcom/genet/if_genet.c @@ -349,7 +349,7 @@ gen_attach(device_t dev) } /* If address was not found, create one based on the hostid and name. */ - if (eaddr_found == 0) + if (!eaddr_found) ether_gen_addr(sc->ifp, &eaddr); /* Attach ethernet interface */ ether_ifattach(sc->ifp, eaddr.octet); @@ -653,7 +653,7 @@ gen_bus_dma_teardown(struct gen_softc *sc) error); } - if (sc->tx_buf_tag != NULL) { + if (sc->rx_buf_tag != NULL) { for (i = 0; i < RX_DESC_COUNT; i++) { error = bus_dmamap_destroy(sc->rx_buf_tag, sc->rx_ring_ent[i].map); diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 2ec736e7f4ac..cae29226d13c 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -2515,6 +2515,15 @@ xpt_action(union ccb *start_ccb) ("xpt_action: func %#x %s\n", start_ccb->ccb_h.func_code, xpt_action_name(start_ccb->ccb_h.func_code))); + /* + * Either it isn't queued, or it has a real priority. There still too + * many places that reuse CCBs with a real priority to do immediate + * queries to do the other side of this assert. + */ + KASSERT((start_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0 || + start_ccb->ccb_h.pinfo.priority != CAM_PRIORITY_NONE, + ("%s: queued ccb and CAM_PRIORITY_NONE illegal.", __func__)); + start_ccb->ccb_h.status = CAM_REQ_INPROG; (*(start_ccb->ccb_h.path->bus->xport->ops->action))(start_ccb); } diff --git a/sys/cam/mmc/mmc_da.c b/sys/cam/mmc/mmc_da.c index 7f8bf3516804..322141a72707 100644 --- a/sys/cam/mmc/mmc_da.c +++ b/sys/cam/mmc/mmc_da.c @@ -1081,7 +1081,7 @@ sdda_start_init_task(void *context, int pending) CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sdda_start_init_task\n")); new_ccb = xpt_alloc_ccb(); xpt_setup_ccb(&new_ccb->ccb_h, periph->path, - CAM_PRIORITY_NONE); + CAM_PRIORITY_NORMAL); cam_periph_lock(periph); cam_periph_hold(periph, PRIBIO|PCATCH); diff --git a/sys/cam/mmc/mmc_xpt.c b/sys/cam/mmc/mmc_xpt.c index 4fce03004994..f5f66f5214a8 100644 --- a/sys/cam/mmc/mmc_xpt.c +++ b/sys/cam/mmc/mmc_xpt.c @@ -610,7 +610,6 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb) CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("Start with PROBE_RESET\n")); /* FALLTHROUGH */ case PROBE_IDENTIFY: - xpt_path_inq(&start_ccb->cpi, periph->path); CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("Start with PROBE_IDENTIFY\n")); init_standard_ccb(start_ccb, XPT_MMC_GET_TRAN_SETTINGS); break; diff --git a/sys/cddl/boot/zfs/zfsimpl.h b/sys/cddl/boot/zfs/zfsimpl.h index 0ce38384abbf..83d964360343 100644 --- a/sys/cddl/boot/zfs/zfsimpl.h +++ b/sys/cddl/boot/zfs/zfsimpl.h @@ -2019,6 +2019,7 @@ typedef struct vdev { vdev_list_t v_children; /* children of this vdev */ const char *v_name; /* vdev name */ uint64_t v_guid; /* vdev guid */ + uint64_t v_txg; /* most recent transaction */ uint64_t v_id; /* index in parent */ uint64_t v_psize; /* physical device capacity */ int v_ashift; /* offset to block shift */ @@ -2048,7 +2049,6 @@ typedef struct spa { STAILQ_ENTRY(spa) spa_link; /* link in global pool list */ char *spa_name; /* pool name */ uint64_t spa_guid; /* pool guid */ - uint64_t spa_txg; /* most recent transaction */ struct uberblock *spa_uberblock; /* best uberblock so far */ vdev_t *spa_root_vdev; /* toplevel vdev container */ objset_phys_t *spa_mos; /* MOS for this pool */ diff --git a/sys/conf/files b/sys/conf/files index 74d251c2b608..dd0d390962f2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3227,6 +3227,19 @@ dev/uart/uart_if.m optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart # +# Universal Flash Storage Host Controller Interface drivers +# +dev/ufshci/ufshci.c optional ufshci +dev/ufshci/ufshci_ctrlr.c optional ufshci +dev/ufshci/ufshci_ctrlr_cmd.c optional ufshci +dev/ufshci/ufshci_dev.c optional ufshci +dev/ufshci/ufshci_pci.c optional ufshci +dev/ufshci/ufshci_req_queue.c optional ufshci +dev/ufshci/ufshci_req_sdb.c optional ufshci +dev/ufshci/ufshci_sim.c optional ufshci +dev/ufshci/ufshci_sysctl.c optional ufshci +dev/ufshci/ufshci_uic_cmd.c optional ufshci +# # USB controller drivers # dev/usb/controller/musb_otg.c optional musb diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 0584fc29d039..80548320c3fc 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -84,8 +84,8 @@ amd64/amd64/xen-locore.S optional xenhvm \ amd64/amd64/machdep.c standard amd64/amd64/mem.c optional mem amd64/amd64/minidump_machdep.c standard -amd64/amd64/mp_machdep.c optional smp -amd64/amd64/mpboot.S optional smp +amd64/amd64/mp_machdep.c standard +amd64/amd64/mpboot.S standard amd64/amd64/pmap.c standard amd64/amd64/ptrace_machdep.c standard amd64/amd64/support.S standard @@ -191,6 +191,10 @@ dev/ice/irdma_di_if.m optional ice pci \ compile-with "${NORMAL_M} -I$S/dev/ice" dev/ice/ice_ddp_common.c optional ice pci \ compile-with "${NORMAL_C} -I$S/dev/ice" +dev/ice/ice_iov.c optional ice pci pci_iov \ + compile-with "${NORMAL_C} -I$S/dev/ice" +dev/ice/ice_vf_mbx.c optional ice pci pci_iov \ + compile-with "${NORMAL_C} -I$S/dev/ice" ice_ddp.c optional ice_ddp \ compile-with "${AWK} -f $S/tools/fw_stub.awk ice_ddp.fw:ice_ddp:0x01032900 -mice_ddp -c${.TARGET}" \ no-ctfconvert no-implicit-rule before-depend local \ diff --git a/sys/dev/drm2/drm_fb_helper.c b/sys/dev/drm2/drm_fb_helper.c index f67cc9f60d02..1f4abd255690 100644 --- a/sys/dev/drm2/drm_fb_helper.c +++ b/sys/dev/drm2/drm_fb_helper.c @@ -51,7 +51,7 @@ struct vt_kms_softc { struct task fb_mode_task; }; -/* Call restore out of vt(9) locks. */ +/* Call restore out of vt(4) locks. */ static void vt_restore_fbdev_mode(void *arg, int pending) { diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c index b0fa33daeca7..b55c1c191077 100644 --- a/sys/dev/efidev/efirt.c +++ b/sys/dev/efidev/efirt.c @@ -107,7 +107,8 @@ static int efi_status2err[25] = { enum efi_table_type { TYPE_ESRT = 0, - TYPE_PROP + TYPE_PROP, + TYPE_MEMORY_ATTR }; static int efi_enter(void); @@ -445,6 +446,42 @@ get_table_length(enum efi_table_type type, size_t *table_len, void **taddr) free(buf, M_TEMP); return (0); } + case TYPE_MEMORY_ATTR: + { + efi_guid_t guid = EFI_MEMORY_ATTRIBUTES_TABLE; + struct efi_memory_attribute_table *tbl_addr, *mem_addr; + int error; + void *buf; + size_t len = sizeof(struct efi_memory_attribute_table); + + error = efi_get_table(&guid, (void **)&tbl_addr); + if (error) + return (error); + + buf = malloc(len, M_TEMP, M_WAITOK); + error = physcopyout((vm_paddr_t)tbl_addr, buf, len); + if (error) { + free(buf, M_TEMP); + return (error); + } + + mem_addr = (struct efi_memory_attribute_table *)buf; + if (mem_addr->version != 2) { + free(buf, M_TEMP); + return (EINVAL); + } + len += mem_addr->descriptor_size * mem_addr->num_ents; + if (len > EFI_TABLE_ALLOC_MAX) { + free(buf, M_TEMP); + return (ENOMEM); + } + + *table_len = len; + if (taddr != NULL) + *taddr = tbl_addr; + free(buf, M_TEMP); + return (0); + } } return (ENOENT); } @@ -457,7 +494,8 @@ copy_table(efi_guid_t *guid, void **buf, size_t buf_len, size_t *table_len) enum efi_table_type type; } tables[] = { { EFI_TABLE_ESRT, TYPE_ESRT }, - { EFI_PROPERTIES_TABLE, TYPE_PROP } + { EFI_PROPERTIES_TABLE, TYPE_PROP }, + { EFI_MEMORY_ATTRIBUTES_TABLE, TYPE_MEMORY_ATTR } }; size_t table_idx; void *taddr; diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index ab7f13177969..764bcb7e6ee8 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -110,10 +110,9 @@ gpio_alloc_intr_resource(device_t consumer_dev, int *rid, u_int alloc_flags, res = bus_alloc_resource(consumer_dev, SYS_RES_IRQ, rid, irq, irq, 1, alloc_flags); if (res == NULL) { - intr_free_intr_map_data((struct intr_map_data *)gpio_data); + intr_unmap_irq(irq); return (NULL); } - rman_set_virtual(res, gpio_data); return (res); } #else @@ -866,6 +865,25 @@ gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, end, count, flags)); } +static int +gpiobus_release_resource(device_t dev, device_t child, struct resource *r) +{ + int err; +#ifdef INTRNG + u_int irq; + + irq = rman_get_start(r); + MPASS(irq == rman_get_end(r)); +#endif + err = bus_generic_rman_release_resource(dev, child, r); + if (err != 0) + return (err); +#ifdef INTRNG + intr_unmap_irq(irq); +#endif + return (0); +} + static struct resource_list * gpiobus_get_resource_list(device_t bus __unused, device_t child) { @@ -1060,7 +1078,7 @@ static device_method_t gpiobus_methods[] = { DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_rman_release_resource), + DEVMETHOD(bus_release_resource, gpiobus_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_rman_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_rman_deactivate_resource), DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), diff --git a/sys/dev/ice/ice_features.h b/sys/dev/ice/ice_features.h index 821abe4806ca..5b23757b1c98 100644 --- a/sys/dev/ice/ice_features.h +++ b/sys/dev/ice/ice_features.h @@ -91,7 +91,9 @@ enum feat_list { static inline void ice_disable_unsupported_features(ice_bitmap_t __unused *bitmap) { +#ifndef PCI_IOV ice_clear_bit(ICE_FEATURE_SRIOV, bitmap); +#endif #ifndef DEV_NETMAP ice_clear_bit(ICE_FEATURE_NETMAP, bitmap); #endif diff --git a/sys/dev/ice/ice_iflib.h b/sys/dev/ice/ice_iflib.h index 3a5dc201189a..e1d5307a9516 100644 --- a/sys/dev/ice/ice_iflib.h +++ b/sys/dev/ice/ice_iflib.h @@ -139,6 +139,9 @@ struct ice_irq_vector { * @tc: traffic class queue belongs to * @q_handle: qidx in tc; used in TXQ enable functions * + * ice_iov.c requires the following parameters (when PCI_IOV is defined): + * @itr_idx: ITR index to use for this queue + * * Other parameters may be iflib driver specific */ struct ice_tx_queue { @@ -153,6 +156,9 @@ struct ice_tx_queue { u32 me; u16 q_handle; u8 tc; +#ifdef PCI_IOV + u8 itr_idx; +#endif /* descriptor writeback status */ qidx_t *tx_rsq; @@ -175,6 +181,9 @@ struct ice_tx_queue { * @stats: queue statistics * @tc: traffic class queue belongs to * + * ice_iov.c requires the following parameters (when PCI_IOV is defined): + * @itr_idx: ITR index to use for this queue + * * Other parameters may be iflib driver specific */ struct ice_rx_queue { @@ -187,6 +196,9 @@ struct ice_rx_queue { struct ice_irq_vector *irqv; u32 me; u8 tc; +#ifdef PCI_IOV + u8 itr_idx; +#endif struct if_irq que_irq; }; @@ -332,6 +344,10 @@ struct ice_softc { ice_declare_bitmap(feat_cap, ICE_FEATURE_COUNT); ice_declare_bitmap(feat_en, ICE_FEATURE_COUNT); +#ifdef PCI_IOV + struct ice_vf *vfs; + u16 num_vfs; +#endif struct ice_resmgr os_imgr; /* For mirror interface */ struct ice_mirr_if *mirr_if; diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c new file mode 100644 index 000000000000..c5a3e1060e44 --- /dev/null +++ b/sys/dev/ice/ice_iov.c @@ -0,0 +1,1856 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2025, Intel Corporation + * 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. + * + * 3. Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +/** + * @file ice_iov.c + * @brief Virtualization support functions + * + * Contains functions for enabling and managing PCIe virtual function devices, + * including enabling new VFs, and managing VFs over the virtchnl interface. + */ + +#include "ice_iov.h" + +static struct ice_vf *ice_iov_get_vf(struct ice_softc *sc, int vf_num); +static void ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf); +static void ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, + bool trigger_vflr); +static void ice_iov_setup_intr_mapping(struct ice_softc *sc, struct ice_vf *vf); + +static void ice_vc_version_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_get_vf_res_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_add_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_del_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static bool ice_vc_isvalid_ring_len(u16 ring_len); +static void ice_vc_cfg_vsi_qs_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_cfg_rss_key_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_set_rss_hena_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_enable_queues_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_notify_vf_link_state(struct ice_softc *sc, struct ice_vf *vf); +static void ice_vc_disable_queues_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_cfg_irq_map_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_get_stats_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_eth_stats_to_virtchnl_eth_stats(struct ice_eth_stats *istats, + struct virtchnl_eth_stats *vstats); +static void ice_vc_cfg_rss_lut_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_cfg_promisc_mode_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static void ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf); +static enum virtchnl_status_code ice_iov_err_to_virt_err(int ice_err); +static int ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr); + +/** + * ice_iov_attach - Initialize SR-IOV PF host support + * @sc: device softc structure + * + * Initialize SR-IOV PF host support at the end of the driver attach process. + * + * @pre Must be called from sleepable context (calls malloc() w/ M_WAITOK) + * + * @returns 0 if successful, or + * - ENOMEM if there is no memory for the PF/VF schemas or iov device + * - ENXIO if the device isn't PCI-E or doesn't support the same SR-IOV + * version as the kernel + * - ENOENT if the device doesn't have the SR-IOV capability + */ +int +ice_iov_attach(struct ice_softc *sc) +{ + device_t dev = sc->dev; + nvlist_t *pf_schema, *vf_schema; + int error; + + pf_schema = pci_iov_schema_alloc_node(); + vf_schema = pci_iov_schema_alloc_node(); + + pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL); + pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof", + IOV_SCHEMA_HASDEFAULT, TRUE); + pci_iov_schema_add_bool(vf_schema, "allow-set-mac", + IOV_SCHEMA_HASDEFAULT, FALSE); + pci_iov_schema_add_bool(vf_schema, "allow-promisc", + IOV_SCHEMA_HASDEFAULT, FALSE); + pci_iov_schema_add_uint16(vf_schema, "num-queues", + IOV_SCHEMA_HASDEFAULT, ICE_DEFAULT_VF_QUEUES); + pci_iov_schema_add_uint16(vf_schema, "mirror-src-vsi", + IOV_SCHEMA_HASDEFAULT, ICE_INVALID_MIRROR_VSI); + pci_iov_schema_add_uint16(vf_schema, "max-vlan-allowed", + IOV_SCHEMA_HASDEFAULT, ICE_DEFAULT_VF_VLAN_LIMIT); + pci_iov_schema_add_uint16(vf_schema, "max-mac-filters", + IOV_SCHEMA_HASDEFAULT, ICE_DEFAULT_VF_FILTER_LIMIT); + + error = pci_iov_attach(dev, pf_schema, vf_schema); + if (error != 0) { + device_printf(dev, + "pci_iov_attach failed (error=%s)\n", + ice_err_str(error)); + ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en); + } else + ice_set_bit(ICE_FEATURE_SRIOV, sc->feat_en); + + return (error); +} + +/** + * ice_iov_detach - Teardown SR-IOV PF host support + * @sc: device softc structure + * + * Teardown SR-IOV PF host support at the start of the driver detach process. + * + * @returns 0 if successful or IOV support hasn't been setup, or + * - EBUSY if VFs still exist + */ +int +ice_iov_detach(struct ice_softc *sc) +{ + device_t dev = sc->dev; + int error; + + error = pci_iov_detach(dev); + if (error != 0) { + device_printf(dev, + "pci_iov_detach failed (error=%s)\n", + ice_err_str(error)); + } + + return (error); +} + +/** + * ice_iov_init - Called by the OS before the first VF is created. + * @sc: device softc structure + * @num_vfs: number of VFs to setup resources for + * @params: configuration parameters for the PF + * + * @returns 0 if successful or an error code on failure + */ +int +ice_iov_init(struct ice_softc *sc, uint16_t num_vfs, const nvlist_t *params __unused) +{ + /* Allocate array of VFs, for tracking */ + sc->vfs = (struct ice_vf *)malloc(sizeof(struct ice_vf) * num_vfs, M_ICE, M_NOWAIT | + M_ZERO); + if (sc->vfs == NULL) + return (ENOMEM); + + /* Initialize each VF with basic information */ + for (int i = 0; i < num_vfs; i++) + sc->vfs[i].vf_num = i; + + /* Save off number of configured VFs */ + sc->num_vfs = num_vfs; + + return (0); +} + +/** + * ice_iov_get_vf - Get pointer to VF at given index + * @sc: device softc structure + * @vf_num: Index of VF to retrieve + * + * @remark will throw an assertion if vf_num is not in the + * range of allocated VFs + * + * @returns a pointer to the VF structure at the given index + */ +static struct ice_vf * +ice_iov_get_vf(struct ice_softc *sc, int vf_num) +{ + MPASS(vf_num < sc->num_vfs); + + return &sc->vfs[vf_num]; +} + +/** + * ice_iov_add_vf - Called by the OS for each VF to create + * @sc: device softc structure + * @vfnum: index of VF to configure + * @params: configuration parameters for the VF + * + * @returns 0 if successful or an error code on failure + */ +int +ice_iov_add_vf(struct ice_softc *sc, uint16_t vfnum, const nvlist_t *params) +{ + struct ice_tx_queue *txq; + struct ice_rx_queue *rxq; + device_t dev = sc->dev; + struct ice_vsi *vsi; + struct ice_vf *vf; + int vf_num_queues; + const void *mac; + size_t size; + int error; + int i; + + vf = ice_iov_get_vf(sc, vfnum); + vf->vf_flags = VF_FLAG_ENABLED; + + /* This VF needs at least one VSI */ + vsi = ice_alloc_vsi(sc, ICE_VSI_VF); + if (vsi == NULL) + return (ENOMEM); + vf->vsi = vsi; + vsi->vf_num = vfnum; + + vf_num_queues = nvlist_get_number(params, "num-queues"); + /* Validate and clamp value if invalid */ + if (vf_num_queues < 1 || vf_num_queues > ICE_MAX_SCATTERED_QUEUES) + device_printf(dev, "Invalid num-queues (%d) for VF %d\n", + vf_num_queues, vf->vf_num); + if (vf_num_queues < 1) { + device_printf(dev, "Setting VF %d num-queues to 1\n", vf->vf_num); + vf_num_queues = 1; + } else if (vf_num_queues > ICE_MAX_SCATTERED_QUEUES) { + device_printf(dev, "Setting VF %d num-queues to %d\n", + vf->vf_num, ICE_MAX_SCATTERED_QUEUES); + vf_num_queues = ICE_MAX_SCATTERED_QUEUES; + } + vsi->qmap_type = ICE_RESMGR_ALLOC_SCATTERED; + + /* Reserve VF queue allocation from PF queues */ + ice_alloc_vsi_qmap(vsi, vf_num_queues, vf_num_queues); + vsi->num_tx_queues = vsi->num_rx_queues = vf_num_queues; + + /* Assign Tx queues from PF space */ + error = ice_resmgr_assign_scattered(&sc->tx_qmgr, vsi->tx_qmap, + vsi->num_tx_queues); + if (error) { + device_printf(sc->dev, "Unable to assign VF Tx queues: %s\n", + ice_err_str(error)); + goto release_vsi; + } + + /* Assign Rx queues from PF space */ + error = ice_resmgr_assign_scattered(&sc->rx_qmgr, vsi->rx_qmap, + vsi->num_rx_queues); + if (error) { + device_printf(sc->dev, "Unable to assign VF Rx queues: %s\n", + ice_err_str(error)); + goto release_vsi; + } + + vsi->max_frame_size = ICE_MAX_FRAME_SIZE; + + /* Allocate queue structure memory */ + vsi->tx_queues = (struct ice_tx_queue *) + malloc(sizeof(struct ice_tx_queue) * vsi->num_tx_queues, M_ICE, + M_NOWAIT | M_ZERO); + if (!vsi->tx_queues) { + device_printf(sc->dev, "VF-%d: Unable to allocate Tx queue memory\n", + vfnum); + error = ENOMEM; + goto release_vsi; + } + for (i = 0, txq = vsi->tx_queues; i < vsi->num_tx_queues; i++, txq++) { + txq->me = i; + txq->vsi = vsi; + } + + /* Allocate queue structure memory */ + vsi->rx_queues = (struct ice_rx_queue *) + malloc(sizeof(struct ice_rx_queue) * vsi->num_rx_queues, M_ICE, + M_NOWAIT | M_ZERO); + if (!vsi->rx_queues) { + device_printf(sc->dev, "VF-%d: Unable to allocate Rx queue memory\n", + vfnum); + error = ENOMEM; + goto free_txqs; + } + for (i = 0, rxq = vsi->rx_queues; i < vsi->num_rx_queues; i++, rxq++) { + rxq->me = i; + rxq->vsi = vsi; + } + + /* Allocate space to store the IRQ vector data */ + vf->num_irq_vectors = vf_num_queues + 1; + vf->tx_irqvs = (struct ice_irq_vector *) + malloc(sizeof(struct ice_irq_vector) * (vf->num_irq_vectors), + M_ICE, M_NOWAIT); + if (!vf->tx_irqvs) { + device_printf(sc->dev, + "Unable to allocate TX irqv memory for VF-%d's %d vectors\n", + vfnum, vf->num_irq_vectors); + error = ENOMEM; + goto free_rxqs; + } + vf->rx_irqvs = (struct ice_irq_vector *) + malloc(sizeof(struct ice_irq_vector) * (vf->num_irq_vectors), + M_ICE, M_NOWAIT); + if (!vf->rx_irqvs) { + device_printf(sc->dev, + "Unable to allocate RX irqv memory for VF-%d's %d vectors\n", + vfnum, vf->num_irq_vectors); + error = ENOMEM; + goto free_txirqvs; + } + + /* Assign VF interrupts from PF space */ + if (!(vf->vf_imap = + (u16 *)malloc(sizeof(u16) * vf->num_irq_vectors, + M_ICE, M_NOWAIT))) { + device_printf(dev, "Unable to allocate VF-%d imap memory\n", vfnum); + error = ENOMEM; + goto free_rxirqvs; + } + error = ice_resmgr_assign_contiguous(&sc->dev_imgr, vf->vf_imap, vf->num_irq_vectors); + if (error) { + device_printf(dev, "Unable to assign VF-%d interrupt mapping: %s\n", + vfnum, ice_err_str(error)); + goto free_imap; + } + + if (nvlist_exists_binary(params, "mac-addr")) { + mac = nvlist_get_binary(params, "mac-addr", &size); + memcpy(vf->mac, mac, ETHER_ADDR_LEN); + + if (nvlist_get_bool(params, "allow-set-mac")) + vf->vf_flags |= VF_FLAG_SET_MAC_CAP; + } else + /* + * If the administrator has not specified a MAC address then + * we must allow the VF to choose one. + */ + vf->vf_flags |= VF_FLAG_SET_MAC_CAP; + + if (nvlist_get_bool(params, "mac-anti-spoof")) + vf->vf_flags |= VF_FLAG_MAC_ANTI_SPOOF; + + if (nvlist_get_bool(params, "allow-promisc")) + vf->vf_flags |= VF_FLAG_PROMISC_CAP; + + vsi->mirror_src_vsi = nvlist_get_number(params, "mirror-src-vsi"); + + vf->vlan_limit = nvlist_get_number(params, "max-vlan-allowed"); + vf->mac_filter_limit = nvlist_get_number(params, "max-mac-filters"); + + vf->vf_flags |= VF_FLAG_VLAN_CAP; + + /* Create and setup VSI in HW */ + error = ice_initialize_vsi(vsi); + if (error) { + device_printf(sc->dev, "Unable to initialize VF %d VSI: %s\n", + vfnum, ice_err_str(error)); + goto release_imap; + } + + /* Add the broadcast address */ + error = ice_add_vsi_mac_filter(vsi, broadcastaddr); + if (error) { + device_printf(sc->dev, "Unable to add broadcast filter VF %d VSI: %s\n", + vfnum, ice_err_str(error)); + goto release_imap; + } + + ice_iov_ready_vf(sc, vf); + + return (0); + +release_imap: + ice_resmgr_release_map(&sc->dev_imgr, vf->vf_imap, + vf->num_irq_vectors); +free_imap: + free(vf->vf_imap, M_ICE); + vf->vf_imap = NULL; +free_rxirqvs: + free(vf->rx_irqvs, M_ICE); + vf->rx_irqvs = NULL; +free_txirqvs: + free(vf->tx_irqvs, M_ICE); + vf->tx_irqvs = NULL; +free_rxqs: + free(vsi->rx_queues, M_ICE); + vsi->rx_queues = NULL; +free_txqs: + free(vsi->tx_queues, M_ICE); + vsi->tx_queues = NULL; +release_vsi: + ice_release_vsi(vsi); + vf->vsi = NULL; + return (error); +} + +/** + * ice_iov_uninit - Called by the OS when VFs are destroyed + * @sc: device softc structure + */ +void +ice_iov_uninit(struct ice_softc *sc) +{ + struct ice_vf *vf; + struct ice_vsi *vsi; + + /* Release per-VF resources */ + for (int i = 0; i < sc->num_vfs; i++) { + vf = &sc->vfs[i]; + vsi = vf->vsi; + + /* Free VF interrupt reservation */ + if (vf->vf_imap) { + free(vf->vf_imap, M_ICE); + vf->vf_imap = NULL; + } + + /* Free queue interrupt mapping trackers */ + if (vf->tx_irqvs) { + free(vf->tx_irqvs, M_ICE); + vf->tx_irqvs = NULL; + } + if (vf->rx_irqvs) { + free(vf->rx_irqvs, M_ICE); + vf->rx_irqvs = NULL; + } + + if (!vsi) + continue; + + /* Free VSI queues */ + if (vsi->tx_queues) { + free(vsi->tx_queues, M_ICE); + vsi->tx_queues = NULL; + } + if (vsi->rx_queues) { + free(vsi->rx_queues, M_ICE); + vsi->rx_queues = NULL; + } + + ice_release_vsi(vsi); + vf->vsi = NULL; + } + + /* Release memory used for VF tracking */ + if (sc->vfs) { + free(sc->vfs, M_ICE); + sc->vfs = NULL; + } + sc->num_vfs = 0; +} + +/** + * ice_iov_handle_vflr - Process VFLR event + * @sc: device softc structure + * + * Identifys which VFs have been reset and re-configure + * them. + */ +void +ice_iov_handle_vflr(struct ice_softc *sc) +{ + struct ice_hw *hw = &sc->hw; + struct ice_vf *vf; + u32 reg, reg_idx, bit_idx; + + for (int i = 0; i < sc->num_vfs; i++) { + vf = &sc->vfs[i]; + + reg_idx = (hw->func_caps.vf_base_id + vf->vf_num) / 32; + bit_idx = (hw->func_caps.vf_base_id + vf->vf_num) % 32; + reg = rd32(hw, GLGEN_VFLRSTAT(reg_idx)); + if (reg & BIT(bit_idx)) + ice_reset_vf(sc, vf, false); + } +} + +/** + * ice_iov_ready_vf - Setup VF interrupts and mark it as ready + * @sc: device softc structure + * @vf: driver's VF structure for the VF to update + * + * Clears VF reset triggering bit, sets up the PF<->VF interrupt + * mapping and marks the VF as active in the HW so that the VF + * driver can use it. + */ +static void +ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf) +{ + struct ice_hw *hw = &sc->hw; + u32 reg; + + /* Clear the triggering bit */ + reg = rd32(hw, VPGEN_VFRTRIG(vf->vf_num)); + reg &= ~VPGEN_VFRTRIG_VFSWR_M; + wr32(hw, VPGEN_VFRTRIG(vf->vf_num), reg); + + /* Setup VF interrupt allocation and mapping */ + ice_iov_setup_intr_mapping(sc, vf); + + /* Indicate to the VF that reset is done */ + wr32(hw, VFGEN_RSTAT(vf->vf_num), VIRTCHNL_VFR_VFACTIVE); + + ice_flush(hw); +} + +/** + * ice_reset_vf - Perform a hardware reset (VFR) on a VF + * @sc: device softc structure + * @vf: driver's VF structure for VF to be reset + * @trigger_vflr: trigger a reset or only handle already executed reset + * + * Performs a VFR for the given VF. This function busy waits until the + * reset completes in the HW, notifies the VF that the reset is done + * by setting a bit in a HW register, then returns. + * + * @remark This also sets up the PF<->VF interrupt mapping and allocations in + * the hardware after the hardware reset is finished, via + * ice_iov_setup_intr_mapping() + */ +static void +ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf, bool trigger_vflr) +{ + u16 global_vf_num, reg_idx, bit_idx; + struct ice_hw *hw = &sc->hw; + int status; + u32 reg; + int i; + + global_vf_num = vf->vf_num + hw->func_caps.vf_base_id; + + if (trigger_vflr) { + reg = rd32(hw, VPGEN_VFRTRIG(vf->vf_num)); + reg |= VPGEN_VFRTRIG_VFSWR_M; + wr32(hw, VPGEN_VFRTRIG(vf->vf_num), reg); + } + + /* clear the VFLR bit for the VF in a GLGEN_VFLRSTAT register */ + reg_idx = (global_vf_num) / 32; + bit_idx = (global_vf_num) % 32; + wr32(hw, GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); + ice_flush(hw); + + /* Wait until there are no pending PCI transactions */ + wr32(hw, PF_PCI_CIAA, + ICE_PCIE_DEV_STATUS | (global_vf_num << PF_PCI_CIAA_VF_NUM_S)); + + for (i = 0; i < ICE_PCI_CIAD_WAIT_COUNT; i++) { + reg = rd32(hw, PF_PCI_CIAD); + if (!(reg & PCIEM_STA_TRANSACTION_PND)) + break; + + DELAY(ICE_PCI_CIAD_WAIT_DELAY_US); + } + if (i == ICE_PCI_CIAD_WAIT_COUNT) + device_printf(sc->dev, + "VF-%d PCI transactions stuck\n", vf->vf_num); + + /* Disable TX queues, which is required during VF reset */ + status = ice_dis_vsi_txq(hw->port_info, vf->vsi->idx, 0, 0, NULL, NULL, + NULL, ICE_VF_RESET, vf->vf_num, NULL); + if (status) + device_printf(sc->dev, + "%s: Failed to disable LAN Tx queues: err %s aq_err %s\n", + __func__, ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + + /* Then check for the VF reset to finish in HW */ + for (i = 0; i < ICE_VPGEN_VFRSTAT_WAIT_COUNT; i++) { + reg = rd32(hw, VPGEN_VFRSTAT(vf->vf_num)); + if ((reg & VPGEN_VFRSTAT_VFRD_M)) + break; + + DELAY(ICE_VPGEN_VFRSTAT_WAIT_DELAY_US); + } + if (i == ICE_VPGEN_VFRSTAT_WAIT_COUNT) + device_printf(sc->dev, + "VF-%d Reset is stuck\n", vf->vf_num); + + ice_iov_ready_vf(sc, vf); +} + +/** + * ice_vc_get_vf_res_msg - Handle VIRTCHNL_OP_GET_VF_RESOURCES msg from VF + * @sc: device private structure + * @vf: VF tracking structure + * @msg_buf: raw message buffer from the VF + * + * Receives a message from the VF listing its supported capabilities, and + * replies to the VF with information about what resources the PF has + * allocated for the VF. + * + * @remark This always replies to the VF with a success status; it does not + * fail. It's up to the VF driver to reject or complain about the PF's response. + */ +static void +ice_vc_get_vf_res_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_vf_resource *vf_res; + struct virtchnl_vsi_resource *vsi_res; + u16 vf_res_len; + u32 vf_caps; + + /* XXX: Only support one VSI per VF, so this size doesn't need adjusting */ + vf_res_len = sizeof(struct virtchnl_vf_resource); + vf_res = (struct virtchnl_vf_resource *)malloc(vf_res_len, M_ICE, + M_WAITOK | M_ZERO); + + vf_res->num_vsis = 1; + vf_res->num_queue_pairs = vf->vsi->num_tx_queues; + vf_res->max_vectors = vf_res->num_queue_pairs + 1; + + vf_res->rss_key_size = ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE; + vf_res->rss_lut_size = ICE_VSIQF_HLUT_ARRAY_SIZE; + vf_res->max_mtu = 0; + + vf_res->vf_cap_flags = VF_BASE_MODE_OFFLOADS; + if (msg_buf != NULL) { + vf_caps = *((u32 *)(msg_buf)); + + if (vf_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) + vf_res->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED; + + if (vf_caps & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) + vf_res->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_WB_ON_ITR; + } + + vsi_res = &vf_res->vsi_res[0]; + vsi_res->vsi_id = vf->vsi->idx; + vsi_res->num_queue_pairs = vf->vsi->num_tx_queues; + vsi_res->vsi_type = VIRTCHNL_VSI_SRIOV; + vsi_res->qset_handle = 0; + if (!ETHER_IS_ZERO(vf->mac)) + memcpy(vsi_res->default_mac_addr, vf->mac, ETHER_ADDR_LEN); + + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_GET_VF_RESOURCES, + VIRTCHNL_STATUS_SUCCESS, (u8 *)vf_res, vf_res_len, NULL); + + free(vf_res, M_ICE); +} + +/** + * ice_vc_version_msg - Handle VIRTCHNL_OP_VERSION msg from VF + * @sc: device private structure + * @vf: VF tracking structure + * @msg_buf: raw message buffer from the VF + * + * Receives a version message from the VF, and responds to the VF with + * the version number that the PF will use. + * + * @remark This always replies to the VF with a success status; it does not + * fail. + */ +static void +ice_vc_version_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct virtchnl_version_info *recv_vf_version; + struct ice_hw *hw = &sc->hw; + device_t dev = sc->dev; + + recv_vf_version = (struct virtchnl_version_info *)msg_buf; + + /* VFs running the 1.0 API expect to get 1.0 back */ + if (VF_IS_V10(recv_vf_version)) { + vf->version.major = 1; + vf->version.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS; + } else { + vf->version.major = VIRTCHNL_VERSION_MAJOR; + vf->version.minor = VIRTCHNL_VERSION_MINOR; + + if ((recv_vf_version->major != VIRTCHNL_VERSION_MAJOR) || + (recv_vf_version->minor != VIRTCHNL_VERSION_MINOR)) + device_printf(dev, + "%s: VF-%d requested version (%d.%d) differs from PF version (%d.%d)\n", + __func__, vf->vf_num, + recv_vf_version->major, recv_vf_version->minor, + VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR); + } + + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_VERSION, + VIRTCHNL_STATUS_SUCCESS, (u8 *)&vf->version, sizeof(vf->version), + NULL); +} + +/** + * ice_vf_validate_mac - Validate MAC address before adding it + * @vf: VF tracking structure + * @addr: MAC address to validate + * + * Validate a MAC address before adding it to a VF during the handling + * of a VIRTCHNL_OP_ADD_ETH_ADDR operation. Notably, this also checks if + * the VF is allowed to set its own arbitrary MAC addresses. + * + * Returns 0 if MAC address is valid for the given vf + */ +static int +ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr) +{ + + if (ETHER_IS_ZERO(addr) || ETHER_IS_BROADCAST(addr)) + return (EINVAL); + + /* + * If the VF is not allowed to change its MAC address, don't let it + * set a MAC filter for an address that is not a multicast address and + * is not its assigned MAC. + */ + if (!(vf->vf_flags & VF_FLAG_SET_MAC_CAP) && + !(ETHER_IS_MULTICAST(addr) || !bcmp(addr, vf->mac, ETHER_ADDR_LEN))) + return (EPERM); + + return (0); +} + +/** + * ice_vc_add_eth_addr_msg - Handle VIRTCHNL_OP_ADD_ETH_ADDR msg from VF + * @sc: device private structure + * @vf: VF tracking structure + * @msg_buf: raw message buffer from the VF + * + * Receives a list of MAC addresses from the VF and adds those addresses + * to the VSI's filter list. + */ +static void +ice_vc_add_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct virtchnl_ether_addr_list *addr_list; + struct ice_hw *hw = &sc->hw; + u16 added_addr_cnt = 0; + int error = 0; + + addr_list = (struct virtchnl_ether_addr_list *)msg_buf; + + if (addr_list->num_elements > + (vf->mac_filter_limit - vf->mac_filter_cnt)) { + v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; + goto done; + } + + for (int i = 0; i < addr_list->num_elements; i++) { + u8 *addr = addr_list->list[i].addr; + + /* The type flag is currently ignored; every MAC address is + * treated as the LEGACY type + */ + + error = ice_vf_validate_mac(vf, addr); + if (error == EPERM) { + device_printf(sc->dev, + "%s: VF-%d: Not permitted to add MAC addr for VSI %d\n", + __func__, vf->vf_num, vf->vsi->idx); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + continue; + } else if (error) { + device_printf(sc->dev, + "%s: VF-%d: Did not add invalid MAC addr for VSI %d\n", + __func__, vf->vf_num, vf->vsi->idx); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + continue; + } + + error = ice_add_vsi_mac_filter(vf->vsi, addr); + if (error) { + device_printf(sc->dev, + "%s: VF-%d: Error adding MAC addr for VSI %d\n", + __func__, vf->vf_num, vf->vsi->idx); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + continue; + } + /* Don't count VF's MAC against its MAC filter limit */ + if (memcmp(addr, vf->mac, ETHER_ADDR_LEN)) + added_addr_cnt++; + } + + vf->mac_filter_cnt += added_addr_cnt; + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ADD_ETH_ADDR, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_del_eth_addr_msg - Handle VIRTCHNL_OP_DEL_ETH_ADDR msg from VF + * @sc: device private structure + * @vf: VF tracking structure + * @msg_buf: raw message buffer from the VF + * + * Receives a list of MAC addresses from the VF and removes those addresses + * from the VSI's filter list. + */ +static void +ice_vc_del_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct virtchnl_ether_addr_list *addr_list; + struct ice_hw *hw = &sc->hw; + u16 deleted_addr_cnt = 0; + int error = 0; + + addr_list = (struct virtchnl_ether_addr_list *)msg_buf; + + for (int i = 0; i < addr_list->num_elements; i++) { + error = ice_remove_vsi_mac_filter(vf->vsi, addr_list->list[i].addr); + if (error) { + device_printf(sc->dev, + "%s: VF-%d: Error removing MAC addr for VSI %d\n", + __func__, vf->vf_num, vf->vsi->idx); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + continue; + } + /* Don't count VF's MAC against its MAC filter limit */ + if (memcmp(addr_list->list[i].addr, vf->mac, ETHER_ADDR_LEN)) + deleted_addr_cnt++; + } + + if (deleted_addr_cnt >= vf->mac_filter_cnt) + vf->mac_filter_cnt = 0; + else + vf->mac_filter_cnt -= deleted_addr_cnt; + + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DEL_ETH_ADDR, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_add_vlan_msg - Handle VIRTCHNL_OP_ADD_VLAN msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Adds the VLANs in msg_buf to the VF's VLAN filter list. + */ +static void +ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_vlan_filter_list *vlan_list; + int status = 0; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + + vlan_list = (struct virtchnl_vlan_filter_list *)msg_buf; + + if (vlan_list->vsi_id != vsi->idx) { + device_printf(sc->dev, + "VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + vf->vf_num, vsi->idx, vlan_list->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + if (vlan_list->num_elements > (vf->vlan_limit - vf->vlan_cnt)) { + v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; + goto done; + } + + status = ice_add_vlan_hw_filters(vsi, vlan_list->vlan_id, + vlan_list->num_elements); + if (status) { + device_printf(sc->dev, + "VF-%d: Failure adding VLANs to VSI %d, err %s aq_err %s\n", + vf->vf_num, vsi->idx, ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + + vf->vlan_cnt += vlan_list->num_elements; + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ADD_VLAN, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_del_vlan_msg - Handle VIRTCHNL_OP_DEL_VLAN msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Removes the VLANs in msg_buf from the VF's VLAN filter list. + */ +static void +ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_vlan_filter_list *vlan_list; + int status = 0; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + + vlan_list = (struct virtchnl_vlan_filter_list *)msg_buf; + + if (vlan_list->vsi_id != vsi->idx) { + device_printf(sc->dev, + "VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + vf->vf_num, vsi->idx, vlan_list->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + status = ice_remove_vlan_hw_filters(vsi, vlan_list->vlan_id, + vlan_list->num_elements); + if (status) { + device_printf(sc->dev, + "VF-%d: Failure deleting VLANs from VSI %d, err %s aq_err %s\n", + vf->vf_num, vsi->idx, ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + + if (vlan_list->num_elements >= vf->vlan_cnt) + vf->vlan_cnt = 0; + else + vf->vlan_cnt -= vlan_list->num_elements; + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DEL_VLAN, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_validate_ring_len - Check to see if a descriptor ring length is valid + * @ring_len: length of ring + * + * Check whether a ring size value is valid. + * + * @returns true if given ring size is valid + */ +static bool +ice_vc_isvalid_ring_len(u16 ring_len) +{ + return (ring_len >= ICE_MIN_DESC_COUNT && + ring_len <= ICE_MAX_DESC_COUNT && + !(ring_len % ICE_DESC_COUNT_INCR)); +} + +/** + * ice_vc_cfg_vsi_qs_msg - Handle VIRTCHNL_OP_CONFIG_VSI_QUEUES msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + */ +static void +ice_vc_cfg_vsi_qs_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + device_t dev = sc->dev; + struct ice_hw *hw = &sc->hw; + struct virtchnl_vsi_queue_config_info *vqci; + struct virtchnl_queue_pair_info *vqpi; + enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + struct ice_tx_queue *txq; + struct ice_rx_queue *rxq; + int i, error = 0; + + vqci = (struct virtchnl_vsi_queue_config_info *)msg_buf; + + if (vqci->num_queue_pairs > vf->vsi->num_tx_queues && + vqci->num_queue_pairs > vf->vsi->num_rx_queues) { + status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + ice_vsi_disable_tx(vf->vsi); + ice_control_all_rx_queues(vf->vsi, false); + + /* + * Clear TX and RX queues config in case VF + * requests different number of queues. + */ + for (i = 0; i < vsi->num_tx_queues; i++) { + txq = &vsi->tx_queues[i]; + + txq->desc_count = 0; + txq->tx_paddr = 0; + txq->tc = 0; + } + + for (i = 0; i < vsi->num_rx_queues; i++) { + rxq = &vsi->rx_queues[i]; + + rxq->desc_count = 0; + rxq->rx_paddr = 0; + } + + vqpi = vqci->qpair; + for (i = 0; i < vqci->num_queue_pairs; i++, vqpi++) { + /* Initial parameter validation */ + if (vqpi->txq.vsi_id != vf->vsi->idx || + vqpi->rxq.vsi_id != vf->vsi->idx || + vqpi->txq.queue_id != vqpi->rxq.queue_id || + vqpi->txq.headwb_enabled || + vqpi->rxq.splithdr_enabled || + vqpi->rxq.crc_disable || + !(ice_vc_isvalid_ring_len(vqpi->txq.ring_len)) || + !(ice_vc_isvalid_ring_len(vqpi->rxq.ring_len))) { + status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + /* Copy parameters into VF's queue/VSI structs */ + txq = &vsi->tx_queues[vqpi->txq.queue_id]; + + txq->desc_count = vqpi->txq.ring_len; + txq->tx_paddr = vqpi->txq.dma_ring_addr; + txq->q_handle = vqpi->txq.queue_id; + txq->tc = 0; + + rxq = &vsi->rx_queues[vqpi->rxq.queue_id]; + + rxq->desc_count = vqpi->rxq.ring_len; + rxq->rx_paddr = vqpi->rxq.dma_ring_addr; + vsi->mbuf_sz = vqpi->rxq.databuffer_size; + } + + /* Configure TX queues in HW */ + error = ice_cfg_vsi_for_tx(vsi); + if (error) { + device_printf(dev, + "VF-%d: Unable to configure VSI for Tx: %s\n", + vf->vf_num, ice_err_str(error)); + status = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; + goto done; + } + + /* Configure RX queues in HW */ + error = ice_cfg_vsi_for_rx(vsi); + if (error) { + device_printf(dev, + "VF-%d: Unable to configure VSI for Rx: %s\n", + vf->vf_num, ice_err_str(error)); + status = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; + ice_vsi_disable_tx(vsi); + goto done; + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_CONFIG_VSI_QUEUES, + status, NULL, 0, NULL); +} + +/** + * ice_vc_cfg_rss_key_msg - Handle VIRTCHNL_OP_CONFIG_RSS_KEY msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Sets the RSS key for the given VF, using the contents of msg_buf. + */ +static void +ice_vc_cfg_rss_key_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_aqc_get_set_rss_keys keydata = + { .standard_rss_key = {0}, .extended_hash_key = {0} }; + struct ice_hw *hw = &sc->hw; + struct virtchnl_rss_key *vrk; + int status = 0; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + + vrk = (struct virtchnl_rss_key *)msg_buf; + + if (vrk->vsi_id != vsi->idx) { + device_printf(sc->dev, + "VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + vf->vf_num, vsi->idx, vrk->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + if ((vrk->key_len > + (ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE + + ICE_AQC_GET_SET_RSS_KEY_DATA_HASH_KEY_SIZE)) || + vrk->key_len == 0) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + memcpy(&keydata, vrk->key, vrk->key_len); + + status = ice_aq_set_rss_key(hw, vsi->idx, &keydata); + if (status) { + device_printf(sc->dev, + "ice_aq_set_rss_key status %s, error %s\n", + ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_CONFIG_RSS_KEY, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_cfg_rss_lut_msg - Handle VIRTCHNL_OP_CONFIG_RSS_LUT msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Adds the LUT from the VF in msg_buf to the PF via an admin queue call. + */ +static void +ice_vc_cfg_rss_lut_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_rss_lut *vrl; + int status = 0; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_aq_get_set_rss_lut_params lut_params = {}; + struct ice_vsi *vsi = vf->vsi; + + vrl = (struct virtchnl_rss_lut *)msg_buf; + + if (vrl->vsi_id != vsi->idx) { + device_printf(sc->dev, + "VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + vf->vf_num, vsi->idx, vrl->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + if (vrl->lut_entries > ICE_VSIQF_HLUT_ARRAY_SIZE) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + lut_params.vsi_handle = vsi->idx; + lut_params.lut_size = vsi->rss_table_size; + lut_params.lut_type = vsi->rss_lut_type; + lut_params.lut = vrl->lut; + lut_params.global_lut_id = 0; + + status = ice_aq_set_rss_lut(hw, &lut_params); + if (status) { + device_printf(sc->dev, + "VF-%d: Cannot set RSS lut, err %s aq_err %s\n", + vf->vf_num, ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_CONFIG_RSS_LUT, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_set_rss_hena_msg - Handle VIRTCHNL_OP_SET_RSS_HENA msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Adds the VF's hena (hash enable) bits as flow types to the PF's RSS flow + * type list. + */ +static void +ice_vc_set_rss_hena_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_rss_hena *vrh; + int status = 0; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + + MPASS(vsi != NULL); + + vrh = (struct virtchnl_rss_hena *)msg_buf; + + /* + * Remove existing configuration to make sure only requested + * config is applied and allow VFs to disable RSS completly. + */ + status = ice_rem_vsi_rss_cfg(hw, vsi->idx); + if (vrh->hena) { + /* + * Problem with removing config is not fatal, when new one + * is requested. Warn about it but try to apply new config + * anyway. + */ + if (status) + device_printf(sc->dev, + "ice_rem_vsi_rss_cfg status %s, error %s\n", + ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + status = ice_add_avf_rss_cfg(hw, vsi->idx, vrh->hena); + if (status) + device_printf(sc->dev, + "ice_add_avf_rss_cfg status %s, error %s\n", + ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + } + v_status = ice_iov_err_to_virt_err(status); + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_SET_RSS_HENA, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_enable_queues_msg - Handle VIRTCHNL_OP_ENABLE_QUEUES msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Enables VF queues selected in msg_buf for Tx/Rx traffic. + * + * @remark Only actually operates on Rx queues; Tx queues are enabled in + * CONFIG_VSI_QUEUES message handler. + */ +static void +ice_vc_enable_queues_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_queue_select *vqs; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + int bit, error = 0; + + vqs = (struct virtchnl_queue_select *)msg_buf; + + if (vqs->vsi_id != vsi->idx) { + device_printf(sc->dev, + "%s: VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + __func__, vf->vf_num, vsi->idx, vqs->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + if (!vqs->rx_queues && !vqs->tx_queues) { + device_printf(sc->dev, + "%s: VF-%d: message queue masks are empty\n", + __func__, vf->vf_num); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + /* Validate rx_queue mask */ + bit = fls(vqs->rx_queues); + if (bit > vsi->num_rx_queues) { + device_printf(sc->dev, + "%s: VF-%d: message's rx_queues map (0x%08x) has invalid bit set (%d)\n", + __func__, vf->vf_num, vqs->rx_queues, bit); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + /* Tx ring enable is handled in an earlier message. */ + for_each_set_bit(bit, &vqs->rx_queues, 32) { + error = ice_control_rx_queue(vsi, bit, true); + if (error) { + device_printf(sc->dev, + "Unable to enable Rx ring %d for receive: %s\n", + bit, ice_err_str(error)); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ENABLE_QUEUES, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_disable_queues_msg - Handle VIRTCHNL_OP_DISABLE_QUEUES msg + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Disables all VF queues for the VF's VSI. + * + * @remark Unlike the ENABLE_QUEUES handler, this operates on both + * Tx and Rx queues + */ +static void +ice_vc_disable_queues_msg(struct ice_softc *sc, struct ice_vf *vf, + u8 *msg_buf __unused) +{ + struct ice_hw *hw = &sc->hw; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + int error = 0; + + error = ice_control_all_rx_queues(vsi, false); + if (error) { + device_printf(sc->dev, + "Unable to disable Rx rings for transmit: %s\n", + ice_err_str(error)); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + error = ice_vsi_disable_tx(vsi); + if (error) { + /* Already prints an error message */ + v_status = VIRTCHNL_STATUS_ERR_PARAM; + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DISABLE_QUEUES, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_cfg_irq_map_msg - Handle VIRTCHNL_OP_CFG_IRQ_MAP msg from VF + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Configures the interrupt vectors described in the message in msg_buf. The + * VF needs to send this message during init, so that queues can be allowed + * to generate interrupts. + */ +static void +ice_vc_cfg_irq_map_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ +#define ICE_VIRTCHNL_QUEUE_MAP_SIZE 16 + struct ice_hw *hw = &sc->hw; + struct virtchnl_irq_map_info *vimi; + struct virtchnl_vector_map *vvm; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + struct ice_vsi *vsi = vf->vsi; + u16 vector; + + vimi = (struct virtchnl_irq_map_info *)msg_buf; + + if (vimi->num_vectors > vf->num_irq_vectors) { + device_printf(sc->dev, + "%s: VF-%d: message has more vectors (%d) than configured for VF (%d)\n", + __func__, vf->vf_num, vimi->num_vectors, vf->num_irq_vectors); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + vvm = vimi->vecmap; + /* Save off information from message */ + for (int i = 0; i < vimi->num_vectors; i++, vvm++) { + struct ice_tx_queue *txq; + struct ice_rx_queue *rxq; + int bit; + + if (vvm->vsi_id != vf->vsi->idx) { + device_printf(sc->dev, + "%s: VF-%d: message's VSI ID (%d) does not match VF's (%d) for vector %d\n", + __func__, vf->vf_num, vvm->vsi_id, vf->vsi->idx, i); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + /* vvm->vector_id is relative to VF space */ + vector = vvm->vector_id; + + if (vector >= vf->num_irq_vectors) { + device_printf(sc->dev, + "%s: VF-%d: message's vector ID (%d) is greater than VF's max ID (%d)\n", + __func__, vf->vf_num, vector, vf->num_irq_vectors - 1); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + /* The Misc/Admin Queue vector doesn't need mapping */ + if (vector == 0) + continue; + + /* coverity[address_of] */ + for_each_set_bit(bit, &vvm->txq_map, ICE_VIRTCHNL_QUEUE_MAP_SIZE) { + if (bit >= vsi->num_tx_queues) { + device_printf(sc->dev, + "%s: VF-%d: txq map has invalid bit set\n", + __func__, vf->vf_num); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + vf->tx_irqvs[vector].me = vector; + + txq = &vsi->tx_queues[bit]; + txq->irqv = &vf->tx_irqvs[vector]; + txq->itr_idx = vvm->txitr_idx; + } + /* coverity[address_of] */ + for_each_set_bit(bit, &vvm->rxq_map, ICE_VIRTCHNL_QUEUE_MAP_SIZE) { + if (bit >= vsi->num_rx_queues) { + device_printf(sc->dev, + "%s: VF-%d: rxq map has invalid bit set\n", + __func__, vf->vf_num); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + vf->rx_irqvs[vector].me = vector; + + rxq = &vsi->rx_queues[bit]; + rxq->irqv = &vf->rx_irqvs[vector]; + rxq->itr_idx = vvm->rxitr_idx; + } + } + + /* Write to T/RQCTL registers to actually map vectors to queues */ + for (int i = 0; i < vf->vsi->num_rx_queues; i++) + if (vsi->rx_queues[i].irqv != NULL) + ice_configure_rxq_interrupt(hw, vsi->rx_qmap[i], + vsi->rx_queues[i].irqv->me, vsi->rx_queues[i].itr_idx); + + for (int i = 0; i < vf->vsi->num_tx_queues; i++) + if (vsi->tx_queues[i].irqv != NULL) + ice_configure_txq_interrupt(hw, vsi->tx_qmap[i], + vsi->tx_queues[i].irqv->me, vsi->tx_queues[i].itr_idx); + + ice_flush(hw); + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_CONFIG_IRQ_MAP, + v_status, NULL, 0, NULL); +} + +/** + * ice_eth_stats_to_virtchnl_eth_stats - Convert stats for virtchnl + * @istats: VSI stats from HW to convert + * @vstats: stats struct to copy to + * + * This function copies all known stats in struct virtchnl_eth_stats from the + * input struct ice_eth_stats to an output struct virtchnl_eth_stats. + * + * @remark These two structure types currently have the same definition up to + * the size of struct virtchnl_eth_stats (on FreeBSD), but that could change + * in the future. + */ +static void +ice_eth_stats_to_virtchnl_eth_stats(struct ice_eth_stats *istats, + struct virtchnl_eth_stats *vstats) +{ + vstats->rx_bytes = istats->rx_bytes; + vstats->rx_unicast = istats->rx_unicast; + vstats->rx_multicast = istats->rx_multicast; + vstats->rx_broadcast = istats->rx_broadcast; + vstats->rx_discards = istats->rx_discards; + vstats->rx_unknown_protocol = istats->rx_unknown_protocol; + vstats->tx_bytes = istats->tx_bytes; + vstats->tx_unicast = istats->tx_unicast; + vstats->tx_multicast = istats->tx_multicast; + vstats->tx_broadcast = istats->tx_broadcast; + vstats->tx_discards = istats->tx_discards; + vstats->tx_errors = istats->tx_errors; +} + +/** + * ice_vc_get_stats_msg - Handle VIRTCHNL_OP_GET_STATS msg + * @sc: device private structure + * @vf: VF tracking structure + * @msg_buf: raw message buffer from the VF + * + * Updates the VF's VSI stats and sends those stats back to the VF. + */ +static void +ice_vc_get_stats_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct virtchnl_queue_select *vqs; + struct virtchnl_eth_stats stats; + struct ice_vsi *vsi = vf->vsi; + struct ice_hw *hw = &sc->hw; + + vqs = (struct virtchnl_queue_select *)msg_buf; + + if (vqs->vsi_id != vsi->idx) { + device_printf(sc->dev, + "%s: VF-%d: message has invalid VSI ID %d (VF has VSI ID %d)\n", + __func__, vf->vf_num, vqs->vsi_id, vsi->idx); + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_GET_STATS, + VIRTCHNL_STATUS_ERR_PARAM, NULL, 0, NULL); + } + + ice_update_vsi_hw_stats(vf->vsi); + ice_eth_stats_to_virtchnl_eth_stats(&vsi->hw_stats.cur, &stats); + + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_GET_STATS, + VIRTCHNL_STATUS_SUCCESS, (u8 *)&stats, + sizeof(struct virtchnl_eth_stats), NULL); +} + +/** + * ice_vc_cfg_promisc_mode_msg - Handle VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE + * @sc: PF's softc structure + * @vf: VF tracking structure + * @msg_buf: message buffer from VF + * + * Configures the promiscuous modes for the given VSI in msg_buf. + */ +static void +ice_vc_cfg_promisc_mode_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) +{ + struct ice_hw *hw = &sc->hw; + struct virtchnl_promisc_info *vpi; + enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; + int status = 0; + struct ice_vsi *vsi = vf->vsi; + ice_declare_bitmap(old_promisc_mask, ICE_PROMISC_MAX); + ice_declare_bitmap(req_promisc_mask, ICE_PROMISC_MAX); + ice_declare_bitmap(clear_promisc_mask, ICE_PROMISC_MAX); + ice_declare_bitmap(set_promisc_mask, ICE_PROMISC_MAX); + ice_declare_bitmap(old_req_xor_mask, ICE_PROMISC_MAX); + u16 vid; + + vpi = (struct virtchnl_promisc_info *)msg_buf; + + /* Check to see if VF has permission to configure promiscuous mode */ + if (!(vf->vf_flags & VF_FLAG_PROMISC_CAP)) { + device_printf(sc->dev, + "VF-%d: attempted to configure promiscuous mode\n", + vf->vf_num); + /* Don't reply to VF with an error */ + goto done; + } + + if (vpi->vsi_id != vsi->idx) { + device_printf(sc->dev, + "VF-%d: Message has invalid VSI ID (expected %d, got %d)\n", + vf->vf_num, vsi->idx, vpi->vsi_id); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + } + + if (vpi->flags & ~ICE_VIRTCHNL_VALID_PROMISC_FLAGS) { + device_printf(sc->dev, + "VF-%d: Message has invalid promiscuous flags set (valid 0x%02x, got 0x%02x)\n", + vf->vf_num, ICE_VIRTCHNL_VALID_PROMISC_FLAGS, + vpi->flags); + v_status = VIRTCHNL_STATUS_ERR_PARAM; + goto done; + + } + + ice_zero_bitmap(req_promisc_mask, ICE_PROMISC_MAX); + /* Convert virtchnl flags to ice AQ promiscuous mode flags */ + if (vpi->flags & FLAG_VF_UNICAST_PROMISC) { + ice_set_bit(ICE_PROMISC_UCAST_TX, req_promisc_mask); + ice_set_bit(ICE_PROMISC_UCAST_RX, req_promisc_mask); + } + if (vpi->flags & FLAG_VF_MULTICAST_PROMISC) { + ice_set_bit(ICE_PROMISC_MCAST_TX, req_promisc_mask); + ice_set_bit(ICE_PROMISC_MCAST_RX, req_promisc_mask); + } + + status = ice_get_vsi_promisc(hw, vsi->idx, old_promisc_mask, &vid); + if (status) { + device_printf(sc->dev, + "VF-%d: Failed to get promiscuous mode mask for VSI %d, err %s aq_err %s\n", + vf->vf_num, vsi->idx, + ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + + /* Figure out what got added and what got removed */ + ice_zero_bitmap(old_req_xor_mask, ICE_PROMISC_MAX); + ice_xor_bitmap(old_req_xor_mask, old_promisc_mask, req_promisc_mask, ICE_PROMISC_MAX); + ice_and_bitmap(clear_promisc_mask, old_req_xor_mask, old_promisc_mask, ICE_PROMISC_MAX); + ice_and_bitmap(set_promisc_mask, old_req_xor_mask, req_promisc_mask, ICE_PROMISC_MAX); + + if (ice_is_any_bit_set(clear_promisc_mask, ICE_PROMISC_MAX)) { + status = ice_clear_vsi_promisc(hw, vsi->idx, + clear_promisc_mask, 0); + if (status) { + device_printf(sc->dev, + "VF-%d: Failed to clear promiscuous mode for VSI %d, err %s aq_err %s\n", + vf->vf_num, vsi->idx, + ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + } + + if (ice_is_any_bit_set(set_promisc_mask, ICE_PROMISC_MAX)) { + status = ice_set_vsi_promisc(hw, vsi->idx, set_promisc_mask, 0); + if (status) { + device_printf(sc->dev, + "VF-%d: Failed to set promiscuous mode for VSI %d, err %s aq_err %s\n", + vf->vf_num, vsi->idx, + ice_status_str(status), + ice_aq_str(hw->adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + } + +done: + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, + v_status, NULL, 0, NULL); +} + +/** + * ice_vc_notify_all_vfs_link_state - Notify all VFs of PF link state + * @sc: device private structure + * + * Sends a message to all VFs about the status of the PF's link + * state. For more details, @see ice_vc_notify_vf_link_state. + */ +void +ice_vc_notify_all_vfs_link_state(struct ice_softc *sc) +{ + for (int i = 0; i < sc->num_vfs; i++) + ice_vc_notify_vf_link_state(sc, &sc->vfs[i]); +} + +/** + * ice_vc_notify_vf_link_state - Notify VF of PF link state + * @sc: device private structure + * @vf: VF tracking structure + * + * Sends an event message to the specified VF with information about + * the current link state from the PF's port. This includes whether + * link is up or down, and the link speed in 100Mbps units. + */ +static void +ice_vc_notify_vf_link_state(struct ice_softc *sc, struct ice_vf *vf) +{ + struct virtchnl_pf_event event = {}; + struct ice_hw *hw = &sc->hw; + + event.event = VIRTCHNL_EVENT_LINK_CHANGE; + event.severity = PF_EVENT_SEVERITY_INFO; + event.event_data.link_event_adv.link_status = sc->link_up; + event.event_data.link_event_adv.link_speed = + (u32)ice_conv_link_speed_to_virtchnl(true, + hw->port_info->phy.link_info.link_speed); + + ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_EVENT, + VIRTCHNL_STATUS_SUCCESS, (u8 *)&event, sizeof(event), NULL); +} + +/** + * ice_vc_handle_vf_msg - Handle a message from a VF + * @sc: device private structure + * @event: event received from the HW MBX queue + * + * Called whenever an event is received from a VF on the HW mailbox queue. + * Responsible for handling these messages as well as responding to the + * VF afterwards, depending on the received message type. + */ +void +ice_vc_handle_vf_msg(struct ice_softc *sc, struct ice_rq_event_info *event) +{ + struct ice_hw *hw = &sc->hw; + device_t dev = sc->dev; + struct ice_vf *vf; + int err = 0; + + u32 v_opcode = event->desc.cookie_high; + u16 v_id = event->desc.retval; + u8 *msg = event->msg_buf; + u16 msglen = event->msg_len; + + if (v_id >= sc->num_vfs) { + device_printf(dev, "%s: Received msg from invalid VF-%d: opcode %d, len %d\n", + __func__, v_id, v_opcode, msglen); + return; + } + + vf = &sc->vfs[v_id]; + + /* Perform basic checks on the msg */ + err = virtchnl_vc_validate_vf_msg(&vf->version, v_opcode, msg, msglen); + if (err) { + device_printf(dev, "%s: Received invalid msg from VF-%d: opcode %d, len %d, error %d\n", + __func__, vf->vf_num, v_opcode, msglen, err); + ice_aq_send_msg_to_vf(hw, v_id, v_opcode, VIRTCHNL_STATUS_ERR_PARAM, NULL, 0, NULL); + return; + } + + switch (v_opcode) { + case VIRTCHNL_OP_VERSION: + ice_vc_version_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_RESET_VF: + ice_reset_vf(sc, vf, true); + break; + case VIRTCHNL_OP_GET_VF_RESOURCES: + ice_vc_get_vf_res_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_ADD_ETH_ADDR: + ice_vc_add_eth_addr_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_DEL_ETH_ADDR: + ice_vc_del_eth_addr_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_ADD_VLAN: + ice_vc_add_vlan_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_DEL_VLAN: + ice_vc_del_vlan_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_CONFIG_VSI_QUEUES: + ice_vc_cfg_vsi_qs_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_CONFIG_RSS_KEY: + ice_vc_cfg_rss_key_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_CONFIG_RSS_LUT: + ice_vc_cfg_rss_lut_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_SET_RSS_HENA: + ice_vc_set_rss_hena_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_ENABLE_QUEUES: + ice_vc_enable_queues_msg(sc, vf, msg); + ice_vc_notify_vf_link_state(sc, vf); + break; + case VIRTCHNL_OP_DISABLE_QUEUES: + ice_vc_disable_queues_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_CONFIG_IRQ_MAP: + ice_vc_cfg_irq_map_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_GET_STATS: + ice_vc_get_stats_msg(sc, vf, msg); + break; + case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: + ice_vc_cfg_promisc_mode_msg(sc, vf, msg); + break; + default: + device_printf(dev, "%s: Received unknown msg from VF-%d: opcode %d, len %d\n", + __func__, vf->vf_num, v_opcode, msglen); + ice_aq_send_msg_to_vf(hw, v_id, v_opcode, + VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL, 0, NULL); + break; + } +} + +/** + * ice_iov_setup_intr_mapping - Setup interrupt config for a VF + * @sc: device softc structure + * @vf: driver's VF structure for VF to be configured + * + * Before a VF can be used, and after a VF reset, the PF must configure + * the VF's interrupt allocation registers. This includes allocating + * interrupts from the PF's interrupt pool to the VF using the + * VPINT_ALLOC(_PCI) registers, and setting up a mapping from PF vectors + * to VF vectors in GLINT_VECT2FUNC. + * + * As well, this sets up queue allocation registers and maps the mailbox + * interrupt for the VF. + */ +static void +ice_iov_setup_intr_mapping(struct ice_softc *sc, struct ice_vf *vf) +{ + struct ice_hw *hw = &sc->hw; + struct ice_vsi *vsi = vf->vsi; + u16 v; + + /* Calculate indices for register ops below */ + u16 vf_first_irq_idx = vf->vf_imap[0]; + u16 vf_last_irq_idx = (vf_first_irq_idx + vf->num_irq_vectors) - 1; + u16 abs_vf_first_irq_idx = hw->func_caps.common_cap.msix_vector_first_id + + vf_first_irq_idx; + u16 abs_vf_last_irq_idx = (abs_vf_first_irq_idx + vf->num_irq_vectors) - 1; + u16 abs_vf_num = vf->vf_num + hw->func_caps.vf_base_id; + + /* Map out VF interrupt allocation in global device space. Both + * VPINT_ALLOC and VPINT_ALLOC_PCI use the same values. + */ + wr32(hw, VPINT_ALLOC(vf->vf_num), + (((abs_vf_first_irq_idx << VPINT_ALLOC_FIRST_S) & VPINT_ALLOC_FIRST_M) | + ((abs_vf_last_irq_idx << VPINT_ALLOC_LAST_S) & VPINT_ALLOC_LAST_M) | + VPINT_ALLOC_VALID_M)); + wr32(hw, VPINT_ALLOC_PCI(vf->vf_num), + (((abs_vf_first_irq_idx << VPINT_ALLOC_PCI_FIRST_S) & VPINT_ALLOC_PCI_FIRST_M) | + ((abs_vf_last_irq_idx << VPINT_ALLOC_PCI_LAST_S) & VPINT_ALLOC_PCI_LAST_M) | + VPINT_ALLOC_PCI_VALID_M)); + + /* Create inverse mapping of vectors to PF/VF combinations */ + for (v = vf_first_irq_idx; v <= vf_last_irq_idx; v++) + { + wr32(hw, GLINT_VECT2FUNC(v), + (((abs_vf_num << GLINT_VECT2FUNC_VF_NUM_S) & GLINT_VECT2FUNC_VF_NUM_M) | + ((hw->pf_id << GLINT_VECT2FUNC_PF_NUM_S) & GLINT_VECT2FUNC_PF_NUM_M))); + } + + /* Map mailbox interrupt to MSI-X index 0. Disable ITR for it, too. */ + wr32(hw, VPINT_MBX_CTL(abs_vf_num), + ((0 << VPINT_MBX_CTL_MSIX_INDX_S) & VPINT_MBX_CTL_MSIX_INDX_M) | + ((0x3 << VPINT_MBX_CTL_ITR_INDX_S) & VPINT_MBX_CTL_ITR_INDX_M) | + VPINT_MBX_CTL_CAUSE_ENA_M); + + /* Mark the TX queue mapping registers as valid */ + wr32(hw, VPLAN_TXQ_MAPENA(vf->vf_num), VPLAN_TXQ_MAPENA_TX_ENA_M); + + /* Indicate to HW that VF has scattered queue allocation */ + wr32(hw, VPLAN_TX_QBASE(vf->vf_num), VPLAN_TX_QBASE_VFQTABLE_ENA_M); + for (int i = 0; i < vsi->num_tx_queues; i++) { + wr32(hw, VPLAN_TX_QTABLE(i, vf->vf_num), + (vsi->tx_qmap[i] << VPLAN_TX_QTABLE_QINDEX_S) & VPLAN_TX_QTABLE_QINDEX_M); + } + + /* Mark the RX queue mapping registers as valid */ + wr32(hw, VPLAN_RXQ_MAPENA(vf->vf_num), VPLAN_RXQ_MAPENA_RX_ENA_M); + wr32(hw, VPLAN_RX_QBASE(vf->vf_num), VPLAN_RX_QBASE_VFQTABLE_ENA_M); + for (int i = 0; i < vsi->num_rx_queues; i++) { + wr32(hw, VPLAN_RX_QTABLE(i, vf->vf_num), + (vsi->rx_qmap[i] << VPLAN_RX_QTABLE_QINDEX_S) & VPLAN_RX_QTABLE_QINDEX_M); + } +} + +/** + * ice_err_to_virt err - translate ice errors into virtchnl errors + * @ice_err: status returned from ice function + */ +static enum virtchnl_status_code +ice_iov_err_to_virt_err(int ice_err) +{ + switch (ice_err) { + case 0: + return VIRTCHNL_STATUS_SUCCESS; + case ICE_ERR_BAD_PTR: + case ICE_ERR_INVAL_SIZE: + case ICE_ERR_DEVICE_NOT_SUPPORTED: + case ICE_ERR_PARAM: + case ICE_ERR_CFG: + return VIRTCHNL_STATUS_ERR_PARAM; + case ICE_ERR_NO_MEMORY: + return VIRTCHNL_STATUS_ERR_NO_MEMORY; + case ICE_ERR_NOT_READY: + case ICE_ERR_RESET_FAILED: + case ICE_ERR_FW_API_VER: + case ICE_ERR_AQ_ERROR: + case ICE_ERR_AQ_TIMEOUT: + case ICE_ERR_AQ_FULL: + case ICE_ERR_AQ_NO_WORK: + case ICE_ERR_AQ_EMPTY: + return VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; + default: + return VIRTCHNL_STATUS_ERR_NOT_SUPPORTED; + } +} diff --git a/sys/dev/ice/ice_iov.h b/sys/dev/ice/ice_iov.h new file mode 100644 index 000000000000..c4fb3e932e3f --- /dev/null +++ b/sys/dev/ice/ice_iov.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2025, Intel Corporation + * 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. + * + * 3. Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +/** + * @file ice_iov.h + * @brief header for IOV functionality + * + * This header includes definitions used to implement device Virtual Functions + * for the ice driver. + */ + +#ifndef _ICE_IOV_H_ +#define _ICE_IOV_H_ + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/nv.h> +#include <sys/iov_schema.h> +#include <sys/param.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#include <dev/pci/pci_iov.h> + +#include "ice_iflib.h" +#include "ice_vf_mbx.h" + +/** + * @enum ice_vf_flags + * @brief VF state flags + * + * Used to indicate the status of a PF's VF, as well as indicating what each VF + * is capabile of. Intended to be modified only using atomic operations, so + * they can be read and modified in places that aren't locked. + * + * Used in struct ice_vf's vf_flags field. + */ +enum ice_vf_flags { + VF_FLAG_ENABLED = BIT(0), + VF_FLAG_SET_MAC_CAP = BIT(1), + VF_FLAG_VLAN_CAP = BIT(2), + VF_FLAG_PROMISC_CAP = BIT(3), + VF_FLAG_MAC_ANTI_SPOOF = BIT(4), +}; + +/** + * @struct ice_vf + * @brief PF's VF software context + * + * Represents the state and options for a VF spawned from a PF. + */ +struct ice_vf { + struct ice_vsi *vsi; + u32 vf_flags; + + u8 mac[ETHER_ADDR_LEN]; + u16 vf_num; + struct virtchnl_version_info version; + + u16 mac_filter_limit; + u16 mac_filter_cnt; + u16 vlan_limit; + u16 vlan_cnt; + + u16 num_irq_vectors; + u16 *vf_imap; + struct ice_irq_vector *tx_irqvs; + struct ice_irq_vector *rx_irqvs; +}; + +#define ICE_PCIE_DEV_STATUS 0xAA + +#define ICE_PCI_CIAD_WAIT_COUNT 100 +#define ICE_PCI_CIAD_WAIT_DELAY_US 1 +#define ICE_VPGEN_VFRSTAT_WAIT_COUNT 100 +#define ICE_VPGEN_VFRSTAT_WAIT_DELAY_US 20 + +#define ICE_VIRTCHNL_VALID_PROMISC_FLAGS (FLAG_VF_UNICAST_PROMISC | \ + FLAG_VF_MULTICAST_PROMISC) + +#define ICE_DEFAULT_VF_VLAN_LIMIT 64 +#define ICE_DEFAULT_VF_FILTER_LIMIT 16 + +int ice_iov_attach(struct ice_softc *sc); +int ice_iov_detach(struct ice_softc *sc); + +int ice_iov_init(struct ice_softc *sc, uint16_t num_vfs, const nvlist_t *params); +int ice_iov_add_vf(struct ice_softc *sc, uint16_t vfnum, const nvlist_t *params); +void ice_iov_uninit(struct ice_softc *sc); + +void ice_iov_handle_vflr(struct ice_softc *sc); + +void ice_vc_handle_vf_msg(struct ice_softc *sc, struct ice_rq_event_info *event); +void ice_vc_notify_all_vfs_link_state(struct ice_softc *sc); + +#endif /* _ICE_IOV_H_ */ + diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c index d44ae5f37750..442111e5ffaf 100644 --- a/sys/dev/ice/ice_lib.c +++ b/sys/dev/ice/ice_lib.c @@ -42,6 +42,9 @@ #include "ice_lib.h" #include "ice_iflib.h" +#ifdef PCI_IOV +#include "ice_iov.h" +#endif #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <machine/resource.h> @@ -741,6 +744,12 @@ ice_initialize_vsi(struct ice_vsi *vsi) case ICE_VSI_VMDQ2: ctx.flags = ICE_AQ_VSI_TYPE_VMDQ2; break; +#ifdef PCI_IOV + case ICE_VSI_VF: + ctx.flags = ICE_AQ_VSI_TYPE_VF; + ctx.vf_num = vsi->vf_num; + break; +#endif default: return (ENODEV); } @@ -1607,6 +1616,12 @@ ice_setup_tx_ctx(struct ice_tx_queue *txq, struct ice_tlan_ctx *tlan_ctx, u16 pf case ICE_VSI_VMDQ2: tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ; break; +#ifdef PCI_IOV + case ICE_VSI_VF: + tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF; + tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_num; + break; +#endif default: return (ENODEV); } @@ -1660,6 +1675,10 @@ ice_cfg_vsi_for_tx(struct ice_vsi *vsi) struct ice_tlan_ctx tlan_ctx = { 0 }; struct ice_tx_queue *txq = &vsi->tx_queues[i]; + /* Last configured queue */ + if (txq->desc_count == 0) + break; + pf_q = vsi->tx_qmap[txq->me]; qg->txqs[0].txq_id = htole16(pf_q); @@ -1788,6 +1807,10 @@ ice_cfg_vsi_for_rx(struct ice_vsi *vsi) for (i = 0; i < vsi->num_rx_queues; i++) { MPASS(vsi->mbuf_sz > 0); + /* Last configured queue */ + if (vsi->rx_queues[i].desc_count == 0) + break; + err = ice_setup_rx_ctx(&vsi->rx_queues[i]); if (err) return err; @@ -2257,6 +2280,11 @@ ice_process_ctrlq_event(struct ice_softc *sc, const char *qname, case ice_aqc_opc_get_link_status: ice_process_link_event(sc, event); break; +#ifdef PCI_IOV + case ice_mbx_opc_send_msg_to_pf: + ice_vc_handle_vf_msg(sc, event); + break; +#endif case ice_aqc_opc_fw_logs_event: ice_handle_fw_log_event(sc, &event->desc, event->msg_buf); break; diff --git a/sys/dev/ice/ice_lib.h b/sys/dev/ice/ice_lib.h index b6b23ec82161..308b2bda2790 100644 --- a/sys/dev/ice/ice_lib.h +++ b/sys/dev/ice/ice_lib.h @@ -611,6 +611,10 @@ struct ice_vsi { u16 mirror_src_vsi; u16 rule_mir_ingress; u16 rule_mir_egress; + +#ifdef PCI_IOV + u8 vf_num; /* Index of owning VF, if applicable */ +#endif }; /** diff --git a/sys/dev/ice/ice_vf_mbx.c b/sys/dev/ice/ice_vf_mbx.c new file mode 100644 index 000000000000..387a1c6739a6 --- /dev/null +++ b/sys/dev/ice/ice_vf_mbx.c @@ -0,0 +1,471 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2025, Intel Corporation + * 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. + * + * 3. Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 "ice_common.h" +#include "ice_hw_autogen.h" +#include "ice_vf_mbx.h" + +/** + * ice_aq_send_msg_to_vf + * @hw: pointer to the hardware structure + * @vfid: VF ID to send msg + * @v_opcode: opcodes for VF-PF communication + * @v_retval: return error code + * @msg: pointer to the msg buffer + * @msglen: msg length + * @cd: pointer to command details + * + * Send message to VF driver (0x0802) using mailbox + * queue and asynchronously sending message via + * ice_sq_send_cmd() function + */ +int +ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, + u8 *msg, u16 msglen, struct ice_sq_cd *cd) +{ + struct ice_aqc_pf_vf_msg *cmd; + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_vf); + + cmd = &desc.params.virt; + cmd->id = CPU_TO_LE32(vfid); + + desc.cookie_high = CPU_TO_LE32(v_opcode); + desc.cookie_low = CPU_TO_LE32(v_retval); + + if (msglen) + desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); + + return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd); +} + +/** + * ice_aq_send_msg_to_pf + * @hw: pointer to the hardware structure + * @v_opcode: opcodes for VF-PF communication + * @v_retval: return error code + * @msg: pointer to the msg buffer + * @msglen: msg length + * @cd: pointer to command details + * + * Send message to PF driver using mailbox queue. By default, this + * message is sent asynchronously, i.e. ice_sq_send_cmd() + * does not wait for completion before returning. + */ +int +ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode, + int v_retval, u8 *msg, u16 msglen, + struct ice_sq_cd *cd) +{ + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_pf); + desc.cookie_high = CPU_TO_LE32(v_opcode); + desc.cookie_low = CPU_TO_LE32(v_retval); + + if (msglen) + desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); + + return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd); +} + +static const u32 ice_legacy_aq_to_vc_speed[] = { + VIRTCHNL_LINK_SPEED_100MB, /* BIT(0) */ + VIRTCHNL_LINK_SPEED_100MB, + VIRTCHNL_LINK_SPEED_1GB, + VIRTCHNL_LINK_SPEED_1GB, + VIRTCHNL_LINK_SPEED_1GB, + VIRTCHNL_LINK_SPEED_10GB, + VIRTCHNL_LINK_SPEED_20GB, + VIRTCHNL_LINK_SPEED_25GB, + VIRTCHNL_LINK_SPEED_40GB, + VIRTCHNL_LINK_SPEED_40GB, + VIRTCHNL_LINK_SPEED_40GB, +}; + +/** + * ice_conv_link_speed_to_virtchnl + * @adv_link_support: determines the format of the returned link speed + * @link_speed: variable containing the link_speed to be converted + * + * Convert link speed supported by HW to link speed supported by virtchnl. + * If adv_link_support is true, then return link speed in Mbps. Else return + * link speed as a VIRTCHNL_LINK_SPEED_* casted to a u32. Note that the caller + * needs to cast back to an enum virtchnl_link_speed in the case where + * adv_link_support is false, but when adv_link_support is true the caller can + * expect the speed in Mbps. + */ +u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed) +{ + /* convert a BIT() value into an array index */ + u16 index = (u16)(ice_fls(link_speed) - 1); + + if (adv_link_support) + return ice_get_link_speed(index); + else if (index < ARRAY_SIZE(ice_legacy_aq_to_vc_speed)) + /* Virtchnl speeds are not defined for every speed supported in + * the hardware. To maintain compatibility with older AVF + * drivers, while reporting the speed the new speed values are + * resolved to the closest known virtchnl speeds + */ + return ice_legacy_aq_to_vc_speed[index]; + + return VIRTCHNL_LINK_SPEED_UNKNOWN; +} + +/* The mailbox overflow detection algorithm helps to check if there + * is a possibility of a malicious VF transmitting too many MBX messages to the + * PF. + * 1. The mailbox snapshot structure, ice_mbx_snapshot, is initialized during + * driver initialization in ice_init_hw() using ice_mbx_init_snapshot(). + * The struct ice_mbx_snapshot helps to track and traverse a static window of + * messages within the mailbox queue while looking for a malicious VF. + * + * 2. When the caller starts processing its mailbox queue in response to an + * interrupt, the structure ice_mbx_snapshot is expected to be cleared before + * the algorithm can be run for the first time for that interrupt. This + * requires calling ice_mbx_reset_snapshot() as well as calling + * ice_mbx_reset_vf_info() for each VF tracking structure. + * + * 3. For every message read by the caller from the MBX Queue, the caller must + * call the detection algorithm's entry function ice_mbx_vf_state_handler(). + * Before every call to ice_mbx_vf_state_handler() the struct ice_mbx_data is + * filled as it is required to be passed to the algorithm. + * + * 4. Every time a message is read from the MBX queue, a tracking structure + * for the VF must be passed to the state handler. The boolean output + * report_malvf from ice_mbx_vf_state_handler() serves as an indicator to the + * caller whether it must report this VF as malicious or not. + * + * 5. When a VF is identified to be malicious, the caller can send a message + * to the system administrator. + * + * 6. The PF is responsible for maintaining the struct ice_mbx_vf_info + * structure for each VF. The PF should clear the VF tracking structure if the + * VF is reset. When a VF is shut down and brought back up, we will then + * assume that the new VF is not malicious and may report it again if we + * detect it again. + * + * 7. The function ice_mbx_reset_snapshot() is called to reset the information + * in ice_mbx_snapshot for every new mailbox interrupt handled. + */ +#define ICE_RQ_DATA_MASK(rq_data) ((rq_data) & PF_MBX_ARQH_ARQH_M) +/* Using the highest value for an unsigned 16-bit value 0xFFFF to indicate that + * the max messages check must be ignored in the algorithm + */ +#define ICE_IGNORE_MAX_MSG_CNT 0xFFFF + +/** + * ice_mbx_reset_snapshot - Initialize mailbox snapshot structure + * @snap: pointer to the mailbox snapshot + */ +static void ice_mbx_reset_snapshot(struct ice_mbx_snapshot *snap) +{ + struct ice_mbx_vf_info *vf_info; + + /* Clear mbx_buf in the mailbox snaphot structure and setting the + * mailbox snapshot state to a new capture. + */ + ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf), ICE_NONDMA_MEM); + snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT; + + /* Reset message counts for all VFs to zero */ + LIST_FOR_EACH_ENTRY(vf_info, &snap->mbx_vf, ice_mbx_vf_info, list_entry) + vf_info->msg_count = 0; +} + +/** + * ice_mbx_traverse - Pass through mailbox snapshot + * @hw: pointer to the HW struct + * @new_state: new algorithm state + * + * Traversing the mailbox static snapshot without checking + * for malicious VFs. + */ +static void +ice_mbx_traverse(struct ice_hw *hw, + enum ice_mbx_snapshot_state *new_state) +{ + struct ice_mbx_snap_buffer_data *snap_buf; + u32 num_iterations; + + snap_buf = &hw->mbx_snapshot.mbx_buf; + + /* As mailbox buffer is circular, applying a mask + * on the incremented iteration count. + */ + num_iterations = ICE_RQ_DATA_MASK(++snap_buf->num_iterations); + + /* Checking either of the below conditions to exit snapshot traversal: + * Condition-1: If the number of iterations in the mailbox is equal to + * the mailbox head which would indicate that we have reached the end + * of the static snapshot. + * Condition-2: If the maximum messages serviced in the mailbox for a + * given interrupt is the highest possible value then there is no need + * to check if the number of messages processed is equal to it. If not + * check if the number of messages processed is greater than or equal + * to the maximum number of mailbox entries serviced in current work item. + */ + if (num_iterations == snap_buf->head || + (snap_buf->max_num_msgs_mbx < ICE_IGNORE_MAX_MSG_CNT && + ++snap_buf->num_msg_proc >= snap_buf->max_num_msgs_mbx)) + *new_state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT; +} + +/** + * ice_mbx_detect_malvf - Detect malicious VF in snapshot + * @hw: pointer to the HW struct + * @vf_info: mailbox tracking structure for a VF + * @new_state: new algorithm state + * @is_malvf: boolean output to indicate if VF is malicious + * + * This function tracks the number of asynchronous messages + * sent per VF and marks the VF as malicious if it exceeds + * the permissible number of messages to send. + */ +static int +ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info, + enum ice_mbx_snapshot_state *new_state, + bool *is_malvf) +{ + /* increment the message count for this VF */ + vf_info->msg_count++; + + if (vf_info->msg_count >= ICE_ASYNC_VF_MSG_THRESHOLD) + *is_malvf = true; + + /* continue to iterate through the mailbox snapshot */ + ice_mbx_traverse(hw, new_state); + + return 0; +} + +/** + * ice_e830_mbx_vf_dec_trig - Decrements the VF mailbox queue counter + * @hw: pointer to the HW struct + * @event: pointer to the control queue receive event + * + * This function triggers to decrement the counter + * MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes + * the buffers at the PF mailbox queue. + */ +void ice_e830_mbx_vf_dec_trig(struct ice_hw *hw, + struct ice_rq_event_info *event) +{ + u16 vfid = LE16_TO_CPU(event->desc.retval); + + wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1); +} + +/** + * ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count + * @hw: pointer to the HW struct + * @vf_id: VF ID in the PF space + * + * This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT, and should + * be called when a VF is created and on VF reset. + */ +void ice_mbx_vf_clear_cnt_e830(struct ice_hw *hw, u16 vf_id) +{ + u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id)); + + wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg); +} + +/** + * ice_mbx_vf_state_handler - Handle states of the overflow algorithm + * @hw: pointer to the HW struct + * @mbx_data: pointer to structure containing mailbox data + * @vf_info: mailbox tracking structure for the VF in question + * @report_malvf: boolean output to indicate whether VF should be reported + * + * The function serves as an entry point for the malicious VF + * detection algorithm by handling the different states and state + * transitions of the algorithm: + * New snapshot: This state is entered when creating a new static + * snapshot. The data from any previous mailbox snapshot is + * cleared and a new capture of the mailbox head and tail is + * logged. This will be the new static snapshot to detect + * asynchronous messages sent by VFs. On capturing the snapshot + * and depending on whether the number of pending messages in that + * snapshot exceed the watermark value, the state machine enters + * traverse or detect states. + * Traverse: If pending message count is below watermark then iterate + * through the snapshot without any action on VF. + * Detect: If pending message count exceeds watermark traverse + * the static snapshot and look for a malicious VF. + */ +int +ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data, + struct ice_mbx_vf_info *vf_info, bool *report_malvf) +{ + struct ice_mbx_snapshot *snap = &hw->mbx_snapshot; + struct ice_mbx_snap_buffer_data *snap_buf; + struct ice_ctl_q_info *cq = &hw->mailboxq; + enum ice_mbx_snapshot_state new_state; + int status = 0; + bool is_malvf = false; + + if (!report_malvf || !mbx_data || !vf_info) + return ICE_ERR_BAD_PTR; + + *report_malvf = false; + + /* When entering the mailbox state machine assume that the VF + * is not malicious until detected. + */ + /* Checking if max messages allowed to be processed while servicing current + * interrupt is not less than the defined AVF message threshold. + */ + if (mbx_data->max_num_msgs_mbx <= ICE_ASYNC_VF_MSG_THRESHOLD) + return ICE_ERR_INVAL_SIZE; + + /* The watermark value should not be lesser than the threshold limit + * set for the number of asynchronous messages a VF can send to mailbox + * nor should it be greater than the maximum number of messages in the + * mailbox serviced in current interrupt. + */ + if (mbx_data->async_watermark_val < ICE_ASYNC_VF_MSG_THRESHOLD || + mbx_data->async_watermark_val > mbx_data->max_num_msgs_mbx) + return ICE_ERR_PARAM; + + new_state = ICE_MAL_VF_DETECT_STATE_INVALID; + snap_buf = &snap->mbx_buf; + + switch (snap_buf->state) { + case ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT: + /* Clear any previously held data in mailbox snapshot structure. */ + ice_mbx_reset_snapshot(snap); + + /* Collect the pending ARQ count, number of messages processed and + * the maximum number of messages allowed to be processed from the + * Mailbox for current interrupt. + */ + snap_buf->num_pending_arq = mbx_data->num_pending_arq; + snap_buf->num_msg_proc = mbx_data->num_msg_proc; + snap_buf->max_num_msgs_mbx = mbx_data->max_num_msgs_mbx; + + /* Capture a new static snapshot of the mailbox by logging the + * head and tail of snapshot and set num_iterations to the tail + * value to mark the start of the iteration through the snapshot. + */ + snap_buf->head = ICE_RQ_DATA_MASK(cq->rq.next_to_clean + + mbx_data->num_pending_arq); + snap_buf->tail = ICE_RQ_DATA_MASK(cq->rq.next_to_clean - 1); + snap_buf->num_iterations = snap_buf->tail; + + /* Pending ARQ messages returned by ice_clean_rq_elem + * is the difference between the head and tail of the + * mailbox queue. Comparing this value against the watermark + * helps to check if we potentially have malicious VFs. + */ + if (snap_buf->num_pending_arq >= + mbx_data->async_watermark_val) { + new_state = ICE_MAL_VF_DETECT_STATE_DETECT; + status = ice_mbx_detect_malvf(hw, vf_info, &new_state, &is_malvf); + } else { + new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE; + ice_mbx_traverse(hw, &new_state); + } + break; + + case ICE_MAL_VF_DETECT_STATE_TRAVERSE: + new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE; + ice_mbx_traverse(hw, &new_state); + break; + + case ICE_MAL_VF_DETECT_STATE_DETECT: + new_state = ICE_MAL_VF_DETECT_STATE_DETECT; + status = ice_mbx_detect_malvf(hw, vf_info, &new_state, &is_malvf); + break; + + default: + new_state = ICE_MAL_VF_DETECT_STATE_INVALID; + status = ICE_ERR_CFG; + } + + snap_buf->state = new_state; + + /* Only report VFs as malicious the first time we detect it */ + if (is_malvf && !vf_info->malicious) { + vf_info->malicious = 1; + *report_malvf = true; + } + + return status; +} + +/** + * ice_mbx_clear_malvf - Clear VF mailbox info + * @vf_info: the mailbox tracking structure for a VF + * + * In case of a VF reset, this function shall be called to clear the VF's + * current mailbox tracking state. + */ +void ice_mbx_clear_malvf(struct ice_mbx_vf_info *vf_info) +{ + vf_info->malicious = 0; + vf_info->msg_count = 0; +} + +/** + * ice_mbx_init_vf_info - Initialize a new VF mailbox tracking info + * @hw: pointer to the hardware structure + * @vf_info: the mailbox tracking info structure for a VF + * + * Initialize a VF mailbox tracking info structure and insert it into the + * snapshot list. + * + * If you remove the VF, you must also delete the associated VF info structure + * from the linked list. + */ +void ice_mbx_init_vf_info(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info) +{ + struct ice_mbx_snapshot *snap = &hw->mbx_snapshot; + + ice_mbx_clear_malvf(vf_info); + LIST_ADD(&vf_info->list_entry, &snap->mbx_vf); +} + +/** + * ice_mbx_init_snapshot - Initialize mailbox snapshot data + * @hw: pointer to the hardware structure + * + * Clear the mailbox snapshot structure and initialize the VF mailbox list. + */ +void ice_mbx_init_snapshot(struct ice_hw *hw) +{ + struct ice_mbx_snapshot *snap = &hw->mbx_snapshot; + + INIT_LIST_HEAD(&snap->mbx_vf); + ice_mbx_reset_snapshot(snap); +} diff --git a/sys/dev/ice/ice_vf_mbx.h b/sys/dev/ice/ice_vf_mbx.h new file mode 100644 index 000000000000..3b185ac89c11 --- /dev/null +++ b/sys/dev/ice/ice_vf_mbx.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2025, Intel Corporation + * 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. + * + * 3. Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _ICE_VF_MBX_H_ +#define _ICE_VF_MBX_H_ + +#include "ice_type.h" +#include "ice_controlq.h" + +/* Defining the mailbox message threshold as 63 asynchronous + * pending messages. Normal VF functionality does not require + * sending more than 63 asynchronous pending message. + */ + + /* Threshold value should be used to initialize + * MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT register. + */ +#define ICE_ASYNC_VF_MSG_THRESHOLD 63 + +int +ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode, + int v_retval, u8 *msg, u16 msglen, + struct ice_sq_cd *cd); +int +ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, + u8 *msg, u16 msglen, struct ice_sq_cd *cd); + +u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed); + +void ice_e830_mbx_vf_dec_trig(struct ice_hw *hw, + struct ice_rq_event_info *event); +void ice_mbx_vf_clear_cnt_e830(struct ice_hw *hw, u16 vf_id); +int +ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data, + struct ice_mbx_vf_info *vf_info, bool *report_malvf); +void ice_mbx_clear_malvf(struct ice_mbx_vf_info *vf_info); +void ice_mbx_init_vf_info(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info); +void ice_mbx_init_snapshot(struct ice_hw *hw); +#endif /* _ICE_VF_MBX_H_ */ diff --git a/sys/dev/ice/if_ice_iflib.c b/sys/dev/ice/if_ice_iflib.c index e60ee0f1c5c3..1469d2916465 100644 --- a/sys/dev/ice/if_ice_iflib.c +++ b/sys/dev/ice/if_ice_iflib.c @@ -42,6 +42,9 @@ #include "ice_drv_info.h" #include "ice_switch.h" #include "ice_sched.h" +#ifdef PCI_IOV +#include "ice_iov.h" +#endif #include <sys/module.h> #include <sys/sockio.h> @@ -85,6 +88,12 @@ static int ice_if_suspend(if_ctx_t ctx); static int ice_if_resume(if_ctx_t ctx); static bool ice_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); static void ice_init_link(struct ice_softc *sc); +#ifdef PCI_IOV +static int ice_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params); +static void ice_if_iov_uninit(if_ctx_t ctx); +static int ice_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params); +static void ice_if_vflr_handle(if_ctx_t ctx); +#endif static int ice_setup_mirror_vsi(struct ice_mirr_if *mif); static int ice_wire_mirror_intrs(struct ice_mirr_if *mif); static void ice_free_irqvs_subif(struct ice_mirr_if *mif); @@ -158,6 +167,11 @@ static device_method_t ice_methods[] = { DEVMETHOD(device_shutdown, iflib_device_shutdown), DEVMETHOD(device_suspend, iflib_device_suspend), DEVMETHOD(device_resume, iflib_device_resume), +#ifdef PCI_IOV + DEVMETHOD(pci_iov_init, iflib_device_iov_init), + DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), + DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), +#endif DEVMETHOD_END }; @@ -198,6 +212,12 @@ static device_method_t ice_iflib_methods[] = { DEVMETHOD(ifdi_suspend, ice_if_suspend), DEVMETHOD(ifdi_resume, ice_if_resume), DEVMETHOD(ifdi_needs_restart, ice_if_needs_restart), +#ifdef PCI_IOV + DEVMETHOD(ifdi_iov_vf_add, ice_if_iov_vf_add), + DEVMETHOD(ifdi_iov_init, ice_if_iov_init), + DEVMETHOD(ifdi_iov_uninit, ice_if_iov_uninit), + DEVMETHOD(ifdi_vflr_handle, ice_if_vflr_handle), +#endif DEVMETHOD_END }; @@ -733,6 +753,9 @@ ice_update_link_status(struct ice_softc *sc, bool update_media) iflib_link_state_change(sc->ctx, LINK_STATE_DOWN, 0); ice_rdma_link_change(sc, LINK_STATE_DOWN, 0); } +#ifdef PCI_IOV + ice_vc_notify_all_vfs_link_state(sc); +#endif update_media = true; } @@ -831,6 +854,14 @@ ice_if_attach_post(if_ctx_t ctx) ice_add_device_sysctls(sc); +#ifdef PCI_IOV + if (ice_is_bit_set(sc->feat_cap, ICE_FEATURE_SRIOV)) { + err = ice_iov_attach(sc); + if (err == ENOMEM) + return (err); + } +#endif /* PCI_IOV */ + /* Get DCBX/LLDP state and start DCBX agent */ ice_init_dcb_setup(sc); @@ -953,6 +984,11 @@ ice_if_detach(if_ctx_t ctx) ice_destroy_mirror_interface(sc); ice_rdma_pf_detach(sc); +#ifdef PCI_IOV + if (ice_is_bit_set(sc->feat_cap, ICE_FEATURE_SRIOV)) + ice_iov_detach(sc); +#endif /* PCI_IOV */ + /* Free allocated media types */ ifmedia_removeall(sc->media); @@ -1676,6 +1712,11 @@ ice_if_msix_intr_assign(if_ctx_t ctx, int msix) /* For future interrupt assignments */ sc->last_rid = rid + sc->irdma_vectors; +#ifdef PCI_IOV + /* Create soft IRQ for handling VF resets */ + iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_IOV, sc, 0, "iov"); +#endif + return (0); fail: for (; i >= 0; i--, vector--) @@ -2277,7 +2318,12 @@ ice_transition_recovery_mode(struct ice_softc *sc) ice_rdma_pf_detach(sc); ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_cap); +#ifdef PCI_IOV + if (ice_test_and_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en)) + ice_iov_detach(sc); +#else ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en); +#endif /* PCI_IOV */ ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_cap); ice_vsi_del_txqs_ctx(vsi); @@ -2325,7 +2371,12 @@ ice_transition_safe_mode(struct ice_softc *sc) ice_rdma_pf_detach(sc); ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_cap); +#ifdef PCI_IOV + if (ice_test_and_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en)) + ice_iov_detach(sc); +#else ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en); +#endif /* PCI_IOV */ ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_cap); ice_clear_bit(ICE_FEATURE_RSS, sc->feat_cap); @@ -2410,6 +2461,15 @@ ice_if_update_admin_status(if_ctx_t ctx) /* Check and update link status */ ice_update_link_status(sc, false); +#ifdef PCI_IOV + /* + * Schedule VFs' reset handler after global resets + * and other events were processed. + */ + if (ice_testandclear_state(&sc->state, ICE_STATE_VFLR_PENDING)) + iflib_iov_intr_deferred(ctx); +#endif + /* * If there are still messages to process, we need to reschedule * ourselves. Otherwise, we can just re-enable the interrupt. We'll be @@ -3349,6 +3409,78 @@ ice_init_link(struct ice_softc *sc) } +#ifdef PCI_IOV +/** + * ice_if_iov_init - iov init handler for iflib + * @ctx: iflib context pointer + * @num_vfs: number of VFs to create + * @params: configuration parameters for the PF + * + * Configure the driver for SR-IOV mode. Used to setup things like memory + * before any VFs are created. + * + * @remark This is a wrapper for ice_iov_init + */ +static int +ice_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + return ice_iov_init(sc, num_vfs, params); +} + +/** + * ice_if_iov_uninit - iov uninit handler for iflib + * @ctx: iflib context pointer + * + * Destroys VFs and frees their memory and resources. + * + * @remark This is a wrapper for ice_iov_uninit + */ +static void +ice_if_iov_uninit(if_ctx_t ctx) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + ice_iov_uninit(sc); +} + +/** + * ice_if_iov_vf_add - iov add vf handler for iflib + * @ctx: iflib context pointer + * @vfnum: index of VF to configure + * @params: configuration parameters for the VF + * + * Sets up the VF given by the vfnum index. This is called by the OS + * for each VF created by the PF driver after it is spawned. + * + * @remark This is a wrapper for ice_iov_vf_add + */ +static int +ice_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + return ice_iov_add_vf(sc, vfnum, params); +} + +/** + * ice_if_vflr_handle - iov VFLR handler + * @ctx: iflib context pointer + * + * Performs the necessar teardown or setup required for a VF after + * a VFLR is initiated. + * + * @remark This is a wrapper for ice_iov_handle_vflr + */ +static void +ice_if_vflr_handle(if_ctx_t ctx) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + ice_iov_handle_vflr(sc); +} +#endif /* PCI_IOV */ + extern struct if_txrx ice_subif_txrx; /** diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 741a7c013f7d..ec1664fac701 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -11,9 +11,9 @@ */ /*- - * The following functions are based on the vn(4) driver: mdstart_swap(), - * mdstart_vnode(), mdcreate_swap(), mdcreate_vnode() and mddestroy(), - * and as such under the following copyright: + * The following functions are based on the historical vn(4) driver: + * mdstart_swap(), mdstart_vnode(), mdcreate_swap(), mdcreate_vnode() + * and mddestroy(), and as such under the following copyright: * * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 @@ -89,6 +89,8 @@ #include <sys/unistd.h> #include <sys/vnode.h> #include <sys/disk.h> +#include <sys/param.h> +#include <sys/bus.h> #include <geom/geom.h> #include <geom/geom_int.h> @@ -2082,8 +2084,10 @@ g_md_init(struct g_class *mp __unused) { caddr_t mod; u_char *ptr, *name, *type; + u_char scratch[40]; unsigned len; int i; + vm_offset_t paddr; /* figure out log2(NINDIR) */ for (i = NINDIR, nshift = -1; i; nshift++) @@ -2123,6 +2127,25 @@ g_md_init(struct g_class *mp __unused) sx_xunlock(&md_sx); } } + + /* + * Load up to 32 pre-loaded disks + */ + for (int i = 0; i < 32; i++) { + if (resource_long_value("md", i, "physaddr", + (long *) &paddr) != 0 || + resource_int_value("md", i, "len", &len) != 0) + break; + ptr = (char *)pmap_map(NULL, paddr, paddr + len, VM_PROT_READ); + if (ptr != NULL && len != 0) { + sprintf(scratch, "preload%d 0x%016jx", i, + (uintmax_t)paddr); + sx_xlock(&md_sx); + md_preloaded(ptr, len, scratch); + sx_xunlock(&md_sx); + } + } + status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL, 0600, MDCTL_NAME); g_topology_lock(); diff --git a/sys/dev/mgb/if_mgb.c b/sys/dev/mgb/if_mgb.c index 1240d0f84415..409f34167df0 100644 --- a/sys/dev/mgb/if_mgb.c +++ b/sys/dev/mgb/if_mgb.c @@ -1435,7 +1435,7 @@ mgb_hw_teardown(struct mgb_softc *sc) /* Stop MAC */ CSR_CLEAR_REG(sc, MGB_MAC_RX, MGB_MAC_ENBL); - CSR_WRITE_REG(sc, MGB_MAC_TX, MGB_MAC_ENBL); + CSR_CLEAR_REG(sc, MGB_MAC_TX, MGB_MAC_ENBL); if ((err = mgb_wait_for_bits(sc, MGB_MAC_RX, MGB_MAC_DSBL, 0))) return (err); if ((err = mgb_wait_for_bits(sc, MGB_MAC_TX, MGB_MAC_DSBL, 0))) diff --git a/sys/dev/mlx5/mlx5_accel/ipsec.h b/sys/dev/mlx5/mlx5_accel/ipsec.h index 361b9f72d873..c3f3a2372482 100644 --- a/sys/dev/mlx5/mlx5_accel/ipsec.h +++ b/sys/dev/mlx5/mlx5_accel/ipsec.h @@ -260,8 +260,8 @@ int mlx5e_accel_ipsec_fs_rx_tables_create(struct mlx5e_priv *priv); void mlx5e_accel_ipsec_fs_rx_catchall_rules_destroy(struct mlx5e_priv *priv); int mlx5e_accel_ipsec_fs_rx_catchall_rules(struct mlx5e_priv *priv); int mlx5_accel_ipsec_rx_tag_add(if_t ifp, struct mlx5e_rq_mbuf *mr); -void mlx5e_accel_ipsec_handle_rx_cqe(struct mbuf *mb, struct mlx5_cqe64 *cqe, - struct mlx5e_rq_mbuf *mr); +void mlx5e_accel_ipsec_handle_rx_cqe(if_t ifp, struct mbuf *mb, + struct mlx5_cqe64 *cqe, struct mlx5e_rq_mbuf *mr); static inline int mlx5e_accel_ipsec_flow(struct mlx5_cqe64 *cqe) { @@ -269,12 +269,12 @@ static inline int mlx5e_accel_ipsec_flow(struct mlx5_cqe64 *cqe) } static inline void -mlx5e_accel_ipsec_handle_rx(struct mbuf *mb, struct mlx5_cqe64 *cqe, +mlx5e_accel_ipsec_handle_rx(if_t ifp, struct mbuf *mb, struct mlx5_cqe64 *cqe, struct mlx5e_rq_mbuf *mr) { u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata); if (MLX5_IPSEC_METADATA_MARKER(ipsec_meta_data)) - mlx5e_accel_ipsec_handle_rx_cqe(mb, cqe, mr); + mlx5e_accel_ipsec_handle_rx_cqe(ifp, mb, cqe, mr); } #endif /* __MLX5_ACCEL_IPSEC_H__ */ diff --git a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_rxtx.c b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_rxtx.c index 0883cfb2d510..5dccb8bc2b87 100644 --- a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_rxtx.c +++ b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_rxtx.c @@ -24,11 +24,14 @@ * */ +#include "opt_ipsec.h" + #include <sys/mbuf.h> #include <sys/socket.h> #include <netinet/in.h> #include <netipsec/keydb.h> #include <netipsec/ipsec_offload.h> +#include <netipsec/xform.h> #include <dev/mlx5/qp.h> #include <dev/mlx5/mlx5_en/en.h> #include <dev/mlx5/mlx5_accel/ipsec.h> @@ -48,7 +51,8 @@ mlx5_accel_ipsec_rx_tag_add(if_t ifp, struct mlx5e_rq_mbuf *mr) return (0); mtag = (struct ipsec_accel_in_tag *)m_tag_get( - PACKET_TAG_IPSEC_ACCEL_IN, sizeof(*mtag), M_NOWAIT); + PACKET_TAG_IPSEC_ACCEL_IN, sizeof(struct ipsec_accel_in_tag) - + __offsetof(struct ipsec_accel_in_tag, xh), M_NOWAIT); if (mtag == NULL) return (-ENOMEM); mr->ipsec_mtag = mtag; @@ -56,8 +60,8 @@ mlx5_accel_ipsec_rx_tag_add(if_t ifp, struct mlx5e_rq_mbuf *mr) } void -mlx5e_accel_ipsec_handle_rx_cqe(struct mbuf *mb, struct mlx5_cqe64 *cqe, - struct mlx5e_rq_mbuf *mr) +mlx5e_accel_ipsec_handle_rx_cqe(if_t ifp, struct mbuf *mb, + struct mlx5_cqe64 *cqe, struct mlx5e_rq_mbuf *mr) { struct ipsec_accel_in_tag *mtag; u32 drv_spi; @@ -65,10 +69,12 @@ mlx5e_accel_ipsec_handle_rx_cqe(struct mbuf *mb, struct mlx5_cqe64 *cqe, drv_spi = MLX5_IPSEC_METADATA_HANDLE(be32_to_cpu(cqe->ft_metadata)); mtag = mr->ipsec_mtag; WARN_ON(mtag == NULL); - mr->ipsec_mtag = NULL; if (mtag != NULL) { mtag->drv_spi = drv_spi; - m_tag_prepend(mb, &mtag->tag); + if (ipsec_accel_fill_xh(ifp, drv_spi, &mtag->xh)) { + m_tag_prepend(mb, &mtag->tag); + mr->ipsec_mtag = NULL; + } } } diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c index 4de451f1b039..89d2010656c5 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c @@ -659,7 +659,8 @@ mlx5e_tls_rx_set_params(void *ctx, struct inpcb *inp, const struct tls_session_p return (EINVAL); MLX5_SET64(sw_tls_rx_cntx, ctx, param.initial_record_number, tls_sn_he); - MLX5_SET(sw_tls_rx_cntx, ctx, param.resync_tcp_sn, tcp_sn_he); + MLX5_SET(sw_tls_rx_cntx, ctx, param.resync_tcp_sn, 0); + MLX5_SET(sw_tls_rx_cntx, ctx, progress.next_record_tcp_sn, tcp_sn_he); return (0); } diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c index 6b53db6fea23..eb569488631a 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c @@ -467,7 +467,7 @@ mlx5e_build_rx_mbuf(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, break; } - mlx5e_accel_ipsec_handle_rx(mb, cqe, mr); + mlx5e_accel_ipsec_handle_rx(ifp, mb, cqe, mr); } static inline void diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 73a7cee4aad0..fd7f00ced14b 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -48,7 +48,7 @@ #define B4_CHK_RDY_DELAY_MS 2300 /* work around controller bug */ static void nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr, - struct nvme_async_event_request *aer); + struct nvme_async_event_request *aer); static void nvme_ctrlr_barrier(struct nvme_controller *ctrlr, int flags) @@ -680,96 +680,6 @@ nvme_ctrlr_log_critical_warnings(struct nvme_controller *ctrlr, } static void -nvme_ctrlr_async_event_log_page_cb(void *arg, const struct nvme_completion *cpl) -{ - struct nvme_async_event_request *aer = arg; - struct nvme_health_information_page *health_info; - struct nvme_ns_list *nsl; - struct nvme_error_information_entry *err; - int i; - - /* - * If the log page fetch for some reason completed with an error, - * don't pass log page data to the consumers. In practice, this case - * should never happen. - */ - if (nvme_completion_is_error(cpl)) - nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, - aer->log_page_id, NULL, 0); - else { - /* Convert data to host endian */ - switch (aer->log_page_id) { - case NVME_LOG_ERROR: - err = (struct nvme_error_information_entry *)aer->log_page_buffer; - for (i = 0; i < (aer->ctrlr->cdata.elpe + 1); i++) - nvme_error_information_entry_swapbytes(err++); - break; - case NVME_LOG_HEALTH_INFORMATION: - nvme_health_information_page_swapbytes( - (struct nvme_health_information_page *)aer->log_page_buffer); - break; - case NVME_LOG_CHANGED_NAMESPACE: - nvme_ns_list_swapbytes( - (struct nvme_ns_list *)aer->log_page_buffer); - break; - case NVME_LOG_COMMAND_EFFECT: - nvme_command_effects_page_swapbytes( - (struct nvme_command_effects_page *)aer->log_page_buffer); - break; - case NVME_LOG_RES_NOTIFICATION: - nvme_res_notification_page_swapbytes( - (struct nvme_res_notification_page *)aer->log_page_buffer); - break; - case NVME_LOG_SANITIZE_STATUS: - nvme_sanitize_status_page_swapbytes( - (struct nvme_sanitize_status_page *)aer->log_page_buffer); - break; - default: - break; - } - - if (aer->log_page_id == NVME_LOG_HEALTH_INFORMATION) { - health_info = (struct nvme_health_information_page *) - aer->log_page_buffer; - nvme_ctrlr_log_critical_warnings(aer->ctrlr, - health_info->critical_warning); - /* - * Critical warnings reported through the - * SMART/health log page are persistent, so - * clear the associated bits in the async event - * config so that we do not receive repeated - * notifications for the same event. - */ - aer->ctrlr->async_event_config &= - ~health_info->critical_warning; - nvme_ctrlr_cmd_set_async_event_config(aer->ctrlr, - aer->ctrlr->async_event_config, NULL, NULL); - } else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE && - !nvme_use_nvd) { - nsl = (struct nvme_ns_list *)aer->log_page_buffer; - for (i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) { - if (nsl->ns[i] > NVME_MAX_NAMESPACES) - break; - nvme_notify_ns(aer->ctrlr, nsl->ns[i]); - } - } - - /* - * Pass the cpl data from the original async event completion, - * not the log page fetch. - */ - nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, - aer->log_page_id, aer->log_page_buffer, aer->log_page_size); - } - - /* - * Repost another asynchronous event request to replace the one - * that just completed. - */ - nvme_ctrlr_construct_and_submit_aer(aer->ctrlr, aer); -} - -static void nvme_ctrlr_async_event_cb(void *arg, const struct nvme_completion *cpl) { struct nvme_async_event_request *aer = arg; @@ -784,33 +694,18 @@ nvme_ctrlr_async_event_cb(void *arg, const struct nvme_completion *cpl) return; } - /* Associated log page is in bits 23:16 of completion entry dw0. */ + /* + * Save the completion status and associated log page is in bits 23:16 + * of completion entry dw0. Print a message and queue it for further + * processing. + */ + memcpy(&aer->cpl, cpl, sizeof(*cpl)); aer->log_page_id = NVMEV(NVME_ASYNC_EVENT_LOG_PAGE_ID, cpl->cdw0); - nvme_printf(aer->ctrlr, "async event occurred (type 0x%x, info 0x%02x," " page 0x%02x)\n", NVMEV(NVME_ASYNC_EVENT_TYPE, cpl->cdw0), NVMEV(NVME_ASYNC_EVENT_INFO, cpl->cdw0), aer->log_page_id); - - if (is_log_page_id_valid(aer->log_page_id)) { - aer->log_page_size = nvme_ctrlr_get_log_page_size(aer->ctrlr, - aer->log_page_id); - memcpy(&aer->cpl, cpl, sizeof(*cpl)); - nvme_ctrlr_cmd_get_log_page(aer->ctrlr, aer->log_page_id, - NVME_GLOBAL_NAMESPACE_TAG, aer->log_page_buffer, - aer->log_page_size, nvme_ctrlr_async_event_log_page_cb, - aer); - /* Wait to notify consumers until after log page is fetched. */ - } else { - nvme_notify_async_consumers(aer->ctrlr, cpl, aer->log_page_id, - NULL, 0); - - /* - * Repost another asynchronous event request to replace the one - * that just completed. - */ - nvme_ctrlr_construct_and_submit_aer(aer->ctrlr, aer); - } + taskqueue_enqueue(aer->ctrlr->taskqueue, &aer->task); } static void @@ -819,15 +714,21 @@ nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr, { struct nvme_request *req; - aer->ctrlr = ctrlr; /* - * XXX-MJ this should be M_WAITOK but we might be in a non-sleepable - * callback context. AER completions should be handled on a dedicated - * thread. + * We're racing the reset thread, so let that process submit this again. + * XXX does this really solve that race? And is that race even possible + * since we only reset when we've no theard from the card in a long + * time. Why would we get an AER in the middle of that just before we + * kick off the reset? */ - req = nvme_allocate_request_null(M_NOWAIT, nvme_ctrlr_async_event_cb, + if (ctrlr->is_resetting) + return; + + aer->ctrlr = ctrlr; + req = nvme_allocate_request_null(M_WAITOK, nvme_ctrlr_async_event_cb, aer); aer->req = req; + aer->log_page_id = 0; /* Not a valid page */ /* * Disable timeout here, since asynchronous event requests should by @@ -1203,6 +1104,140 @@ nvme_ctrlr_reset_task(void *arg, int pending) atomic_cmpset_32(&ctrlr->is_resetting, 1, 0); } +static void +nvme_ctrlr_aer_done(void *arg, const struct nvme_completion *cpl) +{ + struct nvme_async_event_request *aer = arg; + + mtx_lock(&aer->mtx); + if (nvme_completion_is_error(cpl)) + aer->log_page_size = (uint32_t)-1; + else + aer->log_page_size = nvme_ctrlr_get_log_page_size( + aer->ctrlr, aer->log_page_id); + wakeup(aer); + mtx_unlock(&aer->mtx); +} + +static void +nvme_ctrlr_aer_task(void *arg, int pending) +{ + struct nvme_async_event_request *aer = arg; + struct nvme_controller *ctrlr = aer->ctrlr; + uint32_t len; + + /* + * We're resetting, so just punt. + */ + if (ctrlr->is_resetting) + return; + + if (!is_log_page_id_valid(aer->log_page_id)) { + /* + * Repost another asynchronous event request to replace the one + * that just completed. + */ + nvme_notify_async_consumers(ctrlr, &aer->cpl, aer->log_page_id, + NULL, 0); + nvme_ctrlr_construct_and_submit_aer(ctrlr, aer); + goto out; + } + + aer->log_page_size = 0; + len = nvme_ctrlr_get_log_page_size(aer->ctrlr, aer->log_page_id); + nvme_ctrlr_cmd_get_log_page(aer->ctrlr, aer->log_page_id, + NVME_GLOBAL_NAMESPACE_TAG, aer->log_page_buffer, len, + nvme_ctrlr_aer_done, aer); + mtx_lock(&aer->mtx); + while (aer->log_page_size == 0) + mtx_sleep(aer, &aer->mtx, PRIBIO, "nvme_pt", 0); + mtx_unlock(&aer->mtx); + + if (aer->log_page_size != (uint32_t)-1) { + /* + * If the log page fetch for some reason completed with an + * error, don't pass log page data to the consumers. In + * practice, this case should never happen. + */ + nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, + aer->log_page_id, NULL, 0); + goto out; + } + + /* Convert data to host endian */ + switch (aer->log_page_id) { + case NVME_LOG_ERROR: { + struct nvme_error_information_entry *err = + (struct nvme_error_information_entry *)aer->log_page_buffer; + for (int i = 0; i < (aer->ctrlr->cdata.elpe + 1); i++) + nvme_error_information_entry_swapbytes(err++); + break; + } + case NVME_LOG_HEALTH_INFORMATION: + nvme_health_information_page_swapbytes( + (struct nvme_health_information_page *)aer->log_page_buffer); + break; + case NVME_LOG_CHANGED_NAMESPACE: + nvme_ns_list_swapbytes( + (struct nvme_ns_list *)aer->log_page_buffer); + break; + case NVME_LOG_COMMAND_EFFECT: + nvme_command_effects_page_swapbytes( + (struct nvme_command_effects_page *)aer->log_page_buffer); + break; + case NVME_LOG_RES_NOTIFICATION: + nvme_res_notification_page_swapbytes( + (struct nvme_res_notification_page *)aer->log_page_buffer); + break; + case NVME_LOG_SANITIZE_STATUS: + nvme_sanitize_status_page_swapbytes( + (struct nvme_sanitize_status_page *)aer->log_page_buffer); + break; + default: + break; + } + + if (aer->log_page_id == NVME_LOG_HEALTH_INFORMATION) { + struct nvme_health_information_page *health_info = + (struct nvme_health_information_page *)aer->log_page_buffer; + + /* + * Critical warnings reported through the SMART/health log page + * are persistent, so clear the associated bits in the async + * event config so that we do not receive repeated notifications + * for the same event. + */ + nvme_ctrlr_log_critical_warnings(aer->ctrlr, + health_info->critical_warning); + aer->ctrlr->async_event_config &= + ~health_info->critical_warning; + nvme_ctrlr_cmd_set_async_event_config(aer->ctrlr, + aer->ctrlr->async_event_config, NULL, NULL); + } else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE) { + struct nvme_ns_list *nsl = + (struct nvme_ns_list *)aer->log_page_buffer; + for (int i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) { + if (nsl->ns[i] > NVME_MAX_NAMESPACES) + break; + nvme_notify_ns(aer->ctrlr, nsl->ns[i]); + } + } + + /* + * Pass the cpl data from the original async event completion, not the + * log page fetch. + */ + nvme_notify_async_consumers(aer->ctrlr, &aer->cpl, + aer->log_page_id, aer->log_page_buffer, aer->log_page_size); + + /* + * Repost another asynchronous event request to replace the one + * that just completed. + */ +out: + nvme_ctrlr_construct_and_submit_aer(ctrlr, aer); +} + /* * Poll all the queues enabled on the device for completion. */ @@ -1574,13 +1609,8 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) /* * Create 2 threads for the taskqueue. The reset thread will block when * it detects that the controller has failed until all I/O has been - * failed up the stack. The fail_req task needs to be able to run in - * this case to finish the request failure for some cases. - * - * We could partially solve this race by draining the failed requeust - * queue before proceding to free the sim, though nothing would stop - * new I/O from coming in after we do that drain, but before we reach - * cam_sim_free, so this big hammer is used instead. + * failed up the stack. The second thread is used for AER events, which + * can block, but only briefly for memory and log page fetching. */ ctrlr->taskqueue = taskqueue_create("nvme_taskq", M_WAITOK, taskqueue_thread_enqueue, &ctrlr->taskqueue); @@ -1590,7 +1620,12 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev) ctrlr->is_initialized = false; ctrlr->notification_sent = 0; TASK_INIT(&ctrlr->reset_task, 0, nvme_ctrlr_reset_task, ctrlr); - STAILQ_INIT(&ctrlr->fail_req); + for (int i = 0; i < NVME_MAX_ASYNC_EVENTS; i++) { + struct nvme_async_event_request *aer = &ctrlr->aer[i]; + + TASK_INIT(&aer->task, 0, nvme_ctrlr_aer_task, aer); + mtx_init(&aer->mtx, "AER mutex", NULL, MTX_DEF); + } ctrlr->is_failed = false; make_dev_args_init(&md_args); @@ -1678,8 +1713,14 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev) } noadminq: - if (ctrlr->taskqueue) + if (ctrlr->taskqueue) { taskqueue_free(ctrlr->taskqueue); + for (int i = 0; i < NVME_MAX_ASYNC_EVENTS; i++) { + struct nvme_async_event_request *aer = &ctrlr->aer[i]; + + mtx_destroy(&aer->mtx); + } + } if (ctrlr->tag) bus_teardown_intr(ctrlr->dev, ctrlr->res, ctrlr->tag); diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h index 949e69ec9290..36f00fedc48e 100644 --- a/sys/dev/nvme/nvme_private.h +++ b/sys/dev/nvme/nvme_private.h @@ -123,6 +123,8 @@ struct nvme_request { struct nvme_async_event_request { struct nvme_controller *ctrlr; struct nvme_request *req; + struct task task; + struct mtx mtx; struct nvme_completion cpl; uint32_t log_page_id; uint32_t log_page_size; @@ -307,8 +309,6 @@ struct nvme_controller { bool isr_warned; bool is_initialized; - STAILQ_HEAD(, nvme_request) fail_req; - /* Host Memory Buffer */ int hmb_nchunks; size_t hmb_chunk; diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 4d0479dfb957..b99d784929bc 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -634,11 +634,89 @@ ofw_bus_find_iparent(phandle_t node) return (iparent); } +static phandle_t +ofw_bus_search_iparent(phandle_t node) +{ + phandle_t iparent; + + do { + if (OF_getencprop(node, "interrupt-parent", &iparent, + sizeof(iparent)) > 0) { + node = OF_node_from_xref(iparent); + } else { + node = OF_parent(node); + } + if (node == 0) + return (0); + } while (!OF_hasprop(node, "#interrupt-cells")); + + return (OF_xref_from_node(node)); +} + +static int +ofw_bus_traverse_imap(phandle_t inode, phandle_t node, uint32_t *intr, + int intrsz, pcell_t *res, int ressz, phandle_t *iparentp) +{ + struct ofw_bus_iinfo ii; + void *reg; + uint32_t *intrp; + phandle_t iparent; + int rv = 0; + + /* We already have an interrupt controller */ + if (OF_hasprop(node, "interrupt-controller")) + return (0); + + intrp = malloc(intrsz, M_OFWPROP, M_WAITOK); + memcpy(intrp, intr, intrsz); + + while (true) { + /* There is no interrupt-map to follow */ + if (!OF_hasprop(inode, "interrupt-map")) { + free(intrp, M_OFWPROP); + return (0); + } + + memset(&ii, 0, sizeof(ii)); + ofw_bus_setup_iinfo(inode, &ii, sizeof(cell_t)); + + reg = NULL; + if (ii.opi_addrc > 0) + reg = malloc(ii.opi_addrc, M_OFWPROP, M_WAITOK); + + rv = ofw_bus_lookup_imap(node, &ii, reg, ii.opi_addrc, intrp, + intrsz, res, ressz, &iparent); + + free(reg, M_OFWPROP); + free(ii.opi_imap, M_OFWPROP); + free(ii.opi_imapmsk, M_OFWPROP); + free(intrp, M_OFWPROP); + + if (rv == 0) + return (0); + + node = inode; + inode = OF_node_from_xref(iparent); + + /* Stop when we have an interrupt controller */ + if (OF_hasprop(inode, "interrupt-controller")) { + *iparentp = iparent; + return (rv); + } + + intrsz = rv * sizeof(pcell_t); + intrp = malloc(intrsz, M_OFWPROP, M_WAITOK); + memcpy(intrp, res, intrsz); + } +} + int ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, int *rlen) { - phandle_t iparent; + phandle_t iparent, iparent_node; + uint32_t result[16]; + uint32_t intrpcells, *intrp; uint32_t icells, *intr; int err, i, irqnum, nintr, rid; bool extended; @@ -646,15 +724,16 @@ ofw_bus_intr_to_rl(device_t dev, phandle_t node, nintr = OF_getencprop_alloc_multi(node, "interrupts", sizeof(*intr), (void **)&intr); if (nintr > 0) { - iparent = ofw_bus_find_iparent(node); + iparent = ofw_bus_search_iparent(node); if (iparent == 0) { device_printf(dev, "No interrupt-parent found, " "assuming direct parent\n"); iparent = OF_parent(node); iparent = OF_xref_from_node(iparent); } - if (OF_searchencprop(OF_node_from_xref(iparent), - "#interrupt-cells", &icells, sizeof(icells)) == -1) { + iparent_node = OF_node_from_xref(iparent); + if (OF_searchencprop(iparent_node, "#interrupt-cells", &icells, + sizeof(icells)) == -1) { device_printf(dev, "Missing #interrupt-cells " "property, assuming <1>\n"); icells = 1; @@ -677,7 +756,8 @@ ofw_bus_intr_to_rl(device_t dev, phandle_t node, for (i = 0; i < nintr; i += icells) { if (extended) { iparent = intr[i++]; - if (OF_searchencprop(OF_node_from_xref(iparent), + iparent_node = OF_node_from_xref(iparent); + if (OF_searchencprop(iparent_node, "#interrupt-cells", &icells, sizeof(icells)) == -1) { device_printf(dev, "Missing #interrupt-cells " "property\n"); @@ -691,7 +771,16 @@ ofw_bus_intr_to_rl(device_t dev, phandle_t node, break; } } - irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]); + + intrp = &intr[i]; + intrpcells = ofw_bus_traverse_imap(iparent_node, node, intrp, + icells * sizeof(intr[0]), result, sizeof(result), &iparent); + if (intrpcells > 0) + intrp = result; + else + intrpcells = icells; + + irqnum = ofw_bus_map_intr(dev, iparent, intrpcells, intrp); resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1); } if (rlen != NULL) diff --git a/sys/dev/qlnx/qlnxe/qlnx_os.c b/sys/dev/qlnx/qlnxe/qlnx_os.c index 05ec69a70dfe..4ad190374f87 100644 --- a/sys/dev/qlnx/qlnxe/qlnx_os.c +++ b/sys/dev/qlnx/qlnxe/qlnx_os.c @@ -30,6 +30,8 @@ * Author : David C Somayajulu, Cavium, Inc., San Jose, CA 95131. */ +#include "opt_inet.h" + #include <sys/cdefs.h> #include "qlnx_os.h" #include "bcm_osal.h" @@ -2306,8 +2308,6 @@ qlnx_init_ifnet(device_t dev, qlnx_host_t *ha) else if (device_id == QLOGIC_PCI_DEVICE_ID_1644) if_setbaudrate(ifp, IF_Gbps(100)); - if_setcapabilities(ifp, IFCAP_LINKSTATE); - if_setinitfn(ifp, qlnx_init); if_setsoftc(ifp, ha); if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); @@ -2341,7 +2341,6 @@ qlnx_init_ifnet(device_t dev, qlnx_host_t *ha) if_setcapabilities(ifp, IFCAP_HWCSUM); if_setcapabilitiesbit(ifp, IFCAP_JUMBO_MTU, 0); - if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWTAGGING, 0); if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER, 0); @@ -2350,6 +2349,8 @@ qlnx_init_ifnet(device_t dev, qlnx_host_t *ha) if_setcapabilitiesbit(ifp, IFCAP_TSO4, 0); if_setcapabilitiesbit(ifp, IFCAP_TSO6, 0); if_setcapabilitiesbit(ifp, IFCAP_LRO, 0); + if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0); + if_setcapabilitiesbit(ifp, IFCAP_HWSTATS, 0); if_sethwtsomax(ifp, QLNX_MAX_TSO_FRAME_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)); @@ -2778,7 +2779,7 @@ qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data) if (!p_ptt) { QL_DPRINT1(ha, "ecore_ptt_acquire failed\n"); - ret = -1; + ret = ERESTART; break; } @@ -2789,7 +2790,7 @@ qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data) ecore_ptt_release(p_hwfn, p_ptt); if (ret) { - ret = -1; + ret = ENODEV; break; } diff --git a/sys/dev/random/fortuna.c b/sys/dev/random/fortuna.c index c4282c723a44..8363de99a60a 100644 --- a/sys/dev/random/fortuna.c +++ b/sys/dev/random/fortuna.c @@ -341,6 +341,13 @@ random_fortuna_process_event(struct harvest_event *event) u_int pl; RANDOM_RESEED_LOCK(); + /* + * Run SP 800-90B health tests on the source if so configured. + */ + if (!random_harvest_healthtest(event)) { + RANDOM_RESEED_UNLOCK(); + return; + } /*- * FS&K - P_i = P_i|<harvested stuff> * Accumulate the event into the appropriate pool diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c index 395310b115fb..c7762967c4fb 100644 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -88,6 +88,8 @@ static void random_sources_feed(void); static __read_mostly bool epoch_inited; static __read_mostly epoch_t rs_epoch; +static const char *random_source_descr[ENTROPYSOURCE]; + /* * How many events to queue up. We create this many items in * an 'empty' queue, then transfer them to the 'harvest' queue with @@ -299,6 +301,230 @@ random_sources_feed(void) explicit_bzero(entropy, sizeof(entropy)); } +/* + * State used for conducting NIST SP 800-90B health tests on entropy sources. + */ +static struct health_test_softc { + uint32_t ht_rct_value[HARVESTSIZE + 1]; + u_int ht_rct_count; /* number of samples with the same value */ + u_int ht_rct_limit; /* constant after init */ + + uint32_t ht_apt_value[HARVESTSIZE + 1]; + u_int ht_apt_count; /* number of samples with the same value */ + u_int ht_apt_seq; /* sequence number of the last sample */ + u_int ht_apt_cutoff; /* constant after init */ + + uint64_t ht_total_samples; + bool ondemand; /* Set to true to restart the state machine */ + enum { + INIT = 0, /* initial state */ + DISABLED, /* health checking is disabled */ + STARTUP, /* doing startup tests, samples are discarded */ + STEADY, /* steady-state operation */ + FAILED, /* health check failed, discard samples */ + } ht_state; +} healthtest[ENTROPYSOURCE]; + +#define RANDOM_SELFTEST_STARTUP_SAMPLES 1024 /* 4.3, requirement 4 */ +#define RANDOM_SELFTEST_APT_WINDOW 512 /* 4.4.2 */ + +static void +copy_event(uint32_t dst[static HARVESTSIZE + 1], + const struct harvest_event *event) +{ + memset(dst, 0, sizeof(uint32_t) * (HARVESTSIZE + 1)); + memcpy(dst, event->he_entropy, event->he_size); + dst[HARVESTSIZE] = event->he_somecounter; +} + +static void +random_healthtest_rct_init(struct health_test_softc *ht, + const struct harvest_event *event) +{ + ht->ht_rct_count = 1; + copy_event(ht->ht_rct_value, event); +} + +/* + * Apply the repitition count test to a sample. + * + * Return false if the test failed, i.e., we observed >= C consecutive samples + * with the same value, and true otherwise. + */ +static bool +random_healthtest_rct_next(struct health_test_softc *ht, + const struct harvest_event *event) +{ + uint32_t val[HARVESTSIZE + 1]; + + copy_event(val, event); + if (memcmp(val, ht->ht_rct_value, sizeof(ht->ht_rct_value)) != 0) { + ht->ht_rct_count = 1; + memcpy(ht->ht_rct_value, val, sizeof(ht->ht_rct_value)); + return (true); + } else { + ht->ht_rct_count++; + return (ht->ht_rct_count < ht->ht_rct_limit); + } +} + +static void +random_healthtest_apt_init(struct health_test_softc *ht, + const struct harvest_event *event) +{ + ht->ht_apt_count = 1; + ht->ht_apt_seq = 1; + copy_event(ht->ht_apt_value, event); +} + +static bool +random_healthtest_apt_next(struct health_test_softc *ht, + const struct harvest_event *event) +{ + uint32_t val[HARVESTSIZE + 1]; + + if (ht->ht_apt_seq == 0) { + random_healthtest_apt_init(ht, event); + return (true); + } + + copy_event(val, event); + if (memcmp(val, ht->ht_apt_value, sizeof(ht->ht_apt_value)) == 0) { + ht->ht_apt_count++; + if (ht->ht_apt_count >= ht->ht_apt_cutoff) + return (false); + } + + ht->ht_apt_seq++; + if (ht->ht_apt_seq == RANDOM_SELFTEST_APT_WINDOW) + ht->ht_apt_seq = 0; + + return (true); +} + +/* + * Run the health tests for the given event. This is assumed to be called from + * a serialized context. + */ +bool +random_harvest_healthtest(const struct harvest_event *event) +{ + struct health_test_softc *ht; + + ht = &healthtest[event->he_source]; + + /* + * Was on-demand testing requested? Restart the state machine if so, + * restarting the startup tests. + */ + if (atomic_load_bool(&ht->ondemand)) { + atomic_store_bool(&ht->ondemand, false); + ht->ht_state = INIT; + } + + switch (ht->ht_state) { + case __predict_false(INIT): + /* Store the first sample and initialize test state. */ + random_healthtest_rct_init(ht, event); + random_healthtest_apt_init(ht, event); + ht->ht_total_samples = 0; + ht->ht_state = STARTUP; + return (false); + case DISABLED: + /* No health testing for this source. */ + return (true); + case STEADY: + case STARTUP: + ht->ht_total_samples++; + if (random_healthtest_rct_next(ht, event) && + random_healthtest_apt_next(ht, event)) { + if (ht->ht_state == STARTUP && + ht->ht_total_samples >= + RANDOM_SELFTEST_STARTUP_SAMPLES) { + printf( + "random: health test passed for source %s\n", + random_source_descr[event->he_source]); + ht->ht_state = STEADY; + } + return (ht->ht_state == STEADY); + } + ht->ht_state = FAILED; + printf( + "random: health test failed for source %s, discarding samples\n", + random_source_descr[event->he_source]); + /* FALLTHROUGH */ + case FAILED: + return (false); + } +} + +static bool nist_healthtest_enabled = false; +SYSCTL_BOOL(_kern_random, OID_AUTO, nist_healthtest_enabled, + CTLFLAG_RDTUN, &nist_healthtest_enabled, 0, + "Enable NIST SP 800-90B health tests for noise sources"); + +static void +random_healthtest_init(enum random_entropy_source source) +{ + struct health_test_softc *ht; + + ht = &healthtest[source]; + KASSERT(ht->ht_state == INIT, + ("%s: health test state is %d for source %d", + __func__, ht->ht_state, source)); + + /* + * If health-testing is enabled, validate all sources except CACHED and + * VMGENID: they are deterministic sources used only a small, fixed + * number of times, so statistical testing is not applicable. + */ + if (!nist_healthtest_enabled || + source == RANDOM_CACHED || source == RANDOM_PURE_VMGENID) { + ht->ht_state = DISABLED; + return; + } + + /* + * Set cutoff values for the two tests, assuming that each sample has + * min-entropy of 1 bit and allowing for an error rate of 1 in 2^{34}. + * With a sample rate of RANDOM_KTHREAD_HZ, we expect to see an false + * positive once in ~54.5 years. + * + * The RCT limit comes from the formula in section 4.4.1. + * + * The APT cutoff is calculated using the formula in section 4.4.2 + * footnote 10 with the window size changed from 512 to 511, since the + * test as written counts the number of samples equal to the first + * sample in the window, and thus tests W-1 samples. + */ + ht->ht_rct_limit = 35; + ht->ht_apt_cutoff = 330; +} + +static int +random_healthtest_ondemand(SYSCTL_HANDLER_ARGS) +{ + u_int mask, source; + int error; + + mask = 0; + error = sysctl_handle_int(oidp, &mask, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + while (mask != 0) { + source = ffs(mask) - 1; + if (source < nitems(healthtest)) + atomic_store_bool(&healthtest[source].ondemand, true); + mask &= ~(1u << source); + } + return (0); +} +SYSCTL_PROC(_kern_random, OID_AUTO, nist_healthtest_ondemand, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, + random_healthtest_ondemand, "I", + "Re-run NIST SP 800-90B startup health tests for a noise source"); + static int random_check_uint_harvestmask(SYSCTL_HANDLER_ARGS) { @@ -362,7 +588,8 @@ static const char *random_source_descr[ENTROPYSOURCE] = { [RANDOM_SWI] = "SWI", [RANDOM_FS_ATIME] = "FS_ATIME", [RANDOM_UMA] = "UMA", - [RANDOM_CALLOUT] = "CALLOUT", /* ENVIRONMENTAL_END */ + [RANDOM_CALLOUT] = "CALLOUT", + [RANDOM_RANDOMDEV] = "RANDOMDEV", /* ENVIRONMENTAL_END */ [RANDOM_PURE_OCTEON] = "PURE_OCTEON", /* PURE_START */ [RANDOM_PURE_SAFE] = "PURE_SAFE", [RANDOM_PURE_GLXSB] = "PURE_GLXSB", @@ -424,6 +651,9 @@ random_harvestq_init(void *unused __unused) hc_source_mask = almost_everything_mask; RANDOM_HARVEST_INIT_LOCK(); harvest_context.hc_active_buf = 0; + + for (int i = 0; i < ENTROPYSOURCE; i++) + random_healthtest_init(i); } SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_THIRD, random_harvestq_init, NULL); diff --git a/sys/dev/random/random_harvestq.h b/sys/dev/random/random_harvestq.h index 7804bf52aa4f..1d462500df85 100644 --- a/sys/dev/random/random_harvestq.h +++ b/sys/dev/random/random_harvestq.h @@ -49,4 +49,6 @@ random_get_cyclecount(void) return ((uint32_t)get_cyclecount()); } +bool random_harvest_healthtest(const struct harvest_event *event); + #endif /* SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED */ diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index 9d1c7b1167c8..ced4dd8067d9 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -312,7 +312,7 @@ randomdev_accumulate(uint8_t *buf, u_int count) for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) { event.he_somecounter = random_get_cyclecount(); event.he_size = sizeof(event.he_entropy); - event.he_source = RANDOM_CACHED; + event.he_source = RANDOM_RANDOMDEV; event.he_destination = destination++; /* Harmless cheating */ memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy)); p_random_alg_context->ra_event_processor(&event); diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h index cac743884ee6..ac58d44102a0 100644 --- a/sys/dev/ufshci/ufshci_private.h +++ b/sys/dev/ufshci/ufshci_private.h @@ -149,6 +149,8 @@ struct ufshci_hw_queue { bus_dmamap_t queuemem_map; bus_addr_t req_queue_addr; + bus_addr_t *ucd_bus_addr; + uint32_t num_entries; uint32_t num_trackers; @@ -198,8 +200,6 @@ struct ufshci_req_queue { bus_dma_tag_t dma_tag_payload; bus_dmamap_t ucdmem_map; - - bus_addr_t ucd_addr; }; struct ufshci_device { diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c index 4670281d367a..b1f303afaef5 100644 --- a/sys/dev/ufshci/ufshci_req_sdb.c +++ b/sys/dev/ufshci/ufshci_req_sdb.c @@ -48,6 +48,29 @@ ufshci_req_sdb_cmd_desc_destroy(struct ufshci_req_queue *req_queue) } } +static void +ufshci_ucd_map(void *arg, bus_dma_segment_t *seg, int nseg, int error) +{ + struct ufshci_hw_queue *hwq = arg; + int i; + + if (error != 0) { + printf("ufshci: Failed to map UCD, error = %d\n", error); + return; + } + + if (hwq->num_trackers != nseg) { + printf( + "ufshci: Failed to map UCD, num_trackers = %d, nseg = %d\n", + hwq->num_trackers, nseg); + return; + } + + for (i = 0; i < nseg; i++) { + hwq->ucd_bus_addr[i] = seg[i].ds_addr; + } +} + static int ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, uint32_t num_entries, struct ufshci_controller *ctrlr) @@ -55,7 +78,6 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q]; struct ufshci_tracker *tr; size_t ucd_allocsz, payload_allocsz; - uint64_t ucdmem_phys; uint8_t *ucdmem; int i, error; @@ -71,10 +93,11 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, * Allocate physical memory for UTP Command Descriptor (UCD) * Note: UFSHCI UCD format is restricted to 128-byte alignment. */ - error = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev), 128, - ctrlr->page_size, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - ucd_allocsz, howmany(ucd_allocsz, ctrlr->page_size), - ctrlr->page_size, 0, NULL, NULL, &req_queue->dma_tag_ucd); + error = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev), 128, 0, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, ucd_allocsz, + howmany(ucd_allocsz, sizeof(struct ufshci_utp_cmd_desc)), + sizeof(struct ufshci_utp_cmd_desc), 0, NULL, NULL, + &req_queue->dma_tag_ucd); if (error != 0) { ufshci_printf(ctrlr, "request cmd desc tag create failed %d\n", error); @@ -88,7 +111,7 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, } if (bus_dmamap_load(req_queue->dma_tag_ucd, req_queue->ucdmem_map, - ucdmem, ucd_allocsz, ufshci_single_map, &ucdmem_phys, 0) != 0) { + ucdmem, ucd_allocsz, ufshci_ucd_map, hwq, 0) != 0) { ufshci_printf(ctrlr, "failed to load cmd desc memory\n"); bus_dmamem_free(req_queue->dma_tag_ucd, req_queue->ucd, req_queue->ucdmem_map); @@ -96,7 +119,6 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, } req_queue->ucd = (struct ufshci_utp_cmd_desc *)ucdmem; - req_queue->ucd_addr = ucdmem_phys; /* * Allocate physical memory for PRDT @@ -128,10 +150,9 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue, tr->slot_state = UFSHCI_SLOT_STATE_FREE; tr->ucd = (struct ufshci_utp_cmd_desc *)ucdmem; - tr->ucd_bus_addr = ucdmem_phys; + tr->ucd_bus_addr = hwq->ucd_bus_addr[i]; ucdmem += sizeof(struct ufshci_utp_cmd_desc); - ucdmem_phys += sizeof(struct ufshci_utp_cmd_desc); hwq->act_tr[i] = tr; } @@ -175,6 +196,11 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr, req_queue->hwq = malloc(sizeof(struct ufshci_hw_queue), M_UFSHCI, M_ZERO | M_NOWAIT); 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); mtx_init(&hwq->qlock, "ufshci req_queue lock", NULL, MTX_DEF); @@ -277,6 +303,7 @@ ufshci_req_sdb_destroy(struct ufshci_controller *ctrlr, if (mtx_initialized(&hwq->qlock)) mtx_destroy(&hwq->qlock); + free(req_queue->hwq->ucd_bus_addr, M_UFSHCI); free(req_queue->hwq, M_UFSHCI); } diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c index 64039575c0ad..675c0573bd7e 100644 --- a/sys/dev/vt/hw/vga/vt_vga.c +++ b/sys/dev/vt/hw/vga/vt_vga.c @@ -1347,7 +1347,7 @@ vga_postswitch(struct vt_device *vd) /* Reinit VGA mode, to restore view after app which change mode. */ vga_initialize(vd, (vd->vd_flags & VDF_TEXTMODE)); - /* Ask vt(9) to update chars on visible area. */ + /* Ask vt(4) to update chars on visible area. */ vd->vd_flags |= VDF_INVALID; } diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index b0f58b38a6f1..b51ef6766de4 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -125,10 +125,10 @@ static const struct terminal_class vt_termclass = { (vw)->vw_number) static SYSCTL_NODE(_kern, OID_AUTO, vt, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, - "vt(9) parameters"); + "vt(4) parameters"); static VT_SYSCTL_INT(enable_altgr, 1, "Enable AltGr key (Do not assume R.Alt as Alt)"); static VT_SYSCTL_INT(enable_bell, 0, "Enable bell"); -static VT_SYSCTL_INT(debug, 0, "vt(9) debug level"); +static VT_SYSCTL_INT(debug, 0, "vt(4) debug level"); static VT_SYSCTL_INT(deadtimer, 15, "Time to wait busy process in VT_PROCESS mode"); static VT_SYSCTL_INT(suspendswitch, 1, "Switch to VT0 before suspend"); diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 676ea5de12b8..58a22b8bdc50 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -547,6 +547,8 @@ fdesc_readdir(struct vop_readdir_args *ap) fmp = VFSTOFDESC(ap->a_vp->v_mount); if (ap->a_ncookies != NULL) *ap->a_ncookies = 0; + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 0; off = (int)uio->uio_offset; if (off != uio->uio_offset || off < 0 || (u_int)off % UIO_MX != 0 || @@ -559,7 +561,12 @@ fdesc_readdir(struct vop_readdir_args *ap) fcnt = i - 2; /* The first two nodes are `.' and `..' */ FILEDESC_SLOCK(fdp); - while (i < fdp->fd_nfiles + 2 && uio->uio_resid >= UIO_MX) { + while (uio->uio_resid >= UIO_MX) { + if (i >= fdp->fd_nfiles + 2) { + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 1; + break; + } bzero((caddr_t)dp, UIO_MX); switch (i) { case 0: /* `.' */ diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c index da4848169173..208b64930e61 100644 --- a/sys/fs/msdosfs/msdosfs_conv.c +++ b/sys/fs/msdosfs/msdosfs_conv.c @@ -797,19 +797,24 @@ mbsadjpos(const char **instr, size_t inlen, size_t outlen, int weight, int flag, static u_char * dos2unixchr(u_char *outbuf, const u_char **instr, size_t *ilen, int lower, struct msdosfsmount *pmp) { - u_char c, *outp; - size_t len, olen; + u_char c, *outp, *outp1; + size_t i, len, olen; outp = outbuf; if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { olen = len = 4; + outp1 = outp; if (lower & (LCASE_BASE | LCASE_EXT)) msdosfs_iconv->convchr_case(pmp->pm_d2u, (const char **)instr, ilen, (char **)&outp, &olen, KICONV_LOWER); else msdosfs_iconv->convchr(pmp->pm_d2u, (const char **)instr, ilen, (char **)&outp, &olen); + for (i = 0; i < outp - outp1; i++) { + if (outp1[i] == '/') + outp1[i] = '?'; + } len -= olen; /* @@ -826,6 +831,8 @@ dos2unixchr(u_char *outbuf, const u_char **instr, size_t *ilen, int lower, struc c = dos2unix[c]; if (lower & (LCASE_BASE | LCASE_EXT)) c = u2l[c]; + if (c == '/') + c = '?'; *outp++ = c; outbuf[1] = '\0'; } diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 4c498e96a3c0..a957315aaa12 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -647,7 +647,8 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap, NFSATTRBIT_TIMECREATE)) NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE); (void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0, - &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL); + &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, + false, false, false); break; } } @@ -2646,7 +2647,8 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram, int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno, - struct statfs *pnfssf) + struct statfs *pnfssf, bool xattrsupp, bool has_hiddensystem, + bool has_namedattr) { int bitpos, retnum = 0; u_int32_t *tl; @@ -2660,10 +2662,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, struct nfsfsinfo fsinf; struct timespec temptime; NFSACL_T *aclp, *naclp = NULL; - size_t atsiz; - bool xattrsupp; short irflag; - long has_pathconf; #ifdef QUOTA struct dqblk dqb; uid_t savuid; @@ -2747,18 +2746,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, } } - /* Check to see if Extended Attributes are supported. */ - xattrsupp = false; - if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_XATTRSUPPORT)) { - if (NFSVOPLOCK(vp, LK_SHARED) == 0) { - error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, - "xxx", NULL, &atsiz, cred, p); - NFSVOPUNLOCK(vp); - if (error != EOPNOTSUPP) - xattrsupp = true; - } - } - /* * Put out the attribute bitmap for the ones being filled in * and get the field for the number of attributes returned. @@ -2780,11 +2767,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT); NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL); } - if (cred == NULL || p == NULL || vp == NULL || - VOP_PATHCONF(vp, _PC_HAS_HIDDENSYSTEM, - &has_pathconf) != 0) - has_pathconf = 0; - if (has_pathconf == 0) { + if (!has_hiddensystem) { NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN); NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM); } @@ -2828,10 +2811,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, break; case NFSATTRBIT_NAMEDATTR: NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); - if (VOP_PATHCONF(vp, _PC_HAS_NAMEDATTR, - &has_pathconf) != 0) - has_pathconf = 0; - if (has_pathconf != 0) + if (has_namedattr) *tl = newnfs_true; else *tl = newnfs_false; diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 3b6c1ec90c06..54f60a753c50 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -395,8 +395,9 @@ int nfsrv_putopbit(struct nfsrv_descript *, nfsopbit_t *); void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int, struct nfsvattr *); int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *, - struct vattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *); + struct vattr *, fhandle_t *, int, nfsattrbit_t *, struct ucred *, + NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *, bool, bool, + bool); void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *); struct mbuf *nfsrv_adj(struct mbuf *, int, int); void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *); @@ -735,7 +736,8 @@ int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct nfsrv_descript *, NFSPROC_T *); int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t); + struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, bool, bool, + bool); int nfsrv_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, NFSACL_T *, NFSPROC_T *); int nfsv4_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index e0e66baca44d..2f3c59b68518 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -5436,7 +5436,8 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p, NFSZERO_ATTRBIT(&attrbits); NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); (void) nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0, - &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL); + &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, false, false, + false); error = nfscl_request(nd, vp, p, cred); if (error) return (error); diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 1ae5ed1a75ca..99a781640c53 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -3701,7 +3701,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p) if (!error) (void) nfsv4_fillattr(nd, NULL, NULL, NULL, &va, NULL, 0, &rattrbits, NULL, p, 0, 0, 0, 0, - (uint64_t)0, NULL); + (uint64_t)0, NULL, false, false, false); break; case NFSV4OP_CBRECALL: NFSCL_DEBUG(4, "cbrecall\n"); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 43ee0383669f..4f0d5946d6b9 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -2112,7 +2112,8 @@ int nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp, struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, struct ucred *cred, struct thread *p, int isdgram, int reterr, - int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno) + int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno, + bool xattrsupp, bool has_hiddensystem, bool has_namedattr) { struct statfs *sf; int error; @@ -2131,7 +2132,7 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp, } error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror, attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root, - mounted_on_fileno, sf); + mounted_on_fileno, sf, xattrsupp, has_hiddensystem, has_namedattr); free(sf, M_TEMP); NFSEXITCODE2(0, nd); return (error); @@ -2448,7 +2449,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, struct nfsvattr nva, at, *nvap = &nva; struct mbuf *mb0, *mb1; struct nfsreferral *refp; - int nlen, r, error = 0, getret = 1, usevget = 1; + int nlen, r, error = 0, getret = 1, ret, usevget = 1; int siz, cnt, fullsiz, eofflag, ncookies, entrycnt; caddr_t bpos0, bpos1; u_int64_t off, toff, verf __unused; @@ -2462,6 +2463,9 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, uint64_t mounted_on_fileno; struct thread *p = curthread; int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1; + size_t atsiz; + long pathval; + bool has_hiddensystem, has_namedattr, xattrsupp; if (nd->nd_repstat) { nfsrv_postopattr(nd, getret, &at); @@ -2936,9 +2940,32 @@ again: *tl++ = newnfs_true; txdr_hyper(*cookiep, tl); dirlen += nfsm_strtom(nd, dp->d_name, nlen); + xattrsupp = false; + has_hiddensystem = false; + has_namedattr = false; if (nvp != NULL) { supports_nfsv4acls = nfs_supportsnfsv4acls(nvp); + if (NFSISSET_ATTRBIT(&attrbits, + NFSATTRBIT_XATTRSUPPORT)) { + ret = VOP_GETEXTATTR(nvp, + EXTATTR_NAMESPACE_USER, + "xxx", NULL, &atsiz, + nd->nd_cred, p); + xattrsupp = ret != EOPNOTSUPP; + } + if (VOP_PATHCONF(nvp, + _PC_HAS_HIDDENSYSTEM, &pathval) != + 0) + pathval = 0; + has_hiddensystem = pathval > 0; + pathval = 0; + if (NFSISSET_ATTRBIT(&attrbits, + NFSATTRBIT_NAMEDATTR) && + VOP_PATHCONF(nvp, _PC_HAS_NAMEDATTR, + &pathval) != 0) + pathval = 0; + has_namedattr = pathval > 0; NFSVOPUNLOCK(nvp); } else supports_nfsv4acls = 0; @@ -2958,13 +2985,15 @@ again: nvp, nvap, &nfh, r, &rderrbits, nd->nd_cred, p, isdgram, 0, supports_nfsv4acls, at_root, - mounted_on_fileno); + mounted_on_fileno, xattrsupp, + has_hiddensystem, has_namedattr); } else { dirlen += nfsvno_fillattr(nd, new_mp, nvp, nvap, &nfh, r, &attrbits, nd->nd_cred, p, isdgram, 0, supports_nfsv4acls, at_root, - mounted_on_fileno); + mounted_on_fileno, xattrsupp, + has_hiddensystem, has_namedattr); } if (nvp != NULL) vrele(nvp); @@ -6356,7 +6385,7 @@ nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, * the same type (VREG). */ nfsv4_fillattr(nd, NULL, vp, aclp, NULL, NULL, 0, &attrbits, NULL, - NULL, 0, 0, 0, 0, 0, NULL); + NULL, 0, 0, 0, 0, 0, NULL, false, false, false); error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); if (error != 0) { diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index f7564ade401b..9eebcda548c6 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -241,7 +241,7 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, { struct nfsvattr nva; fhandle_t fh; - int at_root = 0, error = 0, supports_nfsv4acls; + int at_root = 0, error = 0, ret, supports_nfsv4acls; struct nfsreferral *refp; nfsattrbit_t attrbits, tmpbits; struct mount *mp; @@ -250,6 +250,9 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, uint64_t mounted_on_fileno = 0; accmode_t accmode; struct thread *p = curthread; + size_t atsiz; + long pathval; + bool has_hiddensystem, has_namedattr, xattrsupp; if (nd->nd_repstat) goto out; @@ -307,6 +310,26 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, &nva, &attrbits, p); if (nd->nd_repstat == 0) { supports_nfsv4acls = nfs_supportsnfsv4acls(vp); + xattrsupp = false; + if (NFSISSET_ATTRBIT(&attrbits, + NFSATTRBIT_XATTRSUPPORT)) { + ret = VOP_GETEXTATTR(vp, + EXTATTR_NAMESPACE_USER, + "xxx", NULL, &atsiz, nd->nd_cred, + p); + xattrsupp = ret != EOPNOTSUPP; + } + if (VOP_PATHCONF(vp, _PC_HAS_HIDDENSYSTEM, + &pathval) != 0) + pathval = 0; + has_hiddensystem = pathval > 0; + pathval = 0; + if (NFSISSET_ATTRBIT(&attrbits, + NFSATTRBIT_NAMEDATTR) && + VOP_PATHCONF(vp, _PC_HAS_NAMEDATTR, + &pathval) != 0) + pathval = 0; + has_namedattr = pathval > 0; mp = vp->v_mount; if (nfsrv_enable_crossmntpt != 0 && vp->v_type == VDIR && @@ -340,7 +363,9 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, (void)nfsvno_fillattr(nd, mp, vp, &nva, &fh, 0, &attrbits, nd->nd_cred, p, isdgram, 1, supports_nfsv4acls, - at_root, mounted_on_fileno); + at_root, mounted_on_fileno, + xattrsupp, has_hiddensystem, + has_namedattr); vfs_unbusy(mp); } vrele(vp); @@ -4353,9 +4378,10 @@ nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram, int error = 0; NFSNAMEICNDSET(&cn, nd->nd_cred, LOOKUP, OPENNAMED | ISLASTCN | - NOFOLLOW); + NOFOLLOW | LOCKLEAF); cn.cn_nameptr = "."; cn.cn_namelen = 1; + cn.cn_lkflags = LK_SHARED; NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); if (*tl == newnfs_true) cn.cn_flags |= CREATENAMED; @@ -4374,6 +4400,8 @@ nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram, if (nd->nd_repstat == ENOATTR) nd->nd_repstat = NFSERR_NOENT; } + if (nd->nd_repstat == 0) + NFSVOPUNLOCK(*vpp); vput(dp); NFSEXITCODE2(0, nd); diff --git a/sys/fs/p9fs/p9fs_vnops.c b/sys/fs/p9fs/p9fs_vnops.c index 56bf766ef801..227e2b93883e 100644 --- a/sys/fs/p9fs/p9fs_vnops.c +++ b/sys/fs/p9fs/p9fs_vnops.c @@ -1784,6 +1784,9 @@ p9fs_readdir(struct vop_readdir_args *ap) return (EBADF); } + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 0; + io_buffer = uma_zalloc(p9fs_io_buffer_zone, M_WAITOK); /* We haven't reached the end yet. read more. */ @@ -1801,8 +1804,11 @@ p9fs_readdir(struct vop_readdir_args *ap) count = p9_client_readdir(vofid, (char *)io_buffer, diroffset, count); - if (count == 0) + if (count == 0) { + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 1; break; + } if (count < 0) { error = EIO; diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index 0bdfedffafcb..8cd092118d0e 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -850,7 +850,7 @@ pfs_readdir(struct vop_readdir_args *va) struct uio *uio; struct pfsentry *pfsent, *pfsent2; struct pfsdirentlist lst; - off_t offset; + off_t coffset, offset; int error, i, resid; STAILQ_INIT(&lst); @@ -860,6 +860,9 @@ pfs_readdir(struct vop_readdir_args *va) PFS_TRACE(("%s pid %lu", pd->pn_name, (unsigned long)pid)); pfs_assert_not_owned(pd); + if (va->a_eofflag != NULL) + *va->a_eofflag = 0; + if (vn->v_type != VDIR) PFS_RETURN (ENOTDIR); KASSERT_PN_IS_DIR(pd); @@ -878,6 +881,10 @@ pfs_readdir(struct vop_readdir_args *va) if (pid != NO_PID && !pfs_lookup_proc(pid, &proc)) PFS_RETURN (ENOENT); + /* + * The allproc lock is required in pfs_iterate() for procdir + * directories. + */ sx_slock(&allproc_lock); pfs_lock(pd); @@ -897,23 +904,15 @@ pfs_readdir(struct vop_readdir_args *va) } } - /* skip unwanted entries */ - for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) { + for (pn = NULL, p = NULL, coffset = 0; resid >= PFS_DELEN; + coffset += PFS_DELEN) { if (pfs_iterate(curthread, proc, pd, &pn, &p) == -1) { - /* nothing left... */ - if (proc != NULL) { - _PRELE(proc); - PROC_UNLOCK(proc); - } - pfs_unlock(pd); - sx_sunlock(&allproc_lock); - PFS_RETURN (0); + if (va->a_eofflag != NULL) + *va->a_eofflag = 1; + break; } - } - - /* fill in entries */ - while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 && - resid >= PFS_DELEN) { + if (coffset < offset) + continue; if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV, M_NOWAIT | M_ZERO)) == NULL) { error = ENOMEM; diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 35454998fc8e..8c484381ed59 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -71,7 +71,7 @@ SYSCTL_INT(_vfs_smbfs, OID_AUTO, fastlookup, CTLFLAG_RW, &smbfs_fastlookup, 0, " #define DE_SIZE (sizeof(struct dirent)) static int -smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) +smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred, int *eofp) { struct dirent de; struct componentname cn; @@ -86,6 +86,8 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) SMBVDEBUG("dirname='%s'\n", np->n_name); scred = smbfs_malloc_scred(); smb_makescred(scred, uio->uio_td, cred); + if (eofp != NULL) + *eofp = 0; offset = uio->uio_offset / DE_SIZE; /* offset in the directory */ limit = uio->uio_resid / DE_SIZE; if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0) { @@ -138,8 +140,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) if (error) { smbfs_findclose(np->n_dirseq, scred); np->n_dirseq = NULL; - error = ENOENT ? 0 : error; - goto out; + goto out1; } } error = 0; @@ -170,16 +171,21 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) if (error) break; } - if (error == ENOENT) - error = 0; uio->uio_offset = offset * DE_SIZE; +out1: + if (error == ENOENT) { + if (eofp != NULL) + *eofp = 1; + error = 0; + } out: smbfs_free_scred(scred); return error; } int -smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred) +smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, + int *eofp) { struct smbmount *smp = VFSTOSMBFS(vp->v_mount); struct smbnode *np = VTOSMB(vp); @@ -209,7 +215,7 @@ smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred) lks = LK_EXCLUSIVE; /* lockstatus(vp->v_vnlock); */ if (lks == LK_SHARED) vn_lock(vp, LK_UPGRADE | LK_RETRY); - error = smbfs_readvdir(vp, uiop, cred); + error = smbfs_readvdir(vp, uiop, cred, eofp); if (lks == LK_SHARED) vn_lock(vp, LK_DOWNGRADE | LK_RETRY); return error; diff --git a/sys/fs/smbfs/smbfs_node.h b/sys/fs/smbfs/smbfs_node.h index f28f0007100a..8c8ce038b913 100644 --- a/sys/fs/smbfs/smbfs_node.h +++ b/sys/fs/smbfs/smbfs_node.h @@ -93,7 +93,7 @@ u_int32_t smbfs_hash(const u_char *name, int nmlen); int smbfs_getpages(struct vop_getpages_args *); int smbfs_putpages(struct vop_putpages_args *); -int smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred); +int smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, int *eofp); int smbfs_writevnode(struct vnode *vp, struct uio *uiop, struct ucred *cred, int ioflag); void smbfs_attr_cacheenter(struct vnode *vp, struct smbfattr *fap); int smbfs_attr_cachelookup(struct vnode *vp ,struct vattr *va); diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 5d412cabadb8..63b249c93771 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -466,7 +466,7 @@ smbfs_read(struct vop_read_args *ap) SMBVDEBUG("\n"); if (vp->v_type != VREG && vp->v_type != VDIR) return EPERM; - return smbfs_readvnode(vp, uio, ap->a_cred); + return smbfs_readvnode(vp, uio, ap->a_cred, NULL); } static int @@ -748,7 +748,6 @@ smbfs_readdir(struct vop_readdir_args *ap) { struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; - int error; if (vp->v_type != VDIR) return (EPERM); @@ -758,8 +757,7 @@ smbfs_readdir(struct vop_readdir_args *ap) return (EOPNOTSUPP); } #endif - error = smbfs_readvnode(vp, uio, ap->a_cred); - return error; + return (smbfs_readvnode(vp, uio, ap->a_cred, ap->a_eofflag)); } /* ARGSUSED */ diff --git a/sys/fs/udf/ecma167-udf.h b/sys/fs/udf/ecma167-udf.h index 839bbec08254..19e114763cac 100644 --- a/sys/fs/udf/ecma167-udf.h +++ b/sys/fs/udf/ecma167-udf.h @@ -243,7 +243,7 @@ struct part_map_spare { uint8_t n_st; /* Number of Sparing Tables */ uint8_t reserved1; uint32_t st_size; - uint32_t st_loc[1]; + uint32_t st_loc[]; } __packed; union udf_pmap { @@ -266,7 +266,7 @@ struct udf_sparing_table { uint16_t rt_l; /* Relocation Table len */ uint8_t reserved[2]; uint32_t seq_num; - struct spare_map_entry entries[1]; + struct spare_map_entry entries[]; } __packed; /* Partition Descriptor [3/10.5] */ diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index c7438147c0a0..c5ef1f686093 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -81,6 +81,7 @@ #include <sys/fcntl.h> #include <sys/iconv.h> #include <sys/kernel.h> +#include <sys/limits.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/namei.h> @@ -729,7 +730,7 @@ udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) struct ifid *ifhp; struct vnode *nvp; struct udf_node *np; - off_t fsize; + uint64_t fsize; int error; ifhp = (struct ifid *)fhp; @@ -741,6 +742,10 @@ udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) np = VTON(nvp); fsize = le64toh(np->fentry->inf_len); + if (fsize > OFF_MAX) { + *vpp = NULLVP; + return (EIO); + } *vpp = nvp; vnode_create_vobject(*vpp, fsize, curthread); diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index 88bf4917a851..37889241e8c3 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -39,6 +39,7 @@ #include <sys/conf.h> #include <sys/buf.h> #include <sys/iconv.h> +#include <sys/limits.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/dirent.h> @@ -182,11 +183,14 @@ udf_access(struct vop_access_args *a) } static int -udf_open(struct vop_open_args *ap) { +udf_open(struct vop_open_args *ap) +{ struct udf_node *np = VTON(ap->a_vp); - off_t fsize; + uint64_t fsize; fsize = le64toh(np->fentry->inf_len); + if (fsize > OFF_MAX) + return (EIO); vnode_create_vobject(ap->a_vp, fsize, ap->a_td); return 0; } @@ -314,12 +318,13 @@ udf_getattr(struct vop_getattr_args *a) * that directories consume at least one logical block, * make it appear so. */ - if (fentry->logblks_rec != 0) { - vap->va_size = - le64toh(fentry->logblks_rec) * node->udfmp->bsize; - } else { + vap->va_size = le64toh(fentry->logblks_rec); + if (vap->va_size == 0) vap->va_size = node->udfmp->bsize; - } + else if (vap->va_size > UINT64_MAX / node->udfmp->bsize) + vap->va_size = UINT64_MAX; + else + vap->va_size *= node->udfmp->bsize; } else { vap->va_size = le64toh(fentry->inf_len); } @@ -446,6 +451,7 @@ udf_read(struct vop_read_args *ap) struct buf *bp; uint8_t *data; daddr_t lbn, rablock; + uint64_t len; off_t diff, fsize; ssize_t n; int error = 0; @@ -471,7 +477,12 @@ udf_read(struct vop_read_args *ap) return (error); } - fsize = le64toh(node->fentry->inf_len); + len = le64toh(node->fentry->inf_len); + if (len > OFF_MAX) { + /* too big, just cap to the requested length */ + len = uio->uio_resid; + } + fsize = len; udfmp = node->udfmp; do { lbn = lblkno(udfmp, uio->uio_offset); @@ -783,6 +794,7 @@ udf_readdir(struct vop_readdir_args *a) struct udf_uiodir uiodir; struct udf_dirstream *ds; uint64_t *cookies = NULL; + uint64_t len; int ncookies; int error = 0; @@ -811,8 +823,12 @@ udf_readdir(struct vop_readdir_args *a) * Iterate through the file id descriptors. Give the parent dir * entry special attention. */ - ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), - node->udfmp); + len = le64toh(node->fentry->inf_len); + if (len > INT_MAX) { + /* too big, just cap to INT_MAX */ + len = INT_MAX; + } + ds = udf_opendir(node, uio->uio_offset, len, node->udfmp); while ((fid = udf_getfid(ds)) != NULL) { /* XXX Should we return an error on a bad fid? */ @@ -904,7 +920,8 @@ udf_readlink(struct vop_readlink_args *ap) struct udf_node *node; void *buf; char *cp; - int error, len, root; + uint64_t len; + int error, root; /* * A symbolic link in UDF is a list of variable-length path @@ -914,6 +931,8 @@ udf_readlink(struct vop_readlink_args *ap) vp = ap->a_vp; node = VTON(vp); len = le64toh(node->fentry->inf_len); + if (len > MAXPATHLEN) + return (EIO); buf = malloc(len, M_DEVBUF, M_WAITOK); iov[0].iov_len = len; iov[0].iov_base = buf; @@ -1116,13 +1135,14 @@ udf_lookup(struct vop_cachedlookup_args *a) struct udf_mnt *udfmp; struct fileid_desc *fid = NULL; struct udf_dirstream *ds; + uint64_t fsize; u_long nameiop; u_long flags; char *nameptr; long namelen; ino_t id = 0; int offset, error = 0; - int fsize, lkflags, ltype, numdirpasses; + int lkflags, ltype, numdirpasses; dvp = a->a_dvp; node = VTON(dvp); @@ -1133,6 +1153,10 @@ udf_lookup(struct vop_cachedlookup_args *a) nameptr = a->a_cnp->cn_nameptr; namelen = a->a_cnp->cn_namelen; fsize = le64toh(node->fentry->inf_len); + if (fsize > INT_MAX) { + /* too big, just cap to INT_MAX */ + fsize = INT_MAX; + } /* * If this is a LOOKUP and we've already partially searched through diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index 2b1cb575cac8..2173a84c7acf 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -590,6 +590,7 @@ g_concat_add_disk(struct g_concat_softc *sc, struct g_provider *pp, u_int no) strcmp(md.md_name, sc->sc_name) != 0 || md.md_id != sc->sc_id) { G_CONCAT_DEBUG(0, "Metadata on %s changed.", pp->name); + error = EINVAL; goto fail; } diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 41cc115225f9..aba4bf7c44c4 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -381,8 +381,8 @@ g_new_geomf(struct g_class *mp, const char *fmt, ...) sbuf_vprintf(sb, fmt, ap); va_end(ap); sbuf_finish(sb); - gp = g_malloc(sizeof *gp, M_WAITOK | M_ZERO); - gp->name = g_malloc(sbuf_len(sb) + 1, M_WAITOK | M_ZERO); + gp = g_malloc(sizeof *gp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); + gp->name = (char *)(gp + 1); gp->class = mp; gp->rank = 1; LIST_INIT(&gp->consumer); @@ -420,7 +420,6 @@ g_destroy_geom(struct g_geom *gp) g_cancel_event(gp); LIST_REMOVE(gp, geom); TAILQ_REMOVE(&geoms, gp, geoms); - g_free(gp->name); g_free(gp); } diff --git a/sys/geom/virstor/g_virstor.c b/sys/geom/virstor/g_virstor.c index b8cf32875660..73bd9f73055a 100644 --- a/sys/geom/virstor/g_virstor.c +++ b/sys/geom/virstor/g_virstor.c @@ -589,7 +589,7 @@ virstor_ctl_remove(struct gctl_req *req, struct g_class *cp) M_GVIRSTOR, M_WAITOK | M_ZERO); bcopy(sc->components, newcomp, found * sizeof(*sc->components)); bcopy(&sc->components[found + 1], newcomp + found, - found * sizeof(*sc->components)); + (sc->n_components - (found + 1)) * sizeof(*sc->components)); if ((sc->components[j].flags & VIRSTOR_PROVIDER_ALLOCATED) != 0) { LOG_MSG(LVL_ERROR, "Allocated provider %s cannot be " "removed from %s", diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index e7d460af21d4..f577cd07ac7c 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -17,6 +17,8 @@ # in NOTES. # +#NO_UNIVERSE + cpu I486_CPU cpu I586_CPU cpu I686_CPU diff --git a/sys/i386/conf/GENERIC-NODEBUG b/sys/i386/conf/GENERIC-NODEBUG index ea07613a796f..a93304481b5f 100644 --- a/sys/i386/conf/GENERIC-NODEBUG +++ b/sys/i386/conf/GENERIC-NODEBUG @@ -25,6 +25,8 @@ # in NOTES. # +#NO_UNIVERSE + include GENERIC include "std.nodebug" diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 41207eb63cb9..2e947202f723 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -1,3 +1,4 @@ +#NO_UNIVERSE include "../../conf/NOTES" include "../../x86/conf/NOTES" diff --git a/sys/i386/conf/MINIMAL b/sys/i386/conf/MINIMAL index 2a06eb84bff8..8019617ca4d4 100644 --- a/sys/i386/conf/MINIMAL +++ b/sys/i386/conf/MINIMAL @@ -31,6 +31,8 @@ # in NOTES. # +#NO_UNIVERSE + cpu I486_CPU cpu I586_CPU cpu I686_CPU diff --git a/sys/i386/conf/PAE b/sys/i386/conf/PAE index a39d32d77106..72af9e9a9eec 100644 --- a/sys/i386/conf/PAE +++ b/sys/i386/conf/PAE @@ -2,6 +2,8 @@ # PAE -- Generic kernel configuration file for FreeBSD/i386 PAE # +#NO_UNIVERSE + include GENERIC ident PAE-GENERIC diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 5065b7e61ee8..b44f5e08bbcf 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -876,14 +876,16 @@ __CONCAT(PMTYPE, init_pat)(void) #ifdef PMAP_PAE_COMP static void * -pmap_pdpt_allocf(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *flags, - int wait) +pmap_pdpt_allocf(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *sflagsp, + int flags) { /* Inform UMA that this allocator uses kernel_map/object. */ - *flags = UMA_SLAB_KERNEL; + *sflagsp = UMA_SLAB_KERNEL; + /* contig allocations cannot be NEVERFREED */ + flags &= ~M_NEVERFREED; return ((void *)kmem_alloc_contig_domainset(DOMAINSET_FIXED(domain), - bytes, wait, 0x0ULL, 0xffffffffULL, 1, 0, VM_MEMATTR_DEFAULT)); + bytes, flags, 0x0ULL, 0xffffffffULL, 1, 0, VM_MEMATTR_DEFAULT)); } #endif diff --git a/sys/kern/subr_asan.c b/sys/kern/subr_asan.c index 0edb631d1475..464efda1e91a 100644 --- a/sys/kern/subr_asan.c +++ b/sys/kern/subr_asan.c @@ -263,8 +263,7 @@ kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code) if (__predict_false(!kasan_enabled)) return; - if ((vm_offset_t)addr >= DMAP_MIN_ADDRESS && - (vm_offset_t)addr < DMAP_MAX_ADDRESS) + if (kasan_md_unsupported((vm_offset_t)addr)) return; KASSERT((vm_offset_t)addr >= VM_MIN_KERNEL_ADDRESS && diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 18388ae5f232..bac7d0080c71 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -338,8 +338,9 @@ ast_handler(struct thread *td, struct trapframe *framep, bool dtor) td->td_ast = 0; } - CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, td->td_proc->p_pid, - td->td_proc->p_comm); + CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, + td->td_proc == NULL ? -1 : td->td_proc->p_pid, + td->td_proc == NULL ? "" : td->td_proc->p_comm); KASSERT(framep == NULL || TRAPF_USERMODE(framep), ("ast in kernel mode")); diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 94e44d888181..b472aaea89e6 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -2309,6 +2309,12 @@ sys_exterrctl(struct thread *td, struct exterrctl_args *uap) return (EINVAL); td->td_pflags2 &= ~TDP2_UEXTERR; return (0); + case EXTERRCTL_UD: + /* + * Important: this code must always return EINVAL and never any + * extended error, for testing purposes. + */ + /* FALLTHROUGH */ default: return (EINVAL); } diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 3d455b3874cc..89c1d779f04c 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -332,7 +332,8 @@ SDT_PROBE_DEFINE2(vfs, namecache, evict_negative, done, "struct vnode *", "char *"); SDT_PROBE_DEFINE1(vfs, namecache, symlink, alloc__fail, "size_t"); -SDT_PROBE_DEFINE3(vfs, fplookup, lookup, done, "struct nameidata", "int", "bool"); +SDT_PROBE_DEFINE3(vfs, fplookup, lookup, done, "struct nameidata *", "int", + "enum cache_fpl_status"); SDT_PROBE_DECLARE(vfs, namei, lookup, entry); SDT_PROBE_DECLARE(vfs, namei, lookup, return); @@ -6420,15 +6421,11 @@ out: cache_fpl_smr_assert_not_entered(&fpl); cache_fpl_assert_status(&fpl); *status = fpl.status; - if (SDT_PROBES_ENABLED()) { - SDT_PROBE3(vfs, fplookup, lookup, done, ndp, fpl.line, fpl.status); - if (fpl.status == CACHE_FPL_STATUS_HANDLED) - SDT_PROBE4(vfs, namei, lookup, return, error, ndp->ni_vp, true, - ndp); - } - + SDT_PROBE3(vfs, fplookup, lookup, done, ndp, fpl.line, fpl.status); if (__predict_true(fpl.status == CACHE_FPL_STATUS_HANDLED)) { MPASS(error != CACHE_FPL_FAILED); + SDT_PROBE4(vfs, namei, lookup, return, error, ndp->ni_vp, true, + ndp); if (error != 0) { cache_fpl_cleanup_cnp(fpl.cnp); MPASS(fpl.dvp == NULL); diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c index 2b42228465a4..d3cd0d1f9832 100644 --- a/sys/kern/vfs_inotify.c +++ b/sys/kern/vfs_inotify.c @@ -371,7 +371,7 @@ inotify_unlink_watch_locked(struct inotify_softc *sc, struct inotify_watch *watc TAILQ_REMOVE(&vp->v_pollinfo->vpi_inotify, watch, vlink); if (TAILQ_EMPTY(&vp->v_pollinfo->vpi_inotify)) - vn_irflag_unset_locked(vp, VIRF_INOTIFY); + vn_irflag_unset(vp, VIRF_INOTIFY); } /* @@ -675,7 +675,8 @@ vn_inotify(struct vnode *vp, struct vnode *dvp, struct componentname *cnp, struct vattr va; int error; - error = VOP_GETATTR(vp, &va, cnp->cn_cred); + error = VOP_GETATTR(vp, &va, + cnp->cn_cred); if (error == 0 && va.va_nlink != 0) selfevent = 0; } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 918b256e6c59..29774cf87393 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -6533,17 +6533,6 @@ vop_read_pgcache_post(void *ap, int rc) VFS_KNOTE_UNLOCKED(a->a_vp, NOTE_READ); } -void -vop_readdir_post(void *ap, int rc) -{ - struct vop_readdir_args *a = ap; - - if (!rc) { - VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ); - INOTIFY(a->a_vp, IN_ACCESS); - } -} - static struct knlist fs_knlist; static void diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 38138a4af921..2e63215b2f97 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -242,8 +242,8 @@ vop_read_pgcache { %% write vp L L L -%! write pre VOP_WRITE_PRE -%! write post VOP_WRITE_POST +%! write pre vop_write_pre +%! write post vop_write_post vop_write { IN struct vnode *vp; @@ -380,6 +380,7 @@ vop_symlink { %% readdir vp L L L +%! readdir pre vop_readdir_pre %! readdir post vop_readdir_post vop_readdir { diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 9922796f8a1d..7cb6e2124326 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -326,6 +326,7 @@ SUBDIR= \ proto \ pseudofs \ ${_pst} \ + ${_pt} \ pty \ puc \ pwm \ @@ -842,6 +843,7 @@ _iwx= iwx _ixl= ixl _nvdimm= nvdimm _pms= pms +_pt= pt _qat= qat .if ${MK_SOURCELESS_UCODE} != "no" _qatfw= qatfw diff --git a/sys/modules/efirt/Makefile b/sys/modules/efirt/Makefile index 4738996fd4e6..c46484465b68 100644 --- a/sys/modules/efirt/Makefile +++ b/sys/modules/efirt/Makefile @@ -9,7 +9,7 @@ SRCS+= device_if.h bus_if.h clock_if.h DPSRCS+= assym.inc .if ${MACHINE_CPUARCH} == "amd64" -SRCS+= opt_hwpmc_hooks.h opt_kstack_pages.h +SRCS+= opt_acpi.h opt_hwpmc_hooks.h opt_kstack_pages.h .endif efirt_support.o: efirt_support.S assym.inc diff --git a/sys/modules/ice/Makefile b/sys/modules/ice/Makefile index 91f20193d878..9f9c9f602cda 100644 --- a/sys/modules/ice/Makefile +++ b/sys/modules/ice/Makefile @@ -13,6 +13,7 @@ SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h SRCS += ice_lib.c ice_osdep.c ice_resmgr.c ice_strings.c SRCS += ice_iflib_recovery_txrx.c ice_iflib_txrx.c if_ice_iflib.c SRCS += ice_fw_logging.c ice_ddp_common.c +SRCS.PCI_IOV += pci_iov_if.h ice_iov.c ice_vf_mbx.c # RDMA Client interface # TODO: Is this the right way to compile this? diff --git a/sys/modules/pt/Makefile b/sys/modules/pt/Makefile new file mode 100644 index 000000000000..416b072face9 --- /dev/null +++ b/sys/modules/pt/Makefile @@ -0,0 +1,8 @@ + +.PATH: ${SRCTOP}/sys/amd64/pt + +KMOD= pt +SRCS= pt.c pt.h device_if.h bus_if.h +SRCS+= opt_hwpmc_hooks.h opt_kstack_pages.h + +.include <bsd.kmod.mk> diff --git a/sys/modules/qlnx/qlnxe/Makefile b/sys/modules/qlnx/qlnxe/Makefile index 3d8415cf0e57..2a44ae6ddde5 100644 --- a/sys/modules/qlnx/qlnxe/Makefile +++ b/sys/modules/qlnx/qlnxe/Makefile @@ -58,6 +58,7 @@ SRCS+=qlnx_rdma.c SRCS+=qlnx_ioctl.c SRCS+=qlnx_os.c +SRCS+=opt_inet.h SRCS+= ${LINUXKPI_GENSRCS} diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h index cf4f75bd0b6c..01485cf26e06 100644 --- a/sys/net/ethernet.h +++ b/sys/net/ethernet.h @@ -62,6 +62,8 @@ struct ether_header { u_char ether_shost[ETHER_ADDR_LEN]; u_short ether_type; } __packed; +_Static_assert(sizeof(struct ether_header) == ETHER_HDR_LEN, + "size of struct ether_header is wrong"); /* * Structure of a 48-bit Ethernet address. @@ -69,6 +71,8 @@ struct ether_header { struct ether_addr { u_char octet[ETHER_ADDR_LEN]; } __packed; +_Static_assert(sizeof(struct ether_addr) == ETHER_ADDR_LEN, + "size of struct ether_addr is wrong"); #define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ #define ETHER_IS_IPV6_MULTICAST(addr) \ @@ -112,6 +116,8 @@ struct ether_vlan_header { uint16_t evl_tag; uint16_t evl_proto; } __packed; +_Static_assert(sizeof(struct ether_vlan_header) == ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN, + "size of struct ether_vlan_header is wrong"); #define EVL_VLID_MASK 0x0FFF #define EVL_PRI_MASK 0xE000 diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 7be4dfac23e7..3ae0c01c0efc 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -92,11 +92,6 @@ #include <crypto/sha1.h> -#ifdef CTASSERT -CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2); -CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN); -#endif - VNET_DEFINE(pfil_head_t, link_pfil_head); /* Packet filter hooks */ /* netgraph node hooks for ng_ether(4) */ diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h index 3c1846b8f82a..c6692d3dd6bc 100644 --- a/sys/net/if_gif.h +++ b/sys/net/if_gif.h @@ -120,7 +120,8 @@ int in6_gif_setopts(struct gif_softc *, u_int); #define GIFGOPTS _IOWR('i', 150, struct ifreq) #define GIFSOPTS _IOW('i', 151, struct ifreq) +#define GIF_NOCLAMP 0x0001 #define GIF_IGNORE_SOURCE 0x0002 -#define GIF_OPTMASK (GIF_IGNORE_SOURCE) +#define GIF_OPTMASK (GIF_NOCLAMP|GIF_IGNORE_SOURCE) #endif /* _NET_IF_GIF_H_ */ diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c index 7bdbc565f4ca..6755997fd1f0 100644 --- a/sys/net/if_ovpn.c +++ b/sys/net/if_ovpn.c @@ -341,6 +341,7 @@ ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) size_t len; const void *addr = nvlist_get_binary(nvl, "address", &len); in->sin_family = af; + in->sin_len = sizeof(*in); if (len != sizeof(in->sin_addr)) return (EINVAL); @@ -355,6 +356,7 @@ ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) size_t len; const void *addr = nvlist_get_binary(nvl, "address", &len); in6->sin6_family = af; + in6->sin6_len = sizeof(*in6); if (len != sizeof(in6->sin6_addr)) return (EINVAL); diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 1f2011634695..d55afe750869 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -331,6 +331,14 @@ MALLOC_DECLARE(M_PF_RULE_ITEM); SDT_PROVIDER_DECLARE(pf); SDT_PROBE_DECLARE(pf, , test, reason_set); +SDT_PROBE_DECLARE(pf, , log, log); + +#define DPFPRINTF(n, fmt, x...) \ + do { \ + SDT_PROBE2(pf, , log, log, (n), fmt); \ + if (V_pf_status.debug >= (n)) \ + printf(fmt "\n", ##x); \ + } while (0) struct pfi_dynaddr { TAILQ_ENTRY(pfi_dynaddr) entry; @@ -1370,7 +1378,6 @@ struct pf_kruleset { struct pf_krulequeue queues[2]; struct { struct pf_krulequeue *ptr; - struct pf_krule **ptr_array; u_int32_t rcount; u_int32_t ticket; int open; @@ -1677,6 +1684,9 @@ struct pf_pdesc { u_int32_t fragoff; /* fragment header offset */ u_int32_t jumbolen; /* length from v6 jumbo header */ u_int32_t badopts; /* v4 options or v6 routing headers */ +#define PF_OPT_OTHER 0x0001 +#define PF_OPT_JUMBO 0x0002 +#define PF_OPT_ROUTER_ALERT 0x0004 u_int16_t *ip_sum; u_int16_t flags; /* Let SCRUB trigger behavior in diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index c5a478533313..9074878e17e4 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -2214,12 +2214,9 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, /* VHT */ if (IEEE80211_IS_CHAN_VHT(ni->ni_chan) && - vhtcap != NULL && - vhtinfo != NULL) { - /* XXX TODO; see below */ - net80211_vap_printf(vap, "%s: VHT TODO!\n", __func__); + vhtcap != NULL) { ieee80211_vht_node_init(ni); - ieee80211_vht_update_cap(ni, vhtcap, vhtinfo); + ieee80211_vht_update_cap(ni, vhtcap); } else if (ni->ni_flags & IEEE80211_NODE_VHT) ieee80211_vht_node_cleanup(ni); diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index 5ec80e3646b8..c28f124648a1 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -1952,6 +1952,11 @@ do { \ _RETURN_CHAN_BITS(0); /* + * TODO: should we bail out if there's no htinfo? + * Or just treat it as if we can't do the HT20/HT40 check? + */ + + /* * The original code was based on * 802.11ac-2013, Table 8-183x-VHT Operation Information subfields. * 802.11-2020, Table 9-274-VHT Operation Information subfields @@ -1962,8 +1967,12 @@ do { \ */ htinfo = (const struct ieee80211_ie_htinfo *)ni->ni_ies.htinfo_ie; - ht40 = ((htinfo->hi_byte1 & IEEE80211_HTINFO_TXWIDTH) == - IEEE80211_HTINFO_TXWIDTH_2040); + if (htinfo != NULL) + ht40 = ((htinfo->hi_byte1 & IEEE80211_HTINFO_TXWIDTH) == + IEEE80211_HTINFO_TXWIDTH_2040); + else + ht40 = false; + can_vht160 = can_vht80p80 = can_vht80 = false; /* 20 Mhz */ diff --git a/sys/net80211/ieee80211_vht.c b/sys/net80211/ieee80211_vht.c index e91977f1ef98..de0b691d4d2a 100644 --- a/sys/net80211/ieee80211_vht.c +++ b/sys/net80211/ieee80211_vht.c @@ -838,12 +838,10 @@ ieee80211_add_vhtinfo(uint8_t *frm, struct ieee80211_node *ni) } void -ieee80211_vht_update_cap(struct ieee80211_node *ni, const uint8_t *vhtcap_ie, - const uint8_t *vhtop_ie) +ieee80211_vht_update_cap(struct ieee80211_node *ni, const uint8_t *vhtcap_ie) { ieee80211_parse_vhtcap(ni, vhtcap_ie); - ieee80211_parse_vhtopmode(ni, vhtop_ie); } static struct ieee80211_channel * diff --git a/sys/net80211/ieee80211_vht.h b/sys/net80211/ieee80211_vht.h index 2964de63c343..a1529df4a85b 100644 --- a/sys/net80211/ieee80211_vht.h +++ b/sys/net80211/ieee80211_vht.h @@ -52,8 +52,7 @@ uint8_t * ieee80211_add_vhtinfo(uint8_t *frm, struct ieee80211_node *); uint8_t *ieee80211_add_vhtcap_ch(uint8_t *, struct ieee80211vap *, struct ieee80211_channel *); -void ieee80211_vht_update_cap(struct ieee80211_node *, - const uint8_t *, const uint8_t *); +void ieee80211_vht_update_cap(struct ieee80211_node *, const uint8_t *); struct ieee80211_channel * ieee80211_vht_adjust_channel(struct ieee80211com *, diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h index b1f2b0ebf911..d6b75e482e35 100644 --- a/sys/netinet/icmp_var.h +++ b/sys/netinet/icmp_var.h @@ -104,11 +104,10 @@ extern int badport_bandlim(int); #define BANDLIM_ICMP_UNREACH 0 #define BANDLIM_ICMP_ECHO 1 #define BANDLIM_ICMP_TSTAMP 2 -#define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */ -#define BANDLIM_RST_OPENPORT 4 /* No connection, listener */ -#define BANDLIM_ICMP6_UNREACH 5 -#define BANDLIM_SCTP_OOTB 6 -#define BANDLIM_MAX 7 +#define BANDLIM_TCP_RST 3 +#define BANDLIM_ICMP6_UNREACH 4 +#define BANDLIM_SCTP_OOTB 5 +#define BANDLIM_MAX 6 #endif #endif diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index cb4b6df57c57..71b75d18efd0 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -1097,8 +1097,7 @@ static const char *icmp_rate_descrs[BANDLIM_MAX] = { [BANDLIM_ICMP_UNREACH] = "icmp unreach", [BANDLIM_ICMP_ECHO] = "icmp ping", [BANDLIM_ICMP_TSTAMP] = "icmp tstamp", - [BANDLIM_RST_CLOSEDPORT] = "closed port RST", - [BANDLIM_RST_OPENPORT] = "open port RST", + [BANDLIM_TCP_RST] = "tcp reset", [BANDLIM_ICMP6_UNREACH] = "icmp6 unreach", [BANDLIM_SCTP_OOTB] = "sctp ootb", }; diff --git a/sys/netinet/tcp_hpts.c b/sys/netinet/tcp_hpts.c index 91f8251589e4..b60cdf45af52 100644 --- a/sys/netinet/tcp_hpts.c +++ b/sys/netinet/tcp_hpts.c @@ -433,38 +433,40 @@ static void tcp_hpts_log(struct tcp_hpts_entry *hpts, struct tcpcb *tp, struct timeval *tv, int slots_to_run, int idx, bool from_callout) { - union tcp_log_stackspecific log; - /* - * Unused logs are - * 64 bit - delRate, rttProp, bw_inuse - * 16 bit - cwnd_gain - * 8 bit - bbr_state, bbr_substate, inhpts; - */ - memset(&log, 0, sizeof(log)); - log.u_bbr.flex1 = hpts->p_nxt_slot; - log.u_bbr.flex2 = hpts->p_cur_slot; - log.u_bbr.flex3 = hpts->p_prev_slot; - log.u_bbr.flex4 = idx; - log.u_bbr.flex5 = hpts->p_curtick; - log.u_bbr.flex6 = hpts->p_on_queue_cnt; - log.u_bbr.flex7 = hpts->p_cpu; - log.u_bbr.flex8 = (uint8_t)from_callout; - log.u_bbr.inflight = slots_to_run; - log.u_bbr.applimited = hpts->overidden_sleep; - log.u_bbr.delivered = hpts->saved_curtick; - log.u_bbr.timeStamp = tcp_tv_to_usectick(tv); - log.u_bbr.epoch = hpts->saved_curslot; - log.u_bbr.lt_epoch = hpts->saved_prev_slot; - log.u_bbr.pkts_out = hpts->p_delayed_by; - log.u_bbr.lost = hpts->p_hpts_sleep_time; - log.u_bbr.pacing_gain = hpts->p_cpu; - log.u_bbr.pkt_epoch = hpts->p_runningslot; - log.u_bbr.use_lt_bw = 1; - TCP_LOG_EVENTP(tp, NULL, - &tptosocket(tp)->so_rcv, - &tptosocket(tp)->so_snd, - BBR_LOG_HPTSDIAG, 0, - 0, &log, false, tv); + if (hpts_does_tp_logging && tcp_bblogging_on(tp)) { + union tcp_log_stackspecific log; + /* + * Unused logs are + * 64 bit - delRate, rttProp, bw_inuse + * 16 bit - cwnd_gain + * 8 bit - bbr_state, bbr_substate, inhpts; + */ + memset(&log, 0, sizeof(log)); + log.u_bbr.flex1 = hpts->p_nxt_slot; + log.u_bbr.flex2 = hpts->p_cur_slot; + log.u_bbr.flex3 = hpts->p_prev_slot; + log.u_bbr.flex4 = idx; + log.u_bbr.flex5 = hpts->p_curtick; + log.u_bbr.flex6 = hpts->p_on_queue_cnt; + log.u_bbr.flex7 = hpts->p_cpu; + log.u_bbr.flex8 = (uint8_t)from_callout; + log.u_bbr.inflight = slots_to_run; + log.u_bbr.applimited = hpts->overidden_sleep; + log.u_bbr.delivered = hpts->saved_curtick; + log.u_bbr.timeStamp = tcp_tv_to_usectick(tv); + log.u_bbr.epoch = hpts->saved_curslot; + log.u_bbr.lt_epoch = hpts->saved_prev_slot; + log.u_bbr.pkts_out = hpts->p_delayed_by; + log.u_bbr.lost = hpts->p_hpts_sleep_time; + log.u_bbr.pacing_gain = hpts->p_cpu; + log.u_bbr.pkt_epoch = hpts->p_runningslot; + log.u_bbr.use_lt_bw = 1; + TCP_LOG_EVENTP(tp, NULL, + &tptosocket(tp)->so_rcv, + &tptosocket(tp)->so_snd, + BBR_LOG_HPTSDIAG, 0, + 0, &log, false, tv); + } } static void @@ -1353,10 +1355,7 @@ again: } CURVNET_SET(inp->inp_vnet); /* Lets do any logging that we might want to */ - if (hpts_does_tp_logging && tcp_bblogging_on(tp)) { - tcp_hpts_log(hpts, tp, &tv, slots_to_run, i, - from_callout); - } + tcp_hpts_log(hpts, tp, &tv, slots_to_run, i, from_callout); if (tp->t_fb_ptr != NULL) { kern_prefetch(tp->t_fb_ptr, &did_prefetch); @@ -1487,7 +1486,7 @@ no_run: } void -__tcp_set_hpts(struct tcpcb *tp, int32_t line) +tcp_set_hpts(struct tcpcb *tp) { struct tcp_hpts_entry *hpts; int failed; diff --git a/sys/netinet/tcp_hpts.h b/sys/netinet/tcp_hpts.h index b097a2b98db9..f5856ed8e688 100644 --- a/sys/netinet/tcp_hpts.h +++ b/sys/netinet/tcp_hpts.h @@ -149,8 +149,7 @@ uint32_t tcp_hpts_insert_diag(struct tcpcb *tp, uint32_t slot, int32_t line, #define tcp_hpts_insert(inp, slot) \ tcp_hpts_insert_diag((inp), (slot), __LINE__, NULL) -void __tcp_set_hpts(struct tcpcb *tp, int32_t line); -#define tcp_set_hpts(a) __tcp_set_hpts(a, __LINE__) +void tcp_set_hpts(struct tcpcb *tp); void tcp_set_inp_to_drop(struct inpcb *inp, uint16_t reason); @@ -165,25 +164,25 @@ extern int32_t tcp_min_hptsi_time; * The following functions should also be available * to userspace as well. */ -static __inline uint32_t +static inline uint32_t tcp_tv_to_hptstick(const struct timeval *sv) { return ((sv->tv_sec * 100000) + (sv->tv_usec / HPTS_TICKS_PER_SLOT)); } -static __inline uint32_t +static inline uint32_t tcp_tv_to_usectick(const struct timeval *sv) { return ((uint32_t) ((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); } -static __inline uint32_t +static inline uint32_t tcp_tv_to_mssectick(const struct timeval *sv) { return ((uint32_t) ((sv->tv_sec * HPTS_MSEC_IN_SEC) + (sv->tv_usec/HPTS_USEC_IN_MSEC))); } -static __inline uint64_t +static inline uint64_t tcp_tv_to_lusectick(const struct timeval *sv) { return ((uint64_t)((sv->tv_sec * HPTS_USEC_IN_SEC) + sv->tv_usec)); @@ -199,7 +198,7 @@ get_hpts_min_sleep_time(void) return (tcp_min_hptsi_time + HPTS_TICKS_PER_SLOT); } -static __inline uint32_t +static inline uint32_t tcp_gethptstick(struct timeval *sv) { struct timeval tv; @@ -210,7 +209,7 @@ tcp_gethptstick(struct timeval *sv) return (tcp_tv_to_hptstick(sv)); } -static __inline uint64_t +static inline uint64_t tcp_get_u64_usecs(struct timeval *tv) { struct timeval tvd; @@ -221,7 +220,7 @@ tcp_get_u64_usecs(struct timeval *tv) return (tcp_tv_to_lusectick(tv)); } -static __inline uint32_t +static inline uint32_t tcp_get_usecs(struct timeval *tv) { struct timeval tvd; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 7c032e13f37a..de428ae1af6f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -621,6 +621,7 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port) #endif /* INET6 */ struct tcpopt to; /* options in this segment */ char *s = NULL; /* address and port logging */ + bool closed_port = false; /* segment is hitting a closed port */ NET_EPOCH_ASSERT(); @@ -907,7 +908,8 @@ findpcb: log(LOG_INFO, "%s; %s: Connection attempt " "to closed port\n", s, __func__); } - rstreason = BANDLIM_RST_CLOSEDPORT; + rstreason = BANDLIM_TCP_RST; + closed_port = true; goto dropwithreset; } INP_LOCK_ASSERT(inp); @@ -998,12 +1000,14 @@ findpcb: * down or it is in the CLOSED state. Either way we drop the * segment and send an appropriate response. */ - rstreason = BANDLIM_RST_CLOSEDPORT; + rstreason = BANDLIM_TCP_RST; + closed_port = true; goto dropwithreset; } if ((tp->t_port != port) && (tp->t_state > TCPS_LISTEN)) { - rstreason = BANDLIM_RST_CLOSEDPORT; + rstreason = BANDLIM_TCP_RST; + closed_port = true; goto dropwithreset; } @@ -1055,6 +1059,8 @@ findpcb: * socket appended to the listen queue in SYN_RECEIVED state. */ if ((thflags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK) { + int result; + /* * Parse the TCP options here because * syncookies need access to the reflected @@ -1064,8 +1070,8 @@ findpcb: /* * NB: syncache_expand() doesn't unlock inp. */ - rstreason = syncache_expand(&inc, &to, th, &so, m, port); - if (rstreason < 0) { + result = syncache_expand(&inc, &to, th, &so, m, port); + if (result < 0) { /* * A failing TCP MD5 signature comparison * must result in the segment being dropped @@ -1073,7 +1079,7 @@ findpcb: * to the sender. */ goto dropunlock; - } else if (rstreason == 0) { + } else if (result == 0) { /* * No syncache entry, or ACK was not for our * SYN/ACK. Do our protection against double @@ -1092,7 +1098,7 @@ findpcb: * of the failure cause. */ INP_WUNLOCK(inp); - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; lookupflag &= ~INPLOOKUP_WILDCARD; goto findpcb; } @@ -1183,7 +1189,7 @@ tfo_socket_result: s, __func__); syncache_badack(&inc, port); /* XXX: Not needed! */ TCPSTAT_INC(tcps_badsyn); - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; goto dropwithreset; } /* @@ -1259,7 +1265,7 @@ tfo_socket_result: "Connection attempt to deprecated " "IPv6 address rejected\n", s, __func__); - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; goto dropwithreset; } } @@ -1380,9 +1386,10 @@ dropwithreset: * When blackholing do not respond with a RST but * completely ignore the segment and drop it. */ - if (((rstreason == BANDLIM_RST_OPENPORT && V_blackhole == 3) || - (rstreason == BANDLIM_RST_CLOSEDPORT && - ((V_blackhole == 1 && (thflags & TH_SYN)) || V_blackhole > 1))) && + if (rstreason == BANDLIM_TCP_RST && + ((!closed_port && V_blackhole == 3) || + (closed_port && + ((V_blackhole == 1 && (thflags & TH_SYN)) || V_blackhole > 1))) && (V_blackhole_local || ( #ifdef INET6 isipv6 ? !in6_localip(&ip6->ip6_src) : @@ -1515,7 +1522,9 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, struct tcpopt to; int tfo_syn; u_int maxseg = 0; + bool no_data; + no_data = (tlen == 0); thflags = tcp_get_flags(th); tp->sackhint.last_sack_ack = 0; sack_changed = SACK_NOCHANGE; @@ -1754,7 +1763,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, tp->ts_recent = to.to_tsval; } - if (tlen == 0) { + if (no_data) { if (SEQ_GT(th->th_ack, tp->snd_una) && SEQ_LEQ(th->th_ack, tp->snd_max) && !IN_RECOVERY(tp->t_flags) && @@ -1963,7 +1972,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, if ((thflags & TH_ACK) && (SEQ_LEQ(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max))) { - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); goto dropwithreset; } @@ -1976,7 +1985,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, * FIN, or a RST. */ if ((thflags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) { - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); goto dropwithreset; } else if (thflags & TH_SYN) { @@ -2244,7 +2253,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, * for the "LAND" DoS attack. */ if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(th->th_seq, tp->irs)) { - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); goto dropwithreset; } @@ -2557,7 +2566,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, if (SEQ_LEQ(th->th_ack, tp->snd_una)) { maxseg = tcp_maxseg(tp); - if (tlen == 0 && + if (no_data && (tiwin == tp->snd_wnd || (tp->t_flags & TF_SACK_PERMIT))) { /* @@ -3113,8 +3122,7 @@ step6: (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) || (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) { /* keep track of pure window updates */ - if (tlen == 0 && - tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) + if (no_data && tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) TCPSTAT_INC(tcps_rcvwinupd); tp->snd_wnd = tiwin; tp->snd_wl1 = th->th_seq; @@ -3424,7 +3432,7 @@ dropafterack: if (tp->t_state == TCPS_SYN_RECEIVED && (thflags & TH_ACK) && (SEQ_GT(tp->snd_una, th->th_ack) || SEQ_GT(th->th_ack, tp->snd_max)) ) { - rstreason = BANDLIM_RST_OPENPORT; + rstreason = BANDLIM_TCP_RST; tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); goto dropwithreset; } diff --git a/sys/netinet/tcp_log_buf.c b/sys/netinet/tcp_log_buf.c index 75d693bc019b..e24790ece43d 100644 --- a/sys/netinet/tcp_log_buf.c +++ b/sys/netinet/tcp_log_buf.c @@ -2878,7 +2878,7 @@ tcp_log_sendfile(struct socket *so, off_t offset, size_t nbytes, int flags) /* double check log state now that we have the lock */ if (inp->inp_flags & INP_DROPPED) goto done; - if (tp->_t_logstate != TCP_LOG_STATE_OFF) { + if (tcp_bblogging_on(tp)) { struct timeval tv; tcp_log_eventspecific_t log; diff --git a/sys/netinet/tcp_log_buf.h b/sys/netinet/tcp_log_buf.h index fef32e16b2e4..3e7eef8a1cda 100644 --- a/sys/netinet/tcp_log_buf.h +++ b/sys/netinet/tcp_log_buf.h @@ -539,12 +539,12 @@ struct tcpcb; NULL, NULL, 0, NULL); \ } while (0) #endif /* TCP_LOG_FORCEVERBOSE */ +/* Assumes/requires the caller has already checked tcp_bblogging_on(tp). */ #define TCP_LOG_EVENTP(tp, th, rxbuf, txbuf, eventid, errornum, len, stackinfo, th_hostorder, tv) \ do { \ - if (tcp_bblogging_on(tp)) \ - tcp_log_event(tp, th, rxbuf, txbuf, eventid, \ - errornum, len, stackinfo, th_hostorder, \ - NULL, NULL, 0, tv); \ + KASSERT(tcp_bblogging_on(tp), ("bblogging is off")); \ + tcp_log_event(tp, th, rxbuf, txbuf, eventid, errornum, len, \ + stackinfo, th_hostorder, NULL, NULL, 0, tv); \ } while (0) #ifdef TCP_BLACKBOX diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c index e2cfec5c9275..d2636f01714e 100644 --- a/sys/netinet/tcp_stacks/bbr.c +++ b/sys/netinet/tcp_stacks/bbr.c @@ -8763,7 +8763,7 @@ bbr_do_syn_sent(struct mbuf *m, struct tcphdr *th, struct socket *so, (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if ((thflags & (TH_ACK | TH_RST)) == (TH_ACK | TH_RST)) { @@ -8965,7 +8965,7 @@ bbr_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, (SEQ_LEQ(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if (tp->t_flags & TF_FASTOPEN) { @@ -8977,7 +8977,7 @@ bbr_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((thflags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } else if (thflags & TH_SYN) { /* non-initial SYN is ignored */ @@ -9010,7 +9010,7 @@ bbr_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if (SEQ_LT(th->th_seq, tp->irs)) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if (ctf_drop_checks(to, m, th, tp, &tlen, &thflags, &drop_hdrlen, &ret_val)) { @@ -9288,7 +9288,7 @@ bbr_do_established(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -9385,7 +9385,7 @@ bbr_do_close_wait(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -9535,7 +9535,7 @@ bbr_do_fin_wait_1(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -9637,7 +9637,7 @@ bbr_do_closing(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -9739,7 +9739,7 @@ bbr_do_lastack(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -9848,7 +9848,7 @@ bbr_do_fin_wait_2(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { bbr_log_progress_event(bbr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -11510,7 +11510,7 @@ bbr_do_segment_nounlock(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, if ((tp->t_state == TCPS_SYN_SENT) && (thflags & TH_ACK) && (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if (tiwin > bbr->r_ctl.rc_high_rwnd) diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c index 8e05498863b9..834e1347a152 100644 --- a/sys/netinet/tcp_stacks/rack.c +++ b/sys/netinet/tcp_stacks/rack.c @@ -40,7 +40,6 @@ #endif #include <sys/lock.h> #include <sys/malloc.h> -#include <sys/lock.h> #include <sys/mutex.h> #include <sys/mbuf.h> #include <sys/proc.h> /* for proc0 declaration */ @@ -198,7 +197,7 @@ static uint32_t rack_pcm_blast = 0; static uint32_t rack_pcm_is_enabled = 1; static uint8_t rack_ssthresh_rest_rto_rec = 0; /* Do we restore ssthresh when we have rec -> rto -> rec */ -static uint32_t rack_gp_gain_req = 1200; /* Amount percent wise required to gain to record a round has "gaining" */ +static uint32_t rack_gp_gain_req = 1200; /* Amount percent wise required to gain to record a round as "gaining" */ static uint32_t rack_rnd_cnt_req = 0x10005; /* Default number of rounds if we are below rack_gp_gain_req where we exit ss */ @@ -938,7 +937,7 @@ rack_init_sysctls(void) SYSCTL_ADD_U32(&rack_sysctl_ctx, SYSCTL_CHILDREN(rack_probertt), OID_AUTO, "time_between", CTLFLAG_RW, - & rack_time_between_probertt, 96000000, + &rack_time_between_probertt, 96000000, "How many useconds between the lowest rtt falling must past before we enter probertt"); SYSCTL_ADD_U32(&rack_sysctl_ctx, SYSCTL_CHILDREN(rack_probertt), @@ -3480,9 +3479,9 @@ static void rack_free(struct tcp_rack *rack, struct rack_sendmap *rsm) { if (rsm->r_flags & RACK_APP_LIMITED) { - if (rack->r_ctl.rc_app_limited_cnt > 0) { - rack->r_ctl.rc_app_limited_cnt--; - } + KASSERT((rack->r_ctl.rc_app_limited_cnt > 0), + ("app_cnt %u, rsm %p", rack->r_ctl.rc_app_limited_cnt, rsm)); + rack->r_ctl.rc_app_limited_cnt--; } if (rsm->r_limit_type) { /* currently there is only one limit type */ @@ -3554,8 +3553,7 @@ rack_get_measure_window(struct tcpcb *tp, struct tcp_rack *rack) * earlier. * * So lets calculate the BDP with the "known" b/w using - * the SRTT has our rtt and then multiply it by the - * goal. + * the SRTT as our rtt and then multiply it by the goal. */ bw = rack_get_bw(rack); srtt = (uint64_t)tp->t_srtt; @@ -5793,7 +5791,7 @@ rack_cong_signal(struct tcpcb *tp, uint32_t type, uint32_t ack, int line) tp->t_badrxtwin = 0; break; } - if ((CC_ALGO(tp)->cong_signal != NULL) && + if ((CC_ALGO(tp)->cong_signal != NULL) && (type != CC_RTO)){ tp->t_ccv.curack = ack; CC_ALGO(tp)->cong_signal(&tp->t_ccv, type); @@ -5904,7 +5902,7 @@ rack_calc_thresh_rack(struct tcp_rack *rack, uint32_t srtt, uint32_t cts, int li * * If reorder-fade is configured, then we track the last time we saw * re-ordering occur. If we reach the point where enough time as - * passed we no longer consider reordering has occuring. + * passed we no longer consider reordering as occurring. * * Or if reorder-face is 0, then once we see reordering we consider * the connection to alway be subject to reordering and just set lro @@ -7045,6 +7043,9 @@ rack_clone_rsm(struct tcp_rack *rack, struct rack_sendmap *nrsm, /* Push bit must go to the right edge as well */ if (rsm->r_flags & RACK_HAD_PUSH) rsm->r_flags &= ~RACK_HAD_PUSH; + /* Update the count if app limited */ + if (nrsm->r_flags & RACK_APP_LIMITED) + rack->r_ctl.rc_app_limited_cnt++; /* Clone over the state of the hw_tls flag */ nrsm->r_hw_tls = rsm->r_hw_tls; /* @@ -7096,7 +7097,7 @@ rack_merge_rsm(struct tcp_rack *rack, l_rsm->r_flags |= RACK_TLP; if (r_rsm->r_flags & RACK_RWND_COLLAPSED) l_rsm->r_flags |= RACK_RWND_COLLAPSED; - if ((r_rsm->r_flags & RACK_APP_LIMITED) && + if ((r_rsm->r_flags & RACK_APP_LIMITED) && ((l_rsm->r_flags & RACK_APP_LIMITED) == 0)) { /* * If both are app-limited then let the @@ -8137,7 +8138,7 @@ rack_update_rsm(struct tcpcb *tp, struct tcp_rack *rack, * remove the lost desgination and reduce the * bytes considered lost. */ - rsm->r_flags &= ~RACK_WAS_LOST; + rsm->r_flags &= ~RACK_WAS_LOST; KASSERT((rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)), ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack)); if (rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)) @@ -8832,7 +8833,7 @@ rack_apply_updated_usrtt(struct tcp_rack *rack, uint32_t us_rtt, uint32_t us_cts val = rack_probertt_lower_within * rack_time_between_probertt; val /= 100; - if ((rack->in_probe_rtt == 0) && + if ((rack->in_probe_rtt == 0) && (rack->rc_skip_timely == 0) && ((us_cts - rack->r_ctl.rc_lower_rtt_us_cts) >= (rack_time_between_probertt - val))) { rack_enter_probertt(rack, us_cts); @@ -10369,7 +10370,7 @@ more: * and yet before retransmitting we get an ack * which can happen due to reordering. */ - rsm->r_flags &= ~RACK_WAS_LOST; + rsm->r_flags &= ~RACK_WAS_LOST; KASSERT((rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)), ("rsm:%p rack:%p rc_considered_lost goes negative", rsm, rack)); if (rack->r_ctl.rc_considered_lost >= (rsm->r_end - rsm->r_start)) @@ -11065,7 +11066,7 @@ rack_strike_dupack(struct tcp_rack *rack, tcp_seq th_ack) * We need to skip anything already set * to be retransmitted. */ - if ((rsm->r_dupack >= DUP_ACK_THRESHOLD) || + if ((rsm->r_dupack >= DUP_ACK_THRESHOLD) || (rsm->r_flags & RACK_MUST_RXT)) { rsm = TAILQ_NEXT(rsm, r_tnext); continue; @@ -12875,7 +12876,7 @@ rack_do_syn_sent(struct mbuf *m, struct tcphdr *th, struct socket *so, (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if ((thflags & (TH_ACK | TH_RST)) == (TH_ACK | TH_RST)) { @@ -13089,7 +13090,7 @@ rack_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, (SEQ_LEQ(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if (tp->t_flags & TF_FASTOPEN) { @@ -13102,7 +13103,7 @@ rack_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((thflags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } else if (thflags & TH_SYN) { /* non-initial SYN is ignored */ @@ -13136,7 +13137,7 @@ rack_do_syn_recv(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if (SEQ_LT(th->th_seq, tp->irs)) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } if (ctf_drop_checks(to, m, th, tp, &tlen, &thflags, &drop_hdrlen, &ret_val)) { @@ -13399,7 +13400,7 @@ rack_do_established(struct mbuf *m, struct tcphdr *th, struct socket *so, if (sbavail(&so->so_snd)) { if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event(rack, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -13495,7 +13496,7 @@ rack_do_close_wait(struct mbuf *m, struct tcphdr *th, struct socket *so, if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event((struct tcp_rack *)tp->t_fb_ptr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -13645,7 +13646,7 @@ rack_do_fin_wait_1(struct mbuf *m, struct tcphdr *th, struct socket *so, if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event((struct tcp_rack *)tp->t_fb_ptr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -13746,7 +13747,7 @@ rack_do_closing(struct mbuf *m, struct tcphdr *th, struct socket *so, if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event((struct tcp_rack *)tp->t_fb_ptr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -13848,7 +13849,7 @@ rack_do_lastack(struct mbuf *m, struct tcphdr *th, struct socket *so, if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event((struct tcp_rack *)tp->t_fb_ptr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -13952,7 +13953,7 @@ rack_do_fin_wait_2(struct mbuf *m, struct tcphdr *th, struct socket *so, if (ctf_progress_timeout_check(tp, true)) { rack_log_progress_event((struct tcp_rack *)tp->t_fb_ptr, tp, tick, PROGRESS_DROP, __LINE__); - ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset_conn(m, tp, th, BANDLIM_TCP_RST, tlen); return (1); } } @@ -16655,7 +16656,7 @@ rack_do_segment_nounlock(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, if ((tp->t_state == TCPS_SYN_SENT) && (thflags & TH_ACK) && (SEQ_LEQ(th->th_ack, tp->iss) || SEQ_GT(th->th_ack, tp->snd_max))) { tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT); - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); #ifdef TCP_ACCOUNTING sched_unpin(); #endif @@ -16919,7 +16920,7 @@ do_output_now: } else if ((nxt_pkt == 0) && (tp->t_flags & TF_ACKNOW)) { goto do_output_now; } else if ((no_output == 1) && - (nxt_pkt == 0) && + (nxt_pkt == 0) && (tcp_in_hpts(rack->rc_tp) == 0)) { /* * We are not in hpts and we had a pacing timer up. Use @@ -17546,7 +17547,7 @@ rack_get_pacing_delay(struct tcp_rack *rack, struct tcpcb *tp, uint32_t len, str rack->r_ctl.rc_last_us_rtt, 88, __LINE__, NULL, gain); } - if (((bw_est == 0) || (rate_wanted == 0) || (rack->gp_ready == 0)) && + if (((bw_est == 0) || (rate_wanted == 0) || (rack->gp_ready == 0)) && (rack->use_fixed_rate == 0)) { /* * No way yet to make a b/w estimate or @@ -17986,7 +17987,7 @@ start_set: tp->gput_ack = tp->gput_seq + rack_get_measure_window(tp, rack); rack->r_ctl.rc_gp_cumack_ts = 0; if ((rack->r_ctl.cleared_app_ack == 1) && - (SEQ_GEQ(rack->r_ctl.cleared_app_ack, tp->gput_seq))) { + (SEQ_GEQ(tp->gput_seq, rack->r_ctl.cleared_app_ack_seq))) { /* * We just cleared an application limited period * so the next seq out needs to skip the first @@ -20043,7 +20044,7 @@ again: rack->r_ctl.pcm_max_seg = ctf_fixed_maxseg(tp) * 10; } } - if ((rack->r_ctl.pcm_max_seg != 0) && (rack->pcm_needed == 1)) { + if ((rack->r_ctl.pcm_max_seg != 0) && (rack->pcm_needed == 1)) { uint32_t rw_avail, cwa; if (tp->snd_wnd > ctf_outstanding(tp)) @@ -21031,7 +21032,7 @@ just_return_nolock: } else log = 1; } - /* Mark the last packet has app limited */ + /* Mark the last packet as app limited */ rsm = tqhash_max(rack->r_ctl.tqh); if (rsm && ((rsm->r_flags & RACK_APP_LIMITED) == 0)) { if (rack->r_ctl.rc_app_limited_cnt == 0) diff --git a/sys/netinet/tcp_stacks/rack_bbr_common.c b/sys/netinet/tcp_stacks/rack_bbr_common.c index da26b8cb1f9b..d1c4ba58bf55 100644 --- a/sys/netinet/tcp_stacks/rack_bbr_common.c +++ b/sys/netinet/tcp_stacks/rack_bbr_common.c @@ -672,7 +672,7 @@ ctf_do_dropafterack(struct mbuf *m, struct tcpcb *tp, struct tcphdr *th, int32_t (SEQ_GT(tp->snd_una, th->th_ack) || SEQ_GT(th->th_ack, tp->snd_max))) { *ret_val = 1; - ctf_do_dropwithreset(m, tp, th, BANDLIM_RST_OPENPORT, tlen); + ctf_do_dropwithreset(m, tp, th, BANDLIM_TCP_RST, tlen); return; } else *ret_val = 0; diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c index d476829e8e3b..2bab1c57ce2a 100644 --- a/sys/netinet6/in6_gif.c +++ b/sys/netinet6/in6_gif.c @@ -194,6 +194,11 @@ in6_gif_setopts(struct gif_softc *sc, u_int options) sc->gif_options = options; in6_gif_attach(sc); } + + if ((options & GIF_NOCLAMP) != + (sc->gif_options & GIF_NOCLAMP)) { + sc->gif_options = options; + } return (0); } @@ -289,6 +294,7 @@ in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn) { struct gif_softc *sc = ifp->if_softc; struct ip6_hdr *ip6; + u_long mtu; /* prepend new IP header */ NET_EPOCH_ASSERT(); @@ -304,11 +310,15 @@ in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn) ip6->ip6_nxt = proto; ip6->ip6_hlim = V_ip6_gif_hlim; /* - * force fragmentation to minimum MTU, to avoid path MTU discovery. - * it is too painful to ask for resend of inner packet, to achieve - * path MTU discovery for encapsulated packets. + * Enforce fragmentation to minimum MTU, even if the interface MTU + * is larger, to avoid path MTU discovery when NOCLAMP is not + * set (default). IPv6 does not allow fragmentation on intermediate + * router nodes, so it is too painful to ask for resend of inner + * packet, to achieve path MTU discovery for encapsulated packets. */ - return (ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL, NULL)); + mtu = ((sc->gif_options & GIF_NOCLAMP) == 0) ? IPV6_MINMTU : 0; + + return (ip6_output(m, 0, NULL, mtu, 0, NULL, NULL)); } static int diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c index 06fe9e8820c9..a825658bd9ee 100644 --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -234,17 +234,20 @@ static SYSCTL_NODE(_net_inet6_mld, OID_AUTO, ifinfo, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_mld_ifinfo, "Per-interface MLDv2 state"); -static int mld_v1enable = 1; -SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RWTUN, - &mld_v1enable, 0, "Enable fallback to MLDv1"); +VNET_DEFINE_STATIC(bool, mld_v1enable) = true; +#define V_mld_v1enable VNET(mld_v1enable) +SYSCTL_BOOL(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_VNET | CTLFLAG_RWTUN, + &VNET_NAME(mld_v1enable), 0, "Enable fallback to MLDv1"); -static int mld_v2enable = 1; -SYSCTL_INT(_net_inet6_mld, OID_AUTO, v2enable, CTLFLAG_RWTUN, - &mld_v2enable, 0, "Enable MLDv2"); +VNET_DEFINE_STATIC(bool, mld_v2enable) = true; +#define V_mld_v2enable VNET(mld_v2enable) +SYSCTL_BOOL(_net_inet6_mld, OID_AUTO, v2enable, CTLFLAG_VNET | CTLFLAG_RWTUN, + &VNET_NAME(mld_v2enable), 0, "Enable MLDv2"); -static int mld_use_allow = 1; -SYSCTL_INT(_net_inet6_mld, OID_AUTO, use_allow, CTLFLAG_RWTUN, - &mld_use_allow, 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves"); +VNET_DEFINE_STATIC(bool, mld_use_allow) = true; +#define V_mld_use_allow VNET(mld_use_allow) +SYSCTL_BOOL(_net_inet6_mld, OID_AUTO, use_allow, CTLFLAG_VNET | CTLFLAG_RWTUN, + &VNET_NAME(mld_use_allow), 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves"); /* * Packed Router Alert option structure declaration. @@ -481,7 +484,7 @@ mld_domifattach(struct ifnet *ifp) mbufq_init(&mli->mli_gq, MLD_MAX_RESPONSE_PACKETS); if ((ifp->if_flags & IFF_MULTICAST) == 0) mli->mli_flags |= MLIF_SILENT; - if (mld_use_allow) + if (V_mld_use_allow) mli->mli_flags |= MLIF_USEALLOW; MLD_LOCK(); @@ -614,7 +617,7 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6, is_general_query = 0; - if (!mld_v1enable) { + if (!V_mld_v1enable) { CTR3(KTR_MLD, "ignore v1 query %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &mld->mld_addr), ifp, if_name(ifp)); @@ -790,7 +793,7 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6, NET_EPOCH_ASSERT(); - if (!mld_v2enable) { + if (!V_mld_v2enable) { CTR3(KTR_MLD, "ignore v2 query src %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &ip6->ip6_src), ifp, if_name(ifp)); @@ -1076,7 +1079,7 @@ mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6, NET_EPOCH_ASSERT(); - if (!mld_v1enable) { + if (!V_mld_v1enable) { CTR3(KTR_MLD, "ignore v1 report %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &mld->mld_addr), ifp, if_name(ifp)); diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 0379ef7c789a..c90a1213bd66 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -765,8 +765,7 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) } if (ifa != NULL && ((struct in6_ifaddr *)ifa)->ia6_flags & - (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| - IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { + (IN6_IFF_NOTREADY|IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { NET_EPOCH_EXIT(et); return (EADDRNOTAVAIL); } diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index 6bacc68b7441..92d0201b398a 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -636,8 +636,10 @@ ipsec4_in_reject1(const struct mbuf *m, struct ip *ip1, struct inpcb *inp) #ifdef IPSEC_OFFLOAD tag = ipsec_accel_input_tag_lookup(m); - if (tag != NULL) - return (0); + if (tag != NULL) { + tag->tag.m_tag_id = PACKET_TAG_IPSEC_IN_DONE; + __DECONST(struct mbuf *, m)->m_flags |= M_DECRYPTED; + } #endif if (ip1 == NULL) { diff --git a/sys/netipsec/ipsec_offload.c b/sys/netipsec/ipsec_offload.c index 467d5ded1d7a..8a09d5f37b4a 100644 --- a/sys/netipsec/ipsec_offload.c +++ b/sys/netipsec/ipsec_offload.c @@ -94,6 +94,7 @@ struct ifp_handle_sav { size_t hdr_ext_size; uint64_t cnt_octets; uint64_t cnt_allocs; + struct xform_history xfh; }; #define IFP_HS_HANDLED 0x00000001 @@ -159,6 +160,8 @@ static void ipsec_accel_drv_sa_lifetime_update_impl(struct secasvar *sav, static int ipsec_accel_drv_sa_lifetime_fetch_impl(struct secasvar *sav, if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs); static void ipsec_accel_ifdetach_event(void *arg, struct ifnet *ifp); +static bool ipsec_accel_fill_xh_impl(if_t ifp, uint32_t drv_spi, + struct xform_history *xh); static void ipsec_accel_init(void *arg) @@ -185,6 +188,7 @@ ipsec_accel_init(void *arg) ipsec_accel_drv_sa_lifetime_update_impl; ipsec_accel_drv_sa_lifetime_fetch_p = ipsec_accel_drv_sa_lifetime_fetch_impl; + ipsec_accel_fill_xh_p = ipsec_accel_fill_xh_impl; pctrie_init(&drv_spi_pctrie); ipsec_accel_ifdetach_event_tag = EVENTHANDLER_REGISTER( ifnet_departure_event, ipsec_accel_ifdetach_event, NULL, @@ -209,6 +213,7 @@ ipsec_accel_fini(void *arg) ipsec_accel_on_ifdown_p = NULL; ipsec_accel_drv_sa_lifetime_update_p = NULL; ipsec_accel_drv_sa_lifetime_fetch_p = NULL; + ipsec_accel_fill_xh_p = NULL; ipsec_accel_sync_imp(); clean_unrhdr(drv_spi_unr); /* avoid panic, should go later */ clear_unrhdr(drv_spi_unr); @@ -412,6 +417,10 @@ ipsec_accel_handle_sav(struct secasvar *sav, struct ifnet *ifp, ihs->ifdata = priv; ihs->flags = flags; ihs->hdr_ext_size = esp_hdrsiz(sav); + memcpy(&ihs->xfh.dst, &sav->sah->saidx.dst, sizeof(ihs->xfh.dst)); + ihs->xfh.spi = sav->spi; + ihs->xfh.proto = sav->sah->saidx.proto; + ihs->xfh.mode = sav->sah->saidx.mode; mtx_lock(&ipsec_accel_sav_tmp); CK_LIST_FOREACH(i, &sav->accel_ifps, sav_link) { if (i->ifp == ifp) { @@ -1162,4 +1171,20 @@ ipsec_accel_key_setaccelif_impl(struct secasvar *sav) return (m); } +static bool +ipsec_accel_fill_xh_impl(if_t ifp, uint32_t drv_spi, struct xform_history *xh) +{ + struct ifp_handle_sav *i; + + if (drv_spi < IPSEC_ACCEL_DRV_SPI_MIN || + drv_spi > IPSEC_ACCEL_DRV_SPI_MAX) + return (false); + + i = DRVSPI_SA_PCTRIE_LOOKUP(&drv_spi_pctrie, drv_spi); + if (i == NULL) + return (false); + memcpy(xh, &i->xfh, sizeof(*xh)); + return (true); +} + #endif /* IPSEC_OFFLOAD */ diff --git a/sys/netipsec/ipsec_offload.h b/sys/netipsec/ipsec_offload.h index 904fe6252396..ae60eaa8ae78 100644 --- a/sys/netipsec/ipsec_offload.h +++ b/sys/netipsec/ipsec_offload.h @@ -30,6 +30,7 @@ #include <sys/errno.h> #include <net/if.h> #include <net/if_var.h> +#include <netipsec/xform.h> struct secpolicy; struct secasvar; @@ -42,6 +43,7 @@ struct ipsec_accel_out_tag { struct ipsec_accel_in_tag { struct m_tag tag; + struct xform_history xh; /* Must be first to mimic IPSEC_IN_DONE */ uint16_t drv_spi; }; @@ -66,6 +68,8 @@ extern void (*ipsec_accel_drv_sa_lifetime_update_p)(struct secasvar *sav, if_t ifp, u_int drv_spi, uint64_t octets, uint64_t allocs); extern int (*ipsec_accel_drv_sa_lifetime_fetch_p)(struct secasvar *sav, if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs); +extern bool (*ipsec_accel_fill_xh_p)(if_t ifp, uint32_t drv_spi, + struct xform_history *xh); #ifdef IPSEC_OFFLOAD /* @@ -158,6 +162,16 @@ ipsec_accel_key_setaccelif(struct secasvar *sav) return (NULL); } +static inline bool +ipsec_accel_fill_xh(if_t ifp, uint32_t drv_spi, struct xform_history *xh) +{ + bool (*p)(if_t ifp, uint32_t drv_spi, struct xform_history *xh); + + p = atomic_load_ptr(&ipsec_accel_fill_xh_p); + if (p != NULL) + return (p(ifp, drv_spi, xh)); + return (false); +} #else #define ipsec_accel_sa_newkey(a) @@ -168,6 +182,7 @@ ipsec_accel_key_setaccelif(struct secasvar *sav) #define ipsec_accel_sync() #define ipsec_accel_is_accel_sav(a) #define ipsec_accel_key_setaccelif(a) +#define ipsec_accel_fill_xh(a, b, c) (false) #endif void ipsec_accel_forget_sav_impl(struct secasvar *sav); @@ -180,6 +195,7 @@ bool ipsec_accel_output(struct ifnet *ifp, struct mbuf *m, struct inpcb *inp, struct secpolicy *sp, struct secasvar *sav, int af, int mtu, int *hwassist); void ipsec_accel_forget_sav(struct secasvar *sav); +struct xform_history; #else #define ipsec_accel_input(a, b, c) (ENXIO) #define ipsec_accel_output(a, b, c, d, e, f, g, h) ({ \ diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index ae67d83c6d13..4ba1b49c24f0 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -114,6 +114,8 @@ void (*ipsec_accel_drv_sa_lifetime_update_p)(struct secasvar *sav, if_t ifp, u_int drv_spi, uint64_t octets, uint64_t allocs); int (*ipsec_accel_drv_sa_lifetime_fetch_p)(struct secasvar *sav, if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs); +bool (*ipsec_accel_fill_xh_p)(if_t ifp, uint32_t drv_spi, + struct xform_history *xh); #endif #define FULLMASK 0xff diff --git a/sys/netlink/netlink_message_parser.h b/sys/netlink/netlink_message_parser.h index 8492ecb3021b..720317ed74f3 100644 --- a/sys/netlink/netlink_message_parser.h +++ b/sys/netlink/netlink_message_parser.h @@ -209,7 +209,8 @@ int nlattr_get_nested(struct nlattr *nla, struct nl_pstate *npt, int nlattr_get_nested_ptr(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); -bool nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...); +bool nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...) + __printflike(2, 3); #define NLMSG_REPORT_ERR_MSG(_npt, _fmt, ...) { \ nlmsg_report_err_msg(_npt, _fmt, ## __VA_ARGS__); \ diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 923633d76df7..c129c8c49921 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -196,7 +196,7 @@ SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "Firewall"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass, CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0, - "Only do a single pass through ipfw when using dummynet(4)"); + "Only do a single pass through ipfw when using dummynet(4), ipfw_nat or other divert(4)-like interfaces"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(autoinc_step), 0, "Rule number auto-increment step"); diff --git a/sys/netpfil/pf/if_pflog.c b/sys/netpfil/pf/if_pflog.c index 0a84f9d680ac..cb96d2fcc44c 100644 --- a/sys/netpfil/pf/if_pflog.c +++ b/sys/netpfil/pf/if_pflog.c @@ -284,9 +284,9 @@ pflog_packet(uint8_t action, u_int8_t reason, * state lock, since this leads to unsafe LOR. * These conditions are very very rare, however. */ - if (trigger->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done && lookupsafe) + if (trigger->log & PF_LOG_USER && !pd->lookup.done && lookupsafe) pd->lookup.done = pf_socket_lookup(pd); - if (pd->lookup.done > 0) + if (trigger->log & PF_LOG_USER && pd->lookup.done > 0) hdr.uid = pd->lookup.uid; else hdr.uid = -1; diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c index 2391edaf1a5a..ee10a997c977 100644 --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -110,8 +110,6 @@ #include <netpfil/pf/pfsync_nv.h> -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - struct pfsync_bucket; struct pfsync_softc; @@ -532,6 +530,7 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) struct pf_kpooladdr *rpool_first; int error; uint8_t rt = 0; + int n = 0; PF_RULES_RASSERT(); @@ -557,10 +556,12 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) */ if (sp->pfs_1301.rule != htonl(-1) && sp->pfs_1301.anchor == htonl(-1) && (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->pfs_1301.rule) < - pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) - r = pf_main_ruleset.rules[ - PF_RULESET_FILTER].active.ptr_array[ntohl(sp->pfs_1301.rule)]; - else + pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) { + TAILQ_FOREACH(r, pf_main_ruleset.rules[ + PF_RULESET_FILTER].active.ptr, entries) + if (ntohl(sp->pfs_1301.rule) == n++) + break; + } else r = &V_pf_default_rule; /* @@ -594,9 +595,9 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) if ((rpool_first == NULL) || (TAILQ_NEXT(rpool_first, entries) != NULL)) { DPFPRINTF(PF_DEBUG_MISC, - ("%s: can't recover routing information " - "because of empty or bad redirection pool\n", - __func__)); + "%s: can't recover routing information " + "because of empty or bad redirection pool", + __func__); return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0); } rt = r->rt; @@ -607,8 +608,8 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) * give up on recovering. */ DPFPRINTF(PF_DEBUG_MISC, - ("%s: can't recover routing information " - "because of different ruleset\n", __func__)); + "%s: can't recover routing information " + "because of different ruleset", __func__); return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0); } break; @@ -621,8 +622,8 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) rt_kif = pfi_kkif_find(sp->pfs_1400.rt_ifname); if (rt_kif == NULL) { DPFPRINTF(PF_DEBUG_MISC, - ("%s: unknown route interface: %s\n", - __func__, sp->pfs_1400.rt_ifname)); + "%s: unknown route interface: %s", + __func__, sp->pfs_1400.rt_ifname); return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0); } rt = sp->pfs_1400.rt; diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index a410fe570c39..c669be47b063 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -119,8 +119,6 @@ #include <machine/in_cksum.h> #include <security/mac/mac_framework.h> -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - SDT_PROVIDER_DEFINE(pf); SDT_PROBE_DEFINE2(pf, , test, reason_set, "int", "int"); SDT_PROBE_DEFINE4(pf, ip, test, done, "int", "int", "struct pf_krule *", @@ -161,6 +159,7 @@ SDT_PROBE_DEFINE2(pf, eth, test_rule, match, "int", "struct pf_keth_rule *"); SDT_PROBE_DEFINE2(pf, eth, test_rule, final_match, "int", "struct pf_keth_rule *"); SDT_PROBE_DEFINE2(pf, purge, state, rowcount, "int", "size_t"); +SDT_PROBE_DEFINE2(pf, , log, log, "int", "const char *"); /* * Global variables @@ -375,6 +374,8 @@ static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, int, u_int16_t); static int pf_check_proto_cksum(struct mbuf *, int, int, u_int8_t, sa_family_t); +static int pf_walk_option(struct pf_pdesc *, struct ip *, + int, int, u_short *); static int pf_walk_header(struct pf_pdesc *, struct ip *, u_short *); #ifdef INET6 static int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *, @@ -4615,8 +4616,8 @@ pf_match_rcvif(struct mbuf *m, struct pf_krule *r) if (kif == NULL) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: kif == NULL, @%d via %s\n", __func__, r->nr, - r->rcv_ifname)); + "%s: kif == NULL, @%d via %s", __func__, r->nr, + r->rcv_ifname); return (0); } @@ -5242,8 +5243,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) if (__predict_false(m->m_len < sizeof(struct ether_header)) && (m = *m0 = m_pullup(*m0, sizeof(struct ether_header))) == NULL) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: m_len < sizeof(struct ether_header)" - ", pullup failed\n", __func__)); + "%s: m_len < sizeof(struct ether_header)" + ", pullup failed", __func__); return (PF_DROP); } e = mtod(m, struct ether_header *); @@ -6168,8 +6169,8 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx, &s->src, &s->dst, &ctx->rewrite)) { /* This really shouldn't happen!!! */ DPFPRINTF(PF_DEBUG_URGENT, - ("%s: tcp normalize failed on first " - "pkt\n", __func__)); + "%s: tcp normalize failed on first " + "pkt", __func__); goto csfailed; } } else if (pd->proto == IPPROTO_SCTP) { @@ -6219,7 +6220,7 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx, if (ctx->tag > 0) s->tag = ctx->tag; if (pd->proto == IPPROTO_TCP && (tcp_get_flags(th) & (TH_SYN|TH_ACK)) == - TH_SYN && r->keep_state == PF_STATE_SYNPROXY) { + TH_SYN && r->keep_state == PF_STATE_SYNPROXY && pd->dir == PF_IN) { pf_set_protostate(s, PF_PEER_SRC, PF_TCPS_PROXY_SRC); pf_undo_nat(ctx->nr, pd, bip_sum); s->src.seqhi = arc4random(); @@ -7965,8 +7966,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, ipoff2, &h2, sizeof(h2), NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(ip)\n")); + "pf: ICMP error message too short " + "(ip)"); return (PF_DROP); } /* @@ -7996,8 +7997,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, ipoff2, &h2_6, sizeof(h2_6), NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(ip6)\n")); + "pf: ICMP error message too short " + "(ip6)"); return (PF_DROP); } pd2.off = ipoff2; @@ -8049,8 +8050,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, pd2.off, th, 8, NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(tcp)\n")); + "pf: ICMP error message too short " + "(tcp)"); return (PF_DROP); } pd2.pcksum = &pd2.hdr.tcp.th_sum; @@ -8244,8 +8245,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, pd2.off, uh, sizeof(*uh), NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(udp)\n")); + "pf: ICMP error message too short " + "(udp)"); return (PF_DROP); } pd2.pcksum = &pd2.hdr.udp.uh_sum; @@ -8376,8 +8377,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (! pf_pull_hdr(pd->m, pd2.off, sh, sizeof(*sh), NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(sctp)\n")); + "pf: ICMP error message too short " + "(sctp)"); return (PF_DROP); } pd2.pcksum = &pd2.sctp_dummy_sum; @@ -8407,8 +8408,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (src->scrub->pfss_v_tag != sh->v_tag) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message has incorrect " - "SCTP v_tag\n")); + "pf: ICMP error message has incorrect " + "SCTP v_tag"); return (PF_DROP); } @@ -8531,8 +8532,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, pd2.off, iih, ICMP_MINLEN, NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short i" - "(icmp)\n")); + "pf: ICMP error message too short i" + "(icmp)"); return (PF_DROP); } pd2.pcksum = &pd2.hdr.icmp.icmp_cksum; @@ -8651,8 +8652,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd, if (!pf_pull_hdr(pd->m, pd2.off, iih, sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: ICMP error message too short " - "(icmp6)\n")); + "pf: ICMP error message too short " + "(icmp6)"); return (PF_DROP); } pd2.pcksum = &pd2.hdr.icmp6.icmp6_cksum; @@ -9068,6 +9069,9 @@ pf_route(struct pf_krule *r, struct ifnet *oifp, goto bad; } + if (r->rt == PF_DUPTO) + skip_test = true; + if (pd->dir == PF_IN && !skip_test) { if (pf_test(AF_INET, PF_OUT, PFIL_FWD, ifp, &m0, inp, &pd->act) != PF_PASS) { @@ -9079,7 +9083,7 @@ pf_route(struct pf_krule *r, struct ifnet *oifp, } if (m0->m_len < sizeof(struct ip)) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: m0->m_len < sizeof(struct ip)\n", __func__)); + "%s: m0->m_len < sizeof(struct ip)", __func__); SDT_PROBE1(pf, ip, route_to, drop, __LINE__); goto bad; } @@ -9370,6 +9374,9 @@ pf_route6(struct pf_krule *r, struct ifnet *oifp, goto bad; } + if (r->rt == PF_DUPTO) + skip_test = true; + if (pd->dir == PF_IN && !skip_test) { if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT, ifp, &m0, inp, &pd->act) != PF_PASS) { @@ -9381,8 +9388,8 @@ pf_route6(struct pf_krule *r, struct ifnet *oifp, } if (m0->m_len < sizeof(struct ip6_hdr)) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: m0->m_len < sizeof(struct ip6_hdr)\n", - __func__)); + "%s: m0->m_len < sizeof(struct ip6_hdr)", + __func__); SDT_PROBE1(pf, ip6, route_to, drop, __LINE__); goto bad; } @@ -9677,7 +9684,7 @@ pf_test_eth(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, if (kif == NULL) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: kif == NULL, if_xname %s\n", __func__, ifp->if_xname)); + "%s: kif == NULL, if_xname %s", __func__, ifp->if_xname); return (PF_DROP); } if (kif->pfik_flags & PFI_IFLAG_SKIP) @@ -9792,6 +9799,62 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s, } static int +pf_walk_option(struct pf_pdesc *pd, struct ip *h, int off, int end, + u_short *reason) +{ + uint8_t type, length, opts[15 * 4 - sizeof(struct ip)]; + + /* IP header in payload of ICMP packet may be too short */ + if (pd->m->m_pkthdr.len < end) { + DPFPRINTF(PF_DEBUG_MISC, "IP option too short"); + REASON_SET(reason, PFRES_SHORT); + return (PF_DROP); + } + + MPASS(end - off <= sizeof(opts)); + m_copydata(pd->m, off, end - off, opts); + end -= off; + off = 0; + + while (off < end) { + type = opts[off]; + if (type == IPOPT_EOL) + break; + if (type == IPOPT_NOP) { + off++; + continue; + } + if (off + 2 > end) { + DPFPRINTF(PF_DEBUG_MISC, "IP length opt"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); + } + length = opts[off + 1]; + if (length < 2) { + DPFPRINTF(PF_DEBUG_MISC, "IP short opt"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); + } + if (off + length > end) { + DPFPRINTF(PF_DEBUG_MISC, "IP long opt"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); + } + switch (type) { + case IPOPT_RA: + pd->badopts |= PF_OPT_ROUTER_ALERT; + break; + default: + pd->badopts |= PF_OPT_OTHER; + break; + } + off += length; + } + + return (PF_PASS); +} + +static int pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason) { struct ah ext; @@ -9803,11 +9866,28 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason) REASON_SET(reason, PFRES_SHORT); return (PF_DROP); } - if (hlen != sizeof(struct ip)) - pd->badopts++; + if (hlen != sizeof(struct ip)) { + if (pf_walk_option(pd, h, pd->off + sizeof(struct ip), + pd->off + hlen, reason) != PF_PASS) + return (PF_DROP); + /* header options which contain only padding is fishy */ + if (pd->badopts == 0) + pd->badopts |= PF_OPT_OTHER; + } end = pd->off + ntohs(h->ip_len); pd->off += hlen; pd->proto = h->ip_p; + /* IGMP packets have router alert options, allow them */ + if (pd->proto == IPPROTO_IGMP) { + /* According to RFC 1112 ttl must be set to 1. */ + if ((h->ip_ttl != 1) || + !IN_MULTICAST(ntohl(h->ip_dst.s_addr))) { + DPFPRINTF(PF_DEBUG_MISC, "Invalid IGMP"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); + } + pd->badopts &= ~PF_OPT_ROUTER_ALERT; + } /* stop walking over non initial fragments */ if ((h->ip_off & htons(IP_OFFMASK)) != 0) return (PF_PASS); @@ -9820,7 +9900,7 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason) return (PF_PASS); if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), NULL, reason, AF_INET)) { - DPFPRINTF(PF_DEBUG_MISC, ("IP short exthdr")); + DPFPRINTF(PF_DEBUG_MISC, "IP short exthdr"); return (PF_DROP); } pd->off += (ext.ah_len + 2) * 4; @@ -9830,7 +9910,7 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason) return (PF_PASS); } } - DPFPRINTF(PF_DEBUG_MISC, ("IPv4 nested authentication header limit")); + DPFPRINTF(PF_DEBUG_MISC, "IPv4 nested authentication header limit"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } @@ -9846,7 +9926,7 @@ pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end, while (off < end) { if (!pf_pull_hdr(pd->m, off, &opt.ip6o_type, sizeof(opt.ip6o_type), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt type")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short opt type"); return (PF_DROP); } if (opt.ip6o_type == IP6OPT_PAD1) { @@ -9855,41 +9935,48 @@ pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end, } if (!pf_pull_hdr(pd->m, off, &opt, sizeof(opt), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short opt"); return (PF_DROP); } if (off + sizeof(opt) + opt.ip6o_len > end) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 long opt")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 long opt"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } switch (opt.ip6o_type) { + case IP6OPT_PADN: + break; case IP6OPT_JUMBO: + pd->badopts |= PF_OPT_JUMBO; if (pd->jumbolen != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple jumbo")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple jumbo"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (ntohs(h->ip6_plen) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 bad jumbo plen")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 bad jumbo plen"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } if (!pf_pull_hdr(pd->m, off, &jumbo, sizeof(jumbo), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbo")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short jumbo"); return (PF_DROP); } memcpy(&pd->jumbolen, jumbo.ip6oj_jumbo_len, sizeof(pd->jumbolen)); pd->jumbolen = ntohl(pd->jumbolen); if (pd->jumbolen < IPV6_MAXPACKET) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbolen")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short jumbolen"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } break; + case IP6OPT_ROUTER_ALERT: + pd->badopts |= PF_OPT_ROUTER_ALERT; + break; default: + pd->badopts |= PF_OPT_OTHER; break; } off += sizeof(opt) + opt.ip6o_len; @@ -9903,6 +9990,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) { struct ip6_frag frag; struct ip6_ext ext; + struct icmp6_hdr icmp6; struct ip6_rthdr rthdr; uint32_t end; int hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0; @@ -9914,27 +10002,40 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) for (hdr_cnt = 0; hdr_cnt < PF_HDR_LIMIT; hdr_cnt++) { switch (pd->proto) { case IPPROTO_ROUTING: - case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: - pd->badopts++; + pd->badopts |= PF_OPT_OTHER; + break; + case IPPROTO_HOPOPTS: + if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), + NULL, reason, AF_INET6)) { + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short exthdr"); + return (PF_DROP); + } + if (pf_walk_option6(pd, h, pd->off + sizeof(ext), + pd->off + (ext.ip6e_len + 1) * 8, + reason) != PF_PASS) + return (PF_DROP); + /* option header which contains only padding is fishy */ + if (pd->badopts == 0) + pd->badopts |= PF_OPT_OTHER; break; } switch (pd->proto) { case IPPROTO_FRAGMENT: if (fraghdr_cnt++) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple fragment")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple fragment"); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } /* jumbo payload packets cannot be fragmented */ if (pd->jumbolen != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 fragmented jumbo")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 fragmented jumbo"); REASON_SET(reason, PFRES_FRAG); return (PF_DROP); } if (!pf_pull_hdr(pd->m, pd->off, &frag, sizeof(frag), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short fragment")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short fragment"); return (PF_DROP); } /* stop walking over non initial fragments */ @@ -9950,7 +10051,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) break; case IPPROTO_ROUTING: if (rthdr_cnt++) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple rthdr")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple rthdr"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } @@ -9962,11 +10063,11 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) } if (!pf_pull_hdr(pd->m, pd->off, &rthdr, sizeof(rthdr), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short rthdr")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short rthdr"); return (PF_DROP); } if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 rthdr0")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 rthdr0"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } @@ -9974,7 +10075,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) case IPPROTO_HOPOPTS: /* RFC2460 4.1: Hop-by-Hop only after IPv6 header */ if (pd->proto == IPPROTO_HOPOPTS && hdr_cnt > 0) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 hopopts not first")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 hopopts not first"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } @@ -9983,7 +10084,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) case IPPROTO_DSTOPTS: if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext), NULL, reason, AF_INET6)) { - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short exthdr")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 short exthdr"); return (PF_DROP); } /* fragments may be short */ @@ -9995,18 +10096,11 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) /* reassembly needs the ext header before the frag */ if (pd->fragoff == 0) pd->extoff = pd->off; - if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0) { - if (pf_walk_option6(pd, h, - pd->off + sizeof(ext), - pd->off + (ext.ip6e_len + 1) * 8, reason) - != PF_PASS) - return (PF_DROP); - if (ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) { - DPFPRINTF(PF_DEBUG_MISC, - ("IPv6 missing jumbo")); - REASON_SET(reason, PFRES_IPOPTIONS); - return (PF_DROP); - } + if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0 && + ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) { + DPFPRINTF(PF_DEBUG_MISC, "IPv6 missing jumbo"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); } if (pd->proto == IPPROTO_AH) pd->off += (ext.ip6e_len + 2) * 4; @@ -10014,10 +10108,45 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) pd->off += (ext.ip6e_len + 1) * 8; pd->proto = ext.ip6e_nxt; break; + case IPPROTO_ICMPV6: + /* fragments may be short, ignore inner header then */ + if (pd->fragoff != 0 && end < pd->off + sizeof(icmp6)) { + pd->off = pd->fragoff; + pd->proto = IPPROTO_FRAGMENT; + return (PF_PASS); + } + if (!pf_pull_hdr(pd->m, pd->off, &icmp6, sizeof(icmp6), + NULL, reason, AF_INET6)) { + DPFPRINTF(PF_DEBUG_MISC, + "IPv6 short icmp6hdr"); + return (PF_DROP); + } + /* ICMP multicast packets have router alert options */ + switch (icmp6.icmp6_type) { + case MLD_LISTENER_QUERY: + case MLD_LISTENER_REPORT: + case MLD_LISTENER_DONE: + case MLDV2_LISTENER_REPORT: + /* + * According to RFC 2710 all MLD messages are + * sent with hop-limit (ttl) set to 1, and link + * local source address. If either one is + * missing then MLD message is invalid and + * should be discarded. + */ + if ((h->ip6_hlim != 1) || + !IN6_IS_ADDR_LINKLOCAL(&h->ip6_src)) { + DPFPRINTF(PF_DEBUG_MISC, "Invalid MLD"); + REASON_SET(reason, PFRES_IPOPTIONS); + return (PF_DROP); + } + pd->badopts &= ~PF_OPT_ROUTER_ALERT; + break; + } + return (PF_PASS); case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_SCTP: - case IPPROTO_ICMPV6: /* fragments may be short, ignore inner header then */ if (pd->fragoff != 0 && end < pd->off + (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) : @@ -10032,7 +10161,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason) return (PF_PASS); } } - DPFPRINTF(PF_DEBUG_MISC, ("IPv6 nested extension header limit")); + DPFPRINTF(PF_DEBUG_MISC, "IPv6 nested extension header limit"); REASON_SET(reason, PFRES_IPOPTIONS); return (PF_DROP); } @@ -10058,6 +10187,8 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, pd->didx = (dir == PF_IN) ? 1 : 0; pd->af = pd->naf = af; + PF_RULES_ASSERT(); + TAILQ_INIT(&pd->sctp_multihome_jobs); if (default_actions != NULL) memcpy(&pd->act, default_actions, sizeof(pd->act)); @@ -10075,8 +10206,15 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, if (__predict_false((*m0)->m_len < sizeof(struct ip)) && (pd->m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: m_len < sizeof(struct ip), pullup failed\n", - __func__)); + "%s: m_len < sizeof(struct ip), pullup failed", + __func__); + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } + + h = mtod(pd->m, struct ip *); + if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) { *action = PF_DROP; REASON_SET(reason, PFRES_SHORT); return (-1); @@ -10089,13 +10227,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, return (-1); } *m0 = pd->m; - h = mtod(pd->m, struct ip *); - if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) { - *action = PF_DROP; - REASON_SET(reason, PFRES_SHORT); - return (-1); - } if (pf_walk_header(pd, h, reason) != PF_PASS) { *action = PF_DROP; @@ -10125,14 +10257,29 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, if (__predict_false((*m0)->m_len < sizeof(struct ip6_hdr)) && (pd->m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: m_len < sizeof(struct ip6_hdr)" - ", pullup failed\n", __func__)); + "%s: m_len < sizeof(struct ip6_hdr)" + ", pullup failed", __func__); *action = PF_DROP; REASON_SET(reason, PFRES_SHORT); return (-1); } h = mtod(pd->m, struct ip6_hdr *); + if (pd->m->m_pkthdr.len < + sizeof(struct ip6_hdr) + ntohs(h->ip6_plen)) { + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } + + /* + * we do not support jumbogram. if we keep going, zero ip6_plen + * will do something bad, so drop the packet for now. + */ + if (htons(h->ip6_plen) == 0) { + *action = PF_DROP; + return (-1); + } if (pf_walk_header6(pd, h, reason) != PF_PASS) { *action = PF_DROP; @@ -10153,15 +10300,6 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0, pd->virtual_proto = (pd->fragoff != 0) ? PF_VPROTO_FRAGMENT : pd->proto; - /* - * we do not support jumbogram. if we keep going, zero ip6_plen - * will do something bad, so drop the packet for now. - */ - if (htons(h->ip6_plen) == 0) { - *action = PF_DROP; - return (-1); - } - /* We do IP header normalization and packet reassembly here */ if (pf_normalize_ip6(pd->fragoff, reason, pd) != PF_PASS) { @@ -10471,35 +10609,30 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 PF_RULES_RLOCK_TRACKER; KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", __func__, dir)); M_ASSERTPKTHDR(*m0); + NET_EPOCH_ASSERT(); if (!V_pf_status.running) return (PF_PASS); - PF_RULES_RLOCK(); - kif = (struct pfi_kkif *)ifp->if_pf_kif; if (__predict_false(kif == NULL)) { DPFPRINTF(PF_DEBUG_URGENT, - ("%s: kif == NULL, if_xname %s\n", - __func__, ifp->if_xname)); - PF_RULES_RUNLOCK(); + "%s: kif == NULL, if_xname %s", + __func__, ifp->if_xname); return (PF_DROP); } if (kif->pfik_flags & PFI_IFLAG_SKIP) { - PF_RULES_RUNLOCK(); return (PF_PASS); } if ((*m0)->m_flags & M_SKIP_FIREWALL) { - PF_RULES_RUNLOCK(); return (PF_PASS); } if (__predict_false(! M_WRITABLE(*m0))) { *m0 = m_unshare(*m0, M_NOWAIT); if (*m0 == NULL) { - PF_RULES_RUNLOCK(); return (PF_DROP); } } @@ -10512,12 +10645,10 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 ifp = ifnet_byindexgen(pd.pf_mtag->if_index, pd.pf_mtag->if_idxgen); if (ifp == NULL || ifp->if_flags & IFF_DYING) { - PF_RULES_RUNLOCK(); m_freem(*m0); *m0 = NULL; return (PF_PASS); } - PF_RULES_RUNLOCK(); (ifp->if_output)(ifp, *m0, sintosa(&pd.pf_mtag->dst), NULL); *m0 = NULL; return (PF_PASS); @@ -10532,11 +10663,12 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 /* But only once. We may see the packet multiple times (e.g. * PFIL_IN/PFIL_OUT). */ pf_dummynet_flag_remove(pd.m, pd.pf_mtag); - PF_RULES_RUNLOCK(); return (PF_PASS); } + PF_RULES_RLOCK(); + if (pf_setup_pdesc(af, dir, &pd, m0, &action, &reason, kif, default_actions) == -1) { if (action != PF_PASS) @@ -10691,14 +10823,14 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0 action = PF_DROP; REASON_SET(&reason, PFRES_NORM); DPFPRINTF(PF_DEBUG_MISC, - ("dropping IPv6 packet with ICMPv4 payload")); + "dropping IPv6 packet with ICMPv4 payload"); break; } if (pd.virtual_proto == IPPROTO_ICMPV6 && af != AF_INET6) { action = PF_DROP; REASON_SET(&reason, PFRES_NORM); DPFPRINTF(PF_DEBUG_MISC, - ("pf: dropping IPv4 packet with ICMPv6 payload\n")); + "pf: dropping IPv4 packet with ICMPv6 payload"); break; } action = pf_test_state_icmp(&s, &pd, &reason); @@ -10724,12 +10856,12 @@ done: if (s) memcpy(&pd.act, &s->act, sizeof(s->act)); - if (action == PF_PASS && pd.badopts && !pd.act.allow_opts) { + if (action == PF_PASS && pd.badopts != 0 && !pd.act.allow_opts) { action = PF_DROP; REASON_SET(&reason, PFRES_IPOPTIONS); pd.act.log = PF_LOG_FORCE; DPFPRINTF(PF_DEBUG_MISC, - ("pf: dropping packet with dangerous headers\n")); + "pf: dropping packet with dangerous headers"); } if (pd.act.max_pkt_size && pd.act.max_pkt_size && @@ -10738,7 +10870,7 @@ done: REASON_SET(&reason, PFRES_NORM); pd.act.log = PF_LOG_FORCE; DPFPRINTF(PF_DEBUG_MISC, - ("pf: dropping overly long packet\n")); + "pf: dropping overly long packet"); } if (s) { @@ -10770,7 +10902,7 @@ done: REASON_SET(&reason, PFRES_MEMORY); pd.act.log = PF_LOG_FORCE; DPFPRINTF(PF_DEBUG_MISC, - ("pf: failed to allocate 802.1q mtag\n")); + "pf: failed to allocate 802.1q mtag"); } } @@ -10827,7 +10959,7 @@ done: REASON_SET(&reason, PFRES_MEMORY); pd.act.log = PF_LOG_FORCE; DPFPRINTF(PF_DEBUG_MISC, - ("pf: failed to allocate tag\n")); + "pf: failed to allocate tag"); } else { pd.pf_mtag->flags |= PF_MTAG_FLAG_FASTFWD_OURS_PRESENT; @@ -10844,7 +10976,7 @@ done: REASON_SET(&reason, PFRES_MEMORY); pd.act.log = PF_LOG_FORCE; DPFPRINTF(PF_DEBUG_MISC, - ("pf: failed to allocate divert tag\n")); + "pf: failed to allocate divert tag"); } } /* XXX: Anybody working on it?! */ diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index db353d185368..cfff58064922 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -140,7 +140,7 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, #define PF_LOG 0x01 #define PF_LOG_ALL 0x02 -#define PF_LOG_SOCKET_LOOKUP 0x04 +#define PF_LOG_USER 0x04 #define PF_LOG_FORCE 0x08 #define PF_LOG_MATCHES 0x10 diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index c14211edf10f..ea9f7fe441c6 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -217,8 +217,6 @@ static u_int16_t tagname2tag(struct pf_tagset *, const char *); static u_int16_t pf_tagname2tag(const char *); static void tag_unref(struct pf_tagset *, u_int16_t); -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - struct cdev *pf_dev; /* @@ -1359,7 +1357,7 @@ static int pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) { struct pf_kruleset *rs; - struct pf_krule *rule, **old_array, *old_rule; + struct pf_krule *rule, *old_rule; struct pf_krulequeue *old_rules; struct pf_krule_global *old_tree; int error; @@ -1384,13 +1382,10 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) /* Swap rules, keep the old. */ old_rules = rs->rules[rs_num].active.ptr; old_rcount = rs->rules[rs_num].active.rcount; - old_array = rs->rules[rs_num].active.ptr_array; old_tree = rs->rules[rs_num].active.tree; rs->rules[rs_num].active.ptr = rs->rules[rs_num].inactive.ptr; - rs->rules[rs_num].active.ptr_array = - rs->rules[rs_num].inactive.ptr_array; rs->rules[rs_num].active.tree = rs->rules[rs_num].inactive.tree; rs->rules[rs_num].active.rcount = @@ -1420,7 +1415,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) } rs->rules[rs_num].inactive.ptr = old_rules; - rs->rules[rs_num].inactive.ptr_array = old_array; rs->rules[rs_num].inactive.tree = NULL; /* important for pf_ioctl_addrule */ rs->rules[rs_num].inactive.rcount = old_rcount; @@ -1433,9 +1427,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) while ((rule = TAILQ_FIRST(old_rules)) != NULL) pf_unlink_rule_locked(old_rules, rule); PF_UNLNKDRULES_UNLOCK(); - if (rs->rules[rs_num].inactive.ptr_array) - free(rs->rules[rs_num].inactive.ptr_array, M_TEMP); - rs->rules[rs_num].inactive.ptr_array = NULL; rs->rules[rs_num].inactive.rcount = 0; rs->rules[rs_num].inactive.open = 0; pf_remove_if_empty_kruleset(rs); @@ -1458,24 +1449,11 @@ pf_setup_pfsync_matching(struct pf_kruleset *rs) if (rs_cnt == PF_RULESET_SCRUB) continue; - if (rs->rules[rs_cnt].inactive.ptr_array) - free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP); - rs->rules[rs_cnt].inactive.ptr_array = NULL; - if (rs->rules[rs_cnt].inactive.rcount) { - rs->rules[rs_cnt].inactive.ptr_array = - mallocarray(rs->rules[rs_cnt].inactive.rcount, - sizeof(struct pf_rule **), - M_TEMP, M_NOWAIT); - - if (!rs->rules[rs_cnt].inactive.ptr_array) - return (ENOMEM); - } - - TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr, - entries) { - pf_hash_rule_rolling(&ctx, rule); - (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule; + TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr, + entries) { + pf_hash_rule_rolling(&ctx, rule); + } } } @@ -2061,6 +2039,47 @@ pf_ioctl_getrules(struct pfioc_rule *pr) return (0); } +static int +pf_rule_checkaf(struct pf_krule *r) +{ + switch (r->af) { + case 0: + if (r->rule_flag & PFRULE_AFTO) + return (EPFNOSUPPORT); + break; + case AF_INET: + if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET6) + return (EPFNOSUPPORT); + break; +#ifdef INET6 + case AF_INET6: + if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET) + return (EPFNOSUPPORT); + break; +#endif /* INET6 */ + default: + return (EPFNOSUPPORT); + } + + if ((r->rule_flag & PFRULE_AFTO) == 0 && r->naf != 0) + return (EPFNOSUPPORT); + + return (0); +} + +static int +pf_validate_range(uint8_t op, uint16_t port[2]) +{ + uint16_t a = ntohs(port[0]); + uint16_t b = ntohs(port[1]); + + if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */ + (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */ + (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */ + return 1; + return 0; +} + int pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket, uint32_t pool_ticket, const char *anchor, const char *anchor_call, @@ -2080,6 +2099,13 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket, #define ERROUT(x) ERROUT_FUNCTION(errout, x) + if ((error = pf_rule_checkaf(rule))) + ERROUT(error); + if (pf_validate_range(rule->src.port_op, rule->src.port)) + ERROUT(EINVAL); + if (pf_validate_range(rule->dst.port_op, rule->dst.port)) + ERROUT(EINVAL); + if (rule->ifname[0]) kif = pf_kkif_create(M_WAITOK); if (rule->rcv_ifname[0]) @@ -2115,14 +2141,14 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket, ERROUT(EINVAL); if (ticket != ruleset->rules[rs_num].inactive.ticket) { DPFPRINTF(PF_DEBUG_MISC, - ("ticket: %d != [%d]%d\n", ticket, rs_num, - ruleset->rules[rs_num].inactive.ticket)); + "ticket: %d != [%d]%d", ticket, rs_num, + ruleset->rules[rs_num].inactive.ticket); ERROUT(EBUSY); } if (pool_ticket != V_ticket_pabuf) { DPFPRINTF(PF_DEBUG_MISC, - ("pool_ticket: %d != %d\n", pool_ticket, - V_ticket_pabuf)); + "pool_ticket: %d != %d", pool_ticket, + V_ticket_pabuf); ERROUT(EBUSY); } /* @@ -2441,7 +2467,7 @@ pf_start(void) V_pf_status.since = time_uptime; new_unrhdr64(&V_pf_stateid, time_second); - DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); + DPFPRINTF(PF_DEBUG_MISC, "pf: started"); } sx_xunlock(&V_pf_ioctl_lock); @@ -2461,7 +2487,7 @@ pf_stop(void) dehook_pf(); dehook_pf_eth(); V_pf_status.since = time_uptime; - DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); + DPFPRINTF(PF_DEBUG_MISC, "pf: stopped"); } sx_xunlock(&V_pf_ioctl_lock); @@ -3236,9 +3262,9 @@ DIOCGETETHRULE_error: if (nvlist_get_number(nvl, "ticket") != ruleset->inactive.ticket) { DPFPRINTF(PF_DEBUG_MISC, - ("ticket: %d != %d\n", + "ticket: %d != %d", (u_int32_t)nvlist_get_number(nvl, "ticket"), - ruleset->inactive.ticket)); + ruleset->inactive.ticket); ERROUT(EBUSY); } @@ -3569,7 +3595,7 @@ DIOCADDRULENV_error: error = pf_rule_to_krule(&pr->rule, rule); if (error != 0) { pf_krule_free(rule); - break; + goto fail; } pr->anchor[sizeof(pr->anchor) - 1] = '\0'; @@ -3728,11 +3754,11 @@ DIOCGETRULENV_error: if (pcr->action < PF_CHANGE_ADD_HEAD || pcr->action > PF_CHANGE_GET_TICKET) { error = EINVAL; - break; + goto fail; } if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { error = EINVAL; - break; + goto fail; } if (pcr->action != PF_CHANGE_REMOVE) { @@ -3740,9 +3766,13 @@ DIOCGETRULENV_error: error = pf_rule_to_krule(&pcr->rule, newrule); if (error != 0) { pf_krule_free(newrule); - break; + goto fail; } + if ((error = pf_rule_checkaf(newrule))) { + pf_krule_free(newrule); + goto fail; + } if (newrule->ifname[0]) kif = pf_kkif_create(M_WAITOK); pf_counter_u64_init(&newrule->evaluations, M_WAITOK); @@ -3890,7 +3920,7 @@ DIOCGETRULENV_error: pf_free_rule(newrule); PF_RULES_WUNLOCK(); PF_CONFIG_UNLOCK(); - break; + goto fail; } newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list); @@ -3917,7 +3947,7 @@ DIOCGETRULENV_error: PF_RULES_WUNLOCK(); PF_CONFIG_UNLOCK(); error = EINVAL; - break; + goto fail; } } @@ -3935,7 +3965,7 @@ DIOCGETRULENV_error: PF_RULES_WUNLOCK(); PF_CONFIG_UNLOCK(); error = EEXIST; - break; + goto fail; } if (oldrule == NULL) @@ -3991,7 +4021,7 @@ DIOCCHANGERULE_error: if (sp->timeout >= PFTM_MAX) { error = EINVAL; - break; + goto fail; } if (V_pfsync_state_import_ptr != NULL) { PF_RULES_RLOCK(); @@ -4011,7 +4041,7 @@ DIOCCHANGERULE_error: s = pf_find_state_byid(ps->state.id, ps->state.creatorid); if (s == NULL) { error = ENOENT; - break; + goto fail; } pfsync_state_export((union pfsync_state_union*)&ps->state, @@ -4090,7 +4120,7 @@ DIOCGETSTATES_retry: error = copyout(pstore, out, sizeof(struct pfsync_state_1301) * count); if (error) - break; + goto fail; out = ps->ps_states + nr; } DIOCGETSTATES_full: @@ -4110,7 +4140,7 @@ DIOCGETSTATES_full: if (ps->ps_req_version > PF_STATE_VERSION) { error = ENOTSUP; - break; + goto fail; } if (ps->ps_len <= 0) { @@ -4168,7 +4198,7 @@ DIOCGETSTATESV2_retry: error = copyout(pstore, out, sizeof(struct pf_state_export) * count); if (error) - break; + goto fail; out = ps->ps_states + nr; } DIOCGETSTATESV2_full: @@ -4274,12 +4304,12 @@ DIOCGETSTATESV2_full: if (psp->ifname[0] == '\0') { error = EINVAL; - break; + goto fail; } error = pf_user_strcpy(ps.ifname, psp->ifname, IFNAMSIZ); if (error != 0) - break; + goto fail; ifp = ifunit(ps.ifname); if (ifp != NULL) { psp->baudrate32 = @@ -4308,7 +4338,7 @@ DIOCGETSTATESV2_full: if (error == 0) V_pf_altq_running = 1; PF_RULES_WUNLOCK(); - DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n")); + DPFPRINTF(PF_DEBUG_MISC, "altq: started"); break; } @@ -4327,7 +4357,7 @@ DIOCGETSTATESV2_full: if (error == 0) V_pf_altq_running = 0; PF_RULES_WUNLOCK(); - DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n")); + DPFPRINTF(PF_DEBUG_MISC, "altq: stopped"); break; } @@ -4340,7 +4370,7 @@ DIOCGETSTATESV2_full: altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO); error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd)); if (error) - break; + goto fail; altq->local_flags = 0; PF_RULES_WLOCK(); @@ -4348,7 +4378,7 @@ DIOCGETSTATESV2_full: PF_RULES_WUNLOCK(); free(altq, M_PFALTQ); error = EBUSY; - break; + goto fail; } /* @@ -4360,7 +4390,7 @@ DIOCGETSTATESV2_full: PF_RULES_WUNLOCK(); error = EBUSY; free(altq, M_PFALTQ); - break; + goto fail; } altq->altq_disc = NULL; TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) { @@ -4380,7 +4410,7 @@ DIOCGETSTATESV2_full: if (error) { PF_RULES_WUNLOCK(); free(altq, M_PFALTQ); - break; + goto fail; } if (altq->qname[0] != 0) @@ -4418,13 +4448,13 @@ DIOCGETSTATESV2_full: if (pa->ticket != V_ticket_altqs_active) { PF_RULES_RUNLOCK(); error = EBUSY; - break; + goto fail; } altq = pf_altq_get_nth_active(pa->nr); if (altq == NULL) { PF_RULES_RUNLOCK(); error = EBUSY; - break; + goto fail; } pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd)); PF_RULES_RUNLOCK(); @@ -4448,20 +4478,20 @@ DIOCGETSTATESV2_full: if (pq->ticket != V_ticket_altqs_active) { PF_RULES_RUNLOCK(); error = EBUSY; - break; + goto fail; } nbytes = pq->nbytes; altq = pf_altq_get_nth_active(pq->nr); if (altq == NULL) { PF_RULES_RUNLOCK(); error = EBUSY; - break; + goto fail; } if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) { PF_RULES_RUNLOCK(); error = ENXIO; - break; + goto fail; } PF_RULES_RUNLOCK(); if (cmd == DIOCGETQSTATSV0) @@ -4530,30 +4560,30 @@ DIOCGETSTATESV2_full: if (pca->action < PF_CHANGE_ADD_HEAD || pca->action > PF_CHANGE_REMOVE) { error = EINVAL; - break; + goto fail; } if (pca->addr.addr.type != PF_ADDR_ADDRMASK && pca->addr.addr.type != PF_ADDR_DYNIFTL && pca->addr.addr.type != PF_ADDR_TABLE) { error = EINVAL; - break; + goto fail; } if (pca->addr.addr.p.dyn != NULL) { error = EINVAL; - break; + goto fail; } if (pca->action != PF_CHANGE_REMOVE) { #ifndef INET if (pca->af == AF_INET) { error = EAFNOSUPPORT; - break; + goto fail; } #endif /* INET */ #ifndef INET6 if (pca->af == AF_INET6) { error = EAFNOSUPPORT; - break; + goto fail; } #endif /* INET6 */ newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK); @@ -4676,7 +4706,7 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != 0) { error = ENODEV; - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, @@ -4692,13 +4722,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) { error = ENOMEM; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_table); @@ -4707,7 +4737,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_add_tables(pfrts, io->pfrio_size, @@ -4724,13 +4754,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) { error = ENOMEM; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_table); @@ -4739,7 +4769,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_del_tables(pfrts, io->pfrio_size, @@ -4757,14 +4787,14 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; - break; + goto fail; } PF_RULES_RLOCK(); n = pfr_table_count(&io->pfrio_table, io->pfrio_flags); if (n < 0) { PF_RULES_RUNLOCK(); error = EINVAL; - break; + goto fail; } io->pfrio_size = min(io->pfrio_size, n); @@ -4775,7 +4805,7 @@ DIOCCHANGEADDR_error: if (pfrts == NULL) { error = ENOMEM; PF_RULES_RUNLOCK(); - break; + goto fail; } error = pfr_get_tables(&io->pfrio_table, pfrts, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -4794,7 +4824,7 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_tstats)) { error = ENODEV; - break; + goto fail; } PF_TABLE_STATS_LOCK(); PF_RULES_RLOCK(); @@ -4803,7 +4833,7 @@ DIOCCHANGEADDR_error: PF_RULES_RUNLOCK(); PF_TABLE_STATS_UNLOCK(); error = EINVAL; - break; + goto fail; } io->pfrio_size = min(io->pfrio_size, n); @@ -4814,7 +4844,7 @@ DIOCCHANGEADDR_error: error = ENOMEM; PF_RULES_RUNLOCK(); PF_TABLE_STATS_UNLOCK(); - break; + goto fail; } error = pfr_get_tstats(&io->pfrio_table, pfrtstats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -4833,7 +4863,7 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || @@ -4842,7 +4872,7 @@ DIOCCHANGEADDR_error: * size, so we didn't fail on overly large requests. * Keep doing so. */ io->pfrio_size = pf_ioctl_maxcount; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_table); @@ -4851,7 +4881,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); - break; + goto fail; } PF_TABLE_STATS_LOCK(); @@ -4872,7 +4902,7 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; - break; + goto fail; } PF_RULES_RLOCK(); @@ -4880,7 +4910,7 @@ DIOCCHANGEADDR_error: if (n < 0) { PF_RULES_RUNLOCK(); error = EINVAL; - break; + goto fail; } io->pfrio_size = min(io->pfrio_size, n); @@ -4892,7 +4922,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_set_tflags(pfrts, io->pfrio_size, @@ -4908,7 +4938,7 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != 0) { error = ENODEV; - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, @@ -4924,13 +4954,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -4938,7 +4968,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_add_addrs(&io->pfrio_table, pfras, @@ -4958,13 +4988,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -4972,7 +5002,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_del_addrs(&io->pfrio_table, pfras, @@ -4992,17 +5022,17 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size2 < 0) { error = EINVAL; - break; + goto fail; } count = max(io->pfrio_size, io->pfrio_size2); if (count > pf_ioctl_maxcount || WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = count * sizeof(struct pfr_addr); pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP, @@ -5010,7 +5040,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_set_addrs(&io->pfrio_table, pfras, @@ -5031,13 +5061,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -5059,13 +5089,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_astats)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_astats); pfrastats = mallocarray(io->pfrio_size, @@ -5087,13 +5117,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -5101,7 +5131,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_clr_astats(&io->pfrio_table, pfras, @@ -5121,13 +5151,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -5135,7 +5165,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_RLOCK(); error = pfr_tst_addrs(&io->pfrio_table, pfras, @@ -5155,13 +5185,13 @@ DIOCCHANGEADDR_error: if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; - break; + goto fail; } if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) { error = EINVAL; - break; + goto fail; } totlen = io->pfrio_size * sizeof(struct pfr_addr); pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), @@ -5169,7 +5199,7 @@ DIOCCHANGEADDR_error: error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); error = pfr_ina_define(&io->pfrio_table, pfras, @@ -5204,13 +5234,13 @@ DIOCCHANGEADDR_error: if (io->esize != sizeof(*ioe)) { error = ENODEV; - break; + goto fail; } if (io->size < 0 || io->size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) { error = EINVAL; - break; + goto fail; } totlen = sizeof(struct pfioc_trans_e) * io->size; ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), @@ -5218,7 +5248,7 @@ DIOCCHANGEADDR_error: error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { @@ -5285,13 +5315,13 @@ DIOCCHANGEADDR_error: if (io->esize != sizeof(*ioe)) { error = ENODEV; - break; + goto fail; } if (io->size < 0 || io->size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) { error = EINVAL; - break; + goto fail; } totlen = sizeof(struct pfioc_trans_e) * io->size; ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), @@ -5299,7 +5329,7 @@ DIOCCHANGEADDR_error: error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { @@ -5368,14 +5398,14 @@ DIOCCHANGEADDR_error: if (io->esize != sizeof(*ioe)) { error = ENODEV; - break; + goto fail; } if (io->size < 0 || io->size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) { error = EINVAL; - break; + goto fail; } totlen = sizeof(struct pfioc_trans_e) * io->size; @@ -5384,7 +5414,7 @@ DIOCCHANGEADDR_error: error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - break; + goto fail; } PF_RULES_WLOCK(); /* First makes sure everything will succeed. */ @@ -5525,7 +5555,7 @@ DIOCCHANGEADDR_error: if (psn->psn_len == 0) { psn->psn_len = sizeof(struct pf_src_node) * nr; - break; + goto fail; } nr = 0; @@ -5550,7 +5580,7 @@ DIOCCHANGEADDR_error: sizeof(struct pf_src_node) * nr); if (error) { free(pstore, M_TEMP); - break; + goto fail; } psn->psn_len = sizeof(struct pf_src_node) * nr; free(pstore, M_TEMP); @@ -5606,14 +5636,14 @@ DIOCCHANGEADDR_error: if (io->pfiio_esize != sizeof(struct pfi_kif)) { error = ENODEV; - break; + goto fail; } if (io->pfiio_size < 0 || io->pfiio_size > pf_ioctl_maxcount || WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) { error = EINVAL; - break; + goto fail; } io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0'; @@ -6425,9 +6455,9 @@ shutdown_pf(void) for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) { if ((error = pf_begin_rules(&t[rs_num], rs_num, anchor->path)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: " - "anchor.path=%s rs_num=%d\n", - __func__, anchor->path, rs_num)); + DPFPRINTF(PF_DEBUG_MISC, "%s: " + "anchor.path=%s rs_num=%d", + __func__, anchor->path, rs_num); goto error; /* XXX: rollback? */ } } @@ -6449,9 +6479,9 @@ shutdown_pf(void) eth_anchor->refcnt = 1; if ((error = pf_begin_eth(&t[0], eth_anchor->path)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: eth " - "anchor.path=%s\n", __func__, - eth_anchor->path)); + DPFPRINTF(PF_DEBUG_MISC, "%s: eth " + "anchor.path=%s", __func__, + eth_anchor->path); goto error; } error = pf_commit_eth(t[0], eth_anchor->path); @@ -6460,27 +6490,27 @@ shutdown_pf(void) if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: SCRUB\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: SCRUB", __func__); break; } if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: FILTER\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: FILTER", __func__); break; /* XXX: rollback? */ } if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: NAT\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: NAT", __func__); break; /* XXX: rollback? */ } if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: BINAT\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: BINAT", __func__); break; /* XXX: rollback? */ } if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: RDR\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: RDR", __func__); break; /* XXX: rollback? */ } @@ -6499,7 +6529,7 @@ shutdown_pf(void) break; if ((error = pf_begin_eth(&t[0], &nn)) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: eth\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: eth", __func__); break; } error = pf_commit_eth(t[0], &nn); @@ -6507,7 +6537,7 @@ shutdown_pf(void) #ifdef ALTQ if ((error = pf_begin_altq(&t[0])) != 0) { - DPFPRINTF(PF_DEBUG_MISC, ("%s: ALTQ\n", __func__)); + DPFPRINTF(PF_DEBUG_MISC, "%s: ALTQ", __func__); break; } pf_commit_altq(t[0]); diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c index 26f7ab41eef4..ea0d6facf695 100644 --- a/sys/netpfil/pf/pf_lb.c +++ b/sys/netpfil/pf/pf_lb.c @@ -71,8 +71,6 @@ #define V_pf_rdr_srcport_rewrite_tries VNET(pf_rdr_srcport_rewrite_tries) VNET_DEFINE_STATIC(int, pf_rdr_srcport_rewrite_tries) = 16; -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - static uint64_t pf_hash(struct pf_addr *, struct pf_addr *, struct pf_poolhashkey *, sa_family_t); struct pf_krule *pf_match_translation(int, struct pf_test_ctx *); @@ -904,19 +902,19 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r, if (pf_get_mape_sport(pd, r, naddr, nportp, &ctx->udp_mapping, rpool)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: MAP-E port allocation (%u/%u/%u)" - " failed\n", + "pf: MAP-E port allocation (%u/%u/%u)" + " failed", rpool->mape.offset, rpool->mape.psidlen, - rpool->mape.psid)); + rpool->mape.psid); reason = PFRES_MAPFAILED; goto notrans; } } else if (pf_get_sport(pd, r, naddr, nportp, low, high, rpool, &ctx->udp_mapping, PF_SN_NAT)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: NAT proxy port allocation (%u-%u) failed\n", - rpool->proxy_port[0], rpool->proxy_port[1])); + "pf: NAT proxy port allocation (%u-%u) failed", + rpool->proxy_port[0], rpool->proxy_port[1]); reason = PFRES_MAPFAILED; goto notrans; } @@ -1012,10 +1010,13 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r, if (rpool->proxy_port[1]) { uint32_t tmp_nport; + uint16_t div; + + div = r->rdr.proxy_port[1] - r->rdr.proxy_port[0] + 1; + div = (div == 0) ? 1 : div; - tmp_nport = ((ntohs(pd->ndport) - ntohs(r->dst.port[0])) % - (rpool->proxy_port[1] - rpool->proxy_port[0] + - 1)) + rpool->proxy_port[0]; + tmp_nport = ((ntohs(pd->ndport) - ntohs(r->dst.port[0])) % div) + + rpool->proxy_port[0]; /* Wrap around if necessary. */ if (tmp_nport > 65535) @@ -1082,13 +1083,13 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r, * the state may be reused if the TCP state is terminal. */ DPFPRINTF(PF_DEBUG_MISC, - ("pf: RDR source port allocation failed\n")); + "pf: RDR source port allocation failed"); break; out: DPFPRINTF(PF_DEBUG_MISC, - ("pf: RDR source port allocation %u->%u\n", - ntohs(pd->nsport), ntohs(ctx->nk->port[0]))); + "pf: RDR source port allocation %u->%u", + ntohs(pd->nsport), ntohs(ctx->nk->port[0])); break; } default: @@ -1137,8 +1138,8 @@ pf_get_transaddr_af(struct pf_krule *r, struct pf_pdesc *pd) if (pf_get_sport(pd, r, &nsaddr, &nport, r->nat.proxy_port[0], r->nat.proxy_port[1], &r->nat, NULL, PF_SN_NAT)) { DPFPRINTF(PF_DEBUG_MISC, - ("pf: af-to NAT proxy port allocation (%u-%u) failed", - r->nat.proxy_port[0], r->nat.proxy_port[1])); + "pf: af-to NAT proxy port allocation (%u-%u) failed", + r->nat.proxy_port[0], r->nat.proxy_port[1]); return (-1); } diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 369292ca365e..8cea9557633c 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -160,13 +160,6 @@ static int pf_reassemble6(struct mbuf **, struct ip6_frag *, uint16_t, uint16_t, u_short *); #endif /* INET6 */ -#define DPFPRINTF(x) do { \ - if (V_pf_status.debug >= PF_DEBUG_MISC) { \ - printf("%s: ", __func__); \ - printf x ; \ - } \ -} while(0) - #ifdef INET static void pf_ip2key(struct ip *ip, struct pf_frnode *key) @@ -262,7 +255,8 @@ pf_purge_fragments(uint32_t expire) if (frag->fr_timeout > expire) break; - DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag)); + DPFPRINTF(PF_DEBUG_MISC, "expiring %d(%p)", + frag->fr_id, frag); pf_free_fragment(frag); } @@ -281,7 +275,7 @@ pf_flush_fragments(void) PF_FRAG_ASSERT(); goal = uma_zone_get_cur(V_pf_frent_z) * 9 / 10; - DPFPRINTF(("trying to free %d frag entriess\n", goal)); + DPFPRINTF(PF_DEBUG_MISC, "trying to free %d frag entriess", goal); while (goal < uma_zone_get_cur(V_pf_frent_z)) { frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue); if (frag) @@ -573,26 +567,30 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, /* No empty fragments. */ if (frent->fe_len == 0) { - DPFPRINTF(("bad fragment: len 0\n")); + DPFPRINTF(PF_DEBUG_MISC, "bad fragment: len 0"); goto bad_fragment; } /* All fragments are 8 byte aligned. */ if (frent->fe_mff && (frent->fe_len & 0x7)) { - DPFPRINTF(("bad fragment: mff and len %d\n", frent->fe_len)); + DPFPRINTF(PF_DEBUG_MISC, "bad fragment: mff and len %d", + frent->fe_len); goto bad_fragment; } /* Respect maximum length, IP_MAXPACKET == IPV6_MAXPACKET. */ if (frent->fe_off + frent->fe_len > IP_MAXPACKET) { - DPFPRINTF(("bad fragment: max packet %d\n", - frent->fe_off + frent->fe_len)); + DPFPRINTF(PF_DEBUG_MISC, "bad fragment: max packet %d", + frent->fe_off + frent->fe_len); goto bad_fragment; } - DPFPRINTF((key->fn_af == AF_INET ? - "reass frag %d @ %d-%d\n" : "reass frag %#08x @ %d-%d\n", - id, frent->fe_off, frent->fe_off + frent->fe_len)); + if (key->fn_af == AF_INET) + DPFPRINTF(PF_DEBUG_MISC, "reass frag %d @ %d-%d\n", + id, frent->fe_off, frent->fe_off + frent->fe_len); + else + DPFPRINTF(PF_DEBUG_MISC, "reass frag %#08x @ %d-%d", + id, frent->fe_off, frent->fe_off + frent->fe_len); /* Fully buffer all of the fragments in this fragment queue. */ frag = pf_find_fragment(key, id); @@ -690,10 +688,10 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, precut = prev->fe_off + prev->fe_len - frent->fe_off; if (precut >= frent->fe_len) { - DPFPRINTF(("new frag overlapped\n")); + DPFPRINTF(PF_DEBUG_MISC, "new frag overlapped"); goto drop_fragment; } - DPFPRINTF(("frag head overlap %d\n", precut)); + DPFPRINTF(PF_DEBUG_MISC, "frag head overlap %d", precut); m_adj(frent->fe_m, precut); frent->fe_off += precut; frent->fe_len -= precut; @@ -705,7 +703,8 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, aftercut = frent->fe_off + frent->fe_len - after->fe_off; if (aftercut < after->fe_len) { - DPFPRINTF(("frag tail overlap %d", aftercut)); + DPFPRINTF(PF_DEBUG_MISC, "frag tail overlap %d", + aftercut); m_adj(after->fe_m, aftercut); /* Fragment may switch queue as fe_off changes */ pf_frent_remove(frag, after); @@ -713,7 +712,8 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, after->fe_len -= aftercut; /* Insert into correct queue */ if (pf_frent_insert(frag, after, prev)) { - DPFPRINTF(("fragment requeue limit exceeded")); + DPFPRINTF(PF_DEBUG_MISC, + "fragment requeue limit exceeded"); m_freem(after->fe_m); uma_zfree(V_pf_frent_z, after); /* There is not way to recover */ @@ -723,7 +723,7 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, } /* This fragment is completely overlapped, lose it. */ - DPFPRINTF(("old frag overlapped\n")); + DPFPRINTF(PF_DEBUG_MISC, "old frag overlapped"); next = TAILQ_NEXT(after, fr_next); pf_frent_remove(frag, after); m_freem(after->fe_m); @@ -732,7 +732,7 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id, /* If part of the queue gets too long, there is not way to recover. */ if (pf_frent_insert(frag, frent, prev)) { - DPFPRINTF(("fragment queue limit exceeded\n")); + DPFPRINTF(PF_DEBUG_MISC, "fragment queue limit exceeded"); goto bad_fragment; } @@ -748,7 +748,7 @@ free_fragment: * fragment, the entire datagram (and any constituent fragments) MUST * be silently discarded. */ - DPFPRINTF(("flush overlapping fragments\n")); + DPFPRINTF(PF_DEBUG_MISC, "flush overlapping fragments"); pf_free_fragment(frag); bad_fragment: @@ -826,7 +826,8 @@ pf_reassemble(struct mbuf **m0, u_short *reason) m = *m0 = NULL; if (frag->fr_holes) { - DPFPRINTF(("frag %d, holes %d\n", frag->fr_id, frag->fr_holes)); + DPFPRINTF(PF_DEBUG_MISC, "frag %d, holes %d", + frag->fr_id, frag->fr_holes); return (PF_PASS); /* drop because *m0 is NULL, no error */ } @@ -872,14 +873,14 @@ pf_reassemble(struct mbuf **m0, u_short *reason) ip->ip_off &= ~(IP_MF|IP_OFFMASK); if (hdrlen + total > IP_MAXPACKET) { - DPFPRINTF(("drop: too big: %d\n", total)); + DPFPRINTF(PF_DEBUG_MISC, "drop: too big: %d", total); ip->ip_len = 0; REASON_SET(reason, PFRES_SHORT); /* PF_DROP requires a valid mbuf *m0 in pf_test() */ return (PF_DROP); } - DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip->ip_len))); + DPFPRINTF(PF_DEBUG_MISC, "complete: %p(%d)", m, ntohs(ip->ip_len)); return (PF_PASS); } #endif /* INET */ @@ -931,8 +932,8 @@ pf_reassemble6(struct mbuf **m0, struct ip6_frag *fraghdr, m = *m0 = NULL; if (frag->fr_holes) { - DPFPRINTF(("frag %d, holes %d\n", frag->fr_id, - frag->fr_holes)); + DPFPRINTF(PF_DEBUG_MISC, "frag %d, holes %d", frag->fr_id, + frag->fr_holes); PF_FRAG_UNLOCK(); return (PF_PASS); /* Drop because *m0 is NULL, no error. */ } @@ -993,14 +994,15 @@ pf_reassemble6(struct mbuf **m0, struct ip6_frag *fraghdr, ip6->ip6_nxt = proto; if (hdrlen - sizeof(struct ip6_hdr) + total > IPV6_MAXPACKET) { - DPFPRINTF(("drop: too big: %d\n", total)); + DPFPRINTF(PF_DEBUG_MISC, "drop: too big: %d", total); ip6->ip6_plen = 0; REASON_SET(reason, PFRES_SHORT); /* PF_DROP requires a valid mbuf *m0 in pf_test6(). */ return (PF_DROP); } - DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip6->ip6_plen))); + DPFPRINTF(PF_DEBUG_MISC, "complete: %p(%d)", m, + ntohs(ip6->ip6_plen)); return (PF_PASS); fail: @@ -1090,7 +1092,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag, action = PF_PASS; } else { /* Drop expects an mbuf to free. */ - DPFPRINTF(("refragment error %d\n", error)); + DPFPRINTF(PF_DEBUG_MISC, "refragment error %d", error); action = PF_DROP; } for (; m; m = t) { @@ -1230,7 +1232,7 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd) * no-df above, fine. Otherwise drop it. */ if (h->ip_off & htons(IP_DF)) { - DPFPRINTF(("IP_DF\n")); + DPFPRINTF(PF_DEBUG_MISC, "IP_DF"); goto bad; } @@ -1238,13 +1240,13 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd) /* All fragments are 8 byte aligned */ if (mff && (ip_len & 0x7)) { - DPFPRINTF(("mff and %d\n", ip_len)); + DPFPRINTF(PF_DEBUG_MISC, "mff and %d", ip_len); goto bad; } /* Respect maximum length */ if (fragoff + ip_len > IP_MAXPACKET) { - DPFPRINTF(("max packet %d\n", fragoff + ip_len)); + DPFPRINTF(PF_DEBUG_MISC, "max packet %d", fragoff + ip_len); goto bad; } @@ -1256,7 +1258,8 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd) /* Fully buffer all of the fragments * Might return a completely reassembled mbuf, or NULL */ PF_FRAG_LOCK(); - DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max)); + DPFPRINTF(PF_DEBUG_MISC, "reass frag %d @ %d-%d", + h->ip_id, fragoff, max); verdict = pf_reassemble(&pd->m, reason); PF_FRAG_UNLOCK(); @@ -1282,7 +1285,7 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd) return (PF_PASS); bad: - DPFPRINTF(("dropping bad fragment\n")); + DPFPRINTF(PF_DEBUG_MISC, "dropping bad fragment"); REASON_SET(reason, PFRES_FRAG); drop: if (r != NULL && r->log) @@ -1711,7 +1714,7 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, (uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE || time_uptime - (state->creation / 1000) > TS_MAX_CONN)) { if (V_pf_status.debug >= PF_DEBUG_MISC) { - DPFPRINTF(("src idled out of PAWS\n")); + DPFPRINTF(PF_DEBUG_MISC, "src idled out of PAWS"); pf_print_state(state); printf("\n"); } @@ -1721,7 +1724,7 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) && uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) { if (V_pf_status.debug >= PF_DEBUG_MISC) { - DPFPRINTF(("dst idled out of PAWS\n")); + DPFPRINTF(PF_DEBUG_MISC, "dst idled out of PAWS"); pf_print_state(state); printf("\n"); } @@ -1826,22 +1829,22 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, * an old timestamp. */ - DPFPRINTF(("Timestamp failed %c%c%c%c\n", + DPFPRINTF(PF_DEBUG_MISC, "Timestamp failed %c%c%c%c", SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ', SEQ_GT(tsval, src->scrub->pfss_tsval + tsval_from_last) ? '1' : ' ', SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ', - SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' ')); - DPFPRINTF((" tsval: %u tsecr: %u +ticks: %u " - "idle: %jus %lums\n", + SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '); + DPFPRINTF(PF_DEBUG_MISC, " tsval: %u tsecr: %u +ticks: " + "%u idle: %jus %lums", tsval, tsecr, tsval_from_last, (uintmax_t)delta_ts.tv_sec, - delta_ts.tv_usec / 1000)); - DPFPRINTF((" src->tsval: %u tsecr: %u\n", - src->scrub->pfss_tsval, src->scrub->pfss_tsecr)); - DPFPRINTF((" dst->tsval: %u tsecr: %u tsval0: %u" - "\n", dst->scrub->pfss_tsval, - dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0)); + delta_ts.tv_usec / 1000); + DPFPRINTF(PF_DEBUG_MISC, " src->tsval: %u tsecr: %u", + src->scrub->pfss_tsval, src->scrub->pfss_tsecr); + DPFPRINTF(PF_DEBUG_MISC, " dst->tsval: %u tsecr: %u " + "tsval0: %u", dst->scrub->pfss_tsval, + dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0); if (V_pf_status.debug >= PF_DEBUG_MISC) { pf_print_state(state); pf_print_flags(tcp_get_flags(th)); @@ -1891,8 +1894,8 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, * stack changed its RFC1323 behavior?!?! */ if (V_pf_status.debug >= PF_DEBUG_MISC) { - DPFPRINTF(("Did not receive expected RFC1323 " - "timestamp\n")); + DPFPRINTF(PF_DEBUG_MISC, "Did not receive expected " + "RFC1323 timestamp"); pf_print_state(state); pf_print_flags(tcp_get_flags(th)); printf("\n"); @@ -1919,9 +1922,9 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, if (V_pf_status.debug >= PF_DEBUG_MISC && dst->scrub && (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) { /* Don't warn if other host rejected RFC1323 */ - DPFPRINTF(("Broken RFC1323 stack did not " - "timestamp data packet. Disabled PAWS " - "security.\n")); + DPFPRINTF(PF_DEBUG_MISC, "Broken RFC1323 stack did " + "not timestamp data packet. Disabled PAWS " + "security."); pf_print_state(state); pf_print_flags(tcp_get_flags(th)); printf("\n"); diff --git a/sys/netpfil/pf/pf_osfp.c b/sys/netpfil/pf/pf_osfp.c index 3e00cc7c80a2..150626c5f3fb 100644 --- a/sys/netpfil/pf/pf_osfp.c +++ b/sys/netpfil/pf/pf_osfp.c @@ -40,9 +40,6 @@ #endif static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints"); -#define DPFPRINTF(format, x...) \ - if (V_pf_status.debug >= PF_DEBUG_NOISY) \ - printf(format , ##x) SLIST_HEAD(pf_osfp_list, pf_os_fingerprint); VNET_DEFINE_STATIC(struct pf_osfp_list, pf_osfp_list) = @@ -189,8 +186,8 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st optlen = MAX(optlen, 1); /* paranoia */ } - DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) " - "(TS=%s,M=%s%d,W=%s%d)\n", + DPFPRINTF(PF_DEBUG_NOISY, "fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) " + "(TS=%s,M=%s%d,W=%s%d)", srcname, ntohs(tcp->th_sport), fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0, fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt, @@ -219,7 +216,7 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os) if (os == PF_OSFP_ANY) return (1); if (list == NULL) { - DPFPRINTF("osfp no match against %x\n", os); + DPFPRINTF(PF_DEBUG_NOISY, "osfp no match against %x", os); return (os == PF_OSFP_UNKNOWN); } PF_OSFP_UNPACK(os, os_class, os_version, os_subtype); @@ -228,13 +225,13 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os) if ((os_class == PF_OSFP_ANY || en_class == os_class) && (os_version == PF_OSFP_ANY || en_version == os_version) && (os_subtype == PF_OSFP_ANY || en_subtype == os_subtype)) { - DPFPRINTF("osfp matched %s %s %s %x==%x\n", + DPFPRINTF(PF_DEBUG_NOISY, "osfp matched %s %s %s %x==%x", entry->fp_class_nm, entry->fp_version_nm, entry->fp_subtype_nm, os, entry->fp_os); return (1); } } - DPFPRINTF("fingerprint 0x%x didn't match\n", os); + DPFPRINTF(PF_DEBUG_NOISY, "fingerprint 0x%x didn't match", os); return (0); } @@ -275,8 +272,8 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc) fpadd.fp_ttl = fpioc->fp_ttl; #if 0 /* XXX RYAN wants to fix logging */ - DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d " - "(TS=%s,M=%s%d,W=%s%d) %x\n", + DPFPRINTF(PF_DEBUG_NOISY, "adding osfp %s %s %s =" + " %s%d:%d:%d:%s%d:0x%llx %d (TS=%s,M=%s%d,W=%s%d) %x", fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm, fpioc->fp_os.fp_subtype_nm, (fpadd.fp_flags & PF_OSFP_WSIZE_MOD) ? "%" : diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c index 2e5165a9900c..43b51f2933f4 100644 --- a/sys/netpfil/pf/pf_ruleset.c +++ b/sys/netpfil/pf/pf_ruleset.c @@ -59,9 +59,6 @@ #error "Kernel only file. Please use sbin/pfctl/pf_ruleset.c instead." #endif -#define DPFPRINTF(format, x...) \ - if (V_pf_status.debug >= PF_DEBUG_NOISY) \ - printf(format , ##x) #define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT|M_ZERO) #define rs_free(x) free(x, M_TEMP) @@ -386,7 +383,8 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, strlcpy(path, s->anchor->path, MAXPATHLEN); while (name[0] == '.' && name[1] == '.' && name[2] == '/') { if (!path[0]) { - DPFPRINTF("%s: .. beyond root\n", __func__); + DPFPRINTF(PF_DEBUG_NOISY, "%s: .. beyond root", + __func__); rs_free(path); return (1); } @@ -408,7 +406,7 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, ruleset = pf_find_or_create_kruleset(path); rs_free(path); if (ruleset == NULL || ruleset == &pf_main_ruleset) { - DPFPRINTF("%s: ruleset\n", __func__); + DPFPRINTF(PF_DEBUG_NOISY, "%s: ruleset", __func__); return (1); } r->anchor = ruleset->anchor; @@ -690,7 +688,8 @@ pf_keth_anchor_setup(struct pf_keth_rule *r, const struct pf_keth_ruleset *s, strlcpy(path, s->anchor->path, MAXPATHLEN); while (name[0] == '.' && name[1] == '.' && name[2] == '/') { if (!path[0]) { - DPFPRINTF("%s: .. beyond root\n", __func__); + DPFPRINTF(PF_DEBUG_NOISY, "%s: .. beyond root", + __func__); rs_free(path); return (1); } @@ -712,7 +711,7 @@ pf_keth_anchor_setup(struct pf_keth_rule *r, const struct pf_keth_ruleset *s, ruleset = pf_find_or_create_keth_ruleset(path); rs_free(path); if (ruleset == NULL || ruleset->anchor == NULL) { - DPFPRINTF("%s: ruleset\n", __func__); + DPFPRINTF(PF_DEBUG_NOISY, "%s: ruleset", __func__); return (1); } r->anchor = ruleset->anchor; diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c index 66757fa4b756..4a935bc65767 100644 --- a/sys/netpfil/pf/pf_syncookies.c +++ b/sys/netpfil/pf/pf_syncookies.c @@ -88,8 +88,6 @@ #include <net/pfvar.h> #include <netpfil/pf/pf_nv.h> -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - union pf_syncookie { uint8_t cookie; struct { @@ -281,7 +279,7 @@ pf_synflood_check(struct pf_pdesc *pd) pf_syncookie_rotate, curvnet); V_pf_status.syncookies_active = true; DPFPRINTF(LOG_WARNING, - ("synflood detected, enabling syncookies\n")); + "synflood detected, enabling syncookies"); // XXXTODO V_pf_status.lcounters[LCNT_SYNFLOODS]++; } @@ -367,7 +365,7 @@ pf_syncookie_rotate(void *arg) V_pf_status.syncookies_mode == PF_SYNCOOKIES_NEVER) ) { V_pf_status.syncookies_active = false; - DPFPRINTF(PF_DEBUG_MISC, ("syncookies disabled\n")); + DPFPRINTF(PF_DEBUG_MISC, "syncookies disabled"); } /* nothing in flight any more? delete keys and return */ diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index e3f3ab9025f7..ecc185f89ad7 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -49,8 +49,6 @@ #include <net/vnet.h> #include <net/pfvar.h> -#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x - #define ACCEPT_FLAGS(flags, oklist) \ do { \ if ((flags & ~(oklist)) & \ @@ -819,10 +817,10 @@ pfr_create_kentry(struct pfr_addr *ad, bool counters) static void pfr_destroy_kentries(struct pfr_kentryworkq *workq) { - struct pfr_kentry *p, *q; + struct pfr_kentry *p; - for (p = SLIST_FIRST(workq); p != NULL; p = q) { - q = SLIST_NEXT(p, pfrke_workq); + while ((p = SLIST_FIRST(workq)) != NULL) { + SLIST_REMOVE_HEAD(workq, pfrke_workq); pfr_destroy_kentry(p); } } @@ -1680,8 +1678,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, } if (!(flags & PFR_FLAG_DUMMY)) { - for (p = SLIST_FIRST(&workq); p != NULL; p = q) { - q = SLIST_NEXT(p, pfrkt_workq); + SLIST_FOREACH_SAFE(p, &workq, pfrkt_workq, q) { pfr_commit_ktable(p, tzero); } rs->topen = 0; @@ -1710,7 +1707,7 @@ pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero) } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) { /* kt might contain addresses */ struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq; - struct pfr_kentry *p, *q, *next; + struct pfr_kentry *p, *q; struct pfr_addr ad; pfr_enqueue_addrs(shadow, &addrq, NULL, 0); @@ -1720,7 +1717,8 @@ pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero) SLIST_INIT(&delq); SLIST_INIT(&garbageq); pfr_clean_node_mask(shadow, &addrq); - SLIST_FOREACH_SAFE(p, &addrq, pfrke_workq, next) { + while ((p = SLIST_FIRST(&addrq)) != NULL) { + SLIST_REMOVE_HEAD(&addrq, pfrke_workq); pfr_copyout_addr(&ad, p); q = pfr_lookup_addr(kt, &ad, 1); if (q != NULL) { @@ -1864,8 +1862,7 @@ pfr_setflags_ktables(struct pfr_ktableworkq *workq) { struct pfr_ktable *p, *q; - for (p = SLIST_FIRST(workq); p; p = q) { - q = SLIST_NEXT(p, pfrkt_workq); + SLIST_FOREACH_SAFE(p, workq, pfrkt_workq, q) { pfr_setflags_ktable(p, p->pfrkt_nflags); } } @@ -2015,10 +2012,10 @@ pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset) static void pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr) { - struct pfr_ktable *p, *q; + struct pfr_ktable *p; - for (p = SLIST_FIRST(workq); p; p = q) { - q = SLIST_NEXT(p, pfrkt_workq); + while ((p = SLIST_FIRST(workq)) != NULL) { + SLIST_REMOVE_HEAD(workq, pfrkt_workq); pfr_destroy_ktable(p, flushaddr); } } @@ -2190,7 +2187,7 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, if ((ke == NULL || ke->pfrke_not) != notrule) { if (op_pass != PFR_OP_PASS) DPFPRINTF(PF_DEBUG_URGENT, - ("pfr_update_stats: assertion failed.\n")); + "pfr_update_stats: assertion failed."); op_pass = PFR_OP_XPASS; } pfr_kstate_counter_add(&kt->pfrkt_packets[dir_out][op_pass], 1); diff --git a/sys/riscv/allwinner/files.allwinner b/sys/riscv/allwinner/files.allwinner index 73fa9660e2d2..7a4ff6b9c62e 100644 --- a/sys/riscv/allwinner/files.allwinner +++ b/sys/riscv/allwinner/files.allwinner @@ -1,5 +1,6 @@ arm/allwinner/aw_gpio.c optional gpio aw_gpio fdt +arm/allwinner/aw_mmc.c optional mmc aw_mmc fdt | mmccam aw_mmc fdt arm/allwinner/aw_rtc.c optional aw_rtc fdt arm/allwinner/aw_syscon.c optional syscon arm/allwinner/aw_sid.c optional aw_sid nvmem diff --git a/sys/riscv/conf/std.allwinner b/sys/riscv/conf/std.allwinner index 2b1e0d4e09dc..34fe195b01ba 100644 --- a/sys/riscv/conf/std.allwinner +++ b/sys/riscv/conf/std.allwinner @@ -7,6 +7,7 @@ options SOC_ALLWINNER_D1 device aw_ccu # Allwinner clock controller device aw_gpio # Allwinner GPIO controller +device aw_mmc # Allwinner SD/MMC controller device aw_rtc # Allwinner Real-time Clock device aw_sid # Allwinner Secure ID EFUSE device aw_timer # Allwinner Timer diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c index 9e87af578885..44b63e38a8e6 100644 --- a/sys/rpc/clnt_rc.c +++ b/sys/rpc/clnt_rc.c @@ -198,6 +198,12 @@ clnt_reconnect_connect(CLIENT *cl) newclient = clnt_vc_create(so, (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers, rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr); + /* + * CLSET_FD_CLOSE must be done now, in case rpctls_connect() + * fails just below. + */ + if (newclient != NULL) + CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0); if (rc->rc_tls && newclient != NULL) { CURVNET_SET(so->so_vnet); stat = rpctls_connect(newclient, rc->rc_tlscertname, so, @@ -236,7 +242,6 @@ clnt_reconnect_connect(CLIENT *cl) goto out; } - CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0); CLNT_CONTROL(newclient, CLSET_CONNECT, &one); CLNT_CONTROL(newclient, CLSET_TIMEOUT, &rc->rc_timeout); CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry); diff --git a/sys/rpc/rpcsec_gss/rpcsec_gss.c b/sys/rpc/rpcsec_gss/rpcsec_gss.c index 62c71937a185..983dd251f81f 100644 --- a/sys/rpc/rpcsec_gss/rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/rpcsec_gss.c @@ -67,6 +67,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/hash.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/kobj.h> #include <sys/lock.h> @@ -772,6 +773,17 @@ rpc_gss_init(AUTH *auth, rpc_gss_options_ret_t *options_ret) gd->gd_cred.gc_seq = 0; /* + * XXX Threads from inside jails can get here via calls + * to clnt_vc_call()->AUTH_REFRESH()->rpc_gss_refresh() + * but the NFS mount is always done outside of the + * jails in vnet0. Since the thread credentials won't + * necessarily have cr_prison == vnet0 and this function + * has no access to the socket, using vnet0 seems the + * only option. This is broken if NFS mounts are enabled + * within vnet prisons. + */ + KGSS_CURVNET_SET_QUIET(vnet0); + /* * For KerberosV, if there is a client principal name, that implies * that this is a host based initiator credential in the default * keytab file. For this case, it is necessary to do a @@ -994,12 +1006,14 @@ out: gss_delete_sec_context(&min_stat, &gd->gd_ctx, GSS_C_NO_BUFFER); } + KGSS_CURVNET_RESTORE(); mtx_lock(&gd->gd_lock); gd->gd_state = RPCSEC_GSS_START; wakeup(gd); mtx_unlock(&gd->gd_lock); return (FALSE); } + KGSS_CURVNET_RESTORE(); mtx_lock(&gd->gd_lock); gd->gd_state = RPCSEC_GSS_ESTABLISHED; diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c b/sys/rpc/rpcsec_tls/rpctls_impl.c index 93fe283e65fd..51fe270b13d9 100644 --- a/sys/rpc/rpcsec_tls/rpctls_impl.c +++ b/sys/rpc/rpcsec_tls/rpctls_impl.c @@ -240,6 +240,14 @@ rpctls_rpc_failed(struct upsock *ups, struct socket *so) * failed to do the handshake. */ mtx_unlock(&rpctls_lock); + /* + * Do a shutdown on the socket, since the daemon is + * probably stuck in SSL_accept() or SSL_connect() trying to + * read the socket. Do not soclose() the socket, since the + * daemon will close() the socket after SSL_accept() + * returns an error. + */ + soshutdown(so, SHUT_RD); } } diff --git a/sys/sys/efi.h b/sys/sys/efi.h index 95a433a950db..89c8b15519de 100644 --- a/sys/sys/efi.h +++ b/sys/sys/efi.h @@ -42,6 +42,8 @@ {0xb122a263,0x3661,0x4f68,{0x99,0x29,0x78,0xf8,0xb0,0xd6,0x21,0x80}} #define EFI_PROPERTIES_TABLE \ {0x880aaca3,0x4adc,0x4a04,{0x90,0x79,0xb7,0x47,0x34,0x08,0x25,0xe5}} +#define EFI_MEMORY_ATTRIBUTES_TABLE \ + {0xdcfa911d,0x26eb,0x469f,{0xa2,0x20,0x38,0xb7,0xdc,0x46,0x12,0x20}} #define LINUX_EFI_MEMRESERVE_TABLE \ {0x888eb0c6,0x8ede,0x4ff5,{0xa8,0xf0,0x9a,0xee,0x5c,0xb9,0x77,0xc2}} @@ -166,6 +168,22 @@ struct efi_prop_table { uint64_t memory_protection_attribute; }; +struct efi_memory_descriptor { + uint32_t type; + caddr_t phy_addr; + caddr_t virt_addr; + uint64_t pages; + uint64_t attrs; +}; + +struct efi_memory_attribute_table { + uint32_t version; + uint32_t num_ents; + uint32_t descriptor_size; + uint32_t flags; + struct efi_memory_descriptor tables[]; +}; + #ifdef _KERNEL #ifdef EFIABI_ATTR diff --git a/sys/sys/exterrvar.h b/sys/sys/exterrvar.h index 15557c614f88..7bf1d264ff5e 100644 --- a/sys/sys/exterrvar.h +++ b/sys/sys/exterrvar.h @@ -21,6 +21,7 @@ #define EXTERRCTL_ENABLE 1 #define EXTERRCTL_DISABLE 2 +#define EXTERRCTL_UD 3 #define EXTERRCTLF_FORCE 0x00000001 diff --git a/sys/sys/inotify.h b/sys/sys/inotify.h index 65dc5dba43f3..d1f23d5898bb 100644 --- a/sys/sys/inotify.h +++ b/sys/sys/inotify.h @@ -107,11 +107,18 @@ void vn_inotify_revoke(struct vnode *); } while (0) /* Log an inotify event using a specific name for the vnode. */ -#define INOTIFY_NAME(vp, dvp, cnp, ev) do { \ +#define INOTIFY_NAME_LOCK(vp, dvp, cnp, ev, lock) do { \ if (__predict_false((vn_irflag_read(vp) & VIRF_INOTIFY) != 0 || \ - (vn_irflag_read(dvp) & VIRF_INOTIFY) != 0)) \ + (vn_irflag_read(dvp) & VIRF_INOTIFY) != 0)) { \ + if (lock) \ + vn_lock((vp), LK_SHARED | LK_RETRY); \ VOP_INOTIFY((vp), (dvp), (cnp), (ev), 0); \ + if (lock) \ + VOP_UNLOCK(vp); \ + } \ } while (0) +#define INOTIFY_NAME(vp, dvp, cnp, ev) \ + INOTIFY_NAME_LOCK((vp), (dvp), (cnp), (ev), false) extern __uint32_t inotify_rename_cookie; @@ -126,7 +133,8 @@ extern __uint32_t inotify_rename_cookie; VOP_INOTIFY((vp), (tdvp), (tcnp), IN_MOVED_TO, cookie); \ } \ if ((tvp) != NULL) \ - INOTIFY_NAME((tvp), (tdvp), (tcnp), _IN_MOVE_DELETE); \ + INOTIFY_NAME_LOCK((tvp), (tdvp), (tcnp), \ + _IN_MOVE_DELETE, true); \ } while (0) #define INOTIFY_REVOKE(vp) do { \ diff --git a/sys/sys/param.h b/sys/sys/param.h index af116d6e3f7a..f941f021a423 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -74,7 +74,7 @@ * cannot include sys/param.h and should only be updated here. */ #undef __FreeBSD_version -#define __FreeBSD_version 1500051 +#define __FreeBSD_version 1500054 /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/random.h b/sys/sys/random.h index 254ba9451d0a..5abf762cd200 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -85,7 +85,8 @@ enum random_entropy_source { RANDOM_FS_ATIME, RANDOM_UMA, /* Special!! UMA/SLAB Allocator */ RANDOM_CALLOUT, - RANDOM_ENVIRONMENTAL_END = RANDOM_CALLOUT, + RANDOM_RANDOMDEV, + RANDOM_ENVIRONMENTAL_END = RANDOM_RANDOMDEV, /* Fast hardware random-number sources from here on. */ RANDOM_PURE_START, RANDOM_PURE_OCTEON = RANDOM_PURE_START, diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 2c6947103c94..a416fddcddc3 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -939,7 +939,6 @@ void vop_mknod_post(void *a, int rc); void vop_open_post(void *a, int rc); void vop_read_post(void *a, int rc); void vop_read_pgcache_post(void *ap, int rc); -void vop_readdir_post(void *a, int rc); void vop_reclaim_post(void *a, int rc); void vop_remove_pre(void *a); void vop_remove_post(void *a, int rc); @@ -1015,7 +1014,36 @@ void vop_rename_fail(struct vop_rename_args *ap); _error; \ }) -#define VOP_WRITE_PRE(ap) \ +#ifdef INVARIANTS +#define vop_readdir_pre_assert(ap) \ + ssize_t nresid, oresid; \ + \ + oresid = (ap)->a_uio->uio_resid; + +#define vop_readdir_post_assert(ap, ret) \ + nresid = (ap)->a_uio->uio_resid; \ + if ((ret) == 0 && (ap)->a_eofflag != NULL) { \ + VNASSERT(oresid == 0 || nresid != oresid || \ + *(ap)->a_eofflag == 1, \ + (ap)->a_vp, ("VOP_READDIR: eofflag not set")); \ + } +#else +#define vop_readdir_pre_assert(ap) +#define vop_readdir_post_assert(ap, ret) +#endif + +#define vop_readdir_pre(ap) do { \ + vop_readdir_pre_assert(ap) + +#define vop_readdir_post(ap, ret) \ + vop_readdir_post_assert(ap, ret); \ + if ((ret) == 0) { \ + VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_READ); \ + INOTIFY((ap)->a_vp, IN_ACCESS); \ + } \ +} while (0) + +#define vop_write_pre(ap) \ struct vattr va; \ int error; \ off_t osize, ooffset, noffset; \ @@ -1029,7 +1057,7 @@ void vop_rename_fail(struct vop_rename_args *ap); osize = (off_t)va.va_size; \ } -#define VOP_WRITE_POST(ap, ret) \ +#define vop_write_post(ap, ret) \ noffset = (ap)->a_uio->uio_offset; \ if (noffset > ooffset) { \ if (!VN_KNLIST_EMPTY((ap)->a_vp)) { \ diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 86b75a2d7989..d6bd06226d04 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -384,8 +384,8 @@ swap_release_by_cred(vm_ooffset_t decr, struct ucred *cred) #endif } -static int swap_pager_full = 2; /* swap space exhaustion (task killing) */ -static int swap_pager_almost_full = 1; /* swap space exhaustion (w/hysteresis)*/ +static bool swap_pager_full = true; /* swap space exhaustion (task killing) */ +static bool swap_pager_almost_full = true; /* swap space exhaustion (w/hysteresis) */ static struct mtx swbuf_mtx; /* to sync nsw_wcount_async */ static int nsw_wcount_async; /* limit async write buffers */ static int nsw_wcount_async_max;/* assigned maximum */ @@ -642,14 +642,14 @@ swp_sizecheck(void) { if (swap_pager_avail < nswap_lowat) { - if (swap_pager_almost_full == 0) { + if (!swap_pager_almost_full) { printf("swap_pager: out of swap space\n"); - swap_pager_almost_full = 1; + swap_pager_almost_full = true; } } else { - swap_pager_full = 0; + swap_pager_full = false; if (swap_pager_avail > nswap_hiwat) - swap_pager_almost_full = 0; + swap_pager_almost_full = false; } } @@ -958,11 +958,10 @@ swp_pager_getswapspace(int *io_npages) swp_sizecheck(); swdevhd = TAILQ_NEXT(sp, sw_list); } else { - if (swap_pager_full != 2) { + if (!swap_pager_full) { printf("swp_pager_getswapspace(%d): failed\n", *io_npages); - swap_pager_full = 2; - swap_pager_almost_full = 1; + swap_pager_full = swap_pager_almost_full = true; } swdevhd = NULL; } @@ -2863,10 +2862,8 @@ swapoff_one(struct swdevt *sp, struct ucred *cred, u_int flags) sp->sw_id = NULL; TAILQ_REMOVE(&swtailq, sp, sw_list); nswapdev--; - if (nswapdev == 0) { - swap_pager_full = 2; - swap_pager_almost_full = 1; - } + if (nswapdev == 0) + swap_pager_full = swap_pager_almost_full = true; if (swdevhd == sp) swdevhd = NULL; mtx_unlock(&sw_dev_mtx); diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 875c22d27628..e7d7b6726d2c 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -110,11 +110,18 @@ u_int exec_map_entry_size; u_int exec_map_entries; SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, - SYSCTL_NULL_ULONG_PTR, VM_MIN_KERNEL_ADDRESS, "Min kernel address"); +#if defined(__amd64__) + &kva_layout.km_low, 0, +#else + SYSCTL_NULL_ULONG_PTR, VM_MIN_KERNEL_ADDRESS, +#endif + "Min kernel address"); SYSCTL_ULONG(_vm, OID_AUTO, max_kernel_address, CTLFLAG_RD, #if defined(__arm__) &vm_max_kernel_address, 0, +#elif defined(__amd64__) + &kva_layout.km_high, 0, #else SYSCTL_NULL_ULONG_PTR, VM_MAX_KERNEL_ADDRESS, #endif diff --git a/sys/vm/vm_pagequeue.h b/sys/vm/vm_pagequeue.h index cbbd27389662..9bd3b389fb60 100644 --- a/sys/vm/vm_pagequeue.h +++ b/sys/vm/vm_pagequeue.h @@ -260,9 +260,9 @@ struct vm_domain { u_int vmd_inactive_shortage; /* Per-thread shortage. */ blockcount_t vmd_inactive_running; /* Number of inactive threads. */ blockcount_t vmd_inactive_starting; /* Number of threads started. */ - volatile u_int vmd_addl_shortage; /* Shortage accumulator. */ - volatile u_int vmd_inactive_freed; /* Successful inactive frees. */ - volatile u_int vmd_inactive_us; /* Microseconds for above. */ + u_int vmd_addl_shortage; /* (a) Shortage accumulator. */ + u_int vmd_inactive_freed; /* (a) Successful inactive frees. */ + u_int vmd_inactive_us; /* (a) Microseconds for above. */ u_int vmd_inactive_pps; /* Exponential decay frees/second. */ int vmd_oom_seq; int vmd_last_active_scan; diff --git a/tests/ci/Makefile b/tests/ci/Makefile index 44b19663fc49..b8797e06ac75 100644 --- a/tests/ci/Makefile +++ b/tests/ci/Makefile @@ -33,11 +33,11 @@ EXTRA_MAKE_FLAGS?= TARGET= ${MACHINE} .endif .if !defined(TARGET_ARCH) || empty(TARGET_ARCH) -.if ${TARGET} == ${MACHINE} +. if ${TARGET} == ${MACHINE} TARGET_ARCH= ${MACHINE_ARCH} -.else +. else TARGET_ARCH= ${TARGET} -.endif +. endif .endif IMAKE= ${MAKE} TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} @@ -47,20 +47,20 @@ CROSS_TOOLCHAIN_PARAM= "CROSS_TOOLCHAIN=${CROSS_TOOLCHAIN}" # Define OSRELEASE by using newvers.sh .if !defined(OSRELEASE) || empty(OSRELEASE) -.for _V in TYPE BRANCH REVISION -. if !defined(${_V}) || empty(${_V}) +. for _V in TYPE BRANCH REVISION +. if !defined(${_V}) || empty(${_V}) ${_V}!= eval $$(awk '/^${_V}=/{print}' ${.CURDIR}/../../sys/conf/newvers.sh); echo $$${_V} -. endif -.endfor -.for _V in ${TARGET_ARCH} -.if !empty(TARGET:M${_V}) +. endif +. endfor +. for _V in ${TARGET_ARCH} +. if !empty(TARGET:M${_V}) OSRELEASE= ${TYPE}-${REVISION}-${BRANCH}-${TARGET} VOLUME_LABEL= ${REVISION:C/[.-]/_/g}_${BRANCH:C/[.-]/_/g}_${TARGET} -.else +. else OSRELEASE= ${TYPE}-${REVISION}-${BRANCH}-${TARGET}-${TARGET_ARCH} VOLUME_LABEL= ${REVISION:C/[.-]/_/g}_${BRANCH:C/[.-]/_/g}_${TARGET_ARCH} -.endif -.endfor +. endif +. endfor .endif .if exists(${.CURDIR}/tools/ci.conf) && !defined(CICONF) @@ -104,13 +104,13 @@ TIMEOUT_VM=$$((${TIMEOUT_EXPECT} - 120)) . include "${.CURDIR}/Makefile.${TARGET_ARCH}" .endif .if ${TARGET_ARCH} != ${MACHINE_ARCH} -.if ( ${TARGET_ARCH} != "i386" ) || ( ${MACHINE_ARCH} != "amd64" ) +. if ( ${TARGET_ARCH} != "i386" ) || ( ${MACHINE_ARCH} != "amd64" ) QEMUSTATIC=/usr/local/bin/qemu-${QEMU_ARCH}-static QEMUTGT=portinstall-qemu -.endif +. endif .endif QEMUTGT?= -QEMU_DEVICES?=-device virtio-blk,drive=hd0 +QEMU_DEVICES?=-device virtio-blk,drive=hd0 -device virtio-blk,drive=hd1 QEMU_EXTRA_PARAM?= QEMU_MACHINE?=virt QEMUBIN=/usr/local/bin/qemu-system-${QEMU_ARCH} diff --git a/tests/ci/tools/freebsdci b/tests/ci/tools/freebsdci index 7b4ce9669ab2..51bd19e2967d 100755 --- a/tests/ci/tools/freebsdci +++ b/tests/ci/tools/freebsdci @@ -25,9 +25,6 @@ . /etc/rc.subr -: ${freebsdci_enable:="NO"} -: ${freebsdci_type:="full"} - name="freebsdci" desc="Run FreeBSD CI" rcvar=freebsdci_enable @@ -39,6 +36,11 @@ tardev=/dev/vtbd1 metadir=/meta istar=$(file -s ${tardev} | grep "POSIX tar archive" | wc -l) +load_rc_config $name +: ${freebsdci_enable:="NO"} +: ${freebsdci_type:="full"} +PATH="${PATH}:/usr/local/sbin:/usr/local/bin" + auto_shutdown() { # NOTE: Currently RISC-V kernels lack the ability to @@ -105,5 +107,4 @@ firstboot_ci_run() auto_shutdown } -load_rc_config $name run_rc_command "$1" diff --git a/tests/sys/cam/ctl/ctl.subr b/tests/sys/cam/ctl/ctl.subr index 5da441b806f0..6cc02d774bdb 100644 --- a/tests/sys/cam/ctl/ctl.subr +++ b/tests/sys/cam/ctl/ctl.subr @@ -25,15 +25,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -load_modules() { - if ! kldstat -q -m ctl; then - kldload ctl || atf_skip "could not load ctl kernel mod" - fi - if ! ctladm port -o on -p 0; then - atf_skip "could not enable the camsim frontend" - fi -} - find_device() { LUN=$1 diff --git a/tests/sys/fs/fusefs/Makefile b/tests/sys/fs/fusefs/Makefile index b11f11bdfa98..a21512798597 100644 --- a/tests/sys/fs/fusefs/Makefile +++ b/tests/sys/fs/fusefs/Makefile @@ -70,7 +70,8 @@ TEST_METADATA.nfs+= required_user="root" TEST_METADATA.ctl+= is_exclusive="true" TEST_METADATA.ctl+= required_user="root" -TEST_METADATA+= timeout=10 +TEST_METADATA+= timeout=10 +TEST_METADATA+= required_kmods="fusefs" FUSEFS= ${SRCTOP}/sys/fs/fuse # Suppress warnings that GCC generates for the libc++ and gtest headers. diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index f2c24ad9dec9..336e73f29835 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -17,6 +17,7 @@ ATF_TESTS_C+= kern_copyin ATF_TESTS_C+= kern_descrip_test # One test modifies the maxfiles limit, which can cause spurious test failures. TEST_METADATA.kern_descrip_test+= is_exclusive="true" +ATF_TESTS_C+= exterr_test ATF_TESTS_C+= fdgrowtable_test ATF_TESTS_C+= getdirentries_test ATF_TESTS_C+= jail_lookup_root diff --git a/tests/sys/kern/exterr_test.c b/tests/sys/kern/exterr_test.c new file mode 100644 index 000000000000..17c84c1f8ed4 --- /dev/null +++ b/tests/sys/kern/exterr_test.c @@ -0,0 +1,108 @@ +/*- + * Copyright (C) 2025 ConnectWise, LLC. 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 <sys/exterrvar.h> +#include <sys/mman.h> + +#include <atf-c.h> +#include <errno.h> +#include <exterr.h> +#include <stdio.h> + +ATF_TC(gettext_extended); +ATF_TC_HEAD(gettext_extended, tc) +{ + atf_tc_set_md_var(tc, "descr", "Retrieve an extended error message"); +} +ATF_TC_BODY(gettext_extended, tc) +{ + char exterr[UEXTERROR_MAXLEN]; + int r; + + /* + * Use an invalid call to mmap() because it supports extended error + * messages, requires no special resources, and does not need root. + */ + ATF_CHECK_ERRNO(ENOTSUP, + mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0)); + r = uexterr_gettext(exterr, sizeof(exterr)); + ATF_CHECK_EQ(0, r); + printf("Extended error: %s\n", exterr); + /* Note: error string may need to be updated due to kernel changes */ + ATF_CHECK(strstr(exterr, "prot is not subset of max_prot") != 0); +} + +ATF_TC(gettext_noextended); +ATF_TC_HEAD(gettext_noextended, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Fail to retrieve an extended error message because none exists"); +} +ATF_TC_BODY(gettext_noextended, tc) +{ + char exterr[UEXTERROR_MAXLEN]; + int r; + + ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL)); + r = uexterr_gettext(exterr, sizeof(exterr)); + ATF_CHECK_EQ(0, r); + ATF_CHECK_STREQ(exterr, ""); +} + +ATF_TC(gettext_noextended_after_extended); +ATF_TC_HEAD(gettext_noextended_after_extended, tc) +{ + atf_tc_set_md_var(tc, "descr", + "uexterr_gettext should not return a stale extended error message"); +} +ATF_TC_BODY(gettext_noextended_after_extended, tc) +{ + char exterr[UEXTERROR_MAXLEN]; + int r; + + /* + * First do something that will create an extended error message, but + * ignore it. + */ + ATF_CHECK_ERRNO(ENOTSUP, + mmap(NULL, 0, PROT_MAX(PROT_READ) | PROT_WRITE, 0, -1, 0)); + + /* Then do something that won't create an extended error message */ + ATF_CHECK_ERRNO(EINVAL, exterrctl(EXTERRCTL_UD, 0, NULL)); + + /* Hopefully we won't see the stale extended error message */ + r = uexterr_gettext(exterr, sizeof(exterr)); + ATF_CHECK_EQ(0, r); + ATF_CHECK_STREQ(exterr, ""); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, gettext_extended); + ATF_TP_ADD_TC(tp, gettext_noextended); + ATF_TP_ADD_TC(tp, gettext_noextended_after_extended); + + return (atf_no_error()); +} diff --git a/tests/sys/mac/bsdextended/Makefile b/tests/sys/mac/bsdextended/Makefile index 69cd27c0e321..cc3a3f8ea534 100644 --- a/tests/sys/mac/bsdextended/Makefile +++ b/tests/sys/mac/bsdextended/Makefile @@ -9,5 +9,6 @@ TEST_METADATA.ugidfw_test+= required_user="root" # Each test case of matches_test reuses the same ruleset number, so they cannot # be run simultaneously TEST_METADATA.matches_test+= is_exclusive=true +TEST_METADATA+= required_kmods="mac_bsdextended" .include <bsd.test.mk> diff --git a/tests/sys/mac/bsdextended/matches_test.sh b/tests/sys/mac/bsdextended/matches_test.sh index 2a28be0f231b..41fa04f221e3 100644 --- a/tests/sys/mac/bsdextended/matches_test.sh +++ b/tests/sys/mac/bsdextended/matches_test.sh @@ -12,9 +12,6 @@ gidoutrange="daemon" # We expect $uidinrange in this group check_ko() { - if ! sysctl -N security.mac.bsdextended >/dev/null 2>&1; then - atf_skip "mac_bsdextended(4) support isn't available" - fi if [ $(sysctl -n security.mac.bsdextended.enabled) = "0" ]; then # The kernel module is loaded but disabled. Enable it for the # duration of the test. diff --git a/tests/sys/netinet6/addr6.sh b/tests/sys/netinet6/addr6.sh index 38e4bb152240..6fd66d5aa0c7 100755 --- a/tests/sys/netinet6/addr6.sh +++ b/tests/sys/netinet6/addr6.sh @@ -39,7 +39,32 @@ addr6_invalid_addr_cleanup() vnet_cleanup } +atf_test_case "anycast_raw_addr" "cleanup" +anycast_raw_addr_head() +{ + atf_set descr "a raw socket can bind to an anycast address" + atf_set require.user root +} + +anycast_raw_addr_body() +{ + # lo0 needs to be up in the test jail for this test to work + ifconfig lo0 up + + netif=$(ifconfig lo create) + echo $netif >netif + atf_check -s exit:0 ifconfig $netif inet6 2001:db8::1/128 up + atf_check -s exit:0 ifconfig $netif inet6 2001:db8::2/128 anycast + atf_check -s exit:0 -o ignore ping -c1 -S 2001:db8::2 2001:db8::1 +} + +anycast_raw_addr_cleanup() +{ + ifconfig $(cat netif) destroy +} + atf_init_test_cases() { atf_add_test_case "addr6_invalid_addr" + atf_add_test_case "anycast_raw_addr" } diff --git a/tests/sys/netpfil/common/dummynet.sh b/tests/sys/netpfil/common/dummynet.sh index b77b2df84010..66736fbecdb7 100644 --- a/tests/sys/netpfil/common/dummynet.sh +++ b/tests/sys/netpfil/common/dummynet.sh @@ -265,10 +265,6 @@ queue_body() { fw=$1 - if [ $fw = "ipfw" ] && [ "$(atf_config_get ci false)" = "true" ]; then - atf_skip "https://bugs.freebsd.org/264805" - fi - firewall_init $fw dummynet_init $fw diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile index 3adaef09ddbd..404d5adfb07a 100644 --- a/tests/sys/netpfil/pf/Makefile +++ b/tests/sys/netpfil/pf/Makefile @@ -58,6 +58,8 @@ ATF_TESTS_SH+= altq \ ATF_TESTS_PYTEST+= frag6.py ATF_TESTS_PYTEST+= header.py ATF_TESTS_PYTEST+= icmp.py +ATF_TESTS_PYTEST+= igmp.py +ATF_TESTS_PYTEST+= mld.py ATF_TESTS_PYTEST+= nat64.py ATF_TESTS_PYTEST+= nat66.py ATF_TESTS_PYTEST+= return.py diff --git a/tests/sys/netpfil/pf/forward.sh b/tests/sys/netpfil/pf/forward.sh index 5d7d48a5dd9a..e9539bc9d278 100644 --- a/tests/sys/netpfil/pf/forward.sh +++ b/tests/sys/netpfil/pf/forward.sh @@ -101,10 +101,6 @@ v6_body() { pft_init - if [ "$(atf_config_get ci false)" = "true" ]; then - atf_skip "https://bugs.freebsd.org/260460" - fi - epair_send=$(vnet_mkepair) epair_recv=$(vnet_mkepair) diff --git a/tests/sys/netpfil/pf/icmp.py b/tests/sys/netpfil/pf/icmp.py index 59f2e8190b30..c5e945d60e99 100644 --- a/tests/sys/netpfil/pf/icmp.py +++ b/tests/sys/netpfil/pf/icmp.py @@ -136,8 +136,7 @@ class TestICMP(VnetTestTemplate): / sp.ICMP(type='echo-request') \ / sp.raw(bytes.fromhex('f0') * payload_size) - p = sp.sr1(packet, iface=self.vnet.iface_alias_map["if1"].name, - timeout=3) + p = sp.sr1(packet, timeout=3) p.show() ip = p.getlayer(sp.IP) @@ -176,6 +175,22 @@ class TestICMP(VnetTestTemplate): self.check_icmp_echo(sp, 1464) self.check_icmp_echo(sp, 1468) + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) + def test_truncated_opts(self): + ToolsHelper.print_output("/sbin/route add default 192.0.2.1") + + # Import in the correct vnet, so at to not confuse Scapy + import scapy.all as sp + + packet = sp.IP(dst="198.51.100.2", flags="DF") \ + / sp.ICMP(type='dest-unreach', length=108) \ + / sp.IP(src="198.51.100.2", dst="192.0.2.2", len=1000, \ + ihl=(120 >> 2), options=[ \ + sp.IPOption_Security(length=100)]) + packet.show() + sp.sr1(packet, timeout=3) + class TestICMP_NAT(VnetTestTemplate): REQUIRED_MODULES = [ "pf" ] TOPOLOGY = { diff --git a/tests/sys/netpfil/pf/igmp.py b/tests/sys/netpfil/pf/igmp.py new file mode 100644 index 000000000000..b339a2825082 --- /dev/null +++ b/tests/sys/netpfil/pf/igmp.py @@ -0,0 +1,95 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# 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. + +import pytest +from utils import DelayedSend +from atf_python.sys.net.tools import ToolsHelper +from atf_python.sys.net.vnet import VnetTestTemplate + +class TestIGMP(VnetTestTemplate): + REQUIRED_MODULES = [ "pf" ] + TOPOLOGY = { + "vnet1": {"ifaces": ["if1"]}, + "vnet2": {"ifaces": ["if1"]}, + "if1": {"prefixes4": [("192.0.2.2/24", "192.0.2.1/24")]}, + } + + def vnet2_handler(self, vnet): + ifname = vnet.iface_alias_map["if1"].name + ToolsHelper.print_output("/sbin/pfctl -e") + ToolsHelper.pf_rules([ + "pass", + ]) + ToolsHelper.print_output("/sbin/pfctl -x loud") + ToolsHelper.print_output("echo \"j 230.0.0.1 %s\ns 3600\nq\" | /usr/sbin/mtest" % ifname) + + def find_igmp_reply(self, pkt, ifname): + pkt.show() + s = DelayedSend(pkt) + + found = False + packets = self.sp.sniff(iface=ifname, timeout=5) + for r in packets: + r.show() + igmp = r.getlayer(self.sc.igmp.IGMP) + if not igmp: + continue + igmp.show() + if not igmp.gaddr == "230.0.0.1": + continue + found = True + return found + + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) + def test_ip_opts(self): + """Verify that we allow IGMP packets with IP options""" + ifname = self.vnet.iface_alias_map["if1"].name + + # Import in the correct vnet, so at to not confuse Scapy + import scapy.all as sp + import scapy.contrib as sc + import scapy.contrib.igmp + self.sp = sp + self.sc = sc + + # We allow IGMP packets with the router alert option + pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=1, + options=[sp.IPOption_Router_Alert()]) \ + / sc.igmp.IGMP(type=0x11, mrcode=1) + assert self.find_igmp_reply(pkt, ifname) + + # But not with other options + pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=1, + options=[sp.IPOption_NOP()]) \ + / sc.igmp.IGMP(type=0x11, mrcode=1) + assert not self.find_igmp_reply(pkt, ifname) + + # Or with the wrong TTL + pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=2, + options=[sp.IPOption_Router_Alert()]) \ + / sc.igmp.IGMP(type=0x11, mrcode=1) + assert not self.find_igmp_reply(pkt, ifname) diff --git a/tests/sys/netpfil/pf/killstate.sh b/tests/sys/netpfil/pf/killstate.sh index 447a4e388f11..0d98db822535 100644 --- a/tests/sys/netpfil/pf/killstate.sh +++ b/tests/sys/netpfil/pf/killstate.sh @@ -117,10 +117,6 @@ v6_body() { pft_init - if [ "$(atf_config_get ci false)" = "true" ]; then - atf_skip "https://bugs.freebsd.org/260458" - fi - epair=$(vnet_mkepair) ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad diff --git a/tests/sys/netpfil/pf/mbuf.sh b/tests/sys/netpfil/pf/mbuf.sh index d845f793a969..e3f138bb73b9 100644 --- a/tests/sys/netpfil/pf/mbuf.sh +++ b/tests/sys/netpfil/pf/mbuf.sh @@ -105,6 +105,12 @@ inet6_in_mbuf_len_body() epair=$(vnet_mkepair) ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad + # Ensure we don't unintentionally send MLD packets to alcatraz + pfctl -e + echo "block + pass out inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv, echoreq, echorep } + " | pfctl -g -f - + # Set up a simple jail with one interface vnet_mkjail alcatraz ${epair}b jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad diff --git a/tests/sys/netpfil/pf/mld.py b/tests/sys/netpfil/pf/mld.py new file mode 100644 index 000000000000..d118a34c8a7d --- /dev/null +++ b/tests/sys/netpfil/pf/mld.py @@ -0,0 +1,95 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# 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. + +import pytest +from utils import DelayedSend +from atf_python.sys.net.tools import ToolsHelper +from atf_python.sys.net.vnet import VnetTestTemplate + +class TestMLD(VnetTestTemplate): + REQUIRED_MODULES = [ "pf" ] + TOPOLOGY = { + "vnet1": {"ifaces": ["if1"]}, + "vnet2": {"ifaces": ["if1"]}, + "if1": {"prefixes6": [("2001:db8::2/64", "2001:db8::1/64")]}, + } + + def vnet2_handler(self, vnet): + ifname = vnet.iface_alias_map["if1"].name + #ToolsHelper.print_output("/sbin/pfctl -e") + ToolsHelper.pf_rules([ + "pass", + ]) + ToolsHelper.print_output("/sbin/pfctl -x loud") + #ToolsHelper.print_output("echo \"j 230.0.0.1 %s\ns 3600\nq\" | /usr/sbin/mtest" % ifname) + + def find_mld_reply(self, pkt, ifname): + pkt.show() + s = DelayedSend(pkt) + + found = False + packets = self.sp.sniff(iface=ifname, timeout=5) + for r in packets: + r.show() + mld = r.getlayer(self.sp.ICMPv6MLReport2) + if not mld: + continue + mld.show() + found = True + return found + + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) + def test_router_alert(self): + """Verify that we allow MLD packets with router alert extension header""" + ifname = self.vnet.iface_alias_map["if1"].name + #ToolsHelper.print_output("/sbin/ifconfig %s inet6 -ifdisable" % ifname) + ToolsHelper.print_output("/sbin/ifconfig") + + # Import in the correct vnet, so at to not confuse Scapy + import scapy.all as sp + import scapy.contrib as sc + import scapy.contrib.igmp + self.sp = sp + self.sc = sc + + # A correct MLD query gets a reply + pkt = sp.IPv6(src="fe80::1%%%s" % ifname, dst="ff02::1", hlim=1) \ + / sp.RouterAlert(value=0) \ + / sp.ICMPv6MLQuery2() + assert self.find_mld_reply(pkt, ifname) + + # The wrong extension header does not + pkt = sp.IPv6(src="fe80::1%%%s" % ifname, dst="ff02::1", hlim=1) \ + / sp.IPv6ExtHdrRouting() \ + / sp.ICMPv6MLQuery2() + assert not self.find_mld_reply(pkt, ifname) + + # Neither does an incorrect hop limit + pkt = sp.IPv6(src="fe80::1%%%s" % ifname, dst="ff02::1", hlim=2) \ + / sp.RouterAlert(value=0) \ + / sp.ICMPv6MLQuery2() + assert not self.find_mld_reply(pkt, ifname) diff --git a/tests/sys/netpfil/pf/nat64.py b/tests/sys/netpfil/pf/nat64.py index adae2489ce5e..5cc4713a16cc 100644 --- a/tests/sys/netpfil/pf/nat64.py +++ b/tests/sys/netpfil/pf/nat64.py @@ -272,3 +272,18 @@ class TestNAT64(VnetTestTemplate): reply = self.common_test_source_addr(packet) icmp = reply.getlayer(sp.ICMPv6EchoRequest) assert icmp + + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) + def test_bad_len(self): + """ + PR 288224: we can panic if the IPv6 plen is longer than the packet length. + """ + ToolsHelper.print_output("/sbin/route -6 add default 2001:db8::1") + import scapy.all as sp + + packet = sp.IPv6(dst="64:ff9b::198.51.100.2", hlim=2, plen=512) \ + / sp.ICMPv6EchoRequest() / sp.Raw("foo") + reply = sp.sr1(packet, timeout=3) + # We don't expect a reply to a corrupted packet + assert not reply diff --git a/tests/sys/netpfil/pf/set_tos.sh b/tests/sys/netpfil/pf/set_tos.sh index 75b96edbab6e..842377ee97c6 100644 --- a/tests/sys/netpfil/pf/set_tos.sh +++ b/tests/sys/netpfil/pf/set_tos.sh @@ -129,10 +129,6 @@ v6_body() { pft_init - if [ "$(atf_config_get ci false)" = "true" ]; then - atf_skip "https://bugs.freebsd.org/260459" - fi - epair=$(vnet_mkepair) ifconfig ${epair}a inet6 add 2001:db8:192::1 vnet_mkjail alcatraz ${epair}b diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index 78320375db7c..5e5fccdaca20 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -582,6 +582,34 @@ anchor_cleanup() pft_cleanup } +atf_test_case "flush" "cleanup" +flush_head() +{ + atf_set descr 'Test flushing addresses from tables' + atf_set require.user root +} + +flush_body() +{ + pft_init + + vnet_mkjail alcatraz + + atf_check -s exit:0 -e match:"1/1 addresses added." \ + jexec alcatraz pfctl -t foo -T add 1.2.3.4 + atf_check -s exit:0 -o match:" 1.2.3.4" \ + jexec alcatraz pfctl -t foo -T show + atf_check -s exit:0 -e match:"1 addresses deleted." \ + jexec alcatraz pfctl -t foo -T flush + atf_check -s exit:0 -o not-match:"1.2.3.4" \ + jexec alcatraz pfctl -t foo -T show +} + +flush_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4_counters" @@ -596,4 +624,5 @@ atf_init_test_cases() atf_add_test_case "pr259689" atf_add_test_case "precreate" atf_add_test_case "anchor" + atf_add_test_case "flush" } diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 1e63e4616909..4c127b392138 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -1441,6 +1441,10 @@ OLD_LIBS+=${DEBUG_LIBS} .endif .endif +.if ${MK_DETECT_TZ_CHANGES} == no +OLD_FILES+=tests/lib/libc/stdtime/detect_tz_changes_test +.endif + .if ${MK_DIALOG} == no OLD_FILES+=usr/bin/dialog OLD_FILES+=usr/bin/dpv diff --git a/tools/test/stress2/misc/all.exclude b/tools/test/stress2/misc/all.exclude index f8a5ea4a91f1..54524c92eac0 100644 --- a/tools/test/stress2/misc/all.exclude +++ b/tools/test/stress2/misc/all.exclude @@ -16,8 +16,6 @@ fsck12.sh Waiting for fix 20230319 fsync.sh panic: Journal overflow 20190208 fuse.sh https://people.freebsd.org/~pho/stress/log/log0546.txt 20240828 fuse2.sh https://people.freebsd.org/~pho/stress/log/log0547.txt 20240828 -getrandom.sh Known DoS issue 20201107 -getrandom2.sh Known DoS issue 20200302 gjournal.sh panic: Journal overflow 20190626 gjournal2.sh panic: Journal overflow 20180125 gjournal3.sh panic: Bio not on queue 20171225 @@ -34,6 +32,7 @@ maxvnodes2.sh https://people.freebsd.org/~pho/stress/log/log0083.txt 20210329 memguard.sh https://people.freebsd.org/~pho/stress/log/log0088.txt 20210402 memguard2.sh Waiting for fix commit memguard3.sh Waiting for fix commit +mount7.sh https://people.freebsd.org/~pho/stress/log/log0549.txt 20240912 mlockall2.sh Unrecoverable OOM killing seen 20190203 mlockall6.sh https://people.freebsd.org/~pho/stress/log/log0430.txt 20230403 mlockall7.sh Needs further investigation 20210123 @@ -46,6 +45,7 @@ nfs16.sh panic: Failed to register NFS lock locally - error=11 20160608 nullfs28.sh Hang in "mount drain" seen 20220111 oom2.sh Hang in pfault 20180324 overcommit2.sh CAM stuck in vmwait seen 20200112 +pmc4.sh https://people.freebsd.org/~pho/stress/log/log0548.txt 20240904 pmc8.sh panic: [pmc,2749] (ri21, rc1) waiting too long for pmc to ... 20210621 rename14.sh https://people.freebsd.org/~pho/stress/log/log0433.txt 20230409 sctp2.sh panic: Queues are not empty when handling SHUTDOWN-COMPLETE 20210211 @@ -71,8 +71,12 @@ syzkaller59.sh Page fault 20220625 syzkaller65.sh panic: in_pcblookup_hash_locked: invalid local address 20230318 syzkaller66.sh panic: in_pcbconnect: inp is already connected 20230621 syzkaller67.sh panic: ASan: Invalid access, 8-byte read at ... 20230621 +syzkaller80.sh panic 20250711 +syzkaller81.sh panic 20250711 quota6.sh https://people.freebsd.org/~pho/stress/log/log0456.txt 20240707 truss3.sh WiP 20200915 +zfs18.sh https://people.freebsd.org/~pho/stress/log/log0560.txt 20241118 +zfs9.sh panic: sacked_bytes < 0 20250711 # Test not to run for other reasons: diff --git a/tools/test/stress2/misc/fullpath2.sh b/tools/test/stress2/misc/fullpath2.sh index e4024c32f317..413f832420d4 100755 --- a/tools/test/stress2/misc/fullpath2.sh +++ b/tools/test/stress2/misc/fullpath2.sh @@ -123,7 +123,7 @@ static volatile u_int *share; #define NB 1024 #define RUNTIME 300 -/* dtrace -w -n 'fbt::*vn_fullpath1:entry {@rw[execname,probefunc] = count(); }' */ +/* dtrace -n 'fbt::vn_fullpath:entry {@rw[execname,probefunc] = count(); }' */ static void getfiles(pid_t pid) diff --git a/tools/test/stress2/misc/syzkaller80.sh b/tools/test/stress2/misc/syzkaller80.sh new file mode 100755 index 000000000000..31eae210d5b3 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller80.sh @@ -0,0 +1,320 @@ +#!/bin/sh + +# panic: ../../../kern/uipc_usrreq.c:1256: uipc_sosend_stream_or_seqpacket: Empty stailq 0xfffffe00ffe5fc88->stqh_last is 0xfffffe00ffe5fcd0, not head's first field address +# cpuid = 5 +# time = 1749593630 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00ffe5fab0 +# vpanic() at vpanic+0x136/frame 0xfffffe00ffe5fbe0 +# panic() at panic+0x43/frame 0xfffffe00ffe5fc40 +# uipc_sosend_stream_or_seqpacket() at uipc_sosend_stream_or_seqpacket+0xa39/frame 0xfffffe00ffe5fd10 +# sousrsend() at sousrsend+0x79/frame 0xfffffe00ffe5fd70 +# dofilewrite() at dofilewrite+0x81/frame 0xfffffe00ffe5fdc0 +# sys_writev() at sys_writev+0x69/frame 0xfffffe00ffe5fe00 +# amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe00ffe5ff30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00ffe5ff30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x82330181a, rsp = 0x8238dbf68, rbp = 0x8238dbf90 --- +# KDB: enter: panic +# [ thread pid 4484 tid 101524 ] +# Stopped at kdb_enter+0x33: movq $0,0x122ebc2(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #0 main-n277833-948078b65c27-dirty: Tue Jun 10 06:01:36 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=210ae0bfcef6324abfffbfaf10120b767106a990 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+cfcb8520b0071b548fba@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static unsigned long long procid; + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + int i, call, thread; + for (call = 0; call < 5; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + if (call == 2) + break; + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + sleep_ms(10); + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_STREAM*/ 1ul, + /*proto=*/0, /*fds=*/0x200000000040ul); + if (res != -1) { + r[0] = *(uint32_t*)0x200000000040; + r[1] = *(uint32_t*)0x200000000044; + } + break; + case 1: + memcpy((void*)0x200000000100, "\x09\x00\x10\x00", 4); + syscall(SYS_setsockopt, /*fd=*/r[1], /*level=*/0, /*optname=*/3, + /*optval=*/0x200000000100ul, /*optlen=*/4ul); + break; + case 2: + *(uint64_t*)0x2000000018c0 = 0; + *(uint32_t*)0x2000000018c8 = 0; + *(uint64_t*)0x2000000018d0 = 0; + *(uint64_t*)0x2000000018d8 = 0; + *(uint64_t*)0x2000000018e0 = 0x200000001880; + memcpy((void*)0x200000001880, "\x10\x00\x00\x00\xff\xff\x00\x00\x06", 9); + *(uint64_t*)0x2000000018e8 = 0x10; + *(uint32_t*)0x2000000018f0 = 0; + syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0x2000000018c0ul, /*f=*/0ul); + for (int i = 0; i < 64; i++) { + syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0x2000000018c0ul, /*f=*/0ul); + } + break; + case 3: + syscall(SYS_writev, /*fd=*/r[0], /*vec=*/0ul, /*vlen=*/0ul); + for (int i = 0; i < 64; i++) { + syscall(SYS_writev, /*fd=*/r[0], /*vec=*/0ul, /*vlen=*/0ul); + } + break; + case 4: + syscall(SYS_setsockopt, /*fd=*/(intptr_t)-1, /*level=*/0, /*optname=*/0xa, + /*optval=*/0ul, /*optlen=*/0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + for (procid = 0; procid < 4; procid++) { + if (fork() == 0) { + loop(); + } + } + sleep(1000000); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +timeout 3m /tmp/$prog > /dev/null 2>&1 + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/syzkaller81.sh b/tools/test/stress2/misc/syzkaller81.sh new file mode 100755 index 000000000000..e3e4ec50aeea --- /dev/null +++ b/tools/test/stress2/misc/syzkaller81.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +# panic: kern_clock_gettime: 22 +# cpuid = 1 +# time = 1750181240 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01a6084ba0 +# vpanic() at vpanic+0x136/frame 0xfffffe01a6084cd0 +# panic() at panic+0x43/frame 0xfffffe01a6084d30 +# kern_clock_nanosleep() at kern_clock_nanosleep+0x38f/frame 0xfffffe01a6084db0 +# sys_clock_nanosleep() at sys_clock_nanosleep+0x49/frame 0xfffffe01a6084e00 +# amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe01a6084f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01a6084f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x8233d281a, rsp = 0x820bfb2b8, rbp = 0x820bfb2e0 --- +# KDB: enter: panic +# [ thread pid 26119 tid 104417 ] +# Stopped at kdb_enter+0x33: movq $0,0x122a7b2(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #1 ufs-n278031-3296ff02387b: Tue Jun 17 16:40:44 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/var/tmp/deviant3/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=5eb7636bc26fcbd20412de35ec10944233b8577d +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+e17e46b1f0b65027b005@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + *(uint64_t*)0x200000000040 = 0x10000000000; + *(uint64_t*)0x200000000048 = 0x4000000; + syscall(SYS_clock_nanosleep, /*id=*/0x10ul, /*flags=TIMER_ABSTIME*/ 1ul, + /*rqtp=*/0x200000000040ul, /*rmtp=*/0ul); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +timeout 3m /tmp/$prog > /dev/null 2>&1 + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/usr.bin/bmake/Makefile.config b/usr.bin/bmake/Makefile.config index 78babc2f1382..8ff6c81b8c78 100644 --- a/usr.bin/bmake/Makefile.config +++ b/usr.bin/bmake/Makefile.config @@ -6,7 +6,7 @@ SRCTOP?= ${.CURDIR:H:H} # things set by configure -_MAKE_VERSION?=20250618 +_MAKE_VERSION?=20250707 prefix?= /usr srcdir= ${SRCTOP}/contrib/bmake diff --git a/usr.bin/bmake/unit-tests/Makefile b/usr.bin/bmake/unit-tests/Makefile index 1b9a47febe11..d4ee6f33f862 100644 --- a/usr.bin/bmake/unit-tests/Makefile +++ b/usr.bin/bmake/unit-tests/Makefile @@ -1,9 +1,9 @@ # This is a generated file, do NOT edit! # See contrib/bmake/bsd.after-import.mk # -# $Id: Makefile,v 1.239 2025/06/15 21:32:16 sjg Exp $ +# $Id: Makefile,v 1.240 2025/06/30 18:40:54 sjg Exp $ # -# $NetBSD: Makefile,v 1.367 2025/06/13 20:23:16 rillig Exp $ +# $NetBSD: Makefile,v 1.369 2025/06/29 09:40:13 rillig Exp $ # # Unit tests for make(1) # @@ -61,6 +61,7 @@ rm-tmpdir: .NOMETA # src/tests/usr.bin/make/t_make.sh as well. #TESTS+= archive #TESTS+= archive-suffix +TESTS+= char-005c-reverse-solidus TESTS+= cmd-errors TESTS+= cmd-errors-jobs TESTS+= cmd-errors-lint @@ -416,6 +417,7 @@ TESTS+= varmod-to-upper TESTS+= varmod-undefined TESTS+= varmod-unique TESTS+= varname +TESTS+= varname-circumflex TESTS+= varname-dollar TESTS+= varname-dot-alltargets TESTS+= varname-dot-curdir @@ -544,7 +546,6 @@ TESTS:= ${TESTS:${BROKEN_TESTS:S,^,N,:ts:}} # Ideas for more tests: # char-0020-space.mk -# char-005C-backslash.mk # escape-cond-str.mk # escape-cond-func-arg.mk # escape-varmod.mk diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index 0b1a37f43723..1ca63b371f65 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -259,6 +259,7 @@ 06/11 Alonso Cardenas Marquez <acm@FreeBSD.org> born in Arequipa, Peru, 1979 06/14 Josh Paetzel <jpaetzel@FreeBSD.org> born in Minneapolis, Minnesota, United States, 1973 06/15 Second quarterly status reports are due on 06/30 +06/15 Aymeric Wibo <obiwac@FreeBSD.org> born in Plaistow, London, United Kingdom, 2004 06/17 Tilman Linneweh <arved@FreeBSD.org> born in Weinheim, Baden-Wuerttemberg, Germany, 1978 06/18 Li-Wen Hsu <lwhsu@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1984 06/18 Roman Bogorodskiy <novel@FreeBSD.org> born in Saratov, Russian Federation, 1986 diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1 index 37f7d7837b11..1b6d800b0285 100644 --- a/usr.bin/du/du.1 +++ b/usr.bin/du/du.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 29, 2024 +.Dd July 16, 2025 .Dt DU 1 .Os .Sh NAME @@ -58,7 +58,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl A Display the apparent size instead of the disk usage. @@ -225,7 +225,7 @@ Also display a grand total at the end: .Xr chflags 2 , .Xr fts 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr symlink 7 , .Xr quot 8 .Sh STANDARDS diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index eb3fd4d0dbde..8c2d8624a82a 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -1156,7 +1156,7 @@ and was removed in .At v3 . It was rewritten for .At v5 -and later be enhanced for the Programmer's Workbench (PWB). +and was later enhanced for the Programmer's Workbench (PWB). These changes were later incorporated in .At v7 . .Sh BUGS diff --git a/usr.bin/iscsictl/iscsictl.8 b/usr.bin/iscsictl/iscsictl.8 index 74394063a007..88c79c297848 100644 --- a/usr.bin/iscsictl/iscsictl.8 +++ b/usr.bin/iscsictl/iscsictl.8 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 27, 2018 +.Dd July 16, 2025 .Dt ISCSICTL 8 .Os .Sh NAME @@ -88,7 +88,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl A Add session. @@ -190,7 +190,7 @@ Disconnect all iSCSI sessions: .Dl Nm Fl Ra .Sh SEE ALSO .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr iscsi 4 , .Xr iscsi.conf 5 , .Xr iscsid 8 diff --git a/usr.bin/last/last.1 b/usr.bin/last/last.1 index f3ccc6e772af..b026ed6a7921 100644 --- a/usr.bin/last/last.1 +++ b/usr.bin/last/last.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 9, 2021 +.Dd July 16, 2025 .Dt LAST 1 .Os .Sh NAME @@ -75,7 +75,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl d Ar date Specify the snapshot date and time. @@ -223,7 +223,7 @@ alice ttyv0 Mon Dec 7 19:18 - 22:27 (03:09) .Xr lastcomm 1 , .Xr getutxent 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr ac 8 , .Xr lastlogin 8 .Sh HISTORY diff --git a/usr.bin/man/man.sh b/usr.bin/man/man.sh index ec20fc813bf4..18595042da5f 100755 --- a/usr.bin/man/man.sh +++ b/usr.bin/man/man.sh @@ -313,6 +313,8 @@ manpath_warnings() { # redirected to another source file. man_check_for_so() { local IFS line tstr + local counter_so=0 + local counter_so_limit=32 unset IFS if [ -n "$catpage" ]; then @@ -320,13 +322,16 @@ man_check_for_so() { fi # We need to loop to accommodate multiple .so directives. - while true + while [ $counter_so -lt $counter_so_limit ] do + counter_so=$((counter_so + 1)) + line=$($cattool "$manpage" 2>/dev/null | grep -E -m1 -v '^\.\\"[ ]*|^[ ]*$') case "$line" in '.so /'*) break ;; # ignore absolute path '.so '*) trim "${line#.so}" - decho "$manpage includes $tstr" + decho "$manpage includes $tstri level=$counter_so" + # Glob and check for the file. if ! check_man "$1/$tstr" ""; then decho " Unable to find $tstr" @@ -337,6 +342,10 @@ man_check_for_so() { esac done + if [ $counter_so -ge $counter_so_limit ]; then + decho ".so include limit of $counter_so_limit reached, stop" + fi + return 0 } diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1 index cf6a907c6aa4..1931c38a1fad 100644 --- a/usr.bin/netstat/netstat.1 +++ b/usr.bin/netstat/netstat.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 30, 2025 +.Dd July 16, 2025 .Dt NETSTAT 1 .Os .Sh NAME @@ -166,7 +166,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl 4 Show IPv4 only. @@ -954,7 +954,7 @@ Show IPv4 listening sockets: .Xr ps 1 , .Xr sockstat 1 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr bpf 4 , .Xr inet 4 , .Xr route 4 , diff --git a/usr.bin/nfsstat/nfsstat.1 b/usr.bin/nfsstat/nfsstat.1 index 7d641b50f1ac..a4a00586f21b 100644 --- a/usr.bin/nfsstat/nfsstat.1 +++ b/usr.bin/nfsstat/nfsstat.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 28, 2023 +.Dd July 16, 2025 .Dt NFSSTAT 1 .Os .Sh NAME @@ -123,7 +123,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .El .Sh SEE ALSO diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1 index 1e05e235e619..b810abf66da7 100644 --- a/usr.bin/procstat/procstat.1 +++ b/usr.bin/procstat/procstat.1 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 7, 2022 +.Dd July 16, 2025 .Dt PROCSTAT 1 .Os .Sh NAME @@ -136,7 +136,7 @@ flag is specified the output is generated via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .Pp The following commands are available for @@ -870,7 +870,7 @@ procstat: procstat_getprocs() .Xr libprocstat 3 , .Xr libxo 3 , .Xr signal 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr ddb 4 , .Xr divert 4 , .Xr icmp 4 , diff --git a/usr.bin/sed/sed.1 b/usr.bin/sed/sed.1 index 345f673310d8..5fd894eaf78b 100644 --- a/usr.bin/sed/sed.1 +++ b/usr.bin/sed/sed.1 @@ -1,3 +1,6 @@ +.\" +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -28,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 17, 2024 +.Dd June 14, 2025 .Dt SED 1 .Os .Sh NAME @@ -597,17 +600,17 @@ with .Ql baz when piped from another command: .Bd -literal -offset indent -echo "An alternate word, like bar, is sometimes used in examples." | sed 's/bar/baz/' +echo "use bar in examples" | sed 's/bar/baz/' .Ed .Pp Using backlashes can sometimes be hard to read and follow: .Bd -literal -offset indent -echo "/home/example" | sed 's/\\/home\\/example/\\/usr\\/local\\/example/' +echo "/bin/bash" | sed 's/\\/bin\\/bash/\\/bin\\/sh/' .Ed .Pp Using a different separator can be handy when working with paths: .Bd -literal -offset indent -echo "/home/example" | sed 's#/home/example#/usr/local/example#' +echo "/bin/bash" | sed 's#/bin/bash#/bin/sh#' .Ed .Pp Replace all occurrences of diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index da658e33e542..4832a09764fd 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -25,7 +25,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 June 27, 2025 +.Dd June 30, 2025 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nd list open sockets .Sh SYNOPSIS .Nm -.Op Fl 46ACcfIiLlnqSsUuv +.Op Fl 46ACcfIiLlnqSsUuvw .Op Fl j Ar jail .Op Fl p Ar ports .Op Fl P Ar protocols @@ -119,6 +119,8 @@ Show sockets. .It Fl v Verbose mode. +.It Fl w +Automatically size the columns. .El .Pp If neither diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index 1a24ff67c321..d0540c54a1aa 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -97,6 +97,7 @@ static bool opt_s; /* Show protocol state if applicable */ static bool opt_U; /* Show remote UDP encapsulation port number */ static bool opt_u; /* Show Unix domain sockets */ static u_int opt_v; /* Verbose mode */ +static bool opt_w; /* Automatically size the columns */ /* * Default protocols to use if no -P was defined. @@ -1101,7 +1102,7 @@ format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) { /* Remote peer we connect(2) to, if any. */ if (faddr->conn != 0) { struct sock *p; - pos += strlcpy(buf, "-> ", bufsize); + pos += strlcpy(SAFEBUF, "-> ", SAFESIZE); p = RB_FIND(pcbs_t, &pcbs, &(struct sock){ .pcb = faddr->conn }); if (__predict_false(p == NULL)) { @@ -1132,8 +1133,7 @@ format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) { while ((p = RB_FIND(pcbs_t, &pcbs, &(struct sock){ .pcb = ref })) != 0) { f = RB_FIND(files_t, &ftree, - &(struct file){ .xf_data = - p->socket }); + &(struct file){ .xf_data = p->socket }); if (f != NULL) { pos += snprintf(SAFEBUF, SAFESIZE, "%s[%lu %d]", fref ? "" : ",", @@ -1178,13 +1178,10 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) len = strlen(s->protoname); if (s->vflag & (INP_IPV4 | INP_IPV6)) len += 1; - if (laddr != NULL && faddr != NULL && s->family == AF_UNIX && - laddr->address.ss_len == 0 && faddr->conn == 0) - len += strlen(" (not connected)"); cw->proto = MAX(cw->proto, len); while (laddr != NULL || faddr != NULL) { - if (s->family == AF_UNIX) { + if (opt_w && s->family == AF_UNIX) { if ((laddr == NULL) || (faddr == NULL)) errx(1, "laddr = %p or faddr = %p is NULL", (void *)laddr, (void *)faddr); @@ -1193,7 +1190,7 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) cw->local_addr = MAX(cw->local_addr, len); len = format_unix_faddr(faddr, NULL, 0); cw->foreign_addr = MAX(cw->foreign_addr, len); - } else { + } else if (opt_w) { if (laddr != NULL) { len = formataddr(&laddr->address, NULL, 0); cw->local_addr = MAX(cw->local_addr, len); @@ -1296,23 +1293,6 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s) static void calculate_column_widths(struct col_widths *cw) { - cw->user = 4; - cw->command = 10; - cw->pid = 3; - cw->fd = 2; - cw->proto = 5; - cw->local_addr = 13; - cw->foreign_addr = 15; - cw->pcb_kva = 18; - cw->fib = 3; - cw->splice_address = 14; - cw->inp_gencnt = 2; - cw->encaps = 6; - cw->path_state = 10; - cw->conn_state = 10; - cw->stack = 5; - cw->cc = 2; - int n, len; struct file *xf; struct sock *s; @@ -1366,13 +1346,10 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) faddr = s->faddr; first = true; - snprintf(buf, bufsize, "%s%s%s%s", + snprintf(buf, bufsize, "%s%s%s", s->protoname, s->vflag & INP_IPV4 ? "4" : "", - s->vflag & INP_IPV6 ? "6" : "", - (laddr != NULL && faddr != NULL && - s->family == AF_UNIX && laddr->address.ss_len == 0 && - faddr->conn == 0) ? " (not connected)" : ""); + s->vflag & INP_IPV6 ? "6" : ""); printf(" %-*s", cw->proto, buf); while (laddr != NULL || faddr != NULL) { if (s->family == AF_UNIX) { @@ -1381,23 +1358,27 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) (void *)laddr, (void *)faddr); if (laddr->address.ss_len > 0) formataddr(&laddr->address, buf, bufsize); + else if (laddr->address.ss_len == 0 && faddr->conn == 0) + strlcpy(buf, "(not connected)", bufsize); else strlcpy(buf, "??", bufsize); - printf(" %-*s", cw->local_addr, buf); + printf(" %-*.*s", cw->local_addr, cw->local_addr, buf); if (format_unix_faddr(faddr, buf, bufsize) == 0) strlcpy(buf, "??", bufsize); - printf(" %-*s", cw->foreign_addr, buf); + printf(" %-*.*s", cw->foreign_addr, + cw->foreign_addr, buf); } else { if (laddr != NULL) formataddr(&laddr->address, buf, bufsize); else strlcpy(buf, "??", bufsize); - printf(" %-*s", cw->local_addr, buf); + printf(" %-*.*s", cw->local_addr, cw->local_addr, buf); if (faddr != NULL) formataddr(&faddr->address, buf, bufsize); else strlcpy(buf, "??", bufsize); - printf(" %-*s", cw->foreign_addr, buf); + printf(" %-*.*s", cw->foreign_addr, + cw->foreign_addr, buf); } if (opt_A) printf(" %#*" PRIx64, cw->pcb_kva, s->pcb); @@ -1411,6 +1392,8 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) if (sp != NULL) formataddr(&sp->laddr->address, buf, bufsize); + else + strlcpy(buf, "??", bufsize); } else strlcpy(buf, "??", bufsize); printf(" %-*s", cw->splice_address, buf); @@ -1510,6 +1493,25 @@ display(void) err(1, "malloc()"); return; } + + cw = (struct col_widths) { + .user = strlen("USER"), + .command = 10, + .pid = strlen("PID"), + .fd = strlen("FD"), + .proto = strlen("PROTO"), + .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21, + .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21, + .pcb_kva = 18, + .fib = strlen("FIB"), + .splice_address = strlen("SPLICE ADDRESS"), + .inp_gencnt = strlen("ID"), + .encaps = strlen("ENCAPS"), + .path_state = strlen("PATH STATE"), + .conn_state = strlen("CONN STATE"), + .stack = strlen("STACK"), + .cc = strlen("CC"), + }; calculate_column_widths(&cw); if (!opt_q) { @@ -1642,7 +1644,7 @@ static void usage(void) { errx(1, - "usage: sockstat [-46ACcfIiLlnqSsUuv] [-j jid] [-p ports] [-P protocols]"); + "usage: sockstat [-46ACcfIiLlnqSsUuvw] [-j jid] [-p ports] [-P protocols]"); } int @@ -1721,7 +1723,7 @@ main(int argc, char *argv[]) ++opt_v; break; case 'w': - /* left for backward compatibility. */ + opt_w = true; break; default: usage(); diff --git a/usr.bin/top/top.1 b/usr.bin/top/top.1 index d8ef763e7a34..53b078839526 100644 --- a/usr.bin/top/top.1 +++ b/usr.bin/top/top.1 @@ -1,4 +1,4 @@ -.Dd April 1, 2025 +.Dd June 9, 2025 .Dt TOP 1 .Os .Sh NAME @@ -398,6 +398,7 @@ ID corresponding to the process, USERNAME is the name of the process's owner (if .Fl u is specified, a UID column will be substituted for USERNAME), +THR is the thread count, showing the number of threads a process has, PRI is the current priority of the process, NICE is the .Xr nice 1 diff --git a/usr.bin/vmstat/vmstat.8 b/usr.bin/vmstat/vmstat.8 index de4176c9361c..80facb05cc35 100644 --- a/usr.bin/vmstat/vmstat.8 +++ b/usr.bin/vmstat/vmstat.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 21, 2021 +.Dd July 16, 2025 .Dt VMSTAT 8 .Os .Sh NAME @@ -71,7 +71,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl a When used with @@ -371,7 +371,7 @@ statistics every second. .Xr systat 1 , .Xr libmemstat 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr gstat 8 , .Xr iostat 8 , .Xr pstat 8 , diff --git a/usr.bin/w/w.1 b/usr.bin/w/w.1 index a92edc6f0059..159eb3370c8c 100644 --- a/usr.bin/w/w.1 +++ b/usr.bin/w/w.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 24, 2020 +.Dd July 16, 2025 .Dt W 1 .Os .Sh NAME @@ -61,7 +61,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl d dumps out the entire process list on a per controlling @@ -145,7 +145,7 @@ flags are no longer supported. .Xr uptime 1 , .Xr who 1 , .Xr libxo 3 , -.Xr xo_parse_args 3 +.Xr xo_options 7 .Sh HISTORY The .Nm diff --git a/usr.bin/wc/wc.1 b/usr.bin/wc/wc.1 index 482145c8f01f..656408794950 100644 --- a/usr.bin/wc/wc.1 +++ b/usr.bin/wc/wc.1 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 11, 2020 +.Dd July 16, 2025 .Dt WC 1 .Os .Sh NAME @@ -70,7 +70,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl L Write the length of the line containing the most bytes (default) or characters @@ -196,7 +196,7 @@ utility. .Sh SEE ALSO .Xr iswspace 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 +.Xr xo_options 7 .Sh STANDARDS The .Nm diff --git a/usr.sbin/arp/arp.8 b/usr.sbin/arp/arp.8 index d31b2b482ba3..0a171c9e36be 100644 --- a/usr.sbin/arp/arp.8 +++ b/usr.sbin/arp/arp.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 13, 2020 +.Dd July 16, 2025 .Dt ARP 8 .Os .Sh NAME @@ -80,7 +80,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl a The program displays or, if it is used with the @@ -183,7 +183,7 @@ character will mark the rest of the line as a comment. .Sh SEE ALSO .Xr inet 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr arp 4 , .Xr ifconfig 8 , .Xr ndp 8 diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c index 5b21361f2823..0871bbb87fe5 100644 --- a/usr.sbin/bhyve/pci_xhci.c +++ b/usr.sbin/bhyve/pci_xhci.c @@ -2588,7 +2588,7 @@ pci_xhci_reset_port(struct pci_xhci_softc *sc, int portn, int warm) if (dev) { port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC); port->portsc |= XHCI_PS_PED | - XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); + XHCI_PS_SPEED_SET(dev->hci.hci_speed); if (warm && dev->dev_ue->ue_usbver == 3) { port->portsc |= XHCI_PS_WRC; @@ -2622,11 +2622,11 @@ pci_xhci_init_port(struct pci_xhci_softc *sc, int portn) if (dev->dev_ue->ue_usbver == 2) { port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_POLL) | - XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); + XHCI_PS_SPEED_SET(dev->hci.hci_speed); } else { port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_U0) | - XHCI_PS_PED | /* enabled */ - XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); + XHCI_PS_PED | /* enabled */ + XHCI_PS_SPEED_SET(dev->hci.hci_speed); } DPRINTF(("Init port %d 0x%x", portn, port->portsc)); @@ -2833,6 +2833,7 @@ pci_xhci_parse_devices(struct pci_xhci_softc *sc, nvlist_t *nvl) dev->hci.hci_sc = dev; dev->hci.hci_intr = pci_xhci_dev_intr; dev->hci.hci_event = pci_xhci_dev_event; + dev->hci.hci_speed = USB_SPEED_MAX; if (ue->ue_usbver == 2) { if (usb2_port == sc->usb2_port_start + @@ -2863,6 +2864,8 @@ pci_xhci_parse_devices(struct pci_xhci_softc *sc, nvlist_t *nvl) dev->dev_ue = ue; dev->dev_sc = devsc; + if (dev->hci.hci_speed == USB_SPEED_MAX) + dev->hci.hci_speed = ue->ue_usbspeed; XHCI_SLOTDEV_PTR(sc, slot) = dev; ndevices++; @@ -3228,6 +3231,7 @@ pci_xhci_snapshot(struct vm_snapshot_meta *meta) /* devices[i]->hci */ SNAPSHOT_VAR_OR_LEAVE(dev->hci.hci_address, meta, ret, done); SNAPSHOT_VAR_OR_LEAVE(dev->hci.hci_port, meta, ret, done); + SNAPSHOT_VAR_OR_LEAVE(dev->hci.hci_speed, meta, ret, done); } SNAPSHOT_VAR_OR_LEAVE(sc->usb2_port_start, meta, ret, done); diff --git a/usr.sbin/bhyve/usb_emul.h b/usr.sbin/bhyve/usb_emul.h index 8e0afcb2878b..85dedfeacd3b 100644 --- a/usr.sbin/bhyve/usb_emul.h +++ b/usr.sbin/bhyve/usb_emul.h @@ -85,6 +85,7 @@ struct usb_hci { /* controller managed fields */ int hci_address; int hci_port; + int hci_speed; }; /* diff --git a/usr.sbin/bsdinstall/scripts/pkgbase.in b/usr.sbin/bsdinstall/scripts/pkgbase.in index 1ff93afe817b..cf8e84de6923 100755 --- a/usr.sbin/bsdinstall/scripts/pkgbase.in +++ b/usr.sbin/bsdinstall/scripts/pkgbase.in @@ -234,12 +234,17 @@ local function pkgbase() local chroot = assert(os.getenv("BSDINSTALL_CHROOT")) assert(os.execute("mkdir -p " .. chroot)) + -- Always install the default FreeBSD-base.conf file to the chroot, even + -- if we don't actually fetch the packages from the repository specified + -- there (e.g. because we are performing an offline installation). + local chroot_repos_dir = chroot .. "/usr/local/etc/pkg/repos/" + assert(os.execute("mkdir -p " .. chroot_repos_dir)) + assert(os.execute("cp /usr/share/bsdinstall/FreeBSD-base.conf " .. + chroot_repos_dir)) + local repos_dir = os.getenv("BSDINSTALL_PKG_REPOS_DIR") if not repos_dir then - repos_dir = chroot .. "/usr/local/etc/pkg/repos/" - assert(os.execute("mkdir -p " .. repos_dir)) - assert(os.execute("cp /usr/share/bsdinstall/FreeBSD-base.conf " .. repos_dir)) - + repos_dir = chroot_repos_dir -- Since pkg always interprets fingerprints paths as relative to -- the --rootdir we must copy the key from the host. assert(os.execute("mkdir -p " .. chroot .. "/usr/share/keys")) diff --git a/usr.sbin/bsdinstall/scripts/wlanconfig b/usr.sbin/bsdinstall/scripts/wlanconfig index 8ac64858eaba..33d94a933f45 100755 --- a/usr.sbin/bsdinstall/scripts/wlanconfig +++ b/usr.sbin/bsdinstall/scripts/wlanconfig @@ -92,7 +92,7 @@ dialog_country_select() sub(/.*domains:/, ""), /[^[:alnum:][[:space:]]/ { n = split($0, domains) for (i = 1; i <= n; i++) - printf "'\''%s'\'' '\'\''", domains[i] + printf "'\''%s'\'' '\'\''\n", domains[i] } ' | sort ) countries=$( echo "$input" | awk ' @@ -200,6 +200,12 @@ fi while :; do SCANSSID=0 + # While wpa_supplicant may IFF_UP the interface, we do not want to rely + # in this. In case the script is run manually (outside the installer, + # e.g., for testing) wpa_supplicant may be running and the wlanN + # interface may be down (especially if dialog_country_select is not + # run successfully either) and scanning will not work. + f_eval_catch -d wlanconfig ifconfig "ifconfig $WLAN_IFACE up" f_eval_catch -d wlanconfig wpa_cli "wpa_cli scan" f_dialog_title "Scanning" f_dialog_pause "Waiting 5 seconds to scan for wireless networks..." 5 || diff --git a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c index 9d5a693c7c68..9252e63749bb 100644 --- a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c +++ b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.c @@ -1179,8 +1179,10 @@ main(int argc, char ** argv) /* On -h (help) exit without error. */ if (opt_num == -2) exit(0); - else + else { + fprintf(stderr, "Error: %s\n", snmp_client.error); exit(1); + } } oid_cnt = argc - opt_num - 1; @@ -1239,7 +1241,7 @@ main(int argc, char ** argv) } if (snmp_open(NULL, NULL, NULL, NULL)) { - warn("Failed to open snmp session"); + fprintf(stderr, "snmp_open(3): %s\n", snmp_client.error); snmp_tool_freeall(&snmptoolctx); exit(1); } diff --git a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c index fb09e1ac785e..b4613763fff5 100644 --- a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c +++ b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c @@ -790,15 +790,6 @@ parse_server(char *opt_arg) if (snmp_parse_server(&snmp_client, opt_arg) < 0) return (-1); - if (snmp_client.trans > SNMP_TRANS_UDP && snmp_client.chost == NULL) { - if ((snmp_client.chost = malloc(strlen(SNMP_DEFAULT_LOCAL) + 1)) - == NULL) { - syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); - return (-1); - } - strcpy(snmp_client.chost, SNMP_DEFAULT_LOCAL); - } - return (2); } diff --git a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.h b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.h index 2874f311fbd0..54a087491a4f 100644 --- a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.h +++ b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.h @@ -43,7 +43,6 @@ #define MAX_BUFF_SIZE (ASN_MAXOCTETSTRING + 50) #define SNMP_DEFS_DIR "/usr/share/snmp/defs/" -#define SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock" #define SNMP_MAX_REPETITIONS 10 diff --git a/usr.sbin/certctl/certctl.8 b/usr.sbin/certctl/certctl.8 index 286072c1b4d6..7e49bb89e2ac 100644 --- a/usr.sbin/certctl/certctl.8 +++ b/usr.sbin/certctl/certctl.8 @@ -24,7 +24,7 @@ .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 10, 2023 +.Dd July 17, 2025 .Dt CERTCTL 8 .Os .Sh NAME @@ -38,15 +38,15 @@ .Op Fl v .Ic untrusted .Nm -.Op Fl nUv +.Op Fl cnUv .Op Fl D Ar destdir .Op Fl M Ar metalog .Ic rehash .Nm -.Op Fl nv +.Op Fl cnv .Ic untrust Ar file .Nm -.Op Fl nv +.Op Fl cnv .Ic trust Ar file .Sh DESCRIPTION The @@ -56,6 +56,8 @@ applications that use OpenSSL. .Pp Flags: .Bl -tag -width 4n +.It Fl c +Copy certificates instead of linking to them. .It Fl D Ar destdir Specify the DESTDIR (overriding values from the environment). .It Fl d Ar distbase diff --git a/usr.sbin/certctl/certctl.sh b/usr.sbin/certctl/certctl.sh index 458f5c53682f..2bde651de126 100755 --- a/usr.sbin/certctl/certctl.sh +++ b/usr.sbin/certctl/certctl.sh @@ -36,6 +36,7 @@ set -u ############################################################ GLOBALS SCRIPTNAME="${0##*/}" +LINK=-lrs ERRORS=0 NOOP=false UNPRIV=false @@ -110,7 +111,6 @@ create_trusted() { local hash certhash otherfile otherhash local suffix - local link=${2:+-lrs} hash=$(do_hash "$1") || return certhash=$(openssl x509 -sha1 -in "$1" -noout -fingerprint) @@ -130,7 +130,7 @@ create_trusted() done suffix=$(get_decimal "$CERTDESTDIR" "$hash") verbose "Adding $hash.$suffix to trust store" - perform install ${INSTALLFLAGS} -m 0444 ${link} \ + perform install ${INSTALLFLAGS} -m 0444 ${LINK} \ "$(realpath "$1")" "$CERTDESTDIR/$hash.$suffix" } @@ -159,7 +159,6 @@ resolve_certname() create_untrusted() { local srcfile filename - local link=${2:+-lrs} set -- $(resolve_certname "$1") srcfile=$1 @@ -170,7 +169,7 @@ create_untrusted() fi verbose "Adding $filename to untrusted list" - perform install ${INSTALLFLAGS} -m 0444 ${link} \ + perform install ${INSTALLFLAGS} -m 0444 ${LINK} \ "$srcfile" "$UNTRUSTDESTDIR/$filename" } @@ -190,7 +189,7 @@ do_scan() 0) ;; 1) - "$CFUNC" "$CFILE" link + "$CFUNC" "$CFILE" ;; *) verbose "Multiple certificates found, splitting..." @@ -303,19 +302,20 @@ usage() echo " List trusted certificates" echo " $SCRIPTNAME [-v] untrusted" echo " List untrusted certificates" - echo " $SCRIPTNAME [-nUv] [-D <destdir>] [-d <distbase>] [-M <metalog>] rehash" - echo " Generate hash links for all certificates" - echo " $SCRIPTNAME [-nv] untrust <file>" + echo " $SCRIPTNAME [-cnUv] [-D <destdir>] [-d <distbase>] [-M <metalog>] rehash" + echo " Rehash all trusted and untrusted certificates" + echo " $SCRIPTNAME [-cnv] untrust <file>" echo " Add <file> to the list of untrusted certificates" - echo " $SCRIPTNAME [-nv] trust <file>" + echo " $SCRIPTNAME [-cnv] trust <file>" echo " Remove <file> from the list of untrusted certificates" exit 64 } ############################################################ MAIN -while getopts D:d:M:nUv flag; do +while getopts cD:d:M:nUv flag; do case "$flag" in + c) LINK=-c ;; D) DESTDIR=${OPTARG} ;; d) DISTBASE=${OPTARG} ;; M) METALOG=${OPTARG} ;; @@ -334,7 +334,7 @@ fi : ${METALOG:=${DESTDIR}/METALOG} INSTALLFLAGS= if "$UNPRIV" ; then - INSTALLFLAGS="-U -M ${METALOG} -D ${DESTDIR} -o root -g wheel" + INSTALLFLAGS="-U -M ${METALOG} -D ${DESTDIR:-/} -o root -g wheel" fi : ${LOCALBASE:=$(sysctl -n user.localbase)} : ${TRUSTPATH:=${DESTDIR}${DISTBASE}/usr/share/certs/trusted:${DESTDIR}${LOCALBASE}/share/certs:${DESTDIR}${LOCALBASE}/etc/ssl/certs} diff --git a/usr.sbin/ctladm/tests/port.sh b/usr.sbin/ctladm/tests/port.sh index 5bc5d879c983..d966529a85ae 100644 --- a/usr.sbin/ctladm/tests/port.sh +++ b/usr.sbin/ctladm/tests/port.sh @@ -38,12 +38,6 @@ # PGTAG,TARGET pair must be globally unique. PGTAG=30257 -load_cfiscsi() { - if ! kldstat -q -m cfiscsi; then - kldload cfiscsi || atf_skip "could not load cfscsi kernel mod" - fi -} - skip_if_ctld() { if service ctld onestatus > /dev/null; then # If ctld is running on this server, let's not interfere. @@ -118,11 +112,11 @@ create_iscsi_head() atf_set "descr" "ctladm can create a new iscsi port" atf_set "require.user" "root" atf_set "require.progs" ctladm + atf_set "require.kmods" "cfiscsi" } create_iscsi_body() { skip_if_ctld - load_cfiscsi TARGET=iqn.2018-10.myhost.create_iscsi atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" @@ -146,11 +140,11 @@ create_iscsi_alias_head() atf_set "descr" "ctladm can create a new iscsi port with a target alias" atf_set "require.user" "root" atf_set "require.progs" ctladm + atf_set "require.kmods" "cfiscsi" } create_iscsi_alias_body() { skip_if_ctld - load_cfiscsi TARGET=iqn.2018-10.myhost.create_iscsi_alias ALIAS="foobar" @@ -173,11 +167,11 @@ create_iscsi_without_required_args_head() atf_set "descr" "ctladm will gracefully fail to create an iSCSI target if required arguments are missing" atf_set "require.user" "root" atf_set "require.progs" ctladm + atf_set "require.kmods" "cfiscsi" } create_iscsi_without_required_args_body() { skip_if_ctld - load_cfiscsi TARGET=iqn.2018-10.myhost.create_iscsi atf_check -s exit:1 -e match:"Missing required argument: cfiscsi_target" ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG @@ -288,11 +282,11 @@ remove_iscsi_head() atf_set "descr" "ctladm can remove an iscsi port" atf_set "require.user" "root" atf_set "require.progs" ctladm + atf_set "require.kmods" "cfiscsi" } remove_iscsi_body() { skip_if_ctld - load_cfiscsi TARGET=iqn.2018-10.myhost.remove_iscsi atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" @@ -314,11 +308,11 @@ remove_iscsi_without_required_args_head() atf_set "descr" "ctladm will gracefully fail to remove an iSCSI target if required arguments are missing" atf_set "require.user" "root" atf_set "require.progs" ctladm + atf_set "require.kmods" "cfiscsi" } remove_iscsi_without_required_args_body() { skip_if_ctld - load_cfiscsi TARGET=iqn.2018-10.myhost.remove_iscsi_without_required_args atf_check -o save:port-create.txt ctladm port -c -d "iscsi" -O cfiscsi_portal_group_tag=$PGTAG -O cfiscsi_target="$TARGET" diff --git a/usr.sbin/efitable/efitable.8 b/usr.sbin/efitable/efitable.8 index d1f4cedcdea8..52949abcb853 100644 --- a/usr.sbin/efitable/efitable.8 +++ b/usr.sbin/efitable/efitable.8 @@ -1,4 +1,6 @@ .\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 2021 3mdeb Embedded Systems Consulting <contact@3mdeb.com> .\" .\" Redistribution and use in source and binary forms, with or without @@ -22,12 +24,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 10, 2021 +.Dd July 16, 2025 .Dt EFITABLE 8 .Os .Sh NAME .Nm efitable -.Nd Dump UEFI tables +.Nd dump UEFI tables .Sh SYNOPSIS .Nm .Op Fl u Ar uuid | Fl t Ar name @@ -39,28 +41,29 @@ This program prints data from tables. .Pp The following options are available: -.Bl -tag -width 20m +.Bl -tag -width "-t name | --table name" .It Fl -libxo Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. -.It Fl t Ar name Fl -table Ar name +.It Fl t Ar name | Fl -table Ar name Specify the name of the table to print. Currently supported tables: .Pp .Bl -tag -width indent -compact .It Cm esrt EFI System Resource Table +.It Cm memory +EFI Memory Attributes Table .It Cm prop EFI Properties Table .El -.It Fl u Ar uuid Fl -uuid Ar uuid +.It Fl u Ar uuid | Fl -uuid Ar uuid Specify the UUID of the table to print. .El -.Pp .Sh HISTORY The .Nm diff --git a/usr.sbin/efitable/efitable.c b/usr.sbin/efitable/efitable.c index 0eee72801592..a506b4dea311 100644 --- a/usr.sbin/efitable/efitable.c +++ b/usr.sbin/efitable/efitable.c @@ -44,6 +44,7 @@ static void efi_table_print_esrt(const void *data); static void efi_table_print_prop(const void *data); +static void efi_table_print_memory(const void *data); static void usage(void) __dead2; struct efi_table_op { @@ -56,7 +57,9 @@ static const struct efi_table_op efi_table_ops[] = { { .name = "esrt", .parse = efi_table_print_esrt, .guid = EFI_TABLE_ESRT }, { .name = "prop", .parse = efi_table_print_prop, - .guid = EFI_PROPERTIES_TABLE } + .guid = EFI_PROPERTIES_TABLE }, + { .name = "memory", .parse = efi_table_print_memory, + .guid = EFI_MEMORY_ATTRIBUTES_TABLE } }; int @@ -239,6 +242,51 @@ efi_table_print_prop(const void *data) xo_err(EX_IOERR, "stdout"); } +static void +efi_table_print_memory(const void *data) +{ + const struct efi_memory_attribute_table *attr = + (const struct efi_memory_attribute_table *)data; + const struct efi_memory_descriptor *desc; + int i, nentries; + + nentries = attr->num_ents; + desc = attr->tables; + + xo_set_version(EFITABLE_XO_VERSION); + + xo_open_container("memory"); + xo_emit("{Lwc:Version}{:version/%#x}\n", attr->version); + xo_emit("{Lwc:Length}{:length/%u}\n", attr->descriptor_size); + xo_emit("{Lwc:Entries}{:entries/%u}\n", attr->num_ents); + + xo_open_container("attributes"); + + /* + * According to https://forum.osdev.org/viewtopic.php?t=32953, the size + * of records into the attribute table never equals to + * sizeof(efi_memory_descriptor). The correct one for indexing the array + * resides in the attributet table. + */ + for (i = 0; i < nentries; i++) { + xo_emit("{Lwc:ID}{:id/%#x}\n", i); + xo_emit("{Lwc:Attributes}{:attributes/%#x}\n", desc->attrs); + xo_emit("{Lwc:Type}{:type/%#x}\n", desc->type); + xo_emit("{Lwc:Pages}{:pages/%#x}\n", desc->pages); + xo_emit("{Lwc:Phyaddr}{:phyaddr/%#p}\n", desc->phy_addr); + xo_emit("{Lwc:Virtaddr}{:virtaddr/%#p}\n", desc->virt_addr); + desc = (const struct efi_memory_descriptor *)(const void *) + ((const char *)desc + attr->descriptor_size); + } + + xo_close_container("attributes"); + + xo_close_container("memory"); + + if (xo_finish() < 0) + xo_err(EX_IOERR, "stdout"); +} + static void usage(void) { xo_error("usage: efitable [-g guid | -t name] [--libxo]\n"); diff --git a/usr.sbin/fwget/Makefile b/usr.sbin/fwget/Makefile index 1cdf0f18230d..4c934aee3413 100644 --- a/usr.sbin/fwget/Makefile +++ b/usr.sbin/fwget/Makefile @@ -2,6 +2,6 @@ PACKAGE= fwget SCRIPTS= fwget MAN= fwget.8 -SUBDIR= pci +SUBDIR= pci usb .include <bsd.prog.mk> diff --git a/usr.sbin/fwget/fwget.8 b/usr.sbin/fwget/fwget.8 index 7b8b606cc591..86e304775e2d 100644 --- a/usr.sbin/fwget/fwget.8 +++ b/usr.sbin/fwget/fwget.8 @@ -23,7 +23,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 June 27, 2024 +.Dd July 7, 2025 .Dt FWGET 8 .Os .Sh NAME @@ -47,7 +47,11 @@ Dry run, only show needed packages .It Fl v Be more verbose .It Ar subsystem -Hardware subsystem, default pci +Hardware subsystem(s), default is all supported subsystems. +Space separated hardware subsystems, accepts +.Cm pci +and +.Cm usb .El .Sh SEE ALSO .Xr firmware 9 @@ -64,4 +68,8 @@ utility and this manual page were written by .An Emmanuel Vadot Aq Mt manu@FreeBSD.org for Beckhoff Automation GmbH & Co\. KG. .Sh CAVEATS -This utility currently only supports the pci subsystem. +This utility currently only supports the +.Xr pci 4 +and +.Xr usb 4 +subsystems. diff --git a/usr.sbin/fwget/fwget.sh b/usr.sbin/fwget/fwget.sh index 138a2a26bfb1..de1e6fa51f0f 100755 --- a/usr.sbin/fwget/fwget.sh +++ b/usr.sbin/fwget/fwget.sh @@ -35,7 +35,7 @@ usage() Usage: $(basename "$0") [options] [subsystem] Supported subsystems - pci + pci, usb Options: -n -- Do not install packages, only print the results @@ -100,9 +100,9 @@ done shift $(($OPTIND - 1)) subsystems="$@" -# Default searching PCI subsystem +# Default searching PCI and USB subsystem if [ -z "${subsystems}" ]; then - subsystems="pci" + subsystems="pci usb" fi # Fail early on unsupported subsystem diff --git a/usr.sbin/fwget/usb/Makefile b/usr.sbin/fwget/usb/Makefile new file mode 100644 index 000000000000..315e9c743cc8 --- /dev/null +++ b/usr.sbin/fwget/usb/Makefile @@ -0,0 +1,10 @@ +PACKAGE= fwget + +SCRIPTS=usb \ + usb_ralink + +BINDIR= ${LIBEXECDIR}/fwget + +MAN= + +.include <bsd.prog.mk> diff --git a/usr.sbin/fwget/usb/usb b/usr.sbin/fwget/usb/usb new file mode 100755 index 000000000000..fef6bc76ba89 --- /dev/null +++ b/usr.sbin/fwget/usb/usb @@ -0,0 +1,43 @@ +# +# Copyright 2023 Beckhoff Automation GmbH & Co. KG +# Copyright 2023 Bjoern A. Zeeb +# Copyright 2025 Jesper Schmitz Mouridsen + +# SPDX-License-Identifier: BSD-2-Clause + + +usb_get_vendor() +{ + local hexvendor=$(echo $1 | sed 's/.*idVendor=\(0x[0-9a-z]*\).*/\1/') + case "${hexvendor}" in + 0x148f) echo "ralink" ;; + esac +} + +usb_get_device() +{ + local hexdevice=$(echo $1 | sed 's/.*idProduct=\(0x[0-9a-z]*\).*/\1/') + echo "${hexdevice}" + +} + +usb_search_packages() +{ + local IFS + + oldifs=$IFS + IFS=$'\n' + for fulldevice in $(usbconfig -l dump_device_desc); do + vendor=$(usb_get_vendor "${fulldevice}") + if [ -z "${vendor}" ]; then + continue + fi + device=$(usb_get_device "${fulldevice}") + log_verbose "Trying to match device ${device} and vendor ${vendor} with usb_${vendor}" + if [ -f ${LIBEXEC_PATH}/usb_${vendor} ]; then + . ${LIBEXEC_PATH}/usb_${vendor} + usb_${vendor} ${device} + fi + done + IFS=${oldifs} +} diff --git a/usr.sbin/fwget/usb/usb_ralink b/usr.sbin/fwget/usb/usb_ralink new file mode 100755 index 000000000000..8d3135063011 --- /dev/null +++ b/usr.sbin/fwget/usb/usb_ralink @@ -0,0 +1,12 @@ +# +# Copyright (c) 2025 Jesper Schmitz Mouridsen +# +# SPDX-License-Identifier: BSD-2-Clause + +usb_ralink() +{ + + case "$1" in + 0x7601) addpkg "wifi-firmware-mt7601u-kmod"; return 1 ;; + esac +} diff --git a/usr.sbin/getfmac/getfmac.8 b/usr.sbin/getfmac/getfmac.8 index eb930e0044f9..6176bfa09271 100644 --- a/usr.sbin/getfmac/getfmac.8 +++ b/usr.sbin/getfmac/getfmac.8 @@ -51,5 +51,8 @@ specified files. .Xr mac 3 , .Xr mac_get_file 3 , .Xr mac 4 , +.Xr maclabel 7 , +.Xr getpmac 8 , .Xr setfmac 8 , +.Xr setpmac 8 , .Xr mac 9 diff --git a/usr.sbin/inetd/inetd.conf b/usr.sbin/inetd/inetd.conf index 40f1e1285af6..a8359ea793f5 100644 --- a/usr.sbin/inetd/inetd.conf +++ b/usr.sbin/inetd/inetd.conf @@ -7,8 +7,8 @@ # #ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l #ftp stream tcp6 nowait root /usr/libexec/ftpd ftpd -l -#ssh stream tcp nowait root /usr/sbin/sshd sshd -i -4 -#ssh stream tcp6 nowait root /usr/sbin/sshd sshd -i -6 +#ssh stream tcp nowait root /usr/sbin/sshd sshd -i +#ssh stream tcp6 nowait root /usr/sbin/sshd sshd -i #telnet stream tcp nowait root /usr/local/libexec/telnetd telnetd #telnet stream tcp6 nowait root /usr/local/libexec/telnetd telnetd #shell stream tcp nowait root /usr/local/sbin/rshd rshd diff --git a/usr.sbin/lastlogin/lastlogin.8 b/usr.sbin/lastlogin/lastlogin.8 index 3b2d47fdaf76..9fd5c88d02cd 100644 --- a/usr.sbin/lastlogin/lastlogin.8 +++ b/usr.sbin/lastlogin/lastlogin.8 @@ -73,7 +73,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 for details on command line arguments. .It Fl f Ar file Open last login database @@ -93,7 +93,7 @@ last login database .Xr last 1 , .Xr getutxent 3 , .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr ac 8 .Sh AUTHORS .An -nosplit diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c index 4efcd20ad91a..c0fcadf11fba 100644 --- a/usr.sbin/makefs/ffs.c +++ b/usr.sbin/makefs/ffs.c @@ -1056,7 +1056,7 @@ ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap) reclen = DIRSIZ_SWAP(0, &de, needswap); de.d_reclen = ufs_rw16(reclen, needswap); - dp = (struct direct *)(dbuf->buf + dbuf->cur); + dp = dbuf->buf == NULL ? NULL : (struct direct *)(dbuf->buf + dbuf->cur); llen = 0; if (dp != NULL) llen = DIRSIZ_SWAP(0, dp, needswap); diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8 index a11eaf8206e9..d20f69d87559 100644 --- a/usr.sbin/makefs/makefs.8 +++ b/usr.sbin/makefs/makefs.8 @@ -33,8 +33,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 19, 2024 - +.Dd July 19, 2025 .Dt MAKEFS 8 .Os .Sh NAME @@ -551,6 +550,12 @@ This option allows the default heuristic to be overridden. .It verify-txgs Prompt OpenZFS to verify pool metadata during import. This is disabled by default as it may significantly increase import times. +.It poolguid +Use the specified 64-bit integer as the pool GUID. +If this option is not specified, the pool GUID will be random but fixed +across multiple identical invocations of +.Nm . +This option is useful for testing but not required for reproducibility. .It poolname The name of the ZFS pool. This option must be specified. @@ -596,10 +601,17 @@ The following properties may be set for a dataset: .Bl -tag -compact -offset indent .It atime .It canmount +.It compression .It exec .It mountpoint .It setuid .El +Note that +.Nm +does not implement compression of files included in the image, +regardless of the value of the +.Dv compression +property. .El .Sh SEE ALSO .Xr mtree 5 , diff --git a/usr.sbin/makefs/tests/Makefile b/usr.sbin/makefs/tests/Makefile index 345b728651d6..748bafa06211 100644 --- a/usr.sbin/makefs/tests/Makefile +++ b/usr.sbin/makefs/tests/Makefile @@ -7,10 +7,6 @@ ATF_TESTS_SH+= makefs_msdos_tests TEST_METADATA.makefs_msdos_tests+= required_files="/sbin/mount_msdosfs" .if ${MK_ZFS} != "no" ATF_TESTS_SH+= makefs_zfs_tests -# ZFS pools created by makefs always have the same GUID, so OpenZFS -# refuses to import more than one at a time. Thus the ZFS tests cannot -# be run in parallel for now. -TEST_METADATA.makefs_zfs_tests+= is_exclusive="true" .endif BINDIR= ${TESTSDIR} diff --git a/usr.sbin/makefs/tests/makefs_msdos_tests.sh b/usr.sbin/makefs/tests/makefs_msdos_tests.sh index b36b43b3abf6..fb94429b477b 100644 --- a/usr.sbin/makefs/tests/makefs_msdos_tests.sh +++ b/usr.sbin/makefs/tests/makefs_msdos_tests.sh @@ -4,7 +4,7 @@ # Copyright (c) 2025 The FreeBSD Foundation # # This software was developed by Klara, Inc. -# under sponsorship from the FreeBSD Foundation and the Sovereign Tech Agency. +# 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 are diff --git a/usr.sbin/makefs/tests/makefs_zfs_tests.sh b/usr.sbin/makefs/tests/makefs_zfs_tests.sh index 520d1f211ac3..2fafce85b347 100644 --- a/usr.sbin/makefs/tests/makefs_zfs_tests.sh +++ b/usr.sbin/makefs/tests/makefs_zfs_tests.sh @@ -28,7 +28,7 @@ # SUCH DAMAGE. # -MAKEFS="makefs -t zfs -o verify-txgs=true" +MAKEFS="makefs -t zfs -o verify-txgs=true -o poolguid=$$" ZFS_POOL_NAME="makefstest$$" TEST_ZFS_POOL_NAME="$TMPDIR/poolname" @@ -124,6 +124,95 @@ basic_cleanup() common_cleanup } +# +# Try configuring various compression algorithms. +# +atf_test_case compression cleanup +compression_body() +{ + create_test_inputs + + cd $TEST_INPUTS_DIR + mkdir dir + mkdir dir2 + cd - + + for alg in off on lzjb gzip gzip-1 gzip-2 gzip-3 gzip-4 \ + gzip-5 gzip-6 gzip-7 gzip-8 gzip-9 zle lz4 zstd; do + atf_check $MAKEFS -s 1g -o rootpath=/ \ + -o poolname=$ZFS_POOL_NAME \ + -o fs=${ZFS_POOL_NAME}\;compression=$alg \ + -o fs=${ZFS_POOL_NAME}/dir \ + -o fs=${ZFS_POOL_NAME}/dir2\;compression=off \ + $TEST_IMAGE $TEST_INPUTS_DIR + + import_image + + check_image_contents + + if [ $alg = gzip-6 ]; then + # ZFS reports gzip-6 as just gzip since it uses + # a default compression level of 6. + alg=gzip + fi + # The "dir" dataset's compression algorithm should be + # inherited from the root dataset. + atf_check -o inline:$alg\\n -e empty -s exit:0 \ + zfs get -H -o value compression ${ZFS_POOL_NAME} + atf_check -o inline:$alg\\n -e empty -s exit:0 \ + zfs get -H -o value compression ${ZFS_POOL_NAME}/dir + atf_check -o inline:off\\n -e empty -s exit:0 \ + zfs get -H -o value compression ${ZFS_POOL_NAME}/dir2 + + atf_check -e ignore dd if=/dev/random \ + of=${TEST_MOUNT_DIR}/dir/random bs=1M count=10 + atf_check -e ignore dd if=/dev/zero \ + of=${TEST_MOUNT_DIR}/dir/zero bs=1M count=10 + atf_check -e ignore dd if=/dev/zero \ + of=${TEST_MOUNT_DIR}/dir2/zero bs=1M count=10 + + # Export and reimport to ensure that everything is + # flushed to disk. + atf_check zpool export ${ZFS_POOL_NAME} + atf_check -o ignore -e empty -s exit:0 \ + zdb -e -p /dev/$(cat $TEST_MD_DEVICE_FILE) -mmm -ddddd \ + $ZFS_POOL_NAME + atf_check zpool import -R $TEST_MOUNT_DIR $ZFS_POOL_NAME + + if [ $alg = off ]; then + # If compression is off, the files should be the + # same size as the input. + atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/random" \ + du -m ${TEST_MOUNT_DIR}/dir/random + atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/zero" \ + du -m ${TEST_MOUNT_DIR}/dir/zero + atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir2/zero" \ + du -m ${TEST_MOUNT_DIR}/dir2/zero + else + # If compression is on, the dir/zero file ought + # to be smaller. + atf_check -o match:"^1[[:space:]]+${TEST_MOUNT_DIR}/dir/zero" \ + du -m ${TEST_MOUNT_DIR}/dir/zero + atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/random" \ + du -m ${TEST_MOUNT_DIR}/dir/random + atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir2/zero" \ + du -m ${TEST_MOUNT_DIR}/dir2/zero + fi + + atf_check zpool destroy ${ZFS_POOL_NAME} + atf_check rm -f ${TEST_ZFS_POOL_NAME} + atf_check mdconfig -d -u $(cat ${TEST_MD_DEVICE_FILE}) + atf_check rm -f ${TEST_MD_DEVICE_FILE} + done +} +compression_cleanup() +{ + common_cleanup +} + +# +# Try destroying a dataset that was created by makefs. +# atf_test_case dataset_removal cleanup dataset_removal_body() { @@ -939,6 +1028,7 @@ atf_init_test_cases() { atf_add_test_case autoexpand atf_add_test_case basic + atf_add_test_case compression atf_add_test_case dataset_removal atf_add_test_case devfs atf_add_test_case empty_dir diff --git a/usr.sbin/makefs/zfs.c b/usr.sbin/makefs/zfs.c index 66e7f8dafc9c..8d50c450541b 100644 --- a/usr.sbin/makefs/zfs.c +++ b/usr.sbin/makefs/zfs.c @@ -38,6 +38,7 @@ #include <stdalign.h> #include <stdbool.h> #include <stddef.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -85,6 +86,8 @@ zfs_prep_opts(fsinfo_t *fsopts) 0, 0, "Bootable dataset" }, { '\0', "mssize", &zfs->mssize, OPT_INT64, MINMSSIZE, MAXMSSIZE, "Metaslab size" }, + { '\0', "poolguid", &zfs->poolguid, OPT_INT64, + 0, INT64_MAX, "ZFS pool GUID" }, { '\0', "poolname", &zfs->poolname, OPT_STRPTR, 0, 0, "ZFS pool name" }, { '\0', "rootpath", &zfs->rootpath, OPT_STRPTR, @@ -547,7 +550,8 @@ pool_init(zfs_opt_t *zfs) { uint64_t dnid; - zfs->poolguid = randomguid(); + if (zfs->poolguid == 0) + zfs->poolguid = randomguid(); zfs->vdevguid = randomguid(); zfs->mos = objset_alloc(zfs, DMU_OST_META); diff --git a/usr.sbin/makefs/zfs/dsl.c b/usr.sbin/makefs/zfs/dsl.c index f7264b9d2ca7..8a8cee7c82b2 100644 --- a/usr.sbin/makefs/zfs/dsl.c +++ b/usr.sbin/makefs/zfs/dsl.c @@ -193,6 +193,39 @@ dsl_dir_set_prop(zfs_opt_t *zfs, zfs_dsl_dir_t *dir, const char *key, nvlist_add_uint64(nvl, key, 0); else errx(1, "invalid value `%s' for %s", val, key); + } else if (strcmp(key, "compression") == 0) { + size_t i; + + const struct zfs_compression_algorithm { + const char *name; + enum zio_compress alg; + } compression_algorithms[] = { + { "off", ZIO_COMPRESS_OFF }, + { "on", ZIO_COMPRESS_ON }, + { "lzjb", ZIO_COMPRESS_LZJB }, + { "gzip", ZIO_COMPRESS_GZIP_6 }, + { "gzip-1", ZIO_COMPRESS_GZIP_1 }, + { "gzip-2", ZIO_COMPRESS_GZIP_2 }, + { "gzip-3", ZIO_COMPRESS_GZIP_3 }, + { "gzip-4", ZIO_COMPRESS_GZIP_4 }, + { "gzip-5", ZIO_COMPRESS_GZIP_5 }, + { "gzip-6", ZIO_COMPRESS_GZIP_6 }, + { "gzip-7", ZIO_COMPRESS_GZIP_7 }, + { "gzip-8", ZIO_COMPRESS_GZIP_8 }, + { "gzip-9", ZIO_COMPRESS_GZIP_9 }, + { "zle", ZIO_COMPRESS_ZLE }, + { "lz4", ZIO_COMPRESS_LZ4 }, + { "zstd", ZIO_COMPRESS_ZSTD }, + }; + for (i = 0; i < nitems(compression_algorithms); i++) { + if (strcmp(val, compression_algorithms[i].name) == 0) { + nvlist_add_uint64(nvl, key, + compression_algorithms[i].alg); + break; + } + } + if (i == nitems(compression_algorithms)) + errx(1, "invalid compression algorithm `%s'", val); } else { errx(1, "unknown property `%s'", key); } @@ -236,9 +269,6 @@ dsl_init(zfs_opt_t *zfs) zfs->rootdsldir = dsl_dir_alloc(zfs, NULL); - nvlist_add_uint64(zfs->rootdsldir->propsnv, "compression", - ZIO_COMPRESS_OFF); - zfs->rootds = dsl_dataset_alloc(zfs, zfs->rootdsldir); zfs->rootdsldir->headds = zfs->rootds; @@ -288,9 +318,13 @@ dsl_init(zfs_opt_t *zfs) } /* - * Set the root dataset's mount point if the user didn't override the - * default. + * Set the root dataset's mount point and compression strategy if the + * user didn't override the defaults. */ + if (nvpair_find(zfs->rootdsldir->propsnv, "compression") == NULL) { + nvlist_add_uint64(zfs->rootdsldir->propsnv, "compression", + ZIO_COMPRESS_OFF); + } if (nvpair_find(zfs->rootdsldir->propsnv, "mountpoint") == NULL) { nvlist_add_string(zfs->rootdsldir->propsnv, "mountpoint", zfs->rootpath); diff --git a/usr.sbin/sesutil/sesutil.8 b/usr.sbin/sesutil/sesutil.8 index 664dcab593e9..d4960b3ec6bf 100644 --- a/usr.sbin/sesutil/sesutil.8 +++ b/usr.sbin/sesutil/sesutil.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 5, 2022 +.Dd July 16, 2025 .Dt SESUTIL 8 .Os .Sh NAME @@ -129,7 +129,7 @@ Generate output via .Xr libxo 3 in a selection of different human and machine readable formats. See -.Xr xo_parse_args 3 +.Xr xo_options 7 .El .Sh EXAMPLES Turn off all locate LEDs: @@ -146,7 +146,7 @@ Turn on the fault LED for a drive bay not associated with a device: .Dl Nm Cm fault -u /dev/ses2 7 on .Sh SEE ALSO .Xr libxo 3 , -.Xr xo_parse_args 3 , +.Xr xo_options 7 , .Xr ses 4 .Sh HISTORY The diff --git a/usr.sbin/trim/trim.8 b/usr.sbin/trim/trim.8 index 1ac10d7e3d46..a4874c54c183 100644 --- a/usr.sbin/trim/trim.8 +++ b/usr.sbin/trim/trim.8 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 18, 2019 +.Dd July 20, 2025 .Dt TRIM 8 .Os .Sh NAME @@ -36,7 +36,7 @@ .Bk -words .Sm off .Ar offset -.Op Cm K | k | M | m | G | g | T | t ] +.Op Cm K | k | M | m | G | g | T | t | P | p | E | e ] .Sm on .Xc .Ek @@ -68,13 +68,13 @@ Overrides .It Fl l Xo .Sm off .Ar offset -.Op Cm K | k | M | m | G | g | T | t +.Op Cm K | k | M | m | G | g | T | t | P | p | E | e .Sm on .Xc .It Fl o Xo .Sm off .Ar offset -.Op Cm K | k | M | m | G | g | T | t +.Op Cm K | k | M | m | G | g | T | t | P | p | E | e .Sm on .Xc Specify the length @@ -88,12 +88,14 @@ unless one or both of these options are presented. The argument may be suffixed with one of .Cm K , .Cm M , -.Cm G +.Cm G , +.Cm T , +.Cm P or -.Cm T +.Cm E (either upper or lower case) to indicate a multiple of -Kilobytes, Megabytes, Gigabytes or Terabytes -respectively. +Kilobytes, Megabytes, Gigabytes, Terabytes, Petabytes or +Exabytes, respectively. .It Fl q Do not output anything except of possible error messages (quiet mode). Overrides diff --git a/usr.sbin/trim/trim.c b/usr.sbin/trim/trim.c index 3e187faa0fb3..27f57ac2fb72 100644 --- a/usr.sbin/trim/trim.c +++ b/usr.sbin/trim/trim.c @@ -114,7 +114,7 @@ main(int argc, char **argv) * * trim -f -- /dev/da0 -r rfile */ - + if (strcmp(argv[optind-1], "--") != 0) { for (ch = optind; ch < argc; ch++) if (argv[ch][0] == '-') @@ -127,6 +127,9 @@ main(int argc, char **argv) if (argc < 1) usage(name); + if (dryrun) + printf("dry run: add -f to actually perform the operation\n"); + while ((fname = *argv++) != NULL) if (trim(fname, offset, length, dryrun, verbose) < 0) error++; @@ -213,10 +216,8 @@ trim(const char *path, off_t offset, off_t length, bool dryrun, bool verbose) printf("trim %s offset %ju length %ju\n", path, (uintmax_t)offset, (uintmax_t)length); - if (dryrun) { - printf("dry run: add -f to actually perform the operation\n"); + if (dryrun) return (0); - } fd = opendev(path, O_RDWR | O_DIRECT); arg[0] = offset; @@ -237,7 +238,7 @@ static void usage(const char *name) { (void)fprintf(stderr, - "usage: %s [-[lo] offset[K|k|M|m|G|g|T|t]] [-r rfile] [-Nfqv] device ...\n", + "usage: %s [-[lo] offset[K|k|M|m|G|g|T|t|P|p|E|e]] [-r rfile] [-Nfqv] device ...\n", name); exit(EX_USAGE); } |