diff options
| -rw-r--r-- | ObsoleteFiles.inc | 3 | ||||
| -rw-r--r-- | include/stdckdint.h | 6 | ||||
| -rw-r--r-- | lib/libc/stdtime/strptime.3 | 2 | ||||
| -rw-r--r-- | lib/libc/stdtime/strptime.c | 3 | ||||
| -rw-r--r-- | libexec/dma/dmagent/Makefile | 6 | ||||
| -rwxr-xr-x | libexec/rc/rc.d/hostapd | 9 | ||||
| -rw-r--r-- | sbin/mount_nullfs/mount_nullfs.8 | 28 | ||||
| -rw-r--r-- | share/man/man5/src.conf.5 | 18 | ||||
| -rw-r--r-- | share/mk/bsd.opts.mk | 2 | ||||
| -rw-r--r-- | share/mk/src.opts.mk | 1 | ||||
| -rw-r--r-- | sys/fs/nullfs/null.h | 13 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_subr.c | 4 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_vfsops.c | 20 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_vnops.c | 10 | ||||
| -rw-r--r-- | sys/netinet/tcp_syncache.c | 33 | ||||
| -rw-r--r-- | sys/netinet/udp_usrreq.c | 15 | ||||
| -rw-r--r-- | tests/sys/netinet/so_reuseport_lb_test.c | 148 | ||||
| -rw-r--r-- | tools/build/mk/OptionalObsoleteFiles.inc | 2 |
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 |
