diff options
932 files changed, 20435 insertions, 6034 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, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e79652a09d2..02d718ef8018 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,9 +33,10 @@ and need discussion, or changes that require specialized review. A pull request will be considered if: +* The request is substantive in nature. We generally don't accept minor or cosmetic changes unless they are part of larger work in that area. Pull requests should solve a real, actual problem. * It is ready or nearly ready to be committed. A committer should be able to land the pull request with less than 10 minutes of additional work. * It passes all the GitHub CI jobs. -* You can respond to feedback quickly. +* You can respond to feedback quickly. If feedback is requested and one month passes without a response we may close the pull request. * It touches fewer than about 10 files and the changes are less than about 200 lines. Changes larger than this may be OK, or you may be asked to submit multiple pull requests of a more manageable size. * Each logical change is a separate commit within the pull request. Commit messages for each change should follow the [commit log message guide](https://docs.freebsd.org/en/articles/committers-guide/#commit-log-message). * All commits have, as the author, your name and valid email address as you would like to see them in the FreeBSD repository. Fake github.com addresses cannot be used. @@ -43,11 +44,14 @@ A pull request will be considered if: * Fixup commits should be squashed with the commit they are fixing. Each commit in your branch should be suitable for FreeBSD's repository. * Commits should include one or more `Signed-off-by:` lines with full name and email address certifying [Developer Certificate of Origin](https://developercertificate.org/). * The commits follow FreeBSD's style guide. See [Style](#Style). -* Run tools/build/checkstyle9.pl on your Git branch and eliminate all errors. +* Run tools/build/checkstyle9.pl on your Git branch and eliminate all errors, or provide an explanation for exceptions. * The commits do not introduce trailing white space. -* If the commit fixes a bug, please add 'PR: \<bugnumber\>' to the commit message. -* If there's a code review in Phabricator, please include a link as a 'Differential Revision: ' line. +* If the commit fixes a bug, please add 'PR: \<bugnumber\>' to the commit message to document the Bugzilla Problem Report number. +* If there's a code review related to this change, please include its URL in the commit message. However, where possible, please do not open both a differential review and a GitHub pull request. * If you have run FreeBSD's sources through a static analysis tool, please don't submit the raw results. Please also see the chunking up guidelines. Also, please make sure that kyua tests are the same before / after your change. Ideally, you'd also create a test case that shows an actual bug that's being fixed by these changes. +* FreeBSD committers submitting pull requests are responsible for pushing them into the tree (possibly with approval if cross-repo commit bit policy needs it). Pull requests by FreeBSD committers will be closed after a month unless there's a very good reason not to. +* Submissions using generative AI will be rejected. +* Submissions from AI chatbots will result in the account being banned. When updating your pull request, please rebase with a forced push rather than a merge commit. @@ -70,7 +74,8 @@ so. While the project strives to have a uniform coding style, our style offers a range of choices making some 'cleanups' ambiguous at best. Also, some files have their own consistent style that deviates from style(9). Style changes take volunteer time to process, but that time can be quite limited, so please be -respectful. +respectful. Trivial spelling changes should generally not be made in isolation +as they usually add little value, but do take up valuable volunteer time. The current theory for pull requests on GitHub is to facilitate inclusion in the project. The guidelines are streamlined for quick decisions about each pull @@ -90,7 +95,8 @@ closing it. We require that contributions are associated with a unique identity. The author email address should not be `<something>@users.noreply.github.com`. Do note that your name and email address will become a permanent and immutable -part of the public Git history of the FreeBSD source tree. +part of the public Git history of the FreeBSD source tree. Authors that use +pseudonyms will be considered on a case by case basis. ## Style @@ -128,7 +134,7 @@ not present in FreeBSD's [shell](https://man.freebsd.org/cgi/man.cgi?query=sh&se ## Signed-off-by -Other projects use Signed-off-by to create a paper trail for contributions they +Other projects mandate Signed-off-by to create a paper trail for contributions they receive. The Developer Certificate of Origin is an attestation that the person making the contribution can do it under the current license of the file. Other projects that have 'delegated' hierarchies also use it when maintainers @@ -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..f1e230f91e95 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,69 @@ # xargs -n1 | sort | uniq -d; # done +# 20250726: MIT KRB5 DSO bump +OLD_LIBS+=usr/lib/libcom_err.so.121 +OLD_LIBS+=usr/lib/libgssapi_krb5.so.121 +OLD_LIBS+=usr/lib/libgssrpc.so.121 +OLD_LIBS+=usr/lib/libk5crypto.so.121 +OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5srv_mit.so.121 +OLD_LIBS+=usr/lib/libkdb5.so.121 +OLD_LIBS+=usr/lib/libkrad.so.121 +OLD_LIBS+=usr/lib/libkrb5.so.121 +OLD_LIBS+=usr/lib/libkrb5profile.so.121 +OLD_LIBS+=usr/lib/libkrb5support.so.121 +OLD_LIBS+=usr/lib/libverto.so.121 +OLD_LIBS+=usr/lib/libcom_err.so.121 +OLD_LIBS+=usr/lib/libgssapi_krb5.so.121 +OLD_LIBS+=usr/lib/libgssrpc.so.121 +OLD_LIBS+=usr/lib/libk5crypto.so.121 +OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5srv_mit.so.121 +OLD_LIBS+=usr/lib/libkdb5.so.121 +OLD_LIBS+=usr/lib/libkrad.so.121 +OLD_LIBS+=usr/lib/libkrb5.so.121 +OLD_LIBS+=usr/lib/libkrb5profile.so.121 +OLD_LIBS+=usr/lib/libkrb5support.so.121 +OLD_LIBS+=usr/lib/libverto.so.121 + +# 20250726: xargs tests rewritten +OLD_FILES+=usr/tests/usr.bin/xargs/legacy_test +OLD_FILES+=usr/tests/usr.bin/xargs/regress.n2147483647.out +OLD_FILES+=usr/tests/usr.bin/xargs/regress.sh + +# 20250726: This file is now installed in /etc/dma +OLD_FILES+=usr/share/examples/dma/auth.conf + +# 20250725: libbsnmp bumped to version 7 +OLD_LIBS+=usr/lib/libbsnmp.so.6 + +# 20250725: Files which were briefly installed by WITH_MITKRB5 in 15.0. +OLD_FILES+=usr/include/kadm5/admin_internal.h +OLD_FILES+=usr/include/kadm5/admin_xdr.h +OLD_FILES+=usr/include/kadm5/kadm_rpc.h +OLD_FILES+=usr/include/kadm5/server_internal.h +OLD_FILES+=usr/include/internal.h +OLD_FILES+=usr/include/t_daemon.h +OLD_FILES+=usr/include/t_test.h +OLD_FILES+=usr/include/dyn.h +OLD_FILES+=usr/include/dynP.h +OLD_FILES+=usr/include/gssrpcint.h +OLD_FILES+=usr/include/import_err.h +OLD_FILES+=usr/share/man/man3/db_btree.3.gz +OLD_FILES+=usr/share/man/man3/db_hash.3.gz +OLD_FILES+=usr/share/man/man3/db_lock.3.gz +OLD_FILES+=usr/share/man/man3/db_log.3.gz +OLD_FILES+=usr/share/man/man3/db_mpool.3.gz +OLD_FILES+=usr/share/man/man3/db_open.3.gz +OLD_FILES+=usr/share/man/man3/db_recno.3.gz +OLD_FILES+=usr/share/man/man3/db_txn.3.gz +OLD_FILES+=usr/share/man/man5/profile.5.gz +OLD_FILES+=usr/share/man/man8/kamdin.local.8.gz + +# 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,18 @@ newline. Entries should be separated by a newline. Changes to this file should not be MFCed. +9ba51cce8bbd: + bsnmpd(1) no longer supports legacy UDP transport. Users, that have + not updated their /etc/snmpd.config since 12.0-RELEASE or older will + need to merge in the new configuration. In particular, the transport + definition shall be changed from begemotSnmpdPortStatus OID to + begemotSnmpdTransInetStatus. + +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,40 @@ 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".) +20250727: + LLVM's debugging assertions are now disabled in main by default. + The WITH_LLVM_ASSERTIONS src.conf(5) knob should be used to + enable it when working on LLVM or requesting help with it. + +20250726: + amd64 kernel configurations must contain "options SMP". + +20250725: + gssd(8) has been moved to a new package, FreeBSD-gssd. If you use + pkgbase and you need gssd, you should install this package. + +20250724: + The Kerberos packages which are built when WITH_MITKRB5 is enabled + have been renamed from FreeBSD-krb5* to FreeBSD-kerberos*. This + affects pkgbase users who manually enabled WITH_MITKRB5, *or* use + the default value of WITH_MITKRB5 and updated past c7da9fb90b0b + (20250721) which made WITH_MITKRB5 the default. + + In either case, if you have FreeBSD-krb5* packages installed, you + should remove them and (re)install the equivalent FreeBSD-kerberos* + packages instead. + +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 7a98baf39776..da8cbd9ffe50 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 +++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 @@ -20,7 +20,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 12, 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 @@ -1223,17 +1269,21 @@ Invalid command line options or arguments were specified. .Xr cpp 1 , .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 , .Xr dtrace_udp 4 , .Xr dtrace_udplite 4 , .Xr elf 5 , +.Xr d 7 , .Xr tracing 7 , .Xr SDT 9 .Rs 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/bsnmpclient.3 b/contrib/bsnmp/lib/bsnmpclient.3 index 0a2286eb14c4..1a5aa2e5e3a6 100644 --- a/contrib/bsnmp/lib/bsnmpclient.3 +++ b/contrib/bsnmp/lib/bsnmpclient.3 @@ -31,7 +31,7 @@ .\" .\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.12 2005/10/04 08:46:50 brandt_h Exp $ .\" -.Dd March 31, 2020 +.Dd June 24, 2025 .Dt BSNMPCLIENT 3 .Os .Sh NAME @@ -155,7 +155,7 @@ struct snmp_client { snmp_timeout_start_f timeout_start; snmp_timeout_stop_f timeout_stop; - char local_path[sizeof(SNMP_LOCAL_PATH)]; + char local_path[SUNPATHLEN]; }; .Ed .Pp @@ -285,8 +285,19 @@ The function will be called with the return value of the corresponding .Fn timeout_start function. .It Va local_path -If in local socket mode, the name of the clients socket. -Not needed by the application. +In local socket mode, optional path name the client socket shall be bound to +before connecting to the server. +For +.Dv SOCK_STREAM +local socket the named path is optional, and library will skip +.Xr bind 2 +if path is not provided. +For +.Dv SOCK_DGRAM +local socket the named path is required, thus library will create a random +one in +.Pa /tmp +if path is not provided. .El .Pp In the current implementation there is a global variable diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c index b312a37ed3ed..44dfbd5a06b1 100644 --- a/contrib/bsnmp/lib/snmpclient.c +++ b/contrib/bsnmp/lib/snmpclient.c @@ -977,18 +977,15 @@ remove_local(void) static int open_client_local(const char *path) { - struct sockaddr_un sa; + struct sockaddr_un sa = { + .sun_family = AF_LOCAL, + .sun_len = sizeof(sa), + }; 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)); @@ -1009,43 +1006,56 @@ open_client_local(const char *path) return (-1); } - snprintf(snmp_client.local_path, sizeof(snmp_client.local_path), - "%s", SNMP_LOCAL_PATH); - - if (mkstemp(snmp_client.local_path) == -1) { - seterr(&snmp_client, "%s", strerror(errno)); - (void)close(snmp_client.fd); - snmp_client.fd = -1; - return (-1); + /* + * A datagram socket requires a name to receive replies back. Would + * be cool to have an extension to unix(4) sockets similar to ip(4) + * IP_RECVDSTADDR/IP_SENDSRCADDR, so that a one-to-many datagram + * UNIX socket can send replies to its anonymous peers. + */ + if (snmp_client.trans == SNMP_TRANS_LOC_DGRAM && + snmp_client.local_path[0] == '\0') { + (void)strlcpy(snmp_client.local_path, "/tmp/snmpXXXXXXXXXXXXXX", + sizeof(snmp_client.local_path)); + if (mktemp(snmp_client.local_path) == NULL) { + seterr(&snmp_client, "mktemp(3): %s", strerror(errno)); + goto fail; + } } - sa.sun_family = AF_LOCAL; - sa.sun_len = sizeof(sa); - strcpy(sa.sun_path, snmp_client.local_path); - - if (bind(snmp_client.fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { - seterr(&snmp_client, "%s", strerror(errno)); - (void)close(snmp_client.fd); - snmp_client.fd = -1; - (void)remove(snmp_client.local_path); - return (-1); + if (snmp_client.local_path[0] != '\0') { + if (strlcpy(sa.sun_path, snmp_client.local_path, + sizeof(sa.sun_path)) >= + sizeof(sa.sun_path)) { + seterr(&snmp_client, "%s", + "Local socket pathname too long"); + goto fail; + } + if (bind(snmp_client.fd, (struct sockaddr *)&sa, sizeof(sa)) == + -1) { + seterr(&snmp_client, "%s", strerror(errno)); + goto fail; + } + atexit(remove_local); } - atexit(remove_local); - sa.sun_family = AF_LOCAL; - sa.sun_len = offsetof(struct sockaddr_un, sun_path) + - strlen(snmp_client.chost); - strncpy(sa.sun_path, snmp_client.chost, sizeof(sa.sun_path) - 1); - sa.sun_path[sizeof(sa.sun_path) - 1] = '\0'; + if (strlcpy(sa.sun_path, snmp_client.chost, sizeof(sa.sun_path)) >= + sizeof(sa.sun_path)) { + seterr(&snmp_client, "%s", "Server socket pathname too long"); + goto fail; + } if (connect(snmp_client.fd, (struct sockaddr *)&sa, sa.sun_len) == -1) { seterr(&snmp_client, "%s", strerror(errno)); - (void)close(snmp_client.fd); - snmp_client.fd = -1; - (void)remove(snmp_client.local_path); - return (-1); + goto fail; } return (0); + +fail: + (void)close(snmp_client.fd); + snmp_client.fd = -1; + if (snmp_client.local_path[0] != '\0') + (void)remove(snmp_client.local_path); + return (-1); } /* @@ -1932,70 +1942,64 @@ get_transp(struct snmp_client *sc, const char **strp) * community strings are legal. * * \param sc client struct to set errors - * \param strp possible start of community; updated to the point to - * the next character to parse + * \param comm possible start of community; updated to start & end * - * \return end of community; equals *strp if there is none; NULL if there - * was an error + * \return the next character to parse; NULL if there was an error */ static inline const char * -get_comm(struct snmp_client *sc, const char **strp) +get_comm(struct snmp_client *sc, const char *comm[2]) { - const char *p = strrchr(*strp, '@'); + const char *p = strrchr(comm[0], '@'); if (p == NULL) /* no community string */ - return (*strp); + return (comm[1] = comm[0]); - if (p - *strp > SNMP_COMMUNITY_MAXLEN) { + if (p - comm[0] > SNMP_COMMUNITY_MAXLEN) { seterr(sc, "community string too long '%.*s'", - p - *strp, *strp); + p - comm[0], comm[0]); return (NULL); } - *strp = p + 1; - return (p); + return ((comm[1] = p) + 1); } /** * Try to get an IPv6 address. This starts with an [ and should end with an ] * and everything between should be not longer than INET6_ADDRSTRLEN and - * parseable by inet_pton(). + * parseable by getaddrinfo(). * * \param sc client struct to set errors - * \param strp possible start of IPv6 address (the '['); updated to point to - * the next character to parse (the one after the closing ']') + * \param ipv6 possible start of IPv6 address (the '['); updated to actual + * start (one after '[') and actual end (the '[' itself) * - * \return end of address (equals *strp + 1 if there is none) or NULL - * on errors + * \return the next character to parse (the one after the closing ']') + * or NULL on errors */ static inline const char * -get_ipv6(struct snmp_client *sc, const char **strp) +get_ipv6(struct snmp_client *sc, const char *ipv6[2]) { - char str[INET6_ADDRSTRLEN + IF_NAMESIZE]; + char str[INET6_ADDRSTRLEN]; + const char *p; struct addrinfo hints, *res; int error; - if (**strp != '[') - return (*strp + 1); + if (ipv6[0][0] != '[') + return (ipv6[1] = ipv6[0]); - const char *p = *strp + 1; - while (*p != ']' ) { - if (*p == '\0') { - seterr(sc, "unterminated IPv6 address '%.*s'", - p - *strp, *strp); - return (NULL); - } - p++; + if ((p = strchr(++(ipv6[0]), ']')) == NULL) { + seterr(sc, "unterminated IPv6 address '%s'", ipv6[0]); + return (NULL); } - if (p - *strp > INET6_ADDRSTRLEN + IF_NAMESIZE) { - seterr(sc, "IPv6 address too long '%.*s'", p - *strp, *strp); + if ((size_t)(p - ipv6[0]) >= sizeof(str)) { + seterr(sc, "IPv6 address too long '%.*s'", + p - ipv6[0], ipv6[0]); return (NULL); } - strncpy(str, *strp + 1, p - (*strp + 1)); - str[p - (*strp + 1)] = '\0'; + strncpy(str, ipv6[0], p - ipv6[0]); + str[p - ipv6[0]] = '\0'; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST; @@ -2008,8 +2012,7 @@ get_ipv6(struct snmp_client *sc, const char **strp) return (NULL); } freeaddrinfo(res); - *strp = p + 1; - return (p); + return ((ipv6[1] = p) + 1); } /** @@ -2018,30 +2021,29 @@ get_ipv6(struct snmp_client *sc, const char **strp) * inet_aton(). * * \param sc client struct to set errors - * \param strp possible start of IPv4 address; updated to point to the - * next character to parse + * \param ipv4 possible start of IPv4 address; updated to start & end * - * \return end of address (equals *strp if there is none) or NULL - * on errors + * \return the next character to parse; or NULL on errors */ static inline const char * -get_ipv4(struct snmp_client *sc, const char **strp) +get_ipv4(struct snmp_client *sc, const char *ipv4[2]) { - const char *p = *strp; + char str[INET_ADDRSTRLEN]; + const char *p = ipv4[0]; while (isascii(*p) && (isdigit(*p) || *p == '.')) p++; - if (p - *strp > INET_ADDRSTRLEN) { - seterr(sc, "IPv4 address too long '%.*s'", p - *strp, *strp); + if ((size_t)(p - ipv4[0]) >= sizeof(str)) { + seterr(sc, "IPv4 address too long '%.*s'", + p - ipv4[0], ipv4[0]); return (NULL); } - if (*strp == p) - return *strp; + if (p == ipv4[0]) + return (ipv4[1] = ipv4[0]); - char str[INET_ADDRSTRLEN + 1]; - strncpy(str, *strp, p - *strp); - str[p - *strp] = '\0'; + strncpy(str, ipv4[0], p - ipv4[0]); + str[p - ipv4[0]] = '\0'; struct in_addr addr; if (inet_aton(str, &addr) != 1) { @@ -2049,8 +2051,7 @@ get_ipv4(struct snmp_client *sc, const char **strp) return (NULL); } - *strp = p; - return (p); + return (ipv4[1] = p); } /** @@ -2058,24 +2059,19 @@ get_ipv4(struct snmp_client *sc, const char **strp) * the last colon (if any). There is no length restriction. * * \param sc client struct to set errors - * \param strp possible start of hostname; updated to point to the next - * character to parse (the trailing NUL character or the last - * colon) + * \param host possible start of hostname; start & end updated * - * \return end of address (equals *strp if there is none) + * \return next character to parse (semicolon or NUL) */ static inline const char * -get_host(struct snmp_client *sc __unused, const char **strp) +get_host(struct snmp_client *sc __unused, const char *host[2]) { - const char *p = strrchr(*strp, ':'); + const char *p = strrchr(host[0], ':'); - if (p == NULL) { - *strp += strlen(*strp); - return (*strp); - } + if (p == NULL) + return (host[1] = host[0] + strlen(host[0])); - *strp = p; - return (p); + return (host[1] = p); } /** @@ -2083,25 +2079,24 @@ get_host(struct snmp_client *sc __unused, const char **strp) * of string. The port number must not be empty. * * \param sc client struct to set errors - * \param strp possible start of port specification; if this points to a + * \param port possible start of port specification; if this points to a * colon there is a port specification * * \return end of port number (equals *strp if there is none); NULL * if there is no port number */ static inline const char * -get_port(struct snmp_client *sc, const char **strp) +get_port(struct snmp_client *sc, const char *port[2]) { - if (**strp != ':') - return (*strp + 1); + if (*port[0] != ':') + return (port[1] = port[0]); - if ((*strp)[1] == '\0') { + if (port[0][1] == '\0') { seterr(sc, "empty port name"); return (NULL); } - *strp += strlen(*strp); - return (*strp); + return (port[1] = ++(port[0]) + strlen(port[0])); } /** @@ -2162,6 +2157,7 @@ int snmp_parse_server(struct snmp_client *sc, const char *str) { const char *const orig = str; + const char *comm[2], *ipv6[2], *ipv4[2], *host[2], *port[2]; /* parse input */ int def_trans = 0, trans = get_transp(sc, &str); @@ -2171,42 +2167,32 @@ snmp_parse_server(struct snmp_client *sc, const char *str) if (orig == str) def_trans = 1; - const char *const comm[2] = { - str, - get_comm(sc, &str), - }; - if (comm[1] == NULL) + comm[0] = str; + if ((str = get_comm(sc, comm)) == NULL) return (-1); - const char *const ipv6[2] = { - str + 1, - get_ipv6(sc, &str), - }; - if (ipv6[1] == NULL) + ipv6[0] = str; + if ((str = get_ipv6(sc, ipv6)) == NULL) return (-1); - const char *ipv4[2] = { - str, - str, - }; - - const char *host[2] = { - str, - str, - }; - if (ipv6[0] == ipv6[1]) { - ipv4[1] = get_ipv4(sc, &str); + ipv4[0] = str; + if ((str = get_ipv4(sc, ipv4)) == NULL) { + /* This failure isn't fatal: restore str. */ + str = ipv4[0]; + ipv4[0] = ipv4[1] = NULL; + } - if (ipv4[0] == ipv4[1]) - host[1] = get_host(sc, &str); - } + if (ipv4[0] == ipv4[1]) { + host[0] = str; + str = get_host(sc, host); + } else + host[0] = host[1] = NULL; + } else + ipv4[0] = ipv4[1] = host[0] = host[1] = NULL; - const char *port[2] = { - str + 1, - get_port(sc, &str), - }; - if (port[1] == NULL) + port[0] = str; + if ((str = get_port(sc, port)) == NULL) return (-1); if (*str != '\0') { @@ -2237,7 +2223,7 @@ snmp_parse_server(struct snmp_client *sc, const char *str) return (-1); if (def_trans) trans = SNMP_TRANS_UDP; - } else { + } else if (host[0] != host[1]) { if ((chost = save_str(sc, host)) == NULL) return (-1); @@ -2252,6 +2238,17 @@ snmp_parse_server(struct snmp_client *sc, const char *str) break; } } + } else switch (trans) { + case SNMP_TRANS_UDP: + case SNMP_TRANS_UDP6: + if ((chost = strdup(DEFAULT_HOST)) == NULL) + return (-1); + break; + case SNMP_TRANS_LOC_DGRAM: + case SNMP_TRANS_LOC_STREAM: + if ((chost = strdup(SNMP_DEFAULT_LOCAL)) == NULL) + return (-1); + break; } char *cport; diff --git a/contrib/bsnmp/lib/snmpclient.h b/contrib/bsnmp/lib/snmpclient.h index a19bdb2ea653..a8a79ff824bc 100644 --- a/contrib/bsnmp/lib/snmpclient.h +++ b/contrib/bsnmp/lib/snmpclient.h @@ -35,13 +35,13 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> +#include <sys/un.h> #include <netinet/in.h> #include <stddef.h> #define SNMP_STRERROR_LEN 200 - -#define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX" +#define SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock" /* * transport methods @@ -110,7 +110,7 @@ struct snmp_client { snmp_timeout_start_f timeout_start; snmp_timeout_stop_f timeout_stop; - char local_path[sizeof(SNMP_LOCAL_PATH)]; + char local_path[SUNPATHLEN]; }; /* the global context */ 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..933ab7aa655a 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> @@ -236,7 +237,6 @@ static struct request_info req; #endif /* transports */ -extern const struct transport_def udp_trans; extern const struct transport_def lsock_trans; struct transport_list transport_list = TAILQ_HEAD_INITIALIZER(transport_list); @@ -1186,12 +1186,7 @@ snmpd_input(struct port_input *pi, struct tport *tport) sndbuf, &sndlen, "SNMP", ierr, vi, NULL); if (ferr == SNMPD_INPUT_OK) { - if (tport->transport->vtab->send != NULL) - slen = tport->transport->vtab->send(tport, sndbuf, - sndlen, pi->peer, pi->peerlen); - else - slen = tport->transport->vtab->send2(tport, sndbuf, - sndlen, pi); + slen = tport->transport->vtab->send(tport, sndbuf, sndlen, pi); if (slen == -1) syslog(LOG_ERR, "send*: %m"); else if ((size_t)slen != sndlen) @@ -1214,6 +1209,11 @@ void snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu, const struct sockaddr *addr, socklen_t addrlen) { + struct port_input pi = { + .fd = -1, + .peer = __DECONST(struct sockaddr *, addr), + .peerlen = addrlen, + }; struct transport *trans = targ; struct tport *tp; u_char *sndbuf; @@ -1231,10 +1231,7 @@ snmp_send_port(void *targ, const struct asn_oid *port, struct snmp_pdu *pdu, snmp_output(pdu, sndbuf, &sndlen, "SNMP PROXY"); - if (trans->vtab->send != NULL) - len = trans->vtab->send(tp, sndbuf, sndlen, addr, addrlen); - else - len = trans->vtab->send2(tp, sndbuf, sndlen, NULL); + len = trans->vtab->send(tp, sndbuf, sndlen, &pi); if (len == -1) syslog(LOG_ERR, "sendto: %m"); @@ -1509,7 +1506,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 +1523,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 +1531,7 @@ main(int argc, char *argv[]) break; case 'd': - background = 0; + background = false; break; case 'D': @@ -1601,6 +1593,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)); @@ -1658,8 +1657,6 @@ main(int argc, char *argv[]) syslog(LOG_ERR, "atexit failed: %m"); exit(1); } - if (udp_trans.start() != SNMP_ERR_NOERROR) - syslog(LOG_WARNING, "cannot start UDP transport"); if (lsock_trans.start() != SNMP_ERR_NOERROR) syslog(LOG_WARNING, "cannot start LSOCK transport"); if (inet_trans.start() != SNMP_ERR_NOERROR) diff --git a/contrib/bsnmp/snmpd/snmpd.h b/contrib/bsnmp/snmpd/snmpd.h index 394a4f4736d6..b0e60040d025 100644 --- a/contrib/bsnmp/snmpd/snmpd.h +++ b/contrib/bsnmp/snmpd/snmpd.h @@ -192,12 +192,8 @@ struct transport_def { int (*init_port)(struct tport *); ssize_t (*send)(struct tport *, const u_char *, size_t, - const struct sockaddr *, size_t); - ssize_t (*recv)(struct tport *, struct port_input *); - - /** send via a multi-socket port */ - ssize_t (*send2)(struct tport *, const u_char *, size_t, struct port_input *); + ssize_t (*recv)(struct tport *, struct port_input *); }; struct transport { struct asn_oid index; /* transport table index */ diff --git a/contrib/bsnmp/snmpd/trans_inet.c b/contrib/bsnmp/snmpd/trans_inet.c index dccfb6234222..d06b85ac11f6 100644 --- a/contrib/bsnmp/snmpd/trans_inet.c +++ b/contrib/bsnmp/snmpd/trans_inet.c @@ -375,17 +375,16 @@ inet_recv(struct tport *tp, struct port_input *pi) * \param tp port * \param buf data to send * \param len number of bytes to send - * \param addr destination address - * \param addlen destination address length + * \param pi destination * * \return number of bytes sent */ static ssize_t -inet_send2(struct tport *tp, const u_char *buf, size_t len, +inet_send(struct tport *tp, const u_char *buf, size_t len, struct port_input *pi) { struct inet_port *p = __containerof(tp, struct inet_port, tport); - struct port_sock *s = (pi == NULL) ? TAILQ_FIRST(&p->socks) : + struct port_sock *s = (pi->fd == -1) ? TAILQ_FIRST(&p->socks) : __containerof(pi, struct port_sock, input); struct iovec iov; @@ -414,15 +413,14 @@ inet_send2(struct tport *tp, const u_char *buf, size_t len, /** exported to daemon */ const struct transport_def inet_trans = { - "inet", - OIDX_begemotSnmpdTransInet, - inet_start, - inet_stop, - inet_destroy_port, - inet_activate, - NULL, - inet_recv, - inet_send2, + .name = "inet", + .id = OIDX_begemotSnmpdTransInet, + .start = inet_start, + .stop = inet_stop, + .close_port = inet_destroy_port, + .init_port = inet_activate, + .recv = inet_recv, + .send = inet_send, }; struct inet_port_params { diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c index fa3bd34d14f0..01beb01927ec 100644 --- a/contrib/bsnmp/snmpd/trans_lsock.c +++ b/contrib/bsnmp/snmpd/trans_lsock.c @@ -58,20 +58,19 @@ static int lsock_stop(int); static void lsock_close_port(struct tport *); static int lsock_init_port(struct tport *); static ssize_t lsock_send(struct tport *, const u_char *, size_t, - const struct sockaddr *, size_t); + struct port_input *); static ssize_t lsock_recv(struct tport *, struct port_input *); /* exported */ const struct transport_def lsock_trans = { - "lsock", - OIDX_begemotSnmpdTransLsock, - lsock_start, - lsock_stop, - lsock_close_port, - lsock_init_port, - lsock_send, - lsock_recv, - NULL + .name = "lsock", + .id = OIDX_begemotSnmpdTransLsock, + .start = lsock_start, + .stop = lsock_stop, + .close_port = lsock_close_port, + .init_port = lsock_init_port, + .send = lsock_send, + .recv = lsock_recv, }; static struct transport *my_trans; @@ -396,28 +395,10 @@ lsock_init_port(struct tport *tp) * Send something */ static ssize_t -lsock_send(struct tport *tp, const u_char *buf, size_t len, - const struct sockaddr *addr, size_t addrlen) +lsock_send(struct tport *tp __unused, const u_char *buf, size_t len, + struct port_input *pi) { - struct lsock_port *p = (struct lsock_port *)tp; - struct lsock_peer *peer; - - if (p->type == LOCP_DGRAM_PRIV || p->type == LOCP_DGRAM_UNPRIV) { - peer = LIST_FIRST(&p->peers); - - } else { - /* search for the peer */ - LIST_FOREACH(peer, &p->peers, link) - if (peer->input.peerlen == addrlen && - memcmp(peer->input.peer, addr, addrlen) == 0) - break; - if (peer == NULL) { - errno = ENOTCONN; - return (-1); - } - } - - return (sendto(peer->input.fd, buf, len, 0, addr, addrlen)); + return (sendto(pi->fd, buf, len, MSG_NOSIGNAL, pi->peer, pi->peerlen)); } static void diff --git a/contrib/bsnmp/snmpd/trans_udp.c b/contrib/bsnmp/snmpd/trans_udp.c deleted file mode 100644 index 8e9d1510d1d7..000000000000 --- a/contrib/bsnmp/snmpd/trans_udp.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 2003 - * Fraunhofer Institute for Open Communication Systems (FhG Fokus). - * All rights reserved. - * - * Author: Harti Brandt <harti@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 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 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. - * - * $Begemot: bsnmp/snmpd/trans_udp.c,v 1.5 2005/10/04 08:46:56 brandt_h Exp $ - * - * UDP transport - */ -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/ucred.h> - -#include <stdbool.h> -#include <stdlib.h> -#include <syslog.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "snmpmod.h" -#include "snmpd.h" -#include "trans_udp.h" -#include "tree.h" -#include "oid.h" - -static int udp_start(void); -static int udp_stop(int); -static void udp_close_port(struct tport *); -static int udp_init_port(struct tport *); -static ssize_t udp_send(struct tport *, const u_char *, size_t, - const struct sockaddr *, size_t); -static ssize_t udp_recv(struct tport *, struct port_input *); - -/* exported */ -const struct transport_def udp_trans = { - "udp", - OIDX_begemotSnmpdTransUdp, - udp_start, - udp_stop, - udp_close_port, - udp_init_port, - udp_send, - udp_recv, - NULL -}; -static struct transport *my_trans; - -static int -udp_start(void) -{ - return (trans_register(&udp_trans, &my_trans)); -} - -static int -udp_stop(int force __unused) -{ - if (my_trans != NULL) - if (trans_unregister(my_trans) != 0) - return (SNMP_ERR_GENERR); - return (SNMP_ERR_NOERROR); -} - -/* - * A UDP port is ready - */ -static void -udp_input(int fd __unused, void *udata) -{ - struct udp_port *p = udata; - - p->input.peerlen = sizeof(p->ret); - snmpd_input(&p->input, &p->tport); -} - -/* - * Create a UDP socket and bind it to the given port - */ -static int -udp_init_port(struct tport *tp) -{ - struct udp_port *p = (struct udp_port *)tp; - struct sockaddr_in addr; - u_int32_t ip; - const int on = 1; - - if ((p->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "creating UDP socket: %m"); - return (SNMP_ERR_RES_UNAVAIL); - } - ip = (p->addr[0] << 24) | (p->addr[1] << 16) | (p->addr[2] << 8) | - p->addr[3]; - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(ip); - addr.sin_port = htons(p->port); - addr.sin_family = AF_INET; - addr.sin_len = sizeof(addr); - if (addr.sin_addr.s_addr == INADDR_ANY) { - if (setsockopt(p->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, - sizeof(on)) == -1) { - syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); - close(p->input.fd); - p->input.fd = -1; - return (SNMP_ERR_GENERR); - } - p->recvdstaddr = true; - } - if (bind(p->input.fd, (struct sockaddr *)&addr, sizeof(addr))) { - if (errno == EADDRNOTAVAIL) { - close(p->input.fd); - p->input.fd = -1; - return (SNMP_ERR_INCONS_NAME); - } - syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(addr.sin_addr), - p->port); - close(p->input.fd); - p->input.fd = -1; - return (SNMP_ERR_GENERR); - } - if ((p->input.id = fd_select(p->input.fd, udp_input, - p, NULL)) == NULL) { - close(p->input.fd); - p->input.fd = -1; - return (SNMP_ERR_GENERR); - } - return (SNMP_ERR_NOERROR); -} - -/* - * Create a new SNMP Port object and start it, if we are not - * in initialization mode. The arguments are in host byte order. - */ -static int -udp_open_port(u_int8_t *addr, u_int32_t udp_port, struct udp_port **pp) -{ - struct udp_port *port; - int err; - - if (udp_port > 0xffff) - return (SNMP_ERR_NO_CREATION); - if ((port = malloc(sizeof(*port))) == NULL) - return (SNMP_ERR_GENERR); - memset(port, 0, sizeof(*port)); - - /* initialize common part */ - port->tport.index.len = 5; - port->tport.index.subs[0] = addr[0]; - port->tport.index.subs[1] = addr[1]; - port->tport.index.subs[2] = addr[2]; - port->tport.index.subs[3] = addr[3]; - port->tport.index.subs[4] = udp_port; - - port->addr[0] = addr[0]; - port->addr[1] = addr[1]; - port->addr[2] = addr[2]; - port->addr[3] = addr[3]; - port->port = udp_port; - - port->input.fd = -1; - port->input.id = NULL; - port->input.stream = 0; - port->input.cred = 0; - port->input.peer = (struct sockaddr *)&port->ret; - port->input.peerlen = sizeof(port->ret); - - trans_insert_port(my_trans, &port->tport); - - if (community != COMM_INITIALIZE && - (err = udp_init_port(&port->tport)) != SNMP_ERR_NOERROR) { - udp_close_port(&port->tport); - return (err); - } - *pp = port; - return (SNMP_ERR_NOERROR); -} - -/* - * Close an SNMP port - */ -static void -udp_close_port(struct tport *tp) -{ - struct udp_port *port = (struct udp_port *)tp; - - snmpd_input_close(&port->input); - trans_remove_port(tp); - free(port); -} - -/* - * Send something - */ -static ssize_t -udp_send(struct tport *tp, const u_char *buf, size_t len, - const struct sockaddr *addr, size_t addrlen) -{ - struct udp_port *p = (struct udp_port *)tp; - struct cmsghdr *cmsg; - struct msghdr msg; - char cbuf[CMSG_SPACE(sizeof(struct in_addr))]; - struct iovec iov; - - iov.iov_base = __DECONST(void*, buf); - iov.iov_len = len; - - msg.msg_flags = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_name = __DECONST(void *, addr); - msg.msg_namelen = addrlen; - - if (p->recvdstaddr) { - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_SENDSRCADDR; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); - memcpy(CMSG_DATA(cmsg), &p->dstaddr, sizeof(struct in_addr)); - } else { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } - - return (sendmsg(p->input.fd, &msg, 0)); -} - -static void -check_priv_dgram(struct port_input *pi, struct sockcred *cred) -{ - - /* process explicitly sends credentials */ - if (cred) - pi->priv = (cred->sc_euid == 0); - else - pi->priv = 0; -} - -/* - * Input from a datagram socket. - * Each receive should return one datagram. - */ -static ssize_t -udp_recv(struct tport *tp, struct port_input *pi) -{ - u_char embuf[1000]; - char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + - CMSG_SPACE(sizeof(struct in_addr))]; - struct udp_port *p = (struct udp_port *)tp; - struct msghdr msg; - struct iovec iov[1]; - ssize_t len; - struct cmsghdr *cmsg; - struct sockcred *cred = NULL; - - if (pi->buf == NULL) { - /* no buffer yet - allocate one */ - if ((pi->buf = buf_alloc(0)) == NULL) { - /* ups - could not get buffer. Read away input - * and drop it */ - (void)recvfrom(pi->fd, embuf, sizeof(embuf), - 0, NULL, NULL); - /* return error */ - return (-1); - } - pi->buflen = buf_size(0); - } - - /* try to get a message */ - msg.msg_name = pi->peer; - msg.msg_namelen = pi->peerlen; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - memset(cbuf, 0, sizeof(cbuf)); - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); - msg.msg_flags = 0; - - iov[0].iov_base = pi->buf; - iov[0].iov_len = pi->buflen; - - len = recvmsg(pi->fd, &msg, 0); - - if (len == -1 || len == 0) - /* receive error */ - return (-1); - - if (msg.msg_flags & MSG_TRUNC) { - /* truncated - drop */ - snmpd_stats.silentDrops++; - snmpd_stats.inTooLong++; - return (-1); - } - - pi->length = (size_t)len; - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == IPPROTO_IP && - cmsg->cmsg_type == IP_RECVDSTADDR) - memcpy(&p->dstaddr, CMSG_DATA(cmsg), - sizeof(struct in_addr)); - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDS) - cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); - } - - if (pi->cred) - check_priv_dgram(pi, cred); - - return (0); -} - -/* - * Port table - */ -int -op_snmp_port(struct snmp_context *ctx, struct snmp_value *value, - u_int sub, u_int iidx, enum snmp_op op) -{ - asn_subid_t which = value->var.subs[sub-1]; - struct udp_port *p; - u_int8_t addr[4]; - u_int32_t port; - - switch (op) { - - case SNMP_OP_GETNEXT: - if ((p = (struct udp_port *)trans_next_port(my_trans, - &value->var, sub)) == NULL) - return (SNMP_ERR_NOSUCHNAME); - index_append(&value->var, sub, &p->tport.index); - break; - - case SNMP_OP_GET: - if ((p = (struct udp_port *)trans_find_port(my_trans, - &value->var, sub)) == NULL) - return (SNMP_ERR_NOSUCHNAME); - break; - - case SNMP_OP_SET: - p = (struct udp_port *)trans_find_port(my_trans, - &value->var, sub); - ctx->scratch->int1 = (p != NULL); - - if (which != LEAF_begemotSnmpdPortStatus) - abort(); - if (!TRUTH_OK(value->v.integer)) - return (SNMP_ERR_WRONG_VALUE); - - ctx->scratch->int2 = TRUTH_GET(value->v.integer); - - if (ctx->scratch->int2) { - /* open an SNMP port */ - if (p != NULL) - /* already open - do nothing */ - return (SNMP_ERR_NOERROR); - - if (index_decode(&value->var, sub, iidx, addr, &port)) - return (SNMP_ERR_NO_CREATION); - return (udp_open_port(addr, port, &p)); - - } else { - /* close SNMP port - do in commit */ - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_ROLLBACK: - p = (struct udp_port *)trans_find_port(my_trans, - &value->var, sub); - if (ctx->scratch->int1 == 0) { - /* did not exist */ - if (ctx->scratch->int2 == 1) { - /* created */ - if (p != NULL) - udp_close_port(&p->tport); - } - } - return (SNMP_ERR_NOERROR); - - case SNMP_OP_COMMIT: - p = (struct udp_port *)trans_find_port(my_trans, - &value->var, sub); - if (ctx->scratch->int1 == 1) { - /* did exist */ - if (ctx->scratch->int2 == 0) { - /* delete */ - if (p != NULL) - udp_close_port(&p->tport); - } - } - return (SNMP_ERR_NOERROR); - - default: - abort(); - } - - /* - * Come here to fetch the value - */ - switch (which) { - - case LEAF_begemotSnmpdPortStatus: - value->v.integer = 1; - break; - - default: - abort(); - } - - return (SNMP_ERR_NOERROR); -} diff --git a/contrib/bsnmp/snmpd/tree.def b/contrib/bsnmp/snmpd/tree.def index 61b581120528..074a6e7e5390 100644 --- a/contrib/bsnmp/snmpd/tree.def +++ b/contrib/bsnmp/snmpd/tree.def @@ -117,15 +117,6 @@ typedef BegemotSnmpdTransportProto ENUM ( ) ) # -# Port table -# - (4 begemotSnmpdPortTable - (1 begemotSnmpdPortEntry : IPADDRESS INTEGER op_snmp_port - (1 begemotSnmpdPortAddress IPADDRESS) - (2 begemotSnmpdPortPort UNSIGNED32) - (3 begemotSnmpdPortStatus INTEGER GET SET) - )) -# # Community table # (5 begemotSnmpdCommunityTable 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..b6e5f6275039 100644 --- a/krb5/lib/Makefile.inc +++ b/krb5/lib/Makefile.inc @@ -9,8 +9,10 @@ .include "../Makefile.inc" +PACKAGE?= kerberos-lib + KRB5_KRB5LIBDIR= ${KRB5_SRCLIBDIR}/krb5 KRB5_K5CRYPTODIR= ${KRB5_SRCLIBDIR}/crypto SHLIBDIR?= /usr/lib -SHLIB_MAJOR?= 121 +SHLIB_MAJOR?= 122 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..4dda0d85da54 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. @@ -24,10 +23,6 @@ LIBADD= com_err krb5support crypto # .include "${KRB5_CRYPTOLIBDIR}/builtin/Makefile.inc" # .include "${KRB5_CRYPTOLIBDIR}/openssl/Makefile.inc" -.include "${KRB5_SRCTOP}/lib/krb5/error_tables/Makefile.inc" - -SRCS+= ${GEN_ET} - .include "${KRB5_SRCTOP}/lib/crypto/krb/Makefile.inc" .include "${KRB5_SRCTOP}/lib/crypto/builtin/Makefile.inc" .include "${KRB5_SRCTOP}/lib/crypto/openssl/Makefile.inc" diff --git a/krb5/lib/crypto/version.map b/krb5/lib/crypto/version.map new file mode 100644 index 000000000000..57448f6d85fa --- /dev/null +++ b/krb5/lib/crypto/version.map @@ -0,0 +1,109 @@ +k5crypto_3_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..d52c0d3d1e36 --- /dev/null +++ b/krb5/lib/gssapi/version.map @@ -0,0 +1,176 @@ +HEIMDAL_GSS_2.0 { + global: + gss_accept_sec_context; + gss_acquire_cred; + gss_acquire_cred_with_password; + gss_add_buffer_set_member; + gss_add_cred; + gss_add_cred_with_password; + gss_add_oid_set_member; + gss_authorize_localname; + gss_canonicalize_name; + gss_compare_name; + 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_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_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_oid_equal; + gss_oid_to_str; + gss_pname_to_uid; + gss_process_context_token; + gss_pseudo_random; + 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_sec_context_option; + gss_sign; + gss_store_cred; + gss_test_oid_set_member; + gss_unseal; + gss_unwrap; + gss_unwrap_iov; + gss_userok; + gss_verify; + gss_verify_mic; + gss_wrap; + gss_wrap_iov; + gss_wrap_iov_length; + gss_wrap_size_limit; + gsskrb5_extract_authtime_from_sec_context; + gsskrb5_extract_authz_data_from_sec_context; + krb5_gss_register_acceptor_identity; +}; + +gssapi_krb5_2_MIT { + global: + GSS_C_ATTR_LOCAL_LOGIN_USER; + GSS_C_INQ_SSPI_SESSION_KEY; + GSS_C_INQ_NEGOEX_KEY; + GSS_C_INQ_NEGOEX_VERIFY_KEY; + 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_KRB5_NT_PRINCIPAL_NAME; + GSS_KRB5_NT_ENTERPRISE_NAME; + GSS_KRB5_NT_X509_CERT; + GSS_KRB5_CRED_NO_CI_FLAGS_X; + GSS_KRB5_GET_CRED_IMPERSONATOR; + GSS_C_MA_MECH_CONCRETE; + GSS_C_MA_MECH_PSEUDO; + GSS_C_MA_MECH_COMPOSITE; + GSS_C_MA_MECH_NEGO; + GSS_C_MA_MECH_GLUE; + GSS_C_MA_NOT_MECH; + GSS_C_MA_DEPRECATED; + GSS_C_MA_NOT_DFLT_MECH; + GSS_C_MA_ITOK_FRAMED; + GSS_C_MA_AUTH_INIT; + GSS_C_MA_AUTH_TARG; + GSS_C_MA_AUTH_INIT_INIT; + GSS_C_MA_AUTH_TARG_INIT; + GSS_C_MA_AUTH_INIT_ANON; + GSS_C_MA_AUTH_TARG_ANON; + GSS_C_MA_DELEG_CRED; + GSS_C_MA_INTEG_PROT; + GSS_C_MA_CONF_PROT; + GSS_C_MA_MIC; + GSS_C_MA_WRAP; + GSS_C_MA_PROT_READY; + GSS_C_MA_REPLAY_DET; + GSS_C_MA_OOS_DET; + GSS_C_MA_CBINDINGS; + GSS_C_MA_PFS; + GSS_C_MA_COMPRESS; + GSS_C_MA_CTX_TRANS; + GSS_C_MA_NEGOEX_AND_SPNEGO; + GSS_C_SEC_CONTEXT_SASL_SSF; + gss_acquire_cred_impersonate_name; + gss_add_cred_impersonate_name; + gss_complete_auth_token; + gss_get_mic_iov; + gss_get_mic_iov_length; + 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_release_any_name_mapping; + gss_set_neg_mechs; + gss_str_to_oid; + gss_unwrap_aead; + gss_verify_mic_iov; + gss_wrap_aead; + gssspi_set_cred_option; + gssspi_mech_invoke; + krb5_gss_dbg_client_expcreds; + krb5_gss_use_kdc_context; + gss_acquire_cred_from; + gss_add_cred_from; + gss_store_cred_into; + gssint_g_seqstate_init; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/lib/kadm5clnt/Makefile b/krb5/lib/kadm5clnt/Makefile index ddb9b0e9fec5..898276e77d04 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 \ @@ -29,7 +28,8 @@ SRCS= alt_prof.c \ .include "${KRB5_SRCTOP}/lib/kadm5clnt/clnt/Makefile.inc" -CFLAGS+=-I${KRB5_DIR}/lib/kadm5 \ +CFLAGS+=-I${KRB5_DIR}/lib \ + -I${KRB5_DIR}/lib/kadm5 \ -I${KRB5_DIR}/include \ -I${KRB5_OBJTOP}/include/krb5_private \ -I${KRB5_SRCTOP}/include \ @@ -37,10 +37,6 @@ CFLAGS+=-I${KRB5_DIR}/lib/kadm5 \ INCSDIR=${INCLUDEDIR}/kadm5 INCS= admin.h \ - admin_internal.h \ - admin_xdr.h \ - kadm_rpc.h \ - server_internal.h \ ${GENI} KADM_ERR= kadm_err.et diff --git a/krb5/lib/kadm5clnt/version.map b/krb5/lib/kadm5clnt/version.map new file mode 100644 index 000000000000..1b624130144d --- /dev/null +++ b/krb5/lib/kadm5clnt/version.map @@ -0,0 +1,119 @@ +kadm5clnt_mit_12_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/lib/kadm5srv/Makefile b/krb5/lib/kadm5srv/Makefile index f716dfcdaedc..e0ec557a3f5b 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 @@ -38,7 +37,8 @@ INCS= admin.h \ GEN= kadm_err.c kadm_err.h chpass_util_strings.c chpass_util_strings.h CLEANFILES= ${GEN} ${GENI} -CFLAGS+=-I${KRB5_DIR}/lib/kadm5 \ +CFLAGS+=-I${KRB5_DIR}/lib \ + -I${KRB5_DIR}/lib/kadm5 \ -I${KRB5_DIR}/include \ -I${KRB5_OBJTOP}/include/krb5_private \ -I${KRB5_SRCTOP}/include \ @@ -49,10 +49,6 @@ CFLAGS+=-I${KRB5_DIR}/lib/kadm5 \ HDRDIR= ${KRB5_OBJHDR}/kadm5 HDRS= ${HDRDIR}/admin.h \ - ${HDRDIR}/admin_internal.h \ - ${HDRDIR}/admin_xdr.h \ - ${HDRDIR}/kadm_rpc.h \ - ${HDRDIR}/server_internal.h \ ${HDRDIR}/chpass_util_strings.h \ ${HDRDIR}/kadm_err.h diff --git a/krb5/lib/kadm5srv/version.map b/krb5/lib/kadm5srv/version.map new file mode 100644 index 000000000000..d18753acad3f --- /dev/null +++ b/krb5/lib/kadm5srv/version.map @@ -0,0 +1,138 @@ +kadm5srv_mit_12_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..63096fe7190a --- /dev/null +++ b/krb5/lib/kdb/version.map @@ -0,0 +1,112 @@ +kdb5_10_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/lib/krad/Makefile b/krb5/lib/krad/Makefile index 4b18af482207..a990354c1877 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 \ @@ -25,10 +24,6 @@ SRCS= attr.c \ packet.c \ remote.c -INCS= internal.h \ - t_daemon.h \ - t_test.h - CFLAGS+=-I${KRB5_DIR}/lib/krad \ -I${KRB5_DIR}/include \ -I${KRB5_SRCTOP}/include \ diff --git a/krb5/lib/krad/version.map b/krb5/lib/krad/version.map new file mode 100644 index 000000000000..a18fa4665e50 --- /dev/null +++ b/krb5/lib/krad/version.map @@ -0,0 +1,27 @@ +krad_0_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/lib/krb5/Makefile b/krb5/lib/krb5/Makefile index bf90c7fc80f7..dc6c53ec6ce2 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 @@ -51,19 +50,24 @@ CFLAGS+=${DEFINES} \ -I${KRB5_SRCTOP}/include \ -I${KRB5_DIR} -MAN= k5identity.5 \ - k5login.5 \ - kadm5.acl.5 \ - kdc.conf.5 \ - krb5.conf.5 \ - kerberos.7 +MANGROUPS= KRB5 +KRB5= k5identity.5 \ + k5login.5 \ + krb5.conf.5 \ + kerberos.7 +KRB5PACKAGE= kerberos +KRB5LINKS=k5identity.5 .k5identity.5 +KRB5LINKS+=k5login.5 .k5login.5 + +MANGROUPS+= KDC +KDC= kadm5.acl.5 \ + kdc.conf.5 +KDCPACKAGE= kerberos-kdc -MLINKS= k5identity.5 .k5identity.5 -MLINKS+=k5login.5 .k5login.5 .include <bsd.lib.mk> -.SUFFIXES: .h .c .et .man .5 .7 +.SUFFIXES: .et .man .man.5: @cp ${.ALLSRC} ${.TARGET} diff --git a/krb5/lib/krb5/error_tables/Makefile.inc b/krb5/lib/krb5/error_tables/Makefile.inc index dee259798dae..5d2ec3b9e920 100644 --- a/krb5/lib/krb5/error_tables/Makefile.inc +++ b/krb5/lib/krb5/error_tables/Makefile.inc @@ -144,3 +144,5 @@ ${GEN_ASN1_ERR_C}: ${GEN_ASN1_ERR} ${COMPILE_ET} et-c-${.PREFIX}.et mv et-c-${.PREFIX}.c ${.PREFIX}.c rm -f et-c-${.PREFIX}.et et-c-${.PREFIX}.c + +SRCS+= ${GEN_ET} diff --git a/krb5/lib/krb5/version.map b/krb5/lib/krb5/version.map new file mode 100644 index 000000000000..ce399a93e03e --- /dev/null +++ b/krb5/lib/krb5/version.map @@ -0,0 +1,633 @@ +HEIMDAL_KRB5_2.0 { + global: + initialize_k524_error_table; + initialize_krb5_error_table; + krb524_convert_creds_kdc; + krb5_address_compare; + krb5_address_order; + krb5_address_search; + krb5_allow_weak_crypto; + krb5_aname_to_localname; + krb5_appdefault_boolean; + krb5_appdefault_string; + krb5_auth_con_free; + krb5_auth_con_genaddrs; + krb5_auth_con_getaddrs; + krb5_auth_con_getauthenticator; + krb5_auth_con_getflags; + krb5_auth_con_getkey; + krb5_auth_con_getlocalseqnumber; + krb5_auth_con_getlocalsubkey; + krb5_auth_con_getrcache; + krb5_auth_con_getrecvsubkey; + krb5_auth_con_getremoteseqnumber; + krb5_auth_con_getremotesubkey; + krb5_auth_con_getsendsubkey; + krb5_auth_con_init; + krb5_auth_con_setaddrs; + krb5_auth_con_setflags; + krb5_auth_con_setrcache; + krb5_auth_con_setrecvsubkey; + krb5_auth_con_setsendsubkey; + krb5_build_principal; + 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_end_seq_get; + 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_initialize; + krb5_cc_move; + krb5_cc_new_unique; + krb5_cc_next_cred; + krb5_cc_register; + krb5_cc_remove_cred; + krb5_cc_resolve; + krb5_cc_retrieve_cred; + 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_change_password; + krb5_clear_error_message; + krb5_copy_addresses; + krb5_copy_checksum; + krb5_copy_context; + krb5_copy_creds; + krb5_copy_data; + krb5_copy_keyblock; + krb5_copy_keyblock_contents; + krb5_copy_principal; + krb5_copy_ticket; + krb5_expand_hostname; + krb5_fcc_ops; + krb5_free_address; + krb5_free_addresses; + krb5_free_ap_rep_enc_part; + krb5_free_authenticator; + krb5_free_checksum; + krb5_free_checksum_contents; + krb5_free_config_files; + krb5_free_context; + krb5_free_cred_contents; + krb5_free_creds; + krb5_free_data; + krb5_free_data_contents; + krb5_free_default_realm; + krb5_free_error_message; + krb5_free_host_realm; + krb5_free_kdc_rep; + krb5_free_keyblock; + krb5_free_keyblock_contents; + krb5_free_principal; + krb5_free_ticket; + krb5_free_unparsed_name; + krb5_fwd_tgt_creds; + krb5_generate_seq_number; + krb5_generate_subkey; + krb5_get_credentials; + krb5_get_default_config_files; + krb5_get_default_realm; + krb5_get_error_message; + 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_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_etype_list; + krb5_get_init_creds_opt_set_forwardable; + 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_salt; + krb5_get_init_creds_opt_set_tkt_life; + krb5_get_init_creds_password; + krb5_get_permitted_enctypes; + krb5_get_renewed_creds; + krb5_get_server_rcache; + krb5_get_validated_creds; + krb5_init_context; + krb5_init_creds_free; + krb5_init_creds_get; + krb5_init_creds_get_creds; + krb5_init_creds_get_error; + krb5_init_creds_init; + krb5_init_creds_set_keytab; + krb5_init_creds_set_password; + krb5_init_creds_set_service; + krb5_is_config_principal; + krb5_is_thread_safe; + krb5_kt_add_entry; + krb5_kt_close; + krb5_kt_default; + krb5_kt_default_name; + 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_kuserok; + krb5_mcc_ops; + krb5_mk_error; + krb5_mk_priv; + krb5_mk_rep; + krb5_mk_req; + krb5_mk_req_extended; + krb5_mk_safe; + krb5_net_read; + krb5_net_write; + krb5_pac_add_buffer; + krb5_pac_free; + krb5_pac_get_buffer; + krb5_pac_get_types; + krb5_pac_init; + krb5_pac_parse; + krb5_pac_verify; + krb5_parse_name; + krb5_parse_name_flags; + krb5_prepend_error_message; + krb5_principal_compare; + krb5_principal_compare_any_realm; + 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_req; + krb5_rd_safe; + krb5_read_message; + krb5_realm_compare; + krb5_recvauth; + krb5_salttype_to_string; + krb5_sendauth; + krb5_sendto_kdc; + krb5_set_config_files; + krb5_set_default_realm; + krb5_set_error_message; + krb5_set_password; + krb5_set_password_using_ccache; + krb5_set_real_time; + krb5_sname_to_principal; + krb5_string_to_deltat; + krb5_string_to_salttype; + krb5_timeofday; + krb5_unparse_name; + krb5_unparse_name_flags; + krb5_us_timeofday; + 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_write_message; +}; + +krb5_3_MIT { + 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; + et_asn1_error_table; + et_k524_error_table; + et_kdb5_error_table; + et_krb5_error_table; + et_kv5m_error_table; + initialize_asn1_error_table; + initialize_kdb5_error_table; + initialize_k5e1_error_table; + initialize_kv5m_error_table; + 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_init_ets; + krb5_425_conv_principal; + krb5_524_conv_principal; + krb5_524_convert_creds; + krb5_anonymous_principal; + krb5_anonymous_realm; + krb5_auth_con_get_checksum_func; + krb5_auth_con_get_authdata_context; + krb5_auth_con_getivector; + krb5_auth_con_getkey_k; + krb5_auth_con_getpermetypes; + krb5_auth_con_getrecvsubkey_k; + krb5_auth_con_getsendsubkey_k; + 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_setivector; + krb5_auth_con_setpermetypes; + krb5_auth_con_setports; + krb5_auth_con_setrecvsubkey_k; + 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_alloc_va; + krb5_cc_dfl_ops; + krb5_cc_dup; + krb5_cc_file_ops; + krb5_cc_select; + krb5_cccol_have_content; + krb5_change_cache; + krb5_check_clockskew; + krb5_check_transited_list; + krb5_chpw_message; + krb5_chpw_result_code_string; + krb5_copy_addr; + krb5_copy_authdata; + krb5_copy_authenticator; + krb5_copy_error_message; + 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_find_authdata; + krb5_free_ad_kdcissued; + krb5_free_ap_rep; + krb5_free_ap_req; + krb5_free_authdata; + krb5_free_authenticator_contents; + krb5_free_cred; + krb5_free_cred_enc_part; + 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_etype_info; + krb5_free_fast_armored_req; + krb5_free_fast_req; + krb5_free_fast_response; + krb5_free_iakerb_finished; + krb5_free_iakerb_header; + krb5_free_kdc_req; + 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_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_tickets; + krb5_free_tkt_authent; + krb5_gen_portaddr; + krb5_gen_replay_name; + krb5_get_cred_via_tkt; + krb5_get_credentials_for_proxy; + krb5_get_credentials_for_user; + krb5_get_credentials_renew; + krb5_get_credentials_validate; + krb5_get_default_in_tkt_ktypes; + krb5_get_etype_info; + krb5_get_fallback_host_realm; + 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_set_change_password_prompt; + 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_in_ccache; + krb5_get_init_creds_opt_set_out_ccache; + krb5_get_init_creds_opt_set_pa; + krb5_get_init_creds_opt_set_responder; + krb5_get_notification_message; + krb5_get_profile; + krb5_get_prompt_types; + krb5_get_realm_domain; + krb5_get_tgs_ktypes; + krb5_get_time_offsets; + krb5_init_context_profile; + krb5_init_creds_get_times; + krb5_init_creds_step; + krb5_init_keyblock; + krb5_init_secure_context; + krb5_is_permitted_enctype; + krb5_is_referral_realm; + krb5_kdc_rep_decrypt_proc; + krb5_kdc_sign_ticket; + krb5_kdc_verify_ticket; + krb5_kt_client_default; + krb5_kt_dfl_ops; + krb5_kt_dup; + krb5_ktf_ops; + krb5_ktf_writable_ops; + krb5_lock_file; + krb5_make_authdata_kdc_issued; + krb5_make_full_ipaddr; + krb5_make_fulladdr; + krb5_marshal_credentials; + krb5_merge_authdata; + krb5_mk_1cred; + krb5_mk_ncred; + krb5_mk_rep_dce; + krb5_os_localaddr; + krb5_overridekeyname; + krb5_pac_sign; + krb5_pac_sign_ext; + krb5_pac_verify_ext; + krb5_pac_get_client_info; + krb5_principal2salt; + krb5_principal2salt_norealm; + krb5_principal_compare_flags; + krb5_rd_rep_dce; + krb5_rd_req_decoded; + krb5_rd_req_decoded_anyflag; + krb5_read_password; + 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_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_debugging_time; + krb5_set_default_tgs_enctypes; + krb5_set_default_tgs_ktypes; + krb5_set_principal_realm; + 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_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_timestamp_to_sfstring; + krb5_timestamp_to_string; + krb5_unlock_file; + krb5_unmarshal_credentials; + krb5_unpack_full_ipaddr; + krb5_unparse_name_ext; + krb5_unparse_name_flags_ext; + krb5_use_natural_time; + krb5_verify_authdata_kdc_issued; + krb5_vwrap_error_message; + krb5_walk_realm_tree; + krb5_wrap_error_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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/lib/rpc/Makefile b/krb5/lib/rpc/Makefile index 13499b184d30..a539803cc57c 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 \ @@ -66,10 +65,6 @@ SRCS= auth_gss.c \ xdr_sizeof.c \ xdr_stdio.c -INCS= dyn.h \ - dynP.h \ - gssrpcint.h - CFLAGS+=-I${KRB5_DIR}/lib/rpc \ -I${KRB5_DIR}/include \ -I${KRB5_SRCTOP}/include \ @@ -80,6 +75,4 @@ CFLAGS+=-I${KRB5_DIR}/lib/rpc \ .include <bsd.lib.mk> -.SUFFIXES: .h .c - .PATH: ${KRB5_DIR}/lib/rpc diff --git a/krb5/lib/rpc/version.map b/krb5/lib/rpc/version.map new file mode 100644 index 000000000000..95ef4715572c --- /dev/null +++ b/krb5/lib/rpc/version.map @@ -0,0 +1,148 @@ +gssrpc_4_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..62046214af7b 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 @@ -31,6 +29,7 @@ CFLAGS+=-I${KRB5_DIR}/include \ -I${KRB5_SRCTOP}/include \ -I${KRB5_OBJTOP}/lib/gssapi \ -I${KRB5_OBJTOP}/lib \ + -I${KRB5_DIR}/lib \ -I${KRB5_DIR}/lib/gssapi/krb5 \ -I${KRB5_DIR}/lib/gssapi/generic 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..d98ed1d3887b 100644 --- a/krb5/plugins/Makefile.inc +++ b/krb5/plugins/Makefile.inc @@ -7,10 +7,11 @@ # under sponsorship from the FreeBSD Foundation. # +PACKAGE?= kerberos-kdc MK_INSTALLLIB= no SHLIB_NAME?= ${LIB}.so.${SHLIB_MAJOR} PLUGINSDIR= ${LIBDIR_BASE}/krb5/plugins SHLIBDIR= ${LIBDIR} -SHLIB_MAJOR= 121 +SHLIB_MAJOR= 122 .include "../Makefile.inc" 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..599442dcd8ab --- /dev/null +++ b/krb5/plugins/audit/version.map @@ -0,0 +1,11 @@ +audit_121_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..d8602cb1559a --- /dev/null +++ b/krb5/plugins/k5tls/version.map @@ -0,0 +1,5 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +k5tls_0_MIT { + global: + tls_k5tls_initvt; +}; diff --git a/krb5/plugins/kdb/db2/Makefile b/krb5/plugins/kdb/db2/Makefile index 7526283f37be..3230a77171f4 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 \ @@ -30,15 +29,6 @@ SRCS= \ .include "${KRB5_SRCTOP}/plugins/kdb/db2/libdb2/Makefile.inc" -MAN= db_btree.3 \ - db_hash.3 \ - db_lock.3 \ - db_log.3 \ - db_mpool.3 \ - db_open.3 \ - db_recno.3 \ - db_txn.3 - CFLAGS+=-I${KRB5_DIR}/plugins/kdb/db2 \ -I${KRB5_DIR}/plugins/kdb/db2/libdb2 \ -I${KRB5_DIR}/plugins/kdb/db2/libdb2/include \ @@ -50,16 +40,12 @@ CFLAGS+=-I${KRB5_DIR}/plugins/kdb/db2 \ -I${KRB5_DIR}/include \ -I${KRB5_SRCTOP}/include \ -I${KRB5_DIR}/lib/kdb \ + -I${KRB5_DIR}/lib \ -I${KRB5_OBJTOP}/plugins/kdb/db2 \ -I${KRB5_OBJTOP}/lib/kdb .include <bsd.lib.mk> -.SUFFIXES: .h .c .man .3 - -.man.3: - @cp ${.ALLSRC} ${.TARGET} - .PATH: ${KRB5_DIR}/plugins/kdb/db2 \ ${KRB5_DIR}/plugins/kdb/db2/libdb2 \ ${KRB5_DIR}/plugins/kdb/db2/libdb2/man diff --git a/krb5/plugins/kdb/db2/version.map b/krb5/plugins/kdb/db2/version.map new file mode 100644 index 000000000000..6c7362e3e06b --- /dev/null +++ b/krb5/plugins/kdb/db2/version.map @@ -0,0 +1,5 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +db2_0_MIT { + global: + 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..f2d914551789 --- /dev/null +++ b/krb5/plugins/preauth/otp/version.map @@ -0,0 +1,5 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +otp_0_MIT { + 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..c4498e8f473a --- /dev/null +++ b/krb5/plugins/preauth/pkinit/version.map @@ -0,0 +1,6 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +pkinit_0_MIT { + 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..d29c0e05083d --- /dev/null +++ b/krb5/plugins/preauth/spake/version.map @@ -0,0 +1,6 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +spake_0_MIT { + 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..d6d445ad5bf8 --- /dev/null +++ b/krb5/plugins/preauth/test/version.map @@ -0,0 +1,6 @@ +HIDDEN { local: __*; _rest*; _save*; *; }; +test_0_MIT { + 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..b2a094795d48 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 \ @@ -21,7 +19,7 @@ SCRIPTS= k5srvutil.sh MAN= kadmin.1 \ k5srvutil.1 -MLINKS= kadmin.1 kamdin.local.8 +MLINKS= kadmin.1 kadmin.local.8 CLEANFILES= kadmin.1 k5srvutil.1 @@ -34,7 +32,7 @@ k5srvutil.1: k5srvutil.man .include <bsd.prog.mk> -.SUFFIXES: .h .c. .man .1 +.SUFFIXES: .man .man.1: @cp ${.ALLSRC} ${.TARGET} 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..ef821d6867f5 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 @@ -27,11 +27,13 @@ SRCS= dump.c \ tdumputil.c \ ${GEN} -INCS= ${GENI} +DPSRCS= ${GENI} MAN= kdb5_util.8 -CFLAGS+=-I${KRB5_DIR}/include \ +CFLAGS+=-I. \ + -I${KRB5_DIR}/include \ + -I${KRB5_DIR}/lib \ -I${KRB5_SRCTOP}/include MAN= kdb5_util.8 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/Makefile.inc b/krb5/util/Makefile.inc index 858c1eb48dd9..95b93a793d77 100644 --- a/krb5/util/Makefile.inc +++ b/krb5/util/Makefile.inc @@ -10,4 +10,4 @@ .include "../Makefile.inc" SHLIBDIR?= /usr/lib -SHLIB_MAJOR?= 121 +SHLIB_MAJOR?= 122 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..3bd290009f22 --- /dev/null +++ b/krb5/util/et/version.map @@ -0,0 +1,17 @@ +HEIMDAL_COM_ERR_1.0 { + global: + com_err; + com_err_va; + error_message; + error_table_name; + reset_com_err_hook; + set_com_err_hook; +}; + +com_err_3_MIT { + global: + add_error_table; + error_table_name_r; + remove_error_table; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/krb5/util/profile/Makefile b/krb5/util/profile/Makefile index 24e06e8c5024..7d1b806bfb5d 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 \ @@ -66,13 +67,8 @@ profile.h: profile.hin prof_err.h prof_file.c: profile.h -MAN= profile.5 - .include <bsd.lib.mk> -.SUFFIXES: .h .c .man .1 .et - -.man.5: - cp ${.ALLSRC} ${.TARGET} +.SUFFIXES: .et .PATH: ${KRB5_DIR}/util/profile diff --git a/krb5/util/profile/version.map b/krb5/util/profile/version.map new file mode 100644 index 000000000000..31960193977b --- /dev/null +++ b/krb5/util/profile/version.map @@ -0,0 +1,74 @@ +profile_1_MIT { + global: + et_prof_error_table; + initialize_prof_error_table; + profile_abandon; + profile_add_node; + profile_add_relation; + profile_clear_relation; + profile_close_file; + profile_copy; + profile_create_node; + profile_dereference_data; + profile_dereference_data_locked; + profile_file_is_writable; + profile_find_node; + profile_find_node_relation; + profile_find_node_subsection; + profile_flush; + profile_flush_file_data; + profile_flush_file_data_to_buffer; + profile_flush_file_data_to_file; + profile_flush_to_buffer; + profile_flush_to_file; + profile_free_buffer; + profile_free_file; + profile_free_list; + profile_free_node; + profile_get_boolean; + profile_get_integer; + profile_get_node_name; + profile_get_node_parent; + profile_get_node_value; + profile_get_relation_names; + profile_get_string; + profile_get_subsection_names; + profile_get_value; + profile_get_values; + profile_init; + profile_init_flags; + profile_init_path; + profile_init_vtable; + profile_is_modified; + profile_is_node_final; + profile_is_writable; + profile_iterator; + profile_iterator_create; + profile_iterator_free; + profile_lock_global; + profile_make_node_final; + profile_make_prf_data; + profile_node_iterator; + profile_node_iterator_create; + profile_node_iterator_free; + profile_open_file; + profile_parse_file; + profile_process_directory; + profile_release; + profile_release_string; + profile_remove_node; + profile_rename_node; + profile_rename_section; + profile_ser_externalize; + profile_ser_internalize; + profile_ser_size; + profile_set_relation_value; + profile_unlock_global; + profile_update_file_data; + profile_update_file_data_locked; + profile_update_relation; + profile_verify_node; + profile_write_tree_file; + profile_write_tree_to_buffer; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..cc48ec6a4c8e --- /dev/null +++ b/krb5/util/support/version.map @@ -0,0 +1,103 @@ +krb5support_0_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; 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..ea3b7dcc13b2 --- /dev/null +++ b/krb5/util/verto/version.map @@ -0,0 +1,37 @@ +verto_0_MIT { + 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; +}; +HIDDEN { local: __*; _rest*; _save*; *; }; diff --git a/lib/libbsnmp/libbsnmp/Makefile b/lib/libbsnmp/libbsnmp/Makefile index 6bdb4003fdf4..2e2770b56c4a 100644 --- a/lib/libbsnmp/libbsnmp/Makefile +++ b/lib/libbsnmp/libbsnmp/Makefile @@ -7,7 +7,7 @@ CONTRIB= ${SRCTOP}/contrib/bsnmp/lib .PATH: ${CONTRIB} LIB= bsnmp -SHLIB_MAJOR= 6 +SHLIB_MAJOR= 7 LD_FATAL_WARNINGS= no CFLAGS+= -I${CONTRIB} -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c index 7a66f5443d94..cc96fb5ce326 100644 --- a/lib/libc/db/hash/hash.c +++ b/lib/libc/db/hash/hash.c @@ -120,7 +120,8 @@ __hash_open(const char *file, int flags, int mode, if ((hashp->fp = _open(file, flags | O_CLOEXEC, mode)) == -1) RETURN_ERROR(errno, error0); new_table = _fstat(hashp->fp, &statbuf) == 0 && - statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY; + statbuf.st_size == 0 && + ((flags & O_ACCMODE) != O_RDONLY || (flags & O_CREAT) != 0); } else new_table = 1; 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/powerpc64/gen/_ctx_start.S b/lib/libc/powerpc64/gen/_ctx_start.S index c2f8abfd6486..98225f9c1138 100644 --- a/lib/libc/powerpc64/gen/_ctx_start.S +++ b/lib/libc/powerpc64/gen/_ctx_start.S @@ -34,6 +34,16 @@ ld %r2,8(%r14) ld %r14,0(%r14) #else + /* + * The stack frame was already set up in makecontext(), + * so we can safely use the guaranteed fields here. + * + * Note we do step on the allocated stack frame's TOC, + * but since we never return from this function (i.e. + * never restore the stack frame) this should be safe. + */ + std %r2,24(%r1) /* save TOC */ + /* Load global entry point */ mr %r12,%r14 #endif @@ -41,6 +51,10 @@ blrl /* branch to start function */ mr %r3,%r15 /* pass pointer to ucontext as argument */ nop +#if defined(_CALL_ELF) && _CALL_ELF != 1 + /* Restore TOC */ + ld %r2,24(%r1) +#endif bl CNAME(_ctx_done) /* branch to ctxt completion func */ /* * we should never return from the diff --git a/lib/libc/powerpc64/gen/makecontext.c b/lib/libc/powerpc64/gen/makecontext.c index 75c2d40bdd60..9e3a976fa1bd 100644 --- a/lib/libc/powerpc64/gen/makecontext.c +++ b/lib/libc/powerpc64/gen/makecontext.c @@ -78,7 +78,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...) */ stackargs = (argc > 8) ? argc - 8 : 0; sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size - - sizeof(uintptr_t)*(stackargs + 2); + - sizeof(uintptr_t)*(stackargs + 6); sp = (char *)((uintptr_t)sp & ~0x1f); mc = &ucp->uc_mcontext; @@ -119,6 +119,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...) mc->mc_srr0 = *(uintptr_t *)_ctx_start; #else mc->mc_srr0 = (uintptr_t) _ctx_start; + mc->mc_gpr[12] = (uintptr_t) _ctx_start;/* required for prologue */ #endif mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */ mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */ 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..c50e932d3382 100644 --- a/lib/libc/string/memchr.3 +++ b/lib/libc/string/memchr.3 @@ -34,7 +34,7 @@ .Os .Sh NAME .Nm memchr -.Nd locate byte in byte string +.Nd locate byte in memory object .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -51,8 +51,11 @@ locates the first occurrence of .Fa c (converted to an .Vt "unsigned char" ) -in string -.Fa b . +in object +.Fa b , +limited to at most +.Fa len +characters. .Pp The .Fn memrchr @@ -60,16 +63,19 @@ function behaves like .Fn memchr , except that it locates the last occurrence of .Fa c -in string -.Fa b . +in object +.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/db/Makefile b/lib/libc/tests/db/Makefile index f1f33bd2bafc..54b38b94a581 100644 --- a/lib/libc/tests/db/Makefile +++ b/lib/libc/tests/db/Makefile @@ -7,6 +7,8 @@ PROGS+= h_lfsr ${PACKAGE}FILES+= README +ATF_TESTS_C+= dbm_open_test + NETBSD_ATF_TESTS_C+= db_hash_seq_test NETBSD_ATF_TESTS_SH+= db_test ATF_TESTS_SH_SED_db_test= -e 's,/bin/csh,/bin/cat,g' diff --git a/lib/libc/tests/db/dbm_open_test.c b/lib/libc/tests/db/dbm_open_test.c new file mode 100644 index 000000000000..18d398e16b2a --- /dev/null +++ b/lib/libc/tests/db/dbm_open_test.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/mman.h> + +#include <fcntl.h> +#include <ndbm.h> +#include <stdio.h> + +#include <atf-c.h> + +ATF_TC(dbm_open_missing_test); +ATF_TC_HEAD(dbm_open_missing_test, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test dbm_open when creating a new database"); +} + +ATF_TC_BODY(dbm_open_missing_test, tc) +{ + const char *path = "tmp"; + const char *dbname = "tmp.db"; + + /* + * POSIX.1 specifies that a missing database file should + * always get created if O_CREAT is present, except when + * O_EXCL is specified as well. + */ + ATF_CHECK(dbm_open(path, O_RDONLY, _PROT_ALL) == NULL); + ATF_REQUIRE(!atf_utils_file_exists(dbname)); + ATF_CHECK(dbm_open(path, O_RDONLY | O_CREAT, _PROT_ALL) != NULL); + ATF_REQUIRE(atf_utils_file_exists(dbname)); + ATF_CHECK(dbm_open(path, O_RDONLY | O_CREAT | O_EXCL, _PROT_ALL) == NULL); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, dbm_open_missing_test); + return (atf_no_error()); +} 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/libc/tests/sys/Makefile b/lib/libc/tests/sys/Makefile index 89d341ff400a..88f8191a16eb 100644 --- a/lib/libc/tests/sys/Makefile +++ b/lib/libc/tests/sys/Makefile @@ -7,11 +7,11 @@ ATF_TESTS_C+= brk_test .endif ATF_TESTS_C+= cpuset_test ATF_TESTS_C+= errno_test +ATF_TESTS_C+= swapcontext_test ATF_TESTS_C+= queue_test ATF_TESTS_C+= sendfile_test -# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg, -# swapcontext +# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg NETBSD_ATF_TESTS_C+= access_test NETBSD_ATF_TESTS_C+= bind_test NETBSD_ATF_TESTS_C+= chroot_test diff --git a/lib/libc/tests/sys/swapcontext_test.c b/lib/libc/tests/sys/swapcontext_test.c new file mode 100644 index 000000000000..f341a746e515 --- /dev/null +++ b/lib/libc/tests/sys/swapcontext_test.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2025 Raptor Computing Systems, LLC + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ucontext.h> +#include <errno.h> + +#include <atf-c.h> + +#define STACK_SIZE (64ull << 10) + +static volatile int callback_reached = 0; + +static ucontext_t uctx_save, uctx_switch; + +static void swapcontext_callback() +{ + // Increment callback reached variable + // If this is called multiple times, we will fail the test + // If this is not called at all, we will fail the test + callback_reached++; +} + +ATF_TC(swapcontext_basic); +ATF_TC_HEAD(swapcontext_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify basic functionality of swapcontext"); +} + +ATF_TC_BODY(swapcontext_basic, tc) +{ + char *stack; + int res; + + stack = malloc(STACK_SIZE); + ATF_REQUIRE_MSG(stack != NULL, "malloc failed: %s", strerror(errno)); + res = getcontext(&uctx_switch); + ATF_REQUIRE_MSG(res == 0, "getcontext failed: %s", strerror(errno)); + + uctx_switch.uc_stack.ss_sp = stack; + uctx_switch.uc_stack.ss_size = STACK_SIZE; + uctx_switch.uc_link = &uctx_save; + makecontext(&uctx_switch, swapcontext_callback, 0); + + res = swapcontext(&uctx_save, &uctx_switch); + + ATF_REQUIRE_MSG(res == 0, "swapcontext failed: %s", strerror(errno)); + ATF_REQUIRE_MSG(callback_reached == 1, + "callback failed, reached %d times", callback_reached); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, swapcontext_basic); + + return (atf_no_error()); +} + diff --git a/lib/libcasper/services/cap_net/tests/net_test.c b/lib/libcasper/services/cap_net/tests/net_test.c index e1045341fe47..adf5773233c8 100644 --- a/lib/libcasper/services/cap_net/tests/net_test.c +++ b/lib/libcasper/services/cap_net/tests/net_test.c @@ -331,7 +331,11 @@ test_extend_mode(cap_channel_t *capnet, int current) } } -ATF_TC_WITHOUT_HEAD(capnet__getnameinfo); +ATF_TC(capnet__getnameinfo); +ATF_TC_HEAD(capnet__getnameinfo, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__getnameinfo, tc) { cap_channel_t *capnet; @@ -344,7 +348,11 @@ ATF_TC_BODY(capnet__getnameinfo, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__connect); +ATF_TC(capnet__connect); +ATF_TC_HEAD(capnet__connect, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__connect, tc) { cap_channel_t *capnet; @@ -356,7 +364,11 @@ ATF_TC_BODY(capnet__connect, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__bind); +ATF_TC(capnet__bind); +ATF_TC_HEAD(capnet__bind, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__bind, tc) { cap_channel_t *capnet; @@ -368,7 +380,11 @@ ATF_TC_BODY(capnet__bind, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__getaddrinfo); +ATF_TC(capnet__getaddrinfo); +ATF_TC_HEAD(capnet__getaddrinfo, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__getaddrinfo, tc) { cap_channel_t *capnet; @@ -386,7 +402,11 @@ ATF_TC_BODY(capnet__getaddrinfo, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__gethostbyname); +ATF_TC(capnet__gethostbyname); +ATF_TC_HEAD(capnet__gethostbyname, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__gethostbyname, tc) { cap_channel_t *capnet; @@ -398,7 +418,11 @@ ATF_TC_BODY(capnet__gethostbyname, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__gethostbyaddr); +ATF_TC(capnet__gethostbyaddr); +ATF_TC_HEAD(capnet__gethostbyaddr, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__gethostbyaddr, tc) { cap_channel_t *capnet; @@ -411,7 +435,11 @@ ATF_TC_BODY(capnet__gethostbyaddr, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__getnameinfo_buffer); +ATF_TC(capnet__getnameinfo_buffer); +ATF_TC_HEAD(capnet__getnameinfo_buffer, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__getnameinfo_buffer, tc) { cap_channel_t *chan; @@ -450,7 +478,11 @@ ATF_TC_BODY(capnet__getnameinfo_buffer, tc) cap_close(chan); } -ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_mode); +ATF_TC(capnet__limits_addr2name_mode); +ATF_TC_HEAD(capnet__limits_addr2name_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_addr2name_mode, tc) { cap_channel_t *capnet; @@ -481,7 +513,11 @@ ATF_TC_BODY(capnet__limits_addr2name_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_family); +ATF_TC(capnet__limits_addr2name_family); +ATF_TC_HEAD(capnet__limits_addr2name_family, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_addr2name_family, tc) { cap_channel_t *capnet; @@ -526,7 +562,11 @@ ATF_TC_BODY(capnet__limits_addr2name_family, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name); +ATF_TC(capnet__limits_addr2name); +ATF_TC_HEAD(capnet__limits_addr2name, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_addr2name, tc) { cap_channel_t *capnet; @@ -580,7 +620,11 @@ ATF_TC_BODY(capnet__limits_addr2name, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name_mode); +ATF_TC(capnet__limits_deprecated_addr2name_mode); +ATF_TC_HEAD(capnet__limits_deprecated_addr2name_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_addr2name_mode, tc) { cap_channel_t *capnet; @@ -609,7 +653,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name_family); +ATF_TC(capnet__limits_deprecated_addr2name_family); +ATF_TC_HEAD(capnet__limits_deprecated_addr2name_family, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_addr2name_family, tc) { cap_channel_t *capnet; @@ -660,7 +708,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name_family, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name); +ATF_TC(capnet__limits_deprecated_addr2name); +ATF_TC_HEAD(capnet__limits_deprecated_addr2name, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_addr2name, tc) { cap_channel_t *capnet; @@ -712,7 +764,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name, tc) } -ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_mode); +ATF_TC(capnet__limits_name2addr_mode); +ATF_TC_HEAD(capnet__limits_name2addr_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_name2addr_mode, tc) { cap_channel_t *capnet; @@ -744,7 +800,11 @@ ATF_TC_BODY(capnet__limits_name2addr_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts); +ATF_TC(capnet__limits_name2addr_hosts); +ATF_TC_HEAD(capnet__limits_name2addr_hosts, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_name2addr_hosts, tc) { cap_channel_t *capnet; @@ -797,7 +857,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_strict); +ATF_TC(capnet__limits_name2addr_hosts_servnames_strict); +ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_strict, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc) { cap_channel_t *capnet; @@ -829,7 +893,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_mix); +ATF_TC(capnet__limits_name2addr_hosts_servnames_mix); +ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_mix, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc) { cap_channel_t *capnet; @@ -882,7 +950,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_family); +ATF_TC(capnet__limits_name2addr_family); +ATF_TC_HEAD(capnet__limits_name2addr_family, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_name2addr_family, tc) { cap_channel_t *capnet; @@ -941,7 +1013,11 @@ ATF_TC_BODY(capnet__limits_name2addr_family, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_mode); +ATF_TC(capnet__limits_deprecated_name2addr_mode); +ATF_TC_HEAD(capnet__limits_deprecated_name2addr_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_name2addr_mode, tc) { cap_channel_t *capnet; @@ -972,7 +1048,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_hosts); +ATF_TC(capnet__limits_deprecated_name2addr_hosts); +ATF_TC_HEAD(capnet__limits_deprecated_name2addr_hosts, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_name2addr_hosts, tc) { cap_channel_t *capnet; @@ -1011,7 +1091,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_hosts, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_family); +ATF_TC(capnet__limits_deprecated_name2addr_family); +ATF_TC_HEAD(capnet__limits_deprecated_name2addr_family, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_name2addr_family, tc) { cap_channel_t *capnet; @@ -1065,7 +1149,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_family, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_bind_mode); +ATF_TC(capnet__limits_bind_mode); +ATF_TC_HEAD(capnet__limits_bind_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_bind_mode, tc) { cap_channel_t *capnet; @@ -1097,7 +1185,11 @@ ATF_TC_BODY(capnet__limits_bind_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_bind); +ATF_TC(capnet__limits_bind); +ATF_TC_HEAD(capnet__limits_bind, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_bind, tc) { cap_channel_t *capnet; @@ -1122,7 +1214,11 @@ ATF_TC_BODY(capnet__limits_bind, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_connect_mode); +ATF_TC(capnet__limits_connect_mode); +ATF_TC_HEAD(capnet__limits_connect_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_connect_mode, tc) { cap_channel_t *capnet; @@ -1154,7 +1250,11 @@ ATF_TC_BODY(capnet__limits_connect_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_connect_dns_mode); +ATF_TC(capnet__limits_connect_dns_mode); +ATF_TC_HEAD(capnet__limits_connect_dns_mode, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_connect_dns_mode, tc) { cap_channel_t *capnet; @@ -1186,7 +1286,11 @@ ATF_TC_BODY(capnet__limits_connect_dns_mode, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_connect); +ATF_TC(capnet__limits_connect); +ATF_TC_HEAD(capnet__limits_connect, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_connect, tc) { cap_channel_t *capnet; @@ -1230,7 +1334,11 @@ ATF_TC_BODY(capnet__limits_connect, tc) cap_close(capnet); } -ATF_TC_WITHOUT_HEAD(capnet__limits_connecttodns); +ATF_TC(capnet__limits_connecttodns); +ATF_TC_HEAD(capnet__limits_connecttodns, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_connecttodns, tc) { cap_channel_t *capnet; @@ -1279,7 +1387,11 @@ ATF_TC_BODY(capnet__limits_connecttodns, tc) } -ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_connecttodns); +ATF_TC(capnet__limits_deprecated_connecttodns); +ATF_TC_HEAD(capnet__limits_deprecated_connecttodns, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} ATF_TC_BODY(capnet__limits_deprecated_connecttodns, tc) { cap_channel_t *capnet; 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/getsockopt.2 b/lib/libsys/getsockopt.2 index 8839b61597a2..3867824681d7 100644 --- a/lib/libsys/getsockopt.2 +++ b/lib/libsys/getsockopt.2 @@ -593,6 +593,15 @@ specified amount of time has elapsed since the initial call to If .Fa sp_fd is -1, the socket will be unspliced immediately. +A successful +.Xr select 2 , +.Xr poll 2 , +or +.Xr kqueue 2 +operation testing the ability to read from the source socket indicates +that the splicing has terminated and at least one byte is available for +reading. +When one of the sockets gets closed, splicing ends. .Pp When passed to .Fn getsockopt , 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/dma/dmagent/Makefile b/libexec/dma/dmagent/Makefile index 5f7deeea0b05..f707cfa3264f 100644 --- a/libexec/dma/dmagent/Makefile +++ b/libexec/dma/dmagent/Makefile @@ -15,14 +15,16 @@ SRCS= aliases_parse.y \ net.c \ spool.c \ util.c -MAN8= dma.8 +MAN= dma.8 MLINKS= dma.8 dma.conf.5 -CONFS= dma.conf +CONFSMODE= 0640 +CONFSGRP= mail +CONFS= auth.conf dma.conf CONFSDIR= ${CONFDIR}/dma CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L YFLAGS+= -i CLEANFILES= aliases_parse.i -FILES= auth.conf mailer.conf +FILES= mailer.conf FILESDIR= ${SHAREDIR}/examples/dma BINMODE= 2555 diff --git a/libexec/rc/rc b/libexec/rc/rc index 5ed47d6eac20..db3c3e20ab44 100644 --- a/libexec/rc/rc +++ b/libexec/rc/rc @@ -83,9 +83,9 @@ fi trap "_rc_conf_loaded=false; load_rc_config" ALRM skip="-s nostart" -if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then +if check_jail jailed; then skip="$skip -s nojail" - if [ `/sbin/sysctl -n security.jail.vnet` -ne 1 ]; then + if ! check_jail vnet; then skip="$skip -s nojailvnet" fi fi 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/Makefile b/libexec/rc/rc.d/Makefile index 8199779e5772..27d8a7526691 100644 --- a/libexec/rc/rc.d/Makefile +++ b/libexec/rc/rc.d/Makefile @@ -223,7 +223,7 @@ FTPDPACKAGE= ftpd .if ${MK_GSSAPI} != "no" CONFGROUPS+= GSSD GSSD= gssd -GSSDPACKAGE= kerberos +GSSDPACKAGE= gssd .endif .if ${MK_HAST} != "no" diff --git a/libexec/rc/rc.d/hostname b/libexec/rc/rc.d/hostname index 8b26c4f60633..0bc31ccd787e 100755 --- a/libexec/rc/rc.d/hostname +++ b/libexec/rc/rc.d/hostname @@ -42,8 +42,8 @@ hostname_start() # If we are not inside a jail, set the host name. # If we are inside a jail, set the host name if it is permitted. # - if [ `$SYSCTL_N security.jail.jailed` -eq 1 ]; then - if [ `$SYSCTL_N security.jail.set_hostname_allowed` -eq 0 ]; then + if check_jail jailed; then + if ! check_jail set_hostname_allowed; then return fi else 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/rc/rc.d/routing b/libexec/rc/rc.d/routing index 893acb83cf4a..dd75604125a3 100755 --- a/libexec/rc/rc.d/routing +++ b/libexec/rc/rc.d/routing @@ -331,7 +331,7 @@ _check_dynamicrouting() # copied from /etc/rc skip="-s nostart" - if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then + if check_jail jailed; then skip="$skip -s nojail" fi [ -n "$local_startup" ] && find_local_scripts_new diff --git a/libexec/rc/rc.d/zfs b/libexec/rc/rc.d/zfs index 26bf3046444b..f88f65c2ec18 100755 --- a/libexec/rc/rc.d/zfs +++ b/libexec/rc/rc.d/zfs @@ -18,7 +18,7 @@ required_modules="zfs" zfs_start_jail() { - if [ `$SYSCTL_N security.jail.mount_allowed` -eq 1 ]; then + if check_jail mount_allowed; then zfs mount -a fi } @@ -34,7 +34,7 @@ zfs_start_main() zfs_start() { - if [ `$SYSCTL_N security.jail.jailed` -eq 1 ]; then + if check_jail jailed; then zfs_start_jail else zfs_start_main @@ -54,7 +54,7 @@ zfs_poststart() zfs_stop_jail() { - if [ `$SYSCTL_N security.jail.mount_allowed` -eq 1 ]; then + if check_jail mount_allowed; then zfs unmount -a fi } @@ -67,7 +67,7 @@ zfs_stop_main() zfs_stop() { - if [ `$SYSCTL_N security.jail.jailed` -eq 1 ]; then + if check_jail jailed; then zfs_stop_jail else zfs_stop_main diff --git a/libexec/rc/rc.d/zfsbe b/libexec/rc/rc.d/zfsbe index f61f3bf097f0..22d53f219679 100755 --- a/libexec/rc/rc.d/zfsbe +++ b/libexec/rc/rc.d/zfsbe @@ -64,7 +64,7 @@ activate_bootonce() be_start() { - if [ `$SYSCTL_N security.jail.jailed` -eq 1 ]; then + if check_jail jailed; then : else mount -p | while read _dev _mp _type _rest; do diff --git a/libexec/rc/rc.shutdown b/libexec/rc/rc.shutdown index 18f67f5ca124..3dfd7a7e0936 100644 --- a/libexec/rc/rc.shutdown +++ b/libexec/rc/rc.shutdown @@ -83,9 +83,9 @@ fi # and perform the operation # rcorder_opts="-k shutdown" -if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then +if check_jail jailed; then rcorder_opts="$rcorder_opts -s nojail" - if [ `/sbin/sysctl -n security.jail.vnet` -ne 1 ]; then + if ! check_jail vnet; then rcorder_opts="$rcorder_opts -s nojailvnet" fi fi diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr index 2eaf336b5220..a2e2e98a5087 100644 --- a/libexec/rc/rc.subr +++ b/libexec/rc/rc.subr @@ -1689,7 +1689,7 @@ $_cpusetcmd $command $rc_flags $command_args" start) # We cannot use protect(1) inside jails. if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] && - [ "$(sysctl -n security.jail.jailed)" -eq 0 ]; then + ! check_jail jailed; then [ -z "${rc_pid}" ] && eval $_pidcmd case $_oomprotect in [Aa][Ll][Ll]) @@ -2671,7 +2671,7 @@ check_required_after() } # check_jail mib -# Return true if security.jail.$mib exists and set to 1. +# Return true if security.jail.$mib exists and is set to 1. check_jail() { diff --git a/libexec/rc/tests/rc_subr_test.sh b/libexec/rc/tests/rc_subr_test.sh index 60f77c2c2de3..9931389e7a02 100644 --- a/libexec/rc/tests/rc_subr_test.sh +++ b/libexec/rc/tests/rc_subr_test.sh @@ -52,7 +52,7 @@ oomprotect_all_body() _rc_arg="$4" setvar "${name}_oomprotect" all command="/usr/sbin/daemon" - command_args="-P $pidfile -p $_childpidfile -- /bin/sleep 5" + command_args="-P $pidfile -p $_childpidfile -- /bin/sleep 60" run_rc_command "$_rc_arg" LITERAL @@ -92,7 +92,7 @@ oomprotect_yes_body() setvar "${name}_oomprotect" yes procname="/bin/sleep" command="/usr/sbin/daemon" - command_args="-p $pidfile -- $procname 5" + command_args="-p $pidfile -- $procname 60" run_rc_command "$_rc_arg" LITERAL 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/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c index f8f9bd549a2e..a3faee86e7d0 100644 --- a/libexec/tftpd/tftpd.c +++ b/libexec/tftpd/tftpd.c @@ -351,10 +351,14 @@ main(int argc, char *argv[]) tftp_log(LOG_ERR, "chdir: %s", strerror(errno)); exit(1); } - if (setgroups(1, &nobody->pw_gid) != 0) { + if (setgroups(0, NULL) != 0) { tftp_log(LOG_ERR, "setgroups failed"); exit(1); } + if (setgid(nobody->pw_gid) != 0) { + tftp_log(LOG_ERR, "setgid failed"); + exit(1); + } if (setuid(nobody->pw_uid) != 0) { tftp_log(LOG_ERR, "setuid failed"); exit(1); 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..a243c6ea7ad0 100755 --- a/release/packages/generate-ucl.lua +++ b/release/packages/generate-ucl.lua @@ -3,33 +3,184 @@ --[[ 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.", + }, +} + +-- A list of packages which don't get the automatic suffix handling, +-- e.g. -man packages with no corresponding base package. +local no_suffix_pkgs = { + ["kernel-man"] = true, +} + +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, + ["kernel-man"] = 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. +if no_suffix_pkgs[pkgname] == nil then + add_suffixes(obj) +end + +-- 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/gssd-all.ucl b/release/packages/ucl/gssd-all.ucl new file mode 100644 index 000000000000..5a01b0559854 --- /dev/null +++ b/release/packages/ucl/gssd-all.ucl @@ -0,0 +1,11 @@ +comment = "gssd(8) daemon for kernel GSS-API" +desc = <<EOD +The Generic Security Services (GSS) API is used to perform authentication over +a network connection, most commonly when using Kerberos authentication. + +The kernel contains an implementation of GSS-API primarily for use by the NFS +client and server. When kernel GSS-API is in use, gssd(8) allows the kernel +to fetch authentication data such as Kerberos tickets from userland. + +This daemon is required when using Kerberos authentication with NFS. +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/kernel-man.ucl b/release/packages/ucl/kernel-man.ucl new file mode 100644 index 000000000000..9d70baf2c3af --- /dev/null +++ b/release/packages/ucl/kernel-man.ucl @@ -0,0 +1,5 @@ +comment = "Kernel manual pages" +desc = <<EOD +Manual pages for kernel interfaces and drivers (section 4) and the kernel +developer manual pages (section 9). +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/devd/moused.conf b/sbin/devd/moused.conf index 002edad9a8a9..ed1060ffdf2e 100644 --- a/sbin/devd/moused.conf +++ b/sbin/devd/moused.conf @@ -31,5 +31,5 @@ notify 100 { match "type" "DESTROY"; match "cdev" "ums[0-9]+"; - action "service moused stop $cdev"; + action "service moused quietstop $cdev"; }; diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index cbab3fa2973c..5d2a7453578b 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -539,7 +539,7 @@ main(int argc, char *argv[]) setproctitle("%s", ifi->name); /* setgroups(2) is not permitted in capability mode. */ - if (setgroups(1, &pw->pw_gid) != 0) + if (setgroups(0, NULL) != 0) error("can't restrict groups: %m"); if (caph_enter_casper() < 0) diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index ce5d2f4894fa..3465dc223ada 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -217,8 +217,9 @@ bridge_status(if_ctx *ctx) printf("%s%s ", prefix, member->ifbr_ifsname); printb("flags", member->ifbr_ifsflags, IFBIFBITS); printf("\n%s", pad); - printf("ifmaxaddr %u port %u priority %u path cost %u", - member->ifbr_addrmax, + if (member->ifbr_addrmax != 0) + printf("ifmaxaddr %u ", member->ifbr_addrmax); + printf("port %u priority %u path cost %u", member->ifbr_portno, member->ifbr_priority, member->ifbr_path_cost); 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/mount_fusefs/Makefile b/sbin/mount_fusefs/Makefile index e683b35f0c8a..a237ba99eb6b 100644 --- a/sbin/mount_fusefs/Makefile +++ b/sbin/mount_fusefs/Makefile @@ -20,7 +20,7 @@ DEBUG_FLAGS+= -DFUSE4BSD_VERSION="\"${F4BVERS}\"" PACKAGE=runtime PROG= mount_fusefs -MAN8= mount_fusefs.8 +MAN= mount_fusefs.8 LIBADD= util .include <bsd.prog.mk> 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/man1/Makefile b/share/man/man1/Makefile index 5b1d3ac1091d..d3975c8e8084 100644 --- a/share/man/man1/Makefile +++ b/share/man/man1/Makefile @@ -1,16 +1,17 @@ .include <src.opts.mk> -MAN= builtin.1 intro.1 +MANGROUPS= MAN -.if ${MK_TESTS} != "no" -ATF= ${SRCTOP}/contrib/atf -.PATH: ${ATF}/doc -MAN+= atf-test-program.1 -.endif +MANLINKS= intro.1 introduction.1 + +MANGROUPS+= RUNTIME +RUNTIME= builtin.1 intro.1 +RUNTIMEPACKAGE= runtime # Create MLINKS for Shell built in commands for which there are no userland # utilities of the same name: -MLINKS= builtin.1 alias.1 \ +RUNTIMELINKS=\ + builtin.1 alias.1 \ builtin.1 alloc.1 \ builtin.1 bg.1 \ builtin.1 bind.1 \ @@ -96,6 +97,13 @@ MLINKS= builtin.1 alias.1 \ builtin.1 wait.1 \ builtin.1 where.1 \ builtin.1 while.1 -MLINKS+=intro.1 introduction.1 + +.if ${MK_TESTS} != "no" +MANGROUPS+= TESTS +ATF= ${SRCTOP}/contrib/atf +.PATH: ${ATF}/doc +TESTS= atf-test-program.1 +TESTSPACKAGE= tests +.endif .include <bsd.prog.mk> diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile index 6cdd443ec067..3511acb254e1 100644 --- a/share/man/man3/Makefile +++ b/share/man/man3/Makefile @@ -1,5 +1,7 @@ .include <src.opts.mk> +PACKAGE= clibs + MAN= alloca.3 \ arb.3 \ assert.3 \ diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 7c8a8f3afc45..1ba1fe46523e 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,5 +1,8 @@ .include <src.opts.mk> +MANGROUPS= MAN +MANPACKAGE= kernel + # If you add a new file here, please consider adding an entry to the # hardware notes template (website/archetypes/release/hardware.adoc in # the doc repository); otherwise the automatically generated hardware @@ -58,7 +61,6 @@ MAN= aac.4 \ atkbdc.4 \ ${_atopcase.4} \ atp.4 \ - ${_atf_test_case.4} \ ${_atrtc.4} \ ${_attimer.4} \ audit.4 \ @@ -594,6 +596,7 @@ MAN= aac.4 \ tws.4 \ udp.4 \ udplite.4 \ + ${_ufshci.4} \ unionfs.4 \ ure.4 \ vale.4 \ @@ -746,7 +749,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 +940,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 @@ -980,11 +986,14 @@ _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 \ @@ -1016,9 +1025,11 @@ MAN+= mlx5io.4 .endif .if ${MK_TESTS} != "no" +MANGROUPS+= TESTS ATF= ${SRCTOP}/contrib/atf .PATH: ${ATF}/doc -_atf_test_case.4= atf-test-case.4 +TESTS= atf-test-case.4 +TESTSPACKAGE= tests .endif .if ${MK_PF} != "no" diff --git a/share/man/man4/dtrace_dtrace.4 b/share/man/man4/dtrace_dtrace.4 new file mode 100644 index 000000000000..b8c31005b47e --- /dev/null +++ b/share/man/man4/dtrace_dtrace.4 @@ -0,0 +1,191 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Mateusz Piotrowski <0mp@FreeBSD.org> +.\" +.Dd July 14, 2025 +.Dt DTRACE_DTRACE 4 +.Os +.Sh NAME +.Nm dtrace_dtrace +.Nd a DTrace provider for BEGIN, END, and ERROR probes +.Sh SYNOPSIS +.Nm dtrace Ns Cm :::BEGIN +.Nm dtrace Ns Cm :::END +.Nm dtrace Ns Cm :::ERROR +.Sh DESCRIPTION +The +.Nm dtrace +provider implements three special probes related to the life cycle of the +DTrace program itself. +.Ss dtrace:::BEGIN +The +.Nm dtrace Ns Cm :::BEGIN +probe fires at the beginning of a +.Xr dtrace 1 , +program before tracing has begun. +It provides a convenient place for initializing variables +and printing column headers. +.Pp +Variables such as +.Va stack +or +.Va execname +cannot be relied upon in the execution context of the +.Nm dtrace Ns Cm :::BEGIN +probe. +.Ss dtrace:::END +The +.Nm dtrace Ns Cm :::END +probe fires at the end of a +.Xr dtrace 1 +program, when all tracing has stopped. +.Ss dtrace:::ERROR +The +.Nm dtrace Ns Cm :::ERROR +probe fires when an unexpected runtime error occurs in another probe. +.Pp +The following table describes the arguments to +.Nm dtrace Ns Cm :::ERROR . +.Bl -column -offset indent "Argument" "Definition" +.It Sy Argument Ta Sy Definition +.It Fa arg1 Ta Enabled probe identifier (EPID) +of the probe where the runtime error occurred +.It Fa arg2 Ta Index of the action statement that caused the error +.It Fa arg3 Ta DIF offset into the action if available (otherwise -1) +.It Fa arg4 Ta Fault type +.It Fa arg5 Ta Accessed address (or 0 if not applicable) when +.Va arg4 +is of fault type +.Dv DTRACEFLT_BADADDR , DTRACEFLT_BADALIGN , DTRACEFLT_KPRIV , +or +.Dv DTRACEFLT_UPRIV +.El +.Pp +The fault types are: +.Bl -tag -offset indent -width "DTRACEFLT_NOSCRATCH" -compact +.It Dv DTRACEFLT_UNKNOWN +Unknown fault +.It Dv DTRACEFLT_BADADDR +Bad address +.It Dv DTRACEFLT_BADALIGN +Bad alignment +.It Dv DTRACEFLT_ILLOP +Illegal operation +.It Dv DTRACEFLT_DIVZERO +Divide-by-zero +.It Dv DTRACEFLT_NOSCRATCH +Out of scratch space +.It Dv DTRACEFLT_KPRIV +Illegal kernel access +.It Dv DTRACEFLT_UPRIV +Illegal user access +.It Dv DTRACEFLT_TUPOFLOW +Tuple stack overflow +.It Dv DTRACEFLT_BADSTACK +Bad stack +.El +.Sh FILES +.Bl -tag -width '<sys/dtrace.h>' +.It In sys/dtrace.h +The header file containing the definitions of DTrace fault types. +.El +.Sh EXAMPLES +.Ss Example 1 : Custom Column Headers +The following script uses the +.Nm dtrace Ns Cm :::BEGIN +probe to print column headers. +Note the pragma line setting the +.Ql quiet +option to disable the default column headers. +.Bd -literal -offset 2n +#pragma D option quiet + +dtrace:::BEGIN +{ + printf(" %12s %-20s %-20s %s\en", + "DELTA(us)", "OLD", "NEW", "TIMESTAMP"); +} +.Ed +.Ss Example 2 : Handling Runtime Errors with dtrace:::ERROR +The following script causes a runtime error by dereferencing a pointer +on address +.Ad 19930908 +in the +.Cm BEGIN +probe. +As a result, the +.Cm ERROR +probe fires and prints out +.Dq Oops +along with the probe arguments. +At that point, the program ends and fires the +.Cm END +probe. +.\" It might look weird to define ERROR first, but that is on purpose. +.\" This way the probe IDs and EPIDs are a bit more mixed up +.\" and are easier to understand. +.Bd -literal -offset 2n +ERROR +{ + printf("Oops\en"); + printf("EPID (arg1): %d\en", arg1); + printf("Action index (arg2): %d\en", arg2); + printf("DIF offset (arg3): %d\en", arg3); + printf("Fault type (arg4): %d\en", arg4); + printf("Accessed address (arg5): %X\en", arg5); + exit(1); +} +BEGIN +{ + *(int *)0x19931101; +} +END { + printf("Bye"); +} +.Ed +.Pp +This script will result in the following output: +.Bd -literal -offset 2n +CPU ID FUNCTION:NAME + 2 3 :ERROR Oops +EPID (arg1): 2 +Action index (arg2): 1 +DIF offset (arg3): 16 +Fault type: 1 +arg5: 19931101 + +dtrace: error on enabled probe ID 2 (ID 1: dtrace:::BEGIN): invalid address (0x19931101) in action #1 at DIF offset 16 + 2 2 :END Bye +.Ed +.Sh SEE ALSO +.Xr dtrace 1 , +.Xr tracing 7 +.Rs +.%B The illumos Dynamic Tracing Guide +.%O Chapter dtrace Provider +.%D 2008 +.%U https://illumos.org/books/dtrace/chp-dtrace.html +.Re +.Sh AUTHORS +This manual page was written by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . +.Sh CAVEATS +The +.Nm dtrace Ns Cm :::ERROR +probe arguments cannot be accessed through the typed +.Va args[] +array. +.Pp +.Xr dtrace 1 +will not fire the +.Nm dtrace Ns Cm :::ERROR +probe recursively. +If an error occurs in one of the action statements of the +.Nm dtrace Ns Cm :::ERROR , +then +.Xr dtrace 1 +will abort further processing of +the +.Nm dtrace Ns Cm :::ERROR +probe's actions. 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/hwt.4 b/share/man/man4/hwt.4 index df02a4672f36..299332c72542 100644 --- a/share/man/man4/hwt.4 +++ b/share/man/man4/hwt.4 @@ -3,7 +3,7 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd July 7, 2025 +.Dd July 12, 2025 .Dt HWT 4 .Os .Sh NAME @@ -131,6 +131,7 @@ For SPE-only, the kernel is waiting for userspace to notify that it has copied out a buffer to avoid data loss/overwriting buffers. .El .Sh SEE ALSO +.Xr tracing 7 , .Xr hwt 8 .Sh HISTORY The diff --git a/share/man/man4/ice.4 b/share/man/man4/ice.4 index 63fdb244f3ed..3f7a9017756d 100644 --- a/share/man/man4/ice.4 +++ b/share/man/man4/ice.4 @@ -32,18 +32,18 @@ .\" .\" * Other names and brands may be claimed as the property of others. .\" -.Dd May 20, 2024 +.Dd March 28, 2025 .Dt ICE 4 .Os .Sh NAME .Nm ice -.Nd "Intel Ethernet 800 Series Driver" +.Nd "Intel\(rg Ethernet 800 Series 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 iflib" -.Cd "device ice" +.Bd -literal -offset indent +.Cd device iflib +.Cd device ice .Ed .Pp To load the driver as a module at boot time, place the following lines in @@ -57,7 +57,7 @@ The .Nm driver provides support for any PCI Express adapter or LOM (LAN On Motherboard) -in the Intel Ethernet 800 Series. +in the Intel\(rg Ethernet 800 Series. As of this writing, the series includes devices with these model numbers: .Pp .Bl -bullet -compact @@ -73,6 +73,16 @@ Intel\(rg Ethernet Connection E822\-L Intel\(rg Ethernet Connection E823\-C .It Intel\(rg Ethernet Connection E823\-L +.It +Intel\(rg Ethernet Connection E825\-C +.It +Intel\(rg Ethernet Connection E830\-C +.It +Intel\(rg Ethernet Connection E830\-CC +.It +Intel\(rg Ethernet Connection E830\-L +.It +Intel\(rg Ethernet Connection E830\-XXV .El .Pp For questions related to hardware requirements, refer to the documentation @@ -83,11 +93,17 @@ Selecting an MTU larger than 1500 bytes with the .Xr ifconfig 8 utility configures the adapter to receive and transmit Jumbo Frames. The maximum MTU size for Jumbo Frames is 9706. -This value coincides with the maximum Jumbo Frame size of 9728. +For more information, see the +.Sx Jumbo Frames +section. .Pp This driver version supports VLANs. -For information on enabling VLANs, see the -.Pa README . +For information on enabling VLANs, see +.Xr vlan 4 . +For additional information on configuring VLANs, see +.Xr ifconfig 8 Ap s +.Dq VLAN Parameters +section. .Pp Offloads are also controlled via the interface, for instance, checksumming for both IPv4 and IPv6 can be set and unset, TSO4 and/or TSO6, and finally LRO can @@ -95,29 +111,739 @@ be set and unset. .Pp For more information on configuring this device, see .Xr ifconfig 8 . +.Pp +The associated Virtual Function (VF) driver for this driver is +.Xr iavf 4 . +.Pp +The associated RDMA driver for this driver is +.Xr irdma 4 . +.Ss Dynamic Device Personalization +The DDP package loads during device initialization. +The driver looks for the +.Sy ice_ddp +module and checks that it contains a valid DDP package file. +.Pp +If the driver is unable to load the DDP package, the device will enter Safe +Mode. +Safe Mode disables advanced and performance features and supports only +basic traffic and minimal functionality, such as updating the NVM or +downloading a new driver or DDP package. +Safe Mode only applies to the affected physical function and does not impact +any other PFs. +See the +.Dq Intel\(rg Ethernet Adapters and Devices User Guide +for more details on DDP and Safe Mode. +.Pp +If you encounter issues with the DDP package file, you may need to download +an updated driver or +.Sy ice_ddp +module. +See the log messages for more information. +.Pp +You cannot update the DDP package if any PF drivers are already loaded. +To overwrite a package, unload all PFs and then reload the driver with the +new package. +.Pp +You can only use one DDP package per driver, even if you have more than one +device installed that uses the driver. +.Pp +Only the first loaded PF per device can download a package for that device. +.Ss Jumbo Frames +Jumbo Frames support is enabled by changing the Maximum Transmission Unit (MTU) +to a value larger than the default value of 1500. +.Pp +Use +.Xr ifconfig 8 +to increase the MTU size. +.Pp +The maximum MTU setting for jumbo frames is 9706. +This corresponds to the maximum jumbo frame size of 9728 bytes. +.Pp +This driver will attempt to use multiple page sized buffers to receive +each jumbo packet. +This should help to avoid buffer starvation issues when allocating receive +packets. +.Pp +Packet loss may have a greater impact on throughput when you use jumbo +frames. +If you observe a drop in performance after enabling jumbo frames, enabling +flow control may mitigate the issue. +.Ss Remote Direct Memory Access +Remote Direct Memory Access, or RDMA, allows a network device to transfer data +directly to and from application memory on another system, increasing +throughput and lowering latency in certain networking environments. +.Pp +The ice driver supports both the iWARP (Internet Wide Area RDMA Protocol) and +RoCEv2 (RDMA over Converged Ethernet) protocols. +The major difference is that iWARP performs RDMA over TCP, while RoCEv2 uses +UDP. +.Pp +Devices based on the Intel\(rg Ethernet 800 Series do not support RDMA when +operating in multiport mode with more than 4 ports. +.Pp +For detailed installation and configuration information for RDMA, see +.Xr irdma 4 . +.Ss RDMA Monitoring +For debugging/testing purposes, you can use sysctl to set up a mirroring +interface on a port. +The interface can receive mirrored RDMA traffic for packet +analysis tools like +.Xr tcpdump 1 . +This mirroring may impact performance. +.Pp +To use RDMA monitoring, you may need to reserve more MSI\-X interrupts. +Before the +.Nm +driver loads, configure the following tunable provided by +.Xr iflib 4 : +.Bd -literal -offset indent +dev.ice.<interface #>.iflib.use_extra_msix_vectors=4 +.Ed +.Pp +You may need to adjust the number of extra MSI\-X interrupt vectors. +.Pp +To create/delete the interface: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.create_interface=1 +sysctl dev.ice.<interface #>.delete_interface=1 +.Ed +.Pp +The mirrored interface receives both LAN and RDMA traffic. +Additional filters can be configured in tcpdump. +.Pp +To differentiate the mirrored interface from the primary interface, the network +interface naming convention is: +.Bd -literal -offset indent +<driver name><port number><modifier><modifier unit number> +.Ed +.Pp +For example, +.Dq Li ice0m0 +is the first mirroring interface on +.Dq Li ice0 . +.Ss Data Center Bridging +Data Center Bridging (DCB) is a configuration Quality of Service +implementation in hardware. +It uses the VLAN priority tag (802.1p) to filter traffic. +That means that there are 8 different priorities that traffic can be filtered +into. +It also enables priority flow control (802.1Qbb) which can limit or eliminate +the number of dropped packets during network stress. +Bandwidth can be allocated to each of these priorities, which is enforced at +the hardware level (802.1Qaz). +.Pp +DCB is normally configured on the network using the DCBX protocol (802.1Qaz), a +specialization of LLDP (802.1AB). The +.Nm +driver supports the following mutually exclusive variants of DCBX support: +.Bl -bullet -compact +.It +Firmware\-based LLDP Agent +.It +Software\-based LLDP Agent +.El +.Pp +In firmware\-based mode, firmware intercepts all LLDP traffic and handles DCBX +negotiation transparently for the user. +In this mode, the adapter operates in +.Dq willing +DCBX mode, receiving DCB settings from the link partner (typically a +switch). +The local user can only query the negotiated DCB configuration. +For information on configuring DCBX parameters on a switch, please consult the +switch manufacturer'ss documentation. +.Pp +In software\-based mode, LLDP traffic is forwarded to the network stack and user +space, where a software agent can handle it. +In this mode, the adapter can operate in +.Dq nonwilling +DCBX mode and DCB configuration can be both queried and set locally. +This mode requires the FW\-based LLDP Agent to be disabled. +.Pp +Firmware\-based mode and software\-based mode are controlled by the +.Dq fw_lldp_agent +sysctl. +Refer to the Firmware Link Layer Discovery Protocol Agent section for more +information. +.Pp +Link\-level flow control and priority flow control are mutually exclusive. +The ice driver will disable link flow control when priority flow control +is enabled on any traffic class (TC). +It will disable priority flow control when link flow control is enabled. +.Pp +To enable/disable priority flow control in software\-based DCBX mode: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.pfc=1 (or 0 to disable) +.Ed +.Pp +Enhanced Transmission Selection (ETS) allows you to assign bandwidth to certain +TCs, to help ensure traffic reliability. +To view the assigned ETS configuration, use the following: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.ets_min_rate +.Ed +.Pp +To set the minimum ETS bandwidth per TC, separate the values by commas. +All values must add up to 100. +For example, to set all TCs to a minimum bandwidth of 10% and TC 7 to 30%, +use the following: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.ets_min_rate=10,10,10,10,10,10,10,30 +.Ed +.Pp +To set the User Priority (UP) to a TC mapping for a port, separate the values +by commas. +For example, to map UP 0 and 1 to TC 0, UP 2 and 3 to TC 1, UP 4 and +5 to TC 2, and UP 6 and 7 to TC 3, use the following: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.up2tc_map=0,0,1,1,2,2,3,3 +.Ed +.Ss L3 QoS mode +The +.Nm +driver supports setting DSCP\-based Layer 3 Quality of Service (L3 QoS) +in the PF driver. +The driver initializes in L2 QoS mode by default; L3 QoS is disabled by +default. +Use the following sysctl to enable or disable L3 QoS: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.pfc_mode=1 (or 0 to disable) +.Ed +.Pp +If you disable L3 QoS mode, it returns to L2 QoS mode. +.Pp +To map a DSCP value to a traffic class, separate the values by commas. +For example, to map DSCPs 0\-3 and DSCP 8 to DCB TCs 0\-3 and 4, respectively: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.dscp2tc_map.0\-7=0,1,2,3,0,0,0,0 +sysctl dev.ice.<interface #>.dscp2tc_map.8\-15=4,0,0,0,0,0,0,0 +.Ed +.Pp +To change the DSCP mapping back to the default traffic class, set all the +values back to 0. +.Pp +To view the currently configured mappings, use the following: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.dscp2tc_map +.Ed +.Pp +L3 QoS mode is not available when FW\-LLDP is enabled. +.Pp +You also cannot enable FW\-LLDP if L3 QoS mode is active. +.Pp +Disable FW\-LLDP before switching to L3 QoS mode. +.Pp +Refer to the +.Sx Firmware Link Layer Discovery Protocol Agent +section in this README for more information on disabling FW\-LLDP. +.Ss Firmware Link Layer Discovery Protocol Agent +Use sysctl to change FW\-LLDP settings. +The FW\-LLDP setting is per port and persists across boots. +.Pp +To enable the FW\-LLDP Agent: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.fw_lldp_agent=1 +.Ed +.Pp +To disable the FW\-LLDP Agebt: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.fw_lldp_agent=0 +.Ed +.Pp +To check the current LLDP setting: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.fw_lldp_agent +.Ed +.Pp +You must enable the UEFI HII LLDP Agent attribute for this setting +to take effect. +If the +.Dq LLDP AGENT +attribute is set to disabled, you cannot enable the FW\-LLDP Agent from the +driver. +.Ss Link\-Level Flow Control (LFC) +Ethernet Flow Control (IEEE 802.3x) can be configured with sysctl to enable +receiving and transmitting pause frames for +.Nm . +When transmit is enabled, pause frames are generated when the receive packet +buffer crosses a predefined threshold. +When receive is enabled, the transmit unit will halt for the time delay +specified in the firmware when a pause frame is received. +.Pp +Flow Control is disabled by default. +.Pp +Use sysctl to change the flow control settings for a single interface without +reloading the driver: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.fc +.Ed +.Pp +The available values for flow control are: +.Bd -literal -offset indent +0 = Disable flow control +1 = Enable Rx pause +2 = Enable Tx pause +3 = Enable Rx and Tx pause +.Ed +.Pp +Verify that link flow control was negotiated on the link by checking the +interface entry in +.Xr ifconfig 8 +and looking for the flags +.Dq txpause +and/or +.Dq rxpause +in the +.Dq media +status. +.Pp +The +.Nm +driver requires flow control on both the port and link partner. +If flow control is disabled on one of the sides, the port may appear to +hang on heavy traffic. +.Pp +For more information on priority flow control, refer to the +.Sx Data Center Bridging +section. +.Pp +The VF driver does not have access to flow control. +It must be managed from the host side. +.Ss Forward Error Correction +Forward Error Correction (FEC) improves link stability but increases latency. +Many high quality optics, direct attach cables, and backplane channels can +provide a stable link without FEC. +.Pp +For devices to benefit from this feature, link partners must have FEC enabled. +.Pp +If you enable the sysctl +.Em allow_no_fec_modules_in_auto +Auto FEC negotiation will include +.Dq No FEC +in case your link partner does not have FEC enabled or is not FEC capable: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.allow_no_fec_modules_in_auto=1 +.Ed +.Pp +NOTE: This flag is currently not supported on the Intel\(rg Ethernet 830 +Series. +.Pp +To show the current FEC settings that are negotiated on the link: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.negotiated_fec +.Ed +.Pp +To view or set the FEC setting that was requested on the link: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.requested_fec +.Ed +.Pp +To see the valid FEC modes for the link: +.Bd -literal -offset indent +sysctl \-d dev.ice.<interface #>.requested_fec +.Ed +.Ss Speed and Duplex Configuration +You cannot set duplex or autonegotiation settings. +.Pp +To have your device change the speeds it will use in auto-negotiation or +force link with: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.advertise_speed=<mask> +.Ed +.Pp +Supported speeds will vary by device. +Depending on the speeds your device supports, valid bits used in a speed mask +could include: +.Bd -literal -offset indent +0x0 \- Auto +0x2 \- 100 Mbps +0x4 \- 1 Gbps +0x8 \- 2.5 Gbps +0x10 \- 5 Gbps +0x20 \- 10 Gbps +0x80 \- 25 Gbps +0x100 \- 40 Gbps +0x200 \- 50 Gbps +0x400 \- 100 Gbps +0x800 \- 200 Gbps +.Ed +.Ss Disabling physical link when the interface is brought down +When the +.Va link_active_on_if_down +sysctl is set to +.Dq 0 , +the port's link will go down when the interface is brought down. +By default, link will stay up. +.Pp +To disable link when the interface is down: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.link_active_on_if_down=0 +.Ed +.Ss Firmware Logging +The +.Nm +driver allows for the generation of firmware logs for supported categories of +events, to help debug issues with Customer Support. +Refer to the +.Dq Intel\(rg Ethernet Adapters and Devices User Guide +for an overview of this feature and additional tips. +.Pp +At a high level, to capture a firmware log: +.Bl -enum -compact +.It +Set the configuration for the firmware log. +.It +Perform the necessary steps to generate the issue you are trying to debug. +.It +Capture the firmware log. +.It +Stop capturing the firmware log. +.It +Reset your firmware log settings as needed. +.It +Work with Customer Support to debug the issue. +.El +.Pp +NOTE: Firmware logs are generated in a binary format and must be decoded by +Customer Support. +Information collected is related only to firmware and hardware for debug +purposes. +.Pp +Once the driver is loaded, it will create the +.Va fw_log +sysctl node under the debug section of the driver's sysctl list. +The driver groups these events into categories, called +.Dq modules . +Supported modules include: +.Pp +.Bl -tag -offset indent -compact -width "task_dispatch" +.It Va general +General (Bit 0) +.It Va ctrl +Control (Bit 1) +.It Va link +Link Management (Bit 2) +.It Va link_topo +Link Topology Detection (Bit 3) +.It Va dnl +Link Control Technology (Bit 4) +.It Va i2c +I2C (Bit 5) +.It Va sdp +SDP (Bit 6) +.It Va mdio +MDIO (Bit 7) +.It Va adminq +Admin Queue (Bit 8) +.It Va hdma +Host DMA (Bit 9) +.It Va lldp +LLDP (Bit 10) +.It Va dcbx +DCBx (Bit 11) +.It Va dcb +DCB (Bit 12) +.It Va xlr +XLR (function\-level resets; Bit 13) +.It Va nvm +NVM (Bit 14) +.It Va auth +Authentication (Bit 15) +.It Va vpd +Vital Product Data (Bit 16) +.It Va iosf +Intel On\-Chip System Fabric (Bit 17) +.It Va parser +Parser (Bit 18) +.It Va sw +Switch (Bit 19) +.It Va scheduler +Scheduler (Bit 20) +.It Va txq +TX Queue Management (Bit 21) +.It Va acl +ACL (Access Control List; Bit 22) +.It Va post +Post (Bit 23) +.It Va watchdog +Watchdog (Bit 24) +.It Va task_dispatch +Task Dispatcher (Bit 25) +.It Va mng +Manageability (Bit 26) +.It Va synce +SyncE (Bit 27) +.It Va health +Health (Bit 28) +.It Va tsdrv +Time Sync (Bit 29) +.It Va pfreg +PF Registration (Bit 30) +.It Va mdlver +Module Version (Bit 31) +.El +.Pp +You can change the verbosity level of the firmware logs. +You can set only one log level per module, and each level includes the +verbosity levels lower than it. +For instance, setting the level to +.Dq normal +will also log warning and error messages. +Available verbosity levels are: +.Pp +.Bl -item -offset indent -compact +.It +0 = none +.It +1 = error +.It +2 = warning +.It +3 = normal +.It +4 = verbose +.El +.Pp +To set the desired verbosity level for a module, use the following sysctl +command and then register it: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.debug.fw_log.severity.<module>=<level> +.Ed +.Pp +For example: +.Bd -literal -offset indent +sysctl dev.ice.0.debug.fw_log.severity.link=1 +sysctl dev.ice.0.debug.fw_log.severity.link_topo=2 +sysctl dev.ice.0.debug.fw_log.register=1 +.Ed +.Pp +To log firmware messages after booting, but before the driver initializes, use +.Xr kenv 1 +to set the tunable. +The +.Va on_load +setting tells the device to register the variable as soon as possible during +driver load. +For example: +.Bd -literal -offset indent +kenv dev.ice.0.debug.fw_log.severity.link=1 +kenv dev.ice.0.debug.fw_log.severity.link_topo=2 +kenv dev.ice.0.debug.fw_log.on_load=1 +.Ed +.Pp +To view the firmware logs and redirect them to a file, use the following +command: +.Bd -literal -offset indent +dmesg > log_output +.Ed +.Pp +NOTE: Logging a large number of modules or too high of a verbosity level will +add extraneous messages to dmesg and could hinder debug efforts. +.Ss Debug Dump +Intel\(rg Ethernet 800 Series devices support debug dump, which allows you to +obtain runtime register values from the firmware for +.Dq clusters +of events and then write the results to a single dump file, for debugging +complicated issues in the field. +.Pp +This debug dump contains a snapshot of the device and its existing hardware +configuration, such as switch tables, transmit scheduler tables, and other +information. +Debug dump captures the current state of the specified cluster(s) and is a +stateless snapshot of the whole device. +.Pp +NOTE: Like with firmware logs, the contents of the debug dump are not +human\-readable. +You must work with Customer Support to decode the file. +.Pp +Debug dump is per device, not per PF. +.Pp +Debug dump writes all information to a single file. +.Pp +To generate a debug dump file in +.Fx +do the following: +.Pp +Specify the cluster(s) to include in the dump file, using a bitmask and the +following command: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.debug.dump.clusters=<bitmask> +.Ed +.Pp +To print the complete cluster bitmask and parameter list to the screen, +pass the +.Fl d +argument. +For example: +.Bd -literal -offset indent +sysctl \-d dev.ice.0.debug.dump.clusters +.Ed +.Pp +Possible bitmask values for +.Va clusters +are: +.Bl -bullet -compact +.It +0 \- Dump all clusters (only supported on Intel\(rg Ethernet E810 Series and +Intel\(rg Ethernet E830 Series) +.It +0x1 \- Switch +.It +0x2 \- ACL +.It +0x4 \- Tx Scheduler +.It +0x8 \- Profile Configuration +.It +0x20 \- Link +.It +0x80 \- DCB +.It +0x100 \- L2P +.It +0x400000 \- Manageability Transactions (only supported on Intel\(rg Ethernet +E810 Series) +.El +.Pp +For example, to dump the Switch, DCB, and L2P clusters, use the following: +.Bd -literal -offset indent +sysctl dev.ice.0.debug.dump.clusters=0x181 +.Ed +.Pp +To dump all clusters, use the following: +.Bd -literal -offset indent +sysctl dev.ice.0.debug.dump.clusters=0 +.Ed +.Pp +NOTE: Using 0 will skip Manageability Transactions data. +.Pp +If you don't specify a cluster, the driver will dump all clusters to a +single file. +Issue the debug dump command, using the following: +.Bd -literal -offset indent +sysctl \-b dev.ice.<interface #>.debug.dump.dump=1 > dump.bin +.Ed +.Pp +NOTE: The driver will not receive the command if you do not write +.Dq 1 +to the sysctl. +.Pp +Replace +.Dq dump.bin +above with the file name you want to use. +.Pp +To clear the +.Va clusters +mask before a subsequent debug dump and then do the dump: +.Bd -literal -offset indent +sysctl dev.ice.0.debug.dump.clusters=0 +sysctl dev.ice.0.debug.dump.dump=1 +.Ed +.Ss Debugging PHY Statistics +The ice driver supports the ability to obtain the values of the PHY registers +from Intel(R) Ethernet 810 Series devices in order to debug link and +connection issues during runtime. +.Pp +The driver allows you to obtain information about: +.Bl -bullet +.It +Rx and Tx Equalization parameters +.It +RS FEC correctable and uncorrectable block counts +.El +.Pp +Use the following sysctl to read the PHY registers: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.debug.phy_statistics +.Ed +.Pp +NOTE: The contents of the registers are not human\-readable. +Like with firmware logs and debug dump, you must work with Customer Support +to decode the file. +.Ss Transmit Balancing +Some Intel(R) Ethernet 800 Series devices allow you to enable a transmit +balancing feature to improve transmit performance under certain conditions. +When the feature is enabled, you should experience more consistent transmit +performance across queues and/or PFs and VFs. +.Pp +By default, transmit balancing is disabled in the NVM. +To enable this feature, use one of the following to persistently change the +setting for the device: +.Bl -bullet +.It +Use the Ethernet Port Configuration Tool (EPCT) to enable the +.Va tx_balancing +option. +Refer to the EPCT readme for more information. +.It +Enable the Transmit Balancing device setting in UEFI HII. +.El +.Pp +When the driver loads, it reads the transmit balancing setting from the NVM and +configures the device accordingly. +.Pp +NOTE: The user selection for transmit balancing in EPCT or HII is persistent +across reboots. +You must reboot the system for the selected setting to take effect. +.Pp +This setting is device wide. +.Pp +The driver, NVM, and DDP package must all support this functionality to +enable the feature. +.Ss Thermal Monitoring +Intel(R) Ethernet 810 Series and Intel(R) Ethernet 830 Series devices can +display temperature data (in degrees Celsius) via: +.Bd -literal -offset indent +sysctl dev.ice.<interface #>.temp +.Ed +.Ss Network Memory Buffer Allocation +.Fx +may have a low number of network memory buffers (mbufs) by default. +If the number of mbufs available is too low, it may cause the driver to fail +to initialize and/or cause the system to become unresponsive. +You can check to see if the system is mbuf\-starved by running +.Ic netstat Fl m . +Increase the number of mbufs by editing the lines below in +.Pa /etc/sysctl.conf : +.Bd -literal -offset indent +kern.ipc.nmbclusters +kern.ipc.nmbjumbop +kern.ipc.nmbjumbo9 +kern.ipc.nmbjumbo16 +kern.ipc.nmbufs +.Ed +.Pp +The amount of memory that you allocate is system specific, and may require some +trial and error. +Also, increasing the following in +.Pa /etc/sysctl.conf +could help increase network performance: +.Bd -literal -offset indent +kern.ipc.maxsockbuf +net.inet.tcp.sendspace +net.inet.tcp.recvspace +net.inet.udp.maxdgram +net.inet.udp.recvspace +.Ed .Ss Additional Utilities There are additional tools available from Intel to help configure and update the adapters covered by this driver. These tools can be downloaded directly from Intel at .Lk https://downloadcenter.intel.com , -by searching for their names, or by installing certain packages: +by searching for their names: .Bl -bullet .It -To change the behavior of the QSFP28 ports on E810-C adapters, use the -Intel EPCT (Ethernet Port configuration tool); installed by the -.Em sysutils/intel-epct -package. +To change the behavior of the QSFP28 ports on E810-C adapters, use the Intel +.Sy Ethernet Port Configuration Tool - FreeBSD . .It -To update the firmware on an adapter, use the Intel Non-Volatile Memory (NVM) -Update Utility for Intel Network Adapter 800 series; installed by the -.Em sysutils/intel-nvmupdate-100g -package. +To update the firmware on an adapter, use the Intel +.Sy Non-Volatile Memory (NVM) Update Utility for Intel Ethernet Network Adapters E810 series - FreeBSD .El .Sh HARDWARE The .Nm driver supports the Intel Ethernet 800 series. -Most adapters in this series with SFP28/QSFP28 cages +Some adapters in this series with SFP28/QSFP28 cages have firmware that requires that Intel qualified modules are used; these qualified modules are listed below. This qualification check cannot be disabled by the driver. @@ -173,6 +899,38 @@ SFF-8472 v10.4 specifications. .Pp This is not an exhaustive list; please consult product documentation for an up-to-date list of supported media. +.Ss Fiber optics and auto\-negotiation +Modules based on 100GBASE\-SR4, active optical cable (AOC), and active copper +cable (ACC) do not support auto\-negotiation per the IEEE specification. +To obtain link with these modules, auto\-negotiation must be turned off on the +link partner's switch ports. +.Ss PCI-Express Slot Bandwidth +Some PCIe x8 slots are actually configured as x4 slots. +These slots have insufficient bandwidth for full line rate with dual port and +quad port devices. +In addition, if you put a PCIe v4.0 or v3.0\-capable adapter into a PCIe v2.x +slot, you cannot get full bandwidth. +.Pp +The driver detects this situation and writes the following message in the +system log: +.Bd -literal -offset indent +PCI\-Express bandwidth available for this device may be insufficient for +optimal performance. +Please move the device to a different PCI\-e link with more lanes and/or +higher transfer rate. +.Ed +.Pp +If this error occurs, moving your adapter to a true PCIe x8 or x16 slot will +resolve the issue. +For best performance, install devices in the following PCI slots: +.Bl -bullet +.It +Any 100Gbps\-capable Intel(R) Ethernet 800 Series device: Install in a +PCIe v4.0 x8 or v3.0 x16 slot +.It +A 200Gbps\-capable Intel(R) Ethernet 830 Series device: Install in a +PCIe v5.0 x8 or v4.0 x16 slot +.El .Sh LOADER TUNABLES Tunables can be set at the .Xr loader 8 @@ -182,42 +940,62 @@ See the .Xr iflib 4 man page for more information on using iflib sysctl variables as tunables. .Bl -tag -width indent -.It Va hw.ice.#.enable_health_events -TBW -.It Va hw.ice.#.debug.enable_tx_fc_filter -TBW -.It Va hw.ice.#.debug.enable_tx_lldp_filter -TBW -.It Va hw.ice.#.debug.enable_health_events -TBW -.El -.Sh SYSCTL PROCEDURES +.It Va hw.ice.enable_health_events +Set to 1 to enable firmware health event reporting across all devices. +Enabled by default. +.Pp +If enabled, when the driver receives a firmware health event message, it will +print out a description of the event to the kernel message buffer and if +applicable, possible actions to take to remedy it. +.It Va hw.ice.irdma +Set to 1 to enable the RDMA client interface, required by the +.Xr irdma 4 +driver. +Enabled by default. +.It Va hw.ice.rdma_max_msix +Set the maximum number of per-device MSI-X vectors that are allocated for use +by the +.Xr irdma 4 +driver. +Set to 64 by default. +.It Va hw.ice.debug.enable_tx_fc_filter +Set to 1 to enable the TX Flow Control filter across all devices. +Enabled by default. +.Pp +If enabled, the hardware will drop any transmitted Ethertype 0x8808 control +frames that do not originate from the hardware. +.It Va hw.ice.debug.enable_tx_lldp_filter +Set to 1 to enable the TX LLDP filter across all devices. +Enabled by default. +.Pp +If enabled, the hardware will drop any transmitted Ethertype 0x88cc LLDP frames +that do not originate from the hardware. +This must be disabled in order to use LLDP daemon software such as +.Xr lldpd 8 . +.It Va hw.ice.debug.ice_tx_balance_en +Set to 1 to allow the driver to use the 5-layer Tx Scheduler tree topology if +configured by the DDP package. +.Pp +Enabled by default. +.El +.Sh SYSCTL VARIABLES .Bl -tag -width indent -.It Va dev.ice.#.fc -Allows one to set the flow control value. -A value of 0 disables flow control, 3 enables full, 1 is RX, and 2 is -TX pause. -.It Va dev.ice.#.advertise_speed -Allows one to set advertised link speeds, this will then cause a link -renegotiation. .It Va dev.ice.#.current_speed -This is a display of the current setting. +This is a display of the current link speed of the interface. +This is expected to match the speed of the media type in-use displayed by +.Xr ifconfig 8 . .It Va dev.ice.#.fw_version Displays the current firmware and NVM versions of the adapter. +This information should be submitted along with any support requests. .It Va dev.ice.#.ddp_version -TBW -.It Va dev.ice.#.requested_fec -TBW -.It Va dev.ice.#.negotiated_fec -TBW -.It Va dev.ice.#.fw_lldp_agent -TBW -.It Va dev.ice.#.ets_min_rate -TBW -.It Va dev.ice.#.up2tc_map -TBW -.It Va dev.ice.#.pfc -TBW +Displays the current DDP package version downloaded to the adapter. +This information should be submitted along with any support requests. +.It Va dev.ice.#.pba_number +Displays the Product Board Assembly Number. +May be used to help identify the type of adapter in use. +This sysctl may not exist depending on the adapter type. +.It Va dev.ice.#.hw.mac.* +This sysctl tree contains statistics collected by the hardware for the port. .El .Sh INTERRUPT STORMS It is important to note that 100G operation can generate high @@ -226,21 +1004,77 @@ a storm condition in the kernel. It is suggested that this be resolved by setting .Va hw.intr_storm_threshold to 0. +.Sh IOVCTL OPTIONS +The driver supports additional optional parameters for created VFs +(Virtual Functions) when using +.Xr iovctl 8 : +.Bl -tag -width indent +.It mac-addr Pq unicast-mac +Set the Ethernet MAC address that the VF will use. +If unspecified, the VF will use a randomly generated MAC address and +.Dq allow-set-mac +will be set to true. +.It mac-anti-spoof Pq bool +Prevent the VF from sending Ethernet frames with a source address +that does not match its own. +Enabled by default. +.It allow-set-mac Pq bool +Allow the VF to set its own Ethernet MAC address. +Disallowed by default. +.It allow-promisc Pq bool +Allow the VF to inspect all of the traffic sent to the port that it is created +on. +Disabled by default. +.It num-queues Pq uint16_t +Specify the number of queues the VF will have. +By default, this is set to the number of MSI\-X vectors supported by the VF +minus one. +.It mirror-src-vsi Pq uint16_t +Specify which VSI the VF will mirror traffic from by setting this to a value +other than \-1. +All traffic from that VSI will be mirrored to this VF. +Can be used as an alternative method to mirror RDMA traffic to another +interface than the method described in the +.Sx RDMA Monitoring +section. +Not affected by the +.Dq allow-promisc +parameter. +.It max-vlan-allowed Pq uint16_t +Specify maximum number of VLAN filters that the VF can use. +Receiving traffic on a VLAN requires a hardware filter which are a finite +resource; this is used to prevent a VF from starving other VFs or the PF of +filter resources. +By default, this is set to 16. +.It max-mac-filters Pq uint16_t +Specify maximum number of MAC address filters that the VF can use. +Each allowed MAC address requires a hardware filter which are a finite +resource; this is used to prevent a VF from starving other VFs or the PF of +filter resources. +The VF's default mac address does not count towards this limit. +By default, this is set to 64. +.El +.Pp +An up to date list of parameters and their defaults can be found by using +.Xr iovctl 8 +with the +.Fl S +option. +.Pp +For more information on standard and mandatory parameters, see +.Xr iovctl.conf 5 . .Sh SUPPORT -For general information and support, -go to the Intel support website at: +For general information and support, go to the Intel support website at: .Lk http://www.intel.com/support/ . .Pp If an issue is identified with this driver with a supported adapter, email all the specific information related to the issue to .Aq Mt freebsd@intel.com . .Sh SEE ALSO -.Xr arp 4 , .Xr iflib 4 , -.Xr netintro 4 , -.Xr ng_ether 4 , .Xr vlan 4 , -.Xr ifconfig 8 +.Xr ifconfig 8 , +.Xr sysctl 8 .Sh HISTORY The .Nm 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/Makefile b/share/man/man5/Makefile index e2abf1d60905..0f6559b236c6 100644 --- a/share/man/man5/Makefile +++ b/share/man/man5/Makefile @@ -1,14 +1,11 @@ .include <src.opts.mk> +MANGROUPS= MAN + #MISSING: dump.5 plot.5 -MAN= acct.5 \ - ar.5 \ - a.out.5 \ +MAN= a.out.5 \ ${_boot.config.5} \ core.5 \ - devfs.conf.5 \ - devfs.rules.5 \ - device.hints.5 \ dir.5 \ disktab.5 \ elf.5 \ @@ -16,32 +13,24 @@ MAN= acct.5 \ eui64.5 \ fbtab.5 \ forward.5 \ - fs.5 \ - fstab.5 \ group.5 \ hosts.5 \ hosts.equiv.5 \ - hosts.lpd.5 \ intro.5 \ libmap.conf.5 \ link.5 \ mailer.conf.5 \ make.conf.5 \ - moduli.5 \ motd.5 \ mount.conf.5 \ networks.5 \ - nsmb.conf.5 \ nsswitch.conf.5 \ os-release.5 \ - passwd.5 \ pbm.5 \ - periodic.conf.5 \ phones.5 \ portindex.5 \ protocols.5 \ quota.user.5 \ - rc.conf.5 \ rctl.conf.5 \ regdomain.5 \ remote.5 \ @@ -54,18 +43,6 @@ MAN= acct.5 \ style.mdoc.5 \ sysctl.conf.5 \ -MLINKS= dir.5 dirent.5 -MLINKS+=fs.5 inode.5 -MLINKS+=hosts.equiv.5 rhosts.5 -MLINKS+=passwd.5 master.passwd.5 -MLINKS+=passwd.5 pwd.db.5 -MLINKS+=passwd.5 spwd.db.5 -MLINKS+=portindex.5 INDEX.5 -MLINKS+=quota.user.5 quota.group.5 -MLINKS+=rc.conf.5 rc.conf.local.5 -MLINKS+=resolver.5 resolv.conf.5 -MLINKS+=src.conf.5 src-env.conf.5 - .if ${MK_BLUETOOTH} != "no" MAN+= bluetooth.device.conf.5 \ bluetooth.hosts.5 \ @@ -80,11 +57,68 @@ MAN+= freebsd-update.conf.5 MAN+= hesiod.conf.5 .endif +MLINKS= dir.5 dirent.5 +MLINKS+=fs.5 inode.5 +MLINKS+=hosts.equiv.5 rhosts.5 +MLINKS+=portindex.5 INDEX.5 +MLINKS+=quota.user.5 quota.group.5 +MLINKS+=resolver.5 resolv.conf.5 +MLINKS+=src.conf.5 src-env.conf.5 + +MANGROUPS+= ACCT +ACCT= acct.5 +ACCTPACKAGE= acct + +MANGROUPS+= BOOTLOADER +BOOTLOADER= device.hints.5 +BOOTLOADERPACKAGE=bootloader + +MANGROUPS+= CLANG +CLANG= ar.5 +CLANGPACKAGE= clang + +MANGROUPS+= LP +LP= hosts.lpd.5 +LPPACKAGE= lp + +MANGROUPS+= PERIODIC +PERIODIC= periodic.conf.5 +PERIODICPACKAGE=periodic + .if ${MK_PF} != "no" -MAN+= pf.conf.5 \ - pf.os.5 +MANGROUPS+= PF +PF= pf.conf.5 \ + pf.os.5 +PFPACKAGE= pf .endif +MANGROUPS+= RC +RC= rc.conf.5 +RCLINKS= rc.conf.5 rc.conf.local.5 +RCPACKAGE= rc + +MANGROUPS+= RUNTIME +RUNTIME= devfs.conf.5 \ + devfs.rules.5 \ + fstab.5 \ + passwd.5 +RUNTIMELINKS= passwd.5 master.passwd.5 +RUNTIMELINKS+= passwd.5 pwd.db.5 +RUNTIMELINKS+= passwd.5 spwd.db.5 +RUNTIMEPACKAGE= runtime + +MANGROUPS+= SMB +SMB= nsmb.conf.5 +SMBPACKAGE= smbutils + +MANGROUPS+= SSH +SSH= moduli.5 +SSHPACKAGE= ssh + +MANGROUPS+= UFS +UFS= fs.5 +UFSPACKAGE= ufs + # This makes more sense for amd64 and i386 but # we decide to install all manpages in all architectures _boot.config.5= boot.config.5 diff --git a/share/man/man5/core.5 b/share/man/man5/core.5 index 8efc8c970014..628fdb7920bb 100644 --- a/share/man/man5/core.5 +++ b/share/man/man5/core.5 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 12, 2023 +.Dd July 17, 2025 .Dt CORE 5 .Os .Sh NAME @@ -48,26 +48,6 @@ a system crash. (In this event, the decision to save the core file is arbitrary, see .Xr savecore 8 . ) .Pp -The maximum size of a core file is limited by the -.Dv RLIMIT_CORE -.Xr setrlimit 2 -limit. -Files which would be larger than the limit are not created. -.Pp -With a large limit, a process that had mapped a very large, -and perhaps sparsely populated, virtual memory region, could take -a very long time to create core dumps. -The system ignores all signals sent to a process writing a core file, except -.Dv SIGKILL -which terminates the writing and causes immediate exit of the process. -The behavior of -.Dv SIGKILL -can be disabled by setting tunable -.Xr sysctl 8 -variable -.Va kern.core_dump_can_intr -to zero. -.Pp The name of the file is controlled via the .Xr sysctl 8 variable @@ -107,6 +87,26 @@ yielding the traditional .Fx behaviour. .Pp +The maximum size of a core file is limited by the +.Dv RLIMIT_CORE +.Xr setrlimit 2 +limit. +Files which would be larger than the limit are not created. +.Pp +With a large limit, a process that had mapped a very large, +and perhaps sparsely populated, virtual memory region, could take +a very long time to create core dumps. +The system ignores all signals sent to a process writing a core file, except +.Dv SIGKILL +which terminates the writing and causes immediate exit of the process. +The behavior of +.Dv SIGKILL +can be disabled by setting tunable +.Xr sysctl 8 +variable +.Va kern.core_dump_can_intr +to zero. +.Pp By default, a process that changes user or group credentials whether real or effective will not create a corefile. This behaviour can be @@ -116,11 +116,13 @@ variable .Va kern.sugid_coredump to 1. .Pp -Corefiles can be compressed by the kernel if the following item -is included in the kernel configuration file: +Corefiles can be compressed by the kernel if one of the following items +are included in the kernel configuration file: .Bl -tag -width "1234567890" -compact -offset "12345" .It options GZIO +.It options +ZSTDIO .El .Pp The following sysctl control core file compression: 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..f93d3f9fc69f 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 27, 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,13 +935,14 @@ 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. To be able to build the system an alternate linker must be provided via XLD. -.It Va WITHOUT_LLVM_ASSERTIONS -Disable debugging assertions in LLVM. +.It Va WITH_LLVM_ASSERTIONS +Enable debugging assertions in LLVM. +Use when working on or requesting help with LLVM components. .It Va WITHOUT_LLVM_BINUTILS Install ELF Tool Chain's binary utilities instead of LLVM's. This includes @@ -1038,7 +1039,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 +1049,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 +1059,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 +1069,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 +1084,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 +1105,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 +1310,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 +1402,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 +1413,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 +1466,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 +1503,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/Makefile b/share/man/man7/Makefile index 7daa0ffed8ea..1e50242a1754 100644 --- a/share/man/man7/Makefile +++ b/share/man/man7/Makefile @@ -6,6 +6,7 @@ MAN= arch.7 \ bsd.snmpmod.mk.7 \ build.7 \ c.7 \ + d.7 \ clocks.7 \ crypto.7 \ development.7 \ 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 new file mode 100644 index 000000000000..f4686d98b1d1 --- /dev/null +++ b/share/man/man7/d.7 @@ -0,0 +1,287 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Mateusz Piotrowski <0mp@FreeBSD.org> +.\" +.Dd June 14, 2025 +.Dt D 7 +.Os +.Sh NAME +.Nm D +.Nd DTrace scripting language overview +.Sh SYNOPSIS +.Sm off +.Ar provider Cm \&: +.Ar module Cm \&: +.Ar function Cm \&: +.Ar name +.Sm on +.Sm off +.Oo +.Cm / +.Ar predicate +.Cm / +.Sm on +.Oc +.Op Cm \&{ Ns Ar action Ns Cm \&} +.Sh DESCRIPTION +.Nm D +is the +.Xr dtrace 1 +scripting language. +This manual provides a brief reference of the +.Nm +language and scripting. +.Pp +This manual page serves as a short reference of the language. +Refer to books listed in +.Sx SEE ALSO +for a complete reference. +.Sh PROBE'S DESCRIPTION +A probe's description consists of four elements: +.Sm off +.D1 Ar provider Ns Cm \&: Ns Ar module Cm \&: Ar function Cm \&: Ar name +.Sm on +.Pp +The exact meaning of +.Ar module , +.Ar function , +and +.Ar name +depends on +.Ar provider . +.Sh USER-DEFINED VARIABLE TYPES +.Bl -column "thread-local" "Syntax" +.It Sy Type Ta Sy Syntax +.It global Ta Va variable_name +.It thread-local Ta Sy self-> Ns Va variable_name +.It clause-local Ta Sy this-> Ns Va variable_name +.It aggregate Ta Sy @ Ns Va variable_name +.El +.Pp +.Em Tips : +.Bl -dash -compact +.It +Always use the variable type with the smallest scope +to minimize processing overhead. +.It +Use aggregate variables instead of global variables when possible. +Aggregate variables are multi-CPU safe in contrast to global variables. +.El +.Sh BUILT-IN VARIABLES +.Ss Probe Arguments +.Bl -tag -width "arg0, ..., arg9" +.It Va args[] +The array of typed probe arguments. +.It Va arg0 , ... , arg9 +The untyped probe arguments represented as 64-bit unsigned integers. +Only the first ten arguments are available this way. +.El +.Ss Probe Information +.Bl -tag -width probeprov +.It Va epid +The enabled probe ID which uniquely identifies an enabled probe. +An enabled probe is defined by its probe ID, its predicates, and its actions. +.It Va id +The probe ID which uniquely identifies a probe available to DTrace. +.It Va probeprov +The +.Ar provider +in the probe's description +.Sm off +.Pq Ar provider Cm \&: Ar module Cm \&: Ar function Cm \&: Ar name +.Sm on . +.It Va probemod +The +.Ar module +in the probe's description +.Sm off +.Pq Ar provider Cm \&: Ar module Cm \&: Ar function Cm \&: Ar name +.Sm on . +.It Va probefunc +The +.Ar function +in the probe's description +.Sm off +.Pq Ar provider Cm \&: Ar module Cm \&: Ar function Cm \&: Ar name +.Sm on . +.It Va probename +The +.Ar name +in the probe's description +.Sm off +.Pq Ar provider Cm \&: Ar module Cm \&: Ar function Cm \&: Ar name +.Sm on . +.El +.Ss Process Information +.Bl -tag -width execname +.It Va execargs +The process arguments. +Effectively, +.Ql curthread->td_proc->p_args . +.It Va execname +The name of the current process. +Effectively, +.Ql curthread->td_proc->p_comm . +.It Va gid +The group ID of the current process. +.It Va pid +The process ID of the current process. +.It Va ppid +The parent process ID of the current process. +.It Va uid +The user ID of the current process. +.El +.Ss Thread Information +.Bl -tag -width curlwpsinfo +.It Va uregs[] +The saved user-mode register values. +.It Va cpu +The ID of the current CPU. +.It Va stackdepth +The kernel stack frame depth. +.It Va ustackdepth +The userspace counterpart of +.Va stackdepth . +.It Va tid +The thread ID. +Depending on the context, +this can be either the ID of a kernel thread or a thread in a user process. +.It Va errno +The +.Xr errno 2 +value of the last system call performed by the current thread. +.It Va curlwpsinfo +A pointer to the +.Vt lwpsinfo_t +representation of the current thread. +Refer to +.Xr dtrace_proc 4 +for more details. +.It Va curpsinfo +A pointer to the +.Vt psinfo_t +representation of the current process. +Refer to +.Xr dtrace_proc 4 +for more details. +.It Va curthread +A pointer to the thread struct that is currently on-CPU. +E.g., +.Ql curthread->td_name +returns the thread name. +The +.In sys/proc.h +header documents all members of +.Vt struct thread . +.It Va caller +The address of the kernel thread instruction at the time of execution +of the current probe. +.It Va ucaller +The userspace counterpart of +.Va caller . +.El +.Ss Timestamps +.Bl -tag -width walltimestamp +.It Va timestamp +The number of nanoseconds since boot. +Suitable for calculating relative time differences of elapsed time and latency. +.It Va vtimestamp +The number of nanoseconds that the current thread spent on CPU. +The counter is not increased during handling of a fired DTrace probe. +Suitable for calculating relative time differences of on-CPU time. +.It Va walltimestamp +The number of nanoseconds since the Epoch +.Pq 1970-01-01T00+00:00 . +Suitable for timestamping logs. +.El +.Sh BUILT-IN FUNCTIONS +.Ss Aggregation Functions +.Bl -tag -compact -width "llquantize(value, factor, low, high, nsteps)" +.It Fn avg value +Average +.It Fn count +Count +.It Fn llquantize value factor low high nsteps +Log-linear quantization +.It Fn lquantize value low high nsteps +Linear quantization +.It Fn max value +Maximum +.It Fn min value +Minimum +.It Fn quantize value +Power-of-two frequency distribution +.It Fn stddev value +Standard deviation +.It Fn sum value +Sum +.El +.Ss Kernel Destructive Functions +By default, +.Xr dtrace 1 +does not permit the use of destructive actions. +.Bl -tag -width "chill(nanoseconds)" +.It Fn breakpoint +Set a kernel breakpoint and transfer control to +the +.Xr ddb 4 +kernel debugger. +.It Fn chill nanoseconds +Spin on the CPU for the specified number of +.Fa nanoseconds . +.It Fn panic +Panic the kernel. +.El +.Sh FILES +.Bl -tag -width /usr/share/dtrace +.It Pa /usr/share/dtrace +DTrace scripts shipped with +.Fx +base. +.El +.Sh SEE ALSO +.Xr awk 1 , +.Xr dtrace 1 , +.Xr tracing 7 +.Rs +.%B The illumos Dynamic Tracing Guide +.%D 2008 +.%U https://illumos.org/books/dtrace/ +.Re +.Rs +.%A Brendan Gregg +.%A Jim Mauro +.%B DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD +.%I Prentice Hall +.%D 2011 +.%U https://www.brendangregg.com/dtracebook/ +.Re +.Rs +.%A George Neville-Neil +.%A Jonathan Anderson +.%A Graeme Jenkinson +.%A Brian Kidney +.%A Domagoj Stolfa +.%A Arun Thomas +.%A Robert N. M. Watson +.%C Cambridge, United Kingdom +.%D August 2018 +.%T Univeristy of Cambridge Computer Laboratory +.%R OpenDTrace Specification version 1.0 +.%U https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-924.pdf +.Re +.Sh HISTORY +This manual page first appeared in +.Fx 15.0 . +.Sh AUTHORS +.An -nosplit +This manual page was written by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . +.Sh BUGS +The +.Va cwd +variable which typically provides the current working directory is +not supported on +.Fx +at the moment. diff --git a/share/man/man7/intro.7 b/share/man/man7/intro.7 index d889c2dd299f..43e48de87bc5 100644 --- a/share/man/man7/intro.7 +++ b/share/man/man7/intro.7 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 23, 2025 +.Dd July 14, 2025 .Dt INTRO 7 .Os .Sh NAME @@ -49,6 +49,9 @@ system timekeeping clocks available in .It Xr crypto 7 cryptographic algorithms provided by OpenCrypto in .Fx +.It Xr d 7 +.Xr dtrace 1 +scripting language overview .It Xr development 7 development introduction to .Fx diff --git a/share/man/man7/named_attribute.7 b/share/man/man7/named_attribute.7 index 7cd778620357..4080dfce2fab 100644 --- a/share/man/man7/named_attribute.7 +++ b/share/man/man7/named_attribute.7 @@ -3,7 +3,7 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd July 3, 2025 +.Dd July 20, 2025 .Dt NAMED_ATTRIBUTE 7 .Os .Sh NAME @@ -122,7 +122,7 @@ Although the named attribute machanism might require different internal implementation of extended attributes within a file system, both ZFS and NFSv4 provide both mechanisms, which can be used interchangeably to manipulate -extended attributes, but with a couple of limitations. +extended attributes, but with a few limitations. .Bl -bullet .It The @@ -135,6 +135,24 @@ The named attribute interface does not support system namespace extended attributes and, as such, system namespace extended attributes must be manipulated via .Xr extattr 2 . +.It +For ZFS, if an extended attribute with a value +that is a small length in bytes is created when the ZFS +.Dv xattr +property is set to +.Dq sa , +that extended attribute is only visible via +.Xr extattr 2 +and not as a named attribute. +Archiving/de-archiving the file via +.Xr tar 1 +after setting the +.Dv xattr +property to +.Dq dir +will make the attribute(s) visible as both named attributes +and via +.Xr extattr 2 . .El .Pp The named attribute mechanism/system call interface provides certain @@ -259,6 +277,7 @@ enters the named attribute directory for the file object .Sh SEE ALSO .Xr bash 1 , .Xr runat 1 , +.Xr tar 1 , .Xr chdir 2 , .Xr extattr 2 , .Xr lseek 2 , diff --git a/share/man/man7/tracing.7 b/share/man/man7/tracing.7 index 7f21bfbbd2a3..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 +.Nd introduction to FreeBSD tracing and performance monitoring .Sh DESCRIPTION .Fx features a large variety of tracing and performance monitoring facilities. @@ -73,6 +73,10 @@ It comes in handy for some niche purposes during kernel development. It lets kernel programmers log events to a global ring buffer, which can later be dumped using .Xr ktrdump 8 . +.Ss Hardware-Accelerated Tracing +.Xr hwt 4 +is a kernel trace framework providing infrastructure +for hardware-assisted tracing. .Ss Hardware Counters .Xr pmcstat 8 , and its kernel counterpart, diff --git a/share/man/man8/Makefile b/share/man/man8/Makefile index bd6bdfe4ba05..c408f1b65a80 100644 --- a/share/man/man8/Makefile +++ b/share/man/man8/Makefile @@ -1,5 +1,7 @@ .include <src.opts.mk> +MANGROUPS= MAN + MAN= \ beinstall.8 \ crash.8 \ @@ -7,29 +9,32 @@ MAN= \ diskless.8 \ intro.8 \ nanobsd.8 \ - rc.8 \ - rc.subr.8 \ rescue.8 \ - ${_uefi.8} \ + ${_uefi.8} MLINKS= \ beinstall.8 beinstall.sh.8 \ - nanobsd.8 nanobsd.sh.8 \ - rc.8 rc.d.8 \ - rc.8 rc.firewall.8 \ - rc.8 rc.local.8 \ - rc.8 rc.network.8 \ - rc.8 rc.pccard.8 \ - rc.8 rc.resume.8 \ - rc.8 rc.serial.8 \ - rc.8 rc.shutdown.8 + nanobsd.8 nanobsd.sh.8 -.if ${MK_NIS} != "no" -MAN+= yp.8 +MANGROUPS+= RC +RC= rc.8 rc.subr.8 +RCLINKS= rc.8 rc.d.8 \ + rc.8 rc.firewall.8 \ + rc.8 rc.local.8 \ + rc.8 rc.network.8 \ + rc.8 rc.pccard.8 \ + rc.8 rc.resume.8 \ + rc.8 rc.serial.8 \ + rc.8 rc.shutdown.8 +RCPACKAGE= rc -MLINKS+=yp.8 NIS.8 \ - yp.8 nis.8 \ - yp.8 YP.8 +.if ${MK_NIS} != "no" +MANGROUPS+= YP +YP= yp.8 +YPLINKS= yp.8 NIS.8 \ + yp.8 nis.8 \ + yp.8 YP.8 +YPPACKAGE= yp .endif # This makes more sense for aarch 64 and amd64 diff --git a/share/man/man8/crash.8 b/share/man/man8/crash.8 index 27c9c56533a5..fdb9b7213847 100644 --- a/share/man/man8/crash.8 +++ b/share/man/man8/crash.8 @@ -30,7 +30,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 23, 2011 +.Dd July 25, 2025 .Dt CRASH 8 .Os .Sh NAME @@ -71,18 +71,19 @@ Left unstated in all cases is the possibility that hardware or software error produced the message in some unexpected way. .Pp .Bl -diag -compact -.It "cannot mount root" -This panic message results from a failure to mount the root file system -during the bootstrap process. -Either the root file system has been corrupted, -or the system is attempting to use the wrong device as root file system. -Usually, an alternate copy of the system binary or an alternate root -file system can be used to bring up the system to investigate. -Most often -this is done by the use of the boot floppy you used to install the system, -and then using the -.Dq fixit -floppy. +.It Mounting from <device> failed with error <err> +The system was unable to mount the configured root filesystem. +Either the root filesystem has been corrupted, +or the system is attempting to use the wrong device as root filesystem. +.Pp +This is not a panic message; rather it is followed by an interactive +.Sy mountroot> +prompt where the operator can list detected devices and filesystems, +and select an alternative root filesystem to mount. +Alternatively, the system can be booted from recovery media to repair +the situation. +The system install media provides a live environment which is suitable +for this task. .Pp .It "init: not found" This is not a panic message, as reboots are likely to be futile. @@ -108,11 +109,6 @@ after a crash, hardware failures, or other condition that should not normally occur. A file system check will normally correct the problem. .Pp -.It "timeout table full" -This really should not be a panic, but until the data structure -involved is made to be extensible, running out of entries causes a crash. -If this happens, make the timeout table bigger. -.Pp .\" .It "trap type %d, code = %x, v = %x" .\" An unexpected trap has occurred within the system; the trap types are: .\" .Bl -column xxxx -offset indent 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/Makefile b/share/man/man9/Makefile index f709a4818dd5..5bcde3030ebc 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1,5 +1,7 @@ .include <src.opts.mk> +PACKAGE= kernel + MAN= accept_filter.9 \ accf_data.9 \ accf_dns.9 \ @@ -67,6 +69,7 @@ MAN= accept_filter.9 \ config_intrhook.9 \ contigmalloc.9 \ copy.9 \ + coredumper_register.9 \ counter.9 \ cpu_machdep.9 \ cpuset.9 \ @@ -903,6 +906,7 @@ MLINKS+=copy.9 copyin.9 \ copy.9 copyout.9 \ copy.9 copyout_nofault.9 \ copy.9 copystr.9 +MLINKS+=coredumper_register.9 coredumper_unregister.9 MLINKS+=counter.9 counter_u64_alloc.9 \ counter.9 counter_u64_free.9 \ counter.9 counter_u64_add.9 \ diff --git a/share/man/man9/coredumper_register.9 b/share/man/man9/coredumper_register.9 new file mode 100644 index 000000000000..f4c9eb4a1bf6 --- /dev/null +++ b/share/man/man9/coredumper_register.9 @@ -0,0 +1,168 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org> +.\" +.Dd July 23, 2025 +.Dt COREDUMPER_REGISTER 9 +.Os +.Sh NAME +.Nm coredumper_register , +.Nm coredumper_unregister +.Nd loadable user coredumper support +.Sh SYNOPSIS +.In sys/ucoredump.h +.Ft void +.Fn coredumper_register "struct coredumper *cd" +.Ft void +.Fn coredumper_unregister "struct coredumper *cd" +.Pp +.Ft int +.Fn coredumper_probe_fn "struct thread *td" +.Ft int +.Fn coredumper_handle_fn "struct thread *td" "off_t limit" +.Bd -literal +/* Incomplete, but the useful members are depicted here. */ +struct coredumper { + const char *cd_name; + coredumper_probe_fn *cd_probe; + coredumper_handle_fn *cd_handle; +}; +.Ed +.Pp +.Ft int +.Fn coredump_init_fn "const struct coredump_writer *" \ +"const struct coredump_params *" +.Ft int +.Fn coredump_write_fn "const struct coredump_writer *" "const void *" "size_t" \ +"off_t" "enum uio_seg" "struct ucred *" "size_t *" "struct thread *" +.Ft int +.Fn coredump_extend_fn "const struct coredump_writer *" "off_t" "struct ucred *" +.Bd -literal +struct coredump_writer { + void *ctx; + coredump_init_fn *init_fn; + coredump_write_fn *write_fn; + coredump_extend_fn *extend_fn; +}; +.Ed +.Sh DESCRIPTION +The +.Nm +mechanism provides a path for kernel modules to register a new user process core +dumper. +The expected use of +.Nm +is for a module to define the fields of the struct coredumper listed above, then +call +.Fn coredumper_register +at +.Dv MOD_LOAD +time. +A corresponding +.Fn coredumper_unregister +should be called at +.Dv MOD_UNLOAD +time. +Note that +.Fn coredumper_unregister +will block until the specified coredumper is no longer processing coredumps. +.Pp +When a user process is preparing to start dumping core, the kernel will execute +the +.Fn cd_probe +function for each coredumper currently registered. +The +.Fn cd_probe +function is expected to return either -1 if it would decline to dump the +process, or a priority level greater than 0. +The coredumper with the highest priority will handle the coredump. +The following default priorities are defined: +.Bl -tag -width indent +.It Dv COREDUMPER_NOMATCH +This dumper declines dumping the process. +.It Dv COREDUMPER_GENERIC +This dumper will dump the process at the lowest priority. +This priority is not recommended, as the default vnode dumper will bid at +.Dv COREDUMPER_GENERIC +as well. +.It Dv COREDUMPER_SPECIAL +This dumper provides special behavior, and will dump the process at a higher +priority. +.It Dv COREDUMPER_HIGHPRIORITY +This dumper would prefer to handle this coredump. +This may be used by, for instance, a custom or vendor-specific coredump +mechanism that wishes to preempt others. +.El +.Pp +Note that this system has been designed such that the +.Fn cd_probe +function can examine the process in question and make an informed decision. +Different processes being dumped could probe at different priorities in the +same coredumper. +.Pp +Once the highest priority coredumper has been selected, the +.Fn cd_handle +function will be invoked. +The +.Fn cd_handle +will receive both the thread and the +.Dv RLIMIT_CORE +.Xr setrlimit 2 +.Fa limit . +The proc lock will be held on entry, and should be unlocked before the handler +returns. +The +.Fa limit +is typically passed to the +.Fn sv_coredump +that belongs to the process's +.Va p_sysent . +.Pp +The +.Fn cd_handle +function should return either 0 if the dump was successful, or an appropriate +.Xr errno 2 +otherwise. +.Ss Customized Coredump Writers +Custom coredumpers can define their own +.Dv coredump_writer +to pass to +.Fn sv_coredump . +.Pp +The +.Va ctx +member is opaque and only to be used by the coredumper itself. +.Pp +The +.Va init_fn +function, if it's provided, will be called by the +.Fn sv_coredump +implementation before any data is to be written. +This allows the writer implementation to record any coredump parameters that it +might need to capture, or setup the object to be written to. +.Pp +The +.Va write_fn +function will be called by the +.Fn sv_coredump +implementation to write out data. +The +.Va extend_fn +function will be called to enlarge the coredump, in the sense that a hole is +created in any difference between the current size and the new size. +For convenience, the +.Fn core_vn_write +and +.Fn core_vn_extend +functions used by the vnode coredumper are exposed in +.In sys/ucordumper.h , +and the +.Dv coredump_vnode_ctx +defined there should be populated with the vnode to write to. +.Sh SEE ALSO +.Xr setrlimit 2 , +.Xr core 5 +.Sh AUTHORS +This manual page was written by +.An Kyle Evans Aq Mt kevans@FreeBSD.org . 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.man.mk b/share/mk/bsd.man.mk index 96b8f07c25e2..a5a4fd528268 100644 --- a/share/mk/bsd.man.mk +++ b/share/mk/bsd.man.mk @@ -39,6 +39,13 @@ # # MANDOC_CMD command and flags to create preformatted pages # +# MANGROUPS A list of groups, each of which should be a variable containing +# a list of manual pages in that group. By default one group is +# defined called "MAN". +# +# For each group, group-specific options may be set: +# <group>OWN, <group>GRP, <group>MODE and <group>PACKAGE. +# # +++ targets +++ # # maninstall: @@ -49,11 +56,10 @@ .error bsd.man.mk cannot be included directly. .endif -.if ${MK_MANSPLITPKG} == "no" -MINSTALL?= ${INSTALL} ${TAG_ARGS} -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} -.else -MINSTALL?= ${INSTALL} ${TAG_ARGS:D${TAG_ARGS},man} -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} -.endif +MANGROUPS?= MAN + +# Backwards compatibility. +MINSTALL?= ${MANINSTALL} CATDIR= ${MANDIR:H:S/$/\/cat/} CATEXT= .cat @@ -65,18 +71,55 @@ MCOMPRESS_EXT?= ${COMPRESS_EXT} SECTIONS= 1 2 3 4 5 6 7 8 9 .SUFFIXES: ${SECTIONS:S/^/./g} - # Backwards compatibility. .if !defined(MAN) .for __sect in ${SECTIONS} -.if defined(MAN${__sect}) && !empty(MAN${__sect}) -MAN+= ${MAN${__sect}} -.endif +MANGROUPS+= MAN${__sect} .endfor .endif +# Following the conventions of MANGROUPS, manpage links should be defined +# as ${group}LINKS, which means the default groups' links would be called +# MANLINKS. However it's actually called MLINKS, so for compatibility, +# use ${MLINKS} as the default group's links if it's set. +.if defined(MLINKS) +MANLINKS= ${MLINKS} +.endif + +maninstall: realmaninstall manlinksinstall .PHONY +# Make sure all manpages are installed before we try to link any. +.ORDER: realmaninstall manlinksinstall +realmaninstall: .PHONY +manlinksinstall: .PHONY + all-man: +.for __group in ${MANGROUPS} + +realmaninstall: realmaninstall-${__group} +manlinksinstall: manlinksinstall-${__group} + +${__group}OWN?= ${MANOWN} +${__group}GRP?= ${MANGRP} +${__group}MODE?= ${MANMODE} + +# Tag processing is only done for NO_ROOT installs. +.if defined(NO_ROOT) + +.if !defined(${__group}TAGS) || ! ${${__group}TAGS:Mpackage=*} +.if ${MK_MANSPLITPKG} == "no" +${__group}TAGS+= package=${${__group}PACKAGE:U${PACKAGE:Uutilities}} +.else +${__group}TAGS+= package=${${__group}PACKAGE:U${PACKAGE:Uutilities}}-man +.endif +.endif + +${__group}TAG_ARGS= -T ${${__group}TAGS:[*]:S/ /,/g} +.endif # defined(NO_ROOT) + +${__group}INSTALL?= ${INSTALL} ${${__group}TAG_ARGS} \ + -o ${${__group}OWN} -g ${${__group}GRP} -m ${${__group}MODE} + .if ${MK_MANCOMPRESS} == "no" # Make special arrangements to filter to a temporary file at build time @@ -90,10 +133,10 @@ FILTEXTENSION= ZEXT= .if defined(MANFILTER) -.if defined(MAN) && !empty(MAN) -CLEANFILES+= ${MAN:T:S/$/${FILTEXTENSION}/g} -CLEANFILES+= ${MAN:T:S/$/${CATEXT}${FILTEXTENSION}/g} -.for __page in ${MAN} +.if defined(${__group}) && !empty(${__group}) +CLEANFILES+= ${${__group}:T:S/$/${FILTEXTENSION}/g} +CLEANFILES+= ${${__group}:T:S/$/${CATEXT}${FILTEXTENSION}/g} +.for __page in ${${__group}} .for __target in ${__page:T:S/$/${FILTEXTENSION}/g} all-man: ${__target} ${__target}: ${__page} @@ -107,12 +150,12 @@ ${__target}: ${__page} .endfor .endif .endfor -.endif # !empty(MAN) +.endif # !empty(${__group}) .else # !defined(MANFILTER) -.if defined(MAN) && !empty(MAN) -CLEANFILES+= ${MAN:T:S/$/${CATEXT}/g} +.if defined(${__group}) && !empty(${__group}) +CLEANFILES+= ${${__group}:T:S/$/${CATEXT}/g} .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) -.for __page in ${MAN} +.for __page in ${${__group}} .for __target in ${__page:T:S/$/${CATEXT}/g} all-man: ${__target} ${__target}: ${__page} @@ -120,7 +163,7 @@ ${__target}: ${__page} .endfor .endfor .else -all-man: ${MAN} +all-man: ${${__group}} .endif .endif .endif # defined(MANFILTER) @@ -129,10 +172,10 @@ all-man: ${MAN} ZEXT= ${MCOMPRESS_EXT} -.if defined(MAN) && !empty(MAN) -CLEANFILES+= ${MAN:T:S/$/${MCOMPRESS_EXT}/g} -CLEANFILES+= ${MAN:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g} -.for __page in ${MAN} +.if defined(${__group}) && !empty(${__group}) +CLEANFILES+= ${${__group}:T:S/$/${MCOMPRESS_EXT}/g} +CLEANFILES+= ${${__group}:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g} +.for __page in ${${__group}} .for __target in ${__page:T:S/$/${MCOMPRESS_EXT}/} all-man: ${__target} ${__target}: ${__page} @@ -158,8 +201,9 @@ ${__target}: ${__page} .endif # ${MK_MANCOMPRESS} == "no" -.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS) -.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} +_MANLINKS= +.if !defined(NO_MLINKS) && defined(${__group}LINKS) && !empty(${__group}LINKS) +.for _oname _osect _dname _dsect in ${${__group}LINKS:C/\.([^.]*)$/.\1 \1/} _MANLINKS+= ${MANDIR}${_osect}${MANSUBDIR}/${_oname} \ ${MANDIR}${_dsect}${MANSUBDIR}/${_dname} .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) @@ -169,37 +213,37 @@ _MANLINKS+= ${CATDIR}${_osect}${MANSUBDIR}/${_oname} \ .endfor .endif -.if defined(MAN) && !empty(MAN) +.if defined(${__group}) && !empty(${__group}) .if ${MK_STAGING_MAN} == "yes" -STAGE_TARGETS+= stage_files -_mansets:= ${MAN:E:O:u:M*[1-9]:@s@man$s@} -STAGE_SETS+= ${_mansets} -.for _page in ${MAN} -stage_files.man${_page:T:E}: ${_page} +STAGE_TARGETS+= stage_files.${__group} +_mansets.${__group}:= ${${__group}:E:O:u:M*[1-9]:@s@man$s@} +STAGE_SETS+= ${_mansets.${__group}} +.for _page in ${${__group}} +stage_files.${__group}.man${_page:T:E}: ${_page} .if target(${_page}${MCOMPRESS_EXT}) -stage_files.man${_page:T:E}: ${_page}${MCOMPRESS_EXT} +stage_files.${__group}.man${_page:T:E}: ${_page}${MCOMPRESS_EXT} .endif -STAGE_DIR.man${_page:T:E}?= ${STAGE_OBJTOP}${MANDIR}${_page:T:E}${MANSUBDIR} +STAGE_DIR.${__group}.man${_page:T:E}?= ${STAGE_OBJTOP}${MANDIR}${_page:T:E}${MANSUBDIR} .endfor -.if !defined(NO_MLINKS) && !empty(MLINKS) -STAGE_SETS+= mlinks -STAGE_TARGETS+= stage_links -STAGE_LINKS.mlinks:= ${MLINKS:M*.[1-9]:@f@${f:S,^,${MANDIR}${f:E}${MANSUBDIR}/,}@} -stage_links.mlinks: ${_mansets:@s@stage_files.$s@} +.if !defined(NO_MLINKS) && !empty(${__group}LINKS) +STAGE_SETS+= mlinks.${__group} +STAGE_TARGETS+= stage_links.${__group} +STAGE_LINKS.mlinks.${__group}:= ${${__group}LINKS:M*.[1-9]:@f@${f:S,^,${MANDIR}${f:E}${MANSUBDIR}/,}@} +stage_links.mlinks.${__group}: ${_mansets.${__group}:@s@stage_files.${__group}.$s@} .endif .endif .endif -maninstall: -.if defined(MAN) && !empty(MAN) -maninstall: ${MAN} +realmaninstall-${__group}: +.if defined(${__group}) && !empty(${__group}) +realmaninstall-${__group}: ${${__group}} .if ${MK_MANCOMPRESS} == "no" .if defined(MANFILTER) -.for __page in ${MAN} - ${MINSTALL} ${__page:T:S/$/${FILTEXTENSION}/g} \ +.for __page in ${${__group}} + ${${__group}INSTALL} ${__page:T:S/$/${FILTEXTENSION}/g} \ ${DESTDIR}${MANDIR}${__page:E}${MANSUBDIR}/${__page} .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) - ${MINSTALL} ${__page:T:S/$/${CATEXT}${FILTEXTENSION}/g} \ + ${${__group}INSTALL} ${__page:T:S/$/${CATEXT}${FILTEXTENSION}/g} \ ${DESTDIR}${CATDIR}${__page:E}${MANSUBDIR}/${__page} .endif .endfor @@ -212,41 +256,39 @@ maninstall: ${MAN} esac; \ page=$$1; shift; sect=$$1; shift; \ d=${DESTDIR}${MANDIR}$${sect}${MANSUBDIR}; \ - ${ECHO} ${MINSTALL} $${page} $${d}; \ - ${MINSTALL} $${page} $${d}; \ + ${ECHO} ${${__group}INSTALL} $${page} $${d}; \ + ${${__group}INSTALL} $${page} $${d}; \ done .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) -.for __page in ${MAN} - ${MINSTALL} ${__page:T:S/$/${CATEXT}/} \ +.for __page in ${${__group}} + ${${__group}INSTALL} ${__page:T:S/$/${CATEXT}/} \ ${DESTDIR}${CATDIR}${__page:E}${MANSUBDIR}/${__page:T} .endfor .endif .endif # defined(MANFILTER) .else # ${MK_MANCOMPRESS} == "yes" -.for __page in ${MAN} - ${MINSTALL} ${__page:T:S/$/${MCOMPRESS_EXT}/g} \ +.for __page in ${${__group}} + ${${__group}INSTALL} ${__page:T:S/$/${MCOMPRESS_EXT}/g} \ ${DESTDIR}${MANDIR}${__page:E}${MANSUBDIR}/ .if defined(MANBUILDCAT) && !empty(MANBUILDCAT) - ${MINSTALL} ${__page:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g} \ + ${${__group}INSTALL} ${__page:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g} \ ${DESTDIR}${CATDIR}${__page:E}${MANSUBDIR}/${__page:T:S/$/${MCOMPRESS_EXT}/} .endif .endfor .endif # ${MK_MANCOMPRESS} == "no" .endif + +manlinksinstall-${__group}: .for l t in ${_MANLINKS} # On MacOS, assume case folding FS, and don't install links from foo.x to FOO.x. .if ${.MAKE.OS} != "Darwin" || ${l:tu} != ${t:tu} -.if ${MK_MANSPLITPKG} == "no" - ${INSTALL_MANLINK} ${TAG_ARGS} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT} -.else - ${INSTALL_MANLINK} ${TAG_ARGS:D${TAG_ARGS},man} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT} -.endif + ${INSTALL_MANLINK} ${${__group}TAG_ARGS} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT} .endif .endfor manlint: -.if defined(MAN) && !empty(MAN) -.for __page in ${MAN} +.if defined(${__group}) && !empty(${__group}) +.for __page in ${${__group}} manlint: ${__page}lint ${__page}lint: ${__page} .if defined(MANFILTER) @@ -256,3 +298,5 @@ ${__page}lint: ${__page} .endif .endfor .endif + +.endfor # __group in ${MANGROUPS} 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..77923ae7b6d1 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -123,7 +123,6 @@ __DEFAULT_YES_OPTIONS = \ LEGACY_CONSOLE \ LLD \ LLD_BOOTSTRAP \ - LLVM_ASSERTIONS \ LLVM_BINUTILS \ LLVM_COV \ LLVM_CXXFILT \ @@ -143,6 +142,7 @@ __DEFAULT_YES_OPTIONS = \ MAIL \ MAILWRAPPER \ MAKE \ + MITKRB5 \ MLX5TOOL \ NETCAT \ NETGRAPH \ @@ -209,9 +209,9 @@ __DEFAULT_NO_OPTIONS = \ HESIOD \ LOADER_VERBOSE \ LOADER_VERIEXEC_PASS_MANIFEST \ + LLVM_ASSERTIONS \ LLVM_FULL_DEBUGINFO \ MALLOC_PRODUCTION \ - MITKRB5 \ OFED_EXTRA \ OPENLDAP \ REPRODUCIBLE_BUILD \ diff --git a/share/termcap/termcap b/share/termcap/termcap index 9704d85c942f..44704653045d 100644 --- a/share/termcap/termcap +++ b/share/termcap/termcap @@ -3549,8 +3549,7 @@ ti931|ti 931:\ # using \EPC\\ and \EPD\\, but I don't think there is a # capability for that. ti703|ti707|Texas Instruments Silent 703/707, 80 cols:\ - :am:hc:os:xn:\ - :co#80:it#8:\ + :am:hc:os:xn:co#80:\ :do=\n:le=\b:cr=\r:nd= :bl=^G:ta=\t:is=\EPC\\: ti703-w|ti707-w|Texas Instruments Silent 703/707, 132 cols:\ :co#132:is=\EPD\\:tc=ti703: @@ -4706,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:\ @@ -4726,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:\ @@ -4743,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:\ @@ -4808,6 +4821,26 @@ alacritty+common|base fragment for alacritty:\ :te=\E[?1049l\E[23;0;0t:ti=\E[?1049h\E[22;0;0t:\ :ts=\E]2;:ue=\E[24m:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:\ :ve=\E[?12l\E[?25h:vi=\E[?25l:vs=\E[?12;25h: + +# From Tim Culverhouse <tim@timculverhouse.com> +xterm-ghostty|ghostty|Ghostty:\ + :am:hs:km:mi:ms:xn:\ + :co#80:it#8:li#24:\ + :AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:DO=\E[%dB:IC=\E[%d@:\ + :LE=\E[%dD: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:ds=\E]2;\007:ec=\E[%dX:\ + :ei=\E[4l:fs=^G:ho=\E[H:ic=\E[@:im=\E[4h:k1=\EOP:k2=\EOQ:\ + :k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:\ + :k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:kP=\E[5~:kb=\177:\ + :kd=\EOB:ke=\E[?1l\E>:kh=\EOH:kl=\EOD:kr=\EOC:\ + :ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[0m:\ + :mh=\E[2m:mr=\E[7m:nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:sf=\n:\ + :so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[?1049l:ti=\E[?1049h:\ + :ts=\E]2;:ue=\E[24m:up=\E[A:us=\E[4m:vb=\E[?5h\E[?5l:\ + :ve=\E[?12l\E[?25h:vi=\E[?25l:vs=\E[?12;25h: + # # END OF TERMCAP # ------------------------ 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 9c985df13ddf..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, @@ -1336,7 +1379,7 @@ static pdp_entry_t *pmap_pti_pdpe(vm_offset_t va); static pd_entry_t *pmap_pti_pde(vm_offset_t va); static void pmap_pti_wire_pte(void *pte); static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, - bool remove_pt, struct spglist *free, struct rwlock **lockp); + bool demote_kpde, struct spglist *free, struct rwlock **lockp); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, pd_entry_t ptepde, struct spglist *free, struct rwlock **lockp); static vm_page_t pmap_remove_pt_page(pmap_t pmap, vm_offset_t va); @@ -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); @@ -6165,8 +6083,7 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, * pmap_remove_kernel_pde: Remove a kernel superpage mapping. */ static void -pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, - bool remove_pt) +pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t newpde; vm_paddr_t mptepa; @@ -6174,12 +6091,8 @@ pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, KASSERT(pmap == kernel_pmap, ("pmap %p is not kernel_pmap", pmap)); PMAP_LOCK_ASSERT(pmap, MA_OWNED); - if (remove_pt) - mpte = pmap_remove_pt_page(pmap, va); - else - mpte = vm_radix_lookup(&pmap->pm_root, pmap_pde_pindex(va)); - if (mpte == NULL) - panic("pmap_remove_kernel_pde: Missing pt page."); + mpte = pmap_remove_pt_page(pmap, va); + KASSERT(mpte != NULL, ("pmap_remove_kernel_pde: missing pt page")); mptepa = VM_PAGE_TO_PHYS(mpte); newpde = mptepa | X86_PG_M | X86_PG_A | X86_PG_RW | X86_PG_V; @@ -6209,7 +6122,7 @@ pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, * pmap_remove_pde: do the things to unmap a superpage in a process */ static int -pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, bool remove_pt, +pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, bool demote_kpde, struct spglist *free, struct rwlock **lockp) { struct md_page *pvh; @@ -6249,9 +6162,7 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, bool remove_pt, pmap_delayed_invl_page(m); } } - if (pmap == kernel_pmap) { - pmap_remove_kernel_pde(pmap, pdq, sva, remove_pt); - } else { + if (pmap != kernel_pmap) { mpte = pmap_remove_pt_page(pmap, sva); if (mpte != NULL) { KASSERT(vm_page_any_valid(mpte), @@ -6262,6 +6173,14 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, bool remove_pt, mpte->ref_count = 0; pmap_add_delayed_free_list(mpte, free, false); } + } else if (demote_kpde) { + pmap_remove_kernel_pde(pmap, pdq, sva); + } else { + mpte = vm_radix_lookup(&pmap->pm_root, pmap_pde_pindex(sva)); + if (vm_page_any_valid(mpte)) { + mpte->valid = 0; + pmap_zero_page(mpte); + } } return (pmap_unuse_pt(pmap, sva, *pmap_pdpe(pmap, sva), free)); } @@ -7183,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)); @@ -7512,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); @@ -7573,8 +7495,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, * the mapping is not from kernel_pmap, then * a reserved PT page could be freed. */ - (void)pmap_remove_pde(pmap, pde, va, - pmap != kernel_pmap, &free, lockp); + (void)pmap_remove_pde(pmap, pde, va, false, &free, + lockp); if ((oldpde & PG_G) == 0) pmap_invalidate_pde_page(pmap, va, oldpde); } else { @@ -7584,10 +7506,9 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, * before any changes to mappings are * made. Abort on failure. */ - mt = PHYS_TO_VM_PAGE(*pde & PG_FRAME); - if (pmap_insert_pt_page(pmap, mt, false, false)) { - if (pdpg != NULL) - pdpg->ref_count--; + mt = PHYS_TO_VM_PAGE(oldpde & PG_FRAME); + if (pmap_insert_pt_page(pmap, mt, false, + false)) { CTR1(KTR_PMAP, "pmap_enter_pde: cannot ins kern ptp va %#lx", va); @@ -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); @@ -9649,6 +9578,8 @@ pmap_demote_pdpe(pmap_t pmap, pdp_entry_t *pdpe, vm_offset_t va, vm_page_t m) void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) { + if (m->md.pat_mode == ma) + return; m->md.pat_mode = ma; @@ -9668,6 +9599,9 @@ pmap_page_set_memattr_noflush(vm_page_t m, vm_memattr_t ma) { int error; + if (m->md.pat_mode == ma) + return; + m->md.pat_mode = ma; if ((m->flags & PG_FICTITIOUS) != 0) @@ -9724,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); @@ -9755,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); /* @@ -9778,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; } @@ -9874,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. */ @@ -9904,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. */ @@ -9932,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. */ @@ -10280,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 @@ -10331,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; @@ -10699,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)); } @@ -10904,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); @@ -11151,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); } @@ -11196,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); } @@ -11971,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; } /* @@ -12014,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)); @@ -12052,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) @@ -12067,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 @@ -12078,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); @@ -12133,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; @@ -12146,6 +12090,7 @@ restart: * freed. Validate the next-level address * before descending. */ + sva += NBPDP; goto restart; } pd = (pd_entry_t *)PHYS_TO_DMAP(pa); @@ -12162,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; @@ -12174,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); @@ -12187,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/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 92eb0589f80b..78883296c5b7 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -5767,7 +5767,7 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) CTR5(KTR_PMAP, "%s: page %p - 0x%08X oma: %d, ma: %d", __func__, m, VM_PAGE_TO_PHYS(m), oma, ma); - if ((m->flags & PG_FICTITIOUS) != 0) + if (ma == oma || (m->flags & PG_FICTITIOUS) != 0) return; #if 0 /* @@ -5784,22 +5784,20 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) * If page is not mapped by sf buffer, map the page * transient and do invalidation. */ - if (ma != oma) { - pa = VM_PAGE_TO_PHYS(m); - sched_pin(); - pc = get_pcpu(); - cmap2_pte2p = pc->pc_cmap2_pte2p; - mtx_lock(&pc->pc_cmap_lock); - if (pte2_load(cmap2_pte2p) != 0) - panic("%s: CMAP2 busy", __func__); - pte2_store(cmap2_pte2p, PTE2_KERN_NG(pa, PTE2_AP_KRW, - vm_memattr_to_pte2(ma))); - dcache_wbinv_poc((vm_offset_t)pc->pc_cmap2_addr, pa, PAGE_SIZE); - pte2_clear(cmap2_pte2p); - tlb_flush((vm_offset_t)pc->pc_cmap2_addr); - sched_unpin(); - mtx_unlock(&pc->pc_cmap_lock); - } + pa = VM_PAGE_TO_PHYS(m); + sched_pin(); + pc = get_pcpu(); + cmap2_pte2p = pc->pc_cmap2_pte2p; + mtx_lock(&pc->pc_cmap_lock); + if (pte2_load(cmap2_pte2p) != 0) + panic("%s: CMAP2 busy", __func__); + pte2_store(cmap2_pte2p, PTE2_KERN_NG(pa, PTE2_AP_KRW, + vm_memattr_to_pte2(ma))); + dcache_wbinv_poc((vm_offset_t)pc->pc_cmap2_addr, pa, PAGE_SIZE); + pte2_clear(cmap2_pte2p); + tlb_flush((vm_offset_t)pc->pc_cmap2_addr); + sched_unpin(); + mtx_unlock(&pc->pc_cmap_lock); } /* diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index d2e56a270f54..2152f7fcc1c6 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -497,7 +497,8 @@ static bool pmap_pv_insert_l3c(pmap_t pmap, vm_offset_t va, vm_page_t m, struct rwlock **lockp); static void pmap_remove_kernel_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va); static int pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, - pd_entry_t l1e, struct spglist *free, struct rwlock **lockp); + pd_entry_t l1e, bool demote_kl2e, struct spglist *free, + struct rwlock **lockp); static int pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t sva, pd_entry_t l2e, struct spglist *free, struct rwlock **lockp); static bool pmap_remove_l3c(pmap_t pmap, pt_entry_t *l3p, vm_offset_t va, @@ -3847,8 +3848,7 @@ pmap_remove_kernel_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va) PMAP_LOCK_ASSERT(pmap, MA_OWNED); ml3 = pmap_remove_pt_page(pmap, va); - if (ml3 == NULL) - panic("pmap_remove_kernel_l2: Missing pt page"); + KASSERT(ml3 != NULL, ("pmap_remove_kernel_l2: missing pt page")); ml3pa = VM_PAGE_TO_PHYS(ml3); newl2 = PHYS_TO_PTE(ml3pa) | L2_TABLE; @@ -3873,8 +3873,8 @@ pmap_remove_kernel_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va) * pmap_remove_l2: Do the things to unmap a level 2 superpage. */ static int -pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, - pd_entry_t l1e, struct spglist *free, struct rwlock **lockp) +pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, pd_entry_t l1e, + bool demote_kl2e, struct spglist *free, struct rwlock **lockp) { struct md_page *pvh; pt_entry_t old_l2; @@ -3910,9 +3910,7 @@ pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, vm_page_aflag_clear(mt, PGA_WRITEABLE); } } - if (pmap == kernel_pmap) { - pmap_remove_kernel_l2(pmap, l2, sva); - } else { + if (pmap != kernel_pmap) { ml3 = pmap_remove_pt_page(pmap, sva); if (ml3 != NULL) { KASSERT(vm_page_any_valid(ml3), @@ -3923,6 +3921,14 @@ pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, ml3->ref_count = 0; pmap_add_delayed_free_list(ml3, free, false); } + } else if (demote_kl2e) { + pmap_remove_kernel_l2(pmap, l2, sva); + } else { + ml3 = vm_radix_lookup(&pmap->pm_root, pmap_l2_pindex(sva)); + if (vm_page_any_valid(ml3)) { + ml3->valid = 0; + pmap_zero_page(ml3); + } } return (pmap_unuse_pt(pmap, sva, l1e, free)); } @@ -4232,7 +4238,7 @@ pmap_remove1(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, bool map_delete) if ((l3_paddr & ATTR_DESCR_MASK) == L2_BLOCK) { if (sva + L2_SIZE == va_next && eva >= va_next) { pmap_remove_l2(pmap, l2, sva, pmap_load(l1), - &free, &lock); + true, &free, &lock); continue; } else if (pmap_demote_l2_locked(pmap, l2, sva, &lock) == NULL) @@ -5703,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) { @@ -5747,33 +5756,51 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags, } } SLIST_INIT(&free); - if ((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK) + if ((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK) { (void)pmap_remove_l2(pmap, l2, va, - pmap_load(pmap_l1(pmap, va)), &free, lockp); - else + pmap_load(pmap_l1(pmap, va)), false, &free, lockp); + } else { + if (ADDR_IS_KERNEL(va)) { + /* + * Try to save the ptp in the trie + * before any changes to mappings are + * made. Abort on failure. + */ + mt = PTE_TO_VM_PAGE(old_l2); + if (pmap_insert_pt_page(pmap, mt, false, + false)) { + CTR1(KTR_PMAP, + "pmap_enter_l2: cannot ins kern ptp va %#lx", + va); + return (KERN_RESOURCE_SHORTAGE); + } + /* + * Both pmap_remove_l2() and + * pmap_remove_l3_range() will zero fill + * the L3 kernel page table page. + */ + } pmap_remove_l3_range(pmap, old_l2, va, va + L2_SIZE, &free, lockp); + if (ADDR_IS_KERNEL(va)) { + /* + * The TLB could have an intermediate + * entry for the L3 kernel page table + * page, so request an invalidation at + * all levels after clearing the + * L2_TABLE entry. + */ + pmap_clear(l2); + pmap_s1_invalidate_page(pmap, va, false); + } + } + KASSERT(pmap_load(l2) == 0, + ("pmap_enter_l2: non-zero L2 entry %p", l2)); if (!ADDR_IS_KERNEL(va)) { vm_page_free_pages_toq(&free, true); - KASSERT(pmap_load(l2) == 0, - ("pmap_enter_l2: non-zero L2 entry %p", l2)); } else { KASSERT(SLIST_EMPTY(&free), ("pmap_enter_l2: freed kernel page table page")); - - /* - * Both pmap_remove_l2() and pmap_remove_l3_range() - * will leave the kernel page table page zero filled. - * Nonetheless, the TLB could have an intermediate - * entry for the kernel page table page, so request - * an invalidation at all levels after clearing - * the L2_TABLE entry. - */ - mt = PTE_TO_VM_PAGE(pmap_load(l2)); - if (pmap_insert_pt_page(pmap, mt, false, false)) - panic("pmap_enter_l2: trie insert failed"); - pmap_clear(l2); - pmap_s1_invalidate_page(pmap, va, false); } } @@ -5804,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, @@ -8045,6 +8081,8 @@ pmap_unmapbios(void *p, vm_size_t size) void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) { + if (m->md.pv_memattr == ma) + return; m->md.pv_memattr = ma; @@ -8424,8 +8462,8 @@ pmap_demote_l2_abort(pmap_t pmap, vm_offset_t va, pt_entry_t *l2, struct spglist free; SLIST_INIT(&free); - (void)pmap_remove_l2(pmap, l2, va, pmap_load(pmap_l1(pmap, va)), &free, - lockp); + (void)pmap_remove_l2(pmap, l2, va, pmap_load(pmap_l1(pmap, va)), true, + &free, lockp); vm_page_free_pages_toq(&free, true); } @@ -8463,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")); @@ -8530,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/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index cfb054235489..1c6d64d6b8bc 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -1911,7 +1911,7 @@ linprocfs_doproclimits(PFS_FILL_ARGS) "kern.sigqueue.max_pending_per_proc", &res, &size, 0, 0, 0, 0); if (error != 0) - goto out; + continue; rl.rlim_cur = res; rl.rlim_max = res; break; @@ -1919,7 +1919,7 @@ linprocfs_doproclimits(PFS_FILL_ARGS) error = kernel_sysctlbyname(td, "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0); if (error != 0) - goto out; + continue; rl.rlim_cur = res; rl.rlim_max = res; break; @@ -1941,9 +1941,9 @@ linprocfs_doproclimits(PFS_FILL_ARGS) li->desc, (unsigned long long)rl.rlim_cur, (unsigned long long)rl.rlim_max, li->unit); } -out: + lim_free(limp); - return (error); + return (0); } /* diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 86834a7ecea8..a4be5313aa96 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1792,7 +1792,7 @@ linux_memfd_create(struct thread *td, struct linux_memfd_create_args *args) if ((flags & MFD_ALLOW_SEALING) != 0) shmflags |= SHM_ALLOW_SEALING; return (kern_shm_open2(td, SHM_ANON, oflags, 0, shmflags, NULL, - memfd_name)); + memfd_name, NULL)); } int diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index f3a840d9bf4b..efa5c8cb67b3 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -45,7 +45,7 @@ MALLOC_DECLARE(M_KMALLOC); -#define kvzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) +#define kvzalloc(size, flags) kvmalloc(size, (flags) | __GFP_ZERO) #define kvcalloc(n, size, flags) kvmalloc_array(n, size, (flags) | __GFP_ZERO) #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) #define kzalloc_node(size, flags, node) kmalloc_node(size, (flags) | __GFP_ZERO, node) diff --git a/sys/compat/linuxkpi/common/src/linux_page.c b/sys/compat/linuxkpi/common/src/linux_page.c index ebb92eacbf9a..628af17df853 100644 --- a/sys/compat/linuxkpi/common/src/linux_page.c +++ b/sys/compat/linuxkpi/common/src/linux_page.c @@ -106,6 +106,7 @@ linux_alloc_pages(gfp_t flags, unsigned int order) if ((flags & M_ZERO) != 0) req |= VM_ALLOC_ZERO; + if (order == 0 && (flags & GFP_DMA32) == 0) { page = vm_page_alloc_noobj(req); if (page == NULL) @@ -113,6 +114,10 @@ linux_alloc_pages(gfp_t flags, unsigned int order) } else { vm_paddr_t pmax = (flags & GFP_DMA32) ? BUS_SPACE_MAXADDR_32BIT : BUS_SPACE_MAXADDR; + + if ((flags & __GFP_NORETRY) != 0) + req |= VM_ALLOC_NORECLAIM; + retry: page = vm_page_alloc_noobj_contig(req, npages, 0, pmax, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); diff --git a/sys/conf/files b/sys/conf/files index 74d251c2b608..b7c19fae0b8e 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 @@ -3755,6 +3768,7 @@ gnu/gcov/gcov_subr.c optional gcov kern/bus_if.m standard kern/clock_if.m standard +kern/coredump_vnode.c standard kern/cpufreq_if.m standard kern/device_if.m standard kern/imgact_binmisc.c optional imgact_binmisc @@ -3843,6 +3857,7 @@ kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_tslog.c optional tslog kern/kern_ubsan.c optional kubsan +kern/kern_ucoredump.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_vnodedumper.c standard 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/conf/files.x86 b/sys/conf/files.x86 index df206b314b38..9976e9cfec5d 100644 --- a/sys/conf/files.x86 +++ b/sys/conf/files.x86 @@ -62,6 +62,7 @@ dev/acpi_support/acpi_wmi_if.m standard dev/agp/agp_amd64.c optional agp dev/agp/agp_i810.c optional agp dev/agp/agp_via.c optional agp +dev/amdsmu/amdsmu.c optional amdsmu pci dev/amdsbwd/amdsbwd.c optional amdsbwd dev/amdsmn/amdsmn.c optional amdsmn | amdtemp dev/amdtemp/amdtemp.c optional amdtemp diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c new file mode 100644 index 000000000000..416f875c6176 --- /dev/null +++ b/sys/dev/amdsmu/amdsmu.c @@ -0,0 +1,466 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * + * This software was developed by Aymeric Wibo <obiwac@freebsd.org> + * under sponsorship from the FreeBSD Foundation. + */ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/sysctl.h> + +#include <dev/pci/pcivar.h> +#include <dev/amdsmu/amdsmu.h> + +static bool +amdsmu_match(device_t dev, const struct amdsmu_product **product_out) +{ + const uint16_t vendorid = pci_get_vendor(dev); + const uint16_t deviceid = pci_get_device(dev); + + for (size_t i = 0; i < nitems(amdsmu_products); i++) { + const struct amdsmu_product *prod = &amdsmu_products[i]; + + if (vendorid == prod->amdsmu_vendorid && + deviceid == prod->amdsmu_deviceid) { + if (product_out != NULL) + *product_out = prod; + return (true); + } + } + return (false); +} + +static void +amdsmu_identify(driver_t *driver, device_t parent) +{ + if (device_find_child(parent, "amdsmu", -1) != NULL) + return; + + if (amdsmu_match(parent, NULL)) { + if (device_add_child(parent, "amdsmu", -1) == NULL) + device_printf(parent, "add amdsmu child failed\n"); + } +} + +static int +amdsmu_probe(device_t dev) +{ + if (resource_disabled("amdsmu", 0)) + return (ENXIO); + if (!amdsmu_match(device_get_parent(dev), NULL)) + return (ENXIO); + device_set_descf(dev, "AMD System Management Unit"); + + return (BUS_PROBE_GENERIC); +} + +static enum amdsmu_res +amdsmu_wait_res(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + enum amdsmu_res res; + + /* + * The SMU has a response ready for us when the response register is + * set. Otherwise, we must wait. + */ + for (size_t i = 0; i < SMU_RES_READ_MAX; i++) { + res = amdsmu_read4(sc, SMU_REG_RESPONSE); + if (res != SMU_RES_WAIT) + return (res); + pause_sbt("amdsmu", ustosbt(SMU_RES_READ_PERIOD_US), 0, + C_HARDCLOCK); + } + device_printf(dev, "timed out waiting for response from SMU\n"); + return (SMU_RES_WAIT); +} + +static int +amdsmu_cmd(device_t dev, enum amdsmu_msg msg, uint32_t arg, uint32_t *ret) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + enum amdsmu_res res; + + /* Wait for SMU to be ready. */ + if (amdsmu_wait_res(dev) == SMU_RES_WAIT) + return (ETIMEDOUT); + + /* Clear previous response. */ + amdsmu_write4(sc, SMU_REG_RESPONSE, SMU_RES_WAIT); + + /* Write out command to registers. */ + amdsmu_write4(sc, SMU_REG_MESSAGE, msg); + amdsmu_write4(sc, SMU_REG_ARGUMENT, arg); + + /* Wait for SMU response and handle it. */ + res = amdsmu_wait_res(dev); + + switch (res) { + case SMU_RES_WAIT: + return (ETIMEDOUT); + case SMU_RES_OK: + if (ret != NULL) + *ret = amdsmu_read4(sc, SMU_REG_ARGUMENT); + return (0); + case SMU_RES_REJECT_BUSY: + device_printf(dev, "SMU is busy\n"); + return (EBUSY); + case SMU_RES_REJECT_PREREQ: + case SMU_RES_UNKNOWN: + case SMU_RES_FAILED: + device_printf(dev, "SMU error: %02x\n", res); + return (EIO); + } + + return (EINVAL); +} + +static int +amdsmu_get_vers(device_t dev) +{ + int err; + uint32_t smu_vers; + struct amdsmu_softc *sc = device_get_softc(dev); + + err = amdsmu_cmd(dev, SMU_MSG_GETSMUVERSION, 0, &smu_vers); + if (err != 0) { + device_printf(dev, "failed to get SMU version\n"); + return (err); + } + sc->smu_program = (smu_vers >> 24) & 0xFF; + sc->smu_maj = (smu_vers >> 16) & 0xFF; + sc->smu_min = (smu_vers >> 8) & 0xFF; + sc->smu_rev = smu_vers & 0xFF; + device_printf(dev, "SMU version: %d.%d.%d (program %d)\n", + sc->smu_maj, sc->smu_min, sc->smu_rev, sc->smu_program); + + return (0); +} + +static int +amdsmu_get_ip_blocks(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + const uint16_t deviceid = pci_get_device(dev); + int err; + struct amdsmu_metrics *m = &sc->metrics; + bool active; + char sysctl_descr[32]; + + /* Get IP block count. */ + switch (deviceid) { + case PCI_DEVICEID_AMD_REMBRANDT_ROOT: + sc->ip_block_count = 12; + break; + case PCI_DEVICEID_AMD_PHOENIX_ROOT: + sc->ip_block_count = 21; + break; + /* TODO How many IP blocks does Strix Point (and the others) have? */ + case PCI_DEVICEID_AMD_STRIX_POINT_ROOT: + default: + sc->ip_block_count = nitems(amdsmu_ip_blocks_names); + } + KASSERT(sc->ip_block_count <= nitems(amdsmu_ip_blocks_names), + ("too many IP blocks for array")); + + /* Get and print out IP blocks. */ + err = amdsmu_cmd(dev, SMU_MSG_GET_SUP_CONSTRAINTS, 0, + &sc->active_ip_blocks); + if (err != 0) { + device_printf(dev, "failed to get IP blocks\n"); + return (err); + } + device_printf(dev, "Active IP blocks: "); + for (size_t i = 0; i < sc->ip_block_count; i++) { + active = (sc->active_ip_blocks & (1 << i)) != 0; + sc->ip_blocks_active[i] = active; + if (!active) + continue; + printf("%s%s", amdsmu_ip_blocks_names[i], + i + 1 < sc->ip_block_count ? " " : "\n"); + } + + /* Create a sysctl node for IP blocks. */ + sc->ip_blocks_sysctlnode = SYSCTL_ADD_NODE(sc->sysctlctx, + SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, "ip_blocks", + CTLFLAG_RD, NULL, "SMU metrics"); + if (sc->ip_blocks_sysctlnode == NULL) { + device_printf(dev, "could not add sysctl node for IP blocks\n"); + return (ENOMEM); + } + + /* Create a sysctl node for each IP block. */ + for (size_t i = 0; i < sc->ip_block_count; i++) { + /* Create the sysctl node itself for the IP block. */ + snprintf(sysctl_descr, sizeof sysctl_descr, + "Metrics about the %s AMD IP block", + amdsmu_ip_blocks_names[i]); + sc->ip_block_sysctlnodes[i] = SYSCTL_ADD_NODE(sc->sysctlctx, + SYSCTL_CHILDREN(sc->ip_blocks_sysctlnode), OID_AUTO, + amdsmu_ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr); + if (sc->ip_block_sysctlnodes[i] == NULL) { + device_printf(dev, + "could not add sysctl node for \"%s\"\n", sysctl_descr); + continue; + } + /* + * Create sysctls for if the IP block is currently active, last + * active time, and total active time. + */ + SYSCTL_ADD_BOOL(sc->sysctlctx, + SYSCTL_CHILDREN(sc->ip_block_sysctlnodes[i]), OID_AUTO, + "active", CTLFLAG_RD, &sc->ip_blocks_active[i], 0, + "IP block is currently active"); + SYSCTL_ADD_U64(sc->sysctlctx, + SYSCTL_CHILDREN(sc->ip_block_sysctlnodes[i]), OID_AUTO, + "last_time", CTLFLAG_RD, &m->ip_block_last_active_time[i], + 0, "How long the IP block was active for during the last" + " sleep (us)"); +#ifdef IP_BLOCK_TOTAL_ACTIVE_TIME + SYSCTL_ADD_U64(sc->sysctlctx, + SYSCTL_CHILDREN(sc->ip_block_sysctlnodes[i]), OID_AUTO, + "total_time", CTLFLAG_RD, &m->ip_block_total_active_time[i], + 0, "How long the IP block was active for during sleep in" + " total (us)"); +#endif + } + return (0); +} + +static int +amdsmu_init_metrics(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + int err; + uint32_t metrics_addr_lo, metrics_addr_hi; + uint64_t metrics_addr; + + /* Get physical address of logging buffer. */ + err = amdsmu_cmd(dev, SMU_MSG_LOG_GETDRAM_ADDR_LO, 0, &metrics_addr_lo); + if (err != 0) + return (err); + err = amdsmu_cmd(dev, SMU_MSG_LOG_GETDRAM_ADDR_HI, 0, &metrics_addr_hi); + if (err != 0) + return (err); + metrics_addr = ((uint64_t) metrics_addr_hi << 32) | metrics_addr_lo; + + /* Map memory of logging buffer. */ + err = bus_space_map(sc->bus_tag, metrics_addr, + sizeof(struct amdsmu_metrics), 0, &sc->metrics_space); + if (err != 0) { + device_printf(dev, "could not map bus space for SMU metrics\n"); + return (err); + } + + /* Start logging for metrics. */ + amdsmu_cmd(dev, SMU_MSG_LOG_RESET, 0, NULL); + amdsmu_cmd(dev, SMU_MSG_LOG_START, 0, NULL); + return (0); +} + +static int +amdsmu_dump_metrics(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + int err; + + err = amdsmu_cmd(dev, SMU_MSG_LOG_DUMP_DATA, 0, NULL); + if (err != 0) { + device_printf(dev, "failed to dump metrics\n"); + return (err); + } + bus_space_read_region_4(sc->bus_tag, sc->metrics_space, 0, + (uint32_t *)&sc->metrics, sizeof(sc->metrics) / sizeof(uint32_t)); + + return (0); +} + +static void +amdsmu_fetch_idlemask(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + + sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK); +} + +static int +amdsmu_attach(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + int err; + uint32_t physbase_addr_lo, physbase_addr_hi; + uint64_t physbase_addr; + int rid = 0; + struct sysctl_oid *node; + + /* + * Find physical base address for SMU. + * XXX I am a little confused about the masks here. I'm just copying + * what Linux does in the amd-pmc driver to get the base address. + */ + pci_write_config(dev, SMU_INDEX_ADDRESS, SMU_PHYSBASE_ADDR_LO, 4); + physbase_addr_lo = pci_read_config(dev, SMU_INDEX_DATA, 4) & 0xFFF00000; + + pci_write_config(dev, SMU_INDEX_ADDRESS, SMU_PHYSBASE_ADDR_HI, 4); + physbase_addr_hi = pci_read_config(dev, SMU_INDEX_DATA, 4) & 0x0000FFFF; + + physbase_addr = (uint64_t)physbase_addr_hi << 32 | physbase_addr_lo; + + /* Map memory for SMU and its registers. */ + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "could not allocate resource\n"); + return (ENXIO); + } + + sc->bus_tag = rman_get_bustag(sc->res); + + if (bus_space_map(sc->bus_tag, physbase_addr, + SMU_MEM_SIZE, 0, &sc->smu_space) != 0) { + device_printf(dev, "could not map bus space for SMU\n"); + err = ENXIO; + goto err_smu_space; + } + if (bus_space_map(sc->bus_tag, physbase_addr + SMU_REG_SPACE_OFF, + SMU_MEM_SIZE, 0, &sc->reg_space) != 0) { + device_printf(dev, "could not map bus space for SMU regs\n"); + err = ENXIO; + goto err_reg_space; + } + + /* sysctl stuff. */ + sc->sysctlctx = device_get_sysctl_ctx(dev); + sc->sysctlnode = device_get_sysctl_tree(dev); + + /* Get version & add sysctls. */ + if ((err = amdsmu_get_vers(dev)) != 0) + goto err_dump; + + SYSCTL_ADD_U8(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, + "program", CTLFLAG_RD, &sc->smu_program, 0, "SMU program number"); + SYSCTL_ADD_U8(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, + "version_major", CTLFLAG_RD, &sc->smu_maj, 0, + "SMU firmware major version number"); + SYSCTL_ADD_U8(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, + "version_minor", CTLFLAG_RD, &sc->smu_min, 0, + "SMU firmware minor version number"); + SYSCTL_ADD_U8(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, + "version_revision", CTLFLAG_RD, &sc->smu_rev, 0, + "SMU firmware revision number"); + + /* Set up for getting metrics & add sysctls. */ + if ((err = amdsmu_init_metrics(dev)) != 0) + goto err_dump; + if ((err = amdsmu_dump_metrics(dev)) != 0) + goto err_dump; + + node = SYSCTL_ADD_NODE(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), + OID_AUTO, "metrics", CTLFLAG_RD, NULL, "SMU metrics"); + if (node == NULL) { + device_printf(dev, "could not add sysctl node for metrics\n"); + err = ENOMEM; + goto err_dump; + } + + SYSCTL_ADD_U32(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "table_version", CTLFLAG_RD, &sc->metrics.table_version, 0, + "SMU metrics table version"); + SYSCTL_ADD_U32(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "hint_count", CTLFLAG_RD, &sc->metrics.hint_count, 0, + "How many times the sleep hint was set"); + SYSCTL_ADD_U32(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "s0i3_last_entry_status", CTLFLAG_RD, + &sc->metrics.s0i3_last_entry_status, 0, + "1 if last S0i3 entry was successful"); + SYSCTL_ADD_U32(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "time_last_in_s0i2", CTLFLAG_RD, &sc->metrics.time_last_in_s0i2, 0, + "Time spent in S0i2 during last sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "time_last_entering_s0i3", CTLFLAG_RD, + &sc->metrics.time_last_entering_s0i3, 0, + "Time spent entering S0i3 during last sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "total_time_entering_s0i3", CTLFLAG_RD, + &sc->metrics.total_time_entering_s0i3, 0, + "Total time spent entering S0i3 (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "time_last_resuming", CTLFLAG_RD, &sc->metrics.time_last_resuming, + 0, "Time spent resuming from last sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "total_time_resuming", CTLFLAG_RD, &sc->metrics.total_time_resuming, + 0, "Total time spent resuming from sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "time_last_in_s0i3", CTLFLAG_RD, &sc->metrics.time_last_in_s0i3, 0, + "Time spent in S0i3 during last sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "total_time_in_s0i3", CTLFLAG_RD, &sc->metrics.total_time_in_s0i3, + 0, "Total time spent in S0i3 (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "time_last_in_sw_drips", CTLFLAG_RD, + &sc->metrics.time_last_in_sw_drips, 0, + "Time spent in awake during last sleep (us)"); + SYSCTL_ADD_U64(sc->sysctlctx, SYSCTL_CHILDREN(node), OID_AUTO, + "total_time_in_sw_drips", CTLFLAG_RD, + &sc->metrics.total_time_in_sw_drips, 0, + "Total time spent awake (us)"); + + /* Get IP blocks & add sysctls. */ + err = amdsmu_get_ip_blocks(dev); + if (err != 0) + goto err_dump; + + /* Get idlemask & add sysctl. */ + amdsmu_fetch_idlemask(dev); + SYSCTL_ADD_U32(sc->sysctlctx, SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, + "idlemask", CTLFLAG_RD, &sc->idlemask, 0, "SMU idlemask. This " + "value is not documented - only used to help AMD internally debug " + "issues"); + + return (0); +err_dump: + bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); +err_reg_space: + bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE); +err_smu_space: + bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res); + return (err); +} + +static int +amdsmu_detach(device_t dev) +{ + struct amdsmu_softc *sc = device_get_softc(dev); + int rid = 0; + + bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE); + bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); + + bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res); + return (0); +} + +static device_method_t amdsmu_methods[] = { + DEVMETHOD(device_identify, amdsmu_identify), + DEVMETHOD(device_probe, amdsmu_probe), + DEVMETHOD(device_attach, amdsmu_attach), + DEVMETHOD(device_detach, amdsmu_detach), + DEVMETHOD_END +}; + +static driver_t amdsmu_driver = { + "amdsmu", + amdsmu_methods, + sizeof(struct amdsmu_softc), +}; + +DRIVER_MODULE(amdsmu, hostb, amdsmu_driver, NULL, NULL); +MODULE_VERSION(amdsmu, 1); +MODULE_DEPEND(amdsmu, amdsmn, 1, 1, 1); +MODULE_PNP_INFO("U16:vendor;U16:device", pci, amdsmu, amdsmu_products, + nitems(amdsmu_products)); diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h new file mode 100644 index 000000000000..025887f7fe5a --- /dev/null +++ b/sys/dev/amdsmu/amdsmu.h @@ -0,0 +1,95 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * + * This software was developed by Aymeric Wibo <obiwac@freebsd.org> + * under sponsorship from the FreeBSD Foundation. + */ +#ifndef _AMDSMU_H_ +#define _AMDSMU_H_ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <machine/bus.h> +#include <x86/cputypes.h> + +#include <dev/amdsmu/amdsmu_reg.h> + +#define SMU_RES_READ_PERIOD_US 50 +#define SMU_RES_READ_MAX 20000 + +static const struct amdsmu_product { + uint16_t amdsmu_vendorid; + uint16_t amdsmu_deviceid; +} amdsmu_products[] = { + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_STRIX_POINT_ROOT }, +}; + +static const char *const amdsmu_ip_blocks_names[] = { + "DISPLAY", + "CPU", + "GFX", + "VDD", + "ACP", + "VCN", + "ISP", + "NBIO", + "DF", + "USB3_0", + "USB3_1", + "LAPIC", + "USB3_2", + "USB3_3", + "USB3_4", + "USB4_0", + "USB4_1", + "MPM", + "JPEG", + "IPU", + "UMSCH", + "VPE", +}; + +CTASSERT(nitems(amdsmu_ip_blocks_names) <= 32); + +struct amdsmu_softc { + struct sysctl_ctx_list *sysctlctx; + struct sysctl_oid *sysctlnode; + + struct resource *res; + bus_space_tag_t bus_tag; + + bus_space_handle_t smu_space; + bus_space_handle_t reg_space; + + uint8_t smu_program; + uint8_t smu_maj, smu_min, smu_rev; + + uint32_t active_ip_blocks; + struct sysctl_oid *ip_blocks_sysctlnode; + size_t ip_block_count; + struct sysctl_oid *ip_block_sysctlnodes[nitems(amdsmu_ip_blocks_names)]; + bool ip_blocks_active[nitems(amdsmu_ip_blocks_names)]; + + bus_space_handle_t metrics_space; + struct amdsmu_metrics metrics; + uint32_t idlemask; +}; + +static inline uint32_t +amdsmu_read4(const struct amdsmu_softc *sc, bus_size_t reg) +{ + return (bus_space_read_4(sc->bus_tag, sc->reg_space, reg)); +} + +static inline void +amdsmu_write4(const struct amdsmu_softc *sc, bus_size_t reg, uint32_t val) +{ + bus_space_write_4(sc->bus_tag, sc->reg_space, reg, val); +} + +#endif /* _AMDSMU_H_ */ diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h new file mode 100644 index 000000000000..e685b34e6883 --- /dev/null +++ b/sys/dev/amdsmu/amdsmu_reg.h @@ -0,0 +1,84 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * + * This software was developed by Aymeric Wibo <obiwac@freebsd.org> + * under sponsorship from the FreeBSD Foundation. + */ +#ifndef _AMDSMU_REG_H_ +#define _AMDSMU_REG_H_ + +#include <sys/types.h> + +/* + * TODO These are in common with amdtemp; should we find a way to factor these + * out? Also, there are way more of these. I couldn't find a centralized place + * which lists them though. + */ +#define PCI_DEVICEID_AMD_REMBRANDT_ROOT 0x14B5 +#define PCI_DEVICEID_AMD_PHOENIX_ROOT 0x14E8 +#define PCI_DEVICEID_AMD_STRIX_POINT_ROOT 0x14A4 + +#define SMU_INDEX_ADDRESS 0xB8 +#define SMU_INDEX_DATA 0xBC + +#define SMU_PHYSBASE_ADDR_LO 0x13B102E8 +#define SMU_PHYSBASE_ADDR_HI 0x13B102EC + +#define SMU_MEM_SIZE 0x1000 +#define SMU_REG_SPACE_OFF 0x10000 + +#define SMU_REG_MESSAGE 0x538 +#define SMU_REG_RESPONSE 0x980 +#define SMU_REG_ARGUMENT 0x9BC +#define SMU_REG_IDLEMASK 0xD14 + +enum amdsmu_res { + SMU_RES_WAIT = 0x00, + SMU_RES_OK = 0x01, + SMU_RES_REJECT_BUSY = 0xFC, + SMU_RES_REJECT_PREREQ = 0xFD, + SMU_RES_UNKNOWN = 0xFE, + SMU_RES_FAILED = 0xFF, +}; + +enum amdsmu_msg { + SMU_MSG_GETSMUVERSION = 0x02, + SMU_MSG_LOG_GETDRAM_ADDR_HI = 0x04, + SMU_MSG_LOG_GETDRAM_ADDR_LO = 0x05, + SMU_MSG_LOG_START = 0x06, + SMU_MSG_LOG_RESET = 0x07, + SMU_MSG_LOG_DUMP_DATA = 0x08, + SMU_MSG_GET_SUP_CONSTRAINTS = 0x09, +}; + +/* XXX Copied from Linux struct smu_metrics. */ +struct amdsmu_metrics { + uint32_t table_version; + uint32_t hint_count; + uint32_t s0i3_last_entry_status; + uint32_t time_last_in_s0i2; + uint64_t time_last_entering_s0i3; + uint64_t total_time_entering_s0i3; + uint64_t time_last_resuming; + uint64_t total_time_resuming; + uint64_t time_last_in_s0i3; + uint64_t total_time_in_s0i3; + uint64_t time_last_in_sw_drips; + uint64_t total_time_in_sw_drips; + /* + * This is how long each IP block was active for (us), i.e., blocking + * entry to S0i3. In Linux, these are called "timecondition_notmet_*". + * + * XXX Total active time for IP blocks seems to be buggy and reporting + * garbage (at least on Phoenix), so it's disabled for now. The last + * active time for the USB4_0 IP block also seems to be buggy. + */ + uint64_t ip_block_last_active_time[32]; +#ifdef IP_BLOCK_TOTAL_ACTIVE_TIME + uint64_t ip_block_total_active_time[32]; +#endif +} __attribute__((packed)); + +#endif /* _AMDSMU_REG_H_ */ diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c index 8547f21586e1..7a6b1cbdd736 100644 --- a/sys/dev/cxgbe/tom/t4_cpl_io.c +++ b/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -703,7 +703,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop) for (m = sndptr; m != NULL; m = m->m_next) { int n; - if ((m->m_flags & M_NOTAVAIL) != 0) + if ((m->m_flags & M_NOTREADY) != 0) break; if (m->m_flags & M_EXTPG) { #ifdef KERN_TLS @@ -787,7 +787,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop) /* nothing to send */ if (plen == 0) { - KASSERT(m == NULL || (m->m_flags & M_NOTAVAIL) != 0, + KASSERT(m == NULL || (m->m_flags & M_NOTREADY) != 0, ("%s: nothing to send, but m != NULL is ready", __func__)); break; @@ -880,7 +880,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop) toep->txsd_avail--; t4_l2t_send(sc, wr, toep->l2te); - } while (m != NULL && (m->m_flags & M_NOTAVAIL) == 0); + } while (m != NULL && (m->m_flags & M_NOTREADY) == 0); /* Send a FIN if requested, but only if there's no more data to send */ if (m == NULL && toep->flags & TPF_SEND_FIN) diff --git a/sys/dev/cxgbe/tom/t4_tls.c b/sys/dev/cxgbe/tom/t4_tls.c index c6377980fca9..27c16b9988ae 100644 --- a/sys/dev/cxgbe/tom/t4_tls.c +++ b/sys/dev/cxgbe/tom/t4_tls.c @@ -563,7 +563,7 @@ t4_push_ktls(struct adapter *sc, struct toepcb *toep, int drop) * If there is no ready data to send, wait until more * data arrives. */ - if (m == NULL || (m->m_flags & M_NOTAVAIL) != 0) { + if (m == NULL || (m->m_flags & M_NOTREADY) != 0) { if (sowwakeup) sowwakeup_locked(so); else @@ -614,7 +614,7 @@ t4_push_ktls(struct adapter *sc, struct toepcb *toep, int drop) /* Shove if there is no additional data pending. */ shove = ((m->m_next == NULL || - (m->m_next->m_flags & M_NOTAVAIL) != 0)) && + (m->m_next->m_flags & M_NOTREADY) != 0)) && (tp->t_flags & TF_MORETOCOME) == 0; if (sb->sb_flags & SB_AUTOSIZE && 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/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index b50e33ea36ce..d5cfd228a429 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -99,6 +99,11 @@ xhci_pci_match(device_t self) return ("AMD Starship USB 3.0 controller"); case 0x149c1022: return ("AMD Matisse USB 3.0 controller"); + case 0x15b61022: + case 0x15b71022: + return ("AMD Raphael/Granite Ridge USB 3.1 controller"); + case 0x15b81022: + return ("AMD Raphael/Granite Ridge USB 2.0 controller"); case 0x15e01022: case 0x15e11022: return ("AMD Raven USB 3.1 controller"); @@ -109,6 +114,8 @@ xhci_pci_match(device_t self) return ("AMD 300 Series USB 3.1 controller"); case 0x43d51022: return ("AMD 400 Series USB 3.1 controller"); + case 0x43f71022: + return ("AMD 600 Series USB 3.2 controller"); case 0x78121022: case 0x78141022: case 0x79141022: diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c index 819debadd1ac..2e2ae0a162d8 100644 --- a/sys/dev/vmm/vmm_dev.c +++ b/sys/dev/vmm/vmm_dev.c @@ -820,7 +820,6 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS) buflen = VM_MAX_NAMELEN + 1; buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO); - strlcpy(buf, "beavis", buflen); error = sysctl_handle_string(oidp, buf, buflen, req); if (error == 0 && req->newptr != NULL) error = vmmdev_lookup_and_destroy(buf, req->td->td_ucred); @@ -830,7 +829,7 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS) SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, NULL, 0, sysctl_vmm_destroy, "A", - NULL); + "Destroy a vmm(4) instance (legacy interface)"); static struct cdevsw vmmdevsw = { .d_name = "vmmdev", @@ -909,7 +908,6 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS) buflen = VM_MAX_NAMELEN + 1; buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO); - strlcpy(buf, "beavis", buflen); error = sysctl_handle_string(oidp, buf, buflen, req); if (error == 0 && req->newptr != NULL) error = vmmdev_create(buf, req->td->td_ucred); @@ -919,7 +917,7 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS) SYSCTL_PROC(_hw_vmm, OID_AUTO, create, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, NULL, 0, sysctl_vmm_create, "A", - NULL); + "Create a vmm(4) instance (legacy interface)"); static int vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td) 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/fuse/fuse_internal.h b/sys/fs/fuse/fuse_internal.h index cddf88095840..932012b5f52a 100644 --- a/sys/fs/fuse/fuse_internal.h +++ b/sys/fs/fuse/fuse_internal.h @@ -208,9 +208,9 @@ fuse_match_cred(struct ucred *basecred, struct ucred *usercred) if (basecred->cr_uid == usercred->cr_uid && basecred->cr_uid == usercred->cr_ruid && basecred->cr_uid == usercred->cr_svuid && - basecred->cr_groups[0] == usercred->cr_groups[0] && - basecred->cr_groups[0] == usercred->cr_rgid && - basecred->cr_groups[0] == usercred->cr_svgid) + basecred->cr_gid == usercred->cr_gid && + basecred->cr_gid == usercred->cr_rgid && + basecred->cr_gid == usercred->cr_svgid) return (0); return (EPERM); diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c index 0b6048644d32..a751c09159ff 100644 --- a/sys/fs/fuse/fuse_ipc.c +++ b/sys/fs/fuse/fuse_ipc.c @@ -868,7 +868,7 @@ fuse_setup_ihead(struct fuse_in_header *ihead, struct fuse_ticket *ftick, ihead->pid = pid; ihead->uid = cred->cr_uid; - ihead->gid = cred->cr_groups[0]; + ihead->gid = cred->cr_gid; } /* diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index ae28617537fd..32872e8f3f3a 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -884,7 +884,7 @@ fuse_vnop_copy_file_range(struct vop_copy_file_range_args *ap) return (EXTERROR(ENOSYS, "FUSE_COPY_FILE_RANGE does not " "support different credentials for infd and outfd")); - if (incred->cr_groups[0] != outcred->cr_groups[0]) + if (incred->cr_gid != outcred->cr_gid) return (EXTERROR(ENOSYS, "FUSE_COPY_FILE_RANGE does not " "support different credentials for infd and outfd")); 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/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 5db61c8951f6..33e0d94954d7 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1521,6 +1521,9 @@ msdosfs_readdir(struct vop_readdir_args *ap) ap->a_vp, uio, ap->a_cred, ap->a_eofflag); #endif + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 0; + /* * msdosfs_readdir() won't operate properly on regular files since * it does i/o only with the filesystem vnode, and hence can @@ -1614,8 +1617,11 @@ msdosfs_readdir(struct vop_readdir_args *ap) on = (offset - bias) & pmp->pm_crbomask; n = min(pmp->pm_bpcluster - on, uio->uio_resid); diff = dep->de_FileSize - (offset - bias); - if (diff <= 0) - break; + if (diff <= 0) { + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 1; + goto out; + } n = min(n, diff); error = pcbmap(dep, lbn, &bn, &cn, &blsize); if (error) @@ -1646,6 +1652,8 @@ msdosfs_readdir(struct vop_readdir_args *ap) */ if (dentp->deName[0] == SLOT_EMPTY) { brelse(bp); + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 1; goto out; } /* @@ -1743,15 +1751,6 @@ out: uio->uio_offset = off; - /* - * Set the eofflag (NFS uses it) - */ - if (ap->a_eofflag) { - if (dep->de_FileSize - (offset - bias) <= 0) - *ap->a_eofflag = 1; - else - *ap->a_eofflag = 0; - } return (error); } diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 0c94f4e7dc52..222cfc03e4b3 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -379,7 +379,8 @@ newnfs_setroot(struct ucred *cred) { cred->cr_uid = 0; - cred->cr_groups[0] = 0; + cred->cr_gid = 0; + /* XXXKE Fix this if cr_gid gets separated out. */ cred->cr_ngroups = 1; } 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..36b534be531e 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); @@ -6932,7 +6933,8 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0) { tcred = NFSNEWCRED(cred); tcred->cr_uid = flp->nfsfl_ffm[mirror].user; - tcred->cr_groups[0] = flp->nfsfl_ffm[mirror].group; + tcred->cr_gid = flp->nfsfl_ffm[mirror].group; + /* XXXKE Fix this if cr_gid gets separated out. */ tcred->cr_ngroups = 1; } else tcred = cred; 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.h b/sys/geom/geom.h index dcd6f793f9f7..908ce86f03a6 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -282,7 +282,7 @@ void g_detach(struct g_consumer *cp); void g_error_provider(struct g_provider *pp, int error); struct g_provider *g_provider_by_name(char const *arg); int g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len); -#define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof *(v)) +#define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof(*(v))) int g_handleattr(struct bio *bp, const char *attribute, const void *val, int len); int g_handleattr_int(struct bio *bp, const char *attribute, int val); diff --git a/sys/geom/geom_ccd.c b/sys/geom/geom_ccd.c index 5700399ee5d1..2140d005160e 100644 --- a/sys/geom/geom_ccd.c +++ b/sys/geom/geom_ccd.c @@ -730,17 +730,17 @@ g_ccd_create(struct gctl_req *req, struct g_class *mp) int i, error; g_topology_assert(); - unit = gctl_get_paraml(req, "unit", sizeof (*unit)); + unit = gctl_get_paraml(req, "unit", sizeof(*unit)); if (unit == NULL) { gctl_error(req, "unit parameter not given"); return; } - ileave = gctl_get_paraml(req, "ileave", sizeof (*ileave)); + ileave = gctl_get_paraml(req, "ileave", sizeof(*ileave)); if (ileave == NULL) { gctl_error(req, "ileave parameter not given"); return; } - nprovider = gctl_get_paraml(req, "nprovider", sizeof (*nprovider)); + nprovider = gctl_get_paraml(req, "nprovider", sizeof(*nprovider)); if (nprovider == NULL) { gctl_error(req, "nprovider parameter not given"); return; @@ -769,7 +769,7 @@ g_ccd_create(struct gctl_req *req, struct g_class *mp) } gp = g_new_geomf(mp, "ccd%d", *unit); - sc = g_malloc(sizeof *sc, M_WAITOK | M_ZERO); + sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); gp->softc = sc; sc->sc_ndisks = *nprovider; @@ -872,7 +872,7 @@ g_ccd_list(struct gctl_req *req, struct g_class *mp) struct g_geom *gp; int i, unit, *up; - up = gctl_get_paraml(req, "unit", sizeof (*up)); + up = gctl_get_paraml(req, "unit", sizeof(*up)); if (up == NULL) { gctl_error(req, "unit parameter not given"); return; diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c index 0a76fd6c6f57..341233a6ef47 100644 --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -145,7 +145,7 @@ g_attr_changed(struct g_provider *pp, const char *attr, int flag) struct g_attrchanged_args *args; int error; - args = g_malloc(sizeof *args, flag); + args = g_malloc(sizeof(*args), flag); if (args == NULL) return (ENOMEM); args->pp = pp; diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index 8d6b9a926e1d..247a623bf1bf 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -278,7 +278,7 @@ g_io_init(void) g_bioq_init(&g_bio_run_down); g_bioq_init(&g_bio_run_up); - biozone = uma_zcreate("g_bio", sizeof (struct bio), + biozone = uma_zcreate("g_bio", sizeof(struct bio), NULL, NULL, NULL, NULL, 0, 0); diff --git a/sys/geom/geom_slice.c b/sys/geom/geom_slice.c index 8cfffc478849..0491b0069be4 100644 --- a/sys/geom/geom_slice.c +++ b/sys/geom/geom_slice.c @@ -57,7 +57,7 @@ g_slice_alloc(unsigned nslice, unsigned scsize) { struct g_slicer *gsp; - gsp = g_malloc(sizeof *gsp, M_WAITOK | M_ZERO); + gsp = g_malloc(sizeof(*gsp), M_WAITOK | M_ZERO); if (scsize > 0) gsp->softc = g_malloc(scsize, M_WAITOK | M_ZERO); else @@ -463,9 +463,9 @@ g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length, int r } gsl = gsp->hotspot; if(idx >= gsp->nhotspot) { - gsl2 = g_malloc((idx + 1) * sizeof *gsl2, M_WAITOK | M_ZERO); + gsl2 = g_malloc((idx + 1) * sizeof(*gsl2), M_WAITOK | M_ZERO); if (gsp->hotspot != NULL) - bcopy(gsp->hotspot, gsl2, gsp->nhotspot * sizeof *gsl2); + bcopy(gsp->hotspot, gsl2, gsp->nhotspot * sizeof(*gsl2)); gsp->hotspot = gsl2; if (gsp->hotspot != NULL) g_free(gsl); diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 41cc115225f9..1429c84942ed 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -267,7 +267,7 @@ g_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", mp->name); - hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh = g_malloc(sizeof(*hh), M_WAITOK | M_ZERO); hh->mp = mp; /* * Once the system is not cold, MOD_LOAD calls will be @@ -351,7 +351,7 @@ g_retaste(struct g_class *mp) if (mp->taste == NULL) return (EINVAL); - hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh = g_malloc(sizeof(*hh), M_WAITOK | M_ZERO); hh->mp = mp; if (cold) { @@ -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); } @@ -528,7 +527,7 @@ g_new_consumer(struct g_geom *gp) ("g_new_consumer on geom(%s) (class %s) without orphan", gp->name, gp->class->name)); - cp = g_malloc(sizeof *cp, M_WAITOK | M_ZERO); + cp = g_malloc(sizeof(*cp), M_WAITOK | M_ZERO); cp->geom = gp; cp->stat = devstat_new_entry(cp, -1, 0, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); @@ -617,7 +616,7 @@ g_new_providerf(struct g_geom *gp, const char *fmt, ...) sbuf_vprintf(sb, fmt, ap); va_end(ap); sbuf_finish(sb); - pp = g_malloc(sizeof *pp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); + pp = g_malloc(sizeof(*pp) + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); pp->name = (char *)(pp + 1); strcpy(pp->name, sbuf_data(sb)); sbuf_delete(sb); @@ -749,7 +748,7 @@ g_resize_provider(struct g_provider *pp, off_t size) if (size == pp->mediasize) return; - hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh = g_malloc(sizeof(*hh), M_WAITOK | M_ZERO); hh->pp = pp; hh->size = size; g_post_event(g_resize_provider_event, hh, M_WAITOK, NULL); @@ -1083,21 +1082,21 @@ int g_handleattr_int(struct bio *bp, const char *attribute, int val) { - return (g_handleattr(bp, attribute, &val, sizeof val)); + return (g_handleattr(bp, attribute, &val, sizeof(val))); } int g_handleattr_uint16_t(struct bio *bp, const char *attribute, uint16_t val) { - return (g_handleattr(bp, attribute, &val, sizeof val)); + return (g_handleattr(bp, attribute, &val, sizeof(val))); } int g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val) { - return (g_handleattr(bp, attribute, &val, sizeof val)); + return (g_handleattr(bp, attribute, &val, sizeof(val))); } int diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 23088c895541..a4935df7eaa1 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -321,7 +321,7 @@ g_multipath_resize(struct g_consumer *cp) if (sc->sc_uuid[0] != 0) { pp = cp->provider; strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); - memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid)); + memcpy(md.md_uuid, sc->sc_uuid, sizeof(sc->sc_uuid)); strlcpy(md.md_name, sc->sc_name, sizeof(md.md_name)); md.md_version = G_MULTIPATH_VERSION; md.md_size = size; @@ -552,8 +552,8 @@ g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md) gp = g_new_geomf(mp, "%s", md->md_name); sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); mtx_init(&sc->sc_mtx, "multipath", NULL, MTX_DEF); - memcpy(sc->sc_uuid, md->md_uuid, sizeof (sc->sc_uuid)); - memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name)); + memcpy(sc->sc_uuid, md->md_uuid, sizeof(sc->sc_uuid)); + memcpy(sc->sc_name, md->md_name, sizeof(sc->sc_name)); sc->sc_active_active = md->md_active_active; sc->sc_size = md->md_size; gp->softc = sc; @@ -906,7 +906,7 @@ g_multipath_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) char buf[16]; u_long rand = random(); - snprintf(buf, sizeof (buf), "%s-%lu", md.md_name, rand); + snprintf(buf, sizeof(buf), "%s-%lu", md.md_name, rand); printf("GEOM_MULTIPATH: geom %s/%s exists already\n", sc->sc_name, sc->sc_uuid); printf("GEOM_MULTIPATH: %s will be (temporarily) %s\n", @@ -1200,7 +1200,7 @@ g_multipath_ctl_configure(struct gctl_req *req, struct g_class *mp) cp = sc->sc_active; pp = cp->provider; strlcpy(md.md_magic, G_MULTIPATH_MAGIC, sizeof(md.md_magic)); - memcpy(md.md_uuid, sc->sc_uuid, sizeof (sc->sc_uuid)); + memcpy(md.md_uuid, sc->sc_uuid, sizeof(sc->sc_uuid)); strlcpy(md.md_name, name, sizeof(md.md_name)); md.md_version = G_MULTIPATH_VERSION; md.md_size = pp->mediasize; diff --git a/sys/geom/virstor/g_virstor.c b/sys/geom/virstor/g_virstor.c index b8cf32875660..c7d737493f11 100644 --- a/sys/geom/virstor/g_virstor.c +++ b/sys/geom/virstor/g_virstor.c @@ -202,7 +202,7 @@ virstor_ctl_stop(struct gctl_req *req, struct g_class *cp) int *force, *nargs; int i; - nargs = gctl_get_paraml(req, "nargs", sizeof *nargs); + nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "Error fetching argument '%s'", "nargs"); return; @@ -211,7 +211,7 @@ virstor_ctl_stop(struct gctl_req *req, struct g_class *cp) gctl_error(req, "Invalid number of arguments"); return; } - force = gctl_get_paraml(req, "force", sizeof *force); + force = gctl_get_paraml(req, "force", sizeof(*force)); if (force == NULL) { gctl_error(req, "Error fetching argument '%s'", "force"); return; @@ -315,7 +315,7 @@ virstor_ctl_add(struct gctl_req *req, struct g_class *cp) u_int nc; u_int j; - snprintf(aname, sizeof aname, "arg%d", i); + snprintf(aname, sizeof(aname), "arg%d", i); pp = gctl_get_provider(req, aname); if (pp == NULL) { /* This is the most common error so be verbose about it */ @@ -487,12 +487,12 @@ fill_metadata(struct g_virstor_softc *sc, struct g_virstor_metadata *md, { struct g_virstor_component *c; - bzero(md, sizeof *md); + bzero(md, sizeof(*md)); c = &sc->components[nc]; - strncpy(md->md_magic, G_VIRSTOR_MAGIC, sizeof md->md_magic); + strncpy(md->md_magic, G_VIRSTOR_MAGIC, sizeof(md->md_magic)); md->md_version = G_VIRSTOR_VERSION; - strncpy(md->md_name, sc->geom->name, sizeof md->md_name); + strncpy(md->md_name, sc->geom->name, sizeof(md->md_name)); md->md_id = sc->id; md->md_virsize = sc->virsize; md->md_chunk_size = sc->chunk_size; @@ -500,7 +500,7 @@ fill_metadata(struct g_virstor_softc *sc, struct g_virstor_metadata *md, if (hardcode) { strncpy(md->provider, c->gcons->provider->name, - sizeof md->provider); + sizeof(md->provider)); } md->no = nc; md->provsize = c->gcons->provider->mediasize; @@ -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", @@ -959,7 +959,7 @@ virstor_geom_destroy(struct g_virstor_softc *sc, boolean_t force, free(sc->map, M_GVIRSTOR); free(sc->components, M_GVIRSTOR); - bzero(sc, sizeof *sc); + bzero(sc, sizeof(*sc)); free(sc, M_GVIRSTOR); pp = LIST_FIRST(&gp->provider); /* We only offer one provider */ @@ -1213,7 +1213,7 @@ virstor_check_and_run(struct g_virstor_softc *sc) sc->provider->name, sc->chunk_count * (off_t)sc->chunk_size); } - sc->map_size = sc->chunk_count * sizeof *(sc->map); + sc->map_size = sc->chunk_count * sizeof(*(sc->map)); /* The following allocation is in order of 4MB - 8MB */ sc->map = malloc(sc->map_size, M_GVIRSTOR, M_WAITOK); KASSERT(sc->map != NULL, ("%s: Memory allocation error (%zu bytes) for %s", @@ -1267,7 +1267,7 @@ virstor_check_and_run(struct g_virstor_softc *sc) bcopy(mapbuf, &sc->map[n], bs); off += bs; count += bs; - n += bs / sizeof *(sc->map); + n += bs / sizeof(*(sc->map)); g_free(mapbuf); } g_access(sc->components[0].gcons, -1, 0, 0); @@ -1306,8 +1306,8 @@ virstor_check_and_run(struct g_virstor_softc *sc) sc->components[index].chunk_next); } - sc->me_per_sector = sc->sectorsize / sizeof *(sc->map); - if (sc->sectorsize % sizeof *(sc->map) != 0) { + sc->me_per_sector = sc->sectorsize / sizeof(*(sc->map)); + if (sc->sectorsize % sizeof(*(sc->map)) != 0) { LOG_MSG(LVL_ERROR, "%s: Map entries don't fit exactly in a sector (%s)", __func__, sc->geom->name); @@ -1653,7 +1653,7 @@ g_virstor_start(struct bio *b) * XXX: this will prevent the fs from * being umounted! */ struct g_virstor_bio_q *biq; - biq = malloc(sizeof *biq, M_GVIRSTOR, + biq = malloc(sizeof(*biq), M_GVIRSTOR, M_NOWAIT); if (biq == NULL) { bioq_dismantle(&bq); @@ -1703,7 +1703,7 @@ g_virstor_start(struct bio *b) * map array. * sc_offset will end up pointing to the drive * sector. */ - s_offset = chunk_index * sizeof *me; + s_offset = chunk_index * sizeof(*me); s_offset = rounddown(s_offset, sc->sectorsize); /* data_me points to map entry sector 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 465b4d0f365b..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 @@ -5617,6 +5619,8 @@ __CONCAT(PMTYPE, unmapdev)(void *p, vm_size_t size) static void __CONCAT(PMTYPE, page_set_memattr)(vm_page_t m, vm_memattr_t ma) { + if (m->md.pat_mode == ma) + return; m->md.pat_mode = ma; if ((m->flags & PG_FICTITIOUS) != 0) diff --git a/sys/kern/coredump_vnode.c b/sys/kern/coredump_vnode.c new file mode 100644 index 000000000000..8b857e9aa4a2 --- /dev/null +++ b/sys/kern/coredump_vnode.c @@ -0,0 +1,562 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause + * + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * 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 University 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 REGENTS 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 REGENTS 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. + * - kern_sig.c + */ +/* + * Copyright (c) 1993, David Greenman + * 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. + * -kern_exec.c + */ + +#include <sys/systm.h> +#include <sys/acct.h> +#include <sys/compressor.h> +#include <sys/devctl.h> +#include <sys/fcntl.h> +#include <sys/jail.h> +#include <sys/limits.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/sbuf.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/sysent.h> +#include <sys/syslog.h> +#include <sys/ucoredump.h> +#include <sys/unistd.h> +#include <sys/vnode.h> + +#include <security/audit/audit.h> + +#define GZIP_SUFFIX ".gz" +#define ZSTD_SUFFIX ".zst" + +#define MAX_NUM_CORE_FILES 100000 +#ifndef NUM_CORE_FILES +#define NUM_CORE_FILES 5 +#endif + +static coredumper_handle_fn coredump_vnode; +static struct coredumper vnode_coredumper = { + .cd_name = "vnode_coredumper", + .cd_handle = coredump_vnode, +}; + +SYSINIT(vnode_coredumper_register, SI_SUB_EXEC, SI_ORDER_ANY, + coredumper_register, &vnode_coredumper); + +_Static_assert(NUM_CORE_FILES >= 0 && NUM_CORE_FILES <= MAX_NUM_CORE_FILES, + "NUM_CORE_FILES is out of range (0 to " __STRING(MAX_NUM_CORE_FILES) ")"); +static int num_cores = NUM_CORE_FILES; + +static int capmode_coredump; +SYSCTL_INT(_kern, OID_AUTO, capmode_coredump, CTLFLAG_RWTUN, + &capmode_coredump, 0, "Allow processes in capability mode to dump core"); + +static int set_core_nodump_flag = 0; +SYSCTL_INT(_kern, OID_AUTO, nodump_coredump, CTLFLAG_RW, &set_core_nodump_flag, + 0, "Enable setting the NODUMP flag on coredump files"); + +static int coredump_devctl = 0; +SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl, + 0, "Generate a devctl notification when processes coredump"); + +/* + * corefilename[] is protected by the allproc_lock. + */ +static char corefilename[MAXPATHLEN] = { "%N.core" }; +TUNABLE_STR("kern.corefile", corefilename, sizeof(corefilename)); + +static int +sysctl_kern_corefile(SYSCTL_HANDLER_ARGS) +{ + int error; + + sx_xlock(&allproc_lock); + error = sysctl_handle_string(oidp, corefilename, sizeof(corefilename), + req); + sx_xunlock(&allproc_lock); + + return (error); +} +SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RW | + CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A", + "Process corefile name format string"); + +static int +sysctl_debug_num_cores_check (SYSCTL_HANDLER_ARGS) +{ + int error; + int new_val; + + new_val = num_cores; + error = sysctl_handle_int(oidp, &new_val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (new_val > MAX_NUM_CORE_FILES) + new_val = MAX_NUM_CORE_FILES; + if (new_val < 0) + new_val = 0; + num_cores = new_val; + return (0); +} +SYSCTL_PROC(_debug, OID_AUTO, ncores, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, sizeof(int), + sysctl_debug_num_cores_check, "I", + "Maximum number of generated process corefiles while using index format"); + +static void +vnode_close_locked(struct thread *td, struct vnode *vp) +{ + + VOP_UNLOCK(vp); + vn_close(vp, FWRITE, td->td_ucred, td); +} + +int +core_vn_write(const struct coredump_writer *cdw, const void *base, size_t len, + off_t offset, enum uio_seg seg, struct ucred *cred, size_t *resid, + struct thread *td) +{ + struct coredump_vnode_ctx *ctx = cdw->ctx; + + return (vn_rdwr_inchunks(UIO_WRITE, ctx->vp, __DECONST(void *, base), + len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED, + cred, ctx->fcred, resid, td)); +} + +int +core_vn_extend(const struct coredump_writer *cdw, off_t newsz, + struct ucred *cred) +{ + struct coredump_vnode_ctx *ctx = cdw->ctx; + struct mount *mp; + int error; + + error = vn_start_write(ctx->vp, &mp, V_WAIT); + if (error != 0) + return (error); + vn_lock(ctx->vp, LK_EXCLUSIVE | LK_RETRY); + error = vn_truncate_locked(ctx->vp, newsz, false, cred); + VOP_UNLOCK(ctx->vp); + vn_finished_write(mp); + return (error); +} + +/* + * If the core format has a %I in it, then we need to check + * for existing corefiles before defining a name. + * To do this we iterate over 0..ncores to find a + * non-existing core file name to use. If all core files are + * already used we choose the oldest one. + */ +static int +corefile_open_last(struct thread *td, char *name, int indexpos, + int indexlen, int ncores, struct vnode **vpp) +{ + struct vnode *oldvp, *nextvp, *vp; + struct vattr vattr; + struct nameidata nd; + int error, i, flags, oflags, cmode; + char ch; + struct timespec lasttime; + + nextvp = oldvp = NULL; + cmode = S_IRUSR | S_IWUSR; + oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE | + (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0); + + for (i = 0; i < ncores; i++) { + flags = O_CREAT | FWRITE | O_NOFOLLOW; + + ch = name[indexpos + indexlen]; + (void)snprintf(name + indexpos, indexlen + 1, "%.*u", indexlen, + i); + name[indexpos + indexlen] = ch; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name); + error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, + NULL); + if (error != 0) + break; + + vp = nd.ni_vp; + NDFREE_PNBUF(&nd); + if ((flags & O_CREAT) == O_CREAT) { + nextvp = vp; + break; + } + + error = VOP_GETATTR(vp, &vattr, td->td_ucred); + if (error != 0) { + vnode_close_locked(td, vp); + break; + } + + if (oldvp == NULL || + lasttime.tv_sec > vattr.va_mtime.tv_sec || + (lasttime.tv_sec == vattr.va_mtime.tv_sec && + lasttime.tv_nsec >= vattr.va_mtime.tv_nsec)) { + if (oldvp != NULL) + vn_close(oldvp, FWRITE, td->td_ucred, td); + oldvp = vp; + VOP_UNLOCK(oldvp); + lasttime = vattr.va_mtime; + } else { + vnode_close_locked(td, vp); + } + } + + if (oldvp != NULL) { + if (nextvp == NULL) { + if ((td->td_proc->p_flag & P_SUGID) != 0) { + error = EFAULT; + vn_close(oldvp, FWRITE, td->td_ucred, td); + } else { + nextvp = oldvp; + error = vn_lock(nextvp, LK_EXCLUSIVE); + if (error != 0) { + vn_close(nextvp, FWRITE, td->td_ucred, + td); + nextvp = NULL; + } + } + } else { + vn_close(oldvp, FWRITE, td->td_ucred, td); + } + } + if (error != 0) { + if (nextvp != NULL) + vnode_close_locked(td, oldvp); + } else { + *vpp = nextvp; + } + + return (error); +} + +/* + * corefile_open(comm, uid, pid, td, compress, vpp, namep) + * Expand the name described in corefilename, using name, uid, and pid + * and open/create core file. + * corefilename is a printf-like string, with three format specifiers: + * %N name of process ("name") + * %P process id (pid) + * %U user id (uid) + * For example, "%N.core" is the default; they can be disabled completely + * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". + * This is controlled by the sysctl variable kern.corefile (see above). + */ +static int +corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, + int compress, int signum, struct vnode **vpp, char **namep) +{ + struct sbuf sb; + struct nameidata nd; + const char *format; + char *hostname, *name; + int cmode, error, flags, i, indexpos, indexlen, oflags, ncores; + + hostname = NULL; + format = corefilename; + name = malloc(MAXPATHLEN, M_TEMP, M_WAITOK | M_ZERO); + indexlen = 0; + indexpos = -1; + ncores = num_cores; + (void)sbuf_new(&sb, name, MAXPATHLEN, SBUF_FIXEDLEN); + sx_slock(&allproc_lock); + for (i = 0; format[i] != '\0'; i++) { + switch (format[i]) { + case '%': /* Format character */ + i++; + switch (format[i]) { + case '%': + sbuf_putc(&sb, '%'); + break; + case 'H': /* hostname */ + if (hostname == NULL) { + hostname = malloc(MAXHOSTNAMELEN, + M_TEMP, M_WAITOK); + } + getcredhostname(td->td_ucred, hostname, + MAXHOSTNAMELEN); + sbuf_cat(&sb, hostname); + break; + case 'I': /* autoincrementing index */ + if (indexpos != -1) { + sbuf_printf(&sb, "%%I"); + break; + } + + indexpos = sbuf_len(&sb); + sbuf_printf(&sb, "%u", ncores - 1); + indexlen = sbuf_len(&sb) - indexpos; + break; + case 'N': /* process name */ + sbuf_printf(&sb, "%s", comm); + break; + case 'P': /* process id */ + sbuf_printf(&sb, "%u", pid); + break; + case 'S': /* signal number */ + sbuf_printf(&sb, "%i", signum); + break; + case 'U': /* user id */ + sbuf_printf(&sb, "%u", uid); + break; + default: + log(LOG_ERR, + "Unknown format character %c in " + "corename `%s'\n", format[i], format); + break; + } + break; + default: + sbuf_putc(&sb, format[i]); + break; + } + } + sx_sunlock(&allproc_lock); + free(hostname, M_TEMP); + if (compress == COMPRESS_GZIP) + sbuf_cat(&sb, GZIP_SUFFIX); + else if (compress == COMPRESS_ZSTD) + sbuf_cat(&sb, ZSTD_SUFFIX); + if (sbuf_error(&sb) != 0) { + log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too " + "long\n", (long)pid, comm, (u_long)uid); + sbuf_delete(&sb); + free(name, M_TEMP); + return (ENOMEM); + } + sbuf_finish(&sb); + sbuf_delete(&sb); + + if (indexpos != -1) { + error = corefile_open_last(td, name, indexpos, indexlen, ncores, + vpp); + if (error != 0) { + log(LOG_ERR, + "pid %d (%s), uid (%u): Path `%s' failed " + "on initial open test, error = %d\n", + pid, comm, uid, name, error); + } + } else { + cmode = S_IRUSR | S_IWUSR; + oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE | + (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0); + flags = O_CREAT | FWRITE | O_NOFOLLOW; + if ((td->td_proc->p_flag & P_SUGID) != 0) + flags |= O_EXCL; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name); + error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, + NULL); + if (error == 0) { + *vpp = nd.ni_vp; + NDFREE_PNBUF(&nd); + } + } + + if (error != 0) { +#ifdef AUDIT + audit_proc_coredump(td, name, error); +#endif + free(name, M_TEMP); + return (error); + } + *namep = name; + return (0); +} + +/* + * The vnode dumper is the traditional coredump handler. Our policy and limits + * are generally checked already, so it creates the coredump name and passes on + * a vnode and a size limit to the process-specific coredump routine if there is + * one. If there _is not_ one, it returns ENOSYS; otherwise it returns the + * error from the process-specific routine. + */ +static int +coredump_vnode(struct thread *td, off_t limit) +{ + struct proc *p = td->td_proc; + struct ucred *cred = td->td_ucred; + struct vnode *vp; + struct coredump_vnode_ctx wctx; + struct coredump_writer cdw = { }; + struct flock lf; + struct vattr vattr; + size_t fullpathsize; + int error, error1, jid, locked, ppid, sig; + char *name; /* name of corefile */ + void *rl_cookie; + char *fullpath, *freepath = NULL; + struct sbuf *sb; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + ppid = p->p_oppid; + sig = p->p_sig; + jid = p->p_ucred->cr_prison->pr_id; + PROC_UNLOCK(p); + + error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, + compress_user_cores, sig, &vp, &name); + if (error != 0) + return (error); + + /* + * Don't dump to non-regular files or files with links. + * Do not dump into system files. Effective user must own the corefile. + */ + if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 || + vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0 || + vattr.va_uid != cred->cr_uid) { + VOP_UNLOCK(vp); + error = EFAULT; + goto out; + } + + VOP_UNLOCK(vp); + + /* Postpone other writers, including core dumps of other processes. */ + rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX); + + lf.l_whence = SEEK_SET; + lf.l_start = 0; + lf.l_len = 0; + lf.l_type = F_WRLCK; + locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0); + + VATTR_NULL(&vattr); + vattr.va_size = 0; + if (set_core_nodump_flag) + vattr.va_flags = UF_NODUMP; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + VOP_SETATTR(vp, &vattr, cred); + VOP_UNLOCK(vp); + PROC_LOCK(p); + p->p_acflag |= ACORE; + PROC_UNLOCK(p); + + wctx.vp = vp; + wctx.fcred = NOCRED; + + cdw.ctx = &wctx; + cdw.write_fn = core_vn_write; + cdw.extend_fn = core_vn_extend; + + if (p->p_sysent->sv_coredump != NULL) { + error = p->p_sysent->sv_coredump(td, &cdw, limit, 0); + } else { + error = ENOSYS; + } + + if (locked) { + lf.l_type = F_UNLCK; + VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); + } + vn_rangelock_unlock(vp, rl_cookie); + + /* + * Notify the userland helper that a process triggered a core dump. + * This allows the helper to run an automated debugging session. + */ + if (error != 0 || coredump_devctl == 0) + goto out; + sb = sbuf_new_auto(); + if (vn_fullpath_global(p->p_textvp, &fullpath, &freepath) != 0) + goto out2; + sbuf_cat(sb, "comm=\""); + devctl_safe_quote_sb(sb, fullpath); + free(freepath, M_TEMP); + sbuf_cat(sb, "\" core=\""); + + /* + * We can't lookup core file vp directly. When we're replacing a core, and + * other random times, we flush the name cache, so it will fail. Instead, + * if the path of the core is relative, add the current dir in front if it. + */ + if (name[0] != '/') { + fullpathsize = MAXPATHLEN; + freepath = malloc(fullpathsize, M_TEMP, M_WAITOK); + if (vn_getcwd(freepath, &fullpath, &fullpathsize) != 0) { + free(freepath, M_TEMP); + goto out2; + } + devctl_safe_quote_sb(sb, fullpath); + free(freepath, M_TEMP); + sbuf_putc(sb, '/'); + } + devctl_safe_quote_sb(sb, name); + sbuf_putc(sb, '"'); + + sbuf_printf(sb, " jid=%d pid=%d ppid=%d signo=%d", + jid, p->p_pid, ppid, sig); + if (sbuf_finish(sb) == 0) + devctl_notify("kernel", "signal", "coredump", sbuf_data(sb)); +out2: + sbuf_delete(sb); +out: + error1 = vn_close(vp, FWRITE, cred, td); + if (error == 0) + error = error1; +#ifdef AUDIT + audit_proc_coredump(td, name, error); +#endif + free(name, M_TEMP); + return (error); +} diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index b7ffbe68b483..2690ad3b2679 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -64,6 +64,7 @@ #include <sys/syscall.h> #include <sys/sysctl.h> #include <sys/sysent.h> +#include <sys/ucoredump.h> #include <sys/vnode.h> #include <sys/syslog.h> #include <sys/eventhandler.h> @@ -1562,9 +1563,6 @@ struct note_info { TAILQ_HEAD(note_info_list, note_info); -extern int compress_user_cores; -extern int compress_user_cores_level; - static void cb_put_phdr(vm_map_entry_t, void *); static void cb_size_segment(vm_map_entry_t, void *); static void each_dumpable_segment(struct thread *, segment_callback, void *, @@ -1595,7 +1593,7 @@ core_compressed_write(void *base, size_t len, off_t offset, void *arg) } int -__elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) +__elfN(coredump)(struct thread *td, struct coredump_writer *cdw, off_t limit, int flags) { struct ucred *cred = td->td_ucred; int compm, error = 0; @@ -1625,9 +1623,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) /* Set up core dump parameters. */ params.offset = 0; params.active_cred = cred; - params.file_cred = NOCRED; params.td = td; - params.vp = vp; + params.cdw = cdw; params.comp = NULL; #ifdef RACCT @@ -1662,6 +1659,12 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO); } + if (cdw->init_fn != NULL) { + error = (*cdw->init_fn)(cdw, ¶ms); + if (error != 0) + goto done; + } + /* * Allocate memory for building the header, fill it up, * and write it out following the notes. diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 93bdd41d1515..a27ab33b34da 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -557,8 +557,10 @@ open_to_fde_flags(int open_flags, bool sticky_orb) { .f = O_CLOFORK, .t = UF_FOCLOSE }, { .f = O_RESOLVE_BENEATH, .t = UF_RESOLVE_BENEATH }, }; +#if defined(__clang__) && __clang_major__ >= 19 _Static_assert(open_to_fde_flags_s[nitems(open_to_fde_flags_s) - 1].f == O_RESOLVE_BENEATH, "O_RESOLVE_BENEATH must be last, for sticky_orb"); +#endif return (flags_trans(open_to_fde_flags_s, nitems(open_to_fde_flags_s) - (sticky_orb ? 0 : 1), open_flags)); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 03268365891e..0fc2d0e7f1bc 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -70,6 +70,7 @@ #include <sys/sysent.h> #include <sys/sysproto.h> #include <sys/timers.h> +#include <sys/ucoredump.h> #include <sys/umtxvar.h> #include <sys/vnode.h> #include <sys/wait.h> @@ -2002,10 +2003,14 @@ int core_write(struct coredump_params *cp, const void *base, size_t len, off_t offset, enum uio_seg seg, size_t *resid) { + return ((*cp->cdw->write_fn)(cp->cdw, base, len, offset, seg, + cp->active_cred, resid, cp->td)); +} - return (vn_rdwr_inchunks(UIO_WRITE, cp->vp, __DECONST(void *, base), - len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED, - cp->active_cred, cp->file_cred, resid, cp->td)); +static int +core_extend(struct coredump_params *cp, off_t newsz) +{ + return ((*cp->cdw->extend_fn)(cp->cdw, newsz, cp->active_cred)); } int @@ -2013,7 +2018,6 @@ core_output(char *base, size_t len, off_t offset, struct coredump_params *cp, void *tmpbuf) { vm_map_t map; - struct mount *mp; size_t resid, runlen; int error; bool success; @@ -2068,14 +2072,7 @@ core_output(char *base, size_t len, off_t offset, struct coredump_params *cp, } } if (!success) { - error = vn_start_write(cp->vp, &mp, V_WAIT); - if (error != 0) - break; - vn_lock(cp->vp, LK_EXCLUSIVE | LK_RETRY); - error = vn_truncate_locked(cp->vp, offset + runlen, - false, cp->td->td_ucred); - VOP_UNLOCK(cp->vp); - vn_finished_write(mp); + error = core_extend(cp, offset + runlen); if (error != 0) break; } diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index d9aeec68e620..0f0bc056cafd 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -287,7 +287,7 @@ sys_getgid(struct thread *td, struct getgid_args *uap) td->td_retval[0] = td->td_ucred->cr_rgid; #if defined(COMPAT_43) - td->td_retval[1] = td->td_ucred->cr_groups[0]; + td->td_retval[1] = td->td_ucred->cr_gid; #endif return (0); } @@ -307,7 +307,7 @@ int sys_getegid(struct thread *td, struct getegid_args *uap) { - td->td_retval[0] = td->td_ucred->cr_groups[0]; + td->td_retval[0] = td->td_ucred->cr_gid; return (0); } @@ -1080,7 +1080,7 @@ sys_setgid(struct thread *td, struct setgid_args *uap) gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ + gid != oldcred->cr_gid && /* allow setgid(getegid()) */ #endif (error = priv_check_cred(oldcred, PRIV_CRED_SETGID)) != 0) goto fail; @@ -1092,7 +1092,7 @@ sys_setgid(struct thread *td, struct setgid_args *uap) */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ - gid == oldcred->cr_groups[0] || + gid == oldcred->cr_gid || #endif /* We are using privs. */ priv_check_cred(oldcred, PRIV_CRED_SETGID) == 0) @@ -1121,7 +1121,7 @@ sys_setgid(struct thread *td, struct setgid_args *uap) * In all cases permitted cases, we are changing the egid. * Copy credentials so other references do not see our changes. */ - if (oldcred->cr_groups[0] != gid) { + if (oldcred->cr_gid != gid) { change_egid(newcred, gid); setsugid(p); } @@ -1167,7 +1167,7 @@ sys_setegid(struct thread *td, struct setegid_args *uap) (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID)) != 0) goto fail; - if (oldcred->cr_groups[0] != egid) { + if (oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -1393,12 +1393,12 @@ sys_setregid(struct thread *td, struct setregid_args *uap) if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && rgid != oldcred->cr_svgid) || - (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && + (egid != (gid_t)-1 && egid != oldcred->cr_gid && egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID)) != 0) goto fail; - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + if (egid != (gid_t)-1 && oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -1406,9 +1406,9 @@ sys_setregid(struct thread *td, struct setregid_args *uap) change_rgid(newcred, rgid); setsugid(p); } - if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && - newcred->cr_svgid != newcred->cr_groups[0]) { - change_svgid(newcred, newcred->cr_groups[0]); + if ((rgid != (gid_t)-1 || newcred->cr_gid != newcred->cr_rgid) && + newcred->cr_svgid != newcred->cr_gid) { + change_svgid(newcred, newcred->cr_gid); setsugid(p); } proc_set_cred(p, newcred); @@ -1547,17 +1547,17 @@ sys_setresgid(struct thread *td, struct setresgid_args *uap) if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && rgid != oldcred->cr_svgid && - rgid != oldcred->cr_groups[0]) || + rgid != oldcred->cr_gid) || (egid != (gid_t)-1 && egid != oldcred->cr_rgid && egid != oldcred->cr_svgid && - egid != oldcred->cr_groups[0]) || + egid != oldcred->cr_gid) || (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && sgid != oldcred->cr_svgid && - sgid != oldcred->cr_groups[0])) && + sgid != oldcred->cr_gid)) && (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID)) != 0) goto fail; - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + if (egid != (gid_t)-1 && oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -1626,8 +1626,8 @@ sys_getresgid(struct thread *td, struct getresgid_args *uap) error1 = copyout(&cred->cr_rgid, uap->rgid, sizeof(cred->cr_rgid)); if (uap->egid) - error2 = copyout(&cred->cr_groups[0], - uap->egid, sizeof(cred->cr_groups[0])); + error2 = copyout(&cred->cr_gid, + uap->egid, sizeof(cred->cr_gid)); if (uap->sgid) error3 = copyout(&cred->cr_svgid, uap->sgid, sizeof(cred->cr_svgid)); @@ -1737,7 +1737,7 @@ groupmember(gid_t gid, const struct ucred *cred) groups_check_positive_len(cred->cr_ngroups); - if (gid == cred->cr_groups[0]) + if (gid == cred->cr_gid) return (true); return (group_is_supplementary(gid, cred)); @@ -3015,7 +3015,7 @@ void change_egid(struct ucred *newcred, gid_t egid) { - newcred->cr_groups[0] = egid; + newcred->cr_gid = egid; } /*- diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index 35b258e68701..8438298afc0e 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -698,10 +698,13 @@ sendfile_wait_generic(struct socket *so, off_t need, int *space) */ error = 0; SOCK_SENDBUF_LOCK(so); - if (so->so_snd.sb_lowat < so->so_snd.sb_hiwat / 2) - so->so_snd.sb_lowat = so->so_snd.sb_hiwat / 2; - if (so->so_snd.sb_lowat < PAGE_SIZE && so->so_snd.sb_hiwat >= PAGE_SIZE) - so->so_snd.sb_lowat = PAGE_SIZE; + if (so->so_snd.sb_flags & SB_AUTOLOWAT) { + if (so->so_snd.sb_lowat < so->so_snd.sb_hiwat / 2) + so->so_snd.sb_lowat = so->so_snd.sb_hiwat / 2; + if (so->so_snd.sb_lowat < PAGE_SIZE && + so->so_snd.sb_hiwat >= PAGE_SIZE) + so->so_snd.sb_lowat = PAGE_SIZE; + } retry_space: if (so->so_snd.sb_state & SBS_CANTSENDMORE) { error = EPIPE; diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5d51aa675cb7..da0efac0598d 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -45,10 +45,10 @@ #include <sys/vnode.h> #include <sys/acct.h> #include <sys/capsicum.h> -#include <sys/compressor.h> #include <sys/condvar.h> #include <sys/devctl.h> #include <sys/event.h> +#include <sys/exec.h> #include <sys/fcntl.h> #include <sys/imgact.h> #include <sys/jail.h> @@ -80,6 +80,7 @@ #include <sys/syslog.h> #include <sys/sysproto.h> #include <sys/timers.h> +#include <sys/ucoredump.h> #include <sys/unistd.h> #include <sys/vmmeter.h> #include <sys/wait.h> @@ -101,7 +102,6 @@ SDT_PROBE_DEFINE2(proc, , , signal__clear, SDT_PROBE_DEFINE3(proc, , , signal__discard, "struct thread *", "struct proc *", "int"); -static int coredump(struct thread *); static int killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi); static int issignal(struct thread *td); @@ -126,11 +126,6 @@ const struct filterops sig_filtops = { .f_event = filt_signal, }; -static int kern_logsigexit = 1; -SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, - &kern_logsigexit, 0, - "Log processes quitting on abnormal signals to syslog(3)"); - static int kern_forcesigexit = 1; SYSCTL_INT(_kern, OID_AUTO, forcesigexit, CTLFLAG_RW, &kern_forcesigexit, 0, "Force trap signal to be handled"); @@ -193,26 +188,6 @@ SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL); (cr1)->cr_ruid == (cr2)->cr_uid || \ (cr1)->cr_uid == (cr2)->cr_uid) -static int sugid_coredump; -SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RWTUN, - &sugid_coredump, 0, "Allow setuid and setgid processes to dump core"); - -static int capmode_coredump; -SYSCTL_INT(_kern, OID_AUTO, capmode_coredump, CTLFLAG_RWTUN, - &capmode_coredump, 0, "Allow processes in capability mode to dump core"); - -static int do_coredump = 1; -SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW, - &do_coredump, 0, "Enable/Disable coredumps"); - -static int set_core_nodump_flag = 0; -SYSCTL_INT(_kern, OID_AUTO, nodump_coredump, CTLFLAG_RW, &set_core_nodump_flag, - 0, "Enable setting the NODUMP flag on coredump files"); - -static int coredump_devctl = 0; -SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl, - 0, "Generate a devctl notification when processes coredump"); - /* * Signal properties and actions. * The array below categorizes the signals and their default actions @@ -784,6 +759,13 @@ sigprop(int sig) return (0); } +bool +sig_do_core(int sig) +{ + + return ((sigprop(sig) & SIGPROP_CORE) != 0); +} + static bool sigact_flag_test(const struct sigaction *act, int flag) { @@ -2665,6 +2647,8 @@ static void ptrace_coredumpreq(struct thread *td, struct proc *p, struct thr_coredump_req *tcq) { + struct coredump_vnode_ctx wctx; + struct coredump_writer cdw; void *rl_cookie; if (p->p_sysent->sv_coredump == NULL) { @@ -2672,8 +2656,15 @@ ptrace_coredumpreq(struct thread *td, struct proc *p, return; } + wctx.vp = tcq->tc_vp; + wctx.fcred = NOCRED; + + cdw.ctx = &wctx; + cdw.write_fn = core_vn_write; + cdw.extend_fn = core_vn_extend; + rl_cookie = vn_rangelock_wlock(tcq->tc_vp, 0, OFF_MAX); - tcq->tc_error = p->p_sysent->sv_coredump(td, tcq->tc_vp, + tcq->tc_error = p->p_sysent->sv_coredump(td, &cdw, tcq->tc_limit, tcq->tc_flags); vn_rangelock_unlock(tcq->tc_vp, rl_cookie); } @@ -3635,82 +3626,6 @@ killproc(struct proc *p, const char *why) } /* - * Force the current process to exit with the specified signal, dumping core - * if appropriate. We bypass the normal tests for masked and caught signals, - * allowing unrecoverable failures to terminate the process without changing - * signal state. Mark the accounting record with the signal termination. - * If dumping core, save the signal number for the debugger. Calls exit and - * does not return. - */ -void -sigexit(struct thread *td, int sig) -{ - struct proc *p = td->td_proc; - const char *coreinfo; - int rv; - bool logexit; - - PROC_LOCK_ASSERT(p, MA_OWNED); - proc_set_p2_wexit(p); - - p->p_acflag |= AXSIG; - if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0) - logexit = kern_logsigexit != 0; - else - logexit = (p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0; - - /* - * We must be single-threading to generate a core dump. This - * ensures that the registers in the core file are up-to-date. - * Also, the ELF dump handler assumes that the thread list doesn't - * change out from under it. - * - * XXX If another thread attempts to single-thread before us - * (e.g. via fork()), we won't get a dump at all. - */ - if ((sigprop(sig) & SIGPROP_CORE) && - thread_single(p, SINGLE_NO_EXIT) == 0) { - p->p_sig = sig; - /* - * Log signals which would cause core dumps - * (Log as LOG_INFO to appease those who don't want - * these messages.) - * XXX : Todo, as well as euid, write out ruid too - * Note that coredump() drops proc lock. - */ - rv = coredump(td); - switch (rv) { - case 0: - sig |= WCOREFLAG; - coreinfo = " (core dumped)"; - break; - case EFAULT: - coreinfo = " (no core dump - bad address)"; - break; - case EINVAL: - coreinfo = " (no core dump - invalid argument)"; - break; - case EFBIG: - coreinfo = " (no core dump - too large)"; - break; - default: - coreinfo = " (no core dump - other error)"; - break; - } - if (logexit) - log(LOG_INFO, - "pid %d (%s), jid %d, uid %d: exited on " - "signal %d%s\n", p->p_pid, p->p_comm, - p->p_ucred->cr_prison->pr_id, - td->td_ucred->cr_uid, - sig &~ WCOREFLAG, coreinfo); - } else - PROC_UNLOCK(p); - exit1(td, 0, sig); - /* NOTREACHED */ -} - -/* * Send queued SIGCHLD to parent when child process's state * is changed. */ @@ -3803,477 +3718,6 @@ childproc_exited(struct proc *p) sigparent(p, reason, status); } -#define MAX_NUM_CORE_FILES 100000 -#ifndef NUM_CORE_FILES -#define NUM_CORE_FILES 5 -#endif -CTASSERT(NUM_CORE_FILES >= 0 && NUM_CORE_FILES <= MAX_NUM_CORE_FILES); -static int num_cores = NUM_CORE_FILES; - -static int -sysctl_debug_num_cores_check (SYSCTL_HANDLER_ARGS) -{ - int error; - int new_val; - - new_val = num_cores; - error = sysctl_handle_int(oidp, &new_val, 0, req); - if (error != 0 || req->newptr == NULL) - return (error); - if (new_val > MAX_NUM_CORE_FILES) - new_val = MAX_NUM_CORE_FILES; - if (new_val < 0) - new_val = 0; - num_cores = new_val; - return (0); -} -SYSCTL_PROC(_debug, OID_AUTO, ncores, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, sizeof(int), - sysctl_debug_num_cores_check, "I", - "Maximum number of generated process corefiles while using index format"); - -#define GZIP_SUFFIX ".gz" -#define ZSTD_SUFFIX ".zst" - -int compress_user_cores = 0; - -static int -sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS) -{ - int error, val; - - val = compress_user_cores; - error = sysctl_handle_int(oidp, &val, 0, req); - if (error != 0 || req->newptr == NULL) - return (error); - if (val != 0 && !compressor_avail(val)) - return (EINVAL); - compress_user_cores = val; - return (error); -} -SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), - sysctl_compress_user_cores, "I", - "Enable compression of user corefiles (" - __XSTRING(COMPRESS_GZIP) " = gzip, " - __XSTRING(COMPRESS_ZSTD) " = zstd)"); - -int compress_user_cores_level = 6; -SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN, - &compress_user_cores_level, 0, - "Corefile compression level"); - -/* - * Protect the access to corefilename[] by allproc_lock. - */ -#define corefilename_lock allproc_lock - -static char corefilename[MAXPATHLEN] = {"%N.core"}; -TUNABLE_STR("kern.corefile", corefilename, sizeof(corefilename)); - -static int -sysctl_kern_corefile(SYSCTL_HANDLER_ARGS) -{ - int error; - - sx_xlock(&corefilename_lock); - error = sysctl_handle_string(oidp, corefilename, sizeof(corefilename), - req); - sx_xunlock(&corefilename_lock); - - return (error); -} -SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RW | - CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A", - "Process corefile name format string"); - -static void -vnode_close_locked(struct thread *td, struct vnode *vp) -{ - - VOP_UNLOCK(vp); - vn_close(vp, FWRITE, td->td_ucred, td); -} - -/* - * If the core format has a %I in it, then we need to check - * for existing corefiles before defining a name. - * To do this we iterate over 0..ncores to find a - * non-existing core file name to use. If all core files are - * already used we choose the oldest one. - */ -static int -corefile_open_last(struct thread *td, char *name, int indexpos, - int indexlen, int ncores, struct vnode **vpp) -{ - struct vnode *oldvp, *nextvp, *vp; - struct vattr vattr; - struct nameidata nd; - int error, i, flags, oflags, cmode; - char ch; - struct timespec lasttime; - - nextvp = oldvp = NULL; - cmode = S_IRUSR | S_IWUSR; - oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE | - (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0); - - for (i = 0; i < ncores; i++) { - flags = O_CREAT | FWRITE | O_NOFOLLOW; - - ch = name[indexpos + indexlen]; - (void)snprintf(name + indexpos, indexlen + 1, "%.*u", indexlen, - i); - name[indexpos + indexlen] = ch; - - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name); - error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, - NULL); - if (error != 0) - break; - - vp = nd.ni_vp; - NDFREE_PNBUF(&nd); - if ((flags & O_CREAT) == O_CREAT) { - nextvp = vp; - break; - } - - error = VOP_GETATTR(vp, &vattr, td->td_ucred); - if (error != 0) { - vnode_close_locked(td, vp); - break; - } - - if (oldvp == NULL || - lasttime.tv_sec > vattr.va_mtime.tv_sec || - (lasttime.tv_sec == vattr.va_mtime.tv_sec && - lasttime.tv_nsec >= vattr.va_mtime.tv_nsec)) { - if (oldvp != NULL) - vn_close(oldvp, FWRITE, td->td_ucred, td); - oldvp = vp; - VOP_UNLOCK(oldvp); - lasttime = vattr.va_mtime; - } else { - vnode_close_locked(td, vp); - } - } - - if (oldvp != NULL) { - if (nextvp == NULL) { - if ((td->td_proc->p_flag & P_SUGID) != 0) { - error = EFAULT; - vn_close(oldvp, FWRITE, td->td_ucred, td); - } else { - nextvp = oldvp; - error = vn_lock(nextvp, LK_EXCLUSIVE); - if (error != 0) { - vn_close(nextvp, FWRITE, td->td_ucred, - td); - nextvp = NULL; - } - } - } else { - vn_close(oldvp, FWRITE, td->td_ucred, td); - } - } - if (error != 0) { - if (nextvp != NULL) - vnode_close_locked(td, oldvp); - } else { - *vpp = nextvp; - } - - return (error); -} - -/* - * corefile_open(comm, uid, pid, td, compress, vpp, namep) - * Expand the name described in corefilename, using name, uid, and pid - * and open/create core file. - * corefilename is a printf-like string, with three format specifiers: - * %N name of process ("name") - * %P process id (pid) - * %U user id (uid) - * For example, "%N.core" is the default; they can be disabled completely - * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". - * This is controlled by the sysctl variable kern.corefile (see above). - */ -static int -corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, - int compress, int signum, struct vnode **vpp, char **namep) -{ - struct sbuf sb; - struct nameidata nd; - const char *format; - char *hostname, *name; - int cmode, error, flags, i, indexpos, indexlen, oflags, ncores; - - hostname = NULL; - format = corefilename; - name = malloc(MAXPATHLEN, M_TEMP, M_WAITOK | M_ZERO); - indexlen = 0; - indexpos = -1; - ncores = num_cores; - (void)sbuf_new(&sb, name, MAXPATHLEN, SBUF_FIXEDLEN); - sx_slock(&corefilename_lock); - for (i = 0; format[i] != '\0'; i++) { - switch (format[i]) { - case '%': /* Format character */ - i++; - switch (format[i]) { - case '%': - sbuf_putc(&sb, '%'); - break; - case 'H': /* hostname */ - if (hostname == NULL) { - hostname = malloc(MAXHOSTNAMELEN, - M_TEMP, M_WAITOK); - } - getcredhostname(td->td_ucred, hostname, - MAXHOSTNAMELEN); - sbuf_cat(&sb, hostname); - break; - case 'I': /* autoincrementing index */ - if (indexpos != -1) { - sbuf_printf(&sb, "%%I"); - break; - } - - indexpos = sbuf_len(&sb); - sbuf_printf(&sb, "%u", ncores - 1); - indexlen = sbuf_len(&sb) - indexpos; - break; - case 'N': /* process name */ - sbuf_printf(&sb, "%s", comm); - break; - case 'P': /* process id */ - sbuf_printf(&sb, "%u", pid); - break; - case 'S': /* signal number */ - sbuf_printf(&sb, "%i", signum); - break; - case 'U': /* user id */ - sbuf_printf(&sb, "%u", uid); - break; - default: - log(LOG_ERR, - "Unknown format character %c in " - "corename `%s'\n", format[i], format); - break; - } - break; - default: - sbuf_putc(&sb, format[i]); - break; - } - } - sx_sunlock(&corefilename_lock); - free(hostname, M_TEMP); - if (compress == COMPRESS_GZIP) - sbuf_cat(&sb, GZIP_SUFFIX); - else if (compress == COMPRESS_ZSTD) - sbuf_cat(&sb, ZSTD_SUFFIX); - if (sbuf_error(&sb) != 0) { - log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too " - "long\n", (long)pid, comm, (u_long)uid); - sbuf_delete(&sb); - free(name, M_TEMP); - return (ENOMEM); - } - sbuf_finish(&sb); - sbuf_delete(&sb); - - if (indexpos != -1) { - error = corefile_open_last(td, name, indexpos, indexlen, ncores, - vpp); - if (error != 0) { - log(LOG_ERR, - "pid %d (%s), uid (%u): Path `%s' failed " - "on initial open test, error = %d\n", - pid, comm, uid, name, error); - } - } else { - cmode = S_IRUSR | S_IWUSR; - oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE | - (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0); - flags = O_CREAT | FWRITE | O_NOFOLLOW; - if ((td->td_proc->p_flag & P_SUGID) != 0) - flags |= O_EXCL; - - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name); - error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, - NULL); - if (error == 0) { - *vpp = nd.ni_vp; - NDFREE_PNBUF(&nd); - } - } - - if (error != 0) { -#ifdef AUDIT - audit_proc_coredump(td, name, error); -#endif - free(name, M_TEMP); - return (error); - } - *namep = name; - return (0); -} - -/* - * Dump a process' core. The main routine does some - * policy checking, and creates the name of the coredump; - * then it passes on a vnode and a size limit to the process-specific - * coredump routine if there is one; if there _is not_ one, it returns - * ENOSYS; otherwise it returns the error from the process-specific routine. - */ - -static int -coredump(struct thread *td) -{ - struct proc *p = td->td_proc; - struct ucred *cred = td->td_ucred; - struct vnode *vp; - struct flock lf; - struct vattr vattr; - size_t fullpathsize; - int error, error1, jid, locked, ppid, sig; - char *name; /* name of corefile */ - void *rl_cookie; - off_t limit; - char *fullpath, *freepath = NULL; - struct sbuf *sb; - - PROC_LOCK_ASSERT(p, MA_OWNED); - MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td); - - if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) || - (p->p_flag2 & P2_NOTRACE) != 0) { - PROC_UNLOCK(p); - return (EFAULT); - } - - /* - * Note that the bulk of limit checking is done after - * the corefile is created. The exception is if the limit - * for corefiles is 0, in which case we don't bother - * creating the corefile at all. This layout means that - * a corefile is truncated instead of not being created, - * if it is larger than the limit. - */ - limit = (off_t)lim_cur(td, RLIMIT_CORE); - if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) { - PROC_UNLOCK(p); - return (EFBIG); - } - - ppid = p->p_oppid; - sig = p->p_sig; - jid = p->p_ucred->cr_prison->pr_id; - PROC_UNLOCK(p); - - error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, - compress_user_cores, p->p_sig, &vp, &name); - if (error != 0) - return (error); - - /* - * Don't dump to non-regular files or files with links. - * Do not dump into system files. Effective user must own the corefile. - */ - if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 || - vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0 || - vattr.va_uid != cred->cr_uid) { - VOP_UNLOCK(vp); - error = EFAULT; - goto out; - } - - VOP_UNLOCK(vp); - - /* Postpone other writers, including core dumps of other processes. */ - rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX); - - lf.l_whence = SEEK_SET; - lf.l_start = 0; - lf.l_len = 0; - lf.l_type = F_WRLCK; - locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0); - - VATTR_NULL(&vattr); - vattr.va_size = 0; - if (set_core_nodump_flag) - vattr.va_flags = UF_NODUMP; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - VOP_SETATTR(vp, &vattr, cred); - VOP_UNLOCK(vp); - PROC_LOCK(p); - p->p_acflag |= ACORE; - PROC_UNLOCK(p); - - if (p->p_sysent->sv_coredump != NULL) { - error = p->p_sysent->sv_coredump(td, vp, limit, 0); - } else { - error = ENOSYS; - } - - if (locked) { - lf.l_type = F_UNLCK; - VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); - } - vn_rangelock_unlock(vp, rl_cookie); - - /* - * Notify the userland helper that a process triggered a core dump. - * This allows the helper to run an automated debugging session. - */ - if (error != 0 || coredump_devctl == 0) - goto out; - sb = sbuf_new_auto(); - if (vn_fullpath_global(p->p_textvp, &fullpath, &freepath) != 0) - goto out2; - sbuf_cat(sb, "comm=\""); - devctl_safe_quote_sb(sb, fullpath); - free(freepath, M_TEMP); - sbuf_cat(sb, "\" core=\""); - - /* - * We can't lookup core file vp directly. When we're replacing a core, and - * other random times, we flush the name cache, so it will fail. Instead, - * if the path of the core is relative, add the current dir in front if it. - */ - if (name[0] != '/') { - fullpathsize = MAXPATHLEN; - freepath = malloc(fullpathsize, M_TEMP, M_WAITOK); - if (vn_getcwd(freepath, &fullpath, &fullpathsize) != 0) { - free(freepath, M_TEMP); - goto out2; - } - devctl_safe_quote_sb(sb, fullpath); - free(freepath, M_TEMP); - sbuf_putc(sb, '/'); - } - devctl_safe_quote_sb(sb, name); - sbuf_putc(sb, '"'); - - sbuf_printf(sb, " jid=%d pid=%d ppid=%d signo=%d", - jid, p->p_pid, ppid, sig); - if (sbuf_finish(sb) == 0) - devctl_notify("kernel", "signal", "coredump", sbuf_data(sb)); -out2: - sbuf_delete(sb); -out: - error1 = vn_close(vp, FWRITE, cred, td); - if (error == 0) - error = error1; -#ifdef AUDIT - audit_proc_coredump(td, name, error); -#endif - free(name, M_TEMP); - return (error); -} - /* * Nonexistent system call-- signal process (may want to handle it). Flag * error in case process won't see signal immediately (blocked or ignored). diff --git a/sys/kern/kern_ucoredump.c b/sys/kern/kern_ucoredump.c new file mode 100644 index 000000000000..d425596b5f24 --- /dev/null +++ b/sys/kern/kern_ucoredump.c @@ -0,0 +1,299 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * 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 University 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 REGENTS 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 REGENTS 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/param.h> +#include <sys/acct.h> +#include <sys/compressor.h> +#include <sys/jail.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/racct.h> +#include <sys/resourcevar.h> +#include <sys/rmlock.h> +#include <sys/sysctl.h> +#include <sys/syslog.h> +#include <sys/ucoredump.h> +#include <sys/wait.h> + +static int coredump(struct thread *td, const char **); + +int compress_user_cores = 0; + +static SLIST_HEAD(, coredumper) coredumpers = + SLIST_HEAD_INITIALIZER(coredumpers); +static struct rmlock coredump_rmlock; +RM_SYSINIT(coredump_lock, &coredump_rmlock, "coredump_lock"); + +static int kern_logsigexit = 1; +SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, + &kern_logsigexit, 0, + "Log processes quitting on abnormal signals to syslog(3)"); + +static int sugid_coredump; +SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RWTUN, + &sugid_coredump, 0, "Allow setuid and setgid processes to dump core"); + +static int do_coredump = 1; +SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW, + &do_coredump, 0, "Enable/Disable coredumps"); + +static int +sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = compress_user_cores; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (val != 0 && !compressor_avail(val)) + return (EINVAL); + compress_user_cores = val; + return (error); +} +SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores, + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), + sysctl_compress_user_cores, "I", + "Enable compression of user corefiles (" + __XSTRING(COMPRESS_GZIP) " = gzip, " + __XSTRING(COMPRESS_ZSTD) " = zstd)"); + +int compress_user_cores_level = 6; +SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN, + &compress_user_cores_level, 0, + "Corefile compression level"); + +void +coredumper_register(struct coredumper *cd) +{ + + blockcount_init(&cd->cd_refcount); + rm_wlock(&coredump_rmlock); + SLIST_INSERT_HEAD(&coredumpers, cd, cd_entry); + rm_wunlock(&coredump_rmlock); +} + +void +coredumper_unregister(struct coredumper *cd) +{ + + rm_wlock(&coredump_rmlock); + SLIST_REMOVE(&coredumpers, cd, coredumper, cd_entry); + rm_wunlock(&coredump_rmlock); + + /* + * Wait for any in-process coredumps to finish before returning. + */ + blockcount_wait(&cd->cd_refcount, NULL, "dumpwait", 0); +} + +/* + * Force the current process to exit with the specified signal, dumping core + * if appropriate. We bypass the normal tests for masked and caught signals, + * allowing unrecoverable failures to terminate the process without changing + * signal state. Mark the accounting record with the signal termination. + * If dumping core, save the signal number for the debugger. Calls exit and + * does not return. + */ +void +sigexit(struct thread *td, int sig) +{ + struct proc *p = td->td_proc; + int rv; + bool logexit; + + PROC_LOCK_ASSERT(p, MA_OWNED); + proc_set_p2_wexit(p); + + p->p_acflag |= AXSIG; + if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0) + logexit = kern_logsigexit != 0; + else + logexit = (p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0; + + /* + * We must be single-threading to generate a core dump. This + * ensures that the registers in the core file are up-to-date. + * Also, the ELF dump handler assumes that the thread list doesn't + * change out from under it. + * + * XXX If another thread attempts to single-thread before us + * (e.g. via fork()), we won't get a dump at all. + */ + if (sig_do_core(sig) && thread_single(p, SINGLE_NO_EXIT) == 0) { + const char *err = NULL; + + p->p_sig = sig; + /* + * Log signals which would cause core dumps + * (Log as LOG_INFO to appease those who don't want + * these messages.) + * XXX : Todo, as well as euid, write out ruid too + * Note that coredump() drops proc lock. + */ + rv = coredump(td, &err); + if (rv == 0) { + MPASS(err == NULL); + sig |= WCOREFLAG; + } else if (err == NULL) { + switch (rv) { + case EFAULT: + err = "bad address"; + break; + case EINVAL: + err = "invalild argument"; + break; + case EFBIG: + err = "too large"; + break; + default: + err = "other error"; + break; + } + } + if (logexit) + log(LOG_INFO, + "pid %d (%s), jid %d, uid %d: exited on " + "signal %d (%s%s)\n", p->p_pid, p->p_comm, + p->p_ucred->cr_prison->pr_id, + td->td_ucred->cr_uid, sig &~ WCOREFLAG, + err != NULL ? "no core dump - " : "core dumped", + err != NULL ? err : ""); + } else + PROC_UNLOCK(p); + exit1(td, 0, sig); + /* NOTREACHED */ +} + + +/* + * Dump a process' core. The main routine does some + * policy checking, and creates the name of the coredump; + * then it passes on a vnode and a size limit to the process-specific + * coredump routine if there is one; if there _is not_ one, it returns + * ENOSYS; otherwise it returns the error from the process-specific routine. + */ +static int +coredump(struct thread *td, const char **errmsg) +{ + struct coredumper *iter, *chosen; + struct proc *p = td->td_proc; + struct rm_priotracker tracker; + off_t limit; + int error, priority; + + PROC_LOCK_ASSERT(p, MA_OWNED); + MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td); + + if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) || + (p->p_flag2 & P2_NOTRACE) != 0) { + PROC_UNLOCK(p); + + if (!do_coredump) + *errmsg = "denied by kern.coredump"; + else if ((p->p_flag2 & P2_NOTRACE) != 0) + *errmsg = "process has trace disabled"; + else + *errmsg = "sugid process denied by kern.sugid_coredump"; + return (EFAULT); + } + + /* + * Note that the bulk of limit checking is done after + * the corefile is created. The exception is if the limit + * for corefiles is 0, in which case we don't bother + * creating the corefile at all. This layout means that + * a corefile is truncated instead of not being created, + * if it is larger than the limit. + */ + limit = (off_t)lim_cur(td, RLIMIT_CORE); + if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) { + PROC_UNLOCK(p); + *errmsg = "coredumpsize limit is 0"; + return (EFBIG); + } + + rm_rlock(&coredump_rmlock, &tracker); + priority = -1; + chosen = NULL; + SLIST_FOREACH(iter, &coredumpers, cd_entry) { + if (iter->cd_probe == NULL) { + /* + * If we haven't found anything of a higher priority + * yet, we'll call this a GENERIC. Ideally, we want + * coredumper modules to include a probe function. + */ + if (priority < 0) { + priority = COREDUMPER_GENERIC; + chosen = iter; + } + + continue; + } + + error = (*iter->cd_probe)(td); + if (error < 0) + continue; + + /* + * Higher priority than previous options. + */ + if (error > priority) { + priority = error; + chosen = iter; + } + } + + /* + * Acquire our refcount before we drop the lock so that + * coredumper_unregister() can safely assume that the refcount will only + * go down once it's dropped the rmlock. + */ + blockcount_acquire(&chosen->cd_refcount, 1); + rm_runlock(&coredump_rmlock, &tracker); + + /* Currently, we always have the vnode dumper built in. */ + MPASS(chosen != NULL); + error = ((*chosen->cd_handle)(td, limit)); + PROC_LOCK_ASSERT(p, MA_NOTOWNED); + + blockcount_release(&chosen->cd_refcount, 1); + + return (error); +} 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_compressor.c b/sys/kern/subr_compressor.c index 280264881241..5d59622e0455 100644 --- a/sys/kern/subr_compressor.c +++ b/sys/kern/subr_compressor.c @@ -538,6 +538,12 @@ compressor_init(compressor_cb_t cb, int format, size_t maxiosize, int level, return (s); } +int +compressor_format(const struct compressor *stream) +{ + return (stream->methods->format); +} + void compressor_reset(struct compressor *stream) { 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/uipc_ktls.c b/sys/kern/uipc_ktls.c index ce09042abdac..66ce1b5a081d 100644 --- a/sys/kern/uipc_ktls.c +++ b/sys/kern/uipc_ktls.c @@ -1207,7 +1207,7 @@ sb_mark_notready(struct sockbuf *sb) for (; m != NULL; m = m->m_next) { KASSERT(m->m_nextpkt == NULL, ("%s: m_nextpkt != NULL", __func__)); - KASSERT((m->m_flags & M_NOTAVAIL) == 0, ("%s: mbuf not avail", + KASSERT((m->m_flags & M_NOTREADY) == 0, ("%s: mbuf not ready", __func__)); KASSERT(sb->sb_acc >= m->m_len, ("%s: sb_acc < m->m_len", __func__)); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 6f83b875a6b6..85fe48ddd466 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -1134,10 +1134,10 @@ shm_doremove(struct shm_mapping *map) int kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, - int shmflags, struct filecaps *fcaps, const char *name __unused) + int shmflags, struct filecaps *fcaps, const char *name __unused, + struct shmfd *shmfd) { struct pwddesc *pdp; - struct shmfd *shmfd; struct file *fp; char *path; void *rl_cookie; @@ -1214,23 +1214,41 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, if (error != 0) goto outnofp; - /* A SHM_ANON path pointer creates an anonymous object. */ + /* + * A SHM_ANON path pointer creates an anonymous object. We allow other + * parts of the kernel to pre-populate a shmfd and then materialize an + * fd for it here as a means to pass data back up to userland. This + * doesn't really make sense for named shm objects, but it makes plenty + * of sense for anonymous objects. + */ if (userpath == SHM_ANON) { - /* A read-only anonymous object is pointless. */ - if ((flags & O_ACCMODE) == O_RDONLY) { - error = EINVAL; - goto out; - } - shmfd = shm_alloc(td->td_ucred, cmode, largepage); - if (shmfd == NULL) { - error = ENOMEM; - goto out; + if (shmfd != NULL) { + shm_hold(shmfd); + } else { + /* + * A read-only anonymous object is pointless, unless it + * was pre-populated by the kernel with the expectation + * that a shmfd would later be created for userland to + * access it through. + */ + if ((flags & O_ACCMODE) == O_RDONLY) { + error = EINVAL; + goto out; + } + shmfd = shm_alloc(td->td_ucred, cmode, largepage); + if (shmfd == NULL) { + error = ENOMEM; + goto out; + } + + shmfd->shm_seals = initial_seals; + shmfd->shm_flags = shmflags; } - shmfd->shm_seals = initial_seals; - shmfd->shm_flags = shmflags; } else { fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&shm_dict_lock); + + MPASS(shmfd == NULL); shmfd = shm_lookup(path, fnv); if (shmfd == NULL) { /* Object does not yet exist, create it if requested. */ @@ -2173,7 +2191,7 @@ kern_shm_open(struct thread *td, const char *path, int flags, mode_t mode, struct filecaps *caps) { - return (kern_shm_open2(td, path, flags, mode, 0, caps, NULL)); + return (kern_shm_open2(td, path, flags, mode, 0, caps, NULL, NULL)); } /* @@ -2191,7 +2209,7 @@ sys_shm_open2(struct thread *td, struct shm_open2_args *uap) { return (kern_shm_open2(td, uap->path, uap->flags, uap->mode, - uap->shmflags, NULL, uap->name)); + uap->shmflags, NULL, uap->name, NULL)); } int diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index ec00878cd9a5..745702bd4a4f 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -195,14 +195,14 @@ int sbready(struct sockbuf *sb, struct mbuf *m0, int count) { struct mbuf *m; - u_int blocker; + bool blocker; SOCKBUF_LOCK_ASSERT(sb); KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb)); KASSERT(count > 0, ("%s: invalid count %d", __func__, count)); m = m0; - blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0; + blocker = (sb->sb_fnrdy == m); while (count > 0) { KASSERT(m->m_flags & M_NOTREADY, @@ -217,8 +217,7 @@ sbready(struct sockbuf *sb, struct mbuf *m0, int count) m->m_epg_nrdy = 0; } else count--; - - m->m_flags &= ~(M_NOTREADY | blocker); + m->m_flags &= ~M_NOTREADY; if (blocker) sb->sb_acc += m->m_len; m = m->m_next; @@ -240,12 +239,8 @@ sbready(struct sockbuf *sb, struct mbuf *m0, int count) } /* This one was blocking all the queue. */ - for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) { - KASSERT(m->m_flags & M_BLOCKED, - ("%s: m %p !M_BLOCKED", __func__, m)); - m->m_flags &= ~M_BLOCKED; + for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) sb->sb_acc += m->m_len; - } sb->sb_fnrdy = m; sbready_compress(sb, m0, m); @@ -269,8 +264,7 @@ sballoc(struct sockbuf *sb, struct mbuf *m) sb->sb_fnrdy = m; else sb->sb_acc += m->m_len; - } else - m->m_flags |= M_BLOCKED; + } if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) sb->sb_ctl += m->m_len; @@ -287,29 +281,29 @@ sballoc(struct sockbuf *sb, struct mbuf *m) void sbfree(struct sockbuf *sb, struct mbuf *m) { + struct mbuf *n; #if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ SOCKBUF_LOCK_ASSERT(sb); #endif - sb->sb_ccc -= m->m_len; - if (!(m->m_flags & M_NOTAVAIL)) - sb->sb_acc -= m->m_len; - if (m == sb->sb_fnrdy) { - struct mbuf *n; - KASSERT(m->m_flags & M_NOTREADY, ("%s: m %p !M_NOTREADY", __func__, m)); n = m->m_next; while (n != NULL && !(n->m_flags & M_NOTREADY)) { - n->m_flags &= ~M_BLOCKED; sb->sb_acc += n->m_len; n = n->m_next; } sb->sb_fnrdy = n; + } else { + /* Assert that mbuf is not behind sb_fnrdy. */ + for (n = sb->sb_fnrdy; n != NULL; n = n->m_next) + KASSERT(n != m, ("%s: sb %p freeing %p behind sb_fnrdy", + __func__, sb, m)); + sb->sb_acc -= m->m_len; } if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) @@ -779,6 +773,7 @@ sbsetopt(struct socket *so, struct sockopt *sopt) * high-water. */ *lowat = (cc > *hiwat) ? *hiwat : cc; + *flags &= ~SB_AUTOLOWAT; break; } @@ -1128,13 +1123,7 @@ sbcheck(struct sockbuf *sb, const char *file, int line) } fnrdy = m; } - if (fnrdy) { - if (!(m->m_flags & M_NOTAVAIL)) { - printf("sb %p: fnrdy %p, m %p is avail\n", - sb, sb->sb_fnrdy, m); - goto fail; - } - } else + if (fnrdy == NULL) acc += m->m_len; ccc += m->m_len; mbcnt += MSIZE; @@ -1601,8 +1590,8 @@ sbcut_internal(struct sockbuf *sb, int len) next = m->m_nextpkt; } if (m->m_len > len) { - KASSERT(!(m->m_flags & M_NOTAVAIL), - ("%s: m %p M_NOTAVAIL", __func__, m)); + KASSERT(!(m->m_flags & M_NOTREADY), + ("%s: m %p M_NOTREADY", __func__, m)); m->m_len -= len; m->m_data += len; sb->sb_ccc -= len; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 6c9eb7139cd1..fe2d8d056062 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1211,7 +1211,8 @@ solisten_clone(struct socket *head) so->so_rcv.sb_timeo = head->sol_sbrcv_timeo; so->so_snd.sb_timeo = head->sol_sbsnd_timeo; so->so_rcv.sb_flags = head->sol_sbrcv_flags & SB_AUTOSIZE; - so->so_snd.sb_flags = head->sol_sbsnd_flags & SB_AUTOSIZE; + so->so_snd.sb_flags = head->sol_sbsnd_flags & + (SB_AUTOSIZE | SB_AUTOLOWAT); if ((so->so_proto->pr_flags & PR_SOCKBUF) == 0) { so->so_snd.sb_mtx = &so->so_snd_mtx; so->so_rcv.sb_mtx = &so->so_rcv_mtx; @@ -2988,8 +2989,8 @@ dontblock: */ moff = 0; offset = 0; - while (m != NULL && !(m->m_flags & M_NOTAVAIL) && uio->uio_resid > 0 - && error == 0) { + while (m != NULL && !(m->m_flags & M_NOTREADY) && uio->uio_resid > 0 && + error == 0) { /* * If the type of mbuf has changed since the last mbuf * examined ('type'), end the receive operation. @@ -3341,7 +3342,7 @@ deliver: for (m = sb->sb_mb; m != NULL && m->m_len <= len; m = m->m_next) { - KASSERT(!(m->m_flags & M_NOTAVAIL), + KASSERT(!(m->m_flags & M_NOTREADY), ("%s: m %p not available", __func__, m)); len -= m->m_len; uio->uio_resid -= m->m_len; @@ -4514,6 +4515,9 @@ sokqfilter_generic(struct socket *so, struct knote *kn) SOCK_BUF_LOCK(so, which); knlist_add(knl, kn, 1); sb->sb_flags |= SB_KNOTE; + if ((kn->kn_sfflags & NOTE_LOWAT) && + (sb->sb_flags & SB_AUTOLOWAT)) + sb->sb_flags &= ~SB_AUTOLOWAT; SOCK_BUF_UNLOCK(so, which); } SOCK_UNLOCK(so); 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/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index c71e0d9ee569..25d40a9806cb 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2253,10 +2253,10 @@ kern_accessat(struct thread *td, int fd, const char *path, cred = td->td_ucred; if ((flag & AT_EACCESS) == 0 && ((cred->cr_uid != cred->cr_ruid || - cred->cr_rgid != cred->cr_groups[0]))) { + cred->cr_rgid != cred->cr_gid))) { usecred = crdup(cred); usecred->cr_uid = cred->cr_ruid; - usecred->cr_groups[0] = cred->cr_rgid; + usecred->cr_gid = cred->cr_rgid; td->td_ucred = usecred; } else usecred = cred; 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..99c9ec9dcd01 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -34,6 +34,7 @@ SUBDIR= \ alq \ ${_amd_ecc_inject} \ ${_amdgpio} \ + ${_amdsmu} \ ${_amdsbwd} \ ${_amdsmn} \ ${_amdtemp} \ @@ -326,6 +327,7 @@ SUBDIR= \ proto \ pseudofs \ ${_pst} \ + ${_pt} \ pty \ puc \ pwm \ @@ -771,6 +773,7 @@ _acpi= acpi _aesni= aesni .endif _amd_ecc_inject=amd_ecc_inject +_amdsmu= amdsmu _amdsbwd= amdsbwd _amdsmn= amdsmn _amdtemp= amdtemp @@ -842,6 +845,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/amdsmu/Makefile b/sys/modules/amdsmu/Makefile new file mode 100644 index 000000000000..752f57173d61 --- /dev/null +++ b/sys/modules/amdsmu/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 The FreeBSD Foundation +# +# This software was developed by Aymeric Wibo <obiwac@freebsd.org> +# under sponsorship from the FreeBSD Foundation. + +.PATH: ${SRCTOP}/sys/dev/amdsmu + +KMOD= amdsmu +SRCS= amdsmu.c +SRCS+= bus_if.h device_if.h pci_if.h + +.include <bsd.kmod.mk> 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_lagg.c b/sys/net/if_lagg.c index 9867a718e148..5b52bfa80e3b 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -718,6 +718,7 @@ lagg_capabilities(struct lagg_softc *sc) sc->sc_ifp->if_capenable = ena; sc->sc_ifp->if_capenable2 = ena2; sc->sc_ifp->if_hwassist = hwa; + (void)if_hw_tsomax_update(sc->sc_ifp, &hw_tsomax); getmicrotime(&sc->sc_ifp->if_lastchange); if (sc->sc_ifflags & IFF_DEBUG) diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c index 7bdbc565f4ca..853a0556a080 100644 --- a/sys/net/if_ovpn.c +++ b/sys/net/if_ovpn.c @@ -79,7 +79,6 @@ #include "if_ovpn.h" struct ovpn_kkey_dir { - int refcount; uint8_t key[32]; uint8_t keylen; uint8_t nonce[8]; @@ -205,7 +204,8 @@ static int ovpn_encap(struct ovpn_softc *, uint32_t, struct mbuf *); static int ovpn_get_af(struct mbuf *); static void ovpn_free_kkey_dir(struct ovpn_kkey_dir *); static bool ovpn_check_replay(struct ovpn_kkey_dir *, uint32_t); -static int ovpn_peer_compare(struct ovpn_kpeer *, struct ovpn_kpeer *); +static int ovpn_peer_compare(const struct ovpn_kpeer *, + const struct ovpn_kpeer *); static RB_PROTOTYPE(ovpn_kpeers, ovpn_kpeer, tree, ovpn_peer_compare); static RB_GENERATE(ovpn_kpeers, ovpn_kpeer, tree, ovpn_peer_compare); @@ -278,7 +278,7 @@ SYSCTL_INT(_net_link_openvpn, OID_AUTO, netisr_queue, "Use netisr_queue() rather than netisr_dispatch()."); static int -ovpn_peer_compare(struct ovpn_kpeer *a, struct ovpn_kpeer *b) +ovpn_peer_compare(const struct ovpn_kpeer *a, const struct ovpn_kpeer *b) { return (a->peerid - b->peerid); } @@ -304,15 +304,15 @@ ovpn_find_only_peer(struct ovpn_softc *sc) } static uint16_t -ovpn_get_port(struct sockaddr_storage *s) +ovpn_get_port(const struct sockaddr_storage *s) { switch (s->ss_family) { case AF_INET: { - struct sockaddr_in *in = (struct sockaddr_in *)s; + const struct sockaddr_in *in = (const struct sockaddr_in *)s; return (in->sin_port); } case AF_INET6: { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)s; + const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)s; return (in6->sin6_port); } default: @@ -320,6 +320,25 @@ ovpn_get_port(struct sockaddr_storage *s) } } +static void +ovpn_set_port(struct sockaddr_storage *s, unsigned short port) +{ + switch (s->ss_family) { + case AF_INET: { + struct sockaddr_in *in = (struct sockaddr_in *)s; + in->sin_port = port; + break; + } + case AF_INET6: { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)s; + in6->sin6_port = port; + break; + } + default: + panic("Unsupported address family %d", s->ss_family); + } +} + static int ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) { @@ -333,14 +352,16 @@ ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) return (EINVAL); af = nvlist_get_number(nvl, "af"); - switch (af) { #ifdef INET case AF_INET: { struct sockaddr_in *in = (struct sockaddr_in *)sa; size_t len; const void *addr = nvlist_get_binary(nvl, "address", &len); + + memset(in, 0, sizeof(*in)); in->sin_family = af; + in->sin_len = sizeof(*in); if (len != sizeof(in->sin_addr)) return (EINVAL); @@ -354,7 +375,10 @@ ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; size_t len; const void *addr = nvlist_get_binary(nvl, "address", &len); + + memset(in6, 0, sizeof(*in6)); in6->sin6_family = af; + in6->sin6_len = sizeof(*in6); if (len != sizeof(in6->sin6_addr)) return (EINVAL); @@ -370,33 +394,6 @@ ovpn_nvlist_to_sockaddr(const nvlist_t *nvl, struct sockaddr_storage *sa) return (0); } -static bool -ovpn_has_peers(struct ovpn_softc *sc) -{ - OVPN_ASSERT(sc); - - return (sc->peercount > 0); -} - -static void -ovpn_rele_so(struct ovpn_softc *sc) -{ - bool has_peers; - - OVPN_WASSERT(sc); - - if (sc->so == NULL) - return; - - has_peers = ovpn_has_peers(sc); - - if (! has_peers) { - MPASS(sc->peercount == 0); - } else { - MPASS(sc->peercount > 0); - } -} - static void ovpn_notify_del_peer(struct ovpn_softc *sc, struct ovpn_kpeer *peer) { @@ -485,8 +482,6 @@ ovpn_peer_release_ref(struct ovpn_kpeer *peer, bool locked) ovpn_free_kkey_dir(peer->keys[i].decrypt); } - ovpn_rele_so(sc); - callout_stop(&peer->ping_send); callout_stop(&peer->ping_rcv); uma_zfree_pcpu(pcpu_zone_4, peer->last_active); @@ -502,7 +497,7 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl) #ifdef INET6 struct epoch_tracker et; #endif - struct sockaddr_storage remote; + struct sockaddr_storage local, remote; struct ovpn_kpeer *peer = NULL; struct file *fp = NULL; struct ovpn_softc *sc = ifp->if_softc; @@ -571,20 +566,37 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl) callout_init_rm(&peer->ping_send, &sc->lock, CALLOUT_SHAREDLOCK); callout_init_rm(&peer->ping_rcv, &sc->lock, 0); - peer->local.ss_len = sizeof(peer->local); - ret = sosockaddr(so, (struct sockaddr *)&peer->local); - if (ret) + memset(&local, 0, sizeof(local)); + local.ss_len = sizeof(local); + ret = sosockaddr(so, (struct sockaddr *)&local); + if (ret != 0) goto error; + if (nvlist_exists_nvlist(nvl, "local")) { + struct sockaddr_storage local1; - if (ovpn_get_port(&peer->local) == 0) { + ret = ovpn_nvlist_to_sockaddr(nvlist_get_nvlist(nvl, "local"), + &local1); + if (ret != 0) + goto error; + + /* + * openvpn doesn't provide a port here when in multihome mode, + * just steal the one the socket is bound to. + */ + if (ovpn_get_port(&local1) == 0) + ovpn_set_port(&local1, ovpn_get_port(&local)); + memcpy(&local, &local1, sizeof(local1)); + } + if (ovpn_get_port(&local) == 0) { ret = EINVAL; goto error; } - if (peer->local.ss_family != remote.ss_family) { + if (local.ss_family != remote.ss_family) { ret = EINVAL; goto error; } + memcpy(&peer->local, &local, sizeof(local)); memcpy(&peer->remote, &remote, sizeof(remote)); #ifdef INET6 @@ -633,6 +645,7 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl) * a new one. */ ret = udp_set_kernel_tunneling(sc->so, NULL, NULL, NULL); + MPASS(ret == 0); sorele(sc->so); sc->so = NULL; } @@ -2519,6 +2532,7 @@ ovpn_clone_destroy_cb(struct epoch_context *ctx) COUNTER_ARRAY_FREE(sc->counters, OVPN_COUNTER_SIZE); + rm_destroy(&sc->lock); if_free(sc->ifp); free(sc, M_OVPN); } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 8ee4d00daaff..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 @@ -2500,7 +2510,7 @@ int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, u_int64_t, int, int, int); int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t, - pf_addr_filter_func_t); + pf_addr_filter_func_t, bool); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_kruleset *, char *); 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/in_fib_dxr.c b/sys/netinet/in_fib_dxr.c index b889131b544b..538cd43a88a3 100644 --- a/sys/netinet/in_fib_dxr.c +++ b/sys/netinet/in_fib_dxr.c @@ -345,7 +345,7 @@ initheap(struct dxr_aux *da, uint32_t dst_u32, uint32_t chunk) struct heap_entry *fhp = &da->heap[0]; struct rtentry *rt; struct route_nhop_data rnd; - + da->heap_index = 0; da->dst.sin_addr.s_addr = htonl(dst_u32); rt = fib4_lookup_rt(da->fibnum, da->dst.sin_addr, 0, NHR_UNLOCKED, @@ -1143,7 +1143,7 @@ dxr_destroy(void *data) free(da, M_DXRAUX); } -static void +static void epoch_dxr_destroy(epoch_context_t ctx) { struct dxr *dxr = __containerof(ctx, struct dxr, epoch_ctx); @@ -1202,7 +1202,7 @@ dxr_dump_end(void *data, struct fib_dp *dp) static enum flm_op_result dxr_dump_rib_item(struct rtentry *rt, void *data) { - + return (FLM_SUCCESS); } 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/sctp_timer.c b/sys/netinet/sctp_timer.c index 66af716eea52..7d8cb965ab09 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -35,7 +35,6 @@ #define _IP_VHL #include <netinet/sctp_os.h> #include <netinet/sctp_pcb.h> - #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_timer.h> 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..f8c064b6a104 100644 --- a/sys/netinet/tcp_log_buf.h +++ b/sys/netinet/tcp_log_buf.h @@ -377,12 +377,12 @@ extern int32_t tcp_trace_point_count; /* * Returns true if any sort of BB logging is enabled, - * commonly used throughout the codebase. + * commonly used throughout the codebase. */ static inline int tcp_bblogging_on(struct tcpcb *tp) { - if (tp->_t_logstate <= TCP_LOG_STATE_OFF) + if (tp->_t_logstate <= TCP_LOG_STATE_OFF) return (0); if (tp->_t_logstate == TCP_LOG_VIA_BBPOINTS) return (0); @@ -427,7 +427,7 @@ tcp_set_bblog_state(struct tcpcb *tp, uint8_t ls, uint8_t bbpoint) } } -static inline uint32_t +static inline uint32_t tcp_get_bblog_state(struct tcpcb *tp) { return (tp->_t_logstate); @@ -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_lro.c b/sys/netinet/tcp_lro.c index 10afed17bf3b..7512679bd4e9 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -1301,9 +1301,9 @@ tcp_lro_rx_common(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum, bool use_h return (TCP_LRO_CANNOT); #endif if (((m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) != - ((CSUM_DATA_VALID | CSUM_PSEUDO_HDR))) || + ((CSUM_DATA_VALID | CSUM_PSEUDO_HDR))) || (m->m_pkthdr.csum_data != 0xffff)) { - /* + /* * The checksum either did not have hardware offload * or it was a bad checksum. We can't LRO such * a packet. @@ -1334,7 +1334,7 @@ tcp_lro_rx_common(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum, bool use_h #endif /* If no hardware or arrival stamp on the packet add timestamp */ if ((m->m_flags & (M_TSTMP_LRO | M_TSTMP)) == 0) { - m->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); + m->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); m->m_flags |= M_TSTMP_LRO; } @@ -1429,9 +1429,9 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) int error; if (((m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) != - ((CSUM_DATA_VALID | CSUM_PSEUDO_HDR))) || + ((CSUM_DATA_VALID | CSUM_PSEUDO_HDR))) || (m->m_pkthdr.csum_data != 0xffff)) { - /* + /* * The checksum either did not have hardware offload * or it was a bad checksum. We can't LRO such * a packet. @@ -1481,7 +1481,7 @@ tcp_lro_queue_mbuf(struct lro_ctrl *lc, struct mbuf *mb) ((mb->m_flags & M_TSTMP) == 0)) { /* Add in an LRO time since no hardware */ binuptime(&lc->lro_last_queue_time); - mb->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); + mb->m_pkthdr.rcv_tstmp = bintime2ns(&lc->lro_last_queue_time); mb->m_flags |= M_TSTMP_LRO; } diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 90d789f0e224..4405098a8620 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -744,7 +744,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) while (cur != NULL) { if (!(sblkp >= sack_blocks)) { if (((loss_sblks >= tcprexmtthresh) || - (loss_thresh > (tcprexmtthresh-1)*tp->t_maxseg))) + (loss_thresh > (tcprexmtthresh-1)*tp->t_maxseg))) break; loss_thresh += loss_hiack - cur->end; loss_hiack = cur->start; diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c index e2cfec5c9275..b232d3f08fe6 100644 --- a/sys/netinet/tcp_stacks/bbr.c +++ b/sys/netinet/tcp_stacks/bbr.c @@ -5126,8 +5126,8 @@ bbr_timeout_rxt(struct tcpcb *tp, struct tcp_bbr *bbr, uint32_t cts) tp->t_maxseg = tp->t_pmtud_saved_maxseg; if (tp->t_maxseg < V_tcp_mssdflt) { /* - * The MSS is so small we should not - * process incoming SACK's since we are + * The MSS is so small we should not + * process incoming SACK's since we are * subject to attack in such a case. */ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT; @@ -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); } } @@ -10141,7 +10141,7 @@ bbr_init(struct tcpcb *tp, void **ptr) * flags. */ bbr_stop_all_timers(tp, bbr); - /* + /* * Validate the timers are not in usec, if they are convert. * BBR should in theory move to USEC and get rid of a * lot of the TICKS_2 calls.. but for now we stay @@ -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) @@ -11544,7 +11544,7 @@ bbr_do_segment_nounlock(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, bbr_check_bbr_for_state(bbr, cts, __LINE__, (bbr->r_ctl.rc_lost - lost)); if (nxt_pkt == 0) { if ((bbr->r_wanted_output != 0) || - (tp->t_flags & TF_ACKNOW)) { + (tp->t_flags & TF_ACKNOW)) { bbr->rc_output_starts_timer = 0; did_out = 1; @@ -13172,11 +13172,7 @@ send: mb, moff, &len, if_hw_tsomaxsegcount, if_hw_tsomaxsegsize, msb, - ((rsm == NULL) ? hw_tls : 0) -#ifdef NETFLIX_COPY_ARGS - , NULL, NULL -#endif - ); + ((rsm == NULL) ? hw_tls : 0)); if (len <= maxseg) { /* * Must have ran out of mbufs for the copy @@ -13806,8 +13802,8 @@ nomore: tp->t_maxseg = old_maxseg - 40; if (tp->t_maxseg < V_tcp_mssdflt) { /* - * The MSS is so small we should not - * process incoming SACK's since we are + * The MSS is so small we should not + * process incoming SACK's since we are * subject to attack in such a case. */ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT; diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c index 8e05498863b9..940a4024bb73 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 @@ -7887,8 +7888,8 @@ drop_it: tp->t_maxseg = tp->t_pmtud_saved_maxseg; if (tp->t_maxseg < V_tcp_mssdflt) { /* - * The MSS is so small we should not - * process incoming SACK's since we are + * The MSS is so small we should not + * process incoming SACK's since we are * subject to attack in such a case. */ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT; @@ -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); } } @@ -14637,9 +14638,6 @@ rack_init(struct tcpcb *tp, void **ptr) if (rack->r_ctl.pcm_s == NULL) { rack->r_ctl.pcm_i.cnt_alloc = 0; } -#ifdef NETFLIX_STATS - rack->r_ctl.side_chan_dis_mask = tcp_sidechannel_disable_mask; -#endif rack->r_ctl.rack_per_upper_bound_ss = (uint8_t)rack_per_upper_bound_ss; rack->r_ctl.rack_per_upper_bound_ca = (uint8_t)rack_per_upper_bound_ca; if (rack_enable_shared_cwnd) @@ -15563,7 +15561,7 @@ rack_log_pcm(struct tcp_rack *rack, uint8_t mod, uint32_t flex1, uint32_t flex2, if (tcp_bblogging_on(rack->rc_tp)) { union tcp_log_stackspecific log; struct timeval tv; - + (void)tcp_get_usecs(&tv); memset(&log, 0, sizeof(log)); log.u_bbr.timeStamp = tcp_tv_to_usectick(&tv); @@ -16655,7 +16653,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 +16917,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 +17544,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 +17984,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 @@ -19914,7 +19912,7 @@ rack_output(struct tcpcb *tp) goto nomore; } else { /* Return == 0, if there is more we can send tot_len wise fall through and send */ - if (tot_len_this_send >= pace_max_seg) + if (tot_len_this_send >= pace_max_seg) return (ret); #ifdef TCP_ACCOUNTING /* We need to re-pin since fast_output un-pined */ @@ -20043,7 +20041,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 +21029,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) @@ -21555,11 +21553,7 @@ send: m->m_next = tcp_m_copym( mb, moff, &len, if_hw_tsomaxsegcount, if_hw_tsomaxsegsize, msb, - ((rsm == NULL) ? hw_tls : 0) -#ifdef NETFLIX_COPY_ARGS - , &s_mb, &s_moff -#endif - ); + ((rsm == NULL) ? hw_tls : 0)); if (len <= (tp->t_maxseg - optlen)) { /* * Must have ran out of mbufs for the copy 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/netinet/tcp_stacks/rack_pcm.c b/sys/netinet/tcp_stacks/rack_pcm.c index b0e300847c4a..101e6826536c 100644 --- a/sys/netinet/tcp_stacks/rack_pcm.c +++ b/sys/netinet/tcp_stacks/rack_pcm.c @@ -172,7 +172,7 @@ rack_update_pcm_ack(struct tcp_rack *rack, int was_cumack, uint32_t start, uint3 goto skip_ack_accounting; } /* - * Record ACK data. + * Record ACK data. */ ack_arrival = tcp_tv_to_lusectick(&rack->r_ctl.act_rcv_time); if (SEQ_GT(end, rack->r_ctl.pcm_i.eseq)) { @@ -305,7 +305,7 @@ skip_ack_accounting: 0, &log, false, NULL, NULL, 0, &tv); } } - /* + /* * Here we need a lot to be added including: * 1) Some form of measurement, where if we think the measurement * is valid we iterate over the PCM data and come up with a path diff --git a/sys/netinet/tcp_stacks/sack_filter.c b/sys/netinet/tcp_stacks/sack_filter.c index fc9ee8454a1e..2b70548f3cc6 100644 --- a/sys/netinet/tcp_stacks/sack_filter.c +++ b/sys/netinet/tcp_stacks/sack_filter.c @@ -400,7 +400,7 @@ sack_filter_run(struct sack_filter *sf, struct sackblk *in, int numblks, tcp_seq break; } /* Copy it out to the outbound */ - memcpy(&in[at], &blkboard[i], sizeof(struct sackblk)); + memcpy(&in[at], &blkboard[i], sizeof(struct sackblk)); at++; room--; /* now lets add it to our sack-board */ @@ -588,7 +588,7 @@ sack_filter_blks(struct tcpcb *tp, struct sack_filter *sf, struct sackblk *in, i sf->sf_ack = th_ack; for(i=0, sf->sf_cur=0; i<numblks; i++) { - if ((in[i].end != tp->snd_max) && + if ((in[i].end != tp->snd_max) && ((in[i].end - in[i].start) < segmax)) { /* * We do not accept blocks less than a MSS minus all @@ -707,7 +707,7 @@ main(int argc, char **argv) out = stdout; memset(&tp, 0, sizeof(tp)); tp.t_maxseg = 1460; - + while ((i = getopt(argc, argv, "dIi:o:?hS:")) != -1) { switch (i) { case 'S': @@ -883,7 +883,7 @@ main(int argc, char **argv) } else { printf("can't open sack_setup.bin -- sorry no load\n"); } - + } else if (strncmp(buffer, "help", 4) == 0) { help: fprintf(out, "You can input:\n"); diff --git a/sys/netinet/tcp_stacks/sack_filter.h b/sys/netinet/tcp_stacks/sack_filter.h index b12fcf84567c..a1c0684a4359 100644 --- a/sys/netinet/tcp_stacks/sack_filter.h +++ b/sys/netinet/tcp_stacks/sack_filter.h @@ -42,7 +42,7 @@ * previously processed sack information. * * The second thing that the sack filter does is help protect against malicious - * attackers that are trying to attack any linked lists (or other data structures) + * attackers that are trying to attack any linked lists (or other data structures) * that are used in sack processing. Consider an attacker sending in sacks for * every other byte of data outstanding. This could in theory drastically split * up any scoreboard you are maintaining and make you search through a very large diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index db415f6bdf03..26e7e53d540c 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -4537,7 +4537,7 @@ tcp_change_time_units(struct tcpcb *tp, int granularity) panic("Unknown granularity:%d tp:%p", granularity, tp); } -#endif +#endif } void diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 32ce3001929c..3b9fe7a317b0 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -757,8 +757,8 @@ tcp_timer_rexmt(struct tcpcb *tp) tp->t_maxseg = tp->t_pmtud_saved_maxseg; if (tp->t_maxseg < V_tcp_mssdflt) { /* - * The MSS is so small we should not - * process incoming SACK's since we are + * The MSS is so small we should not + * process incoming SACK's since we are * subject to attack in such a case. */ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 687b0d538666..98c934955121 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -164,7 +164,7 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td) goto out; so->so_rcv.sb_flags |= SB_AUTOSIZE; - so->so_snd.sb_flags |= SB_AUTOSIZE; + so->so_snd.sb_flags |= (SB_AUTOLOWAT | SB_AUTOSIZE); error = in_pcballoc(so, &V_tcbinfo); if (error) goto out; @@ -1768,9 +1768,9 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt) /* * Release the ref count the lookup * acquired. - */ + */ refcount_release(&blk->tfb_refcnt); - /* + /* * Now there is a chance that the * init() function mucked with some * things before it failed, such as @@ -1800,7 +1800,7 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt) * new one already. */ refcount_release(&tp->t_fb->tfb_refcnt); - /* + /* * Set in the new stack. */ tp->t_fb = blk; @@ -1934,7 +1934,7 @@ tcp_set_cc_mod(struct inpcb *inp, struct sockopt *sopt) CC_LIST_RUNLOCK(); return(ESRCH); } - /* + /* * With a reference the algorithm cannot be removed * so we hold a reference through the change process. */ diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 059b2aff689d..b90f65e83cb1 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -182,7 +182,7 @@ struct tcp_sendfile_track { * snd_una). When the response comes back indicating * that there was data (return value 1), then the caller * can build a sendmap entry based on the range and the - * times. The next query would then be done at the + * times. The next query would then be done at the * newly created sendmap_end. Repeated until sendmap_end == snd_max. * * Flags in sendmap_flags are defined below as well. @@ -197,7 +197,7 @@ struct tcp_sendfile_track { * The rack_times are a misc collection of information that * the old stack might possibly fill in. Of course its possible * that an old stack may not have a piece of information. If so - * then setting that value to zero is advised. Setting any + * then setting that value to zero is advised. Setting any * timestamp passed should only place a zero in it when it * is unfilled. This may mean that a time is off by a micro-second * but this is ok in the grand scheme of things. @@ -205,13 +205,13 @@ struct tcp_sendfile_track { * When switching stacks it is desireable to get as much information * from the old stack to the new stack as possible. Though not always * will the stack be compatible in the types of information. The - * init() function needs to take care when it begins changing + * init() function needs to take care when it begins changing * things such as inp_flags2 and the timer units to position these * changes at a point where it is unlikely they will fail after * making such changes. A stack optionally can have an "undo" - * function + * function * - * To transfer information to the old stack from the new in + * To transfer information to the old stack from the new in * respect to LRO and the inp_flags2, the new stack should set * the inp_flags2 to what it supports. The old stack in its * fini() function should call the tcp_handle_orphaned_packets() @@ -544,13 +544,13 @@ typedef enum { * do is: * a) Make sure that the inp_flags2 is setup correctly * for LRO. There are two flags that the previous - * stack may have set INP_MBUF_ACKCMP and + * stack may have set INP_MBUF_ACKCMP and * INP_SUPPORTS_MBUFQ. If the new stack does not * support these it *should* clear the flags. * b) Make sure that the timers are in the proper * granularity that the stack wants. The stack * should check the t_tmr_granularity field. Currently - * there are two values that it may hold + * there are two values that it may hold * TCP_TMR_GRANULARITY_TICKS and TCP_TMR_GRANULARITY_USEC. * Use the functions tcp_timer_convert(tp, granularity); * to move the timers to the correct format for your stack. @@ -558,14 +558,14 @@ typedef enum { * The new stack may also optionally query the tfb_chg_query * function if the old stack has one. The new stack may ask * for one of three entries and can also state to the old - * stack its support for the INP_MBUF_ACKCMP and + * stack its support for the INP_MBUF_ACKCMP and * INP_SUPPORTS_MBUFQ. This is important since if there are * queued ack's without that statement the old stack will * be forced to discard the queued acks. The requests that * can be made for information by the new stacks are: * * Note also that the tfb_tcp_fb_init() when called can - * determine if a query is needed by looking at the + * determine if a query is needed by looking at the * value passed in the ptr. The ptr is designed to be * set in with any allocated memory, but the address * of the condtion (ptr == &tp->t_fb_ptr) will be @@ -573,17 +573,17 @@ typedef enum { * setup of a tcb (which means no query would be needed). * If, however, the value is not t_fb_ptr, then the caller * is in the middle of a stack switch and is the new stack. - * A query would be appropriate (if the new stack support + * A query would be appropriate (if the new stack support * the query mechanism). * * TCP_QUERY_SENDMAP - Query of outstanding data. * TCP_QUERY_TIMERS_UP - Query about running timers. - * TCP_SUPPORTED_LRO - Declaration in req_param of - * the inp_flags2 supported by + * TCP_SUPPORTED_LRO - Declaration in req_param of + * the inp_flags2 supported by * the new stack. * TCP_QUERY_RACK_TIMES - Enquire about various timestamps * and states the old stack may be in. - * + * * tfb_tcp_fb_fini is changed to add a flag to tell * the old stack if the tcb is being destroyed or * not. A one in the flag means the TCB is being diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index dafbaf6dc672..42cfb919e263 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -243,7 +243,6 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, struct sockaddr_in6 udp_in6; #endif struct udpcb *up; - bool filtered; INP_LOCK_ASSERT(inp); @@ -252,13 +251,19 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, */ up = intoudpcb(inp); if (up->u_tun_func != NULL) { + bool filtered; + in_pcbref(inp); INP_RUNLOCK(inp); filtered = (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0], up->u_tun_ctx); INP_RLOCK(inp); - if (filtered) - return (in_pcbrele_rlocked(inp)); + if (in_pcbrele_rlocked(inp)) + return (1); + if (filtered) { + INP_RUNLOCK(inp); + return (1); + } } off += sizeof(struct udphdr); 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/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 304effa26e01..b3ed16fda713 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -142,7 +142,6 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off, struct socket *so; struct mbuf *opts = NULL, *tmp_opts; struct udpcb *up; - bool filtered; INP_LOCK_ASSERT(inp); @@ -151,13 +150,19 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off, */ up = intoudpcb(inp); if (up->u_tun_func != NULL) { + bool filtered; + in_pcbref(inp); INP_RUNLOCK(inp); filtered = (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&fromsa[0], up->u_tun_ctx); INP_RLOCK(inp); - if (filtered) - return (in_pcbrele_rlocked(inp)); + if (in_pcbrele_rlocked(inp)) + return (1); + if (filtered) { + INP_RUNLOCK(inp); + return (1); + } } off += sizeof(struct udphdr); 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 41658a29014e..41e9ca27912d 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); } @@ -4975,7 +4976,7 @@ pf_socket_lookup(struct pf_pdesc *pd) } INP_RLOCK_ASSERT(inp); pd->lookup.uid = inp->inp_cred->cr_uid; - pd->lookup.gid = inp->inp_cred->cr_groups[0]; + pd->lookup.gid = inp->inp_cred->cr_gid; INP_RUNLOCK(inp); return (1); @@ -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 *); @@ -5759,7 +5760,7 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, if (inp != NULL) { INP_LOCK_ASSERT(inp); pd->lookup.uid = inp->inp_cred->cr_uid; - pd->lookup.gid = inp->inp_cred->cr_groups[0]; + pd->lookup.gid = inp->inp_cred->cr_gid; pd->lookup.done = 1; } @@ -5906,11 +5907,12 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, * it is applied only from the last pass rule. */ pd->act.rt = r->rt; - /* Don't use REASON_SET, pf_map_addr increases the reason counters */ - ctx.reason = pf_map_addr_sn(pd->af, r, pd->src, &pd->act.rt_addr, - &pd->act.rt_kif, NULL, &(r->route), PF_SN_ROUTE); - if (ctx.reason != 0) + if ((transerror = pf_map_addr_sn(pd->af, r, pd->src, + &pd->act.rt_addr, &pd->act.rt_kif, NULL, &(r->route), + PF_SN_ROUTE)) != PFRES_MATCH) { + REASON_SET(&ctx.reason, transerror); goto cleanup; + } } if (pd->virtual_proto != PF_VPROTO_FRAGMENT && @@ -6054,9 +6056,16 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx, /* src node for translation rule */ if (ctx->nr != NULL) { KASSERT(ctx->nat_pool != NULL, ("%s: nat_pool is NULL", __func__)); + /* + * The NAT addresses are chosen during ruleset parsing. + * The new afto code stores post-nat addresses in nsaddr. + * The old nat code (also used for new nat-to rules) creates + * state keys and stores addresses in them. + */ if ((ctx->nat_pool->opts & PF_POOL_STICKYADDR) && (sn_reason = pf_insert_src_node(sns, snhs, ctx->nr, - &ctx->sk->addr[pd->sidx], pd->af, &ctx->nk->addr[1], NULL, + ctx->sk ? &(ctx->sk->addr[pd->sidx]) : pd->src, pd->af, + ctx->nk ? &(ctx->nk->addr[1]) : &(pd->nsaddr), NULL, PF_SN_NAT)) != 0 ) { REASON_SET(&ctx->reason, sn_reason); goto csfailed; @@ -6160,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) { @@ -6211,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(); @@ -7957,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); } /* @@ -7988,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; @@ -8041,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; @@ -8236,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; @@ -8368,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; @@ -8399,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); } @@ -8523,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; @@ -8643,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; @@ -9060,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) { @@ -9071,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; } @@ -9362,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) { @@ -9373,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; } @@ -9669,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) @@ -9784,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; @@ -9795,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); @@ -9812,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; @@ -9822,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); } @@ -9838,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) { @@ -9847,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; @@ -9895,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; @@ -9906,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 */ @@ -9942,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); } @@ -9954,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); } @@ -9966,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); } @@ -9975,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 */ @@ -9987,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; @@ -10006,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) : @@ -10024,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); } @@ -10050,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)); @@ -10067,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); @@ -10081,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; @@ -10117,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; @@ -10145,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) { @@ -10463,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); } } @@ -10504,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); @@ -10524,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) @@ -10683,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); @@ -10716,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 && @@ -10730,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) { @@ -10762,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"); } } @@ -10819,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; @@ -10836,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 d4728f61dce8..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 *); @@ -617,7 +615,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, rpool->tblidx = (int)arc4random_uniform(cnt); memset(&rpool->counter, 0, sizeof(rpool->counter)); if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter, - af, pf_islinklocal)) { + af, pf_islinklocal, false)) { reason = PFRES_MAPFAILED; goto done_pool_mtx; /* unsupported */ } @@ -684,7 +682,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, rpool->tblidx = (int)(hashidx % cnt); memset(&rpool->counter, 0, sizeof(rpool->counter)); if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter, - af, pf_islinklocal)) { + af, pf_islinklocal, false)) { reason = PFRES_MAPFAILED; goto done_pool_mtx; /* unsupported */ } @@ -701,11 +699,12 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, if (rpool->cur->addr.type == PF_ADDR_TABLE) { if (!pfr_pool_get(rpool->cur->addr.p.tbl, - &rpool->tblidx, &rpool->counter, af, NULL)) + &rpool->tblidx, &rpool->counter, af, NULL, true)) goto get_addr; } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, - &rpool->tblidx, &rpool->counter, af, pf_islinklocal)) + &rpool->tblidx, &rpool->counter, af, pf_islinklocal, + true)) goto get_addr; } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) goto get_addr; @@ -715,9 +714,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, rpool->cur = TAILQ_FIRST(&rpool->list); else rpool->cur = TAILQ_NEXT(rpool->cur, entries); + rpool->tblidx = -1; if (rpool->cur->addr.type == PF_ADDR_TABLE) { if (pfr_pool_get(rpool->cur->addr.p.tbl, - &rpool->tblidx, &rpool->counter, af, NULL)) { + &rpool->tblidx, &rpool->counter, af, NULL, true)) { /* table contains no address of type 'af' */ if (rpool->cur != acur) goto try_next; @@ -725,9 +725,9 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, goto done_pool_mtx; } } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { - rpool->tblidx = -1; if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, - &rpool->tblidx, &rpool->counter, af, pf_islinklocal)) { + &rpool->tblidx, &rpool->counter, af, pf_islinklocal, + true)) { /* table contains no address of type 'af' */ if (rpool->cur != acur) goto try_next; @@ -755,10 +755,6 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, done_pool_mtx: mtx_unlock(&rpool->mtx); - if (reason) { - counter_u64_add(V_pf_status.counters[reason], 1); - } - return (reason); } @@ -793,7 +789,7 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, if (nkif) *nkif = sn->rkif; if (V_pf_status.debug >= PF_DEBUG_NOISY) { - printf("pf_map_addr: src tracking maps "); + printf("%s: src tracking maps ", __func__); pf_print_host(saddr, 0, af); printf(" to "); pf_print_host(naddr, 0, af); @@ -808,14 +804,16 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr, * Source node has not been found. Find a new address and store it * in variables given by the caller. */ - if (pf_map_addr(af, r, saddr, naddr, nkif, init_addr, rpool) != 0) { - /* pf_map_addr() sets reason counters on its own */ + if ((reason = pf_map_addr(af, r, saddr, naddr, nkif, init_addr, + rpool)) != 0) { + if (V_pf_status.debug >= PF_DEBUG_MISC) + printf("%s: pf_map_addr has failed\n", __func__); goto done; } if (V_pf_status.debug >= PF_DEBUG_NOISY && (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { - printf("pf_map_addr: selected address "); + printf("%s: selected address ", __func__); pf_print_host(naddr, 0, af); if (nkif) printf("@%s", (*nkif)->pfik_name); @@ -826,10 +824,6 @@ done: if (sn != NULL) PF_SRC_NODE_UNLOCK(sn); - if (reason) { - counter_u64_add(V_pf_status.counters[reason], 1); - } - return (reason); } @@ -908,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; } @@ -1016,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) @@ -1086,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: @@ -1141,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 2034f4422ef1..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); @@ -2294,7 +2291,7 @@ pfr_detach_table(struct pfr_ktable *kt) int pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, - sa_family_t af, pf_addr_filter_func_t filter) + sa_family_t af, pf_addr_filter_func_t filter, bool loop_once) { struct pf_addr *addr, cur, mask, umask_addr; union sockaddr_union uaddr, umask; @@ -2339,7 +2336,7 @@ _next_block: ke = pfr_kentry_byidx(kt, idx, af); if (ke == NULL) { /* we don't have this idx, try looping */ - if (loop || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) { + if ((loop || loop_once) || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) { pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); return (1); } diff --git a/sys/netsmb/smb_conn.c b/sys/netsmb/smb_conn.c index 259635e2d8d5..ab6cd130a057 100644 --- a/sys/netsmb/smb_conn.c +++ b/sys/netsmb/smb_conn.c @@ -422,7 +422,7 @@ smb_vc_create(struct smb_vcspec *vcspec, if (uid == SMBM_ANY_OWNER) uid = realuid; if (gid == SMBM_ANY_GROUP) - gid = cred->cr_groups[0]; + gid = cred->cr_gid; vcp->vc_uid = uid; vcp->vc_grp = gid; @@ -765,7 +765,7 @@ smb_share_create(struct smb_vc *vcp, struct smb_sharespec *shspec, if (uid == SMBM_ANY_OWNER) uid = realuid; if (gid == SMBM_ANY_GROUP) - gid = cred->cr_groups[0]; + gid = cred->cr_gid; ssp = smb_zmalloc(sizeof(*ssp), M_SMBCONN, M_WAITOK); smb_co_init(SSTOCP(ssp), SMBL_SHARE, "smbss ilock", "smbss"); ssp->obj.co_free = smb_share_free; diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 7746b668265d..ae17b3289593 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -1469,6 +1469,9 @@ moea_page_set_memattr(vm_page_t m, vm_memattr_t ma) pmap_t pmap; u_int lo; + if (m->md.mdpg_cache_attrs == ma) + return; + if ((m->oflags & VPO_UNMANAGED) != 0) { m->md.mdpg_cache_attrs = ma; return; diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 79cea408bb5f..796b1719b8ba 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -2134,6 +2134,9 @@ moea64_page_set_memattr(vm_page_t m, vm_memattr_t ma) CTR3(KTR_PMAP, "%s: pa=%#jx, ma=%#x", __func__, (uintmax_t)VM_PAGE_TO_PHYS(m), ma); + if (m->md.mdpg_cache_attrs == ma) + return; + if ((m->oflags & VPO_UNMANAGED) != 0) { m->md.mdpg_cache_attrs = ma; return; diff --git a/sys/powerpc/aim/mmu_radix.c b/sys/powerpc/aim/mmu_radix.c index 45f7bef8bcc9..a12142fc2d7b 100644 --- a/sys/powerpc/aim/mmu_radix.c +++ b/sys/powerpc/aim/mmu_radix.c @@ -5937,6 +5937,10 @@ mmu_radix_page_set_memattr(vm_page_t m, vm_memattr_t ma) { CTR3(KTR_PMAP, "%s(%p, %#x)", __func__, m, ma); + + if (m->md.mdpg_cache_attrs == ma) + return; + m->md.mdpg_cache_attrs = ma; /* diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h index 050ada6b0f64..0230cf78aba7 100644 --- a/sys/powerpc/include/pcb.h +++ b/sys/powerpc/include/pcb.h @@ -66,16 +66,8 @@ struct pcb { #define PCB_VECREGS 0x200 /* Process had Altivec registers initialized */ struct fpu { union { -#if _BYTE_ORDER == _BIG_ENDIAN - double fpr; - uint32_t vsr[4]; -#else uint32_t vsr[4]; - struct { - double padding; - double fpr; - }; -#endif + double fpr; } fpr[32]; double fpscr; /* FPSCR stored as double for easier access */ } pcb_fpu; /* Floating point processor */ diff --git a/sys/powerpc/include/ucontext.h b/sys/powerpc/include/ucontext.h index d35c6c773fe0..dc87edd578bc 100644 --- a/sys/powerpc/include/ucontext.h +++ b/sys/powerpc/include/ucontext.h @@ -41,6 +41,7 @@ typedef struct __mcontext { int mc_flags; #define _MC_FP_VALID 0x01 #define _MC_AV_VALID 0x02 +#define _MC_VS_VALID 0x04 int mc_onstack; /* saved onstack flag */ int mc_len; /* sizeof(__mcontext) */ __uint64_t mc_avec[32*2]; /* vector register file */ @@ -56,6 +57,7 @@ typedef struct __mcontext32 { int mc_flags; #define _MC_FP_VALID 0x01 #define _MC_AV_VALID 0x02 +#define _MC_VS_VALID 0x04 int mc_onstack; /* saved onstack flag */ int mc_len; /* sizeof(__mcontext) */ uint64_t mc_avec[32*2]; /* vector register file */ diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index 1893d79f29a8..8a33d0f589a7 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -214,10 +214,10 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) sfpsize = sizeof(sf); #ifdef __powerpc64__ /* - * 64-bit PPC defines a 288 byte scratch region - * below the stack. + * 64-bit PPC defines a 512 byte red zone below + * the existing stack (ELF ABI v2 §2.2.2.4) */ - rndfsize = 288 + roundup(sizeof(sf), 48); + rndfsize = 512 + roundup(sizeof(sf), 48); #else rndfsize = roundup(sizeof(sf), 16); #endif @@ -349,13 +349,6 @@ sys_sigreturn(struct thread *td, struct sigreturn_args *uap) if (error != 0) return (error); - /* - * Save FPU state if needed. User may have changed it on - * signal handler - */ - if (uc.uc_mcontext.mc_srr1 & PSL_FP) - save_fpu(td); - kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", @@ -432,6 +425,7 @@ grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) } if (pcb->pcb_flags & PCB_VSX) { + mcp->mc_flags |= _MC_VS_VALID; for (i = 0; i < 32; i++) memcpy(&mcp->mc_vsxfpreg[i], &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double)); @@ -481,6 +475,7 @@ set_mcontext(struct thread *td, mcontext_t *mcp) struct pcb *pcb; struct trapframe *tf; register_t tls; + register_t msr; int i; pcb = td->td_pcb; @@ -531,6 +526,22 @@ set_mcontext(struct thread *td, mcontext_t *mcp) tf->srr1 &= ~(PSL_FP | PSL_VSX | PSL_VEC); pcb->pcb_flags &= ~(PCB_FPU | PCB_VSX | PCB_VEC); + /* + * Ensure the FPU is also disabled in hardware. + * + * Without this, it's possible for the register reload to fail if we + * don't switch to a FPU disabled context before resuming the original + * thread. Specifically, if the FPU/VSX unavailable exception is never + * hit, then whatever data is still in the FP/VSX registers when + * sigresume is callled will used by the resumed thread, instead of the + * previously saved data from the mcontext. + */ + critical_enter(); + msr = mfmsr() & ~(PSL_FP | PSL_VSX | PSL_VEC); + isync(); + mtmsr(msr); + critical_exit(); + if (mcp->mc_flags & _MC_FP_VALID) { /* enable_fpu() will happen lazily on a fault */ pcb->pcb_flags |= PCB_FPREGS; @@ -539,8 +550,12 @@ set_mcontext(struct thread *td, mcontext_t *mcp) for (i = 0; i < 32; i++) { memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i], sizeof(double)); - memcpy(&pcb->pcb_fpu.fpr[i].vsr[2], - &mcp->mc_vsxfpreg[i], sizeof(double)); + } + if (mcp->mc_flags & _MC_VS_VALID) { + for (i = 0; i < 32; i++) { + memcpy(&pcb->pcb_fpu.fpr[i].vsr[2], + &mcp->mc_vsxfpreg[i], sizeof(double)); + } } } diff --git a/sys/powerpc/powerpc/fpu.c b/sys/powerpc/powerpc/fpu.c index 0eaff2ea4932..cc8f22f7dda3 100644 --- a/sys/powerpc/powerpc/fpu.c +++ b/sys/powerpc/powerpc/fpu.c @@ -64,8 +64,19 @@ save_fpu_int(struct thread *td) * Save the floating-point registers and FPSCR to the PCB */ if (pcb->pcb_flags & PCB_VSX) { - #define SFP(n) __asm ("stxvw4x " #n ", 0,%0" \ +#if _BYTE_ORDER == _BIG_ENDIAN + #define SFP(n) __asm("stxvw4x " #n ", 0,%0" \ :: "b"(&pcb->pcb_fpu.fpr[n])); +#else + /* + * stxvw2x will swap words within the FP double word on LE systems, + * leading to corruption if VSX is used to store state and FP is + * subsequently used to restore state. + * Use stxvd2x instead. + */ + #define SFP(n) __asm("stxvd2x " #n ", 0,%0" \ + :: "b"(&pcb->pcb_fpu.fpr[n])); +#endif SFP(0); SFP(1); SFP(2); SFP(3); SFP(4); SFP(5); SFP(6); SFP(7); SFP(8); SFP(9); SFP(10); SFP(11); @@ -76,7 +87,7 @@ save_fpu_int(struct thread *td) SFP(28); SFP(29); SFP(30); SFP(31); #undef SFP } else { - #define SFP(n) __asm ("stfd " #n ", 0(%0)" \ + #define SFP(n) __asm("stfd " #n ", 0(%0)" \ :: "b"(&pcb->pcb_fpu.fpr[n].fpr)); SFP(0); SFP(1); SFP(2); SFP(3); SFP(4); SFP(5); SFP(6); SFP(7); @@ -149,8 +160,19 @@ enable_fpu(struct thread *td) :: "b"(&pcb->pcb_fpu.fpscr)); if (pcb->pcb_flags & PCB_VSX) { - #define LFP(n) __asm ("lxvw4x " #n ", 0,%0" \ +#if _BYTE_ORDER == _BIG_ENDIAN + #define LFP(n) __asm("lxvw4x " #n ", 0,%0" \ + :: "b"(&pcb->pcb_fpu.fpr[n])); +#else + /* + * lxvw4x will swap words within the FP double word on LE systems, + * leading to corruption if FP is used to store state and VSX is + * subsequently used to restore state. + * Use lxvd2x instead. + */ + #define LFP(n) __asm("lxvd2x " #n ", 0,%0" \ :: "b"(&pcb->pcb_fpu.fpr[n])); +#endif LFP(0); LFP(1); LFP(2); LFP(3); LFP(4); LFP(5); LFP(6); LFP(7); LFP(8); LFP(9); LFP(10); LFP(11); @@ -161,7 +183,7 @@ enable_fpu(struct thread *td) LFP(28); LFP(29); LFP(30); LFP(31); #undef LFP } else { - #define LFP(n) __asm ("lfd " #n ", 0(%0)" \ + #define LFP(n) __asm("lfd " #n ", 0(%0)" \ :: "b"(&pcb->pcb_fpu.fpr[n].fpr)); LFP(0); LFP(1); LFP(2); LFP(3); LFP(4); LFP(5); LFP(6); LFP(7); 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/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 5d15bd671285..26efaecc64d1 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -4838,6 +4838,8 @@ pmap_unmapbios(void *p, vm_size_t size) void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) { + if (m->md.pv_memattr == ma) + return; m->md.pv_memattr = ma; diff --git a/sys/rpc/authunix_prot.c b/sys/rpc/authunix_prot.c index 91fb96f44397..7b531946488a 100644 --- a/sys/rpc/authunix_prot.c +++ b/sys/rpc/authunix_prot.c @@ -93,9 +93,10 @@ xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) if (!xdr_uint32_t(xdrs, &cred->cr_uid)) return (FALSE); - if (!xdr_uint32_t(xdrs, &cred->cr_groups[0])) + if (!xdr_uint32_t(xdrs, &cred->cr_gid)) return (FALSE); + /* XXXKE Fix this is cr_gid gets separated out. */ if (xdrs->x_op == XDR_ENCODE) { ngroups = cred->cr_ngroups - 1; if (ngroups > NGRPS) @@ -105,7 +106,7 @@ xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) if (!xdr_uint32_t(xdrs, &ngroups)) return (FALSE); for (i = 0; i < ngroups; i++) { - if (i + 1 < ngroups_max + 1) { + if (i < ngroups_max) { if (!xdr_uint32_t(xdrs, &cred->cr_groups[i + 1])) return (FALSE); } else { @@ -115,7 +116,7 @@ xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) } if (xdrs->x_op == XDR_DECODE) { - if (ngroups + 1 > ngroups_max + 1) + if (ngroups > ngroups_max) cred->cr_ngroups = ngroups_max + 1; else cred->cr_ngroups = ngroups + 1; 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/rpc/svc_auth_unix.c b/sys/rpc/svc_auth_unix.c index 5d6402a05006..b10ef33be704 100644 --- a/sys/rpc/svc_auth_unix.c +++ b/sys/rpc/svc_auth_unix.c @@ -83,12 +83,13 @@ _svcauth_unix(struct svc_req *rqst, struct rpc_msg *msg) str_len = RNDUP(str_len); buf += str_len / sizeof (int32_t); xcr->cr_uid = IXDR_GET_UINT32(buf); - xcr->cr_groups[0] = IXDR_GET_UINT32(buf); + xcr->cr_gid = IXDR_GET_UINT32(buf); gid_len = (size_t)IXDR_GET_UINT32(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } + /* XXXKE Fix this if cr_gid gets separated out. */ for (i = 0; i < gid_len; i++) { if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c index 05928f1c33e8..7ec50d990d4e 100644 --- a/sys/security/audit/audit.c +++ b/sys/security/audit/audit.c @@ -279,7 +279,7 @@ audit_record_ctor(void *mem, int size, void *arg, int flags) cru2x(cred, &ar->k_ar.ar_subj_cred); ar->k_ar.ar_subj_ruid = cred->cr_ruid; ar->k_ar.ar_subj_rgid = cred->cr_rgid; - ar->k_ar.ar_subj_egid = cred->cr_groups[0]; + ar->k_ar.ar_subj_egid = cred->cr_gid; ar->k_ar.ar_subj_auid = cred->cr_audit.ai_auid; ar->k_ar.ar_subj_asid = cred->cr_audit.ai_asid; ar->k_ar.ar_subj_pid = td->td_proc->p_pid; diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index c667d3968817..3ea645373dbe 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -408,7 +408,7 @@ audit_arg_process(struct proc *p) cred = p->p_ucred; ar->k_ar.ar_arg_auid = cred->cr_audit.ai_auid; ar->k_ar.ar_arg_euid = cred->cr_uid; - ar->k_ar.ar_arg_egid = cred->cr_groups[0]; + ar->k_ar.ar_arg_egid = cred->cr_gid; ar->k_ar.ar_arg_ruid = cred->cr_ruid; ar->k_ar.ar_arg_rgid = cred->cr_rgid; ar->k_ar.ar_arg_asid = cred->cr_audit.ai_asid; diff --git a/sys/sys/compressor.h b/sys/sys/compressor.h index cad9080b46ff..e59eeabec2cd 100644 --- a/sys/sys/compressor.h +++ b/sys/sys/compressor.h @@ -42,6 +42,7 @@ struct compressor; bool compressor_avail(int format); struct compressor *compressor_init(compressor_cb_t cb, int format, size_t maxiosize, int level, void *arg); +int compressor_format(const struct compressor *stream); void compressor_reset(struct compressor *stream); int compressor_write(struct compressor *stream, void *data, size_t len); 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/exec.h b/sys/sys/exec.h index 4bf114a7c698..580a5372c4db 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -57,16 +57,6 @@ struct ps_strings { unsigned int ps_nenvstr; /* the number of environment strings */ }; -/* Coredump output parameters. */ -struct coredump_params { - off_t offset; - struct ucred *active_cred; - struct ucred *file_cred; - struct thread *td; - struct vnode *vp; - struct compressor *comp; -}; - struct image_params; struct execsw { @@ -105,16 +95,6 @@ int exec_unregister(const struct execsw *); enum uio_seg; -#define CORE_BUF_SIZE (16 * 1024) - -int core_write(struct coredump_params *, const void *, size_t, off_t, - enum uio_seg, size_t *); -int core_output(char *, size_t, off_t, struct coredump_params *, void *); -int sbuf_drain_core_output(void *, const char *, int); - -extern int coredump_pack_fileinfo; -extern int coredump_pack_vmmapinfo; - /* * note: name##_mod cannot be const storage because the * linker_file_sysinit() function modifies _file in the 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/imgact_elf.h b/sys/sys/imgact_elf.h index c9444e5aec41..2845a9dbc1e2 100644 --- a/sys/sys/imgact_elf.h +++ b/sys/sys/imgact_elf.h @@ -45,6 +45,7 @@ {(pos)->a_type = (id); (pos)->a_un.a_ptr = (ptr); (pos)++;} #endif +struct coredump_writer; struct image_params; struct thread; struct vnode; @@ -114,7 +115,7 @@ bool __elfN(brand_inuse)(Elf_Brandinfo *entry); int __elfN(insert_brand_entry)(Elf_Brandinfo *entry); int __elfN(remove_brand_entry)(Elf_Brandinfo *entry); int __elfN(freebsd_fixup)(uintptr_t *, struct image_params *); -int __elfN(coredump)(struct thread *, struct vnode *, off_t, int); +int __elfN(coredump)(struct thread *, struct coredump_writer *, off_t, int); size_t __elfN(populate_note)(int, void *, void *, size_t, void **); int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t); void __elfN(puthdr)(struct thread *, void *, size_t, int, size_t, int); 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..33d61e8a1619 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 1500055 /* * __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/signalvar.h b/sys/sys/signalvar.h index 23e8426b26ee..8f181b7beee6 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -403,6 +403,7 @@ int sigev_findtd(struct proc *p, struct sigevent *sigev, struct thread **); void sigfastblock_clear(struct thread *td); void sigfastblock_fetch(struct thread *td); int sig_intr(void); +bool sig_do_core(int); void siginit(struct proc *p); void signotify(struct thread *td); void sigqueue_delete(struct sigqueue *queue, int sig); diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h index 7f6234ade6f4..b4593f38f592 100644 --- a/sys/sys/sockbuf.h +++ b/sys/sys/sockbuf.h @@ -40,7 +40,7 @@ #define SB_SEL 0x08 /* someone is selecting */ #define SB_ASYNC 0x10 /* ASYNC I/O, need signals */ #define SB_UPCALL 0x20 /* someone wants an upcall */ -/* was SB_NOINTR 0x40 */ +#define SB_AUTOLOWAT 0x40 /* sendfile(2) may autotune sb_lowat */ #define SB_AIO 0x80 /* AIO operations queued */ #define SB_KNOTE 0x100 /* kernel note attached */ #define SB_NOCOALESCE 0x200 /* don't coalesce new data into existing mbufs */ @@ -210,8 +210,6 @@ typedef enum { SO_RCV, SO_SND } sb_which; * Socket buffer private mbuf(9) flags. */ #define M_NOTREADY M_PROTO1 /* m_data not populated yet */ -#define M_BLOCKED M_PROTO2 /* M_NOTREADY in front of m */ -#define M_NOTAVAIL (M_NOTREADY | M_BLOCKED) void sbappend(struct sockbuf *sb, struct mbuf *m, int flags); void sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags); diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index fd183ffbc7a4..8237165b84ce 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -60,6 +60,7 @@ struct rusage; struct sched_param; struct sembuf; union semun; +struct shmfd; struct sockaddr; struct spacectl_range; struct stat; @@ -337,7 +338,7 @@ int kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, struct filecaps *fcaps); int kern_shm_open2(struct thread *td, const char *path, int flags, mode_t mode, int shmflags, struct filecaps *fcaps, - const char *name); + const char *name, struct shmfd *shmfd); int kern_shmat(struct thread *td, int shmid, const void *shmaddr, int shmflg); int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf, diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 4ddfc8516053..1714fa5a7416 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -90,6 +90,7 @@ struct sysent { /* system call table */ #define SY_THR_STATIC_KLD SY_THR_STATIC #endif +struct coredump_writer; struct image_params; struct proc; struct __sigset; @@ -108,7 +109,8 @@ struct sysentvec { int *sv_szsigcode; /* size of sigtramp code */ int sv_sigcodeoff; char *sv_name; /* name of binary type */ - int (*sv_coredump)(struct thread *, struct vnode *, off_t, int); + int (*sv_coredump)(struct thread *, struct coredump_writer *, + off_t, int); /* function to dump core, or NULL */ int sv_elf_core_osabi; const char *sv_elf_core_abi_vendor; diff --git a/sys/sys/ucoredump.h b/sys/sys/ucoredump.h new file mode 100644 index 000000000000..0a51ee7f50c8 --- /dev/null +++ b/sys/sys/ucoredump.h @@ -0,0 +1,99 @@ +/* + * + * Copyright (c) 2015 Mark Johnston <markj@FreeBSD.org> + * Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + * + */ + +#ifndef _SYS_UCOREDUMP_H_ +#define _SYS_UCOREDUMP_H_ + +#ifdef _KERNEL + +#include <sys/_uio.h> +#include <sys/blockcount.h> +#include <sys/queue.h> + +/* Coredump output parameters. */ +struct coredump_params; +struct coredump_writer; +struct thread; +struct ucred; + +typedef int coredump_init_fn(const struct coredump_writer *, + const struct coredump_params *); +typedef int coredump_write_fn(const struct coredump_writer *, const void *, size_t, + off_t, enum uio_seg, struct ucred *, size_t *, struct thread *); +typedef int coredump_extend_fn(const struct coredump_writer *, off_t, + struct ucred *); + +struct coredump_vnode_ctx { + struct vnode *vp; + struct ucred *fcred; +}; + +coredump_write_fn core_vn_write; +coredump_extend_fn core_vn_extend; + +struct coredump_writer { + void *ctx; + coredump_init_fn *init_fn; + coredump_write_fn *write_fn; + coredump_extend_fn *extend_fn; +}; + +struct coredump_params { + off_t offset; + struct ucred *active_cred; + struct thread *td; + const struct coredump_writer *cdw; + struct compressor *comp; +}; + +#define CORE_BUF_SIZE (16 * 1024) + +int core_write(struct coredump_params *, const void *, size_t, off_t, + enum uio_seg, size_t *); +int core_output(char *, size_t, off_t, struct coredump_params *, void *); +int sbuf_drain_core_output(void *, const char *, int); + +extern int coredump_pack_fileinfo; +extern int coredump_pack_vmmapinfo; + +extern int compress_user_cores; +extern int compress_user_cores_level; + +typedef int coredumper_probe_fn(struct thread *); + +/* + * Some arbitrary values for coredumper probes to return. The highest priority + * we can find wins. It's somewhat expected that a coredumper may want to bid + * differently based on the process in question. Note that probe functions will + * be called with the proc lock held, so they must not sleep. + */ +#define COREDUMPER_NOMATCH (-1) /* Decline to touch it */ +#define COREDUMPER_GENERIC (0) /* I handle coredumps */ +#define COREDUMPER_SPECIAL (50) /* Special handler */ +#define COREDUMPER_HIGH_PRIORITY (100) /* High-priority handler */ + +/* + * The handle functions will be called with the proc lock held, and should + * return with the proc lock dropped. + */ +typedef int coredumper_handle_fn(struct thread *, off_t); + +struct coredumper { + SLIST_ENTRY(coredumper) cd_entry; + const char *cd_name; + coredumper_probe_fn *cd_probe; + coredumper_handle_fn *cd_handle; + blockcount_t cd_refcount; +}; + +void coredumper_register(struct coredumper *); +void coredumper_unregister(struct coredumper *); + +#endif /* _KERNEL */ +#endif /* _SYS_UCOREDUMP_H_ */ diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h index c291c1dc2b95..85ed93fd359d 100644 --- a/sys/sys/unistd.h +++ b/sys/sys/unistd.h @@ -156,6 +156,8 @@ #define _PC_DEALLOC_PRESENT 65 #define _PC_NAMEDATTR_ENABLED 66 #define _PC_HAS_NAMEDATTR 67 +#define _PC_XATTR_ENABLED _PC_NAMEDATTR_ENABLED /* Solaris Compatible */ +#define _PC_XATTR_EXISTS _PC_HAS_NAMEDATTR /* Solaris Compatible */ #define _PC_HAS_HIDDENSYSTEM 68 #endif 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/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 53fac4b0665e..17308706c3f4 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -2064,9 +2064,13 @@ ufs_mkdir( */ ucred.cr_ref = 1; ucred.cr_uid = ip->i_uid; + + /* + * XXXKE Fix this is cr_gid gets separated out + */ ucred.cr_ngroups = 1; ucred.cr_groups = &ucred_group; - ucred.cr_groups[0] = dp->i_gid; + ucred.cr_gid = ucred_group = dp->i_gid; ucp = &ucred; } #endif @@ -2823,9 +2827,13 @@ ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp, */ ucred.cr_ref = 1; ucred.cr_uid = ip->i_uid; + + /* + * XXXKE Fix this is cr_gid gets separated out + */ ucred.cr_ngroups = 1; ucred.cr_groups = &ucred_group; - ucred.cr_groups[0] = pdir->i_gid; + ucred.cr_gid = ucred_group = pdir->i_gid; ucp = &ucred; #endif } else { 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_domainset.c b/sys/vm/vm_domainset.c index 7b8bf4c77663..b44bdb96b0d4 100644 --- a/sys/vm/vm_domainset.c +++ b/sys/vm/vm_domainset.c @@ -131,8 +131,7 @@ static void vm_domainset_iter_next(struct vm_domainset_iter *di, int *domain) { - KASSERT(di->di_n > 0, - ("vm_domainset_iter_first: Invalid n %d", di->di_n)); + KASSERT(di->di_n > 0, ("%s: Invalid n %d", __func__, di->di_n)); switch (di->di_policy) { case DOMAINSET_POLICY_FIRSTTOUCH: /* @@ -149,11 +148,10 @@ vm_domainset_iter_next(struct vm_domainset_iter *di, int *domain) vm_domainset_iter_prefer(di, domain); break; default: - panic("vm_domainset_iter_first: Unknown policy %d", - di->di_policy); + panic("%s: Unknown policy %d", __func__, di->di_policy); } KASSERT(*domain < vm_ndomains, - ("vm_domainset_iter_next: Invalid domain %d", *domain)); + ("%s: Invalid domain %d", __func__, *domain)); } static void @@ -189,13 +187,11 @@ vm_domainset_iter_first(struct vm_domainset_iter *di, int *domain) di->di_n = di->di_domain->ds_cnt; break; default: - panic("vm_domainset_iter_first: Unknown policy %d", - di->di_policy); + panic("%s: Unknown policy %d", __func__, di->di_policy); } - KASSERT(di->di_n > 0, - ("vm_domainset_iter_first: Invalid n %d", di->di_n)); + KASSERT(di->di_n > 0, ("%s: Invalid n %d", __func__, di->di_n)); KASSERT(*domain < vm_ndomains, - ("vm_domainset_iter_first: Invalid domain %d", *domain)); + ("%s: Invalid domain %d", __func__, *domain)); } void 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_page.c b/sys/vm/vm_page.c index bbae55895c2c..b239a6ffb4ce 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -396,7 +396,7 @@ vm_page_blacklist_load(char **list, char **end) } *list = ptr; if (ptr != NULL) - *end = ptr + len; + *end = ptr + len - 1; else *end = NULL; return; 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..48e638fdb79c 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?= QEMU_EXTRA_PARAM?= QEMU_MACHINE?=virt QEMUBIN=/usr/local/bin/qemu-system-${QEMU_ARCH} @@ -134,7 +134,8 @@ METAMODE?=-DWITH_META_MODE .endif CLEANFILES+= ${.OBJDIR}/${CIIMAGE} ${.OBJDIR}/ci.img ${META_TAR} -CLEANDIRS+= ${.OBJDIR}/ci-buildimage +IMAGEDIR= ${.OBJDIR}/ci-buildimage +CLEANDIRS+= ${IMAGEDIR} portinstall: portinstall-pkg portinstall-qemu portinstall-expect portinstall-${TARGET_ARCH:tl} .PHONY @@ -157,7 +158,7 @@ portinstall-expect: portinstall-pkg .PHONY .endif beforeclean: .PHONY - chflags -R noschg ${.OBJDIR}/${.TARGET} + chflags -R noschg ${IMAGEDIR} .include <bsd.obj.mk> clean: beforeclean .PHONY @@ -205,6 +206,7 @@ ci-create-meta: .PHONY ci-extract-meta: .PHONY tar xfv ${META_TAR} -C ${META_DIROUT} + rm -rf ${META_TAR} ${META_DIR} @echo "Extracted kyua reports to ${META_DIROUT}" ci-runtest: ci-buildimage-${TARGET_ARCH:tl} portinstall .PHONY @@ -235,8 +237,10 @@ ci-runtest: ci-buildimage-${TARGET_ARCH:tl} portinstall .PHONY -nographic \ -no-reboot \ ${QEMU_EXTRA_PARAM} \ - -drive if=none,file=${CIDISK},format=raw,id=hd0 \ - -drive if=none,file=${META_TAR},format=raw,id=hd1 \ + -device virtio-blk,drive=hd0 \ + -device virtio-blk,drive=hd1 \ + -blockdev driver=raw,node-name=hd0,file.driver=file,file.filename=${CIDISK} \ + -blockdev driver=raw,node-name=hd1,file.driver=file,file.filename=${META_TAR} \ ${QEMU_DEVICES} .endif @@ -254,7 +258,7 @@ ci-checktarget: .PHONY ci-smoke: ci-set-smoke-var ci-create-meta ci-checktarget .WAIT ci-runtest-${TARGET_ARCH:tl} .PHONY -ci-full: ci-set-full-var ci-create-meta ci-checktarget .WAIT ci-runtest-${TARGET_ARCH:tl} ci-extract-meta .PHONY +ci-full: ci-set-full-var ci-create-meta ci-checktarget .WAIT ci-runtest-${TARGET_ARCH:tl} .WAIT ci-extract-meta .PHONY ci: ci-${CITYPE:tl} .PHONY diff --git a/tests/ci/Makefile.aarch64 b/tests/ci/Makefile.aarch64 index 9cbec6010a36..5a62e73d8eaa 100644 --- a/tests/ci/Makefile.aarch64 +++ b/tests/ci/Makefile.aarch64 @@ -8,7 +8,7 @@ # CI Makefile for aarch64. # QEMU_ARCH=aarch64 -QEMU_DEVICES=-device virtio-blk,drive=hd0 -device ahci,id=ahci +QEMU_DEVICES=-device ahci,id=ahci QEMU_EXTRA_PARAM=-bios /usr/local/share/u-boot/u-boot-qemu-arm64/u-boot.bin -cpu cortex-a57 QEMU_MAX_CPU_COUNT=64 QEMU_MAX_MEM_SIZE=64 diff --git a/tests/ci/Makefile.armv7 b/tests/ci/Makefile.armv7 index 21ee6b387b05..3b0d180fa352 100644 --- a/tests/ci/Makefile.armv7 +++ b/tests/ci/Makefile.armv7 @@ -8,7 +8,7 @@ # CI Makefile for armv7. # QEMU_ARCH=arm -QEMU_DEVICES=-device virtio-blk,drive=hd0 -device ahci,id=ahci +QEMU_DEVICES=-device ahci,id=ahci QEMU_EXTRA_PARAM=-bios /usr/local/share/u-boot/u-boot-qemu-arm/u-boot.bin QEMU_MAX_CPU_COUNT=1 QEMU_MAX_MEM_SIZE=3 diff --git a/tests/ci/Makefile.powerpc64 b/tests/ci/Makefile.powerpc64 index 26712b45f30b..d4e8e2cdc778 100644 --- a/tests/ci/Makefile.powerpc64 +++ b/tests/ci/Makefile.powerpc64 @@ -8,7 +8,6 @@ # CI Makefile for powerpc64. # QEMU_ARCH=ppc64 -QEMU_DEVICES=-device virtio-blk,drive=hd0 QEMU_EXTRA_PARAM=-vga none -accel tcg,thread=multi QEMU_MACHINE=pseries,cap-hpt-max-page-size=16M QEMU_MAX_CPU_COUNT=1 diff --git a/tests/ci/Makefile.powerpc64le b/tests/ci/Makefile.powerpc64le index 974ab04b8eed..60c255f569fa 100644 --- a/tests/ci/Makefile.powerpc64le +++ b/tests/ci/Makefile.powerpc64le @@ -8,7 +8,6 @@ # CI Makefile for powerpc64le. # QEMU_ARCH=ppc64 -QEMU_DEVICES=-device virtio-blk,drive=hd0 QEMU_EXTRA_PARAM=-vga none -accel tcg,thread=multi QEMU_MACHINE=pseries,cap-hpt-max-page-size=16M QEMU_MAX_CPU_COUNT=1 diff --git a/tests/ci/Makefile.riscv64 b/tests/ci/Makefile.riscv64 index 749df3f0b369..d494fc4f43f5 100644 --- a/tests/ci/Makefile.riscv64 +++ b/tests/ci/Makefile.riscv64 @@ -8,7 +8,6 @@ # CI Makefile for riscv64. # QEMU_ARCH=riscv64 -QEMU_DEVICES=-device virtio-blk-device,drive=hd0 QEMU_EXTRA_PARAM=-bios /usr/local/share/opensbi/lp64/generic/firmware/fw_jump.elf -kernel /usr/local/share/u-boot/u-boot-qemu-riscv64/u-boot.bin QEMU_MAX_CPU_COUNT=16 QEMU_MAX_MEM_SIZE=64 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/mac/portacl/Makefile b/tests/sys/mac/portacl/Makefile index c9fb6bbaae3e..856a85d331d5 100644 --- a/tests/sys/mac/portacl/Makefile +++ b/tests/sys/mac/portacl/Makefile @@ -10,6 +10,7 @@ TAP_TESTS_SH+= root_test .for t in ${TAP_TESTS_SH} TEST_METADATA.$t+= required_user="root" TEST_METADATA.$t+= timeout="450" +TEST_METADATA.$t+= is_exclusive="true" .endfor .include <bsd.test.mk> diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh index cc0b212aebd2..cd38adea28ad 100755 --- a/tests/sys/net/if_bridge_test.sh +++ b/tests/sys/net/if_bridge_test.sh @@ -537,7 +537,7 @@ get_mtu() { intf=$1 - ifconfig ${intf} ether | awk '$5 == "mtu" { print $6 }' + ifconfig ${intf} | awk '$5 == "mtu" { print $6 }' } check_mtu() @@ -546,7 +546,7 @@ check_mtu() expected=$2 mtu=$(get_mtu $intf) - if [ $mtu -ne $expected ]; + if [ "$mtu" -ne "$expected" ]; then atf_fail "Expected MTU of $expected on $intf but found $mtu" fi diff --git a/tests/sys/net/if_ovpn/if_ovpn.sh b/tests/sys/net/if_ovpn/if_ovpn.sh index 2138e0f666ec..26807a095455 100644 --- a/tests/sys/net/if_ovpn/if_ovpn.sh +++ b/tests/sys/net/if_ovpn/if_ovpn.sh @@ -1149,6 +1149,171 @@ destroy_unused_cleanup() ovpn_cleanup } +atf_test_case "multihome4" "cleanup" +multihome4_head() +{ + atf_set descr 'Test multihome IPv4 with OpenVPN' + atf_set require.user root + atf_set require.progs openvpn +} + +multihome4_body() +{ + pft_init + ovpn_init + + l=$(vnet_mkepair) + + vnet_mkjail a ${l}a + atf_check jexec a ifconfig ${l}a inet 192.0.2.1/24 + atf_check jexec a ifconfig ${l}a alias 192.0.2.2/24 + vnet_mkjail b ${l}b + atf_check jexec b ifconfig ${l}b inet 192.0.2.3/24 + + # Sanity check + atf_check -s exit:0 -o ignore jexec b ping -c 1 192.0.2.1 + atf_check -s exit:0 -o ignore jexec b ping -c 1 192.0.2.2 + + ovpn_start a " + dev ovpn0 + dev-type tun + proto udp4 + + cipher AES-256-GCM + auth SHA256 + + multihome + server 198.51.100.0 255.255.255.0 + ca $(atf_get_srcdir)/ca.crt + cert $(atf_get_srcdir)/server.crt + key $(atf_get_srcdir)/server.key + dh $(atf_get_srcdir)/dh.pem + + mode server + script-security 2 + auth-user-pass-verify /usr/bin/true via-env + topology subnet + + keepalive 100 600 + " + ovpn_start b " + dev tun0 + dev-type tun + + client + + remote 192.0.2.2 + auth-user-pass $(atf_get_srcdir)/user.pass + + ca $(atf_get_srcdir)/ca.crt + cert $(atf_get_srcdir)/client.crt + key $(atf_get_srcdir)/client.key + dh $(atf_get_srcdir)/dh.pem + + keepalive 100 600 + " + + # Block packets from the primary address, openvpn should only use the + # configured remote address. + jexec b pfctl -e + pft_set_rules b \ + "block in quick from 192.0.2.1 to any" \ + "pass all" + + # Give the tunnel time to come up + sleep 10 + + atf_check -s exit:0 -o ignore jexec b ping -c 3 198.51.100.1 +} + +multihome4_cleanup() +{ + ovpn_cleanup + pft_cleanup +} + +multihome6_head() +{ + atf_set descr 'Test multihome IPv6 with OpenVPN' + atf_set require.user root + atf_set require.progs openvpn +} + +multihome6_body() +{ + ovpn_init + + l=$(vnet_mkepair) + + vnet_mkjail a ${l}a + atf_check jexec a ifconfig ${l}a inet6 2001:db8::1/64 no_dad + atf_check jexec a ifconfig ${l}a inet6 alias 2001:db8::2/64 no_dad + vnet_mkjail b ${l}b + atf_check jexec b ifconfig ${l}b inet6 2001:db8::3/64 no_dad + + # Sanity check + atf_check -s exit:0 -o ignore jexec b ping6 -c 1 2001:db8::1 + atf_check -s exit:0 -o ignore jexec b ping6 -c 1 2001:db8::2 + + ovpn_start a " + dev ovpn0 + dev-type tun + proto udp6 + + cipher AES-256-GCM + auth SHA256 + + multihome + server-ipv6 2001:db8:1::/64 + + ca $(atf_get_srcdir)/ca.crt + cert $(atf_get_srcdir)/server.crt + key $(atf_get_srcdir)/server.key + dh $(atf_get_srcdir)/dh.pem + + mode server + script-security 2 + auth-user-pass-verify /usr/bin/true via-env + topology subnet + + keepalive 100 600 + " + ovpn_start b " + dev tun0 + dev-type tun + + client + + remote 2001:db8::2 + auth-user-pass $(atf_get_srcdir)/user.pass + + ca $(atf_get_srcdir)/ca.crt + cert $(atf_get_srcdir)/client.crt + key $(atf_get_srcdir)/client.key + dh $(atf_get_srcdir)/dh.pem + + keepalive 100 600 + " + + # Block packets from the primary address, openvpn should only use the + # configured remote address. + jexec b pfctl -e + pft_set_rules b \ + "block in quick from 2001:db8::1 to any" \ + "pass all" + + # Give the tunnel time to come up + sleep 10 + + atf_check -s exit:0 -o ignore jexec b ping6 -c 3 2001:db8:1::1 + atf_check -s exit:0 -o ignore jexec b ping6 -c 3 -z 16 2001:db8:1::1 +} + +multihome6_cleanup() +{ + ovpn_cleanup +} + atf_init_test_cases() { atf_add_test_case "4in4" @@ -1165,4 +1330,6 @@ atf_init_test_cases() atf_add_test_case "chacha" atf_add_test_case "gcm_128" atf_add_test_case "destroy_unused" + atf_add_test_case "multihome4" + atf_add_test_case "multihome6" } 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/anchor.sh b/tests/sys/netpfil/pf/anchor.sh index 4692c06142df..64ca84b34c3d 100644 --- a/tests/sys/netpfil/pf/anchor.sh +++ b/tests/sys/netpfil/pf/anchor.sh @@ -350,9 +350,9 @@ nat_body() jexec alcatraz pfctl -sn -a "foo/bar" jexec alcatraz pfctl -sn -a "foo/baz" - atf_check -s exit:0 -o match:"nat log on epair0a inet from 192.0.2.0/24 to any port = domain -> 192.0.2.1" \ + atf_check -s exit:0 -o match:"nat log on ${epair}a inet from 192.0.2.0/24 to any port = domain -> 192.0.2.1" \ jexec alcatraz pfctl -sn -a "*" - atf_check -s exit:0 -o match:"rdr on epair0a inet proto tcp from any to any port = echo -> 127.0.0.1 port 7" \ + atf_check -s exit:0 -o match:"rdr on ${epair}a inet proto tcp from any to any port = echo -> 127.0.0.1 port 7" \ jexec alcatraz pfctl -sn -a "*" } 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/nat.sh b/tests/sys/netpfil/pf/nat.sh index f1fdf6405d97..16c981f97399 100644 --- a/tests/sys/netpfil/pf/nat.sh +++ b/tests/sys/netpfil/pf/nat.sh @@ -777,6 +777,38 @@ binat_match_cleanup() kill $(cat ${PWD}/inetd_tester.pid) } +atf_test_case "empty_pool" "cleanup" +empty_pool_head() +{ + atf_set descr 'NAT with empty pool' + atf_set require.user root +} + +empty_pool_body() +{ + pft_init + setup_router_server_ipv6 + + + pft_set_rules router \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ + "pass in on ${epair_tester}b" \ + "pass out on ${epair_server}a inet6 from any to ${net_server_host_server} nat-to <nonexistent>" \ + + # pf_map_addr_sn() won't be able to pick a target address, because + # the table used in redireciton pool is empty. Packet will not be + # forwarded, error counter will be increased. + ping_server_check_reply exit:1 + # Ignore warnings about not-loaded ALTQ + atf_check -o "match:map-failed +1 +" -x "jexec router pfctl -qvvsi 2> /dev/null" +} + +empty_pool_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "exhaust" @@ -794,4 +826,5 @@ atf_init_test_cases() atf_add_test_case "nat_match" atf_add_test_case "binat_compat" atf_add_test_case "binat_match" + atf_add_test_case "empty_pool" } 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/rdr.sh b/tests/sys/netpfil/pf/rdr.sh index 4c08b4973891..f7c920bbfa8f 100644 --- a/tests/sys/netpfil/pf/rdr.sh +++ b/tests/sys/netpfil/pf/rdr.sh @@ -142,7 +142,7 @@ tcp_v6_pass_body() { tcp_v6_setup # Sets ${epair_…} variables tcp_v6_common \ - "rdr on ${epair_one}a proto tcp from any to any port 80 -> 2001:db8:b::2 port 8000" + "pass in on ${epair_one}a proto tcp from any to any port 80 rdr-to 2001:db8:b::2 port 8000" } tcp_v6_pass_cleanup() diff --git a/tests/sys/netpfil/pf/route_to.sh b/tests/sys/netpfil/pf/route_to.sh index 5c0d355b8ea1..fd1653cce311 100644 --- a/tests/sys/netpfil/pf/route_to.sh +++ b/tests/sys/netpfil/pf/route_to.sh @@ -859,6 +859,121 @@ ttl_cleanup() pft_cleanup } + +atf_test_case "empty_pool" "cleanup" +empty_pool_head() +{ + atf_set descr 'Route-to with empty pool' + atf_set require.user root +} + +empty_pool_body() +{ + pft_init + setup_router_server_ipv6 + + + pft_set_rules router \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ + "pass in on ${epair_tester}b route-to (${epair_server}a <nonexistent>) inet6 from any to ${net_server_host_server}" \ + "pass out on ${epair_server}a" + + # pf_map_addr_sn() won't be able to pick a target address, because + # the table used in redireciton pool is empty. Packet will not be + # forwarded, error counter will be increased. + ping_server_check_reply exit:1 + # Ignore warnings about not-loaded ALTQ + atf_check -o "match:map-failed +1 +" -x "jexec router pfctl -qvvsi 2> /dev/null" +} + +empty_pool_cleanup() +{ + pft_cleanup +} + + +atf_test_case "table_loop" "cleanup" + +table_loop_head() +{ + atf_set descr 'Check that iterating over tables poperly loops' + atf_set require.user root +} + +table_loop_body() +{ + setup_router_server_nat64 + + # Clients will connect from another network behind the router. + # This allows for using multiple source addresses. + jexec router route add -6 ${net_clients_6}::/${net_clients_6_mask} ${net_tester_6_host_tester} + jexec router route add ${net_clients_4}.0/${net_clients_4_mask} ${net_tester_4_host_tester} + + # The servers are reachable over additional IP addresses for + # testing of tables and subnets. The addresses are noncontinougnus + # for pf_map_addr() counter tests. + for i in 0 1 4 5; do + a1=$((24 + i)) + jexec server1 ifconfig ${epair_server1}b inet ${net_server1_4}.${a1}/32 alias + jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6}::42:${i}/128 alias + a2=$((40 + i)) + jexec server2 ifconfig ${epair_server2}b inet ${net_server2_4}.${a2}/32 alias + jexec server2 ifconfig ${epair_server2}b inet6 ${net_server2_6}::42:${i}/128 alias + done + + jexec router pfctl -e + pft_set_rules router \ + "set debug loud" \ + "set reassemble yes" \ + "set state-policy if-bound" \ + "table <rt_targets_1> { ${net_server1_6}::42:4/127 ${net_server1_6}::42:0/127 }" \ + "table <rt_targets_2> { ${net_server2_6}::42:4/127 }" \ + "pass in on ${epair_tester}b \ + route-to { \ + (${epair_server1}a <rt_targets_1>) \ + (${epair_server2}a <rt_targets_2_empty>) \ + (${epair_server2}a <rt_targets_2>) \ + } \ + inet6 proto tcp \ + keep state" + + # Both hosts of the pool are tables. Each table gets iterated over once, + # then the pool iterates to the next host, which is also iterated, + # then the pool loops back to the 1st host. If an empty table is found, + # it is skipped. Unless that's the only table, that is tested by + # the "empty_pool" test. + for port in $(seq 1 7); do + port=$((4200 + port)) + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_tester}a --replyif ${epair_tester}a \ + --fromaddr ${net_clients_6}::1 --to ${host_server_6} \ + --ping-type=tcp3way --send-sport=${port} + done + + states=$(mktemp) || exit 1 + jexec router pfctl -qvvss | normalize_pfctl_s > $states + cat $states + + for state_regexp in \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4201\] .* route-to: ${net_server1_6}::42:0@${epair_server1}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4202\] .* route-to: ${net_server1_6}::42:1@${epair_server1}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4203\] .* route-to: ${net_server1_6}::42:4@${epair_server1}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4204\] .* route-to: ${net_server1_6}::42:5@${epair_server1}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4205\] .* route-to: ${net_server2_6}::42:4@${epair_server2}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4206\] .* route-to: ${net_server2_6}::42:5@${epair_server2}a" \ + "${epair_tester}b tcp ${host_server_6}\[9\] <- ${net_clients_6}::1\[4207\] .* route-to: ${net_server1_6}::42:0@${epair_server1}a" \ + ; do + grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'" + done +} + +table_loop_cleanup() +{ + pft_cleanup +} + + atf_init_test_cases() { atf_add_test_case "v4" @@ -877,4 +992,6 @@ atf_init_test_cases() atf_add_test_case "dummynet_double" atf_add_test_case "sticky" atf_add_test_case "ttl" + atf_add_test_case "empty_pool" + atf_add_test_case "table_loop" } 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/tests/sys/netpfil/pf/utils.subr b/tests/sys/netpfil/pf/utils.subr index 6af10e80390d..3f8d437920f9 100644 --- a/tests/sys/netpfil/pf/utils.subr +++ b/tests/sys/netpfil/pf/utils.subr @@ -274,6 +274,107 @@ setup_router_server_ipv6() jexec server inetd -p ${PWD}/inetd.pid $inetd_conf } +# Create a router and 2 server jails for nat64 and rfc5549 test cases. +# The router is connected to servers, both are dual-stack, and to the +# tester jail. All links are dual stack. +setup_router_server_nat64() +{ + pft_init + + epair_tester=$(vnet_mkepair) + epair_server1=$(vnet_mkepair) + epair_server2=$(vnet_mkepair) + + # Funny how IPv4 address space is to small to even assign nice /24 + # prefixes on all needed networks. On IPv6 we have a separate /64 for + # each link, loopback server, and client/SNAT pool. On IPv4 we must + # use small /28 prefixes, so even though we define all networks + # as variables we can't easily use them in tests if additional addresses + # are needed. + + # IP addresses which can be used by the tester jail. + # Can be used as SNAT or as source with pft_ping.py. It is up to + # the test code to make them accessible from router. + net_clients_4=203.0.113 + net_clients_4_mask=24 + net_clients_6=2001:db8:44 + net_clients_6_mask=64 + + # IP addresses on loopback interfaces of both servers. They can be + # accessed using the route-to targtet. + host_server_4=192.0.2.100 + host_server_6=2001:db8:4203::100 + + net_tester_4=198.51.100 + net_tester_4_mask=28 + net_tester_4_host_router=198.51.100.1 + net_tester_4_host_tester=198.51.100.2 + + net_tester_6=2001:db8:4200 + net_tester_6_mask=64 + net_tester_6_host_router=2001:db8:4200::1 + net_tester_6_host_tester=2001:db8:4200::2 + + net_server1_4=198.51.100 + net_server1_4_mask=28 + net_server1_4_host_router=198.51.100.17 + net_server1_4_host_server=198.51.100.18 + + net_server1_6=2001:db8:4201 + net_server1_6_mask=64 + net_server1_6_host_router=2001:db8:4201::1 + net_server1_6_host_server=2001:db8:4201::2 + + net_server2_4=198.51.100 + net_server2_4_mask=28 + net_server2_4_host_router=198.51.100.33 + net_server2_4_host_server=198.51.100.34 + + net_server2_6=2001:db8:4202 + net_server2_6_mask=64 + net_server2_6_host_router=2001:db8:4202::1 + net_server2_6_host_server=2001:db8:4202::2 + + vnet_mkjail router ${epair_tester}b ${epair_server1}a ${epair_server2}a + jexec router ifconfig ${epair_tester}b inet ${net_tester_4_host_router}/${net_tester_4_mask} up + jexec router ifconfig ${epair_tester}b inet6 ${net_tester_6_host_router}/${net_tester_6_mask} up no_dad + jexec router ifconfig ${epair_server1}a inet ${net_server1_4_host_router}/${net_server1_4_mask} up + jexec router ifconfig ${epair_server1}a inet6 ${net_server1_6_host_router}/${net_server1_6_mask} up no_dad + jexec router ifconfig ${epair_server2}a inet ${net_server2_4_host_router}/${net_server2_4_mask} up + jexec router ifconfig ${epair_server2}a inet6 ${net_server2_6_host_router}/${net_server2_6_mask} up no_dad + jexec router sysctl net.inet.ip.forwarding=1 + jexec router sysctl net.inet6.ip6.forwarding=1 + jexec router pfctl -e + + ifconfig ${epair_tester}a inet ${net_tester_4_host_tester}/${net_tester_4_mask} up + ifconfig ${epair_tester}a inet6 ${net_tester_6_host_tester}/${net_tester_6_mask} up no_dad + route add 0.0.0.0/0 ${net_tester_4_host_router} + route add -6 ::/0 ${net_tester_6_host_router} + + inetd_conf=$(mktemp) + echo "discard stream tcp46 nowait root internal" >> $inetd_conf + + vnet_mkjail server1 ${epair_server1}b + jexec server1 /etc/rc.d/netif start lo0 + jexec server1 ifconfig ${epair_server1}b inet ${net_server1_4_host_server}/${net_server1_4_mask} up + jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6_host_server}/${net_server1_6_mask} up no_dad + jexec server1 ifconfig lo0 ${host_server_4}/32 alias + jexec server1 ifconfig lo0 inet6 ${host_server_6}/128 alias + jexec server1 inetd -p ${PWD}/inetd_1.pid $inetd_conf + jexec server1 route add 0.0.0.0/0 ${net_server1_4_host_router} + + jexec server1 route add -6 ::/0 ${net_server1_6_host_router} + vnet_mkjail server2 ${epair_server2}b + jexec server2 /etc/rc.d/netif start lo0 + jexec server2 ifconfig ${epair_server2}b inet ${net_server2_4_host_server}/${net_server2_4_mask} up + jexec server2 ifconfig ${epair_server2}b inet6 ${net_server2_6_host_server}/${net_server2_6_mask} up no_dad + jexec server2 ifconfig lo0 ${host_server_4}/32 alias + jexec server2 ifconfig lo0 inet6 ${host_server_6}/128 alias + jexec server2 inetd -p ${PWD}/inetd_2.pid $inetd_conf + jexec server2 route add 0.0.0.0/0 ${net_server2_4_host_router} + jexec server2 route add -6 ::/0 ${net_server2_6_host_router} +} + # Ping the dummy static NDP target. # Check for pings being forwarded through the router towards the target. ping_dummy_check_request() diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 1e63e4616909..da7f57eec2d5 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -461,7 +461,7 @@ OLD_FILES+=usr/include/bsnmp/snmpclient.h OLD_FILES+=usr/include/bsnmp/snmpmod.h OLD_FILES+=usr/lib/libbsnmp.a OLD_FILES+=usr/lib/libbsnmp.so -OLD_LIBS+=usr/lib/libbsnmp.so.6 +OLD_LIBS+=usr/lib/libbsnmp.so.7 OLD_FILES+=usr/lib/libbsnmp_p.a OLD_FILES+=usr/lib/libbsnmptools.a OLD_FILES+=usr/lib/libbsnmptools.so @@ -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 @@ -1469,12 +1473,12 @@ OLD_DIRS+=usr/share/dict .endif .if ${MK_DMAGENT} == no +OLD_FILES+=etc/dma/auth.conf OLD_FILES+=etc/dma/dma.conf OLD_DIRS+=etc/dma OLD_FILES+=usr/libexec/dma OLD_FILES+=usr/libexec/dma-mbox-create OLD_FILES+=usr/share/man/man8/dma.8.gz -OLD_FILES+=usr/share/examples/dma/auth.conf OLD_FILES+=usr/share/examples/dma/mailer.conf OLD_DIRS+=usr/share/examples/dma .endif @@ -3709,33 +3713,33 @@ OLD_FILES+=usr/lib/krb5/plugins/preauth/test.so OLD_FILES+=usr/lib/krb5/plugins/tls/k5tls.so OLD_FILES+=usr/lib/libcom_err.a OLD_LIBS+=usr/lib/libcom_err.so -OLD_LIBS+=usr/lib/libcom_err.so.121 +OLD_LIBS+=usr/lib/libcom_err.so.122 OLD_FILES+=usr/lib/libgssapi_krb5.so -OLD_LIBS+=usr/lib/libgssapi_krb5.so.121 +OLD_LIBS+=usr/lib/libgssapi_krb5.so.122 OLD_FILES+=usr/lib/libgssrpc.so -OLD_LIBS+=usr/lib/libgssrpc.so.121 +OLD_LIBS+=usr/lib/libgssrpc.so.122 OLD_FILES+=usr/lib/libk5crypto.so -OLD_LIBS+=usr/lib/libk5crypto.so.121 +OLD_LIBS+=usr/lib/libk5crypto.so.122 OLD_FILES+=usr/lib/libkadm5clnt.so OLD_FILES+=usr/lib/libkadm5clnt_mit.so -OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.122 OLD_FILES+=usr/lib/libkadm5srv.so OLD_FILES+=usr/lib/libkadm5srv_mit.so -OLD_LIBS+=usr/lib/libkadm5srv_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5srv_mit.so.122 OLD_FILES+=usr/lib/libkdb5.so -OLD_LIBS+=usr/lib/libkdb5.so.121 +OLD_LIBS+=usr/lib/libkdb5.so.122 OLD_FILES+=usr/lib/libkrad.so -OLD_LIBS+=usr/lib/libkrad.so.121 +OLD_LIBS+=usr/lib/libkrad.so.122 OLD_FILES+=usr/lib/libkrb5.so -OLD_LIBS+=usr/lib/libkrb5.so.121 +OLD_LIBS+=usr/lib/libkrb5.so.122 OLD_FILES+=usr/lib/libkrb5profile.a OLD_FILES+=usr/lib/libkrb5profile.so -OLD_LIBS+=usr/lib/libkrb5profile.so.121 +OLD_LIBS+=usr/lib/libkrb5profile.so.122 OLD_FILES+=usr/lib/libkrb5support.a OLD_FILES+=usr/lib/libkrb5support.so -OLD_LIBS+=usr/lib/libkrb5support.so.121 +OLD_LIBS+=usr/lib/libkrb5support.so.122 OLD_FILES+=usr/lib/libverto.so -OLD_LIBS+=usr/lib/libverto.so.121 +OLD_LIBS+=usr/lib/libverto.so.122 OLD_FILES+=usr/libdata/pkgconfig/gssrpc.pc OLD_FILES+=usr/libdata/pkgconfig/kadm-client.pc OLD_FILES+=usr/libdata/pkgconfig/kadm-server.pc @@ -5766,36 +5770,36 @@ OLD_FILES+=usr/lib/krb5/plugins/preauth/pkinit.so OLD_FILES+=usr/lib/krb5/plugins/preauth/spake.so OLD_FILES+=usr/lib/krb5/plugins/preauth/test.so OLD_FILES+=usr/lib/krb5/plugins/tls/k5tls.so -OLD_LIBS+=usr/lib/libcom_err.so.121 -OLD_LIBS+=usr/lib/libgssapi_krb5.so.121 +OLD_LIBS+=usr/lib/libcom_err.so.122 +OLD_LIBS+=usr/lib/libgssapi_krb5.so.122 OLD_FILES+=usr/lib/libgssrpc.a OLD_FILES+=usr/lib/libgssrpc.so -OLD_LIBS+=usr/lib/libgssrpc.so.121 +OLD_LIBS+=usr/lib/libgssrpc.so.122 OLD_FILES+=usr/lib/libk5crypto.a OLD_FILES+=usr/lib/libk5crypto.so -OLD_LIBS+=usr/lib/libk5crypto.so.121 +OLD_LIBS+=usr/lib/libk5crypto.so.122 OLD_FILES+=usr/lib/libkadm5clnt_mit.a OLD_FILES+=usr/lib/libkadm5clnt_mit.so -OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5clnt_mit.so.122 OLD_FILES+=usr/lib/libkadm5srv_mit.a OLD_FILES+=usr/lib/libkadm5srv_mit.so -OLD_LIBS+=usr/lib/libkadm5srv_mit.so.121 +OLD_LIBS+=usr/lib/libkadm5srv_mit.so.122 OLD_FILES+=usr/lib/libkdb5.a OLD_FILES+=usr/lib/libkdb5.so -OLD_LIBS+=usr/lib/libkdb5.so.121 +OLD_LIBS+=usr/lib/libkdb5.so.122 OLD_FILES+=usr/lib/libkrad.so OLD_FILES+=usr/lib/libkrad.a -OLD_LIBS+=usr/lib/libkrad.so.121 -OLD_LIBS+=usr/lib/libkrb5.so.121 +OLD_LIBS+=usr/lib/libkrad.so.122 +OLD_LIBS+=usr/lib/libkrb5.so.122 OLD_FILES+=usr/lib/libkrb5profile.a OLD_FILES+=usr/lib/libkrb5profile.so -OLD_LIBS+=usr/lib/libkrb5profile.so.121 +OLD_LIBS+=usr/lib/libkrb5profile.so.122 OLD_FILES+=usr/lib/libkrb5support.a OLD_FILES+=usr/lib/libkrb5support.so -OLD_LIBS+=usr/lib/libkrb5support.so.121 +OLD_LIBS+=usr/lib/libkrb5support.so.122 OLD_FILES+=usr/lib/libverto.a OLD_FILES+=usr/lib/libverto.so -OLD_LIBS+=usr/lib/libverto.so.121 +OLD_LIBS+=usr/lib/libverto.so.122 OLD_FILES+=usr/libdata/pkgconfig/gssrpc.pc OLD_FILES+=usr/libdata/pkgconfig/kadm-client.pc OLD_FILES+=usr/libdata/pkgconfig/kadm-server.pc diff --git a/tools/build/options/WITH_LLVM_ASSERTIONS b/tools/build/options/WITH_LLVM_ASSERTIONS index 0e7fbfbda0a3..6af75221a206 100644 --- a/tools/build/options/WITH_LLVM_ASSERTIONS +++ b/tools/build/options/WITH_LLVM_ASSERTIONS @@ -1 +1,2 @@ Enable debugging assertions in LLVM. +Use when working on or requesting help with LLVM components. 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/tools/tools/vt/mkkfont/Makefile b/tools/tools/vt/mkkfont/Makefile index f9758be0ef15..1e8a9bcdafd7 100644 --- a/tools/tools/vt/mkkfont/Makefile +++ b/tools/tools/vt/mkkfont/Makefile @@ -1,4 +1,4 @@ PROG= mkkfont -MAN1= +MAN= .include <bsd.prog.mk> diff --git a/usr.bin/asa/asa.1 b/usr.bin/asa/asa.1 index da1af0e8ce84..68d0735774a6 100644 --- a/usr.bin/asa/asa.1 +++ b/usr.bin/asa/asa.1 @@ -84,8 +84,6 @@ To format the output of a program and redirect it to a line-printer: .Pp .Dl "a.out | asa | lpr" -.Sh SEE ALSO -.Xr f77 1 .Sh STANDARDS The .Nm diff --git a/usr.bin/bmake/Makefile b/usr.bin/bmake/Makefile index a8bcdfd9f859..bbceea3ae8c2 100644 --- a/usr.bin/bmake/Makefile +++ b/usr.bin/bmake/Makefile @@ -99,8 +99,6 @@ COPTS.filemon_ktrace.c+= -Wno-error=unused-parameter SUBDIR.${MK_TESTS}+= unit-tests .endif -MAN1= ${MAN} - .if ${MK_GEN_MAN:Uno} == "yes" # we use this to generate ${MAN} 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/Makefile b/usr.bin/find/Makefile index 904c08620833..48b164133bb0 100644 --- a/usr.bin/find/Makefile +++ b/usr.bin/find/Makefile @@ -3,7 +3,7 @@ PACKAGE= runtime PROG= find -SRCS= find.c function.c ls.c main.c misc.c operator.c option.c \ +SRCS= find.c function.c ls.c main.c misc.c operator.c option.c printf.c \ getdate.y YFLAGS= CFLAGS.clang+= -Werror=undef diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h index feb2e0202056..02c85d06a34c 100644 --- a/usr.bin/find/extern.h +++ b/usr.bin/find/extern.h @@ -44,6 +44,8 @@ void printlong(char *, char *, struct stat *); int queryuser(char **); OPTION *lookup_option(const char *); void finish_execplus(void); +void do_printf(PLAN *plan, FTSENT *entry, FILE *fout); + creat_f c_Xmin; creat_f c_Xtime; @@ -55,6 +57,7 @@ creat_f c_empty; creat_f c_exec; creat_f c_flags; creat_f c_follow; +creat_f c_fprint; creat_f c_fstype; creat_f c_group; creat_f c_ignore_readdir_race; @@ -68,6 +71,7 @@ creat_f c_nogroup; creat_f c_nouser; creat_f c_perm; creat_f c_print; +creat_f c_printf; creat_f c_regex; creat_f c_samefile; creat_f c_simple; @@ -90,6 +94,8 @@ exec_f f_executable; exec_f f_expr; exec_f f_false; exec_f f_flags; +exec_f f_fprint; +exec_f f_fprint0; exec_f f_fstype; exec_f f_group; exec_f f_inum; @@ -106,6 +112,7 @@ exec_f f_path; exec_f f_perm; exec_f f_print; exec_f f_print0; +exec_f f_printf; exec_f f_prune; exec_f f_quit; exec_f f_readable; diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index eb3fd4d0dbde..b16c4bcc95a2 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 23, 2024 +.Dd July 26, 2025 .Dt FIND 1 .Os .Sh NAME @@ -515,6 +515,28 @@ and none of the .Ar flags bits match those of .Ar notflags . +.It Ic -fprint Ar filename +This primary always evaluates to true. +This creates +.Ar filename +or truncates the file if it already exists. +The file is created at startup. +It writes the pathname of the current file to this file, followed +by a newline character. +The file will be empty if no files are matched. +.Pp +.It Ic -fprint0 Ar filename +This primary always evaluates to true. +This creates +.Ar filename +or truncates the file if it already exists. +The file is created at startup. +It writes the pathname of the current file to this file, followed +by an ASCII +.Dv NUL +character (character code 0). +The file will be empty if no files are matched. +.Pp .It Ic -fstype Ar type True if the file is contained in a file system of type .Ar type . @@ -821,6 +843,17 @@ It prints the pathname of the current file to standard output, followed by an ASCII .Dv NUL character (character code 0). +.It Ic -printf Ar fmt +This primary always evaluates to true. +It prints information about the file, interpreting +.Sq \ +and +.Sq % +escape sequences as described in the PRINTF FORMATS section. +Unlike +.Ic -print , +.Ic -printf +does not add a newline automatically. .It Ic -prune This primary always evaluates to true. It causes @@ -993,6 +1026,149 @@ All operands and primaries must be separate arguments to Primaries which themselves take arguments expect each argument to be a separate argument to .Nm . +.Sh PRINTF FORMATS +The following +.Sq \e +escapes are recognized: +.Bl -tag -width Ds -offset indent -compact +.It Cm \ea +Write a <bell> character. +.It Cm \eb +Write a <backspace> character. +.It Cm \ec +Writes no characters, but terminates the string and flushes the output so far +after each match. +.It Cm \ef +Write a <form-feed> character. +.It Cm \en +Write a <new-line> character. +.It Cm \er +Write a <carriage return> character. +.It Cm \et +Write a <tab> character. +.It Cm \ev +Write a <vertical tab> character. +.It Cm \e\' +Write a <single quote> character. +.It Cm \e\e +Write a backslash character. +.It Cm \e Ns Ar num +Write a byte whose +value is the 1-, 2-, or 3-digit +octal number +.Ar num . +Multibyte characters can be constructed using multiple +.Cm \e Ns Ar num +sequences. +.El +.Pp +Each format specification is introduced by the percent character +(``%''). +The remainder of the format specification includes, +in the following order: +.Bl -tag -width Ds +.It "Zero or more of the following flags:" +.Bl -tag -width Ds +.It Cm # +A `#' character, has no effect on almost all formats. +It is not yet implemented. +.It Cm \&\- +A minus sign `\-' which specifies +.Em left adjustment +of the output in the indicated field; +It is not yet implemented. +.It "Field Width:" +An optional digit string specifying a +.Em field width ; +if the output string has fewer bytes than the field width it will +be blank-padded on the left (or right, if the left-adjustment indicator +has been given) to make up the field width (note that a leading zero +is a flag, but an embedded zero is part of a field width); +It is not yet implemented. +.It Precision: +An optional period, +.Sq Cm \&.\& , +followed by an optional digit string giving a +.Em precision +which specifies the maximum number of bytes to be printed +from a string; if the digit string is missing, the precision is treated +as zero; +It is not yet implemented. +.It Format: +One or two characters, described below, which indicates the information to display. +.Bl -tag -width Ds +.It p +Path to file +.It f +Filename without directories. +.It h +Path relative to the starting point, or '.' if that's empty for some reason. +.It P +Unimplemented -- File with command line arg. +.It H +Unimplemented -- Command line arg. +.It g +gid in human readable form. +.It G +gid as a number. +.It h +uid in human readable form. +.It U +uid as a number. +.It m +File permission mode in octal. +.It M +File mode in +.Xr ls 1 +standard form. +.It k +File size in KiB (units of 1024 bytes). +.It b +File size in blocks (Always 512 byte units, even if underlying storage +size differs). +.It s +Size in bytes of the file. +.It S +Sparseness of the file. +The blocks the file occupies times 512 divided by the file size. +.It d +Depth in the tree +.It D +Device number for the file. +.It F +Unimplemented -- Filesystem type where the file resides. +.It l +Object of the symbolic link. +.It i +Inode of the file. +.It n +Number of hard links. +.It y +Unimplemented -- Type of the file +.It Y +Unimplemented -- Type of the file with loop detection +.It a +Access time of the file. +.It A +Access time of the file in strftime format. +Takes an additional argument. +.It B +Birth time of the file in strftime format. +Takes an additional argument. +.It c +Creation time of the file. +.It C +Creation time of the file in strftime format. +Takes an additional argument. +.It t +Modification time of the file. +.It T +Modification time of the file in strftime format. +Takes an additional argument. +.El +Any format not listed is not supported, though the error changes. +.El +.El .Sh ENVIRONMENT The .Ev LANG , LC_ALL , LC_COLLATE , LC_CTYPE , LC_MESSAGES @@ -1156,7 +1332,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/find/find.h b/usr.bin/find/find.h index 1664eeb9a93f..e8bb0ca8c649 100644 --- a/usr.bin/find/find.h +++ b/usr.bin/find/find.h @@ -97,6 +97,8 @@ typedef struct _plandata *creat_f(struct _option *, char ***); #define F_TIME2_B 0x00080000 /* one of -newer?B */ #endif #define F_LINK 0x00100000 /* lname or ilname */ +/* Notes about execution */ +#define F_HAS_WARNED 0x10000000 /* Has issued a warning for maybe bad input */ /* node definition */ typedef struct _plandata { @@ -133,6 +135,7 @@ typedef struct _plandata { char *_a_data[2]; /* array of char pointers */ char *_c_data; /* char pointer */ regex_t *_re_data; /* regex */ + FILE *_fprint_file; /* file stream for -fprint */ } p_un; } PLAN; #define a_data p_un._a_data @@ -160,6 +163,7 @@ typedef struct _plandata { #define e_pbsize p_un.ex._e_pbsize #define e_psizemax p_un.ex._e_psizemax #define e_next p_un.ex._e_next +#define fprint_file p_un._fprint_file typedef struct _option { const char *name; /* option name */ diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index ef610903cc00..11455b395022 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -866,6 +866,49 @@ c_follow(OPTION *option, char ***argvp __unused) return palloc(option); } +/* + * -fprint functions -- + * + * Always true, causes the current pathname to be written to + * specified file followed by a newline + */ +int +f_fprint(PLAN *plan, FTSENT *entry) +{ + fprintf(plan->fprint_file, "%s\n", entry->fts_path); + return 1; +} + +PLAN * +c_fprint(OPTION *option, char ***argvp) +{ + PLAN *new; + char *fn; + + isoutput = 1; + + new = palloc(option); + fn = nextarg(option, argvp); + new->fprint_file = fopen(fn, "w"); + if (new->fprint_file == NULL) + err(1, "fprint: cannot create %s", fn); + + return (new); +} + +/* + * -fprint0 functions -- + * + * Always true, causes the current pathname to be written to + * specified file followed by a NUL + */ +int +f_fprint0(PLAN *plan, FTSENT *entry) +{ + fprintf(plan->fprint_file, "%s%c", entry->fts_path, '\0'); + return 1; +} + #if HAVE_STRUCT_STATFS_F_FSTYPENAME /* * -fstype functions -- @@ -1389,6 +1432,36 @@ f_print0(PLAN *plan __unused, FTSENT *entry) /* c_print0 is the same as c_print */ /* + * -printf functions -- + * + * Always true. Causes information as specified in the + * argument to be written to standard output. + */ +int +f_printf(PLAN *plan, FTSENT *entry) +{ + do_printf(plan, entry, stdout); + return 1; +} + +PLAN * +c_printf(OPTION *option, char ***argvp) +{ + PLAN *new; + + isoutput = 1; + /* + * XXX We could scan the format looking for stat-dependent formats, and + * turn off the stat if there's none: `%p`/`%f`/`%h` don't need a stat. + */ + + new = palloc(option); + new->c_data = nextarg(option, argvp); + + return (new); +} + +/* * -prune functions -- * * Prune a portion of the hierarchy. diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c index 268803343a8d..fa09231a3152 100644 --- a/usr.bin/find/option.c +++ b/usr.bin/find/option.c @@ -83,8 +83,8 @@ static OPTION const options[] = { #endif // -fls { "-follow", c_follow, f_always_true, 0 }, -// -fprint -// -fprint0 + { "-fprint", c_fprint, f_fprint, 0 }, + { "-fprint0", c_fprint, f_fprint0, 0 }, // -fprintf #if HAVE_STRUCT_STATFS_F_FSTYPENAME { "-fstype", c_fstype, f_fstype, 0 }, @@ -148,7 +148,7 @@ static OPTION const options[] = { { "-perm", c_perm, f_perm, 0 }, { "-print", c_print, f_print, 0 }, { "-print0", c_print, f_print0, 0 }, -// -printf + { "-printf", c_printf, f_printf, 0 }, { "-prune", c_simple, f_prune, 0 }, { "-quit", c_simple, f_quit, 0 }, { "-readable", c_simple, f_readable, 0 }, diff --git a/usr.bin/find/printf.c b/usr.bin/find/printf.c new file mode 100644 index 000000000000..671d1d1dbb9a --- /dev/null +++ b/usr.bin/find/printf.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2023, Netflix, Inc + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/types.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <fts.h> +#include <grp.h> +#include <pwd.h> +#include <time.h> + +#include "find.h" + +/* translate \X to proper escape, or to itself if no special meaning */ +static const char *esc = "\a\bcde\fghijklm\nopq\rs\tu\v"; + +static inline bool +isoct(char c) +{ + return (c >= '0' && c <= '7'); +} + +static inline bool +isesc(char c) +{ + return (c >= 'a' && c <= 'v' && esc[c - 'a'] != c); +} + +static const char * +escape(const char *str, bool *flush, bool *warned) +{ + char c; + int value; + char *tmpstr; + size_t tmplen; + FILE *fp; + + fp = open_memstream(&tmpstr, &tmplen); + + /* + * Copy the str string into a new struct sbuf and return that expanding + * the different ANSI escape sequences. + */ + *flush = false; + for (c = *str++; c; c = *str++) { + if (c != '\\') { + putc(c, fp); + continue; + } + c = *str++; + + /* + * User error \ at end of string + */ + if (c == '\0') { + putc('\\', fp); + break; + } + + /* + * \c terminates output now and is supposed to flush the output + * too... + */ + if (c == 'c') { + *flush = true; + break; + } + + /* + * Is it octal? If so, decode up to 3 octal characters. + */ + if (isoct(c)) { + value = 0; + for (int i = 3; i-- > 0 && isoct(c); + c = *str++) { + value <<= 3; + value += c - '0'; + } + str--; + putc((char)value, fp); + continue; + } + + /* + * It's an ANSI X3.159-1989 escape, use the mini-escape lookup + * table to translate. + */ + if (isesc(c)) { + putc(esc[c - 'a'], fp); + continue; + } + + /* + * Otherwise, it's self inserting. gnu find specifically says + * not to rely on this behavior though. gnu find will issue + * a warning here, while printf(1) won't. + */ + if (!*warned) { + warn("Unknown character %c after \\.", c); + *warned = true; + } + putc(c, fp); + } + fclose(fp); + + return (tmpstr); +} + +static void +fp_ctime(FILE *fp, time_t t) +{ + char s[26]; + + ctime_r(&t, s); + s[24] = '\0'; /* kill newline, though gnu find info silent on issue */ + fputs(s, fp); +} + +/* + * Assumes all times are displayed in UTC rather than local time, gnu find info + * page silent on the issue. + * + * Also assumes that gnu find doesn't support multiple character escape sequences, + * which it's info page is also silent on. + */ +static void +fp_strftime(FILE *fp, time_t t, char mod) +{ + struct tm tm; + char buffer[128]; + char fmt[3] = "% "; + + /* + * Gnu libc extension we don't yet support -- seconds since epoch + * Used in Linux kernel build, so we kinda have to support it here + */ + if (mod == '@') { + fprintf(fp, "%ju", (uintmax_t)t); + return; + } + + gmtime_r(&t, &tm); + fmt[1] = mod; + printf("fmt is '%s'\n", fmt); + if (strftime(buffer, sizeof(buffer), fmt, &tm) == 0) + errx(1, "Format bad or data too long for buffer"); /* Can't really happen ??? */ + fputs(buffer, fp); +} + +void +do_printf(PLAN *plan, FTSENT *entry, FILE *fout) +{ + const char *fmt, *path, *pend, *all; + char c; + FILE *fp; + bool flush, warned; + struct stat *sb; + char *tmp; + size_t tmplen; + + fp = open_memstream(&tmp, &tmplen); + warned = (plan->flags & F_HAS_WARNED) != 0; + all = fmt = escape(plan->c_data, &flush, &warned); + if (warned) + plan->flags |= F_HAS_WARNED; + sb = entry->fts_statp; + for (c = *fmt++; c; c = *fmt++) { + if (c != '%') { + putc(c, fp); + continue; + } + c = *fmt++; + /* Style(9) deviation: case order same as gnu find info doc */ + switch (c) { + case '%': + putc(c, fp); + break; + case 'p': /* Path to file */ + fputs(entry->fts_path, fp); + break; + case 'f': /* filename w/o dirs */ + fputs(entry->fts_name, fp); + break; + case 'h': + /* + * path, relative to the starting point, of the file, or + * '.' if that's empty for some reason. + */ + path = entry->fts_path; + pend = strrchr(path, '/'); + if (pend == NULL) + putc('.', fp); + else { + char *t = malloc(pend - path + 1); + memcpy(t, path, pend - path); + t[pend - path] = '\0'; + fputs(t, fp); + free(t); + } + break; + case 'P': /* file with command line arg rm'd -- HOW? fts_parent? */ + errx(1, "%%%c is unimplemented", c); + case 'H': /* Command line arg -- HOW? */ + errx(1, "%%%c is unimplemented", c); + case 'g': /* gid human readable */ + fputs(group_from_gid(sb->st_gid, 0), fp); + break; + case 'G': /* gid numeric */ + fprintf(fp, "%d", sb->st_gid); + break; + case 'u': /* uid human readable */ + fputs(user_from_uid(sb->st_uid, 0), fp); + break; + case 'U': /* uid numeric */ + fprintf(fp, "%d", sb->st_uid); + break; + case 'm': /* mode in octal */ + fprintf(fp, "%o", sb->st_mode & 07777); + break; + case 'M': { /* Mode in ls-standard form */ + char mode[12]; + strmode(sb->st_mode, mode); + fputs(mode, fp); + break; + } + case 'k': /* kbytes used by file */ + fprintf(fp, "%jd", (intmax_t)sb->st_blocks / 2); + break; + case 'b': /* blocks used by file */ + fprintf(fp, "%jd", (intmax_t)sb->st_blocks); + break; + case 's': /* size in bytes of file */ + fprintf(fp, "%ju", (uintmax_t)sb->st_size); + break; + case 'S': /* sparseness of file */ + fprintf(fp, "%3.1f", + (float)sb->st_blocks * 512 / (float)sb->st_size); + break; + case 'd': /* Depth in tree */ + fprintf(fp, "%ld", entry->fts_level); + break; + case 'D': /* device number */ + fprintf(fp, "%ju", (uintmax_t)sb->st_dev); + break; + case 'F': /* Filesystem type */ + errx(1, "%%%c is unimplemented", c); + case 'l': /* object of symbolic link */ + fprintf(fp, "%s", entry->fts_accpath); + break; + case 'i': /* inode # */ + fprintf(fp, "%ju", (uintmax_t)sb->st_ino); + break; + case 'n': /* number of hard links */ + fprintf(fp, "%ju", (uintmax_t)sb->st_nlink); + break; + case 'y': /* -type of file, incl 'l' */ + errx(1, "%%%c is unimplemented", c); + case 'Y': /* -type of file, following 'l' types L loop ? error */ + errx(1, "%%%c is unimplemented", c); + case 'a': /* access time ctime */ + fp_ctime(fp, sb->st_atime); + break; + case 'A': /* access time with next char strftime format */ + fp_strftime(fp, sb->st_atime, *fmt++); + break; + case 'B': /* birth time with next char strftime format */ +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + if (sb->st_birthtime != 0) + fp_strftime(fp, sb->st_birthtime, *fmt); +#endif + fmt++; + break; /* blank on systems that don't support it */ + case 'c': /* status change time ctime */ + fp_ctime(fp, sb->st_ctime); + break; + case 'C': /* status change time with next char strftime format */ + fp_strftime(fp, sb->st_ctime, *fmt++); + break; + case 't': /* modification change time ctime */ + fp_ctime(fp, sb->st_mtime); + break; + case 'T': /* modification time with next char strftime format */ + fp_strftime(fp, sb->st_mtime, *fmt++); + break; + case 'Z': /* empty string for compat SELinux context string */ + break; + /* Modifier parsing here, but also need to modify above somehow */ + case '#': case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': case '.': + errx(1, "Format modifier %c not yet supported: '%s'", c, all); + /* Any FeeeBSD-specific modifications here -- none yet */ + default: + errx(1, "Unknown format %c '%s'", c, all); + } + } + fputs(tmp, fout); + if (flush) + fflush(fout); + free(__DECONST(char *, fmt)); + free(tmp); +} diff --git a/usr.bin/fortune/datfiles/freebsd-tips b/usr.bin/fortune/datfiles/freebsd-tips index 1e9501e3a6fb..6a2b59ff5fa7 100644 --- a/usr.bin/fortune/datfiles/freebsd-tips +++ b/usr.bin/fortune/datfiles/freebsd-tips @@ -555,7 +555,7 @@ Use "sysrc name=value" to add an entry and "sysrc -x name" to delete an entry. You can upload the dmesg of your system to help developers get an overview of commonly used hardware and peripherals for FreeBSD. Use the curl package to upload it like this: curl -v -d "nickname=$USER" -d "description=FreeBSD/$(uname -m) on \ -$(kenv smbios.system.maker) $(kenv smbios.system.product)" -d "do=addd" \ +$(kenv smbios.system.maker) $(kenv smbios.system.product)" -d "do=add" \ --data-urlencode 'dmesg@/var/run/dmesg.boot' http://dmesgd.nycbug.org/index.cgi % Want to know how much memory (in bytes) your machine has installed? Let diff --git a/usr.bin/fstat/Makefile b/usr.bin/fstat/Makefile index fa51a92eb52f..f8617fd0c6a4 100644 --- a/usr.bin/fstat/Makefile +++ b/usr.bin/fstat/Makefile @@ -3,6 +3,6 @@ SRCS= fstat.c fuser.c main.c LINKS= ${BINDIR}/fstat ${BINDIR}/fuser LIBADD= procstat -MAN1= fuser.1 fstat.1 +MAN= fuser.1 fstat.1 .include <bsd.prog.mk> diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile index 2204758ece5a..c72b86656148 100644 --- a/usr.bin/grep/Makefile +++ b/usr.bin/grep/Makefile @@ -6,7 +6,7 @@ PACKAGE= runtime PROG= grep -MAN1= grep.1 zgrep.1 +MAN= grep.1 zgrep.1 SRCS= file.c grep.c queue.c util.c 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 1a2c786e90aa..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. @@ -416,7 +416,8 @@ When used with or .Fl 6 , limit the output to IPv4 or IPv6 routes respectively. -This option provides details about individual nexthop addresses used in routing decisions. +This option provides details about individual nexthop addresses +used in routing decisions. .It Xo .Bk -words .Nm netstat @@ -430,7 +431,8 @@ When used with or .Fl 6 , restrict the output to IPv4 or IPv6 nexthop groups respectively. -This option shows grouped nexthop entries for multipath or load-balanced routing setups. +This option shows grouped nexthop entries for multipath or +load-balanced routing setups. .It Xo .Bk -words .Nm @@ -926,25 +928,25 @@ binary is not available in the .Sh EXAMPLES Show packet traffic information (packets, bytes, errors, packet drops, etc) for interface re0 updated every 2 seconds and exit after 5 outputs: -.Bd -literal -offset indent -$ netstat -w 2 -q 5 -I re0 -.Ed +.Pp +.Dl netstat -w 2 -q 5 -I re0 .Pp Show statistics for ICMP on any interface: -.Bd -literal -offset indent -$ netstat -s -p icmp -.Ed +.Pp +.Dl netstat -s -p icmp .Pp Show routing tables: -.Bd -literal -offset indent -$ netstat -r -.Ed +.Pp +.Dl netstat -r .Pp Same as above, but without resolving numeric addresses and port numbers to names: -.Bd -literal -offset indent -$ netstat -rn -.Ed +.Pp +.Dl netstat -rn +.Pp +Show IPv4 listening sockets: +.Pp +.Dl netstat -4l .Sh SEE ALSO .Xr fstat 1 , .Xr nfsstat 1 , @@ -952,7 +954,7 @@ $ netstat -rn .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/pom/pom.6 b/usr.bin/pom/pom.6 index a3dc68b0a46b..a4dbdde2d4f5 100644 --- a/usr.bin/pom/pom.6 +++ b/usr.bin/pom/pom.6 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 14, 2010 +.Dd July 24, 2025 .Dt POM 6 .Os .Sh NAME @@ -60,4 +60,10 @@ but not has been specified, it will calculate the phase of the moon on that day at midnight. .Sh SEE ALSO -`Practical Astronomy with Your Calculator' by Duffett-Smith. +.Rs +.%A Peter Duffett-Smith +.%B Practical Astronomy with Your Calculator +.%I Cambridge University Press +.%C Cambridge, UK +.%D 1979 +.Re diff --git a/usr.bin/pom/pom.c b/usr.bin/pom/pom.c index db0033373b47..bcfbcadc8238 100644 --- a/usr.bin/pom/pom.c +++ b/usr.bin/pom/pom.c @@ -83,6 +83,7 @@ main(int argc, char **argv) err(1, "unable to limit capabitilities for stdio"); caph_cache_catpages(); + caph_cache_tzdata(); if (caph_enter() < 0) err(1, "unable to enter capability mode"); 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/sdiff/Makefile b/usr.bin/sdiff/Makefile index 03587f373098..af9a037e9a58 100644 --- a/usr.bin/sdiff/Makefile +++ b/usr.bin/sdiff/Makefile @@ -3,7 +3,7 @@ PROG= sdiff SRCS= edit.c sdiff.c -MAN1= sdiff.1 +MAN= sdiff.1 HAS_TESTS= SUBDIR.${MK_TESTS}+= tests 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..9b1860246de9 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 @@ -189,7 +189,7 @@ This option makes them visible. Set the delay between screen updates to .Ar time seconds, which may be fractional. -The default delay between updates is 1 second. +The default delay between updates is 2 seconds. .It Fl T Toggle displaying thread ID (tid) instead of process id (pid). .It Fl t @@ -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/vtfontcvt/Makefile b/usr.bin/vtfontcvt/Makefile index de011660ca28..13e60c406b26 100644 --- a/usr.bin/vtfontcvt/Makefile +++ b/usr.bin/vtfontcvt/Makefile @@ -1,6 +1,6 @@ PROG= vtfontcvt SRCS= vtfontcvt.c lz4.c -MAN8= vtfontcvt.8 +MAN= vtfontcvt.8 # lz4 compression functionality .PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4 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.bin/xargs/tests/Makefile b/usr.bin/xargs/tests/Makefile index b1e6782069de..9fa8ff11fac2 100644 --- a/usr.bin/xargs/tests/Makefile +++ b/usr.bin/xargs/tests/Makefile @@ -1,6 +1,6 @@ PACKAGE= tests -TAP_TESTS_SH= legacy_test +ATF_TESTS_SH= xargs_test ${PACKAGE}FILES+= regress.0.in ${PACKAGE}FILES+= regress.0.out @@ -17,12 +17,11 @@ ${PACKAGE}FILES+= regress.R-1.out ${PACKAGE}FILES+= regress.in ${PACKAGE}FILES+= regress.n1.out ${PACKAGE}FILES+= regress.n2.out -${PACKAGE}FILES+= regress.n2147483647.out +${PACKAGE}FILES+= regress.nargmax.out ${PACKAGE}FILES+= regress.n2P0.out ${PACKAGE}FILES+= regress.n3.out ${PACKAGE}FILES+= regress.normal.out ${PACKAGE}FILES+= regress.quotes.in ${PACKAGE}FILES+= regress.quotes.out -${PACKAGE}FILES+= regress.sh .include <bsd.test.mk> diff --git a/usr.bin/xargs/tests/legacy_test.sh b/usr.bin/xargs/tests/legacy_test.sh deleted file mode 100644 index 3c7842d07bf0..000000000000 --- a/usr.bin/xargs/tests/legacy_test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -SRCDIR="$(dirname "${0}")"; export SRCDIR - -m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh diff --git a/usr.bin/xargs/tests/regress.n2147483647.out b/usr.bin/xargs/tests/regress.nargmax.out index cc32a92a2199..cc32a92a2199 100644 --- a/usr.bin/xargs/tests/regress.n2147483647.out +++ b/usr.bin/xargs/tests/regress.nargmax.out diff --git a/usr.bin/xargs/tests/regress.sh b/usr.bin/xargs/tests/regress.sh deleted file mode 100644 index 9b4839d2a8ec..000000000000 --- a/usr.bin/xargs/tests/regress.sh +++ /dev/null @@ -1,32 +0,0 @@ - -echo 1..21 - -REGRESSION_START($1) - -REGRESSION_TEST(`normal', `xargs echo The <${SRCDIR}/regress.in') -REGRESSION_TEST(`I', `xargs -I% echo The % % % %% % % <${SRCDIR}/regress.in') -REGRESSION_TEST(`J', `xargs -J% echo The % again. <${SRCDIR}/regress.in') -REGRESSION_TEST(`L', `xargs -L3 echo <${SRCDIR}/regress.in') -REGRESSION_TEST(`P1', `xargs -P1 echo <${SRCDIR}/regress.in') -REGRESSION_TEST(`R', `xargs -I% -R1 echo The % % % %% % % <${SRCDIR}/regress.in') -REGRESSION_TEST(`R-1', `xargs -I% -R-1 echo The % % % %% % % <${SRCDIR}/regress.in') -REGRESSION_TEST(`n1', `xargs -n1 echo <${SRCDIR}/regress.in') -REGRESSION_TEST(`n2', `xargs -n2 echo <${SRCDIR}/regress.in') -# This test may consume a large amount of memory, making it unsuited to CI -# environments. Disable it for now. -#REGRESSION_TEST(`n2147483647', `xargs -n2147483647 <${SRCDIR}/regress.in') -REGRESSION_TEST(`n2P0',`xargs -n2 -P0 echo <${SRCDIR}/regress.in | sort') -REGRESSION_TEST(`n3', `xargs -n3 echo <${SRCDIR}/regress.in') -REGRESSION_TEST(`0', `xargs -0 -n1 echo <${SRCDIR}/regress.0.in') -REGRESSION_TEST(`0I', `xargs -0 -I% echo The % %% % <${SRCDIR}/regress.0.in') -REGRESSION_TEST(`0J', `xargs -0 -J% echo The % again. <${SRCDIR}/regress.0.in') -REGRESSION_TEST(`0L', `xargs -0 -L2 echo <${SRCDIR}/regress.0.in') -REGRESSION_TEST(`0P1', `xargs -0 -P1 echo <${SRCDIR}/regress.0.in') -REGRESSION_TEST(`quotes', `xargs -n1 echo <${SRCDIR}/regress.quotes.in') - -REGRESSION_TEST_FREEFORM(`parallel1', `echo /var/empty /var/empty | xargs -n1 -P2 test -d; [ $? = 0 ]') -REGRESSION_TEST_FREEFORM(`parallel2', `echo /var/empty /var/empty/nodir | xargs -n1 -P2 test -d; [ $? = 1 ]') -REGRESSION_TEST_FREEFORM(`parallel3', `echo /var/empty/nodir /var/empty | xargs -n1 -P2 test -d; [ $? = 1 ]') -REGRESSION_TEST_FREEFORM(`parallel4', `echo /var/empty/nodir /var/empty/nodir | xargs -n1 -P2 test -d; [ $? = 1 ]') - -REGRESSION_END() diff --git a/usr.bin/xargs/tests/xargs_test.sh b/usr.bin/xargs/tests/xargs_test.sh new file mode 100755 index 000000000000..12c9407a7e45 --- /dev/null +++ b/usr.bin/xargs/tests/xargs_test.sh @@ -0,0 +1,193 @@ +# +# Copyright (c) 2002 Juli Mallett <jmallett@FreeBSD.org> +# Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +SRCDIR=$(atf_get_srcdir) + +atf_test_case xargs_normal +xargs_normal_body() +{ + atf_check -o file:${SRCDIR}/regress.normal.out \ + xargs echo The <${SRCDIR}/regress.in +} + +atf_test_case xargs_I +xargs_I_body() +{ + atf_check -o file:${SRCDIR}/regress.I.out \ + xargs -I% echo The % % % %% % % <${SRCDIR}/regress.in +} + +atf_test_case xargs_J +xargs_J_body() +{ + atf_check -o file:${SRCDIR}/regress.J.out \ + xargs -J% echo The % again. <${SRCDIR}/regress.in +} + +atf_test_case xargs_L +xargs_L_body() +{ + atf_check -o file:${SRCDIR}/regress.L.out \ + xargs -L3 echo <${SRCDIR}/regress.in +} + +atf_test_case xargs_P1 +xargs_P1_body() +{ + atf_check -o file:${SRCDIR}/regress.P1.out \ + xargs -P1 echo <${SRCDIR}/regress.in +} + +atf_test_case xargs_R +xargs_R_body() +{ + atf_check -o file:${SRCDIR}/regress.R.out \ + xargs -I% -R1 echo The % % % %% % % <${SRCDIR}/regress.in +} + +atf_test_case xargs_R_1 +xargs_R_1_body() +{ + atf_check -o file:${SRCDIR}/regress.R-1.out \ + xargs -I% -R-1 echo The % % % %% % % <${SRCDIR}/regress.in +} + +atf_test_case xargs_n1 +xargs_n1_body() +{ + atf_check -o file:${SRCDIR}/regress.n1.out \ + xargs -n1 echo <${SRCDIR}/regress.in +} + +atf_test_case xargs_n2 +xargs_n2_body() +{ + atf_check -o file:${SRCDIR}/regress.n2.out \ + xargs -n2 echo <${SRCDIR}/regress.in +} + +atf_test_case xargs_nargmax +xargs_nargmax_body() +{ + argmax=$(sysctl -n kern.argmax) + atf_check -o file:${SRCDIR}/regress.nargmax.out \ + xargs -n$((argmax)) <${SRCDIR}/regress.in + atf_check -s exit:1 -e match:"too large" \ + xargs -n$((argmax+1)) <${SRCDIR}/regress.in +} + +atf_test_case xargs_n2P0 +xargs_n2P0_body() +{ + atf_check -o save:regress.out \ + xargs -n2 -P0 echo <${SRCDIR}/regress.in + atf_check -o file:${SRCDIR}/regress.n2P0.out \ + sort regress.out +} + +atf_test_case xargs_n3 +xargs_n3_body() +{ + atf_check -o file:${SRCDIR}/regress.n3.out \ + xargs -n3 echo <${SRCDIR}/regress.in +} + +atf_test_case xargs_0 +xargs_0_body() +{ + atf_check -o file:${SRCDIR}/regress.0.out \ + xargs -0 -n1 echo <${SRCDIR}/regress.0.in +} + +atf_test_case xargs_0I +xargs_0I_body() +{ + atf_check -o file:${SRCDIR}/regress.0I.out \ + xargs -0 -I% echo The % %% % <${SRCDIR}/regress.0.in +} + +atf_test_case xargs_0J +xargs_0J_body() +{ + atf_check -o file:${SRCDIR}/regress.0J.out \ + xargs -0 -J% echo The % again. <${SRCDIR}/regress.0.in +} + +atf_test_case xargs_0L +xargs_0L_body() +{ + atf_check -o file:${SRCDIR}/regress.0L.out \ + xargs -0 -L2 echo <${SRCDIR}/regress.0.in +} + +atf_test_case xargs_0P1 +xargs_0P1_body() +{ + atf_check -o file:${SRCDIR}/regress.0P1.out \ + xargs -0 -P1 echo <${SRCDIR}/regress.0.in +} + +atf_test_case xargs_quotes +xargs_quotes_body() +{ + atf_check -o file:${SRCDIR}/regress.quotes.out \ + xargs -n1 echo <${SRCDIR}/regress.quotes.in +} + +atf_test_case xargs_parallel1 +xargs_parallel1_body() +{ + echo /var/empty /var/empty >input + atf_check xargs -n1 -P2 test -d <input +} + +atf_test_case xargs_parallel2 +xargs_parallel2_body() +{ + echo /var/empty /var/empty/nodir >input + atf_check -s exit:1 xargs -n1 -P2 test -d <input +} + +atf_test_case xargs_parallel3 +xargs_parallel3_body() +{ + echo /var/empty/nodir /var/empty >input + atf_check -s exit:1 xargs -n1 -P2 test -d <input +} + +atf_test_case xargs_parallel4 +xargs_parallel4_body() +{ + echo /var/empty/nodir /var/empty/nodir >input + atf_check -s exit:1 xargs -n1 -P2 test -d <input +} + +atf_init_test_cases() +{ + atf_add_test_case xargs_normal + atf_add_test_case xargs_I + atf_add_test_case xargs_J + atf_add_test_case xargs_L + atf_add_test_case xargs_P1 + atf_add_test_case xargs_R + atf_add_test_case xargs_R_1 + atf_add_test_case xargs_n1 + atf_add_test_case xargs_n2 + atf_add_test_case xargs_nargmax + atf_add_test_case xargs_n2P0 + atf_add_test_case xargs_n3 + atf_add_test_case xargs_0 + atf_add_test_case xargs_0I + atf_add_test_case xargs_0J + atf_add_test_case xargs_0L + atf_add_test_case xargs_0P1 + atf_add_test_case xargs_quotes + atf_add_test_case xargs_parallel1 + atf_add_test_case xargs_parallel2 + atf_add_test_case xargs_parallel3 + atf_add_test_case xargs_parallel4 +} diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c index 237beff26504..2a7f026e5066 100644 --- a/usr.bin/xargs/xargs.c +++ b/usr.bin/xargs/xargs.c @@ -166,7 +166,7 @@ main(int argc, char *argv[]) break; case 'n': nflag = 1; - nargs = (int)strtonum(optarg, 1, INT_MAX, &errstr); + nargs = (int)strtonum(optarg, 1, arg_max, &errstr); if (errstr) errx(1, "-%c %s: %s", ch, optarg, errstr); break; 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/amd64/xmsr.c b/usr.sbin/bhyve/amd64/xmsr.c index cd80e4ef782e..7c174728f4fa 100644 --- a/usr.sbin/bhyve/amd64/xmsr.c +++ b/usr.sbin/bhyve/amd64/xmsr.c @@ -204,6 +204,15 @@ emulate_rdmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t *val) *val = 1; break; + case MSR_VM_CR: + /* + * We currently don't support nested virt. + * Windows seems to ignore the cpuid bits and reads this + * MSR anyways. + */ + *val = VM_CR_SVMDIS; + break; + default: error = -1; break; 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/bluetooth/bluetooth-config/bluetooth-config.sh b/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh index 48a399a82fc7..148325fcecbc 100755 --- a/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh +++ b/usr.sbin/bluetooth/bluetooth-config/bluetooth-config.sh @@ -17,7 +17,7 @@ main() { unset node device started bdaddresses retry # Only one command at the moment is scan (+ add) -[ "$#" -eq 1 -a "$1" = "scan" ] || print_syntax +[ "$1" = "scan" ] || print_syntax shift # Get command line options @@ -28,6 +28,12 @@ while getopts :d:n: arg; do ?) print_syntax;; esac done +shift "$((OPTIND-1))" + +# If there's leftover parameters, print usage +[ "$#" -eq 0 ] || print_syntax +shift + # No use running without super user rights if [ $( id -u ) -ne 0 ]; then diff --git a/usr.sbin/bluetooth/sdpd/server.c b/usr.sbin/bluetooth/sdpd/server.c index ab398cd9339f..05a4cb5f0236 100644 --- a/usr.sbin/bluetooth/sdpd/server.c +++ b/usr.sbin/bluetooth/sdpd/server.c @@ -345,14 +345,12 @@ server_accept_client(server_p srv, int32_t fd) return; } } else { - struct xucred cr; + uid_t uid; + gid_t gid; struct passwd *pw; /* Get peer's credentials */ - memset(&cr, 0, sizeof(cr)); - size = sizeof(cr); - - if (getsockopt(cfd, 0, LOCAL_PEERCRED, &cr, &size) < 0) { + if (getpeereid(cfd, &uid, &gid) < 0) { log_err("Could not get peer's credentials. %s (%d)", strerror(errno), errno); close(cfd); @@ -360,12 +358,12 @@ server_accept_client(server_p srv, int32_t fd) } /* Check credentials */ - pw = getpwuid(cr.cr_uid); + pw = getpwuid(uid); if (pw != NULL) priv = (strcmp(pw->pw_name, "root") == 0); else log_warning("Could not verify credentials for uid %d", - cr.cr_uid); + uid); memcpy(&srv->req_sa.l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(srv->req_sa.l2cap_bdaddr)); diff --git a/usr.sbin/bsdinstall/Makefile b/usr.sbin/bsdinstall/Makefile index 75db149b814b..e5bb3197fa05 100644 --- a/usr.sbin/bsdinstall/Makefile +++ b/usr.sbin/bsdinstall/Makefile @@ -22,8 +22,11 @@ REVISION?= ${_REVISION} .if ${BRANCH} == CURRENT || ${BRANCH} == STABLE SUBURL= base_latest -.else +.elif ${BRANCH} == RELEASE SUBURL= base_release_${REVISION:C/[0-9]+\.//} +.else +.warning Invalid branch "${BRANCH}" +SUBURL= base_latest .endif FreeBSD-base.conf: FreeBSD-base.conf.in diff --git a/usr.sbin/bsdinstall/scripts/bootconfig b/usr.sbin/bsdinstall/scripts/bootconfig index 9b330801e409..41243ad14b9b 100755 --- a/usr.sbin/bsdinstall/scripts/bootconfig +++ b/usr.sbin/bsdinstall/scripts/bootconfig @@ -74,7 +74,7 @@ update_uefi_bootentry() fi $DIALOG --backtitle "$OSNAME Installer" --title 'Boot Configuration' \ - --yesno "There are multiple \"$OSNAME\" EFI boot entries. Would you like to remove them all and add a new one?" 0 0 + --yesno "One or more \"$OSNAME\" EFI boot manager entries already exist. Would you like to remove them all and add a new one?" 0 0 if [ $? -eq $DIALOG_OK ]; then for entry in $(efibootmgr | awk "\$NF == \"$EFI_LABEL_NAME\" { sub(/.*Boot/,\"\", \$1); sub(/\*/,\"\", \$1); print \$1 }"); do efibootmgr -B -b ${entry} 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/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 493f137092ec..60feec28e888 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -86,7 +86,7 @@ f_include $BSDCFG_SHARE/variable.subr # # Create a separate boot pool? -# NB: Automatically set when using geli(8) or MBR +# NB: Automatically set when using geli(8) # : ${ZFSBOOT_BOOT_POOL=} @@ -96,12 +96,12 @@ f_include $BSDCFG_SHARE/variable.subr : ${ZFSBOOT_BOOT_POOL_CREATE_OPTIONS:=} # -# Default name for boot pool when enabled (e.g., geli(8) or MBR) +# Default name for boot pool when enabled (e.g., geli(8)) # : ${ZFSBOOT_BOOT_POOL_NAME:=bootpool} # -# Default size for boot pool when enabled (e.g., geli(8) or MBR) +# Default size for boot pool when enabled (e.g., geli(8)) # : ${ZFSBOOT_BOOT_POOL_SIZE:=2g} @@ -790,7 +790,7 @@ zfs_create_diskpart() # Check for unknown partition scheme before proceeding further case "$ZFSBOOT_PARTITION_SCHEME" in - ""|MBR|GPT*) : known good ;; + ""|GPT*) : known good ;; *) f_dprintf "$funcname: %s is an unsupported partition scheme" \ "$ZFSBOOT_PARTITION_SCHEME" @@ -825,14 +825,11 @@ zfs_create_diskpart() # # Lay down the desired type of partition scheme # - local setsize mbrindex align_small align_big + local setsize align_small align_big # # If user has requested 4 K alignment, add these params to the # gpart add calls. With GPT, we align large partitions to 1 M for - # improved performance on SSDs. MBR does not always play well with gaps - # between partitions, so all alignment is only 4k for that case. - # With MBR, we align the BSD partition that contains the MBR, otherwise - # the system fails to boot. + # improved performance on SSDs. # if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then align_small="-a 4k" @@ -974,90 +971,6 @@ zfs_create_diskpart() /dev/$disk$targetpart ;; - MBR) f_dprintf "$funcname: Creating MBR layout..." - # - # Enable boot pool if encryption is desired - # - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && ZFSBOOT_BOOT_POOL=1 - # - # 1. Create MBR layout (no labels) - # - f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk || - return $FAILURE - f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \ - $disk || return $FAILURE - - # - # 2. Add freebsd slice with all available space - # - f_eval_catch $funcname gpart "$GPART_ADD_ALIGN" \ - "$align_small" freebsd $disk || return $FAILURE - f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 $disk || - return $FAILURE - # Pedantically nuke any old labels - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/${disk}s1 - # Pedantically nuke any old scheme - f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" ${disk}s1 - - # - # 3. Write BSD scheme to the freebsd slice - # - f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 || - return $FAILURE - - # NB: ZFS pools will use s1a (no labels) - bootpart=s1a swappart=s1b targetpart=s1d mbrindex=4 - - # - # Always prepare a boot pool on MBR - # Do not align this partition, there must not be a gap - # - ZFSBOOT_BOOT_POOL=1 - f_eval_catch $funcname gpart \ - "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \ - "" 1 freebsd-zfs ${bootsize}b ${disk}s1 || - return $FAILURE - # Pedantically nuke any old labels - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/$disk$bootpart - if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then - # Pedantically detach targetpart for later - f_eval_catch -d $funcname geli \ - "$GELI_DETACH_F" \ - /dev/$disk$targetpart - fi - - # - # 4. Add freebsd-swap partition - # - if [ ${swapsize:-0} -gt 0 ]; then - f_eval_catch $funcname gpart \ - "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \ - "$align_small" 2 freebsd-swap \ - ${swapsize}b ${disk}s1 || return $FAILURE - # Pedantically nuke any old labels on the swap - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/${disk}s1b - fi - - # - # 5. Add freebsd-zfs partition for zroot - # - if [ "$ZFSBOOT_POOL_SIZE" ]; then - f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \ - "$align_small" $mbrindex freebsd-zfs $ZFSBOOT_POOL_SIZE ${disk}s1 || return $FAILURE - else - f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_INDEX" \ - "$align_small" $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE - fi - f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ - /dev/$disk$targetpart # Pedantic - f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /boot/zfsboot /dev/${disk}s1 count=1 || - return $FAILURE - ;; - esac # $ZFSBOOT_PARTITION_SCHEME # Update fstab(5) @@ -1102,7 +1015,7 @@ zfs_create_boot() local zroot_vdevtype="$2" local zroot_vdevs= # Calculated below local swap_devs= # Calculated below - local boot_vdevs= # Used for geli(8) and/or MBR layouts + local boot_vdevs= # Used for geli(8) layouts shift 2 # poolname vdev_type local disks="$*" disk local isswapmirror @@ -1191,7 +1104,6 @@ zfs_create_boot() f_dprintf "$funcname: With 4K sectors..." f_eval_catch $funcname sysctl "$SYSCTL_ZFS_MIN_ASHIFT_12" \ || return $FAILURE - sysctl kern.geom.part.mbr.enforce_chs=0 fi local n=0 for disk in $disks; do @@ -1415,40 +1327,6 @@ zfs_create_boot() "bootfs=\"$zroot_name/$zroot_bootfs\"" "$zroot_name" || return $FAILURE - # MBR boot loader touch-up - if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then - # Export the pool(s) - f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..." - f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$zroot_name" || - return $FAILURE - if [ "$ZFSBOOT_BOOT_POOL" ]; then - f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \ - "$bootpool_name" || return $FAILURE - fi - - f_dprintf "$funcname: Updating MBR boot loader on disks..." - # Stick the ZFS boot loader in the "convenient hole" after - # the ZFS internal metadata - for disk in $disks; do - f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ - /boot/zfsboot /dev/$disk$bootpart \ - "skip=1 seek=1024" || return $FAILURE - done - - # Re-import the ZFS pool(s) - f_dprintf "$funcname: Re-importing ZFS pool(s)..." - f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ - "-o altroot=\"$BSDINSTALL_CHROOT\"" \ - "$zroot_name" || return $FAILURE - if [ "$ZFSBOOT_BOOT_POOL" ]; then - # Import the bootpool, but do not mount it yet - f_eval_catch $funcname zpool \ - "$ZPOOL_IMPORT_WITH_OPTIONS" \ - "-o altroot=\"$BSDINSTALL_CHROOT\" -N" \ - "$bootpool_name" || return $FAILURE - fi - fi - # Remount bootpool and create symlink(s) if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch $funcname zfs "$ZFS_MOUNT" "$bootpool_name" || @@ -1793,7 +1671,7 @@ while :; do fi ;; ?" $msg_partition_scheme") - # Toggle between GPT (BIOS), GPT (UEFI) and MBR + # Toggle between partition schemes if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" -a \ "$ZFSBOOT_BOOT_TYPE" = "BIOS" ] then @@ -1805,9 +1683,6 @@ while :; do ZFSBOOT_PARTITION_SCHEME="GPT" ZFSBOOT_BOOT_TYPE="BIOS+UEFI" elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" ]; then - ZFSBOOT_PARTITION_SCHEME="MBR" - ZFSBOOT_BOOT_TYPE="BIOS" - elif [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then ZFSBOOT_PARTITION_SCHEME="GPT + Active" ZFSBOOT_BOOT_TYPE="BIOS" elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then diff --git a/usr.sbin/bsnmpd/bsnmpd/Makefile b/usr.sbin/bsnmpd/bsnmpd/Makefile index e7c7a87eec7c..601fc31ec475 100644 --- a/usr.sbin/bsnmpd/bsnmpd/Makefile +++ b/usr.sbin/bsnmpd/bsnmpd/Makefile @@ -9,7 +9,7 @@ CONTRIB=${SRCTOP}/contrib/bsnmp CONFS= snmpd.config CONFSMODE= 600 PROG= bsnmpd -SRCS= main.c action.c config.c export.c trap.c trans_udp.c trans_lsock.c +SRCS= main.c action.c config.c export.c trap.c trans_lsock.c SRCS+= trans_inet.c oid.h tree.c tree.h XSYM= snmpMIB begemotSnmpdModuleTable begemotSnmpd begemotTrapSinkTable \ sysUpTime snmpTrapOID coldStart authenticationFailure \ 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..d8fbb55290a8 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); } @@ -890,12 +881,11 @@ parse_local_path(char *opt_arg) { assert(opt_arg != NULL); - if (sizeof(opt_arg) > sizeof(SNMP_LOCAL_PATH)) { + if (strlcpy(snmp_client.local_path, opt_arg, + sizeof(snmp_client.local_path)) >= sizeof(snmp_client.local_path)) { warnx("Filename too long - %s", opt_arg); return (-1); } - - strlcpy(snmp_client.local_path, opt_arg, sizeof(SNMP_LOCAL_PATH)); 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/chroot/chroot.c b/usr.sbin/chroot/chroot.c index 32becaf12588..bd4932ee9b48 100644 --- a/usr.sbin/chroot/chroot.c +++ b/usr.sbin/chroot/chroot.c @@ -111,7 +111,12 @@ main(int argc, char *argv[]) ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL) err(1, "malloc"); - for (gids = 0; + /* Populate the egid slot in our groups to avoid accidents. */ + if (gid == 0) + gidlist[0] = getegid(); + else + gidlist[0] = gid; + for (gids = 1; (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) { if (*p == '\0') continue; 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/devinfo/devinfo.c b/usr.sbin/devinfo/devinfo.c index 629a04ba6687..4163151ec840 100644 --- a/usr.sbin/devinfo/devinfo.c +++ b/usr.sbin/devinfo/devinfo.c @@ -100,7 +100,7 @@ print_kvlist(char *s) while ((kv = strsep(©, " ")) != NULL) { char* k = strsep(&kv, "="); - xo_emit("{ea:%s/%s} {d:%s}={d:%s}", k, kv, k, kv); + xo_emit("{ea:%s/%s} {d:key/%s}={d:value/%s}", k, kv, k, kv); } free(copy); } @@ -200,7 +200,7 @@ print_device_rman_resources(struct devinfo_rman *rman, void *arg) /* there are, print header */ safe_desc = xml_safe_string(rman->dm_desc); print_indent(indent); - xo_emit("{d:%s}:\n", rman->dm_desc); + xo_emit("<{:description/%s}>\n", rman->dm_desc); xo_open_list(safe_desc); /* print resources */ @@ -220,8 +220,7 @@ print_device_props(struct devinfo_dev *dev) { if (vflag) { if (*dev->dd_desc) { - xo_emit(" <{d:%s}>", dev->dd_desc); - xo_emit("{e:description/%s}", dev->dd_desc); + xo_emit("<{:description/%s}>", dev->dd_desc); } if (*dev->dd_pnpinfo) { xo_open_container("pnpinfo"); @@ -273,7 +272,7 @@ print_device(struct devinfo_dev *dev, void *arg) print_indent(indent); xo_open_container(devname); - xo_emit("{d:%s}", devname); + xo_emit("{d:devicename/%s}", devname); print_device_props(dev); xo_emit("\n"); @@ -367,7 +366,7 @@ print_rman(struct devinfo_rman *rman, void *arg __unused) { char* safe_desc = xml_safe_string(rman->dm_desc); - xo_emit("{d:%s}:\n", rman->dm_desc); + xo_emit("<{:description/%s}\n>", rman->dm_desc); xo_open_container(safe_desc); devinfo_foreach_rman_resource(rman, print_rman_resource, 0); @@ -385,7 +384,7 @@ print_device_path_entry(struct devinfo_dev *dev) xo_open_container(devname); open_tag_count++; - xo_emit("{d:%s }", devname); + xo_emit("{:devicename/%s} ", devname); print_device_props(dev); if (vflag) xo_emit("\n"); 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/gssd/Makefile b/usr.sbin/gssd/Makefile index 7ad1cae7eb55..569e2c7e18f5 100644 --- a/usr.sbin/gssd/Makefile +++ b/usr.sbin/gssd/Makefile @@ -1,6 +1,6 @@ .include <src.opts.mk> -PACKAGE= kerberos +PACKAGE= gssd PROG= gssd MAN= gssd.8 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/jail/command.c b/usr.sbin/jail/command.c index 8ea3f3ee8795..9da4fe51673a 100644 --- a/usr.sbin/jail/command.c +++ b/usr.sbin/jail/command.c @@ -290,7 +290,7 @@ run_command(struct cfjail *j) const struct cfstring *comstring, *s; login_cap_t *lcap; const char **argv; - char *acs, *ajidstr, *cs, *comcs, *devpath; + char *acs, *cs, *comcs, *devpath; const char *jidstr, *conslog, *fmt, *path, *ruleset, *term, *username; enum intparam comparam; size_t comlen, ret; @@ -332,6 +332,25 @@ run_command(struct cfjail *j) printf("%d\n", j->jid); if (verbose >= 0 && (j->name || verbose > 0)) jail_note(j, "created\n"); + + /* + * Populate our jid and name parameters if they were not + * provided. This simplifies later logic that wants to + * use the jid or name to be able to do so reliably. + */ + if (j->intparams[KP_JID] == NULL) { + char ljidstr[16]; + + (void)snprintf(ljidstr, sizeof(ljidstr), "%d", + j->jid); + add_param(j, NULL, KP_JID, ljidstr); + } + + /* This matches the kernel behavior. */ + if (j->intparams[KP_NAME] == NULL) + add_param(j, j->intparams[KP_JID], KP_NAME, + NULL); + dep_done(j, DF_LIGHT); } return 0; @@ -456,8 +475,7 @@ run_command(struct cfjail *j) argv[0] = _PATH_IFCONFIG; argv[1] = comstring->s; argv[2] = down ? "-vnet" : "vnet"; - jidstr = string_param(j->intparams[KP_JID]); - argv[3] = jidstr ? jidstr : string_param(j->intparams[KP_NAME]); + argv[3] = string_param(j->intparams[KP_JID]); argv[4] = NULL; break; @@ -592,9 +610,7 @@ run_command(struct cfjail *j) case IP_ZFS_DATASET: argv = alloca(4 * sizeof(char *)); - jidstr = string_param(j->intparams[KP_JID]) ? - string_param(j->intparams[KP_JID]) : - string_param(j->intparams[KP_NAME]); + jidstr = string_param(j->intparams[KP_JID]); fmt = "if [ $(/sbin/zfs get -H -o value jailed %s) = on ]; then /sbin/zfs jail %s %s || echo error, attaching %s to jail %s failed; else echo error, you need to set jailed=on for dataset %s; fi"; comlen = strlen(fmt) + 2 * strlen(jidstr) @@ -796,14 +812,10 @@ run_command(struct cfjail *j) endpwent(); } if (!injail) { - if (asprintf(&ajidstr, "%d", j->jid) == -1) { - jail_warnx(j, "asprintf jid=%d: %s", j->jid, - strerror(errno)); - exit(1); - } - setenv("JID", ajidstr, 1); - free(ajidstr); + if (string_param(j->intparams[KP_JID])) + setenv("JID", string_param(j->intparams[KP_JID]), 1); setenv("JNAME", string_param(j->intparams[KP_NAME]), 1); + path = string_param(j->intparams[KP_PATH]); setenv("JPATH", path ? path : "", 1); } diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c index 3af0088626c9..70de82e662e7 100644 --- a/usr.sbin/jail/config.c +++ b/usr.sbin/jail/config.c @@ -156,11 +156,14 @@ load_config(const char *cfname) TAILQ_CONCAT(&opp, &j->params, tq); /* * The jail name implies its "name" or "jid" parameter, - * though they may also be explicitly set later on. + * though they may also be explicitly set later on. After we + * collect other parameters, we'll go back and ensure they're + * both set if we need to do so here. */ add_param(j, NULL, strtol(j->name, &ep, 10) && !*ep ? KP_JID : KP_NAME, j->name); + /* * Collect parameters for the jail, global parameters/variables, * and any matching wildcard jails. @@ -180,6 +183,14 @@ load_config(const char *cfname) TAILQ_FOREACH(p, &opp, tq) add_param(j, p, 0, NULL); + /* + * We only backfill if it's the name that wasn't set; if it was + * the jid, we can assume that will be populated later when the + * jail is created or found. + */ + if (j->intparams[KP_NAME] == NULL) + add_param(j, j->intparams[KP_JID], KP_NAME, NULL); + /* Resolve any variable substitutions. */ pgen = 0; TAILQ_FOREACH(p, &j->params, tq) { diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c index 27769cc14958..46cabf76ae11 100644 --- a/usr.sbin/jail/jail.c +++ b/usr.sbin/jail/jail.c @@ -890,7 +890,14 @@ running_jid(struct cfjail *j) j->jid = -1; return; } + j->jid = jail_get(jiov, 2, 0); + if (j->jid > 0 && j->intparams[KP_JID] == NULL) { + char jidstr[16]; + + (void)snprintf(jidstr, sizeof(jidstr), "%d", j->jid); + add_param(j, NULL, KP_JID, jidstr); + } } static void diff --git a/usr.sbin/jail/tests/commands.jail.conf b/usr.sbin/jail/tests/commands.jail.conf index afd56d1fa5d6..ad152a28b7fe 100644 --- a/usr.sbin/jail/tests/commands.jail.conf +++ b/usr.sbin/jail/tests/commands.jail.conf @@ -4,6 +4,4 @@ exec.prestart = "echo START"; exec.poststart = "env"; persist; -path = "/tmp/test_${name}_root"; - basejail {} diff --git a/usr.sbin/jail/tests/jail_basic_test.sh b/usr.sbin/jail/tests/jail_basic_test.sh index 6498eb1c1fdc..509900e8569c 100755 --- a/usr.sbin/jail/tests/jail_basic_test.sh +++ b/usr.sbin/jail/tests/jail_basic_test.sh @@ -129,36 +129,168 @@ commands_head() { atf_set descr 'Commands jail test' atf_set require.user root - mkdir /tmp/test_basejail_root } commands_body() { + cp "$(atf_get_srcdir)/commands.jail.conf" jail.conf + echo "path = \"$PWD\";" >> jail.conf + # exec.prestart (START) and exec.poststart (env) - atf_check -s exit:0 -o save:stdout -e empty \ - jail -f $(atf_get_srcdir)/commands.jail.conf -qc basejail - grep -E '^START$' stdout || atf_fail "exec.prestart output not found" - grep -E '^JID=[0-9]+' stdout || atf_fail "JID not found in exec.poststart env output" - grep -E '^JNAME=basejail$' stdout || atf_fail "JNAME not found in exec.poststart env output" - grep -E '^JPATH=/tmp/test_basejail_root$' stdout || atf_fail "JPATH not found in exec.poststart env output" + atf_check -o save:stdout -e empty \ + jail -f jail.conf -qc basejail + + # exec.prestart output is missing + atf_check grep -qE '^START$' stdout + # JID was not set in the exec.poststart env + atf_check grep -qE '^JID=[0-9]+' stdout + # JNAME was not set in the exec.poststart env + atf_check grep -qE '^JNAME=basejail$' stdout + # JPATH was not set in the exec.poststart env + atf_check grep -qE "^JPATH=$PWD$" stdout # exec.prestop by jailname atf_check -s exit:0 -o inline:"STOP\n" \ - jail -f $(atf_get_srcdir)/commands.jail.conf -qr basejail + jail -f jail.conf -qr basejail # exec.prestop by jid - jail -f $(atf_get_srcdir)/commands.jail.conf -qc basejail + jail -f jail.conf -qc basejail atf_check -s exit:0 -o inline:"STOP\n" \ - jail -f $(atf_get_srcdir)/commands.jail.conf -qr `jls -j basejail jid` + jail -f jail.conf -qr `jls -j basejail jid` } -commands_cleanup() +commands_cleanup() { - jls -j basejail > /dev/null 2>&1 - if [ $? -e 0 ] - then + if jls -j basejail > /dev/null 2>&1; then jail -r basejail fi - rmdir /tmp/test_basejail_root +} + +atf_test_case "jid_name_set" "cleanup" +jid_name_set_head() +{ + atf_set descr 'Test that one can set both the jid and name in a config file' + atf_set require.user root +} + +find_unused_jid() +{ + : ${JAIL_MAX=999999} + + # We'll start at a higher jid number and roll through the space until + # we find one that isn't taken. We start high to avoid racing parallel + # activity for the 'next available', though ideally we don't have a lot + # of parallel jail activity like that. + jid=5309 + while jls -cj "$jid"; do + if [ "$jid" -eq "$JAIL_MAX" ]; then + atf_skip "System has too many jail, cannot find free slot" + fi + + jid=$((jid + 1)) + done + + echo "$jid" | tee -a jails.lst +} +clean_jails() +{ + if [ ! -s jails.lst ]; then + return 0 + fi + + while read jail; do + if jls -e -j "$jail"; then + jail -r "$jail" + fi + done < jails.lst +} + +jid_name_set_body() +{ + local jid=$(find_unused_jid) + + echo "basejail" >> jails.lst + echo "$jid { name = basejail; persist; }" > jail.conf + atf_check -o match:"$jid: created" jail -f jail.conf -c "$jid" + atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" + + echo "basejail { jid = $jid; persist; }" > jail.conf + atf_check -o match:"basejail: created" jail -f jail.conf -c basejail + atf_check -o match:"basejail: removed" jail -f jail.conf -r basejail +} + +jid_name_set_cleanup() +{ + clean_jails +} + +atf_test_case "param_consistency" "cleanup" +param_consistency_head() +{ + atf_set descr 'Test for consistency in jid/name params being set implicitly' + atf_set require.user root +} + +param_consistency_body() +{ + local iface jid + + echo "basejail" >> jails.lst + + # Most basic test: exec.poststart running a command without a jail + # config. This would previously crash as we only had the jid and name + # as populated at creation time. + atf_check jail -c path=/ exec.poststart="true" command=/usr/bin/true + + iface=$(ifconfig lo create) + atf_check test -n "$iface" + echo "$iface" >> interfaces.lst + + # Now do it again but exercising IP_VNET_INTERFACE, which is an + # implied command that wants to use the jid or name. This would crash + # as neither KP_JID or KP_NAME are populated when a jail is created, + # just as above- just at a different spot. + atf_check jail -c \ + path=/ vnet=new vnet.interface="$iface" command=/usr/bin/true + + # Test that a jail that we only know by name will have its jid resolved + # and added to its param set. + echo "basejail {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf + + atf_check -o ignore jail -f jail.conf -c basejail + atf_check -o match:"STOP" jail -f jail.conf -r basejail + + # Do the same sequence as above, but use a jail with a jid-ish name. + jid=$(find_unused_jid) + echo "$jid {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf + + atf_check -o ignore jail -f jail.conf -c "$jid" + atf_check -o match:"STOP" jail -f jail.conf -r "$jid" + + # Ditto, but now we set a name for that jid-jail. + echo "$jid {name = basejail; path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf + + atf_check -o ignore jail -f jail.conf -c "$jid" + atf_check -o match:"STOP" jail -f jail.conf -r "$jid" + + # Confirm that we have a valid jid available in exec.poststop. It's + # probably debatable whether we should or not. + echo "basejail {path = /; exec.poststop = 'echo JID=\$JID'; persist; }" > jail.conf + atf_check -o ignore jail -f jail.conf -c basejail + jid=$(jls -j basejail jid) + + atf_check -o match:"JID=$jid" jail -f jail.conf -r basejail + +} + +param_consistency_cleanup() +{ + clean_jails + + if [ -f "interfaces.lst" ]; then + while read iface; do + ifconfig "$iface" destroy + done < interfaces.lst + fi } atf_init_test_cases() @@ -167,4 +299,6 @@ atf_init_test_cases() atf_add_test_case "list" atf_add_test_case "nested" atf_add_test_case "commands" + atf_add_test_case "jid_name_set" + atf_add_test_case "param_consistency" } diff --git a/usr.sbin/jls/jls.8 b/usr.sbin/jls/jls.8 index f7a5eeb321ef..715033082963 100644 --- a/usr.sbin/jls/jls.8 +++ b/usr.sbin/jls/jls.8 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 13, 2025 +.Dd July 25, 2025 .Dt JLS 8 .Os .Sh NAME @@ -35,6 +35,10 @@ .Op Fl dhNnqsv .Op Fl j Ar jail .Op Ar parameter ... +.Nm +.Fl c +.Op Fl d +.Fl j Ar jail .Sh DESCRIPTION The .Nm @@ -54,11 +58,21 @@ for a description of some core parameters. If no .Ar parameters or any of the options -.Fl hns +.Fl chns are given, the following four columns will be printed: jail identifier (jid), IP address (ip4.addr), hostname (host.hostname), and path (path). .Pp +When the +.Fl c +option is used, +.Nm +will not emit any output except for usage errors. +This mode is intended solely to check for a single jail's existence, and it does +not accept any +.Ar parameter +or print-option flags. +.Pp The following options are available: .Bl -tag -width indent .It Fl -libxo @@ -68,6 +82,8 @@ in a selection of different human and machine readable formats. See .Xr xo_options 7 for details on command line arguments. +.It Fl c +Only check for the jail's existence. .It Fl d List .Va dying diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c index bd193a69c458..4f697a5bb382 100644 --- a/usr.sbin/jls/jls.c +++ b/usr.sbin/jls/jls.c @@ -37,6 +37,7 @@ #include <arpa/inet.h> #include <netinet/in.h> +#include <assert.h> #include <ctype.h> #include <errno.h> #include <jail.h> @@ -59,6 +60,7 @@ #define PRINT_SKIP 0x10 #define PRINT_VERBOSE 0x20 #define PRINT_JAIL_NAME 0x40 +#define PRINT_EXISTS 0x80 static struct jailparam *params; static int *param_parent; @@ -81,6 +83,14 @@ static void quoted_print(int pflags, char *name, char *value); static void emit_ip_addr_list(int af_family, const char *list_name, struct jailparam *param); +static void +usage(void) +{ + xo_errx(1, + "usage: jls [-dhNnqv] [-j jail] [param ...]\n" + " jls -c [-d] -j jail"); +} + int main(int argc, char **argv) { @@ -94,12 +104,15 @@ main(int argc, char **argv) xo_set_version(JLS_XO_VERSION); jname = NULL; pflags = jflags = jid = 0; - while ((c = getopt(argc, argv, "adj:hNnqsv")) >= 0) + while ((c = getopt(argc, argv, "acdj:hNnqsv")) >= 0) switch (c) { case 'a': case 'd': jflags |= JAIL_DYING; break; + case 'c': + pflags |= PRINT_EXISTS; + break; case 'j': jid = strtoul(optarg, &ep, 10); if (!jid || *ep) { @@ -130,7 +143,7 @@ main(int argc, char **argv) PRINT_VERBOSE; break; default: - xo_errx(1, "usage: jls [-dhNnqv] [-j jail] [param ...]"); + usage(); } #ifdef INET6 @@ -140,8 +153,28 @@ main(int argc, char **argv) ip4_ok = feature_present("inet"); #endif + argc -= optind; + argv += optind; + /* Add the parameters to print. */ - if (optind == argc) { + if ((pflags & PRINT_EXISTS) != 0) { + if ((pflags & ~PRINT_EXISTS) != 0) { + xo_warnx("-c is incompatible with other print options"); + usage(); + } else if (argc != 0) { + xo_warnx("-c does not accept non-option arguments"); + usage(); + } else if (jid == 0 && jname == NULL) { + xo_warnx("-j jail to check must be provided for -c"); + usage(); + } + + /* + * Force libxo to be silent, as well -- we're only wanting our + * exit status. + */ + xo_set_style(NULL, XO_STYLE_TEXT); + } else if (argc == 0) { if (pflags & (PRINT_HEADER | PRINT_NAMEVAL)) add_param("all", NULL, (size_t)0, NULL, JP_USER); else if (pflags & PRINT_VERBOSE) { @@ -179,9 +212,8 @@ main(int argc, char **argv) } } else { pflags &= ~PRINT_VERBOSE; - while (optind < argc) - add_param(argv[optind++], NULL, (size_t)0, NULL, - JP_USER); + for (i = 0; i < argc; i++) + add_param(argv[i], NULL, (size_t)0, NULL, JP_USER); } if (pflags & PRINT_SKIP) { @@ -237,9 +269,17 @@ main(int argc, char **argv) xo_open_list("jail"); /* Fetch the jail(s) and print the parameters. */ if (jid != 0 || jname != NULL) { - if (print_jail(pflags, jflags) < 0) + if (print_jail(pflags, jflags) < 0) { + /* + * We omit errors from existential issues if we're just + * doing a -c check that the jail exists. + */ + if (pflags & PRINT_EXISTS) + exit(1); xo_errx(1, "%s", jail_errmsg); + } } else { + assert((pflags & PRINT_EXISTS) == 0); for (lastjid = 0; (lastjid = print_jail(pflags, jflags)) >= 0; ) ; @@ -390,6 +430,8 @@ print_jail(int pflags, int jflags) jid = jailparam_get(params, nparams, jflags); if (jid < 0) return jid; + else if (pflags & PRINT_EXISTS) + return 0; xo_open_instance("jail"); 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/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile index 85b66d4b6f49..49c0e688e8e2 100644 --- a/usr.sbin/mfiutil/Makefile +++ b/usr.sbin/mfiutil/Makefile @@ -4,7 +4,7 @@ LINKS= ${BINDIR}/mfiutil ${BINDIR}/mrsasutil SRCS= mfiutil.c mfi_bbu.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c \ mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c \ mfi_properties.c -MAN8= mfiutil.8 +MAN= mfiutil.8 MLINKS= mfiutil.8 mrsasutil.8 CFLAGS.gcc+= -fno-builtin-strftime diff --git a/usr.sbin/rpc.lockd/kern.c b/usr.sbin/rpc.lockd/kern.c index c24b81159ea5..1945bd68328a 100644 --- a/usr.sbin/rpc.lockd/kern.c +++ b/usr.sbin/rpc.lockd/kern.c @@ -39,6 +39,7 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <assert.h> #include <err.h> #include <errno.h> #include <fcntl.h> @@ -232,17 +233,29 @@ void set_auth(CLIENT *cl, struct xucred *xucred) { int ngroups; + gid_t *groups; - ngroups = xucred->cr_ngroups - 1; + /* + * Exclude the first element if it is actually the egid, but account for + * the possibility that we could eventually exclude the egid from the + * exported group list some day. + */ + ngroups = xucred->cr_ngroups; + groups = &xucred->cr_groups[0]; + if (groups == &xucred->cr_gid) { + assert(ngroups > 0); + ngroups--; + groups++; + } if (ngroups > NGRPS) ngroups = NGRPS; if (cl->cl_auth != NULL) cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth); cl->cl_auth = authunix_create(hostname, xucred->cr_uid, - xucred->cr_groups[0], + xucred->cr_gid, ngroups, - &xucred->cr_groups[1]); + groups); } diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c index 237663eef74d..b99e4ea74b5a 100644 --- a/usr.sbin/rwhod/rwhod.c +++ b/usr.sbin/rwhod/rwhod.c @@ -246,12 +246,12 @@ main(int argc, char *argv[]) syslog(LOG_ERR, "bind: %m"); exit(1); } - if (setgid(unpriv_gid) != 0) { - syslog(LOG_ERR, "setgid: %m"); + if (setgroups(0, NULL) != 0) { + syslog(LOG_ERR, "setgroups: %m"); exit(1); } - if (setgroups(1, &unpriv_gid) != 0) { /* XXX BOGUS groups[0] = egid */ - syslog(LOG_ERR, "setgroups: %m"); + if (setgid(unpriv_gid) != 0) { + syslog(LOG_ERR, "setgid: %m"); exit(1); } if (setuid(unpriv_uid) != 0) { 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/spi/Makefile b/usr.sbin/spi/Makefile index 73f5af6fc3cc..fee967f6a234 100644 --- a/usr.sbin/spi/Makefile +++ b/usr.sbin/spi/Makefile @@ -2,6 +2,6 @@ PROG= spi -MAN8= spi.8 +MAN= spi.8 .include <bsd.prog.mk> 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); } diff --git a/usr.sbin/ypldap/ldapclient.c b/usr.sbin/ypldap/ldapclient.c index acd4410d939f..a246a25a9605 100644 --- a/usr.sbin/ypldap/ldapclient.c +++ b/usr.sbin/ypldap/ldapclient.c @@ -385,7 +385,7 @@ ldapclient(int pipe_main2client[2]) ypldap_process = PROC_CLIENT; #ifndef DEBUG - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("cannot drop privileges"); diff --git a/usr.sbin/ypldap/ypldap.c b/usr.sbin/ypldap/ypldap.c index 01b5955aa822..b9e938227831 100644 --- a/usr.sbin/ypldap/ypldap.c +++ b/usr.sbin/ypldap/ypldap.c @@ -602,7 +602,7 @@ main(int argc, char *argv[]) fatal("getpwnam"); #ifndef DEBUG - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("cannot drop privileges"); diff --git a/usr.sbin/ypldap/ypldap_dns.c b/usr.sbin/ypldap/ypldap_dns.c index 09ce636ebdc8..9dbbf26d237b 100644 --- a/usr.sbin/ypldap/ypldap_dns.c +++ b/usr.sbin/ypldap/ypldap_dns.c @@ -91,7 +91,7 @@ ypldap_dns(int pipe_ntp[2], struct passwd *pw) setproctitle("dns engine"); close(pipe_ntp[0]); - if (setgroups(1, &pw->pw_gid) || + if (setgroups(0, NULL) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); |