aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ObsoleteFiles.inc3
-rw-r--r--include/stdckdint.h6
-rw-r--r--lib/libc/stdtime/strptime.32
-rw-r--r--lib/libc/stdtime/strptime.c3
-rw-r--r--libexec/dma/dmagent/Makefile6
-rwxr-xr-xlibexec/rc/rc.d/hostapd9
-rw-r--r--sbin/mount_nullfs/mount_nullfs.828
-rw-r--r--share/man/man5/src.conf.518
-rw-r--r--share/mk/bsd.opts.mk2
-rw-r--r--share/mk/src.opts.mk1
-rw-r--r--sys/fs/nullfs/null.h13
-rw-r--r--sys/fs/nullfs/null_subr.c4
-rw-r--r--sys/fs/nullfs/null_vfsops.c20
-rw-r--r--sys/fs/nullfs/null_vnops.c10
-rw-r--r--sys/netinet/tcp_syncache.c33
-rw-r--r--sys/netinet/udp_usrreq.c15
-rw-r--r--tests/sys/netinet/so_reuseport_lb_test.c148
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc2
18 files changed, 267 insertions, 56 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 9d8c8a048041..de25b6608fe6 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -51,6 +51,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20251023: This file is now installed in /etc/dma
+OLD_FILES+=usr/share/examples/dma/auth.conf
+
# 20251006: Remove libnss_tacplus.a (it never should have been installed)
OLD_FILES+=usr/lib/libnss_tacplus.a
diff --git a/include/stdckdint.h b/include/stdckdint.h
index af3074dded89..9cb877fe8198 100644
--- a/include/stdckdint.h
+++ b/include/stdckdint.h
@@ -13,7 +13,7 @@
#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_add_overflow)
#define ckd_add(result, a, b) \
- (_Bool)__builtin_add_overflow((a), (b), (result))
+ __builtin_add_overflow((a), (b), (result))
#else
#define ckd_add(result, a, b) \
_Static_assert(0, "checked addition not supported")
@@ -21,7 +21,7 @@
#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_sub_overflow)
#define ckd_sub(result, a, b) \
- (_Bool)__builtin_sub_overflow((a), (b), (result))
+ __builtin_sub_overflow((a), (b), (result))
#else
#define ckd_sub(result, a, b) \
_Static_assert(0, "checked subtraction not supported")
@@ -29,7 +29,7 @@
#if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_mul_overflow)
#define ckd_mul(result, a, b) \
- (_Bool)__builtin_mul_overflow((a), (b), (result))
+ __builtin_mul_overflow((a), (b), (result))
#else
#define ckd_mul(result, a, b) \
_Static_assert(0, "checked multiplication not supported")
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
index 7df73d2d080a..9456fa757b85 100644
--- a/lib/libc/stdtime/strptime.3
+++ b/lib/libc/stdtime/strptime.3
@@ -171,7 +171,7 @@ is taken as noon.
The
.Fa %Z
format specifier only accepts time zone abbreviations of the local time zone,
-or the value "GMT".
+and the values "GMT", "UTC", or "Z".
This limitation is because of ambiguity due to of the over loading of time
zone abbreviations.
One such example is
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index e9ffe7180916..b89e140aa8d5 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -554,7 +554,8 @@ label:
zonestr[cp - buf] = '\0';
tzset();
if (0 == strcmp(zonestr, "GMT") ||
- 0 == strcmp(zonestr, "UTC")) {
+ 0 == strcmp(zonestr, "UTC") ||
+ 0 == strcmp(zonestr, "Z")) {
*GMTp = 1;
} else if (0 == strcmp(zonestr, tzname[0])) {
tm->tm_isdst = 0;
diff --git a/libexec/dma/dmagent/Makefile b/libexec/dma/dmagent/Makefile
index 0b38c5dca6b5..f73ca1ddccf1 100644
--- a/libexec/dma/dmagent/Makefile
+++ b/libexec/dma/dmagent/Makefile
@@ -18,12 +18,14 @@ SRCS= aliases_parse.y \
util.c
MAN8= dma.8
MLINKS= dma.8 dma.conf.5
-CONFS= dma.conf
+CONFSMODE= 0640
+CONFSGRP= mail
+CONFS= auth.conf dma.conf
CONFSDIR= ${CONFDIR}/dma
CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L
YFLAGS+= -i
CLEANFILES= aliases_parse.i
-FILES= auth.conf mailer.conf
+FILES= mailer.conf
FILESDIR= ${SHAREDIR}/examples/dma
BINMODE= 2555
diff --git a/libexec/rc/rc.d/hostapd b/libexec/rc/rc.d/hostapd
index fe3dac1dea06..6986250b7c07 100755
--- a/libexec/rc/rc.d/hostapd
+++ b/libexec/rc/rc.d/hostapd
@@ -11,15 +11,6 @@
name="hostapd"
desc="Authenticator for IEEE 802.11 networks"
command=${hostapd_program}
-start_postcmd="hostapd_poststart"
-
-hostapd_poststart() {
- if [ -n "$ifn" ]; then
- ifconfig ${ifn} down
- sleep 2
- ifconfig ${ifn} up
- fi
-}
ifn="$2"
if [ -z "$ifn" ]; then
diff --git a/sbin/mount_nullfs/mount_nullfs.8 b/sbin/mount_nullfs/mount_nullfs.8
index 68ff6beb8eaf..ea4f5a53c1d3 100644
--- a/sbin/mount_nullfs/mount_nullfs.8
+++ b/sbin/mount_nullfs/mount_nullfs.8
@@ -92,7 +92,7 @@ See the
.Xr mount 8
man page for possible options and their meanings.
Additionally the following option is supported:
-.Bl -tag -width nocache
+.Bl -tag -width nounixbypass
.It Cm nocache
Disable metadata caching in the null layer.
Some lower-layer file systems may force this option.
@@ -100,6 +100,32 @@ Depending on the access pattern,
this may result in increased lock contention.
.It Cm cache
Force enable metadata caching.
+.It Cm nounixbypass
+Disable bypassing
+.Xr unix 4
+socket files used for
+.Xr bind 2
+and
+.Xr connect 2 ,
+to the lower (mounted-from) filesystem layer.
+.Pp
+The effect is that lower and upper (bypassed) unix sockets
+are separate.
+.It Cm unixbypass
+Enable the bypass of unix socket file to lower filesystem layer.
+This is default.
+.Pp
+The effect is that
+.Xr bind 2
+and
+.Xr connect 2
+operations on a unix socket done from either the upper (nullfs) or lower
+layer path are performed on same unix socket.
+For instance, if a server
+.Xr bind 2
+is done on a socket in the lower layer, then
+.Xr connect 2
+on the socket file accessed via the nullfs mount, connects to the server.
.El
.El
.Pp
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index 24d041d055a4..f7e523ea70bb 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -1,5 +1,5 @@
.\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman.
-.Dd September 16, 2025
+.Dd October 22, 2025
.Dt SRC.CONF 5
.Os
.Sh NAME
@@ -1046,6 +1046,16 @@ Build GELI bootloader support.
.Pp
This is a default setting on
amd64/amd64, arm/armv7, arm64/aarch64, i386/i386 and riscv/riscv64.
+.It Va WITHOUT_LOADER_IA32
+Do not build the 32-bit UEFI loader.
+.Pp
+This is a default setting on
+arm/armv7, arm64/aarch64, i386/i386, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpc64le and riscv/riscv64.
+.It Va WITH_LOADER_IA32
+Build the 32-bit UEFI loader.
+.Pp
+This is a default setting on
+amd64/amd64.
.It Va WITHOUT_LOADER_KBOOT
Do not build kboot, a linuxboot environment loader
.Pp
@@ -1187,15 +1197,15 @@ if executed as an unprivileged user.
See
.Xr tests 7
for more details.
-.It Va WITH_MALLOC_PRODUCTION
-Disable assertions and statistics gathering in
+.It Va WITHOUT_MALLOC_PRODUCTION
+Enable assertions and statistics gathering in
.Xr malloc 3 .
The run-time options
.Dv opt.abort ,
.Dv opt.abort_conf ,
and
.Dv opt.junk
-also default to false.
+also default to true.
.It Va WITHOUT_MAN
Do not build manual pages.
When set, these options are also in effect:
diff --git a/share/mk/bsd.opts.mk b/share/mk/bsd.opts.mk
index b56afb89a44d..dfbcab89b7fd 100644
--- a/share/mk/bsd.opts.mk
+++ b/share/mk/bsd.opts.mk
@@ -65,6 +65,7 @@ __DEFAULT_YES_OPTIONS = \
NLS \
OPENSSH \
RELRO \
+ REPRODUCIBLE_BUILD \
SSP \
TESTS \
TOOLCHAIN \
@@ -80,7 +81,6 @@ __DEFAULT_NO_OPTIONS = \
INIT_ALL_ZERO \
INSTALL_AS_USER \
PROFILE \
- REPRODUCIBLE_BUILD \
RETPOLINE \
STALE_STAGED \
UBSAN
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index 0bc3d64806c9..0c8eb737fa05 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -166,7 +166,6 @@ __DEFAULT_YES_OPTIONS = \
QUOTAS \
RADIUS_SUPPORT \
RBOOTD \
- REPRODUCIBLE_BUILD \
RESCUE \
ROUTED \
SENDMAIL \
diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h
index 3ae0cd02b2b6..eebf6da571b8 100644
--- a/sys/fs/nullfs/null.h
+++ b/sys/fs/nullfs/null.h
@@ -37,7 +37,8 @@
#ifndef FS_NULL_H
#define FS_NULL_H
-#define NULLM_CACHE 0x0001
+#define NULLM_CACHE 0x0001
+#define NULLM_NOUNPBYPASS 0x0002
struct null_mount {
struct mount *nullm_vfs;
@@ -80,6 +81,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
#endif
extern struct vop_vector null_vnodeops;
+extern struct vop_vector null_vnodeops_no_unp_bypass;
+
+static inline bool
+null_is_nullfs_vnode(struct vnode *vp)
+{
+ const struct vop_vector *op;
+
+ op = vp->v_op;
+ return (op == &null_vnodeops || op == &null_vnodeops_no_unp_bypass);
+}
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_NULLFSNODE);
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 546f0aea3766..b0e3d15b4789 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -212,7 +212,9 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
*/
xp = malloc(sizeof(struct null_node), M_NULLFSNODE, M_WAITOK);
- error = getnewvnode("nullfs", mp, &null_vnodeops, &vp);
+ error = getnewvnode("nullfs", mp, (MOUNTTONULLMOUNT(mp)->nullm_flags &
+ NULLM_NOUNPBYPASS) != 0 ? &null_vnodeops_no_unp_bypass :
+ &null_vnodeops, &vp);
if (error) {
vput(lowervp);
free(xp, M_NULLFSNODE);
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 8d980932623d..8b9e04775449 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -89,6 +89,10 @@ nullfs_mount(struct mount *mp)
char *target;
int error, len;
bool isvnunlocked;
+ static const char cache_opt_name[] = "cache";
+ static const char nocache_opt_name[] = "nocache";
+ static const char unixbypass_opt_name[] = "unixbypass";
+ static const char nounixbypass_opt_name[] = "nounixbypass";
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
@@ -120,7 +124,7 @@ nullfs_mount(struct mount *mp)
/*
* Unlock lower node to avoid possible deadlock.
*/
- if (mp->mnt_vnodecovered->v_op == &null_vnodeops &&
+ if (null_is_nullfs_vnode(mp->mnt_vnodecovered) &&
VOP_ISLOCKED(mp->mnt_vnodecovered) == LK_EXCLUSIVE) {
VOP_UNLOCK(mp->mnt_vnodecovered);
isvnunlocked = true;
@@ -154,7 +158,7 @@ nullfs_mount(struct mount *mp)
/*
* Check multi null mount to avoid `lock against myself' panic.
*/
- if (mp->mnt_vnodecovered->v_op == &null_vnodeops) {
+ if (null_is_nullfs_vnode(mp->mnt_vnodecovered)) {
nn = VTONULL(mp->mnt_vnodecovered);
if (nn == NULL || lowerrootvp == nn->null_lowervp) {
NULLFSDEBUG("nullfs_mount: multi null mount?\n");
@@ -209,9 +213,10 @@ nullfs_mount(struct mount *mp)
MNT_IUNLOCK(mp);
}
- if (vfs_getopt(mp->mnt_optnew, "cache", NULL, NULL) == 0) {
+ if (vfs_getopt(mp->mnt_optnew, cache_opt_name, NULL, NULL) == 0) {
xmp->nullm_flags |= NULLM_CACHE;
- } else if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0) {
+ } else if (vfs_getopt(mp->mnt_optnew, nocache_opt_name, NULL,
+ NULL) == 0) {
;
} else if (null_cache_vnodes &&
(xmp->nullm_vfs->mnt_kern_flag & MNTK_NULL_NOCACHE) == 0) {
@@ -223,6 +228,13 @@ nullfs_mount(struct mount *mp)
&xmp->notify_node);
}
+ if (vfs_getopt(mp->mnt_optnew, unixbypass_opt_name, NULL, NULL) == 0) {
+ ;
+ } else if (vfs_getopt(mp->mnt_optnew, nounixbypass_opt_name, NULL,
+ NULL) == 0) {
+ xmp->nullm_flags |= NULLM_NOUNPBYPASS;
+ }
+
if (lowerrootvp == mp->mnt_vnodecovered) {
vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
lowerrootvp->v_vflag |= VV_CROSSLOCK;
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 41915da7f13c..2e34b77a5a7e 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -258,7 +258,7 @@ null_bypass(struct vop_generic_args *ap)
* that aren't. (We must always map first vp or vclean fails.)
*/
if (i != 0 && (*this_vp_p == NULLVP ||
- (*this_vp_p)->v_op != &null_vnodeops)) {
+ !null_is_nullfs_vnode(*this_vp_p))) {
old_vps[i] = NULLVP;
} else {
old_vps[i] = *this_vp_p;
@@ -1192,3 +1192,11 @@ struct vop_vector null_vnodeops = {
.vop_copy_file_range = VOP_PANIC,
};
VFS_VOP_VECTOR_REGISTER(null_vnodeops);
+
+struct vop_vector null_vnodeops_no_unp_bypass = {
+ .vop_default = &null_vnodeops,
+ .vop_unp_bind = vop_stdunp_bind,
+ .vop_unp_connect = vop_stdunp_connect,
+ .vop_unp_detach = vop_stdunp_detach,
+};
+VFS_VOP_VECTOR_REGISTER(null_vnodeops_no_unp_bypass);
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 1c585378dc5b..077c3a5f6ef3 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1056,6 +1056,8 @@ abort:
*
* On syncache_socket() success the newly created socket
* has its underlying inp locked.
+ *
+ * *lsop is updated, if and only if 1 is returned.
*/
int
syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
@@ -1103,12 +1105,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* a valid syncookie.
*/
SCH_UNLOCK(sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(syncookies disabled)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
if (sch->sch_last_overflow <
time_uptime - SYNCOOKIE_LIFETIME) {
@@ -1117,12 +1121,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* don't even check for a valid syncookie.
*/
SCH_UNLOCK(sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(no syncache entry)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
SCH_UNLOCK(sch);
}
@@ -1135,11 +1141,13 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc = &scs;
TCPSTAT_INC(tcps_sc_recvcookie);
} else {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Segment failed "
"SYNCOOKIE authentication, segment rejected "
"(probably spoofed)\n", s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/* If received ACK has MD5 signature, check it. */
@@ -1213,9 +1221,9 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"%s; %s: SEG.TSval %u < TS.Recent %u, "
"segment dropped\n", s, __func__,
to->to_tsval, sc->sc_tsreflect);
- free(s, M_TCPLOG);
}
SCH_UNLOCK(sch);
+ free(s, M_TCPLOG);
return (-1); /* Do not send RST */
}
@@ -1232,7 +1240,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"expected, segment processed normally\n",
s, __func__);
free(s, M_TCPLOG);
- s = NULL;
}
}
@@ -1319,16 +1326,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (sc != &scs)
syncache_free(sc);
return (1);
-failed:
- if (sc != NULL) {
- TCPSTATES_DEC(TCPS_SYN_RECEIVED);
- if (sc != &scs)
- syncache_free(sc);
- }
- if (s != NULL)
- free(s, M_TCPLOG);
- *lsop = NULL;
- return (0);
}
static struct socket *
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index f44bd1838d07..88df8f8d38fc 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -786,7 +786,8 @@ udplite_ctlinput(struct icmp *icmp)
static int
udp_pcblist(SYSCTL_HANDLER_ARGS)
{
- struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_udbinfo,
+ struct inpcbinfo *pcbinfo = udp_get_inpcbinfo(arg2);
+ struct inpcb_iterator inpi = INP_ALL_ITERATOR(pcbinfo,
INPLOOKUP_RLOCKPCB);
struct xinpgen xig;
struct inpcb *inp;
@@ -798,7 +799,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
if (req->oldptr == 0) {
int n;
- n = V_udbinfo.ipi_count;
+ n = pcbinfo->ipi_count;
n += imax(n / 8, 10);
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xinpcb);
return (0);
@@ -809,8 +810,8 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
bzero(&xig, sizeof(xig));
xig.xig_len = sizeof xig;
- xig.xig_count = V_udbinfo.ipi_count;
- xig.xig_gen = V_udbinfo.ipi_gencnt;
+ xig.xig_count = pcbinfo->ipi_count;
+ xig.xig_gen = pcbinfo->ipi_gencnt;
xig.xig_sogen = so_gencnt;
error = SYSCTL_OUT(req, &xig, sizeof xig);
if (error)
@@ -837,9 +838,9 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
* that something happened while we were processing this
* request, and it might be necessary to retry.
*/
- xig.xig_gen = V_udbinfo.ipi_gencnt;
+ xig.xig_gen = pcbinfo->ipi_gencnt;
xig.xig_sogen = so_gencnt;
- xig.xig_count = V_udbinfo.ipi_count;
+ xig.xig_count = pcbinfo->ipi_count;
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
@@ -847,7 +848,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, IPPROTO_UDP,
udp_pcblist, "S,xinpcb",
"List of active UDP sockets");
diff --git a/tests/sys/netinet/so_reuseport_lb_test.c b/tests/sys/netinet/so_reuseport_lb_test.c
index 5d3b2ab03af8..6c345c84f452 100644
--- a/tests/sys/netinet/so_reuseport_lb_test.c
+++ b/tests/sys/netinet/so_reuseport_lb_test.c
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
#include <sys/param.h>
+#include <sys/filio.h>
+#include <sys/ioccom.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -236,10 +238,156 @@ ATF_TC_BODY(basic_ipv6, tc)
}
}
+/*
+ * The kernel erroneously permits calling connect() on a UDP socket with
+ * SO_REUSEPORT_LB set. Verify that packets sent to the bound address are
+ * dropped unless they come from the connected address.
+ */
+ATF_TC_WITHOUT_HEAD(connect_udp);
+ATF_TC_BODY(connect_udp, tc)
+{
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_len = sizeof(sin),
+ .sin_addr = { htonl(INADDR_LOOPBACK) },
+ };
+ ssize_t n;
+ int error, len, s1, s2, s3;
+ char ch;
+
+ s1 = socket(PF_INET, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s1 >= 0);
+ s2 = socket(PF_INET, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s2 >= 0);
+ s3 = socket(PF_INET, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s3 >= 0);
+
+ error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1},
+ sizeof(int));
+ ATF_REQUIRE_MSG(error == 0,
+ "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno));
+ error = bind(s1, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ error = bind(s2, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ error = bind(s3, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ /* Connect to an address not owned by s2. */
+ error = getsockname(s3, (struct sockaddr *)&sin,
+ (socklen_t[]){sizeof(sin)});
+ ATF_REQUIRE(error == 0);
+ error = connect(s1, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno));
+
+ /* Try to send a packet to s1 from s2. */
+ error = getsockname(s1, (struct sockaddr *)&sin,
+ (socklen_t[]){sizeof(sin)});
+ ATF_REQUIRE(error == 0);
+
+ ch = 42;
+ n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin,
+ sizeof(sin));
+ ATF_REQUIRE(n == 1);
+
+ /* Give the packet some time to arrive. */
+ usleep(100000);
+
+ /* s1 is connected to s3 and shouldn't receive from s2. */
+ error = ioctl(s1, FIONREAD, &len);
+ ATF_REQUIRE(error == 0);
+ ATF_REQUIRE_MSG(len == 0, "unexpected data available");
+
+ /* ... but s3 can of course send to s1. */
+ n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin,
+ sizeof(sin));
+ ATF_REQUIRE(n == 1);
+ usleep(100000);
+ error = ioctl(s1, FIONREAD, &len);
+ ATF_REQUIRE(error == 0);
+ ATF_REQUIRE_MSG(len == 1, "unexpected data available");
+}
+
+/*
+ * The kernel erroneously permits calling connect() on a UDP socket with
+ * SO_REUSEPORT_LB set. Verify that packets sent to the bound address are
+ * dropped unless they come from the connected address.
+ */
+ATF_TC_WITHOUT_HEAD(connect_udp6);
+ATF_TC_BODY(connect_udp6, tc)
+{
+ struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ .sin6_len = sizeof(sin6),
+ .sin6_addr = IN6ADDR_LOOPBACK_INIT,
+ };
+ ssize_t n;
+ int error, len, s1, s2, s3;
+ char ch;
+
+ s1 = socket(PF_INET6, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s1 >= 0);
+ s2 = socket(PF_INET6, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s2 >= 0);
+ s3 = socket(PF_INET6, SOCK_DGRAM, 0);
+ ATF_REQUIRE(s3 >= 0);
+
+ error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1},
+ sizeof(int));
+ ATF_REQUIRE_MSG(error == 0,
+ "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno));
+ error = bind(s1, (struct sockaddr *)&sin6, sizeof(sin6));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ error = bind(s2, (struct sockaddr *)&sin6, sizeof(sin6));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ error = bind(s3, (struct sockaddr *)&sin6, sizeof(sin6));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ /* Connect to an address not owned by s2. */
+ error = getsockname(s3, (struct sockaddr *)&sin6,
+ (socklen_t[]){sizeof(sin6)});
+ ATF_REQUIRE(error == 0);
+ error = connect(s1, (struct sockaddr *)&sin6, sizeof(sin6));
+ ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno));
+
+ /* Try to send a packet to s1 from s2. */
+ error = getsockname(s1, (struct sockaddr *)&sin6,
+ (socklen_t[]){sizeof(sin6)});
+ ATF_REQUIRE(error == 0);
+
+ ch = 42;
+ n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6,
+ sizeof(sin6));
+ ATF_REQUIRE(n == 1);
+
+ /* Give the packet some time to arrive. */
+ usleep(100000);
+
+ /* s1 is connected to s3 and shouldn't receive from s2. */
+ error = ioctl(s1, FIONREAD, &len);
+ ATF_REQUIRE(error == 0);
+ ATF_REQUIRE_MSG(len == 0, "unexpected data available");
+
+ /* ... but s3 can of course send to s1. */
+ n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6,
+ sizeof(sin6));
+ ATF_REQUIRE(n == 1);
+ usleep(100000);
+ error = ioctl(s1, FIONREAD, &len);
+ ATF_REQUIRE(error == 0);
+ ATF_REQUIRE_MSG(len == 1, "unexpected data available");
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, basic_ipv4);
ATF_TP_ADD_TC(tp, basic_ipv6);
+ ATF_TP_ADD_TC(tp, connect_udp);
+ ATF_TP_ADD_TC(tp, connect_udp6);
return (atf_no_error());
}
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 331c88c0619b..5b49c713182a 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -1481,12 +1481,12 @@ OLD_DIRS+=usr/share/dict
.endif
.if ${MK_DMAGENT} == no
+OLD_FILES+=etc/dma/auth.conf
OLD_FILES+=etc/dma/dma.conf
OLD_DIRS+=etc/dma
OLD_FILES+=usr/libexec/dma
OLD_FILES+=usr/libexec/dma-mbox-create
OLD_FILES+=usr/share/man/man8/dma.8.gz
-OLD_FILES+=usr/share/examples/dma/auth.conf
OLD_FILES+=usr/share/examples/dma/mailer.conf
OLD_DIRS+=usr/share/examples/dma
.endif