Re: Realtime Preemption, 2.6.12, Beginners Guide?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> (gdb) ####################################
> (gdb) # c02de0f3, stack size:  572 bytes #
> (gdb) ####################################
> (gdb) 0xc02de0f3 is in ip_setsockopt (net/ipv4/ip_sockglue.c:385).

----
this patch reduces ip_setsockopt's stack footprint from 572 bytes to 164 
bytes. (Note: needs review and testing as i could not excercise this 
multicast codepath.)

Signed-off-by: Ingo Molnar <[email protected]>

Index: linux/net/ipv4/ip_sockglue.c
===================================================================
--- linux.orig/net/ipv4/ip_sockglue.c
+++ linux/net/ipv4/ip_sockglue.c
@@ -691,52 +691,65 @@ int ip_setsockopt(struct sock *sk, int l
 		case MCAST_JOIN_GROUP:
 		case MCAST_LEAVE_GROUP: 
 		{
-			struct group_req greq;
+			struct group_req *greq;
 			struct sockaddr_in *psin;
 			struct ip_mreqn mreq;
 
+			err = -ENOMEM;
+			greq = kmalloc(sizeof(*greq), GFP_KERNEL);
+			if (!greq)
+				break;
 			if (optlen < sizeof(struct group_req))
-				goto e_inval;
+				goto free_greq_e_inval;
 			err = -EFAULT;
-			if(copy_from_user(&greq, optval, sizeof(greq)))
-				break;
-			psin = (struct sockaddr_in *)&greq.gr_group;
+			if(copy_from_user(greq, optval, sizeof(*greq)))
+				goto free_greq_break;
+			psin = (struct sockaddr_in *)&greq->gr_group;
 			if (psin->sin_family != AF_INET)
-				goto e_inval;
+				goto free_greq_e_inval;
 			memset(&mreq, 0, sizeof(mreq));
 			mreq.imr_multiaddr = psin->sin_addr;
-			mreq.imr_ifindex = greq.gr_interface;
+			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);
+free_greq_break:
+			kfree(greq);
 			break;
+free_greq_e_inval:
+			kfree(greq);
+			goto e_inval;
 		}
 		case MCAST_JOIN_SOURCE_GROUP:
 		case MCAST_LEAVE_SOURCE_GROUP:
 		case MCAST_BLOCK_SOURCE:
 		case MCAST_UNBLOCK_SOURCE:
 		{
-			struct group_source_req greqs;
+			struct group_source_req *greqs;
 			struct ip_mreq_source mreqs;
 			struct sockaddr_in *psin;
 			int omode, add;
 
+			err = -ENOMEM;
+			greqs = kmalloc(sizeof(*greqs), GFP_KERNEL);
+			if (!greqs)
+				break;
 			if (optlen != sizeof(struct group_source_req))
-				goto e_inval;
-			if (copy_from_user(&greqs, optval, sizeof(greqs))) {
+				goto free_greqs_e_inval;
+			if (copy_from_user(&greqs, optval, sizeof(*greqs))) {
 				err = -EFAULT;
-				break;
+				goto free_greqs_break;
 			}
-			if (greqs.gsr_group.ss_family != AF_INET ||
-			    greqs.gsr_source.ss_family != AF_INET) {
+			if (greqs->gsr_group.ss_family != AF_INET ||
+			    greqs->gsr_source.ss_family != AF_INET) {
 				err = -EADDRNOTAVAIL;
-				break;
+				goto free_greqs_break;
 			}
-			psin = (struct sockaddr_in *)&greqs.gsr_group;
+			psin = (struct sockaddr_in *)&greqs->gsr_group;
 			mreqs.imr_multiaddr = psin->sin_addr.s_addr;
-			psin = (struct sockaddr_in *)&greqs.gsr_source;
+			psin = (struct sockaddr_in *)&greqs->gsr_source;
 			mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
 			mreqs.imr_interface = 0; /* use index for mc_source */
 
@@ -749,14 +762,14 @@ int ip_setsockopt(struct sock *sk, int l
 			} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
 				struct ip_mreqn mreq;
 
-				psin = (struct sockaddr_in *)&greqs.gsr_group;
+				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;
+				mreq.imr_ifindex = greqs->gsr_interface;
 				err = ip_mc_join_group(sk, &mreq);
 				if (err)
-					break;
-				greqs.gsr_interface = mreq.imr_ifindex;
+					goto free_greqs_break;
+				greqs->gsr_interface = mreq.imr_ifindex;
 				omode = MCAST_INCLUDE;
 				add = 1;
 			} else /* MCAST_LEAVE_SOURCE_GROUP */ {
@@ -764,8 +777,13 @@ int ip_setsockopt(struct sock *sk, int l
 				add = 0;
 			}
 			err = ip_mc_source(add, omode, sk, &mreqs,
-				greqs.gsr_interface);
-			break;
+				greqs->gsr_interface);
+free_greqs_break:
+			kfree(greqs);
+			break;
+free_greqs_e_inval:
+			kfree(greqs);
+			goto e_inval;
 		}
 		case MCAST_MSFILTER:
 		{
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux