Commit dc2a3808 authored by David Stevens's avatar David Stevens Committed by David S. Miller

[IPV4]: Add sysctl for per-socket limit on number of mcast src filters.

parent 416ecb64
...@@ -321,6 +321,7 @@ enum ...@@ -321,6 +321,7 @@ enum
NET_TCP_LOW_LATENCY=93, NET_TCP_LOW_LATENCY=93,
NET_IPV4_IPFRAG_SECRET_INTERVAL=94, NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
NET_TCP_WESTWOOD=95, NET_TCP_WESTWOOD=95,
NET_IPV4_IGMP_MAX_MSF=96,
}; };
enum { enum {
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
#endif #endif
#define IP_MAX_MEMBERSHIPS 20 #define IP_MAX_MEMBERSHIPS 20
#define IP_MAX_MSF 10
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
/* Parameter names and values are taken from igmp-v2-06 draft */ /* Parameter names and values are taken from igmp-v2-06 draft */
...@@ -1325,6 +1326,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) ...@@ -1325,6 +1326,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
* Join a socket to a group * Join a socket to a group
*/ */
int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS; int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
int sysctl_igmp_max_msf = IP_MAX_MSF;
static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
...@@ -1790,6 +1792,10 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct ...@@ -1790,6 +1792,10 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
} }
/* else, add a new source to the filter */ /* else, add a new source to the filter */
if (psl && psl->sl_count >= sysctl_igmp_max_msf) {
err = -ENOBUFS;
goto done;
}
if (!psl || psl->sl_count == psl->sl_max) { if (!psl || psl->sl_count == psl->sl_max) {
struct ip_sf_socklist *newpsl; struct ip_sf_socklist *newpsl;
int count = IP_SFBLOCK; int count = IP_SFBLOCK;
......
...@@ -618,6 +618,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -618,6 +618,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
case IP_MSFILTER: case IP_MSFILTER:
{ {
extern int sysctl_optmem_max; extern int sysctl_optmem_max;
extern int sysctl_igmp_max_msf;
struct ip_msfilter *msf; struct ip_msfilter *msf;
if (optlen < IP_MSFILTER_SIZE(0)) if (optlen < IP_MSFILTER_SIZE(0))
...@@ -636,9 +637,14 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -636,9 +637,14 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
kfree(msf); kfree(msf);
break; break;
} }
if (IP_MSFILTER_SIZE(msf->imsf_numsrc) < /* numsrc >= (1G-4) overflow in 32 bits */
IP_MSFILTER_SIZE(0) || if (msf->imsf_numsrc >= 0x3ffffffcU ||
IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { msf->imsf_numsrc > sysctl_igmp_max_msf) {
kfree(msf);
err = -ENOBUFS;
break;
}
if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
kfree(msf); kfree(msf);
err = -EINVAL; err = -EINVAL;
break; break;
......
...@@ -39,6 +39,7 @@ extern int sysctl_icmp_ratemask; ...@@ -39,6 +39,7 @@ extern int sysctl_icmp_ratemask;
/* From igmp.c */ /* From igmp.c */
extern int sysctl_igmp_max_memberships; extern int sysctl_igmp_max_memberships;
extern int sysctl_igmp_max_msf;
/* From inetpeer.c */ /* From inetpeer.c */
extern int inet_peer_threshold; extern int inet_peer_threshold;
...@@ -411,6 +412,14 @@ ctl_table ipv4_table[] = { ...@@ -411,6 +412,14 @@ ctl_table ipv4_table[] = {
}, },
#endif #endif
{
.ctl_name = NET_IPV4_IGMP_MAX_MSF,
.procname = "igmp_max_msf",
.data = &sysctl_igmp_max_msf,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{ {
.ctl_name = NET_IPV4_INET_PEER_THRESHOLD, .ctl_name = NET_IPV4_INET_PEER_THRESHOLD,
.procname = "inet_peer_threshold", .procname = "inet_peer_threshold",
......
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