public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: William Lee Irwin III <wli@holomorphy.com>
To: Matt Mackall <mpm@selenic.com>, Andrew Morton <akpm@osdl.org>,
	J?rn Engel <joern@wohnheim.fh-wedel.de>,
	arjanv@redhat.com, benh@kernel.crashing.org,
	kronos@kronoz.cjb.net, linux-kernel@vger.kernel.org
Subject: Re: [4KSTACK][2.6.6] Stack overflow in radeonfb
Date: Wed, 19 May 2004 05:01:38 -0700	[thread overview]
Message-ID: <20040519120138.GI1223@holomorphy.com> (raw)
In-Reply-To: <20040519102846.GG1223@holomorphy.com>

On Mon, May 17, 2004 at 06:35:15PM -0500, Matt Mackall wrote:
>> I have a cleaned up version of this script in -tiny which is a bit
>> nicer for adding new arches to and produces simpler output:
>>  1428 huft_build
>>  1292 inflate_dynamic
>>  1168 inflate_fixed
>>   528 ip_setsockopt
>>   496 tcp_check_req
>>   496 tcp_v4_conn_request
>>   484 tcp_timewait_state_process
>>   440 ip_getsockopt
>>   408 extract_entropy
>>   364 shrink_zone
>>   324 do_execve

On Wed, May 19, 2004 at 03:28:46AM -0700, William Lee Irwin III wrote:
> By eyeballing things, I see >= 384B on-stack in ep_send_events(). Hence:

I might as well hit something higher up in the list. Does this help
ip_setsockopt() any (untested)?


-- wli


Index: mm3-2.6.6/net/ipv4/ip_sockglue.c
===================================================================
--- mm3-2.6.6.orig/net/ipv4/ip_sockglue.c	2004-05-09 19:32:27.000000000 -0700
+++ mm3-2.6.6/net/ipv4/ip_sockglue.c	2004-05-19 04:48:13.000000000 -0700
@@ -384,6 +384,312 @@
  *	an IP socket.
  */
 
+static int ip_options_setsockopt(struct inet_opt *inet, struct sock *sk, char *optval, int optlen)
+{
+	int err;
+	struct ip_options *opt = NULL;
+
+	if (optlen > 40 || optlen < 0)
+		return -EINVAL;
+	err = ip_options_get(&opt, optval, optlen, 1);
+	if (err)
+		return err;
+	if (sk->sk_type == SOCK_STREAM) {
+		struct tcp_opt *tp = tcp_sk(sk);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		if (sk->sk_family == PF_INET ||
+		    (!((1 << sk->sk_state) &
+		       (TCPF_LISTEN | TCPF_CLOSE)) &&
+		     inet->daddr != LOOPBACK4_IPV6)) {
+#endif
+			if (inet->opt)
+				tp->ext_header_len -= inet->opt->optlen;
+			if (opt)
+				tp->ext_header_len += opt->optlen;
+			tcp_sync_mss(sk, tp->pmtu_cookie);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		}
+#endif
+	}
+	opt = xchg(&inet->opt, opt);
+	if (opt)
+		kfree(opt);
+	return err;
+}
+
+static int ip_membership_setsockopt(struct sock *sk, char *optval, int optlen, int optname)
+{
+	int err;
+	struct ip_mreqn mreq;
+
+	if (optlen < sizeof(struct ip_mreq))
+		return -EINVAL;
+	if (optlen >= sizeof(struct ip_mreqn)) {
+		if(copy_from_user(&mreq,optval,sizeof(mreq)))
+			return -EFAULT;
+	} else {
+		memset(&mreq, 0, sizeof(mreq));
+		if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
+			return -EFAULT; 
+	}
+
+	if (optname == IP_ADD_MEMBERSHIP)
+		err = ip_mc_join_group(sk, &mreq);
+	else
+		err = ip_mc_leave_group(sk, &mreq);
+	return err;
+}
+
+static int ip_multicast_if_setsockopt(struct inet_opt *inet, struct sock *sk, char *optval, int optlen)
+{
+	struct ip_mreqn mreq;
+	struct net_device *dev = NULL;
+
+	if (sk->sk_type == SOCK_STREAM)
+		return -EINVAL;
+	/*
+	 *	Check the arguments are allowable
+	 */
+
+	if (optlen >= sizeof(struct ip_mreqn)) {
+		if (copy_from_user(&mreq,optval,sizeof(mreq)))
+			return -EFAULT;
+	} else {
+		memset(&mreq, 0, sizeof(mreq));
+		if (optlen >= sizeof(struct in_addr) &&
+		    copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))
+			return -EFAULT;
+	}
+
+	if (!mreq.imr_ifindex) {
+		if (mreq.imr_address.s_addr == INADDR_ANY) {
+			inet->mc_index = 0;
+			inet->mc_addr  = 0;
+			return 0;
+		}
+		dev = ip_dev_find(mreq.imr_address.s_addr);
+		if (dev) {
+			mreq.imr_ifindex = dev->ifindex;
+			dev_put(dev);
+		}
+	} else
+		dev = __dev_get_by_index(mreq.imr_ifindex);
+
+
+	if (!dev)
+		return -EADDRNOTAVAIL;
+
+	if (sk->sk_bound_dev_if && mreq.imr_ifindex != sk->sk_bound_dev_if)
+		return -EINVAL;
+
+	inet->mc_index = mreq.imr_ifindex;
+	inet->mc_addr  = mreq.imr_address.s_addr;
+	return 0;
+}
+
+static int ip_msfilter_setsockopt(struct sock *sk, char *optval, int optlen)
+{
+	extern int sysctl_optmem_max;
+	extern int sysctl_igmp_max_msf;
+	int err;
+	struct ip_msfilter *msf;
+
+	if (optlen < IP_MSFILTER_SIZE(0))
+		return -EINVAL;
+	if (optlen > sysctl_optmem_max)
+		return -ENOBUFS;
+	msf = kmalloc(optlen, GFP_KERNEL);
+	if (!msf)
+		return -ENOBUFS;
+	if (copy_from_user(msf, optval, optlen)) {
+		kfree(msf);
+		return -EFAULT;
+	}
+	/* numsrc >= (1G-4) overflow in 32 bits */
+	if (msf->imsf_numsrc >= 0x3ffffffcU ||
+	    msf->imsf_numsrc > sysctl_igmp_max_msf) {
+		kfree(msf);
+		return -ENOBUFS;
+	}
+	if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+		kfree(msf);
+		return -EINVAL;
+	}
+	err = ip_mc_msfilter(sk, msf, 0);
+	kfree(msf);
+	return err;
+}
+
+static int ip_source_membership_setsockopt(struct sock *sk, char *optval, int optlen, int optname)
+{
+	struct ip_mreq_source mreqs;
+	int omode, add;
+
+	if (optlen != sizeof(struct ip_mreq_source))
+		return -EINVAL;
+	if (copy_from_user(&mreqs, optval, sizeof(mreqs)))
+		return -EFAULT;
+	if (optname == IP_BLOCK_SOURCE) {
+		omode = MCAST_EXCLUDE;
+		add = 1;
+	} else if (optname == IP_UNBLOCK_SOURCE) {
+		omode = MCAST_EXCLUDE;
+		add = 0;
+	} else if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
+		struct ip_mreqn mreq;
+		int err;
+
+		mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;
+		mreq.imr_address.s_addr = mreqs.imr_interface;
+		mreq.imr_ifindex = 0;
+		err = ip_mc_join_group(sk, &mreq);
+		if (err)
+			return err;
+		omode = MCAST_INCLUDE;
+		add = 1;
+	} else /*IP_DROP_SOURCE_MEMBERSHIP */ {
+		omode = MCAST_INCLUDE;
+		add = 0;
+	}
+	return ip_mc_source(add, omode, sk, &mreqs, 0);
+}
+
+static int ip_mcast_group_setsockopt(struct sock *sk, char *optval, int optlen, int optname)
+{
+	int err;
+	struct group_req greq;
+	struct sockaddr_in *psin;
+	struct ip_mreqn mreq;
+
+	if (optlen < sizeof(struct group_req))
+		return -EINVAL;
+	if(copy_from_user(&greq, optval, sizeof(greq)))
+		return -EFAULT;
+	psin = (struct sockaddr_in *)&greq.gr_group;
+	if (psin->sin_family != AF_INET)
+		return -EINVAL;
+	memset(&mreq, 0, sizeof(mreq));
+	mreq.imr_multiaddr = psin->sin_addr;
+	mreq.imr_ifindex = greq.gr_interface;
+
+	if (optname == MCAST_JOIN_GROUP)
+		err = ip_mc_join_group(sk, &mreq);
+	else
+		err = ip_mc_leave_group(sk, &mreq);
+	return err;
+}
+
+static int ip_mcast_source_setsockopt(struct sock *sk, char *optval, int optlen, int optname)
+{
+	struct group_source_req greqs;
+	struct ip_mreq_source mreqs;
+	struct sockaddr_in *psin;
+	int omode, add;
+
+	if (optlen != sizeof(struct group_source_req))
+		return -EINVAL;
+	if (copy_from_user(&greqs, optval, sizeof(greqs)))
+		return -EFAULT;
+	if (greqs.gsr_group.ss_family != AF_INET ||
+	    greqs.gsr_source.ss_family != AF_INET)
+		return -EADDRNOTAVAIL;
+	psin = (struct sockaddr_in *)&greqs.gsr_group;
+	mreqs.imr_multiaddr = psin->sin_addr.s_addr;
+	psin = (struct sockaddr_in *)&greqs.gsr_source;
+	mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
+	mreqs.imr_interface = 0; /* use index for mc_source */
+
+	if (optname == MCAST_BLOCK_SOURCE) {
+		omode = MCAST_EXCLUDE;
+		add = 1;
+	} else if (optname == MCAST_UNBLOCK_SOURCE) {
+		omode = MCAST_EXCLUDE;
+		add = 0;
+	} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
+		int err;
+		struct ip_mreqn mreq;
+
+		psin = (struct sockaddr_in *)&greqs.gsr_group;
+		mreq.imr_multiaddr = psin->sin_addr;
+		mreq.imr_address.s_addr = 0;
+		mreq.imr_ifindex = greqs.gsr_interface;
+		err = ip_mc_join_group(sk, &mreq);
+		if (err)
+			return err;
+		omode = MCAST_INCLUDE;
+		add = 1;
+	} else /* MCAST_LEAVE_SOURCE_GROUP */ {
+		omode = MCAST_INCLUDE;
+		add = 0;
+	}
+	return ip_mc_source(add, omode, sk, &mreqs, greqs.gsr_interface);
+}
+
+static int ip_mcast_msfilter_setsockopt(struct sock *sk, char *optval, int optlen)
+{
+	extern int sysctl_optmem_max;
+	extern int sysctl_igmp_max_msf;
+	struct sockaddr_in *psin;
+	struct ip_msfilter *msf = NULL;
+	struct group_filter *gsf = NULL;
+	int msize, i, ifindex, err;
+
+	if (optlen < GROUP_FILTER_SIZE(0))
+		return -EINVAL;
+	if (optlen > sysctl_optmem_max)
+		return -ENOBUFS;
+	gsf = kmalloc(optlen, GFP_KERNEL);
+	if (!gsf)
+		return -ENOBUFS;
+	if (copy_from_user(gsf, optval, optlen)) {
+		err = -EFAULT;
+		goto mc_msf_out;
+	}
+	/* 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;
+	}
+	msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);
+	msf = kmalloc(msize, GFP_KERNEL);
+	if (!msf) {
+		err = -ENOBUFS;
+		goto mc_msf_out;
+	}
+	ifindex = gsf->gf_interface;
+	psin = (struct sockaddr_in *)&gsf->gf_group;
+	if (psin->sin_family != AF_INET) {
+		err = -EADDRNOTAVAIL;
+		goto mc_msf_out;
+	}
+	msf->imsf_multiaddr = psin->sin_addr.s_addr;
+	msf->imsf_interface = 0;
+	msf->imsf_fmode = gsf->gf_fmode;
+	msf->imsf_numsrc = gsf->gf_numsrc;
+	err = -EADDRNOTAVAIL;
+	for (i=0; i<gsf->gf_numsrc; ++i) {
+		psin = (struct sockaddr_in *)&gsf->gf_slist[i];
+
+		if (psin->sin_family != AF_INET)
+			goto mc_msf_out;
+		msf->imsf_slist[i] = psin->sin_addr.s_addr;
+	}
+	kfree(gsf);
+	gsf = NULL;
+	err = ip_mc_msfilter(sk, msf, ifindex);
+mc_msf_out:
+	if (msf)
+		kfree(msf);
+	if (gsf)
+		kfree(gsf);
+	return err;
+}
+
 int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
 {
 	struct inet_opt *inet = inet_sk(sk);
@@ -424,35 +730,8 @@
 
 	switch (optname) {
 		case IP_OPTIONS:
-		{
-			struct ip_options * opt = NULL;
-			if (optlen > 40 || optlen < 0)
-				goto e_inval;
-			err = ip_options_get(&opt, optval, optlen, 1);
-			if (err)
-				break;
-			if (sk->sk_type == SOCK_STREAM) {
-				struct tcp_opt *tp = tcp_sk(sk);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-				if (sk->sk_family == PF_INET ||
-				    (!((1 << sk->sk_state) &
-				       (TCPF_LISTEN | TCPF_CLOSE)) &&
-				     inet->daddr != LOOPBACK4_IPV6)) {
-#endif
-					if (inet->opt)
-						tp->ext_header_len -= inet->opt->optlen;
-					if (opt)
-						tp->ext_header_len += opt->optlen;
-					tcp_sync_mss(sk, tp->pmtu_cookie);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-				}
-#endif
-			}
-			opt = xchg(&inet->opt, opt);
-			if (opt)
-				kfree(opt);
+			err = ip_options_setsockopt(inet, sk, optval, optlen);
 			break;
-		}
 		case IP_PKTINFO:
 			if (val)
 				inet->cmsg_flags |= IP_CMSG_PKTINFO;
@@ -540,304 +819,34 @@
 			inet->mc_loop = !!val;
 	                break;
 		case IP_MULTICAST_IF: 
-		{
-			struct ip_mreqn mreq;
-			struct net_device *dev = NULL;
-
-			if (sk->sk_type == SOCK_STREAM)
-				goto e_inval;
-			/*
-			 *	Check the arguments are allowable
-			 */
-
-			err = -EFAULT;
-			if (optlen >= sizeof(struct ip_mreqn)) {
-				if (copy_from_user(&mreq,optval,sizeof(mreq)))
-					break;
-			} else {
-				memset(&mreq, 0, sizeof(mreq));
-				if (optlen >= sizeof(struct in_addr) &&
-				    copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))
-					break;
-			}
-
-			if (!mreq.imr_ifindex) {
-				if (mreq.imr_address.s_addr == INADDR_ANY) {
-					inet->mc_index = 0;
-					inet->mc_addr  = 0;
-					err = 0;
-					break;
-				}
-				dev = ip_dev_find(mreq.imr_address.s_addr);
-				if (dev) {
-					mreq.imr_ifindex = dev->ifindex;
-					dev_put(dev);
-				}
-			} else
-				dev = __dev_get_by_index(mreq.imr_ifindex);
-
-
-			err = -EADDRNOTAVAIL;
-			if (!dev)
-				break;
-
-			err = -EINVAL;
-			if (sk->sk_bound_dev_if &&
-			    mreq.imr_ifindex != sk->sk_bound_dev_if)
-				break;
-
-			inet->mc_index = mreq.imr_ifindex;
-			inet->mc_addr  = mreq.imr_address.s_addr;
-			err = 0;
+			err = ip_multicast_if_setsockopt(inet, sk, optval, optlen);
 			break;
-		}
-
 		case IP_ADD_MEMBERSHIP:
 		case IP_DROP_MEMBERSHIP: 
-		{
-			struct ip_mreqn mreq;
-
-			if (optlen < sizeof(struct ip_mreq))
-				goto e_inval;
-			err = -EFAULT;
-			if (optlen >= sizeof(struct ip_mreqn)) {
-				if(copy_from_user(&mreq,optval,sizeof(mreq)))
-					break;
-			} else {
-				memset(&mreq, 0, sizeof(mreq));
-				if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
-					break; 
-			}
-
-			if (optname == IP_ADD_MEMBERSHIP)
-				err = ip_mc_join_group(sk, &mreq);
-			else
-				err = ip_mc_leave_group(sk, &mreq);
+			err = ip_membership_setsockopt(sk, optval, optlen, optname);
 			break;
-		}
 		case IP_MSFILTER:
-		{
-			extern int sysctl_optmem_max;
-			extern int sysctl_igmp_max_msf;
-			struct ip_msfilter *msf;
-
-			if (optlen < IP_MSFILTER_SIZE(0))
-				goto e_inval;
-			if (optlen > sysctl_optmem_max) {
-				err = -ENOBUFS;
-				break;
-			}
-			msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);
-			if (msf == 0) {
-				err = -ENOBUFS;
-				break;
-			}
-			err = -EFAULT;
-			if (copy_from_user(msf, optval, optlen)) {
-				kfree(msf);
-				break;
-			}
-			/* numsrc >= (1G-4) overflow in 32 bits */
-			if (msf->imsf_numsrc >= 0x3ffffffcU ||
-			    msf->imsf_numsrc > sysctl_igmp_max_msf) {
-				kfree(msf);
-				err = -ENOBUFS;
-				break;
-			}
-			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
-				kfree(msf);
-				err = -EINVAL;
-				break;
-			}
-			err = ip_mc_msfilter(sk, msf, 0);
-			kfree(msf);
+			err = ip_msfilter_setsockopt(sk, optval, optlen);
 			break;
