Commit b46f30e2 authored by David Stevens's avatar David Stevens Committed by Patrick McHardy

[IPV4/IPV6]: Add sysctl limits for mcast src filters.

parent f93fe4da
...@@ -405,7 +405,8 @@ enum { ...@@ -405,7 +405,8 @@ enum {
NET_IPV6_IP6FRAG_HIGH_THRESH=21, NET_IPV6_IP6FRAG_HIGH_THRESH=21,
NET_IPV6_IP6FRAG_LOW_THRESH=22, NET_IPV6_IP6FRAG_LOW_THRESH=22,
NET_IPV6_IP6FRAG_TIME=23, NET_IPV6_IP6FRAG_TIME=23,
NET_IPV6_IP6FRAG_SECRET_INTERVAL=24 NET_IPV6_IP6FRAG_SECRET_INTERVAL=24,
NET_IPV6_MLD_MAX_MSF=25,
}; };
enum { enum {
......
...@@ -108,6 +108,7 @@ struct frag_hdr { ...@@ -108,6 +108,7 @@ struct frag_hdr {
/* sysctls */ /* sysctls */
extern int sysctl_ipv6_bindv6only; extern int sysctl_ipv6_bindv6only;
extern int sysctl_mld_max_msf;
/* MIBs */ /* MIBs */
DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics); DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
......
...@@ -771,6 +771,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -771,6 +771,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
} }
case MCAST_MSFILTER: case MCAST_MSFILTER:
{ {
extern int sysctl_optmem_max;
extern int sysctl_igmp_max_msf;
struct sockaddr_in *psin; struct sockaddr_in *psin;
struct ip_msfilter *msf = 0; struct ip_msfilter *msf = 0;
struct group_filter *gsf = 0; struct group_filter *gsf = 0;
...@@ -778,6 +780,10 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -778,6 +780,10 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
if (optlen < GROUP_FILTER_SIZE(0)) if (optlen < GROUP_FILTER_SIZE(0))
goto e_inval; goto e_inval;
if (optlen > sysctl_optmem_max) {
err = -ENOBUFS;
break;
}
gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL); gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
if (gsf == 0) { if (gsf == 0) {
err = -ENOBUFS; err = -ENOBUFS;
...@@ -787,7 +793,13 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -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)) { if (copy_from_user(gsf, optval, optlen)) {
goto mc_msf_out; 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; err = EINVAL;
goto mc_msf_out; goto mc_msf_out;
} }
......
...@@ -437,6 +437,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, ...@@ -437,6 +437,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
case MCAST_MSFILTER: case MCAST_MSFILTER:
{ {
extern int sysctl_optmem_max; extern int sysctl_optmem_max;
extern int sysctl_mld_max_msf;
struct group_filter *gsf; struct group_filter *gsf;
if (optlen < GROUP_FILTER_SIZE(0)) if (optlen < GROUP_FILTER_SIZE(0))
...@@ -455,8 +456,14 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, ...@@ -455,8 +456,14 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
kfree(gsf); kfree(gsf);
break; break;
} }
if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < GROUP_FILTER_SIZE(0) || /* numsrc >= (4G-140)/128 overflow in 32 bits */
GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { 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); kfree(gsf);
retv = -EINVAL; retv = -EINVAL;
break; break;
......
...@@ -166,6 +166,10 @@ int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, ...@@ -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_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
#define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 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 * socket join on multicast group
*/ */
...@@ -404,6 +408,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk, ...@@ -404,6 +408,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
} }
/* else, add a new source to the filter */ /* 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) { if (!psl || psl->sl_count == psl->sl_max) {
struct ip6_sf_socklist *newpsl; struct ip6_sf_socklist *newpsl;
int count = IP6_SFBLOCK; int count = IP6_SFBLOCK;
......
...@@ -76,6 +76,14 @@ ctl_table ipv6_table[] = { ...@@ -76,6 +76,14 @@ ctl_table ipv6_table[] = {
.proc_handler = &proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_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 } { .ctl_name = 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment