diff options
Diffstat (limited to 'usr.sbin')
38 files changed, 1174 insertions, 676 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 44679ca290a5..0290ed4f1c58 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -117,6 +117,7 @@ SUBDIR.${MK_AUDIT}+= auditdistd .endif SUBDIR.${MK_AUDIT}+= auditreduce SUBDIR.${MK_AUDIT}+= praudit +SUBDIR.${MK_AUDIT}+= setaudit SUBDIR.${MK_AUTHPF}+= authpf SUBDIR.${MK_AUTOFS}+= autofs SUBDIR.${MK_BLACKLIST}+= blacklistctl diff --git a/usr.sbin/apm/Makefile b/usr.sbin/apm/Makefile index f6c42194401f..f9b3e11d22fa 100644 --- a/usr.sbin/apm/Makefile +++ b/usr.sbin/apm/Makefile @@ -1,6 +1,5 @@ PROG= apm MAN= apm.8 -MLINKS= apm.8 apmconf.8 MANSUBDIR= /${MACHINE_CPUARCH} PACKAGE=apm diff --git a/usr.sbin/apm/apm.8 b/usr.sbin/apm/apm.8 index d6ede22066da..e295ec989a73 100644 --- a/usr.sbin/apm/apm.8 +++ b/usr.sbin/apm/apm.8 @@ -9,7 +9,7 @@ .\" the author assume any responsibility for damages incurred with its .\" use. .\" -.Dd December 22, 2009 +.Dd November 12, 2025 .Dt APM 8 i386 .Os .Sh NAME @@ -120,13 +120,6 @@ If no options are specified, displays information and current status of APM in verbose mode. If multiple display options are given, the values are displayed one per line in the order given here. -.Sh NOTES -.Xr apmconf 8 -has been merged in -.Nm -and thus -.Nm -replaces all of its functionality. .Sh SEE ALSO .Xr apm 4 , .Xr zzz 8 diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index e5e8bf9b5567..c454a280edba 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -77,6 +77,8 @@ SRCS+= snapshot.c .include "${MACHINE_CPUARCH}/Makefile.inc" +SUBDIR+= slirp + .if defined(BHYVE_FDT_SUPPORT) LIBADD+= fdt CFLAGS+= -I${SRCTOP}/sys/contrib/libfdt diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index 27e067f50394..45450b5b5db5 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -532,7 +532,9 @@ considered unconnected. .Xc .It .Xo -.Cm slirp,hostfwd= Ar proto : Ar hostaddr : Ar hostport - Ar guestaddr : Ar guestport +.Cm slirp +.Op Cm \&,open +.Op Cm \&,hostfwd= Ar proto : Ar hostaddr : Ar hostport - Ar guestaddr : Ar guestport .Xc .El .Sm on @@ -598,6 +600,12 @@ configuration on the host system. It depends on the .Pa net/libslirp port. +If the +.Cm open +keyword is set, the guest will be able to make outbound network +connections, and +.Nm +will transparently handle the necessary address translation. The .Cm hostfwd option takes a 5-tuple describing how connections from the host are to be @@ -605,6 +613,7 @@ forwarded to the guest. Multiple rules can be specified, separated by semicolons. Note that semicolons must be escaped or quoted to prevent the shell from interpreting them. +The backend will provide DHCP and DNS service to the guest. .Ss Block storage device backends: .Bl -bullet .Sm off diff --git a/usr.sbin/bhyve/net_backend_slirp.c b/usr.sbin/bhyve/net_backend_slirp.c index 171c5b5bdbbd..c98e54b2ee88 100644 --- a/usr.sbin/bhyve/net_backend_slirp.c +++ b/usr.sbin/bhyve/net_backend_slirp.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2023 Mark Johnston <markj@FreeBSD.org> + * Copyright (c) 2023, 2025 Mark Johnston <markj@FreeBSD.org> * * This software was developed by the University of Cambridge Computer * Laboratory (Department of Computer Science and Technology) under Innovate @@ -31,13 +31,15 @@ */ /* - * The slirp backend enables unprivileged networking via libslirp, which must be - * installed on the host system via pkg or the ports tree. bhyve dlopen()s - * libslirp.so upon instantiating the slirp backend. Various network parameters - * are hard-coded in _slirp_init(). + * The slirp backend enables unprivileged userspace networking via libslirp, + * which must be installed on the host system via pkg or the ports tree. + * libslirp.so is dlopen()ed into a helper process with which this backend + * communicates. * * Packets received from the guest (i.e., transmitted by the frontend, such as a - * virtio NIC device model) are injected into the slirp backend via slirp_send(). + * virtio NIC device model) are injected into the slirp backend via slirp_send(), + * which sends the packet to the helper process. + * * Packets to be transmitted to the guest (i.e., inserted into the frontend's * receive buffers) are buffered in a per-interface socket pair and read by the * mevent loop. Sockets instantiated by libslirp are monitored by a thread @@ -46,14 +48,12 @@ */ #include <sys/socket.h> +#include <sys/wait.h> #include <assert.h> -#include <capsicum_helpers.h> -#include <dlfcn.h> #include <errno.h> -#include <poll.h> -#include <pthread.h> -#include <pthread_np.h> +#include <signal.h> +#include <spawn.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -61,537 +61,92 @@ #include "config.h" #include "debug.h" -#include "libslirp.h" #include "mevent.h" #include "net_backends.h" #include "net_backends_priv.h" -typedef int (*slirp_add_hostxfwd_p_t)(Slirp *, - const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t, - int); -typedef void (*slirp_cleanup_p_t)(Slirp *); -typedef void (*slirp_input_p_t)(Slirp *, const uint8_t *, int); -typedef Slirp *(*slirp_new_p_t)(const SlirpConfig *, const SlirpCb *, void *); -typedef void (*slirp_pollfds_fill_p_t)(Slirp *, uint32_t *timeout, - SlirpAddPollCb, void *); -typedef void (*slirp_pollfds_poll_p_t)(Slirp *, int, SlirpGetREventsCb, void *); - -/* Function pointer table, initialized by slirp_init_once(). */ -static slirp_add_hostxfwd_p_t slirp_add_hostxfwd_p; -static slirp_cleanup_p_t slirp_cleanup_p; -static slirp_input_p_t slirp_input_p; -static slirp_new_p_t slirp_new_p; -static slirp_pollfds_fill_p_t slirp_pollfds_fill_p; -static slirp_pollfds_poll_p_t slirp_pollfds_poll_p; - -static void -checked_close(int *fdp) -{ - int error; - - if (*fdp != -1) { - error = close(*fdp); - assert(error == 0); - *fdp = -1; - } -} - -static int -slirp_init_once(void) -{ - static void *handle = NULL; - - if (handle != NULL) - return (0); - handle = dlopen("libslirp.so.0", RTLD_LAZY); - if (handle == NULL) { - EPRINTLN("Unable to open libslirp.so.0: %s", dlerror()); - return (-1); - } - -#define IMPORT_SYM(sym) do { \ - sym##_p = (sym##_p_t)dlsym(handle, #sym); \ - if (sym##_p == NULL) { \ - EPRINTLN("failed to resolve %s", #sym); \ - goto err; \ - } \ -} while (0) - IMPORT_SYM(slirp_add_hostxfwd); - IMPORT_SYM(slirp_cleanup); - IMPORT_SYM(slirp_input); - IMPORT_SYM(slirp_new); - IMPORT_SYM(slirp_pollfds_fill); - IMPORT_SYM(slirp_pollfds_poll); -#undef IMPORT_SYM - - /* - * libslirp uses glib, which uses tzdata to format log messages. Help - * it out. - * - * XXX-MJ glib will also look for charset files, not sure what we can do - * about that... - */ - caph_cache_tzdata(); - - return (0); - -err: - dlclose(handle); - handle = NULL; - return (-1); -} +#define SLIRP_MTU 2048 struct slirp_priv { - Slirp *slirp; - -#define SLIRP_MTU 2048 + int s; + pid_t helper; struct mevent *mevp; - int pipe[2]; /* used to buffer data sent to the guest */ - int wakeup[2]; /* used to wake up the pollfd thread */ - - pthread_t pollfd_td; - struct pollfd *pollfds; - size_t npollfds; - - /* Serializes libslirp calls. */ - pthread_mutex_t mtx; -}; - -static void -slirp_priv_init(struct slirp_priv *priv) -{ - int error; - - memset(priv, 0, sizeof(*priv)); - priv->pipe[0] = priv->pipe[1] = -1; - priv->wakeup[0] = priv->wakeup[1] = -1; - error = pthread_mutex_init(&priv->mtx, NULL); - assert(error == 0); -} - -static void -slirp_priv_cleanup(struct slirp_priv *priv) -{ - int error; - - checked_close(&priv->pipe[0]); - checked_close(&priv->pipe[1]); - checked_close(&priv->wakeup[0]); - checked_close(&priv->wakeup[1]); - if (priv->mevp) - mevent_delete(priv->mevp); - if (priv->slirp != NULL) - slirp_cleanup_p(priv->slirp); - error = pthread_mutex_destroy(&priv->mtx); - assert(error == 0); -} - -static int64_t -slirp_cb_clock_get_ns(void *param __unused) -{ - struct timespec ts; - int error; - - error = clock_gettime(CLOCK_MONOTONIC, &ts); - assert(error == 0); - return ((int64_t)(ts.tv_sec * 1000000000L + ts.tv_nsec)); -} - -static void -slirp_cb_notify(void *param) -{ - struct slirp_priv *priv; - - /* Wake up the poll thread. We assume that priv->mtx is held here. */ - priv = param; - (void)write(priv->wakeup[1], "M", 1); -} - -static void -slirp_cb_register_poll_fd(int fd, void *param __unused) -{ - const int one = 1; - - (void)setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); -} - -static ssize_t -slirp_cb_send_packet(const void *buf, size_t len, void *param) -{ - struct slirp_priv *priv; - ssize_t n; - - priv = param; - - assert(len <= SLIRP_MTU); - n = send(priv->pipe[1], buf, len, 0); - if (n < 0) { - EPRINTLN("slirp_cb_send_packet: send: %s", strerror(errno)); - return (n); - } - assert((size_t)n == len); - - return (n); -} - -static void -slirp_cb_unregister_poll_fd(int fd __unused, void *opaque __unused) -{ -} - -/* Callbacks invoked from within libslirp. */ -static const struct SlirpCb slirp_cbs = { - .clock_get_ns = slirp_cb_clock_get_ns, - .notify = slirp_cb_notify, - .register_poll_fd = slirp_cb_register_poll_fd, - .send_packet = slirp_cb_send_packet, - .unregister_poll_fd = slirp_cb_unregister_poll_fd, }; static int -slirpev2pollev(int events) -{ - int ret; - - ret = 0; - if (events & SLIRP_POLL_IN) - ret |= POLLIN; - if (events & SLIRP_POLL_OUT) - ret |= POLLOUT; - if (events & SLIRP_POLL_PRI) - ret |= POLLPRI; - if (events & SLIRP_POLL_ERR) - ret |= POLLERR; - if (events & SLIRP_POLL_HUP) - ret |= POLLHUP; - return (ret); -} - -static int -pollev2slirpev(int events) -{ - int ret; - - ret = 0; - if (events & POLLIN) - ret |= SLIRP_POLL_IN; - if (events & POLLOUT) - ret |= SLIRP_POLL_OUT; - if (events & POLLPRI) - ret |= SLIRP_POLL_PRI; - if (events & POLLERR) - ret |= SLIRP_POLL_ERR; - if (events & POLLHUP) - ret |= SLIRP_POLL_HUP; - return (ret); -} - -static int -slirp_addpoll_cb(int fd, int events, void *param) -{ - struct slirp_priv *priv; - struct pollfd *pollfd, *pollfds; - size_t i; - - priv = param; - - for (i = 0; i < priv->npollfds; i++) - if (priv->pollfds[i].fd == -1) - break; - if (i == priv->npollfds) { - const size_t POLLFD_GROW = 4; - - priv->npollfds += POLLFD_GROW; - pollfds = realloc(priv->pollfds, - sizeof(*pollfds) * priv->npollfds); - if (pollfds == NULL) - return (-1); - for (i = priv->npollfds - POLLFD_GROW; i < priv->npollfds; i++) - pollfds[i].fd = -1; - priv->pollfds = pollfds; - - i = priv->npollfds - POLLFD_GROW; - } - pollfd = &priv->pollfds[i]; - pollfd->fd = fd; - pollfd->events = slirpev2pollev(events); - pollfd->revents = 0; - - return ((int)i); -} - -static int -slirp_poll_revents(int idx, void *param) -{ - struct slirp_priv *priv; - struct pollfd *pollfd; - short revents; - - priv = param; - assert(idx >= 0); - assert((unsigned int)idx < priv->npollfds); - pollfd = &priv->pollfds[idx]; - assert(pollfd->fd != -1); - - /* The kernel may report POLLHUP even if we didn't ask for it. */ - revents = pollfd->revents; - if ((pollfd->events & POLLHUP) == 0) - revents &= ~POLLHUP; - return (pollev2slirpev(revents)); -} - -static void * -slirp_pollfd_td_loop(void *param) -{ - struct slirp_priv *priv; - struct pollfd *pollfds; - size_t npollfds; - uint32_t timeout; - int error; - - pthread_set_name_np(pthread_self(), "slirp pollfd"); - priv = param; - - pthread_mutex_lock(&priv->mtx); - for (;;) { - int wakeup; - - for (size_t i = 0; i < priv->npollfds; i++) - priv->pollfds[i].fd = -1; - - /* Register for notifications from slirp_cb_notify(). */ - wakeup = slirp_addpoll_cb(priv->wakeup[0], POLLIN, priv); - - timeout = UINT32_MAX; - slirp_pollfds_fill_p(priv->slirp, &timeout, slirp_addpoll_cb, - priv); - - pollfds = priv->pollfds; - npollfds = priv->npollfds; - pthread_mutex_unlock(&priv->mtx); - error = poll(pollfds, npollfds, timeout); - if (error == -1 && errno != EINTR) { - EPRINTLN("poll: %s", strerror(errno)); - exit(1); - } - pthread_mutex_lock(&priv->mtx); - slirp_pollfds_poll_p(priv->slirp, error == -1, - slirp_poll_revents, priv); - - /* - * If we were woken up by the notify callback, mask the - * interrupt. - */ - if ((pollfds[wakeup].revents & POLLIN) != 0) { - ssize_t n; - - do { - uint8_t b; - - n = read(priv->wakeup[0], &b, 1); - } while (n == 1); - if (n != -1 || errno != EAGAIN) { - EPRINTLN("read(wakeup): %s", strerror(errno)); - exit(1); - } - } - } -} - -static int -parse_addr(char *addr, struct sockaddr_in *sinp) -{ - char *port; - int error, porti; - - memset(sinp, 0, sizeof(*sinp)); - sinp->sin_family = AF_INET; - sinp->sin_len = sizeof(struct sockaddr_in); - - port = strchr(addr, ':'); - if (port == NULL) - return (EINVAL); - *port++ = '\0'; - - if (strlen(addr) > 0) { - error = inet_pton(AF_INET, addr, &sinp->sin_addr); - if (error != 1) - return (error == 0 ? EPFNOSUPPORT : errno); - } else { - sinp->sin_addr.s_addr = htonl(INADDR_ANY); - } - - porti = strlen(port) > 0 ? atoi(port) : 0; - if (porti < 0 || porti > UINT16_MAX) - return (EINVAL); - sinp->sin_port = htons(porti); - - return (0); -} - -static int -parse_hostfwd_rule(const char *descr, int *is_udp, struct sockaddr *hostaddr, - struct sockaddr *guestaddr) -{ - struct sockaddr_in *hostaddrp, *guestaddrp; - const char *proto; - char *p, *host, *guest; - int error; - - error = 0; - *is_udp = 0; - - p = strdup(descr); - if (p == NULL) - return (ENOMEM); - - host = strchr(p, ':'); - if (host == NULL) { - error = EINVAL; - goto out; - } - *host++ = '\0'; - - proto = p; - *is_udp = strcmp(proto, "udp") == 0; - - guest = strchr(host, '-'); - if (guest == NULL) { - error = EINVAL; - goto out; - } - *guest++ = '\0'; - - hostaddrp = (struct sockaddr_in *)hostaddr; - error = parse_addr(host, hostaddrp); - if (error != 0) - goto out; - - guestaddrp = (struct sockaddr_in *)guestaddr; - error = parse_addr(guest, guestaddrp); - if (error != 0) - goto out; - -out: - free(p); - return (error); -} - -static int -config_one_hostfwd(struct slirp_priv *priv, const char *rule) -{ - struct sockaddr hostaddr, guestaddr; - int error, is_udp; - - error = parse_hostfwd_rule(rule, &is_udp, &hostaddr, &guestaddr); - if (error != 0) { - EPRINTLN("Unable to parse hostfwd rule '%s': %s", - rule, strerror(error)); - return (error); - } - - error = slirp_add_hostxfwd_p(priv->slirp, &hostaddr, hostaddr.sa_len, - &guestaddr, guestaddr.sa_len, is_udp ? SLIRP_HOSTFWD_UDP : 0); - if (error != 0) { - EPRINTLN("Unable to add hostfwd rule '%s': %s", - rule, strerror(errno)); - return (error); - } - - return (0); -} - -static int -_slirp_init(struct net_backend *be, const char *devname __unused, +slirp_init(struct net_backend *be, const char *devname __unused, nvlist_t *nvl, net_be_rxeof_t cb, void *param) { + extern char **environ; struct slirp_priv *priv = NET_BE_PRIV(be); - SlirpConfig config = { - .version = 4, - .if_mtu = SLIRP_MTU, - .restricted = true, - .in_enabled = true, - .vnetwork.s_addr = htonl(0x0a000200), /* 10.0.2.0/24 */ - .vnetmask.s_addr = htonl(0xffffff00), - .vdhcp_start.s_addr = htonl(0x0a00020f),/* 10.0.2.15 */ - .vhost.s_addr = htonl(0x0a000202), /* 10.0.2.2 */ - .enable_emu = false, - }; - const char *hostfwd; - int error, sndbuf; - - error = slirp_init_once(); - if (error != 0) - return (error); - - slirp_priv_init(priv); + nvlist_t *config; + posix_spawn_file_actions_t fa; + pid_t child; + const char **argv; + char sockname[32]; + int error, s[2]; + + if (socketpair(PF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, s) != 0) { + EPRINTLN("socketpair"); + return (-1); + } - priv->slirp = slirp_new_p(&config, &slirp_cbs, priv); - if (priv->slirp == NULL) { - EPRINTLN("Unable to create slirp instance"); + /* + * The child will exit once its connection goes away, so make sure only + * one end is inherited by the child. + */ + if (posix_spawn_file_actions_init(&fa) != 0) { + EPRINTLN("posix_spawn_file_actions_init"); goto err; } - - hostfwd = get_config_value_node(nvl, "hostfwd"); - if (hostfwd != NULL) { - char *rules, *tofree; - const char *rule; - - tofree = rules = strdup(hostfwd); - if (rules == NULL) - goto err; - while ((rule = strsep(&rules, ";")) != NULL) { - error = config_one_hostfwd(priv, rule); - if (error != 0) { - free(tofree); - goto err; - } - } - free(tofree); + if (posix_spawn_file_actions_addclose(&fa, s[0]) != 0) { + EPRINTLN("posix_spawn_file_actions_addclose"); + posix_spawn_file_actions_destroy(&fa); + goto err; } - error = socketpair(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, priv->pipe); + (void)snprintf(sockname, sizeof(sockname), "%d", s[1]); + argv = (const char *[]){ + "/usr/libexec/bhyve-slirp-helper", "-S", sockname, NULL + }; + error = posix_spawn(&child, "/usr/libexec/bhyve-slirp-helper", + &fa, NULL, __DECONST(char **, argv), environ); + posix_spawn_file_actions_destroy(&fa); if (error != 0) { - EPRINTLN("Unable to create pipe: %s", strerror(errno)); + EPRINTLN("posix_spawn(bhyve-slirp-helper): %s", + strerror(error)); goto err; } - error = pipe2(priv->wakeup, O_CLOEXEC | O_NONBLOCK); - if (error != 0) { - EPRINTLN("Unable to create wakeup pipe: %s", strerror(errno)); + config = nvlist_clone(nvl); + if (config == NULL) { + EPRINTLN("nvlist_clone"); goto err; } - - /* - * Try to avoid dropping buffered packets in slirp_cb_send_packet(). - */ - sndbuf = 1024 * 1024; - error = setsockopt(priv->pipe[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, - sizeof(sndbuf)); + nvlist_add_string(config, "vmname", get_config_value("name")); + error = nvlist_send(s[0], config); + nvlist_destroy(config); if (error != 0) { - EPRINTLN("Could not set socket buffer size: %s", - strerror(errno)); + EPRINTLN("nvlist_send"); goto err; } - be->fd = priv->pipe[0]; + be->fd = s[0]; priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param); if (priv->mevp == NULL) { EPRINTLN("Could not register event"); goto err; } - error = pthread_create(&priv->pollfd_td, NULL, slirp_pollfd_td_loop, - priv); - if (error != 0) { - EPRINTLN("Unable to create pollfd thread: %s", strerror(error)); - goto err; - } + priv->helper = child; + priv->s = s[0]; + (void)close(s[1]); return (0); err: - slirp_priv_cleanup(priv); + (void)close(s[0]); + (void)close(s[1]); return (-1); } @@ -599,52 +154,43 @@ static ssize_t slirp_send(struct net_backend *be, const struct iovec *iov, int iovcnt) { struct slirp_priv *priv = NET_BE_PRIV(be); + struct msghdr hdr; - if (iovcnt == 1) { - /* We can avoid copying if there's a single segment. */ - pthread_mutex_lock(&priv->mtx); - slirp_input_p(priv->slirp, iov->iov_base, - (int)iov->iov_len); - pthread_mutex_unlock(&priv->mtx); - return (iov[0].iov_len); - } else { - uint8_t *pkt; - size_t pktlen; - - pktlen = 0; - for (int i = 0; i < iovcnt; i++) - pktlen += iov[i].iov_len; - pkt = malloc(pktlen); - if (pkt == NULL) - return (-1); - pktlen = 0; - for (int i = 0; i < iovcnt; i++) { - memcpy(pkt + pktlen, iov[i].iov_base, iov[i].iov_len); - pktlen += iov[i].iov_len; - } - pthread_mutex_lock(&priv->mtx); - slirp_input_p(priv->slirp, pkt, (int)pktlen); - pthread_mutex_unlock(&priv->mtx); - free(pkt); - return (pktlen); - } + memset(&hdr, 0, sizeof(hdr)); + hdr.msg_iov = __DECONST(struct iovec *, iov); + hdr.msg_iovlen = iovcnt; + return (sendmsg(priv->s, &hdr, MSG_EOR)); } static void -_slirp_cleanup(struct net_backend *be) +slirp_cleanup(struct net_backend *be) { struct slirp_priv *priv = NET_BE_PRIV(be); - slirp_priv_cleanup(priv); + if (priv->helper > 0) { + int status; + + if (kill(priv->helper, SIGKILL) != 0) { + EPRINTLN("kill(bhyve-slirp-helper): %s", + strerror(errno)); + return; + } + (void)waitpid(priv->helper, &status, 0); + } } static ssize_t slirp_peek_recvlen(struct net_backend *be) { struct slirp_priv *priv = NET_BE_PRIV(be); + uint8_t buf[SLIRP_MTU]; ssize_t n; - n = recv(priv->pipe[0], NULL, 0, MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); + /* + * Copying into the buffer is totally unnecessary, but we don't + * implement MSG_TRUNC for SEQPACKET sockets. + */ + n = recv(priv->s, buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT); if (n < 0) return (errno == EWOULDBLOCK ? 0 : -1); assert((size_t)n <= SLIRP_MTU); @@ -665,7 +211,7 @@ slirp_recv(struct net_backend *be, const struct iovec *iov, int iovcnt) hdr.msg_control = NULL; hdr.msg_controllen = 0; hdr.msg_flags = 0; - n = recvmsg(priv->pipe[0], &hdr, MSG_DONTWAIT); + n = recvmsg(priv->s, &hdr, MSG_DONTWAIT); if (n < 0) { if (errno == EWOULDBLOCK) return (0); @@ -707,8 +253,8 @@ slirp_set_cap(struct net_backend *be __unused, uint64_t features __unused, static struct net_backend slirp_backend = { .prefix = "slirp", .priv_size = sizeof(struct slirp_priv), - .init = _slirp_init, - .cleanup = _slirp_cleanup, + .init = slirp_init, + .cleanup = slirp_cleanup, .send = slirp_send, .peek_recvlen = slirp_peek_recvlen, .recv = slirp_recv, diff --git a/usr.sbin/bhyve/slirp/Makefile b/usr.sbin/bhyve/slirp/Makefile new file mode 100644 index 000000000000..da76fda45e86 --- /dev/null +++ b/usr.sbin/bhyve/slirp/Makefile @@ -0,0 +1,11 @@ +.PATH: ${.CURDIR}/../ + +PROG= bhyve-slirp-helper +SRCS= slirp-helper.c config.c +CFLAGS+= -I${.CURDIR}/../ +LIBADD= nv +MAN= + +BINDIR?= /usr/libexec + +.include <bsd.prog.mk> diff --git a/usr.sbin/bhyve/libslirp.h b/usr.sbin/bhyve/slirp/libslirp.h index a679c4db7913..a679c4db7913 100644 --- a/usr.sbin/bhyve/libslirp.h +++ b/usr.sbin/bhyve/slirp/libslirp.h diff --git a/usr.sbin/bhyve/slirp/slirp-helper.c b/usr.sbin/bhyve/slirp/slirp-helper.c new file mode 100644 index 000000000000..ee62dd212369 --- /dev/null +++ b/usr.sbin/bhyve/slirp/slirp-helper.c @@ -0,0 +1,570 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023, 2025 Mark Johnston <markj@FreeBSD.org> + * + * This software was developed by the University of Cambridge Computer + * Laboratory (Department of Computer Science and Technology) under Innovate + * UK project 105694, "Digital Security by Design (DSbD) Technology Platform + * Prototype". + */ + +/* + * A helper process which lets bhyve's libslirp-based network backend work + * outside bhyve's Capsicum sandbox. We are started with a SOCK_SEQPACKET + * socket through which we pass and receive packets from the guest's frontend. + * + * At initialization time, we receive an nvlist over the socket which describes + * the desired slirp configuration. + */ + +#include <sys/nv.h> +#include <sys/socket.h> + +#include <assert.h> +#include <capsicum_helpers.h> +#include <dlfcn.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "config.h" +#include "libslirp.h" + +#define SLIRP_MTU 2048 + +struct slirp_priv { + Slirp *slirp; /* libslirp handle */ + int sock; /* data and control socket */ + int wakeup[2]; /* used to wake up the pollfd thread */ + struct pollfd *pollfds; + size_t npollfds; + size_t lastpollfd; +}; + +typedef int (*slirp_add_hostxfwd_p_t)(Slirp *, + const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t, + int); +typedef void (*slirp_cleanup_p_t)(Slirp *); +typedef void (*slirp_input_p_t)(Slirp *, const uint8_t *, int); +typedef Slirp *(*slirp_new_p_t)(const SlirpConfig *, const SlirpCb *, void *); +typedef void (*slirp_pollfds_fill_p_t)(Slirp *, uint32_t *timeout, + SlirpAddPollCb, void *); +typedef void (*slirp_pollfds_poll_p_t)(Slirp *, int, SlirpGetREventsCb, void *); + +/* Function pointer table, initialized by libslirp_init(). */ +static slirp_add_hostxfwd_p_t slirp_add_hostxfwd_p; +static slirp_cleanup_p_t slirp_cleanup_p; +static slirp_input_p_t slirp_input_p; +static slirp_new_p_t slirp_new_p; +static slirp_pollfds_fill_p_t slirp_pollfds_fill_p; +static slirp_pollfds_poll_p_t slirp_pollfds_poll_p; + +static int64_t +slirp_cb_clock_get_ns(void *param __unused) +{ + struct timespec ts; + int error; + + error = clock_gettime(CLOCK_MONOTONIC, &ts); + assert(error == 0); + return ((int64_t)(ts.tv_sec * 1000000000L + ts.tv_nsec)); +} + +static void +slirp_cb_notify(void *param) +{ + struct slirp_priv *priv; + + /* Wake up the poll thread. We assume that priv->mtx is held here. */ + priv = param; + (void)write(priv->wakeup[1], "M", 1); +} + +static void +slirp_cb_register_poll_fd(int fd, void *param __unused) +{ + const int one = 1; + + (void)setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); +} + +static ssize_t +slirp_cb_send_packet(const void *buf, size_t len, void *param) +{ + struct slirp_priv *priv; + ssize_t n; + + priv = param; + + assert(len <= SLIRP_MTU); + n = send(priv->sock, buf, len, MSG_EOR); + if (n < 0) { + warn("slirp_cb_send_packet: send"); + return (n); + } + assert((size_t)n == len); + + return (n); +} + +static void +slirp_cb_unregister_poll_fd(int fd __unused, void *opaque __unused) +{ +} + +/* Callbacks invoked from within libslirp. */ +static const struct SlirpCb slirp_cbs = { + .clock_get_ns = slirp_cb_clock_get_ns, + .notify = slirp_cb_notify, + .register_poll_fd = slirp_cb_register_poll_fd, + .send_packet = slirp_cb_send_packet, + .unregister_poll_fd = slirp_cb_unregister_poll_fd, +}; + +static int +slirpev2pollev(int events) +{ + int ret; + + ret = 0; + if (events & SLIRP_POLL_IN) + ret |= POLLIN; + if (events & SLIRP_POLL_OUT) + ret |= POLLOUT; + if (events & SLIRP_POLL_PRI) + ret |= POLLPRI; + if (events & SLIRP_POLL_ERR) + ret |= POLLERR; + if (events & SLIRP_POLL_HUP) + ret |= POLLHUP; + return (ret); +} + +static int +pollev2slirpev(int events) +{ + int ret; + + ret = 0; + if (events & POLLIN) + ret |= SLIRP_POLL_IN; + if (events & POLLOUT) + ret |= SLIRP_POLL_OUT; + if (events & POLLPRI) + ret |= SLIRP_POLL_PRI; + if (events & POLLERR) + ret |= SLIRP_POLL_ERR; + if (events & POLLHUP) + ret |= SLIRP_POLL_HUP; + return (ret); +} + +static int +slirp_addpoll(struct slirp_priv *priv, int fd, int events) +{ + struct pollfd *pollfd, *pollfds; + size_t i; + + for (i = priv->lastpollfd + 1; i < priv->npollfds; i++) + if (priv->pollfds[i].fd == -1) + break; + if (i == priv->npollfds) { + const size_t POLLFD_GROW = 4; + + priv->npollfds += POLLFD_GROW; + pollfds = realloc(priv->pollfds, + sizeof(*pollfds) * priv->npollfds); + if (pollfds == NULL) + return (-1); + for (i = priv->npollfds - POLLFD_GROW; i < priv->npollfds; i++) + pollfds[i].fd = -1; + priv->pollfds = pollfds; + + i = priv->npollfds - POLLFD_GROW; + } + pollfd = &priv->pollfds[i]; + pollfd->fd = fd; + pollfd->events = slirpev2pollev(events); + pollfd->revents = 0; + priv->lastpollfd = i; + + return ((int)i); +} + +static int +slirp_addpoll_cb(int fd, int events, void *param) +{ + struct slirp_priv *priv; + + priv = param; + return (slirp_addpoll(priv, fd, events)); +} + +static int +slirp_poll_revents(int idx, void *param) +{ + struct slirp_priv *priv; + struct pollfd *pollfd; + short revents; + + priv = param; + assert(idx >= 0); + assert((unsigned int)idx < priv->npollfds); + pollfd = &priv->pollfds[idx]; + assert(pollfd->fd != -1); + + /* The kernel may report POLLHUP even if we didn't ask for it. */ + revents = pollfd->revents; + if ((pollfd->events & POLLHUP) == 0) + revents &= ~POLLHUP; + return (pollev2slirpev(revents)); +} + +/* + * Main loop. Poll libslirp's descriptors plus a couple of our own. + */ +static void +slirp_pollfd_loop(struct slirp_priv *priv) +{ + struct pollfd *pollfds; + size_t npollfds; + uint32_t timeout; + int error; + + for (;;) { + int input, wakeup; + + for (size_t i = 0; i < priv->npollfds; i++) + priv->pollfds[i].fd = -1; + priv->lastpollfd = -1; + + /* Register for notifications from slirp_cb_notify(). */ + wakeup = slirp_addpoll(priv, priv->wakeup[0], POLLIN); + /* Register for input from our parent process. */ + input = slirp_addpoll(priv, priv->sock, POLLIN | POLLRDHUP); + + timeout = UINT32_MAX; + slirp_pollfds_fill_p(priv->slirp, &timeout, slirp_addpoll_cb, + priv); + + pollfds = priv->pollfds; + npollfds = priv->npollfds; + error = poll(pollfds, npollfds, timeout); + if (error == -1 && errno != EINTR) + err(1, "poll"); + slirp_pollfds_poll_p(priv->slirp, error == -1, + slirp_poll_revents, priv); + + /* + * If we were woken up by the notify callback, mask the + * interrupt. + */ + if ((pollfds[wakeup].revents & POLLIN) != 0) { + ssize_t n; + + do { + uint8_t b; + + n = read(priv->wakeup[0], &b, 1); + } while (n == 1); + if (n != -1 || errno != EAGAIN) + err(1, "read"); + } + + /* + * If new packets arrived from our parent, feed them to + * libslirp. + */ + if ((pollfds[input].revents & (POLLHUP | POLLRDHUP)) != 0) + errx(1, "parent process closed connection"); + if ((pollfds[input].revents & POLLIN) != 0) { + ssize_t n; + + do { + uint8_t buf[SLIRP_MTU]; + + n = recv(priv->sock, buf, sizeof(buf), + MSG_DONTWAIT); + if (n < 0) { + if (errno == EWOULDBLOCK) + break; + err(1, "recv"); + } + slirp_input_p(priv->slirp, buf, (int)n); + } while (n >= 0); + } + } +} + +static int +parse_addr(char *addr, struct sockaddr_in *sinp) +{ + char *port; + int error, porti; + + memset(sinp, 0, sizeof(*sinp)); + sinp->sin_family = AF_INET; + sinp->sin_len = sizeof(struct sockaddr_in); + + port = strchr(addr, ':'); + if (port == NULL) + return (EINVAL); + *port++ = '\0'; + + if (strlen(addr) > 0) { + error = inet_pton(AF_INET, addr, &sinp->sin_addr); + if (error != 1) + return (error == 0 ? EPFNOSUPPORT : errno); + } else { + sinp->sin_addr.s_addr = htonl(INADDR_ANY); + } + + porti = strlen(port) > 0 ? atoi(port) : 0; + if (porti < 0 || porti > UINT16_MAX) + return (EINVAL); + sinp->sin_port = htons(porti); + + return (0); +} + +static int +parse_hostfwd_rule(const char *descr, int *is_udp, struct sockaddr *hostaddr, + struct sockaddr *guestaddr) +{ + struct sockaddr_in *hostaddrp, *guestaddrp; + const char *proto; + char *p, *host, *guest; + int error; + + error = 0; + *is_udp = 0; + + p = strdup(descr); + if (p == NULL) + return (ENOMEM); + + host = strchr(p, ':'); + if (host == NULL) { + error = EINVAL; + goto out; + } + *host++ = '\0'; + + proto = p; + *is_udp = strcmp(proto, "udp") == 0; + + guest = strchr(host, '-'); + if (guest == NULL) { + error = EINVAL; + goto out; + } + *guest++ = '\0'; + + hostaddrp = (struct sockaddr_in *)(void *)hostaddr; + error = parse_addr(host, hostaddrp); + if (error != 0) + goto out; + + guestaddrp = (struct sockaddr_in *)(void *)guestaddr; + error = parse_addr(guest, guestaddrp); + if (error != 0) + goto out; + +out: + free(p); + return (error); +} + +static void +config_one_hostfwd(Slirp *slirp, const char *rule) +{ + struct sockaddr hostaddr, guestaddr; + int error, is_udp; + + error = parse_hostfwd_rule(rule, &is_udp, &hostaddr, &guestaddr); + if (error != 0) + errx(1, "unable to parse hostfwd rule '%s': %s", rule, + strerror(error)); + + error = slirp_add_hostxfwd_p(slirp, &hostaddr, hostaddr.sa_len, + &guestaddr, guestaddr.sa_len, is_udp ? SLIRP_HOSTFWD_UDP : 0); + if (error != 0) + errx(1, "Unable to add hostfwd rule '%s': %s", rule, + strerror(errno)); +} + +/* + * Drop privileges to the "nobody" user. Ideally we'd chroot to somewhere like + * /var/empty but libslirp might need to access /etc/resolv.conf. + */ +static void +drop_privs(void) +{ + struct passwd *pw; + + if (geteuid() != 0) + return; + + pw = getpwnam("nobody"); + if (pw == NULL) + err(1, "getpwnam(nobody) failed"); + if (initgroups(pw->pw_name, pw->pw_gid) != 0) + err(1, "initgroups"); + if (setgid(pw->pw_gid) != 0) + err(1, "setgid"); + if (setuid(pw->pw_uid) != 0) + err(1, "setuid"); +} + +static void +libslirp_init(void) +{ + void *handle; + + handle = dlopen("libslirp.so.0", RTLD_LAZY); + if (handle == NULL) + errx(1, "unable to open libslirp.so.0: %s", dlerror()); + +#define IMPORT_SYM(sym) do { \ + sym##_p = (sym##_p_t)dlsym(handle, #sym); \ + if (sym##_p == NULL) \ + errx(1, "failed to resolve %s", #sym); \ +} while (0) + IMPORT_SYM(slirp_add_hostxfwd); + IMPORT_SYM(slirp_cleanup); + IMPORT_SYM(slirp_input); + IMPORT_SYM(slirp_new); + IMPORT_SYM(slirp_pollfds_fill); + IMPORT_SYM(slirp_pollfds_poll); +#undef IMPORT_SYM +} + +static void +usage(void) +{ + fprintf(stderr, "Usage: slirp-helper -S <socket>\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct slirp_priv priv; + SlirpConfig slirpconfig; + Slirp *slirp; + nvlist_t *config; + const char *hostfwd, *vmname; + int ch, fd, sd; + bool restricted; + + sd = -1; + while ((ch = getopt(argc, argv, "S:")) != -1) { + switch (ch) { + case 'S': + sd = atoi(optarg); + if (fcntl(sd, F_GETFD) == -1) + err(1, "invalid socket %s", optarg); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (sd == -1) + usage(); + + /* + * Clean the fd space: point stdio to /dev/null and keep our socket. + */ + fd = open("/dev/null", O_RDWR); + if (fd == -1) + err(1, "open(/dev/null)"); + if (dup2(fd, STDIN_FILENO) == -1) + err(1, "dup2(stdin)"); + if (dup2(fd, STDOUT_FILENO) == -1) + err(1, "dup2(stdout)"); + if (dup2(fd, STDERR_FILENO) == -1) + err(1, "dup2(stderr)"); + if (dup2(sd, 3) == -1) + err(1, "dup2(slirp socket)"); + sd = 3; + closefrom(sd + 1); + + memset(&priv, 0, sizeof(priv)); + priv.sock = sd; + if (pipe2(priv.wakeup, O_CLOEXEC | O_NONBLOCK) != 0) + err(1, "pipe2"); + + /* + * Apply the configuration we received from bhyve. + */ + config = nvlist_recv(sd, 0); + if (config == NULL) + err(1, "nvlist_recv"); + vmname = get_config_value_node(config, "vmname"); + if (vmname != NULL) + setproctitle("%s", vmname); + restricted = !get_config_bool_node_default(config, "open", false); + + slirpconfig = (SlirpConfig){ + .version = 4, + .if_mtu = SLIRP_MTU, + .restricted = restricted, + .in_enabled = true, + .vnetwork.s_addr = htonl(0x0a000200), /* 10.0.2.0/24 */ + .vnetmask.s_addr = htonl(0xffffff00), /* 255.255.255.0 */ + .vdhcp_start.s_addr = htonl(0x0a00020f),/* 10.0.2.15 */ + .vhost.s_addr = htonl(0x0a000202), /* 10.0.2.2 */ + .vnameserver.s_addr = htonl(0x0a000203),/* 10.0.2.3 */ + .enable_emu = false, + }; + libslirp_init(); + slirp = slirp_new_p(&slirpconfig, &slirp_cbs, &priv); + + hostfwd = get_config_value_node(config, "hostfwd"); + if (hostfwd != NULL) { + char *rules, *tofree; + const char *rule; + + tofree = rules = strdup(hostfwd); + if (rules == NULL) + err(1, "strdup"); + while ((rule = strsep(&rules, ";")) != NULL) + config_one_hostfwd(slirp, rule); + free(tofree); + } + + priv.slirp = slirp; + + /* + * In restricted mode, we can enter a Capsicum sandbox without losing + * functionality. + */ + if (restricted && caph_enter() != 0) + err(1, "caph_enter"); + + /* + * Drop root privileges if we have them. + */ + drop_privs(); + + /* + * Enter our main loop. If bhyve goes away, we should observe a hangup + * on the socket and exit. + */ + slirp_pollfd_loop(&priv); + /* NOTREACHED */ + + return (1); +} diff --git a/usr.sbin/bsdinstall/FreeBSD-base.conf.in b/usr.sbin/bsdinstall/FreeBSD-base.conf.in index 792c290facdf..86ec8fabe253 100644 --- a/usr.sbin/bsdinstall/FreeBSD-base.conf.in +++ b/usr.sbin/bsdinstall/FreeBSD-base.conf.in @@ -1,7 +1,7 @@ FreeBSD-base: { - url: "pkg+https://pkg.FreeBSD.org/${ABI}/%%SUBURL%%", + url: "pkg+https://%%PKGHOST%%.FreeBSD.org/${ABI}/%%SUBURL%%", mirror_type: "srv", signature_type: "fingerprints", - fingerprints: "/usr/share/keys/pkg", + fingerprints: "/usr/share/keys/%%KEYSDIR%%", enabled: yes } diff --git a/usr.sbin/bsdinstall/Makefile b/usr.sbin/bsdinstall/Makefile index 5d7be97ed7cf..9a6b25fc5c7a 100644 --- a/usr.sbin/bsdinstall/Makefile +++ b/usr.sbin/bsdinstall/Makefile @@ -21,16 +21,26 @@ _REVISION!= ${MAKE} -C ${SRCTOP}/release -V REVISION REVISION?= ${_REVISION} .if ${BRANCH} == CURRENT || ${BRANCH} == STABLE +PKGHOST= pkg +KEYSDIR= pkg SUBURL= base_latest -.elif ${BRANCH} == RELEASE || ${BRANCH:C/[0-9]+$//} == BETA || \ - ${BRANCH:C/[0-9]+$//} == RC +.elif ${BRANCH} == RELEASE +PKGHOST= pkgbase +KEYSDIR= pkgbase-${REVISION:C/\.[0-9]+//} SUBURL= base_release_${REVISION:C/[0-9]+\.//} +.elif ${BRANCH:C/[0-9]+$//} == BETA || \ + ${BRANCH:C/[0-9]+$//} == RC +PKGHOST= pkgbase +KEYSDIR= pkgbase-${REVISION:C/\.[0-9]+//} +SUBURL= base_release_${REVISION:C/[0-9]+\.//}_${BRANCH:tl} .else .warning Invalid branch "${BRANCH}" +PKGHOST= pkg +KEYSDIR= pkg SUBURL= base_latest .endif FreeBSD-base.conf: FreeBSD-base.conf.in - sed "s|%%SUBURL%%|${SUBURL}|" < ${.ALLSRC} > ${.TARGET} + sed "s|%%PKGHOST%%|${PKGHOST}|;s|%%SUBURL%%|${SUBURL}|;s|%%KEYSDIR%%|${KEYSDIR}|" < ${.ALLSRC} > ${.TARGET} .include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/scripts/pkgbase.in b/usr.sbin/bsdinstall/scripts/pkgbase.in index 5299d34fcb71..89ddc244171e 100755 --- a/usr.sbin/bsdinstall/scripts/pkgbase.in +++ b/usr.sbin/bsdinstall/scripts/pkgbase.in @@ -309,7 +309,7 @@ local function parse_options() end -- Fetch and install pkgbase packages to BSDINSTALL_CHROOT. --- Respect BSDINSTALL_PKG_REPOS_DIR if set, otherwise use pkg.freebsd.org. +-- Respect BSDINSTALL_PKG_REPOS_DIR if set, otherwise use pkgbase.freebsd.org. local function pkgbase() local options = parse_options() @@ -323,21 +323,13 @@ local function pkgbase() local chroot = assert(os.getenv("BSDINSTALL_CHROOT")) assert(os.execute("mkdir -p " .. chroot)) - -- Always install the default FreeBSD-base.conf file to the chroot, even - -- if we don't actually fetch the packages from the repository specified - -- there (e.g. because we are performing an offline installation). - local chroot_repos_dir = chroot .. "/usr/local/etc/pkg/repos/" - assert(os.execute("mkdir -p " .. chroot_repos_dir)) - assert(os.execute("cp /usr/share/bsdinstall/FreeBSD-base.conf " .. - chroot_repos_dir)) - local repos_dir = os.getenv("BSDINSTALL_PKG_REPOS_DIR") if not repos_dir then - repos_dir = chroot_repos_dir + repos_dir = "/usr/share/bsdinstall/" -- Since pkg always interprets fingerprints paths as relative to -- the --rootdir we must copy the key from the host. assert(os.execute("mkdir -p " .. chroot .. "/usr/share/keys")) - assert(os.execute("cp -R /usr/share/keys/pkg " .. chroot .. "/usr/share/keys/")) + assert(os.execute("cp -R /usr/share/keys/* " .. chroot .. "/usr/share/keys/")) end -- We must use --repo-conf-dir rather than -o REPOS_DIR here as the latter @@ -363,6 +355,10 @@ local function pkgbase() if not os.execute(pkg .. "install -U -y -r FreeBSD-base " .. packages) then os.exit(1) end + + -- Enable the FreeBSD-base repository for this system. + assert(os.execute("mkdir -p " .. chroot .. "/usr/local/etc/pkg/repos")) + assert(os.execute("echo 'FreeBSD-base: { enabled: yes }' > " .. chroot .. "/usr/local/etc/pkg/repos/FreeBSD.conf")) end pkgbase() diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 9ea6ec3a4ac9..a4c9220a709c 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -216,7 +216,7 @@ KLDLOAD='kldload %s' LN_SF='ln -sf "%s" "%s"' MKDIR_P='mkdir -p "%s"' MOUNT_TYPE='mount -t %s "%s" "%s"' -NEWFS_ESP='newfs_msdos "%s"' +NEWFS_ESP='newfs_msdos -F 32 -c 1 "%s"' PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\"" PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"' SHELL_TRUNCATE=':> "%s"' diff --git a/usr.sbin/cxgbetool/reg_defs_t7.c b/usr.sbin/cxgbetool/reg_defs_t7.c index 549db9c546d5..338c75946b1d 100644 --- a/usr.sbin/cxgbetool/reg_defs_t7.c +++ b/usr.sbin/cxgbetool/reg_defs_t7.c @@ -1,6 +1,6 @@ /* This file is automatically generated --- changes will be lost */ -/* Generation Date : Thu Sep 11 05:26:14 PM IST 2025 */ -/* Directory name: t7_reg.txt, Changeset: 5945:1487219ecb20 */ +/* Generation Date : Tue Oct 28 05:24:53 PM IST 2025 */ +/* Directory name: t7_sw_reg.txt, Changeset: 5946:0b60ff298e7d */ struct reg_info t7_sge_regs[] = { { "SGE_PF_KDOORBELL", 0x1e000, 0 }, @@ -1546,17 +1546,6 @@ struct reg_info t7_pcie_regs[] = { { "PERstTimeout", 8, 1 }, { "PERstTimer", 0, 4 }, { "PCIE_CFG7", 0x302c, 0 }, - { "PCIE_CFG_SPACE_REQ", 0x3060, 0 }, - { "Enable", 31, 1 }, - { "AI", 30, 1 }, - { "CS2", 29, 1 }, - { "WrBE", 25, 4 }, - { "VFVld", 24, 1 }, - { "RVF", 16, 8 }, - { "PF", 12, 3 }, - { "ExtRegister", 8, 4 }, - { "Register", 0, 8 }, - { "PCIE_CFG_SPACE_DATA", 0x3064, 0 }, { "PCIE_MAILBOX_BASE_WIN", 0x30a4, 0 }, { "PCIEOfst", 6, 26 }, { "BIR", 4, 2 }, @@ -1591,15 +1580,6 @@ struct reg_info t7_pcie_regs[] = { { "PCIE_STATIC_CFG2", 0x30e8, 0 }, { "PL_CONTROL", 16, 16 }, { "STATIC_SPARE3", 0, 15 }, - { "PCIE_DBG_INDIR_REQ", 0x30ec, 0 }, - { "Enable", 31, 1 }, - { "AI", 30, 1 }, - { "Pointer", 8, 16 }, - { "Select", 0, 4 }, - { "PCIE_DBG_INDIR_DATA_0", 0x30f0, 0 }, - { "PCIE_DBG_INDIR_DATA_1", 0x30f4, 0 }, - { "PCIE_DBG_INDIR_DATA_2", 0x30f8, 0 }, - { "PCIE_DBG_INDIR_DATA_3", 0x30fc, 0 }, { "PCIE_PF_INT_CFG", 0x3140, 0 }, { "PBAOfst", 28, 4 }, { "TABOfst", 24, 4 }, @@ -3136,14 +3116,6 @@ struct reg_info t7_pcie_regs[] = { { "PCIE_X8_CORE_PIPE_CONTROL", 0x48b8, 0 }, { "Loopback_Enable", 31, 1 }, { "PCIE_X8_CORE_DBI_RO_WE", 0x48bc, 0 }, - { "PCIE_X8_CFG_SPACE_REQ", 0x48c0, 0 }, - { "Enable", 31, 1 }, - { "AI", 30, 1 }, - { "CS2", 29, 1 }, - { "WrBE", 25, 4 }, - { "ExtRegister", 8, 4 }, - { "Register", 0, 8 }, - { "PCIE_X8_CFG_SPACE_DATA", 0x48c4, 0 }, { "PCIE_X8_CFG_MPS_MRS", 0x4900, 0 }, { "MRS", 3, 3 }, { "MPS", 0, 3 }, @@ -3513,10 +3485,6 @@ struct reg_info t7_pcie_regs[] = { { "PCIE_PHY_PRESET_COEFF", 0x5be4, 0 }, { "PCIE_PHY_PRESET_COEFF", 0x5be8, 0 }, { "PCIE_PHY_PRESET_COEFF", 0x5bec, 0 }, - { "PCIE_PHY_INDIR_REQ", 0x5bf0, 0 }, - { "Enable", 31, 1 }, - { "RegAddr", 0, 16 }, - { "PCIE_PHY_INDIR_DATA", 0x5bf4, 0 }, { "PCIE_STATIC_SPARE1", 0x5bf8, 0 }, { "PCIE_STATIC_SPARE2", 0x5bfc, 0 }, { "x8_sw_en", 30, 1 }, @@ -3606,13 +3574,6 @@ struct reg_info t7_pcie_regs[] = { { "Phy_Reg_Select", 22, 2 }, { "Phy_Reg_RegAddr", 0, 16 }, { "PCIE_MULTI_PHY_INDIR_DATA", 0x5c40, 0 }, - { "PCIE_VF_INT_INDIR_REQ", 0x5c44, 0 }, - { "Enable", 24, 1 }, - { "AI", 23, 1 }, - { "VFID", 0, 10 }, - { "PCIE_VF_INT_INDIR_DATA", 0x5c48, 0 }, - { "VecNum", 12, 10 }, - { "VecBase", 0, 12 }, { "PCIE_VF_256_INT_CFG2", 0x5c4c, 0 }, { "SendFLRRsp", 31, 1 }, { "ImmFLRRsp", 24, 1 }, @@ -4300,15 +4261,6 @@ struct reg_info t7_pcie_regs[] = { { "ByteEnable", 26, 4 }, { "RegAddr", 0, 15 }, { "PCIE_SWITCH_CFG_SPACE_DATA8", 0x5f78, 0 }, - { "PCIE_SNPS_G5_PHY_CR_REQ", 0x5f7c, 0 }, - { "RegSel", 31, 1 }, - { "RdEnable", 30, 1 }, - { "WrEnable", 29, 1 }, - { "AutoIncrVal", 21, 2 }, - { "AutoIncr", 20, 1 }, - { "PhySel", 16, 4 }, - { "RegAddr", 0, 16 }, - { "PCIE_SNPS_G5_PHY_CR_DATA", 0x5f80, 0 }, { "PCIE_SNPS_G5_PHY_SRAM_CFG", 0x5f84, 0 }, { "phy3_sram_bootload_bypass", 27, 1 }, { "phy3_sram_bypass", 26, 1 }, @@ -8895,10 +8847,6 @@ struct reg_info t7_mps_regs[] = { { "MPS_FPGA_BIST_CFG_P3", 0x912c, 0 }, { "AddrMask", 16, 16 }, { "BaseAddr", 0, 16 }, - { "MPS_INIC_CTL", 0x9130, 0 }, - { "RD_WRN", 16, 1 }, - { "ADDR", 0, 16 }, - { "MPS_INIC_DATA", 0x9134, 0 }, { "MPS_RED_CTL", 0x9140, 0 }, { "LPBK_SHIFT_0", 28, 4 }, { "LPBK_SHIFT_1", 24, 4 }, @@ -9279,7 +9227,19 @@ struct reg_info t7_mps_regs[] = { { "xgmac2mps_rx0_perr", 25, 1 }, { "xgmac2mps_rx1_perr", 24, 1 }, { "mps2crypto_rx_intf_fifo", 20, 4 }, - { "RX_PRE_PROC_PERR", 9, 11 }, + { "mac_rx_pproc_mps2tp_tf", 19, 1 }, + { "mac_rx_pproc_lb_ch3", 18, 1 }, + { "mac_rx_pproc_lb_ch2", 17, 1 }, + { "mac_rx_pproc_lb_ch1", 16, 1 }, + { "mac_rx_pproc_lb_ch0", 15, 1 }, + { "mac_rx_pproc_dwrr_ch0_3", 14, 1 }, + { "mac_rx_fifo_perr", 13, 1 }, + { "mac2mps_pt3_perr", 12, 1 }, + { "mac2mps_pt2_perr", 11, 1 }, + { "mac2mps_pt1_perr", 10, 1 }, + { "mac2mps_pt0_perr", 9, 1 }, + { "lpbk_fifo_perr", 8, 1 }, + { "tp2mps_tf_fifo_perr", 7, 1 }, { "MPS_RX_PERR_INT_ENABLE2", 0x11090, 0 }, { "crypt2mps_rx_intf_fifo", 28, 4 }, { "inic2mps_tx0_perr", 27, 1 }, @@ -9287,7 +9247,19 @@ struct reg_info t7_mps_regs[] = { { "xgmac2mps_rx0_perr", 25, 1 }, { "xgmac2mps_rx1_perr", 24, 1 }, { "mps2crypto_rx_intf_fifo", 20, 4 }, - { "RX_PRE_PROC_PERR", 9, 11 }, + { "mac_rx_pproc_mps2tp_tf", 19, 1 }, + { "mac_rx_pproc_lb_ch3", 18, 1 }, + { "mac_rx_pproc_lb_ch2", 17, 1 }, + { "mac_rx_pproc_lb_ch1", 16, 1 }, + { "mac_rx_pproc_lb_ch0", 15, 1 }, + { "mac_rx_pproc_dwrr_ch0_3", 14, 1 }, + { "mac_rx_fifo_perr", 13, 1 }, + { "mac2mps_pt3_perr", 12, 1 }, + { "mac2mps_pt2_perr", 11, 1 }, + { "mac2mps_pt1_perr", 10, 1 }, + { "mac2mps_pt0_perr", 9, 1 }, + { "lpbk_fifo_perr", 8, 1 }, + { "tp2mps_tf_fifo_perr", 7, 1 }, { "MPS_RX_PERR_ENABLE2", 0x11094, 0 }, { "crypt2mps_rx_intf_fifo", 28, 4 }, { "inic2mps_tx0_perr", 27, 1 }, @@ -9295,7 +9267,19 @@ struct reg_info t7_mps_regs[] = { { "xgmac2mps_rx0_perr", 25, 1 }, { "xgmac2mps_rx1_perr", 24, 1 }, { "mps2crypto_rx_intf_fifo", 20, 4 }, - { "RX_PRE_PROC_PERR", 9, 11 }, + { "mac_rx_pproc_mps2tp_tf", 19, 1 }, + { "mac_rx_pproc_lb_ch3", 18, 1 }, + { "mac_rx_pproc_lb_ch2", 17, 1 }, + { "mac_rx_pproc_lb_ch1", 16, 1 }, + { "mac_rx_pproc_lb_ch0", 15, 1 }, + { "mac_rx_pproc_dwrr_ch0_3", 14, 1 }, + { "mac_rx_fifo_perr", 13, 1 }, + { "mac2mps_pt3_perr", 12, 1 }, + { "mac2mps_pt2_perr", 11, 1 }, + { "mac2mps_pt1_perr", 10, 1 }, + { "mac2mps_pt0_perr", 9, 1 }, + { "lpbk_fifo_perr", 8, 1 }, + { "tp2mps_tf_fifo_perr", 7, 1 }, { "MPS_RX_PERR_INT_CAUSE3", 0x11310, 0 }, { "MPS_RX_PERR_INT_ENABLE3", 0x11314, 0 }, { "MPS_RX_PERR_ENABLE3", 0x11318, 0 }, @@ -22654,6 +22638,14 @@ struct reg_info t7_mac_t7_regs[] = { { "TX_CDR_LANE_SEL", 3, 3 }, { "RX_CDR_LANE_SEL", 0, 3 }, { "MAC_DEBUG_PL_IF_1", 0x381c4, 0 }, + { "MAC_HSS0_ANALOG_TEST_CTRL", 0x381d0, 0 }, + { "MAC_HSS1_ANALOG_TEST_CTRL", 0x381d4, 0 }, + { "MAC_HSS2_ANALOG_TEST_CTRL", 0x381d8, 0 }, + { "MAC_HSS3_ANALOG_TEST_CTRL", 0x381dc, 0 }, + { "MAC_HSS0_ANALOG_TEST_STATUS", 0x381e0, 0 }, + { "MAC_HSS1_ANALOG_TEST_STATUS", 0x381e4, 0 }, + { "MAC_HSS2_ANALOG_TEST_STATUS", 0x381e8, 0 }, + { "MAC_HSS3_ANALOG_TEST_STATUS", 0x381ec, 0 }, { "MAC_SIGNAL_DETECT_CTRL", 0x381f0, 0 }, { "Signal_Det_ln7", 15, 1 }, { "Signal_Det_ln6", 14, 1 }, @@ -24583,6 +24575,26 @@ struct reg_info t7_mac_t7_regs[] = { { "Q1_LOS_2_assert", 2, 1 }, { "Q1_LOS_1_assert", 1, 1 }, { "Q1_LOS_0_assert", 0, 1 }, + { "MAC_HSS0_PMD_RECEIVE_SIGNAL_DETECT", 0x3a93c, 0 }, + { "pmd_receive_signal_detect_1n3", 4, 1 }, + { "pmd_receive_signal_detect_1n2", 3, 1 }, + { "pmd_receive_signal_detect_ln1", 2, 1 }, + { "pmd_receive_signal_detect_1n0", 1, 1 }, + { "MAC_HSS1_PMD_RECEIVE_SIGNAL_DETECT", 0x3b93c, 0 }, + { "pmd_receive_signal_detect_1n3", 4, 1 }, + { "pmd_receive_signal_detect_1n2", 3, 1 }, + { "pmd_receive_signal_detect_ln1", 2, 1 }, + { "pmd_receive_signal_detect_1n0", 1, 1 }, + { "MAC_HSS2_PMD_RECEIVE_SIGNAL_DETECT", 0x3c93c, 0 }, + { "pmd_receive_signal_detect_1n3", 4, 1 }, + { "pmd_receive_signal_detect_1n2", 3, 1 }, + { "pmd_receive_signal_detect_ln1", 2, 1 }, + { "pmd_receive_signal_detect_1n0", 1, 1 }, + { "MAC_HSS3_PMD_RECEIVE_SIGNAL_DETECT", 0x3d93c, 0 }, + { "pmd_receive_signal_detect_1n3", 4, 1 }, + { "pmd_receive_signal_detect_1n2", 3, 1 }, + { "pmd_receive_signal_detect_ln1", 2, 1 }, + { "pmd_receive_signal_detect_1n0", 1, 1 }, { "MAC_MTIP_PCS_1G_0_CONTROL", 0x3e000, 0 }, { "Reset", 15, 1 }, { "Loopback", 14, 1 }, diff --git a/usr.sbin/cxgbetool/tcbinfot7.c b/usr.sbin/cxgbetool/tcbinfot7.c index 93b97bddbda6..9dea19774044 100644 --- a/usr.sbin/cxgbetool/tcbinfot7.c +++ b/usr.sbin/cxgbetool/tcbinfot7.c @@ -856,7 +856,7 @@ _TCBVAR g_tcb_info7[]={ NULL , 0, 0, /* faka,flo,fhi */ "rq_start" , /* aka */ COMP_NONE , /* comp */ - "DW aligned starting addres of RQ", /*desc*/ + "DW aligned starting address of RQ", /*desc*/ NULL, /*akadesc */ }, {"rq_MSN" , 2, 986, 998, /* name,aux,lo,hi */ diff --git a/usr.sbin/dumpcis/dumpcis.8 b/usr.sbin/dumpcis/dumpcis.8 index c40e5fe75d40..9da5ed9f3bdf 100644 --- a/usr.sbin/dumpcis/dumpcis.8 +++ b/usr.sbin/dumpcis/dumpcis.8 @@ -38,8 +38,7 @@ The utility translates a raw CIS stream into human readable form. .Sh SEE ALSO .Xr cardbus 4 , -.Xr cbb 4 , -.Xr pccard 4 +.Xr cbb 4 .Sh AUTHORS The original version was written by .An Warner Losh Aq Mt imp@FreeBSD.org . diff --git a/usr.sbin/fdcontrol/fdcontrol.8 b/usr.sbin/fdcontrol/fdcontrol.8 index 23c3a2ee20de..cbf8864d5fe7 100644 --- a/usr.sbin/fdcontrol/fdcontrol.8 +++ b/usr.sbin/fdcontrol/fdcontrol.8 @@ -23,7 +23,7 @@ .\" USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH .\" DAMAGE. .\" -.Dd April 7, 2017 +.Dd November 16, 2025 .Dt FDCONTROL 8 .Os .Sh NAME @@ -37,6 +37,11 @@ .Op Fl s Ar fmtstr .Op Fl v .Ar device +.Sh DEPRECATION NOTICE +.Nm +is deprecated and may not be present in +.Fx 16.0 +and later. .Sh DESCRIPTION The .Nm diff --git a/usr.sbin/fdformat/fdformat.8 b/usr.sbin/fdformat/fdformat.8 index bf18f93f5e87..72ec2bd2be5c 100644 --- a/usr.sbin/fdformat/fdformat.8 +++ b/usr.sbin/fdformat/fdformat.8 @@ -22,7 +22,7 @@ .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 23, 2020 +.Dd November 16, 2025 .Dt FDFORMAT 8 .Os .Sh NAME @@ -35,6 +35,11 @@ .Op Fl s Ar fmtstr .Op Fl nqvy .Ar device +.Sh DEPRECATION NOTICE +.Nm +is deprecated and may not be present in +.Fx 16.0 +and later. .Sh DESCRIPTION The .Nm diff --git a/usr.sbin/fdread/fdread.1 b/usr.sbin/fdread/fdread.1 index c0036906bee6..83892877b48b 100644 --- a/usr.sbin/fdread/fdread.1 +++ b/usr.sbin/fdread/fdread.1 @@ -24,7 +24,7 @@ .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" -.Dd May 14, 2001 +.Dd November 16, 2025 .Dt FDREAD 1 .Os .Sh NAME @@ -40,6 +40,11 @@ .Op Fl d Ar device .Fl I Ar numsects .Op Fl t Ar trackno +.Sh DEPRECATION NOTICE +.Nm +is deprecated and may not be present in +.Fx 16.0 +and later. .Sh DESCRIPTION The .Nm diff --git a/usr.sbin/fdwrite/fdwrite.1 b/usr.sbin/fdwrite/fdwrite.1 index 9d188de02d83..4773cfa20d9a 100644 --- a/usr.sbin/fdwrite/fdwrite.1 +++ b/usr.sbin/fdwrite/fdwrite.1 @@ -7,7 +7,7 @@ .\" ---------------------------------------------------------------------------- .\" .\" -.Dd September 16, 1993 +.Dd November 16, 2025 .Dt FDWRITE 1 .Os .Sh NAME @@ -19,6 +19,11 @@ .Op Fl y .Op Fl f Ar inputfile .Op Fl d Ar device +.Sh DEPRECATION NOTICE +.Nm +is deprecated and may not be present in +.Fx 16.0 +and later. .Sh DESCRIPTION The .Nm diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh index 2a07bc1fb7bc..b6e42e94f4bf 100644 --- a/usr.sbin/freebsd-update/freebsd-update.sh +++ b/usr.sbin/freebsd-update/freebsd-update.sh @@ -1402,7 +1402,7 @@ fetch_metadata_index () { fetch_metadata_bogus () { echo echo "The update metadata$1 is correctly signed, but" - echo "failed an integrity check." + echo "failed an integrity check ($2)." echo "Cowardly refusing to proceed any further." return 1 } @@ -1413,7 +1413,7 @@ fetch_metadata_index_merge () { for METAFILE in $@; do if [ `grep -E "^${METAFILE}\|" ${TINDEXHASH} | wc -l` \ -ne 1 ]; then - fetch_metadata_bogus " index" + fetch_metadata_bogus " index" "${METAFILE} count not 1" return 1 fi @@ -1436,7 +1436,7 @@ fetch_metadata_index_merge () { # specifically grepped out of ${TINDEXHASH}. fetch_metadata_index_sanity () { if grep -qvE '^[0-9A-Z.-]+\|[0-9a-f]{64}$' tINDEX.new; then - fetch_metadata_bogus " index" + fetch_metadata_bogus " index" "unexpected entry in tINDEX.new" return 1 fi } @@ -1453,7 +1453,7 @@ fetch_metadata_sanity () { # Check that the first four fields make sense. if gunzip -c < files/$1.gz | grep -qvE "^[a-z]+\|[0-9a-z-]+\|${P}+\|[fdL-]\|"; then - fetch_metadata_bogus "" + fetch_metadata_bogus "" "invalid initial fields" return 1 fi @@ -1464,28 +1464,28 @@ fetch_metadata_sanity () { # Sanity check entries with type 'f' if grep -E '^f' sanitycheck.tmp | grep -qvE "^f\|${M}\|${H}\|${P}*\$"; then - fetch_metadata_bogus "" + fetch_metadata_bogus "" "invalid type f entry" return 1 fi # Sanity check entries with type 'd' if grep -E '^d' sanitycheck.tmp | grep -qvE "^d\|${M}\|\|\$"; then - fetch_metadata_bogus "" + fetch_metadata_bogus "" "invalid type d entry" return 1 fi # Sanity check entries with type 'L' if grep -E '^L' sanitycheck.tmp | grep -qvE "^L\|${M}\|${P}*\|\$"; then - fetch_metadata_bogus "" + fetch_metadata_bogus "" "invalid type L entry" return 1 fi # Sanity check entries with type '-' if grep -E '^-' sanitycheck.tmp | grep -qvE "^-\|\|\|\|\|\|"; then - fetch_metadata_bogus "" + fetch_metadata_bogus "" "invalid type - entry" return 1 fi diff --git a/usr.sbin/fstyp/Makefile b/usr.sbin/fstyp/Makefile index ae5bae2e4f9d..c1f812cb5b97 100644 --- a/usr.sbin/fstyp/Makefile +++ b/usr.sbin/fstyp/Makefile @@ -47,7 +47,7 @@ CFLAGS.${src}+=-I${SRCTOP}/sys LIBADD= geom md ufs .if ${MK_ZFS} != "no" -LIBADD+=nvpair zfs spl +LIBADD+=nvpair zfs spl pthread .endif .include <bsd.prog.mk> diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 index 3a925bda8174..6098010ebbc4 100644 --- a/usr.sbin/jail/jail.8 +++ b/usr.sbin/jail/jail.8 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 6, 2025 +.Dd November 13, 2025 .Dt JAIL 8 .Os .Sh NAME @@ -1147,6 +1147,13 @@ D=/here/is/the/jail mkdir -p $D tar -xf /usr/freebsd-dist/base.txz -C $D --unlink .Ed +.Ss Setting up a Jail Directory Tree from System Packages +To set up a jail directory tree containing an selectable +.Fx +distribution with the packages tech preview, +the following command can be used: +.Pp +.Dl bsdinstall jail /here/is/the/jail .Pp In many cases these examples would put far more in the jail than needed. In the other extreme case a jail might contain only one file: diff --git a/usr.sbin/lpr/lpr/lpr.1 b/usr.sbin/lpr/lpr/lpr.1 index 8acb9d23d9da..b73870a0f46e 100644 --- a/usr.sbin/lpr/lpr/lpr.1 +++ b/usr.sbin/lpr/lpr/lpr.1 @@ -105,7 +105,7 @@ phototypesetter commands from ancient versions of .Xr troff 1 Pq Pa ports/textproc/groff . .It Fl v The files are assumed to contain a raster image for devices like the -Benson Varian. +Benson Variant. .El .Pp These options apply to the handling of diff --git a/usr.sbin/moused/moused/moused.8 b/usr.sbin/moused/moused/moused.8 index 2483f8a04b2a..b414b2ff787e 100644 --- a/usr.sbin/moused/moused/moused.8 +++ b/usr.sbin/moused/moused/moused.8 @@ -299,7 +299,7 @@ or .Dq Li generic . .It Fl l Ar level Ignored. -Used for compatibiliy with legacy +Used for compatibility with legacy .Nm . .It Fl m Ar N=M Assign the physical button @@ -529,7 +529,7 @@ The .Nm utility first appeared in .Fx 2.2 . -It was rewriten to support multiple input event devices in +It was rewritten to support multiple input event devices in .Fx 15.0 . .Sh AUTHORS .An -nosplit diff --git a/usr.sbin/moused/moused/moused.conf.5 b/usr.sbin/moused/moused/moused.conf.5 index bc62b5d00995..4b3955c8c7d1 100644 --- a/usr.sbin/moused/moused/moused.conf.5 +++ b/usr.sbin/moused/moused/moused.conf.5 @@ -37,7 +37,7 @@ file specifies how the (mouse daemon) should operate. It provides ability to adjust certain mice parameters on per-device basis. .Pp -Configuration file format is derrived from +Configuration file format is derived from .Xr libinput 1 device quirk files. A file may contain multiple section headers ([some identifier]) @@ -72,7 +72,7 @@ glob for the DMI modalias or the DeviceTree compatible string. .It MatchDevType One of touchpad, mouse, pointingstick, keyboard, joystick, tablet, tablet-pad. -Only touchpad and mouse types are suppported. +Only touchpad and mouse types are supported. .El .Ss List of currently available Moused tags. .Bl -tag -width indent @@ -296,10 +296,10 @@ Enable natural scrolling. .It MousedThreeFingerDrag Enable dragging with three fingers. .It MousedSoftButton2X -Horisontal position of 2-nd softbutton left edge in percents. +Horizontal position of 2-nd softbutton left edge in percents. (0-disable) .It MousedSoftButton3X -Horisontal position of 3-rd softbutton left edge in percents. +Horizontal position of 3-rd softbutton left edge in percents. (0-disable) .It MousedSoftButtonsY Vertical size of softbuttons area in percents. @@ -392,7 +392,7 @@ Predefined quirks processed before .Nm . .El .Sh EXAMPLES -Set touch pressure and palm detection thesholds for PS/2 Synaptics +Set touch pressure and palm detection thresholds for PS/2 Synaptics touchpad: .Bd -literal -offset indent [SynPS/2 Synaptics TouchPad] diff --git a/usr.sbin/pkg/FreeBSD.conf.latest b/usr.sbin/pkg/FreeBSD.conf.latest index ac1636386942..f4b80c02cffa 100644 --- a/usr.sbin/pkg/FreeBSD.conf.latest +++ b/usr.sbin/pkg/FreeBSD.conf.latest @@ -6,6 +6,8 @@ # echo "FreeBSD-ports: { enabled: no }" > /usr/local/etc/pkg/repos/FreeBSD.conf # echo "FreeBSD-ports-kmods: { enabled: no }" >> /usr/local/etc/pkg/repos/FreeBSD.conf # +# Note that the FreeBSD-base repository is disabled by default. +# FreeBSD-ports: { url: "pkg+https://pkg.FreeBSD.org/${ABI}/latest", @@ -21,3 +23,10 @@ FreeBSD-ports-kmods: { fingerprints: "/usr/share/keys/pkg", enabled: yes } +FreeBSD-base: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_latest", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: no +} diff --git a/usr.sbin/pkg/FreeBSD.conf.quarterly b/usr.sbin/pkg/FreeBSD.conf.quarterly index 4e26582c6981..117bbd49aeae 100644 --- a/usr.sbin/pkg/FreeBSD.conf.quarterly +++ b/usr.sbin/pkg/FreeBSD.conf.quarterly @@ -6,6 +6,8 @@ # echo "FreeBSD-ports: { enabled: no }" > /usr/local/etc/pkg/repos/FreeBSD.conf # echo "FreeBSD-ports-kmods: { enabled: no }" >> /usr/local/etc/pkg/repos/FreeBSD.conf # +# Note that the FreeBSD-base repository is disabled by default. +# FreeBSD-ports: { url: "pkg+https://pkg.FreeBSD.org/${ABI}/quarterly", @@ -21,3 +23,10 @@ FreeBSD-ports-kmods: { fingerprints: "/usr/share/keys/pkg", enabled: yes } +FreeBSD-base: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_latest", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: no +} diff --git a/usr.sbin/pkg/FreeBSD.conf.quarterly-release b/usr.sbin/pkg/FreeBSD.conf.quarterly-release index b4a78009f7d2..035d0ae976b9 100644 --- a/usr.sbin/pkg/FreeBSD.conf.quarterly-release +++ b/usr.sbin/pkg/FreeBSD.conf.quarterly-release @@ -6,6 +6,8 @@ # echo "FreeBSD-ports: { enabled: no }" > /usr/local/etc/pkg/repos/FreeBSD.conf # echo "FreeBSD-ports-kmods: { enabled: no }" >> /usr/local/etc/pkg/repos/FreeBSD.conf # +# Note that the FreeBSD-base repository is disabled by default. +# FreeBSD-ports: { url: "pkg+https://pkg.FreeBSD.org/${ABI}/quarterly", @@ -21,3 +23,10 @@ FreeBSD-ports-kmods: { fingerprints: "/usr/share/keys/pkg", enabled: yes } +FreeBSD-base: { + url: "pkg+https://pkgbase.FreeBSD.org/${ABI}/base_release_${VERSION_MINOR}", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkgbase-${VERSION_MAJOR}", + enabled: no +} diff --git a/usr.sbin/quot/quot.8 b/usr.sbin/quot/quot.8 index 32e666e2a863..b4b40bf395e9 100644 --- a/usr.sbin/quot/quot.8 +++ b/usr.sbin/quot/quot.8 @@ -27,7 +27,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 15, 2025 +.Dd November 13, 2025 .Dt QUOT 8 .Os .Sh NAME @@ -41,7 +41,9 @@ The .Nm utility -is used to gather statistics about the disk usage for each local user. +is used to gather per-user disk usage statistics from +.Xr ffs 7 +file systems. .Pp The following options are available: .Bl -tag -width indent @@ -51,8 +53,16 @@ Include statistics for all mounted file systems. Display three columns containing number of blocks per file, number of files in this category, and aggregate total of blocks in files with this or lower size. +This option is mutually exclusive with the +.Fl n +option. .It Fl f For each user, display count of files and space occupied. +This option has no effect if combined with the +.Fl c +or +.Fl n +options. .It Fl k Force the numbers to be reported in kilobyte counts. By default, all sizes are reported in 512-byte block counts. @@ -60,6 +70,7 @@ By default, all sizes are reported in 512-byte block counts. Given a list of inodes (plus some optional data on each line) in the standard input, for each file print out the owner (plus the remainder of the input line). +Lines that do not begin with a number are ignored. This is traditionally used in the pipe: .Bd -literal -offset indent @@ -68,9 +79,17 @@ ls -i | sed -e 's,^ *,,' | sort -k 1n | quot -n filesystem .Ed .Pp to get a report of files and their owners. +This option is mutually exclusive with the +.Fl c +option. .It Fl v In addition to the default output, display the number of files not accessed within 30, 60 and 90 days. +This option has no effect if combined with the +.Fl c +or +.Fl n +options. .El .Sh ENVIRONMENT .Bl -tag -width BLOCKSIZE @@ -87,6 +106,7 @@ size block. .Xr quota 1 , .Xr getmntinfo 3 , .Xr fstab 5 , +.Xr ffs 7 , .Xr mount 8 .Sh HISTORY This implementation of diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c index 5dda36ac8499..d2f7646f7041 100644 --- a/usr.sbin/quot/quot.c +++ b/usr.sbin/quot/quot.c @@ -41,6 +41,7 @@ #include <errno.h> #include <fcntl.h> #include <fstab.h> +#include <inttypes.h> #include <libufs.h> #include <mntopts.h> #include <paths.h> @@ -390,41 +391,43 @@ douser(int fd, struct fs *super) static void donames(int fd, struct fs *super) { - int c; - ino_t maxino; - uintmax_t inode; union dinode *dp; + char *end, *line; + size_t cap; + ssize_t len; + intmax_t inode, maxino; maxino = super->fs_ncg * super->fs_ipg - 1; - /* first skip the name of the filesystem */ - while ((c = getchar()) != EOF && (c < '0' || c > '9')) - while ((c = getchar()) != EOF && c != '\n'); - ungetc(c, stdin); - while (scanf("%ju", &inode) == 1) { - if (inode > maxino) { - warnx("illegal inode %ju", inode); - return; + line = NULL; + cap = 0; + while ((len = getline(&line, &cap, stdin)) > 0) { + if (len > 0 && line[len - 1] == '\n') + line[--len] = '\0'; + inode = strtoimax(line, &end, 10); + /* + * Silently ignore lines that do not begin with a number. + * For backward compatibility reasons, we do not require + * the optional comment to be preceded by whitespace. + */ + if (end == line) + continue; + if (inode <= 0 || inode > maxino) { + warnx("invalid inode %jd", inode); + continue; } if ((dp = get_inode(fd, super, inode)) != NULL && !isfree(super, dp)) { printf("%s\t", user(DIP(super, dp, di_uid))->name); /* now skip whitespace */ - while ((c = getchar()) == ' ' || c == '\t') - /* nothing */; + while (*end == ' ' || *end == '\t') + end++; /* and print out the remainder of the input line */ - while (c != EOF && c != '\n') { - putchar(c); - c = getchar(); - } - putchar('\n'); + printf("%s\n", end); } else { /* skip this line */ - while ((c = getchar()) != EOF && c != '\n') - /* nothing */; } - if (c == EOF) - break; } + free(line); } static void diff --git a/usr.sbin/quot/tests/quot_test.sh b/usr.sbin/quot/tests/quot_test.sh index 21088d162a53..c5e6717adca1 100644 --- a/usr.sbin/quot/tests/quot_test.sh +++ b/usr.sbin/quot/tests/quot_test.sh @@ -15,6 +15,8 @@ quot_setup() atf_check mount /dev/$dev "$mnt" echo "/dev/$dev: ($mnt)" >expect printf "%5d\t%5d\t%-8s\n" 8 2 "#0" >>expect + printf "%s\n" "/dev/$dev" >ninput + echo "/dev/$dev: ($mnt)" >nexpect } # Create a directory owned by a given UID @@ -23,12 +25,25 @@ quot_adduid() local uid=$1 atf_check install -d -o $uid -g 0 mnt/$uid printf "%5d\t%5d\t%-8s\n" 4 1 "#$uid" >>expect + ls -di mnt/$uid >>ninput + printf "%s\t%s\n" "#$uid" mnt/$uid >>nexpect } # Perform the tests quot_test() { local dev=$(cat dev) + # Deliberately add invalid lines to our -n input before the + # valid ones to verify that quot does not abort on first + # error. Note that quot deliberately ignores initial lines + # that don't start with a number, and that after encountering + # at least one line that does start with a number, quot would + # previously terminate on encountering one that doesn't (now + # it simply ignores them). This also tests that we don't + # require whitespace between the inode number and the comment. + echo "0zero" >>ninput + echo "invalid" >>ninput + echo "-1minusone" >>ninput # Create inodes owned by a large number of users to exercise # hash collisions and rehashing. The code uses an open hash # table that starts out with only 8 entries and doubles every @@ -50,6 +65,10 @@ quot_test() atf_check mount -ur /dev/$dev atf_check -o file:expect quot -fkN /dev/$dev atf_check -o file:expect quot -fkN $(realpath mnt) + # Test -n option + atf_check -o file:nexpect \ + -e inline:"quot: invalid inode 0\nquot: invalid inode -1\n" \ + quot -Nn /dev/$dev <ninput } # Unmount and release the memory disk diff --git a/usr.sbin/setaudit/.gitignore b/usr.sbin/setaudit/.gitignore new file mode 100644 index 000000000000..459fdebd0a30 --- /dev/null +++ b/usr.sbin/setaudit/.gitignore @@ -0,0 +1,2 @@ +setaudit +setaudit.o diff --git a/usr.sbin/setaudit/Makefile b/usr.sbin/setaudit/Makefile new file mode 100644 index 000000000000..548780f4cd03 --- /dev/null +++ b/usr.sbin/setaudit/Makefile @@ -0,0 +1,6 @@ +PROG= setaudit +MAN= setaudit.8 + +LIBADD+= bsm + +.include <bsd.prog.mk> diff --git a/usr.sbin/setaudit/setaudit.8 b/usr.sbin/setaudit/setaudit.8 new file mode 100644 index 000000000000..7dd66225979c --- /dev/null +++ b/usr.sbin/setaudit/setaudit.8 @@ -0,0 +1,88 @@ +.\" Copyright (c) 2018-2022 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. +.Dd March 21, 2018 +.Dt SETAUDIT 8 +.Os +.Sh NAME +.Nm setaudit +.Nd "specify audit configurations on a process" +.Sh SYNOPSIS +.Nm +.Op Fl 46U +.Op Fl a Ar auid +.Op Fl m Ar mask +.Op Fl s Ar source +.Op Fl p Ar port +.Ar command ... +.Sh DESCRIPTION +.Nm +is a tool to specify audit configurations on a process. +.Pp +The following options are available: +.Bl -tag -width ".Fl d Ar argument" +.It Fl 4 +Use IPv4. +.It Fl 6 +Use IPv6. +.It Fl U +Update audit session state rather than overwriting it. +By default, +.Nm +will overwrite the entire audit session state using the specified +parameters. +If +.Fl U +is specified, only the parameters given on the command line will be +updated, leaving the rest unchanged. +.It Fl a Ar auid +Audit user ID or user name. +.It Fl m Ar mask +String representation of an audit mask. +.It Fl s Ar source +IPv4 or IPv6 address of a Terminal ID. +.It Fl p Ar port +Port of a Terminal ID. +.Xr +.El +.Sh EXAMPLES +Enable all exe related audit events performed by +.Ar command +and its child processes: +.Pp +.Dl # setaudit -m ex command +.Sh SEE ALSO +.Xr getaudit 2 , +.Xr setaudit 2 , +.Xr au_mask 3 , +.Xr libbsm 3 , +.Xr audit_user 5 , +.Xr audit 8 +.Sh HISTORY +The +.Nm +utility was written by +.An Christian S.J. Peron Aq Mt csjp@FreeBSD.org . +.Sh AUTHORS +This +manual page was written by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . diff --git a/usr.sbin/setaudit/setaudit.c b/usr.sbin/setaudit/setaudit.c new file mode 100644 index 000000000000..af8f481afcb3 --- /dev/null +++ b/usr.sbin/setaudit/setaudit.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2018 Christian S.J. Peron + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <bsm/audit.h> +#include <bsm/libbsm.h> + +#include <netinet/in.h> + +#include <err.h> +#include <netdb.h> +#include <pwd.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static void +usage(char *prog) +{ + (void)fprintf(stderr, + "usage: %s [-46U] [-a auid] [-m mask] [-p port] [-s source] command ...\n", + prog); + exit(1); +} + +int +main(int argc, char *argv []) +{ + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + struct addrinfo hints; + auditinfo_addr_t aia; + char *aflag, *mflag, *sflag, *prog; + dev_t term_port; + uint32_t term_type; + int ch, error; + bool Uflag; + + aflag = mflag = sflag = NULL; + Uflag = false; + + prog = argv[0]; + bzero(&aia, sizeof(aia)); + bzero(&hints, sizeof(hints)); + term_type = AU_IPv4; + hints.ai_family = PF_UNSPEC; + while ((ch = getopt(argc, argv, "46a:m:p:s:U")) != -1) + switch (ch) { + case '4': + hints.ai_family = PF_INET; + break; + case '6': + hints.ai_family = PF_INET6; + break; + case 'a': + aflag = optarg; + break; + case 'm': + mflag = optarg; + break; + case 'p': + term_port = htons(atoi(optarg)); + break; + case 's': + sflag = optarg; + break; + case 'U': + Uflag = true; + break; + default: + usage(prog); + /* NOT REACHED */ + } + argc -= optind; + argv += optind; + if (argc == 0) + usage(prog); + + if (Uflag) { + if (getaudit_addr(&aia, sizeof(aia)) < 0) + err(1, "getaudit_addr"); + } + if (aflag) { + struct passwd *pwd; + + pwd = getpwnam(aflag); + if (pwd == NULL) { + char *r; + + aia.ai_auid = strtoul(aflag, &r, 10); + if (*r != '\0') + errx(1, "%s: invalid user", aflag); + } else + aia.ai_auid = pwd->pw_uid; + } + if (mflag) { + if (getauditflagsbin(mflag, &aia.ai_mask) < 0) + err(1, "getauditflagsbin"); + } + if (sflag) { + struct addrinfo *res; + + error = getaddrinfo(sflag, NULL, &hints, &res); + if (error) + errx(1, "%s", gai_strerror(error)); + switch (res->ai_family) { + case PF_INET6: + sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr; + bcopy(&sin6->sin6_addr.s6_addr, + &aia.ai_termid.at_addr[0], + sizeof(struct in6_addr)); + term_type = AU_IPv6; + break; + case PF_INET: + sin = (struct sockaddr_in *)(void *)res->ai_addr; + bcopy(&sin->sin_addr.s_addr, + &aia.ai_termid.at_addr[0], + sizeof(struct in_addr)); + term_type = AU_IPv4; + break; + } + } + if (!Uflag || sflag) { + aia.ai_termid.at_port = term_port; + aia.ai_termid.at_type = term_type; + } + if (setaudit_addr(&aia, sizeof(aia)) < 0) + err(1, "setaudit_addr"); + (void)execvp(*argv, argv); + err(1, "%s", *argv); +} diff --git a/usr.sbin/unbound/setup/local-unbound-setup.sh b/usr.sbin/unbound/setup/local-unbound-setup.sh index 25cfef48b6f0..ec3aeb673ecc 100755 --- a/usr.sbin/unbound/setup/local-unbound-setup.sh +++ b/usr.sbin/unbound/setup/local-unbound-setup.sh @@ -118,8 +118,8 @@ set_chrootdir() { get_nameservers() { while read line ; do local bareline=${line%%\#*} - local key=${bareline%% *} - local value=${bareline#* } + local key=${bareline%%[[:space:]]*} + local value=${bareline#*[[:space:]]} case ${key} in nameserver) case ${value} in @@ -145,8 +145,8 @@ gen_resolv_conf() { local edns0=no while read line ; do local bareline=${line%%\#*} - local key=${bareline%% *} - local value=${bareline#* } + local key=${bareline%%[[:space:]]*} + local value=${bareline#*[[:space:]]} case ${key} in nameserver) case ${value} in diff --git a/usr.sbin/ypldap/ldapclient.c b/usr.sbin/ypldap/ldapclient.c index a246a25a9605..76918de90366 100644 --- a/usr.sbin/ypldap/ldapclient.c +++ b/usr.sbin/ypldap/ldapclient.c @@ -317,7 +317,7 @@ client_dispatch_parent(int fd, short events, void *p) client_configure(env); break; default: - log_debug("client_dispatch_parent: unexpect imsg %d", + log_debug("client_dispatch_parent: unexpected imsg %d", imsg.hdr.type); break; |