-		}
 		case IP_BLOCK_SOURCE:
 		case IP_UNBLOCK_SOURCE:
 		case IP_ADD_SOURCE_MEMBERSHIP:
 		case IP_DROP_SOURCE_MEMBERSHIP:
-		{
-			struct ip_mreq_source mreqs;
-			int omode, add;
-
-			if (optlen != sizeof(struct ip_mreq_source))
-				goto e_inval;
-			if (copy_from_user(&mreqs, optval, sizeof(mreqs))) {
-				err = -EFAULT;
-				break;
-			}
-			if (optname == IP_BLOCK_SOURCE) {
-				omode = MCAST_EXCLUDE;
-				add = 1;
-			} else if (optname == IP_UNBLOCK_SOURCE) {
-				omode = MCAST_EXCLUDE;
-				add = 0;
-			} else if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
-				struct ip_mreqn mreq;
-
-				mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;
-				mreq.imr_address.s_addr = mreqs.imr_interface;
-				mreq.imr_ifindex = 0;
-				err = ip_mc_join_group(sk, &mreq);
-				if (err)
-					break;
-				omode = MCAST_INCLUDE;
-				add = 1;
-			} else /*IP_DROP_SOURCE_MEMBERSHIP */ {
-				omode = MCAST_INCLUDE;
-				add = 0;
-			}
-			err = ip_mc_source(add, omode, sk, &mreqs, 0);
+			err = ip_source_membership_setsockopt(sk, optval, optlen, optname);
 			break;
-		}
 		case MCAST_JOIN_GROUP:
 		case MCAST_LEAVE_GROUP: 
-		{
-			struct group_req greq;
-			struct sockaddr_in *psin;
-			struct ip_mreqn mreq;
-
-			if (optlen < sizeof(struct group_req))
-				goto e_inval;
-			err = -EFAULT;
-			if(copy_from_user(&greq, optval, sizeof(greq)))
-				break;
-			psin = (struct sockaddr_in *)&greq.gr_group;
-			if (psin->sin_family != AF_INET)
-				goto e_inval;
-			memset(&mreq, 0, sizeof(mreq));
-			mreq.imr_multiaddr = psin->sin_addr;
-			mreq.imr_ifindex = greq.gr_interface;
-
-			if (optname == MCAST_JOIN_GROUP)
-				err = ip_mc_join_group(sk, &mreq);
-			else
-				err = ip_mc_leave_group(sk, &mreq);
+			err = ip_mcast_group_setsockopt(sk, optval, optlen, optname);
 			break;
-		}
 		case MCAST_JOIN_SOURCE_GROUP:
 		case MCAST_LEAVE_SOURCE_GROUP:
 		case MCAST_BLOCK_SOURCE:
 		case MCAST_UNBLOCK_SOURCE:
-		{
-			struct group_source_req greqs;
-			struct ip_mreq_source mreqs;
-			struct sockaddr_in *psin;
-			int omode, add;
-
-			if (optlen != sizeof(struct group_source_req))
-				goto e_inval;
-			if (copy_from_user(&greqs, optval, sizeof(greqs))) {
-				err = -EFAULT;
-				break;
-			}
-			if (greqs.gsr_group.ss_family != AF_INET ||
-			    greqs.gsr_source.ss_family != AF_INET) {
-				err = -EADDRNOTAVAIL;
-				break;
-			}
-			psin = (struct sockaddr_in *)&greqs.gsr_group;
-			mreqs.imr_multiaddr = psin->sin_addr.s_addr;
-			psin = (struct sockaddr_in *)&greqs.gsr_source;
-			mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
-			mreqs.imr_interface = 0; /* use index for mc_source */
-
-			if (optname == MCAST_BLOCK_SOURCE) {
-				omode = MCAST_EXCLUDE;
-				add = 1;
-			} else if (optname == MCAST_UNBLOCK_SOURCE) {
-				omode = MCAST_EXCLUDE;
-				add = 0;
-			} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
-				struct ip_mreqn mreq;
-
-				psin = (struct sockaddr_in *)&greqs.gsr_group;
-				mreq.imr_multiaddr = psin->sin_addr;
-				mreq.imr_address.s_addr = 0;
-				mreq.imr_ifindex = greqs.gsr_interface;
-				err = ip_mc_join_group(sk, &mreq);
-				if (err)
-					break;
-				omode = MCAST_INCLUDE;
-				add = 1;
-			} else /* MCAST_LEAVE_SOURCE_GROUP */ {
-				omode = MCAST_INCLUDE;
-				add = 0;
-			}
-			err = ip_mc_source(add, omode, sk, &mreqs,
-				greqs.gsr_interface);
+			err = ip_mcast_source_setsockopt(sk, optval, optlen, optname);
 			break;
