From: Vitaliy Makkoveev Subject: Unlock IPV6CTL_MAXFRAGS case of ip6_sysctl() To: Alexander Bluhm , tech@openbsd.org Date: Fri, 25 Jul 2025 01:19:32 +0300 The frag6_input() assumes that `ip6_maxfrags' could be negative and accept all the fragments without the limit in this case, meanwhile the sysctl(2) interface denies negative values for `ip6_maxfrags'. Unlimited queue is bad thing, so adjust the frag6_input() to be consistent with sysctl(2). Don't check `ip6_maxfrags' against null because in such case the "frag6_nfrags >= ip6_maxfrags" condition is always true. Unused in ramdisk. Index: sys/netinet6/frag6.c =================================================================== RCS file: /cvs/src/sys/netinet6/frag6.c,v retrieving revision 1.94 diff -u -p -r1.94 frag6.c --- sys/netinet6/frag6.c 21 Jul 2025 11:07:31 -0000 1.94 +++ sys/netinet6/frag6.c 24 Jul 2025 22:18:01 -0000 @@ -46,12 +46,17 @@ #include #include /* for ECN definitions */ -/* Protects `frag6_queue', `frag6_nfragpackets' and `frag6_nfrags'. */ + +/* + * Locks used to protect global variables in this file: + * Q frag6_mutex + */ + struct mutex frag6_mutex = MUTEX_INITIALIZER(IPL_SOFTNET); -u_int frag6_nfragpackets; -u_int frag6_nfrags; -TAILQ_HEAD(ip6q_head, ip6q) frag6_queue; /* ip6 reassemble queue */ +u_int frag6_nfragpackets; /* [Q] */ +u_int frag6_nfrags; /* [Q] */ +TAILQ_HEAD(ip6q_head, ip6q) frag6_queue; /* [Q] ip6 reassemble queue */ void frag6_freef(struct ip6q *); void frag6_unlink(struct ip6q *, struct ip6q_head *); @@ -173,9 +178,8 @@ frag6_input(struct mbuf **mp, int *offp, /* * Enforce upper bound on number of fragments. * If maxfrag is 0, never accept fragments. - * If maxfrag is -1, accept all fragments without limitation. */ - if (ip6_maxfrags >= 0 && frag6_nfrags >= (u_int)ip6_maxfrags) { + if (frag6_nfrags >= atomic_load_int(&ip6_maxfrags)) { mtx_leave(&frag6_mutex); goto dropfrag; } Index: sys/netinet6/in6_proto.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_proto.c,v retrieving revision 1.143 diff -u -p -r1.143 in6_proto.c --- sys/netinet6/in6_proto.c 24 Jul 2025 21:34:07 -0000 1.143 +++ sys/netinet6/in6_proto.c 24 Jul 2025 22:18:01 -0000 @@ -355,7 +355,7 @@ int ip6_sendredirects = 1; /* [a] */ int ip6_defhlim = IPV6_DEFHLIM; /* [a] */ int ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS; /* [a] */ int ip6_maxfragpackets = 200; /* [a] */ -int ip6_maxfrags = 200; +int ip6_maxfrags = 200; /* [a] */ int ip6_log_interval = 5; /* [a] */ int ip6_hdrnestlimit = 10; /* [a] appropriate? */ int ip6_dad_count = 1; /* [a] DupAddrDetectionTransmits */ Index: sys/netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.288 diff -u -p -r1.288 ip6_input.c --- sys/netinet6/ip6_input.c 24 Jul 2025 21:35:53 -0000 1.288 +++ sys/netinet6/ip6_input.c 24 Jul 2025 22:18:01 -0000 @@ -1454,10 +1454,10 @@ const struct sysctl_bounded_args ipv6ctl { IPV6CTL_AUTO_FLOWLABEL, &ip6_auto_flowlabel, 0, 1 }, { IPV6CTL_DEFMCASTHLIM, &ip6_defmcasthlim, 0, 255 }, { IPV6CTL_USE_DEPRECATED, &ip6_use_deprecated, 0, 1 }, + { IPV6CTL_MAXFRAGS, &ip6_maxfrags, 0, 1000 }, }; const struct sysctl_bounded_args ipv6ctl_vars[] = { - { IPV6CTL_MAXFRAGS, &ip6_maxfrags, 0, 1000 }, { IPV6CTL_MFORWARDING, &ip6_mforwarding, 0, 1 }, { IPV6CTL_MCAST_PMTU, &ip6_mcast_pmtu, 0, 1 }, { IPV6CTL_NEIGHBORGCTHRESH, &ip6_neighborgcthresh, -1, 5 * 2048 }, @@ -1574,6 +1574,7 @@ ip6_sysctl(int *name, u_int namelen, voi case IPV6CTL_AUTO_FLOWLABEL: case IPV6CTL_DEFMCASTHLIM: case IPV6CTL_USE_DEPRECATED: + case IPV6CTL_MAXFRAGS: return (sysctl_bounded_arr( ipv6ctl_vars_unlocked, nitems(ipv6ctl_vars_unlocked), name, namelen, oldp, oldlenp, newp, newlen));