[PATCH] multi-protocol MSF API sysctl limit support
From: David Stevens <hidden>
Date: 2004-03-06 09:37:56
This patch adds support for administrator-controlled multicast source
filter limits for the multiprotocol multicast source filter API. The v4
portion
uses the same sysctl variable as the previous v4-only API patch, and
the v6 portion uses a new v6 sysctl variable, "mld_max_msf".
In-line 2.4.x and attached 2.4.x and 2.6.x versions.
+-DLS
diff -ruN linux-2.4.25F4/include/linux/sysctl.h linux-2.4.25F5/include/linux/sysctl.h--- linux-2.4.25F4/include/linux/sysctl.h 2004-03-04 17:02:54.000000000 -0800
+++ linux-2.4.25F5/include/linux/sysctl.h 2004-03-05 00:02:57.000000000 -0800@@ -388,7 +388,8 @@ NET_IPV6_NEIGH=17, NET_IPV6_ROUTE=18, NET_IPV6_ICMP=19, - NET_IPV6_BINDV6ONLY=20 + NET_IPV6_BINDV6ONLY=20, + NET_IPV6_MLD_MAX_MSF=25, }; enum {
diff -ruN linux-2.4.25F4/include/net/ipv6.h linux-2.4.25F5/include/net/ipv6.h
--- linux-2.4.25F4/include/net/ipv6.h 2004-03-04 17:15:19.000000000 -0800
+++ linux-2.4.25F5/include/net/ipv6.h 2004-03-05 00:19:31.000000000 -0800@@ -104,6 +104,7 @@ /* sysctls */ extern int sysctl_ipv6_bindv6only; +extern int sysctl_mld_max_msf; extern struct ipv6_mib ipv6_statistics[NR_CPUS*2]; #define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
diff -ruN linux-2.4.25F4/net/ipv4/ip_sockglue.c linux-2.4.25F5/net/ipv4/ip_sockglue.c
--- linux-2.4.25F4/net/ipv4/ip_sockglue.c 2004-03-04 19:29:33.000000000 -0800
+++ linux-2.4.25F5/net/ipv4/ip_sockglue.c 2004-03-05 16:21:06.000000000 -0800@@ -762,6 +762,8 @@ } case MCAST_MSFILTER: { + extern int sysctl_optmem_max; + extern int sysctl_igmp_max_msf; struct sockaddr_in *psin; struct ip_msfilter *msf = 0; struct group_filter *gsf = 0;
@@ -769,6 +771,10 @@ if (optlen < GROUP_FILTER_SIZE(0)) goto e_inval; + if (optlen > sysctl_optmem_max) { + err = -ENOBUFS; + break; + } gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL); if (gsf == 0) { err = -ENOBUFS;
@@ -778,7 +784,13 @@ if (copy_from_user(gsf, optval, optlen)) { goto mc_msf_out; } - if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) { + /* numsrc >= (4G-140)/128 overflow in 32 bits */ + if (gsf->gf_numsrc >= 0x1ffffff || + gsf->gf_numsrc > sysctl_igmp_max_msf) { + err = -ENOBUFS; + goto mc_msf_out; + } + if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { err = EINVAL; goto mc_msf_out; }
diff -ruN linux-2.4.25F4/net/ipv6/ipv6_sockglue.c linux-2.4.25F5/net/ipv6/ipv6_sockglue.c
--- linux-2.4.25F4/net/ipv6/ipv6_sockglue.c 2004-02-23 16:35:09.000000000 -0800
+++ linux-2.4.25F5/net/ipv6/ipv6_sockglue.c 2004-03-05 01:57:30.000000000 -0800@@ -453,6 +453,7 @@ case MCAST_MSFILTER: { extern int sysctl_optmem_max; + extern int sysctl_mld_max_msf; struct group_filter *gsf; if (optlen < GROUP_FILTER_SIZE(0))
@@ -471,8 +472,14 @@ kfree(gsf); break; } - if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < GROUP_FILTER_SIZE(0) || - GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { + /* numsrc >= (4G-140)/128 overflow in 32 bits */ + if (gsf->gf_numsrc >= 0x1ffffffU || + gsf->gf_numsrc > sysctl_mld_max_msf) { + kfree(gsf); + retv = -ENOBUFS; + break; + } + if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { kfree(gsf); retv = -EINVAL; break;
diff -ruN linux-2.4.25F4/net/ipv6/mcast.c linux-2.4.25F5/net/ipv6/mcast.c
--- linux-2.4.25F4/net/ipv6/mcast.c 2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.25F5/net/ipv6/mcast.c 2004-03-04 22:37:31.000000000 -0800@@ -163,6 +163,10 @@ #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) +#define IPV6_MLD_MAX_MSF 10 + +int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF; + /* * socket join on multicast group */
@@ -401,6 +405,10 @@ } /* else, add a new source to the filter */ + if (psl && psl->sl_count >= sysctl_mld_max_msf) { + err = -ENOBUFS; + goto done; + } if (!psl || psl->sl_count == psl->sl_max) { struct ip6_sf_socklist *newpsl; int count = IP6_SFBLOCK;
diff -ruN linux-2.4.25F4/net/ipv6/sysctl_net_ipv6.c linux-2.4.25F5/net/ipv6/sysctl_net_ipv6.c
--- linux-2.4.25F4/net/ipv6/sysctl_net_ipv6.c 2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.25F5/net/ipv6/sysctl_net_ipv6.c 2004-03-05 00:01:05.000000000 -0800@@ -24,6 +24,8 @@ {NET_IPV6_ICMP, "icmp", NULL, 0, 0500, ipv6_icmp_table}, {NET_IPV6_BINDV6ONLY, "bindv6only", &sysctl_ipv6_bindv6only, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV6_MLD_MAX_MSF, "mld_max_msf", + &sysctl_mld_max_msf, sizeof(int), 0644, NULL, &proc_dointvec}, {0} };
(See attached file: 2.4.25mpmsflimit.patch) (See attached file: 2.6.4rc2mpmsflimit.patch)