]> git.hungrycats.org Git - linux/commitdiff
[IPV4/IPV6]: Add sysctl limits for mcast src filters.
authorDavid Stevens <dlstevens@us.ibm.com>
Mon, 8 Mar 2004 04:15:15 +0000 (20:15 -0800)
committerPatrick McHardy <kaber@trash.net>
Mon, 8 Mar 2004 04:15:15 +0000 (20:15 -0800)
include/linux/sysctl.h
include/net/ipv6.h
net/ipv4/ip_sockglue.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/sysctl_net_ipv6.c

index fca4306e8f583877c31088d07c2aabd9478c0184..dbd57168ac61c7cb2b0cc24b0fcebf87128e74fc 100644 (file)
@@ -405,7 +405,8 @@ enum {
        NET_IPV6_IP6FRAG_HIGH_THRESH=21,
        NET_IPV6_IP6FRAG_LOW_THRESH=22,
        NET_IPV6_IP6FRAG_TIME=23,
-       NET_IPV6_IP6FRAG_SECRET_INTERVAL=24
+       NET_IPV6_IP6FRAG_SECRET_INTERVAL=24,
+       NET_IPV6_MLD_MAX_MSF=25,
 };
 
 enum {
index 6ebdb4b25922231202893d9f6eb020db37acd678..b647b048bbbf3d76fbd74b506e25184349c326e4 100644 (file)
@@ -108,6 +108,7 @@ struct frag_hdr {
 
 /* sysctls */
 extern int sysctl_ipv6_bindv6only;
+extern int sysctl_mld_max_msf;
 
 /* MIBs */
 DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
index debe5332925a554f72ac28bd79c1b92b162ecb41..c5ee82829e932fd726128a25cc53d7bfb80451f1 100644 (file)
@@ -771,6 +771,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                }
                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;
@@ -778,6 +780,10 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
 
                        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;
@@ -787,7 +793,13 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        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;
                        }
index 1b28ffcefc4e85b73e7b76bdcd297dffd0f7e211..4f77f0f5b574bb698da46abd1d305a17c9ff57a4 100644 (file)
@@ -437,6 +437,7 @@ done:
        case MCAST_MSFILTER:
        {
                extern int sysctl_optmem_max;
+               extern int sysctl_mld_max_msf;
                struct group_filter *gsf;
 
                if (optlen < GROUP_FILTER_SIZE(0))
@@ -455,8 +456,14 @@ done:
                        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;
index daad690f9927c46f2315f4c2b7c5deb898adf356..33a6f7a01665ec76b7ec33756ff87893d6141d5b 100644 (file)
@@ -166,6 +166,10 @@ int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
 #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
  */
@@ -404,6 +408,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
        }
        /* 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;
index db0690722e9d74bf93603fdd05a3edf7528bd5dd..9639eaefeb5790837e0f5ae608e2f26192ebf33c 100644 (file)
@@ -76,6 +76,14 @@ ctl_table ipv6_table[] = {
                .proc_handler   = &proc_dointvec_jiffies,
                .strategy       = &sysctl_jiffies
        },
+       {
+               .ctl_name       = NET_IPV6_MLD_MAX_MSF,
+               .procname       = "mld_max_msf",
+               .data           = &sysctl_mld_max_msf,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
        { .ctl_name = 0 }
 };