-		}
 		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;
-			int msize, i, ifindex;
-
-			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;
-				break;
-			}
-			err = -EFAULT;
-			if (copy_from_user(gsf, optval, optlen)) {
-				goto mc_msf_out;
-			}
-			/* 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;
-			}
-			msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);
-			msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);
-			if (msf == 0) {
-				err = -ENOBUFS;
-				goto mc_msf_out;
-			}
-			ifindex = gsf->gf_interface;
-			psin = (struct sockaddr_in *)&gsf->gf_group;
-			if (psin->sin_family != AF_INET) {
-				err = -EADDRNOTAVAIL;
-				goto mc_msf_out;
-			}
-			msf->imsf_multiaddr = psin->sin_addr.s_addr;
-			msf->imsf_interface = 0;
-			msf->imsf_fmode = gsf->gf_fmode;
-			msf->imsf_numsrc = gsf->gf_numsrc;
-			err = -EADDRNOTAVAIL;
-			for (i=0; i<gsf->gf_numsrc; ++i) {
-				psin = (struct sockaddr_in *)&gsf->gf_slist[i];
-
-				if (psin->sin_family != AF_INET)
-					goto mc_msf_out;
-				msf->imsf_slist[i] = psin->sin_addr.s_addr;
-			}
-			kfree(gsf);
-			gsf = 0;
-
-			err = ip_mc_msfilter(sk, msf, ifindex);
-mc_msf_out:
-			if (msf)
-				kfree(msf);
-			if (gsf)
-				kfree(gsf);
+			err = ip_mcast_msfilter_setsockopt(sk, optval, optlen);
 			break;
-		}
 		case IP_ROUTER_ALERT:	
 			err = ip_ra_control(sk, val ? 1 : 0, NULL);
 			break;

  reply	other threads:[~2004-05-19 12:02 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-13 13:48 [4KSTACK][2.6.6] Stack overflow in radeonfb Kronos
2004-05-13 14:03 ` Kronos
2004-05-13 14:56 ` Kronos
2004-05-13 15:15   ` Jörn Engel
2004-05-13 15:36     ` Valdis.Kletnieks
2004-05-13 16:02       ` Jörn Engel
2004-05-13 22:56     ` Benjamin Herrenschmidt
2004-05-14 10:00       ` Jörn Engel
2004-05-13 22:55   ` Benjamin Herrenschmidt
2004-05-14  1:21     ` Andrew Morton
2004-05-14  3:26       ` Randy.Dunlap
2004-05-14  9:49       ` Arjan van de Ven
2004-05-14 11:47         ` Jörn Engel
2004-05-14 22:15           ` Andrew Morton
2004-05-14 22:56             ` Chris Wright
2004-05-14 23:18               ` Andrew Morton
2004-05-14 23:19                 ` Chris Wright
2004-05-14 23:48                   ` Andrew Morton
2004-05-17 10:53                     ` Jörn Engel
2004-05-15  7:19             ` Arjan van de Ven
2004-05-17 23:35             ` Matt Mackall
2004-05-17 23:59               ` Andrew Morton
2004-05-26 10:06                 ` Jörn Engel
2004-05-26 10:08                   ` Jörn Engel
2004-05-19 10:28               ` William Lee Irwin III
2004-05-19 12:01                 ` William Lee Irwin III [this message]
2004-05-26 10:17                   ` Jörn Engel
     [not found]               ` <20040518051745.GK2151@krispykreme>
     [not found]                 ` <20040518171136.GC28735@waste.org>
     [not found]                   ` <20040518171959.GQ2151@krispykreme>
     [not found]                     ` <20040518174734.GE28735@waste.org>
2004-05-26 10:14                       ` Jörn Engel
2004-05-14 16:41     ` Kronos
2004-05-14 21:48       ` Benjamin Herrenschmidt
2004-05-14 22:34         ` Andrew Morton
2004-05-14 22:36           ` Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040519120138.GI1223@holomorphy.com \
    --to=wli@holomorphy.com \
    --cc=akpm@osdl.org \
    --cc=arjanv@redhat.com \
    --cc=benh@kernel.crashing.org \
    --cc=joern@wohnheim.fh-wedel.de \
    --cc=kronos@kronoz.cjb.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpm@selenic.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox