aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/pwait/pwait.16
-rw-r--r--bin/pwait/pwait.c102
-rw-r--r--bin/pwait/tests/pwait_test.sh38
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h5
-rw-r--r--lib/libc/string/ffs.315
-rw-r--r--libexec/rc/rc.subr29
-rw-r--r--sbin/ipfw/dummynet.c4
-rw-r--r--sbin/ipfw/ipfw2.c8
-rw-r--r--share/examples/mdoc/example.123
-rw-r--r--share/examples/mdoc/example.323
-rw-r--r--share/examples/mdoc/example.423
-rw-r--r--share/examples/mdoc/example.923
-rw-r--r--share/man/man5/style.mdoc.530
-rw-r--r--share/man/man9/g_bio.93
-rw-r--r--share/man/man9/uio.914
-rw-r--r--sys/arm/include/ieeefp.h10
-rw-r--r--sys/arm64/arm64/elf32_machdep.c2
-rw-r--r--sys/fs/deadfs/dead_vnops.c10
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c13
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c34
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c5
-rw-r--r--sys/x86/x86/mca.c279
-rw-r--r--usr.bin/id/id.128
-rw-r--r--usr.bin/id/id.c185
24 files changed, 561 insertions, 351 deletions
diff --git a/bin/pwait/pwait.1 b/bin/pwait/pwait.1
index 9310b74d5683..c61f6854358b 100644
--- a/bin/pwait/pwait.1
+++ b/bin/pwait/pwait.1
@@ -30,7 +30,7 @@
.\" USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
-.Dd January 21, 2021
+.Dd October 22, 2025
.Dt PWAIT 1
.Os
.Sh NAME
@@ -39,7 +39,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl t Ar duration
-.Op Fl ov
+.Op Fl opv
.Ar pid
\&...
.Sh DESCRIPTION
@@ -51,6 +51,8 @@ The following option is available:
.Bl -tag -width indent
.It Fl o
Exit when any of the given processes has terminated.
+.It Fl p
+On exit, print a list of processes that have not terminated.
.It Fl t Ar duration
If any process is still running after
.Ar duration ,
diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c
index b402328849ef..6e9e634b4526 100644
--- a/bin/pwait/pwait.c
+++ b/bin/pwait/pwait.c
@@ -34,7 +34,9 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/event.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/tree.h>
#include <sys/wait.h>
#include <err.h>
@@ -47,10 +49,25 @@
#include <sysexits.h>
#include <unistd.h>
+struct pid {
+ RB_ENTRY(pid) entry;
+ pid_t pid;
+};
+
+static int
+pidcmp(const struct pid *a, const struct pid *b)
+{
+ return (a->pid > b->pid ? 1 : a->pid < b->pid ? -1 : 0);
+}
+
+RB_HEAD(pidtree, pid);
+static struct pidtree pids = RB_INITIALIZER(&pids);
+RB_GENERATE_STATIC(pidtree, pid, entry, pidcmp);
+
static void
usage(void)
{
- fprintf(stderr, "usage: pwait [-t timeout] [-ov] pid ...\n");
+ fprintf(stderr, "usage: pwait [-t timeout] [-opv] pid ...\n");
exit(EX_USAGE);
}
@@ -62,21 +79,28 @@ main(int argc, char *argv[])
{
struct itimerval itv;
struct kevent *e;
+ struct pid k, *p;
char *end, *s;
double timeout;
+ size_t sz;
long pid;
- int i, kq, n, nleft, opt, status;
- bool oflag, tflag, verbose;
+ pid_t mypid;
+ int i, kq, n, ndone, nleft, opt, pid_max, ret, status;
+ bool oflag, pflag, tflag, verbose;
oflag = false;
+ pflag = false;
tflag = false;
verbose = false;
memset(&itv, 0, sizeof(itv));
- while ((opt = getopt(argc, argv, "ot:v")) != -1) {
+ while ((opt = getopt(argc, argv, "opt:v")) != -1) {
switch (opt) {
case 'o':
- oflag = 1;
+ oflag = true;
+ break;
+ case 'p':
+ pflag = true;
break;
case 't':
tflag = true;
@@ -128,16 +152,18 @@ main(int argc, char *argv[])
usage();
}
- kq = kqueue();
- if (kq == -1) {
+ if ((kq = kqueue()) < 0)
err(EX_OSERR, "kqueue");
- }
- e = malloc((argc + tflag) * sizeof(struct kevent));
- if (e == NULL) {
+ sz = sizeof(pid_max);
+ if (sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) != 0) {
+ pid_max = 99999;
+ }
+ if ((e = malloc((argc + tflag) * sizeof(*e))) == NULL) {
err(EX_OSERR, "malloc");
}
- nleft = 0;
+ ndone = nleft = 0;
+ mypid = getpid();
for (n = 0; n < argc; n++) {
s = argv[n];
/* Undocumented Solaris compat */
@@ -146,35 +172,37 @@ main(int argc, char *argv[])
}
errno = 0;
pid = strtol(s, &end, 10);
- if (pid < 0 || *end != '\0' || errno != 0) {
+ if (pid < 0 || pid > pid_max || *end != '\0' || errno != 0) {
warnx("%s: bad process id", s);
continue;
}
- if (pid == getpid()) {
+ if (pid == mypid) {
warnx("%s: skipping my own pid", s);
continue;
}
- for (i = 0; i < nleft; i++) {
- if (e[i].ident == (uintptr_t)pid) {
- break;
- }
+ if ((p = malloc(sizeof(*p))) == NULL) {
+ err(EX_OSERR, NULL);
}
- if (i < nleft) {
+ p->pid = pid;
+ if (RB_INSERT(pidtree, &pids, p) != NULL) {
/* Duplicate. */
+ free(p);
continue;
}
EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) {
+ if (errno != ESRCH)
+ err(EX_OSERR, "kevent()");
warn("%ld", pid);
- if (oflag) {
- exit(EX_OK);
- }
+ RB_REMOVE(pidtree, &pids, p);
+ free(p);
+ ndone++;
} else {
nleft++;
}
}
- if (nleft > 0 && tflag) {
+ if ((ndone == 0 || !oflag) && nleft > 0 && tflag) {
/*
* Explicitly detect SIGALRM so that an exit status of 124
* can be returned rather than 142.
@@ -189,7 +217,8 @@ main(int argc, char *argv[])
err(EX_OSERR, "setitimer");
}
}
- while (nleft > 0) {
+ ret = EX_OK;
+ while ((ndone == 0 || !oflag) && ret == EX_OK && nleft > 0) {
n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
if (n == -1) {
err(EX_OSERR, "kevent");
@@ -199,29 +228,34 @@ main(int argc, char *argv[])
if (verbose) {
printf("timeout\n");
}
- exit(124);
+ ret = 124;
}
+ pid = e[i].ident;
if (verbose) {
status = e[i].data;
if (WIFEXITED(status)) {
printf("%ld: exited with status %d.\n",
- (long)e[i].ident,
- WEXITSTATUS(status));
+ pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("%ld: killed by signal %d.\n",
- (long)e[i].ident,
- WTERMSIG(status));
+ pid, WTERMSIG(status));
} else {
- printf("%ld: terminated.\n",
- (long)e[i].ident);
+ printf("%ld: terminated.\n", pid);
}
}
- if (oflag) {
- exit(EX_OK);
+ k.pid = pid;
+ if ((p = RB_FIND(pidtree, &pids, &k)) != NULL) {
+ RB_REMOVE(pidtree, &pids, p);
+ free(p);
+ ndone++;
}
--nleft;
}
}
-
- exit(EX_OK);
+ if (pflag) {
+ RB_FOREACH(p, pidtree, &pids) {
+ printf("%d\n", p->pid);
+ }
+ }
+ exit(ret);
}
diff --git a/bin/pwait/tests/pwait_test.sh b/bin/pwait/tests/pwait_test.sh
index 66bdd6981704..d31ca21cff93 100644
--- a/bin/pwait/tests/pwait_test.sh
+++ b/bin/pwait/tests/pwait_test.sh
@@ -310,6 +310,43 @@ or_flag_cleanup()
wait $p2 $p4 $p6 >/dev/null 2>&1
}
+atf_test_case print
+print_head()
+{
+ atf_set "descr" "Test the -p flag"
+}
+
+print_body()
+{
+ sleep 1 &
+ p1=$!
+
+ sleep 5 &
+ p5=$!
+
+ sleep 10 &
+ p10=$!
+
+ atf_check \
+ -o inline:"$p5\n$p10\n" \
+ -s exit:124 \
+ pwait -t 2 -p $p10 $p5 $p1 $p5 $p10
+
+ atf_check \
+ -e inline:"kill: $p1: No such process\n" \
+ -s exit:1 \
+ kill -0 $p1
+
+ atf_check kill -0 $p5
+ atf_check kill -0 $p10
+}
+
+print_cleanup()
+{
+ kill $p1 $p5 $p10 >/dev/null 2>&1
+ wait $p1 $p5 $p10 >/dev/null 2>&1
+}
+
atf_init_test_cases()
{
atf_add_test_case basic
@@ -318,4 +355,5 @@ atf_init_test_cases()
atf_add_test_case timeout_no_timeout
atf_add_test_case timeout_many
atf_add_test_case or_flag
+ atf_add_test_case print
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
index 7ab63905ed4f..7d090ba682b3 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -78,6 +78,11 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ bool IsAArch64OutlineAtomicsDefault(
+ const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
+
UnwindTableLevel
getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
diff --git a/lib/libc/string/ffs.3 b/lib/libc/string/ffs.3
index 1adece73c8ae..1cca54c0b30b 100644
--- a/lib/libc/string/ffs.3
+++ b/lib/libc/string/ffs.3
@@ -27,9 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ffs.3 8.2 (Berkeley) 4/19/94
-.\"
-.Dd October 17, 2015
+.Dd October 25, 2025
.Dt FFS 3
.Os
.Sh NAME
@@ -82,6 +80,17 @@ argument was zero.
.Sh SEE ALSO
.Xr bitstring 3 ,
.Xr bitset 9
+.Sh STANDARDS
+The
+.Fn ffs
+function conforms to
+.St -p1003.1-2008 .
+The
+.Fn ffsl
+and
+.Fn ffsll
+functions conform to
+.St -p1003.1-2024 .
.Sh HISTORY
The
.Fn ffs
diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
index a4f3762afd2c..bef364af0843 100644
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -634,31 +634,18 @@ sort_lite()
#
wait_for_pids()
{
- local _list _prefix _nlist _j
+ local _list _prefix _j
- _list="$@"
- if [ -z "$_list" ]; then
- return
- fi
- _prefix=
- while true; do
- _nlist=""
- for _j in $_list; do
- if kill -0 $_j 2>/dev/null; then
- _nlist="${_nlist}${_nlist:+ }$_j"
- fi
- done
- if [ -z "$_nlist" ]; then
- break
+ for _j in "$@"; do
+ if kill -0 $_j 2>/dev/null; then
+ _list="${_list}${_list:+ }$_j"
fi
- _list=$_nlist
+ done
+ _prefix=
+ while [ -n "$_list" ]; do
echo -n ${_prefix:-"Waiting for PIDS: "}$_list
_prefix=", "
- pwait -o $_list 2>/dev/null
- # At least one of the processes we were waiting for
- # has terminated. Give init a chance to collect it
- # before looping around and checking again.
- sleep 1
+ _list=$(pwait -op $_list 2>/dev/null)
done
if [ -n "$_prefix" ]; then
echo "."
diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c
index 26d535428ec3..688fd6d4c5b0 100644
--- a/sbin/ipfw/dummynet.c
+++ b/sbin/ipfw/dummynet.c
@@ -672,7 +672,7 @@ ipfw_delete_pipe(int do_pipe, int i)
i = do_cmd(IP_DUMMYNET3, &cmd, cmd.oid.len);
if (i) {
i = 1;
- warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", i);
+ warn("rule %u: setsockopt(IP_DUMMYNET3)", i);
}
return i;
}
@@ -1841,7 +1841,7 @@ end_mask:
i = do_cmd(IP_DUMMYNET3, base, (char *)buf - (char *)base);
if (i)
- err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
+ err(1, "setsockopt(%s)", "IP_DUMMYNET3");
}
void
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index beff243ecdbd..eecf6a9c056f 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -620,11 +620,7 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
if (ipfw_socket < 0)
err(EX_UNAVAILABLE, "socket");
- if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
- optname == IP_FW_ADD || optname == IP_FW3 ||
- optname == IP_FW_NAT_GET_CONFIG ||
- optname < 0 ||
- optname == IP_FW_NAT_GET_LOG) {
+ if (optname == IP_FW3 || optname < 0) {
if (optname < 0)
optname = -optname;
i = getsockopt(ipfw_socket, IPPROTO_IP, optname, optval,
@@ -5575,7 +5571,7 @@ ipfw_add(char *av[])
sz = default_off + sizeof(ipfw_obj_ctlv) + tlen + rlen;
if ((tbuf = calloc(1, sz)) == NULL)
- err(EX_UNAVAILABLE, "malloc() failed for IP_FW_ADD");
+ err(EX_UNAVAILABLE, "malloc() failed for IP_FW_XADD");
op3 = (ip_fw3_opheader *)tbuf;
/* Tables first */
ctlv = (ipfw_obj_ctlv *)(op3 + 1);
diff --git a/share/examples/mdoc/example.1 b/share/examples/mdoc/example.1
index 0bdabe95aa95..daffb8bc0422 100644
--- a/share/examples/mdoc/example.1
+++ b/share/examples/mdoc/example.1
@@ -1,28 +1,7 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause
-.\"
.\" Copyright (c) [year] [your name]
.\"
-.\" 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.
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
diff --git a/share/examples/mdoc/example.3 b/share/examples/mdoc/example.3
index c4e85062cad1..22c398e0491c 100644
--- a/share/examples/mdoc/example.3
+++ b/share/examples/mdoc/example.3
@@ -1,28 +1,7 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause
-.\"
.\" Copyright (c) [year] [your name]
.\"
-.\" 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.
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
diff --git a/share/examples/mdoc/example.4 b/share/examples/mdoc/example.4
index 47ae5456b79a..e627f81af530 100644
--- a/share/examples/mdoc/example.4
+++ b/share/examples/mdoc/example.4
@@ -1,28 +1,7 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause
-.\"
.\" Copyright (c) [year] [your name]
.\"
-.\" 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.
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
diff --git a/share/examples/mdoc/example.9 b/share/examples/mdoc/example.9
index 1dd24a99fd42..f105f7465f2c 100644
--- a/share/examples/mdoc/example.9
+++ b/share/examples/mdoc/example.9
@@ -1,28 +1,7 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause
-.\"
.\" Copyright (c) [year] [your name]
.\"
-.\" 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.
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
diff --git a/share/man/man5/style.mdoc.5 b/share/man/man5/style.mdoc.5
index 1c3ec2012118..2f8ea90ae21f 100644
--- a/share/man/man5/style.mdoc.5
+++ b/share/man/man5/style.mdoc.5
@@ -1,30 +1,9 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause
-.\"
-.\" Copyright (c) 2018-2022 Mateusz Piotrowski <0mp@FreeBSD.org>
+.\" Copyright (c) 2018-2025 Mateusz Piotrowski <0mp@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.
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
-.Dd December 21, 2024
+.Dd October 24, 2025
.Dt STYLE.MDOC 5
.Os
.Sh NAME
@@ -71,6 +50,9 @@ Historically,
was the preferred way before the deprecation of
.Sy \&Li .
.El
+.Ss Copyright Header
+Refer to
+.Xr style 9 .
.Ss HARDWARE Section
Driver manuals in section four should have a
.Sx HARDWARE
diff --git a/share/man/man9/g_bio.9 b/share/man/man9/g_bio.9
index 407c38e6ca70..fc278cd229a9 100644
--- a/share/man/man9/g_bio.9
+++ b/share/man/man9/g_bio.9
@@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd August 7, 2019
+.Dd October 26, 2025
.Dt G_BIO 9
.Os
.Sh NAME
@@ -309,6 +309,7 @@ example_start(struct bio *bp)
}
.Ed
.Sh SEE ALSO
+.Xr dtrace_io 4 ,
.Xr geom 4 ,
.Xr DECLARE_GEOM_CLASS 9 ,
.Xr g_access 9 ,
diff --git a/share/man/man9/uio.9 b/share/man/man9/uio.9
index e6240c4e51d3..b143eb6e8e62 100644
--- a/share/man/man9/uio.9
+++ b/share/man/man9/uio.9
@@ -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 March 11, 2017
+.Dd October 22, 2025
.Dt UIO 9
.Os
.Sh NAME
@@ -107,10 +107,14 @@ The I/O vector points into the kernel address space.
Do not copy, already in object.
.El
.It Va uio_rw
-The direction of the desired transfer, either
-.Dv UIO_READ
-or
-.Dv UIO_WRITE .
+The direction of the desired transfer.
+The supported flags are:
+.Bl -tag -width "UIO_WRITE"
+.It Dv UIO_READ
+Transfer data from the buffers into the I/O vectors.
+.It Dv UIO_WRITE
+Transfer data from the I/O vectors into the buffers.
+.El
.It Va uio_td
The pointer to a
.Vt "struct thread"
diff --git a/sys/arm/include/ieeefp.h b/sys/arm/include/ieeefp.h
index 57dd058b8a95..57719b883d58 100644
--- a/sys/arm/include/ieeefp.h
+++ b/sys/arm/include/ieeefp.h
@@ -49,4 +49,14 @@ typedef enum {
#define fp_except_t int
+/* Augment the userland declarations. */
+__BEGIN_DECLS
+extern fp_rnd_t fpgetround(void);
+extern fp_rnd_t fpsetround(fp_rnd_t);
+extern fp_except_t fpgetmask(void);
+extern fp_except_t fpsetmask(fp_except_t);
+extern fp_except_t fpgetsticky(void);
+extern fp_except_t fpsetsticky(fp_except_t);
+__END_DECLS
+
#endif /* _MACHINE_IEEEFP_H_ */
diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
index 5f35d01f9ac0..285be3d89cbb 100644
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -208,7 +208,7 @@ freebsd32_fetch_syscall_args(struct thread *td)
sa->code = *ap++;
nap--;
} else if (sa->code == SYS___syscall) {
- sa->code = ap[1];
+ sa->code = ap[_QUAD_LOWWORD];
nap -= 2;
ap += 2;
}
diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c
index 0f850cede292..75a1398ad6aa 100644
--- a/sys/fs/deadfs/dead_vnops.c
+++ b/sys/fs/deadfs/dead_vnops.c
@@ -124,18 +124,18 @@ dead_read(struct vop_read_args *ap)
{
/*
- * Return EOF for tty devices, EIO for others
+ * Return EOF for tty devices, ENXIO for others
*/
- if ((ap->a_vp->v_vflag & VV_ISTTY) == 0)
- return (EIO);
- return (0);
+ if (ap->a_vp->v_vflag & VV_ISTTY)
+ return (0);
+ return (ENXIO);
}
int
dead_write(struct vop_write_args *ap)
{
- return (EIO);
+ return (ENXIO);
}
int
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index bde9be0885e0..6a9a73b40fb0 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -4033,10 +4033,15 @@ nfssvc_idname(struct nfsd_idargs *nidp)
nidp->nid_namelen);
if (error == 0 && nidp->nid_ngroup > 0 &&
(nidp->nid_flag & NFSID_ADDUID) != 0) {
- grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP,
- M_WAITOK);
- error = copyin(nidp->nid_grps, grps,
- sizeof(gid_t) * nidp->nid_ngroup);
+ grps = NULL;
+ if (nidp->nid_ngroup > NGROUPS_MAX)
+ error = EINVAL;
+ if (error == 0) {
+ grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP,
+ M_WAITOK);
+ error = copyin(nidp->nid_grps, grps,
+ sizeof(gid_t) * nidp->nid_ngroup);
+ }
if (error == 0) {
/*
* Create a credential just like svc_getcred(),
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 3c580b90e6b9..387c5465618a 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -2208,7 +2208,7 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED
+ NFSX_VERF);
rlen = fxdr_unsigned(int, *tl++);
- if (rlen == 0) {
+ if (rlen <= 0 || rlen > len) {
error = NFSERR_IO;
goto nfsmout;
} else if (rlen < len) {
@@ -5157,7 +5157,7 @@ nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,
struct nfsrv_descript nfsd;
struct nfsrv_descript *nd = &nfsd;
u_char *cp, *cp2, *fhp;
- int error, cnt, len, setnil;
+ int error, cnt, i, len, setnil;
u_int32_t *opcntp;
nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL, 0,
@@ -5198,8 +5198,12 @@ nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,
if (error)
return (error);
if (nd->nd_repstat == 0) {
- NFSM_DISSECT(tl, u_int32_t *, (3 + 2 * cnt) * NFSX_UNSIGNED);
- tl += (2 + 2 * cnt);
+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
+ tl += 2;
+ for (i = 0; i < cnt; i++) {
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ tl++;
+ }
if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
len > NFSX_FHMAX) {
nd->nd_repstat = NFSERR_BADXDR;
@@ -5470,7 +5474,7 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
}
*tl++ = txdr_unsigned(4096); /* Max response size cached */
*tl++ = txdr_unsigned(20); /* Max operations */
- *tl++ = txdr_unsigned(64); /* Max slots */
+ *tl++ = txdr_unsigned(NFSV4_SLOTS); /* Max slots */
*tl = 0; /* No rdma ird */
/* Fill in back channel attributes. */
@@ -5539,6 +5543,11 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
sep->nfsess_maxcache = fxdr_unsigned(int, *tl++);
tl++;
sep->nfsess_foreslots = fxdr_unsigned(uint16_t, *tl++);
+ if (sep->nfsess_foreslots == 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ } else if (sep->nfsess_foreslots > NFSV4_SLOTS)
+ sep->nfsess_foreslots = NFSV4_SLOTS;
NFSCL_DEBUG(4, "fore slots=%d\n", (int)sep->nfsess_foreslots);
irdcnt = fxdr_unsigned(int, *tl);
if (irdcnt < 0 || irdcnt > 1) {
@@ -5552,6 +5561,8 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
tl += 5;
sep->nfsess_backslots = fxdr_unsigned(uint16_t, *tl);
+ if (sep->nfsess_backslots > NFSV4_CBSLOTS)
+ sep->nfsess_backslots = NFSV4_CBSLOTS;
NFSCL_DEBUG(4, "back slots=%d\n", (int)sep->nfsess_backslots);
}
error = nd->nd_repstat;
@@ -5671,7 +5682,8 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
stripecnt = fxdr_unsigned(int, *tl);
NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt);
- if (stripecnt < 1 || stripecnt > 4096) {
+ if (stripecnt >= MHLEN / NFSX_UNSIGNED ||
+ stripecnt < 1) {
printf("pNFS File layout devinfo stripecnt %d:"
" out of range\n", stripecnt);
error = NFSERR_BADXDR;
@@ -7120,7 +7132,7 @@ nfsrpc_writeds(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF);
rlen = fxdr_unsigned(int, *tl++);
NFSCL_DEBUG(4, "nfsrpc_writeds: len=%d rlen=%d\n", len, rlen);
- if (rlen == 0) {
+ if (rlen <= 0 || rlen > len) {
error = NFSERR_IO;
goto nfsmout;
} else if (rlen < len) {
@@ -8117,7 +8129,7 @@ nfsrv_parseug(struct nfsrv_descript *nd, int dogrp, uid_t *uidp, gid_t *gidp,
NFSPROC_T *p)
{
uint32_t *tl;
- char *cp, *str, str0[NFSV4_SMALLSTR + 1];
+ char *str, str0[NFSV4_SMALLSTR + 1];
uint32_t len = 0;
int error = 0;
@@ -8140,9 +8152,9 @@ nfsrv_parseug(struct nfsrv_descript *nd, int dogrp, uid_t *uidp, gid_t *gidp,
str = malloc(len + 1, M_TEMP, M_WAITOK);
else
str = str0;
- NFSM_DISSECT(cp, char *, NFSM_RNDUP(len));
- NFSBCOPY(cp, str, len);
- str[len] = '\0';
+ error = nfsrv_mtostr(nd, str, len);
+ if (error != 0)
+ goto nfsmout;
NFSCL_DEBUG(4, "nfsrv_parseug: str=%s\n", str);
if (dogrp != 0)
error = nfsv4_strtogid(nd, str, len, gidp);
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 88ae643d193e..6047e6f2970e 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -4950,6 +4950,11 @@ nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram,
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
layouttype = fxdr_unsigned(int, *tl++);
maxcnt = fxdr_unsigned(int, *tl);
+ /* There is no limit in the RFC, so use 1000 as a sanity limit. */
+ if (maxcnt < 0 || maxcnt > 1000) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
if (maxcnt > 0) {
layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
error = nfsrv_mtostr(nd, layp, maxcnt);
diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c
index e43c88b3a27b..735efe307215 100644
--- a/sys/x86/x86/mca.c
+++ b/sys/x86/x86/mca.c
@@ -46,9 +46,11 @@
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
+#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <machine/intr_machdep.h>
@@ -124,6 +126,22 @@ SYSCTL_INT(_hw_mca, OID_AUTO, erratum383, CTLFLAG_RDTUN,
&workaround_erratum383, 0,
"Is the workaround for Erratum 383 on AMD Family 10h processors enabled?");
+#ifdef DIAGNOSTIC
+static uint64_t fake_status;
+SYSCTL_U64(_hw_mca, OID_AUTO, fake_status, CTLFLAG_RW,
+ &fake_status, 0,
+ "Insert artificial MCA with given status (testing purpose only)");
+static int fake_bank;
+SYSCTL_INT(_hw_mca, OID_AUTO, fake_bank, CTLFLAG_RW,
+ &fake_bank, 0,
+ "Bank to use for artificial MCAs (testing purpose only)");
+#endif
+
+static bool mca_uselog = false;
+SYSCTL_BOOL(_hw_mca, OID_AUTO, uselog, CTLFLAG_RWTUN, &mca_uselog, 0,
+ "Should the system send non-fatal machine check errors to the log "
+ "(instead of the console)?");
+
static STAILQ_HEAD(, mca_internal) mca_freelist;
static int mca_freecount;
static STAILQ_HEAD(, mca_internal) mca_records;
@@ -136,12 +154,40 @@ static struct timeout_task mca_scan_task;
static struct mtx mca_lock;
static bool mca_startup_done = false;
-/* Statistics on number of MCA events by type, updated atomically. */
+/* Static buffer to compose messages while in an interrupt context. */
+static char mca_msg_buf[1024];
+static struct mtx mca_msg_buf_lock;
+
+/* Statistics on number of MCA events by type, updated with the mca_lock. */
static uint64_t mca_stats[MCA_T_COUNT];
SYSCTL_OPAQUE(_hw_mca, OID_AUTO, stats, CTLFLAG_RD | CTLFLAG_SKIP,
mca_stats, MCA_T_COUNT * sizeof(mca_stats[0]),
"S", "Array of MCA events by type");
+/* Variables to track and control message rate limiting. */
+static struct timeval mca_last_log_time;
+static struct timeval mca_log_interval;
+static int mca_log_skipped;
+
+static int
+sysctl_mca_log_interval(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ u_int val;
+
+ val = mca_log_interval.tv_sec;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ mca_log_interval.tv_sec = val;
+ return (0);
+}
+SYSCTL_PROC(_hw_mca, OID_AUTO, log_interval,
+ CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &mca_log_interval, 0,
+ sysctl_mca_log_interval, "IU",
+ "Minimum number of seconds between logging correctable MCAs"
+ " (0 = no limit)");
+
static unsigned int
mca_ia32_ctl_reg(int bank)
{
@@ -437,98 +483,111 @@ mca_mute(const struct mca_record *rec)
/* Dump details about a single machine check. */
static void
-mca_log(const struct mca_record *rec)
+mca_log(enum scan_mode mode, const struct mca_record *rec, bool fatal)
{
+ int error, numskipped;
uint16_t mca_error;
enum mca_stat_types event_type;
+ struct sbuf sb;
+ bool uncor, using_shared_buf;
if (mca_mute(rec))
return;
- if (!log_corrected && (rec->mr_status & MC_STATUS_UC) == 0 &&
- (!tes_supported(rec->mr_mcg_cap) ||
+ uncor = (rec->mr_status & MC_STATUS_UC) != 0;
+
+ if (!log_corrected && !uncor && (!tes_supported(rec->mr_mcg_cap) ||
((rec->mr_status & MC_STATUS_TES_STATUS) >> 53) != 0x2))
return;
- printf("MCA: Bank %d, Status 0x%016llx\n", rec->mr_bank,
+ /* Try to use an allocated buffer when not in an interrupt context. */
+ if (mode == POLLED && sbuf_new(&sb, NULL, 512, SBUF_AUTOEXTEND) != NULL)
+ using_shared_buf = false;
+ else {
+ using_shared_buf = true;
+ mtx_lock_spin(&mca_msg_buf_lock);
+ sbuf_new(&sb, mca_msg_buf, sizeof(mca_msg_buf), SBUF_FIXEDLEN);
+ }
+
+ sbuf_printf(&sb, "MCA: Bank %d, Status 0x%016llx\n", rec->mr_bank,
(long long)rec->mr_status);
- printf("MCA: Global Cap 0x%016llx, Status 0x%016llx\n",
+ sbuf_printf(&sb, "MCA: Global Cap 0x%016llx, Status 0x%016llx\n",
(long long)rec->mr_mcg_cap, (long long)rec->mr_mcg_status);
- printf("MCA: Vendor \"%s\", ID 0x%x, APIC ID %d\n", cpu_vendor,
- rec->mr_cpu_id, rec->mr_apic_id);
- printf("MCA: CPU %d ", rec->mr_cpu);
+ sbuf_printf(&sb, "MCA: Vendor \"%s\", ID 0x%x, APIC ID %d\n",
+ cpu_vendor, rec->mr_cpu_id, rec->mr_apic_id);
+ sbuf_printf(&sb, "MCA: CPU %d ", rec->mr_cpu);
if (rec->mr_status & MC_STATUS_UC)
- printf("UNCOR ");
+ sbuf_printf(&sb, "UNCOR ");
else {
- printf("COR ");
+ sbuf_printf(&sb, "COR ");
if (cmci_supported(rec->mr_mcg_cap))
- printf("(%lld) ", ((long long)rec->mr_status &
+ sbuf_printf(&sb, "(%lld) ", ((long long)rec->mr_status &
MC_STATUS_COR_COUNT) >> 38);
if (tes_supported(rec->mr_mcg_cap)) {
switch ((rec->mr_status & MC_STATUS_TES_STATUS) >> 53) {
case 0x1:
- printf("(Green) ");
+ sbuf_printf(&sb, "(Green) ");
break;
case 0x2:
- printf("(Yellow) ");
+ sbuf_printf(&sb, "(Yellow) ");
break;
}
}
}
if (rec->mr_status & MC_STATUS_EN)
- printf("EN ");
+ sbuf_printf(&sb, "EN ");
if (rec->mr_status & MC_STATUS_PCC)
- printf("PCC ");
+ sbuf_printf(&sb, "PCC ");
if (ser_supported(rec->mr_mcg_cap)) {
if (rec->mr_status & MC_STATUS_S)
- printf("S ");
+ sbuf_printf(&sb, "S ");
if (rec->mr_status & MC_STATUS_AR)
- printf("AR ");
+ sbuf_printf(&sb, "AR ");
}
if (rec->mr_status & MC_STATUS_OVER)
- printf("OVER ");
+ sbuf_printf(&sb, "OVER ");
mca_error = rec->mr_status & MC_STATUS_MCA_ERROR;
event_type = MCA_T_COUNT;
switch (mca_error) {
/* Simple error codes. */
case 0x0000:
- printf("no error");
+ sbuf_printf(&sb, "no error");
event_type = MCA_T_NONE;
break;
case 0x0001:
- printf("unclassified error");
+ sbuf_printf(&sb, "unclassified error");
event_type = MCA_T_UNCLASSIFIED;
break;
case 0x0002:
- printf("ucode ROM parity error");
+ sbuf_printf(&sb, "ucode ROM parity error");
event_type = MCA_T_UCODE_ROM_PARITY;
break;
case 0x0003:
- printf("external error");
+ sbuf_printf(&sb, "external error");
event_type = MCA_T_EXTERNAL;
break;
case 0x0004:
- printf("FRC error");
+ sbuf_printf(&sb, "FRC error");
event_type = MCA_T_FRC;
break;
case 0x0005:
- printf("internal parity error");
+ sbuf_printf(&sb, "internal parity error");
event_type = MCA_T_INTERNAL_PARITY;
break;
case 0x0006:
- printf("SMM handler code access violation");
+ sbuf_printf(&sb, "SMM handler code access violation");
event_type = MCA_T_SMM_HANDLER;
break;
case 0x0400:
- printf("internal timer error");
+ sbuf_printf(&sb, "internal timer error");
event_type = MCA_T_INTERNAL_TIMER;
break;
case 0x0e0b:
- printf("generic I/O error");
+ sbuf_printf(&sb, "generic I/O error");
event_type = MCA_T_GENERIC_IO;
if (rec->mr_cpu_vendor_id == CPU_VENDOR_INTEL &&
(rec->mr_status & MC_STATUS_MISCV)) {
- printf(" (pci%d:%d:%d:%d)",
+ sbuf_printf(&sb, " (pci%d:%d:%d:%d)",
(int)((rec->mr_misc & MC_MISC_PCIE_SEG) >> 32),
(int)((rec->mr_misc & MC_MISC_PCIE_BUS) >> 24),
(int)((rec->mr_misc & MC_MISC_PCIE_SLOT) >> 19),
@@ -537,7 +596,8 @@ mca_log(const struct mca_record *rec)
break;
default:
if ((mca_error & 0xfc00) == 0x0400) {
- printf("internal error %x", mca_error & 0x03ff);
+ sbuf_printf(&sb, "internal error %x",
+ mca_error & 0x03ff);
event_type = MCA_T_INTERNAL;
break;
}
@@ -546,14 +606,16 @@ mca_log(const struct mca_record *rec)
/* Memory hierarchy error. */
if ((mca_error & 0xeffc) == 0x000c) {
- printf("%s memory error", mca_error_level(mca_error));
+ sbuf_printf(&sb, "%s memory error",
+ mca_error_level(mca_error));
event_type = MCA_T_MEMORY;
break;
}
/* TLB error. */
if ((mca_error & 0xeff0) == 0x0010) {
- printf("%sTLB %s error", mca_error_ttype(mca_error),
+ sbuf_printf(&sb, "%sTLB %s error",
+ mca_error_ttype(mca_error),
mca_error_level(mca_error));
event_type = MCA_T_TLB;
break;
@@ -561,19 +623,19 @@ mca_log(const struct mca_record *rec)
/* Memory controller error. */
if ((mca_error & 0xef80) == 0x0080) {
- printf("%s channel ", mca_error_mmtype(mca_error,
- &event_type));
+ sbuf_printf(&sb, "%s channel ",
+ mca_error_mmtype(mca_error, &event_type));
if ((mca_error & 0x000f) != 0x000f)
- printf("%d", mca_error & 0x000f);
+ sbuf_printf(&sb, "%d", mca_error & 0x000f);
else
- printf("??");
- printf(" memory error");
+ sbuf_printf(&sb, "??");
+ sbuf_printf(&sb, " memory error");
break;
}
/* Cache error. */
if ((mca_error & 0xef00) == 0x0100) {
- printf("%sCACHE %s %s error",
+ sbuf_printf(&sb, "%sCACHE %s %s error",
mca_error_ttype(mca_error),
mca_error_level(mca_error),
mca_error_request(mca_error));
@@ -583,77 +645,129 @@ mca_log(const struct mca_record *rec)
/* Extended memory error. */
if ((mca_error & 0xef80) == 0x0280) {
- printf("%s channel ", mca_error_mmtype(mca_error,
- &event_type));
+ sbuf_printf(&sb, "%s channel ",
+ mca_error_mmtype(mca_error, &event_type));
if ((mca_error & 0x000f) != 0x000f)
- printf("%d", mca_error & 0x000f);
+ sbuf_printf(&sb, "%d", mca_error & 0x000f);
else
- printf("??");
- printf(" extended memory error");
+ sbuf_printf(&sb, "??");
+ sbuf_printf(&sb, " extended memory error");
break;
}
/* Bus and/or Interconnect error. */
if ((mca_error & 0xe800) == 0x0800) {
- printf("BUS%s ", mca_error_level(mca_error));
+ sbuf_printf(&sb, "BUS%s ", mca_error_level(mca_error));
event_type = MCA_T_BUS;
switch ((mca_error & 0x0600) >> 9) {
case 0:
- printf("Source");
+ sbuf_printf(&sb, "Source");
break;
case 1:
- printf("Responder");
+ sbuf_printf(&sb, "Responder");
break;
case 2:
- printf("Observer");
+ sbuf_printf(&sb, "Observer");
break;
default:
- printf("???");
+ sbuf_printf(&sb, "???");
break;
}
- printf(" %s ", mca_error_request(mca_error));
+ sbuf_printf(&sb, " %s ", mca_error_request(mca_error));
switch ((mca_error & 0x000c) >> 2) {
case 0:
- printf("Memory");
+ sbuf_printf(&sb, "Memory");
break;
case 2:
- printf("I/O");
+ sbuf_printf(&sb, "I/O");
break;
case 3:
- printf("Other");
+ sbuf_printf(&sb, "Other");
break;
default:
- printf("???");
+ sbuf_printf(&sb, "???");
break;
}
if (mca_error & 0x0100)
- printf(" timed out");
+ sbuf_printf(&sb, " timed out");
break;
}
- printf("unknown error %x", mca_error);
+ sbuf_printf(&sb, "unknown error %x", mca_error);
event_type = MCA_T_UNKNOWN;
break;
}
- printf("\n");
+ sbuf_printf(&sb, "\n");
if (rec->mr_status & MC_STATUS_ADDRV) {
- printf("MCA: Address 0x%llx", (long long)rec->mr_addr);
+ sbuf_printf(&sb, "MCA: Address 0x%llx",
+ (long long)rec->mr_addr);
if (ser_supported(rec->mr_mcg_cap) &&
(rec->mr_status & MC_STATUS_MISCV)) {
- printf(" (Mode: %s, LSB: %d)",
+ sbuf_printf(&sb, " (Mode: %s, LSB: %d)",
mca_addres_mode(rec->mr_misc),
(int)(rec->mr_misc & MC_MISC_RA_LSB));
}
- printf("\n");
+ sbuf_printf(&sb, "\n");
}
if (rec->mr_status & MC_STATUS_MISCV)
- printf("MCA: Misc 0x%llx\n", (long long)rec->mr_misc);
+ sbuf_printf(&sb, "MCA: Misc 0x%llx\n", (long long)rec->mr_misc);
+
if (event_type < 0 || event_type >= MCA_T_COUNT) {
KASSERT(0, ("%s: invalid event type (%d)", __func__,
event_type));
event_type = MCA_T_UNKNOWN;
}
- atomic_add_64(&mca_stats[event_type], 1);
+ numskipped = 0;
+ if (!fatal && !uncor) {
+ /*
+ * Update statistics and check the rate limit for
+ * correctable errors. The rate limit is only applied
+ * after the system records a reasonable number of errors
+ * of the same type. The goal is to reduce the impact of
+ * the system seeing and attempting to log a burst of
+ * similar errors, which (especially when printed to the
+ * console) can be expensive.
+ */
+ mtx_lock_spin(&mca_lock);
+ mca_stats[event_type]++;
+ if (mca_log_interval.tv_sec > 0 && mca_stats[event_type] > 50 &&
+ ratecheck(&mca_last_log_time, &mca_log_interval) == 0) {
+ mca_log_skipped++;
+ mtx_unlock_spin(&mca_lock);
+ goto done;
+ }
+ numskipped = mca_log_skipped;
+ mca_log_skipped = 0;
+ mtx_unlock_spin(&mca_lock);
+ }
+
+ error = sbuf_finish(&sb);
+ if (fatal || !mca_uselog) {
+ if (numskipped > 0)
+ printf("MCA: %d events skipped due to rate limit\n",
+ numskipped);
+ if (error)
+ printf("MCA: error logging message (sbuf error %d)\n",
+ error);
+ else
+ sbuf_putbuf(&sb);
+ } else {
+ if (numskipped > 0)
+ log(LOG_ERR,
+ "MCA: %d events skipped due to rate limit\n",
+ numskipped);
+ if (error)
+ log(LOG_ERR,
+ "MCA: error logging message (sbuf error %d)\n",
+ error);
+ else
+ log(uncor ? LOG_CRIT : LOG_ERR, "%s", sbuf_data(&sb));
+ }
+
+done:
+ sbuf_delete(&sb);
+ if (using_shared_buf)
+ mtx_unlock_spin(&mca_msg_buf_lock);
}
static bool
@@ -701,8 +815,24 @@ mca_check_status(enum scan_mode mode, uint64_t mcg_cap, int bank,
bool mce, recover;
status = rdmsr(mca_msr_ops.status(bank));
- if (!(status & MC_STATUS_VAL))
+ if (!(status & MC_STATUS_VAL)) {
+#ifdef DIAGNOSTIC
+ /*
+ * Check if we have a pending artificial event to generate.
+ * Note that this is potentially racy with the sysctl. The
+ * tradeoff is deemed acceptable given the test nature
+ * of the code.
+ */
+ if (fake_status && bank == fake_bank) {
+ status = fake_status;
+ fake_status = 0;
+ }
+ if (!(status & MC_STATUS_VAL))
+ return (0);
+#else
return (0);
+#endif
+ }
recover = *recoverablep;
mce = mca_is_mce(mcg_cap, status, &recover);
@@ -796,9 +926,9 @@ mca_record_entry(enum scan_mode mode, const struct mca_record *record)
mtx_lock_spin(&mca_lock);
rec = STAILQ_FIRST(&mca_freelist);
if (rec == NULL) {
- printf("MCA: Unable to allocate space for an event.\n");
- mca_log(record);
mtx_unlock_spin(&mca_lock);
+ printf("MCA: Unable to allocate space for an event.\n");
+ mca_log(mode, record, false);
return;
}
STAILQ_REMOVE_HEAD(&mca_freelist, link);
@@ -955,7 +1085,7 @@ mca_scan(enum scan_mode mode, bool *recoverablep)
if (*recoverablep)
mca_record_entry(mode, &rec);
else
- mca_log(&rec);
+ mca_log(mode, &rec, true);
}
#ifdef DEV_APIC
@@ -1017,6 +1147,7 @@ static void
mca_process_records(enum scan_mode mode)
{
struct mca_internal *mca;
+ STAILQ_HEAD(, mca_internal) tmplist;
/*
* If in an interrupt context, defer the post-scan activities to a
@@ -1028,10 +1159,21 @@ mca_process_records(enum scan_mode mode)
return;
}
+ /*
+ * Copy the pending list to the stack so we can drop the spin lock
+ * while we are emitting logs.
+ */
+ STAILQ_INIT(&tmplist);
+ mtx_lock_spin(&mca_lock);
+ STAILQ_SWAP(&mca_pending, &tmplist, mca_internal);
+ mtx_unlock_spin(&mca_lock);
+
+ STAILQ_FOREACH(mca, &tmplist, link)
+ mca_log(mode, &mca->rec, false);
+
mtx_lock_spin(&mca_lock);
- while ((mca = STAILQ_FIRST(&mca_pending)) != NULL) {
- STAILQ_REMOVE_HEAD(&mca_pending, link);
- mca_log(&mca->rec);
+ while ((mca = STAILQ_FIRST(&tmplist)) != NULL) {
+ STAILQ_REMOVE_HEAD(&tmplist, link);
mca_store_record(mca);
}
mtx_unlock_spin(&mca_lock);
@@ -1192,6 +1334,7 @@ mca_setup(uint64_t mcg_cap)
mca_banks = mcg_cap & MCG_CAP_COUNT;
mtx_init(&mca_lock, "mca", NULL, MTX_SPIN);
+ mtx_init(&mca_msg_buf_lock, "mca_msg_buf", NULL, MTX_SPIN);
STAILQ_INIT(&mca_records);
STAILQ_INIT(&mca_pending);
mca_tq = taskqueue_create_fast("mca", M_WAITOK,
diff --git a/usr.bin/id/id.1 b/usr.bin/id/id.1
index eab875c635ef..a03926e702e4 100644
--- a/usr.bin/id/id.1
+++ b/usr.bin/id/id.1
@@ -30,7 +30,7 @@
.\"
.\" @(#)id.1 8.1 (Berkeley) 6/6/93
.\"
-.Dd March 5, 2011
+.Dd October 23, 2025
.Dt ID 1
.Os
.Sh NAME
@@ -52,12 +52,18 @@
.Nm
.Fl c
.Nm
+.Fl d
+.Op Ar user
+.Nm
.Fl g Op Fl nr
.Op Ar user
.Nm
.Fl p
.Op Ar user
.Nm
+.Fl s
+.Op Ar user
+.Nm
.Fl u Op Fl nr
.Op Ar user
.Sh DESCRIPTION
@@ -92,6 +98,8 @@ Ignored for compatibility with other
implementations.
.It Fl c
Display current login class.
+.It Fl d
+Display the home directory of the current or specified user.
.It Fl g
Display the effective group ID as a number.
.It Fl n
@@ -130,6 +138,8 @@ Display the real ID for the
and
.Fl u
options instead of the effective ID.
+.It Fl s
+Display the shell of the current or specified user.
.It Fl u
Display the effective user ID as a number.
.El
@@ -176,8 +186,20 @@ bob pts/5 Dec 4 19:51
.Sh STANDARDS
The
.Nm
-function is expected to conform to
-.St -p1003.2 .
+utility is expected to conform to
+.St -p1003.1-2024 .
+The
+.Fl A ,
+.Fl M ,
+.Fl P ,
+.Fl c ,
+.Fl d ,
+.Fl p ,
+and
+.Fl s
+options are
+.Fx
+extensions.
.Sh HISTORY
The
historic
diff --git a/usr.bin/id/id.c b/usr.bin/id/id.c
index 772558191306..238c6f2bf709 100644
--- a/usr.bin/id/id.c
+++ b/usr.bin/id/id.c
@@ -52,91 +52,107 @@ static char sccsid[] = "@(#)id.c 8.2 (Berkeley) 2/16/94";
#include <errno.h>
#include <grp.h>
#include <pwd.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-static void id_print(struct passwd *, int, int, int);
+static void id_print(struct passwd *);
static void pline(struct passwd *);
static void pretty(struct passwd *);
#ifdef USE_BSM_AUDIT
static void auditid(void);
#endif
-static void group(struct passwd *, int);
+static void group(struct passwd *, bool);
static void maclabel(void);
+static void dir(struct passwd *);
+static void shell(struct passwd *);
static void usage(void);
static struct passwd *who(char *);
-static int isgroups, iswhoami;
+static bool isgroups, iswhoami;
int
main(int argc, char *argv[])
{
struct group *gr;
struct passwd *pw;
- int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
- int Aflag, cflag;
- int error;
- const char *myname;
+#ifdef USE_BSM_AUDIT
+ bool Aflag;
+#endif
+ bool Gflag, Mflag, Pflag;
+ bool cflag, dflag, gflag, nflag, pflag, rflag, sflag, uflag;
+ int ch, combo, error, id;
+ const char *myname, *optstr;
char loginclass[MAXLOGNAME];
- Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
- Aflag = cflag = 0;
+#ifdef USE_BSM_AUDIT
+ Aflag = false;
+#endif
+ Gflag = Mflag = Pflag = false;
+ cflag = dflag = gflag = nflag = pflag = rflag = sflag = uflag = false;
- myname = strrchr(argv[0], '/');
- myname = (myname != NULL) ? myname + 1 : argv[0];
+ myname = getprogname();
+ optstr = "AGMPacdgnprsu";
if (strcmp(myname, "groups") == 0) {
- isgroups = 1;
- Gflag = nflag = 1;
+ isgroups = true;
+ optstr = "";
+ Gflag = nflag = true;
}
else if (strcmp(myname, "whoami") == 0) {
- iswhoami = 1;
- uflag = nflag = 1;
+ iswhoami = true;
+ optstr = "";
+ uflag = nflag = true;
}
- while ((ch = getopt(argc, argv,
- (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
+ while ((ch = getopt(argc, argv, optstr)) != -1) {
switch(ch) {
#ifdef USE_BSM_AUDIT
case 'A':
- Aflag = 1;
+ Aflag = true;
break;
#endif
case 'G':
- Gflag = 1;
+ Gflag = true;
break;
case 'M':
- Mflag = 1;
+ Mflag = true;
break;
case 'P':
- Pflag = 1;
+ Pflag = true;
break;
case 'a':
break;
case 'c':
- cflag = 1;
+ cflag = true;
+ break;
+ case 'd':
+ dflag = true;
break;
case 'g':
- gflag = 1;
+ gflag = true;
break;
case 'n':
- nflag = 1;
+ nflag = true;
break;
case 'p':
- pflag = 1;
+ pflag = true;
break;
case 'r':
- rflag = 1;
+ rflag = true;
+ break;
+ case 's':
+ sflag = true;
break;
case 'u':
- uflag = 1;
+ uflag = true;
break;
- case '?':
default:
usage();
}
+ }
argc -= optind;
argv += optind;
@@ -145,16 +161,13 @@ main(int argc, char *argv[])
if ((cflag || Aflag || Mflag) && argc > 0)
usage();
- switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
- case 1:
- break;
- case 0:
- if (!nflag && !rflag)
- break;
- /* FALLTHROUGH */
- default:
+ combo = Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag;
+ if (combo + dflag + sflag > 1)
+ usage();
+ if (combo > 1)
+ usage();
+ if (combo == 0 && (nflag || rflag))
usage();
- }
pw = *argv ? who(*argv) : NULL;
@@ -194,6 +207,11 @@ main(int argc, char *argv[])
exit(0);
}
+ if (dflag) {
+ dir(pw);
+ exit(0);
+ }
+
if (Gflag) {
group(pw, nflag);
exit(0);
@@ -214,14 +232,12 @@ main(int argc, char *argv[])
exit(0);
}
- if (pw) {
- id_print(pw, 1, 0, 0);
- }
- else {
- id = getuid();
- pw = getpwuid(id);
- id_print(pw, 0, 1, 1);
+ if (sflag) {
+ shell(pw);
+ exit(0);
}
+
+ id_print(pw);
exit(0);
}
@@ -235,7 +251,7 @@ pretty(struct passwd *pw)
if (pw) {
(void)printf("uid\t%s\n", pw->pw_name);
(void)printf("groups\t");
- group(pw, 1);
+ group(pw, true);
} else {
if ((login = getlogin()) == NULL)
err(1, "getlogin");
@@ -261,12 +277,12 @@ pretty(struct passwd *pw)
(void)printf("rgid\t%u\n", rid);
}
(void)printf("groups\t");
- group(NULL, 1);
+ group(NULL, true);
}
}
static void
-id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
+id_print(struct passwd *pw)
{
struct group *gr;
gid_t gid, egid, lastgid;
@@ -275,21 +291,24 @@ id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
long ngroups_max;
gid_t *groups;
const char *fmt;
+ bool print_dbinfo;
- if (pw != NULL) {
+ print_dbinfo = pw != NULL;
+ if (print_dbinfo) {
uid = pw->pw_uid;
gid = pw->pw_gid;
}
else {
uid = getuid();
gid = getgid();
+ pw = getpwuid(uid);
}
ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
err(1, "malloc");
- if (use_ggl && pw != NULL) {
+ if (print_dbinfo) {
ngroups = ngroups_max;
getgrouplist(pw->pw_name, gid, groups, &ngroups);
}
@@ -297,19 +316,23 @@ id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
ngroups = getgroups(ngroups_max, groups);
}
+ /*
+ * We always resolve uids and gids where we can to a name, even if we
+ * are printing the running process credentials, to be nice.
+ */
if (pw != NULL)
printf("uid=%u(%s)", uid, pw->pw_name);
- else
- printf("uid=%u", getuid());
+ else
+ printf("uid=%u", uid);
printf(" gid=%u", gid);
if ((gr = getgrgid(gid)))
(void)printf("(%s)", gr->gr_name);
- if (p_euid && (euid = geteuid()) != uid) {
+ if (!print_dbinfo && (euid = geteuid()) != uid) {
(void)printf(" euid=%u", euid);
if ((pw = getpwuid(euid)))
(void)printf("(%s)", pw->pw_name);
}
- if (p_egid && (egid = getegid()) != gid) {
+ if (!print_dbinfo && (egid = getegid()) != gid) {
(void)printf(" egid=%u", egid);
if ((gr = getgrgid(egid)))
(void)printf("(%s)", gr->gr_name);
@@ -377,7 +400,7 @@ auditid(void)
#endif
static void
-group(struct passwd *pw, int nflag)
+group(struct passwd *pw, bool nflag)
{
struct group *gr;
int cnt, id, lastid, ngroups;
@@ -463,41 +486,57 @@ who(char *u)
static void
pline(struct passwd *pw)
{
-
- if (!pw) {
+ if (pw == NULL) {
if ((pw = getpwuid(getuid())) == NULL)
err(1, "getpwuid");
}
-
(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
- pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
- (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
- pw->pw_dir, pw->pw_shell);
+ pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
+ (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
+ pw->pw_dir, pw->pw_shell);
}
+static void
+dir(struct passwd *pw)
+{
+ if (pw == NULL) {
+ if ((pw = getpwuid(getuid())) == NULL)
+ err(1, "getpwuid");
+ }
+ printf("%s\n", pw->pw_dir);
+}
static void
-usage(void)
+shell(struct passwd *pw)
{
+ if (pw == NULL) {
+ if ((pw = getpwuid(getuid())) == NULL)
+ err(1, "getpwuid");
+ }
+ printf("%s\n", pw->pw_shell);
+}
+static void
+usage(void)
+{
if (isgroups)
(void)fprintf(stderr, "usage: groups [user]\n");
else if (iswhoami)
(void)fprintf(stderr, "usage: whoami\n");
else
- (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
- "usage: id [user]",
+ (void)fprintf(stderr,
+ "usage: id [user]\n"
#ifdef USE_BSM_AUDIT
- " id -A\n",
-#else
- "",
+ " id -A\n"
#endif
- " id -G [-n] [user]",
- " id -M",
- " id -P [user]",
- " id -c",
- " id -g [-nr] [user]",
- " id -p [user]",
- " id -u [-nr] [user]");
+ " id -G [-n] [user]\n"
+ " id -M\n"
+ " id -P [user]\n"
+ " id -c\n"
+ " id -d [user]\n"
+ " id -g [-nr] [user]\n"
+ " id -p [user]\n"
+ " id -s [user]\n"
+ " id -u [-nr] [user]\n");
exit(1);
}