patch-2.4.23 linux-2.4.23/net/core/pktgen.c

Next file: linux-2.4.23/net/core/sysctl_net_core.c
Previous file: linux-2.4.23/net/core/neighbour.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/net/core/pktgen.c linux-2.4.23/net/core/pktgen.c
@@ -46,6 +46,9 @@
  * Also moved to /proc/net/pktgen/ 
  * --ro 
  *
+ * Fix refcount off by one if first packet fails, potential null deref, 
+ * memleak 030710- KJP
+ *
  * See Documentation/networking/pktgen.txt for how to use this.
  */
 
@@ -84,9 +87,9 @@
 #define cycles()	((u32)get_cycles())
 
 
-#define VERSION "pktgen version 1.2"
+#define VERSION "pktgen version 1.3"
 static char version[] __initdata = 
-  "pktgen.c: v1.2: Packet Generator for packet performance testing.\n";
+  "pktgen.c: v1.3: Packet Generator for packet performance testing.\n";
 
 /* Used to help with determining the pkts on receive */
 
@@ -613,12 +616,11 @@
                                 kfree_skb(skb);
                                 skb = fill_packet(odev, info);
                                 if (skb == NULL) {
-                                        break;
+					goto out_reldev;
                                 }
                                 fp++;
                                 fp_tmp = 0; /* reset counter */
                         }
-                        atomic_inc(&skb->users);
                 }
 
                 nr_frags = skb_shinfo(skb)->nr_frags;
@@ -626,7 +628,11 @@
 		spin_lock_bh(&odev->xmit_lock);
 		if (!netif_queue_stopped(odev)) {
 
+			atomic_inc(&skb->users);
+
 			if (odev->hard_start_xmit(skb, odev)) {
+
+				atomic_dec(&skb->users);
 				if (net_ratelimit()) {
                                    printk(KERN_INFO "Hard xmit error\n");
                                 }
@@ -731,15 +737,15 @@
 			     (unsigned long long) info->errors
 			     );
 	}
-        
+
+	kfree_skb(skb);
+
 out_reldev:
         if (odev) {
                 dev_put(odev);
                 odev = NULL;
         }
 
-        /* TODO:  Is this worth printing out (other than for debug?) */
-        printk("fp = %llu\n", (unsigned long long) fp);
 	return;
 
 }
@@ -955,7 +961,8 @@
 	if (len < 0)
 		return len;
 	memset(name, 0, sizeof(name));
-	copy_from_user(name, &user_buffer[i], len);
+	if (copy_from_user(name, &user_buffer[i], len))
+		return -EFAULT;
 	i += len;
   
 	max = count -i;
@@ -1085,18 +1092,20 @@
 		if (len < 0)
 			return len;
 		memset(info->outdev, 0, sizeof(info->outdev));
-		copy_from_user(info->outdev, &user_buffer[i], len);
+		if (copy_from_user(info->outdev, &user_buffer[i], len))
+			return -EFAULT;
 		i += len;
 		sprintf(result, "OK: odev=%s", info->outdev);
 		return count;
 	}
 	if (!strcmp(name, "flag")) {
                 char f[32];
-                memset(f, 0, 32);
 		len = strn_len(&user_buffer[i], sizeof(f) - 1);
 		if (len < 0)
 			return len;
-		copy_from_user(f, &user_buffer[i], len);
+                memset(f, 0, 32);
+		if (copy_from_user(f, &user_buffer[i], len))
+			return -EFAULT;
 		i += len;
                 if (strcmp(f, "IPSRC_RND") == 0) {
                         info->flags |= F_IPSRC_RND;
@@ -1148,7 +1157,8 @@
 		if (len < 0)
 			return len;
 		memset(info->dst_min, 0, sizeof(info->dst_min));
-		copy_from_user(info->dst_min, &user_buffer[i], len);
+		if (copy_from_user(info->dst_min, &user_buffer[i], len))
+			return -EFAULT;
 		if(debug)
 			printk("pg: dst_min set to: %s\n", info->dst_min);
 		i += len;
@@ -1160,7 +1170,8 @@
 		if (len < 0)
 			return len;
 		memset(info->dst_max, 0, sizeof(info->dst_max));
-		copy_from_user(info->dst_max, &user_buffer[i], len);
+		if (copy_from_user(info->dst_max, &user_buffer[i], len))
+			return -EFAULT;
 		if(debug)
 			printk("pg: dst_max set to: %s\n", info->dst_max);
 		i += len;
@@ -1172,7 +1183,8 @@
 		if (len < 0)
 			return len;
 		memset(info->src_min, 0, sizeof(info->src_min));
-		copy_from_user(info->src_min, &user_buffer[i], len);
+		if (copy_from_user(info->src_min, &user_buffer[i], len))
+			return -EFAULT;
 		if(debug)
 			printk("pg: src_min set to: %s\n", info->src_min);
 		i += len;
@@ -1184,7 +1196,8 @@
 		if (len < 0)
 			return len;
 		memset(info->src_max, 0, sizeof(info->src_max));
-		copy_from_user(info->src_max, &user_buffer[i], len);
+		if (copy_from_user(info->src_max, &user_buffer[i], len))
+			return -EFAULT;
 		if(debug)
 			printk("pg: src_max set to: %s\n", info->src_max);
 		i += len;
@@ -1199,7 +1212,8 @@
 		if (len < 0)
 			return len;
 		memset(valstr, 0, sizeof(valstr));
-		copy_from_user(valstr, &user_buffer[i], len);
+		if (copy_from_user(valstr, &user_buffer[i], len))
+			return -EFAULT;
 		i += len;
 
 		for(*m = 0;*v && m < info->dst_mac + 6; v++) {
@@ -1231,7 +1245,8 @@
 		if (len < 0)
 			return len;
 		memset(valstr, 0, sizeof(valstr));
-		copy_from_user(valstr, &user_buffer[i], len);
+		if (copy_from_user(valstr, &user_buffer[i], len))
+			return -EFAULT;
 		i += len;
 
 		for(*m = 0;*v && m < info->src_mac + 6; v++) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)