diff options
| -rw-r--r-- | bin/pwait/pwait.1 | 6 | ||||
| -rw-r--r-- | bin/pwait/pwait.c | 102 | ||||
| -rw-r--r-- | bin/pwait/tests/pwait_test.sh | 38 | ||||
| -rw-r--r-- | contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h | 5 | ||||
| -rw-r--r-- | lib/libc/string/ffs.3 | 15 | ||||
| -rw-r--r-- | libexec/rc/rc.subr | 29 | ||||
| -rw-r--r-- | sbin/ipfw/dummynet.c | 4 | ||||
| -rw-r--r-- | sbin/ipfw/ipfw2.c | 8 | ||||
| -rw-r--r-- | share/examples/mdoc/example.1 | 23 | ||||
| -rw-r--r-- | share/examples/mdoc/example.3 | 23 | ||||
| -rw-r--r-- | share/examples/mdoc/example.4 | 23 | ||||
| -rw-r--r-- | share/examples/mdoc/example.9 | 23 | ||||
| -rw-r--r-- | share/man/man5/style.mdoc.5 | 30 | ||||
| -rw-r--r-- | share/man/man9/g_bio.9 | 3 | ||||
| -rw-r--r-- | share/man/man9/uio.9 | 14 | ||||
| -rw-r--r-- | sys/arm/include/ieeefp.h | 10 | ||||
| -rw-r--r-- | sys/arm64/arm64/elf32_machdep.c | 2 | ||||
| -rw-r--r-- | sys/fs/deadfs/dead_vnops.c | 10 | ||||
| -rw-r--r-- | sys/fs/nfs/nfs_commonsubs.c | 13 | ||||
| -rw-r--r-- | sys/fs/nfsclient/nfs_clrpcops.c | 34 | ||||
| -rw-r--r-- | sys/fs/nfsserver/nfs_nfsdserv.c | 5 | ||||
| -rw-r--r-- | sys/x86/x86/mca.c | 279 | ||||
| -rw-r--r-- | usr.bin/id/id.1 | 28 | ||||
| -rw-r--r-- | usr.bin/id/id.c | 185 | 
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);  } | 
