All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephane Ouellette <ouellettes@videotron.ca>
To: netfilter-devel@lists.netfilter.org
Subject: [PATCH] Recent Match - Possible memory leaks + Possible buffer overflow with strncpy()
Date: Tue, 29 Oct 2002 13:11:54 -0500	[thread overview]
Message-ID: <3DBECF6A.3040903@videotron.ca> (raw)

[-- Attachment #1: Type: text/plain, Size: 251 bytes --]

Folks,

   the attached patch fixes for the recent match two issues:

1- using strncpy() does not garantee that the destination string will be 
NULL-terminated

2- If a vmalloc() fails, the previously allocated memory blocks are not 
freed.

Enjoy !


[-- Attachment #2: recent.patch --]
[-- Type: text/plain, Size: 6450 bytes --]

diff -aruN linux-2.4.20-pre10-ac2/include/linux/netfilter_ipv4/ipt_recent.h linux-2.4.20-pre10-ac2-new/include/linux/netfilter_ipv4/ipt_recent.h
--- linux-2.4.20-pre10-ac2/include/linux/netfilter_ipv4/ipt_recent.h	2002-10-24 12:06:54.000000000 -0400
+++ linux-2.4.20-pre10-ac2-new/include/linux/netfilter_ipv4/ipt_recent.h	2002-10-24 12:28:42.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef _IPT_RECENT_H
 #define _IPT_RECENT_H
 
+#define NAME_LEN  200
+
 const static int IPT_RECENT_CHECK = 1;
 const static int IPT_RECENT_SET = 2;
 const static int IPT_RECENT_UPDATE = 4;
@@ -15,7 +17,7 @@
 	u_int32_t   hit_count;
 	u_int8_t    check_set;
 	u_int8_t    invert;
-	char        name[200];
+	char        name[NAME_LEN];
 	u_int8_t    side;
 };
 
diff -aruN linux-2.4.20-pre10-ac2/net/ipv4/netfilter/ipt_recent.c linux-2.4.20-pre10-ac2-new/net/ipv4/netfilter/ipt_recent.c
--- linux-2.4.20-pre10-ac2/net/ipv4/netfilter/ipt_recent.c	2002-10-24 12:06:54.000000000 -0400
+++ linux-2.4.20-pre10-ac2-new/net/ipv4/netfilter/ipt_recent.c	2002-10-24 13:11:30.000000000 -0400
@@ -69,7 +69,7 @@
 
 /* Structure of our linked list of tables of recent lists. */
 struct recent_ip_tables {
-	char name[200];
+	char name[NAME_LEN];
 	int count;
 	int side;
 	int time_pos;
@@ -259,7 +259,7 @@
 	info.hit_count = 0;
 	info.check_set = check_set;
 	info.invert = 0;
-	strncpy(info.name,curr_table->name,200);
+	strncpy(info.name,curr_table->name,NAME_LEN);
 
 	skb.nh.iph = kmalloc(sizeof(struct iphdr),GFP_ATOMIC);
 	if(!skb.nh.iph) { return -ENOMEM; }
@@ -322,7 +322,7 @@
 	/* Find the right table */
 	spin_lock_bh(&recent_lock);
 	curr_table = r_tables;
-	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,200) && (curr_table = curr_table->next) );
+	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,NAME_LEN) && (curr_table = curr_table->next) );
 
 	if(debug) printk(KERN_INFO "ipt_recent: match(): table found('%s')\n",info->name);
 
@@ -585,7 +585,7 @@
 	/* Look for an entry with this name already created */
 	/* Finds the end of the list and the entry before the end if current name does not exist */
 	curr_table = r_tables;
-	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,200) && (curr_table = curr_table->next) );
+	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,NAME_LEN) && (curr_table = curr_table->next) );
 
 	/* If a table already exists just increment the count on that table and return */
 	if(curr_table) { 
@@ -598,18 +598,20 @@
 	/* Table with this name not found */
 	/* Allocate memory for new linked list item */
 
-	if(debug) printk(KERN_INFO "ipt_recent: checkentry: no table found (%s)\n",info->name);
-
-	if(debug) printk(KERN_INFO "ipt_recent: checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
+	if(debug) {
+		printk(KERN_INFO "ipt_recent: checkentry: no table found (%s)\n",info->name);
+		printk(KERN_INFO "ipt_recent: checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
+	}
 
 	curr_table = vmalloc(sizeof(struct recent_ip_tables));
-	if(curr_table == NULL) { spin_unlock_bh(&recent_lock); return -ENOMEM; }
+	if(curr_table == NULL) goto out1;
 
 	curr_table->list_lock = SPIN_LOCK_UNLOCKED;
 	curr_table->next = NULL;
 	curr_table->count = 1;
 	curr_table->time_pos = 0;
-	strncpy(curr_table->name,info->name,200);
+	strncpy(curr_table->name,info->name,NAME_LEN-1);
+	curr_table->name[NAME_LEN-1] = 0;  // Garantee a NULL-terminated string
 
 	if(info->side != IPT_RECENT_SOURCE && info->side != IPT_RECENT_DEST) 
 		curr_table->side = IPT_RECENT_SOURCE;
@@ -622,7 +624,8 @@
 			info->name);
 
 	curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
-	if(curr_table->table == NULL) { spin_unlock_bh(&recent_lock); return -ENOMEM; }
+	if(curr_table->table == NULL) goto out2;
+
 	memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
 	if(debug) printk(KERN_INFO "ipt_recent: checkentry: Allocating %d for pkt_list.\n",
 			sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
@@ -631,8 +634,7 @@
 	if(debug) printk(KERN_INFO "ipt_recent: checkentry: After pkt_list allocation.\n");
 	if(hold == NULL) { 
 		printk(KERN_INFO "ipt_recent: checkentry: unable to allocate for pkt_list.\n");
-		vfree(curr_table->table); spin_unlock_bh(&recent_lock);
-		return -ENOMEM;
+		goto out3;
 	}
 	for(c = 0; c < ip_list_tot; c++) {
 		curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
@@ -643,6 +645,8 @@
 			sizeof(int)*ip_list_hash_size);
 
 	curr_table->hash_table = vmalloc(sizeof(int)*ip_list_hash_size);
+	if(curr_table->hash_table == NULL) goto out4;
+
 	for(c = 0; c < ip_list_hash_size; c++) {
 		curr_table->hash_table[c] = -1;
 	}
@@ -652,6 +656,8 @@
 			sizeof(struct time_info_list)*ip_list_tot);
 
 	curr_table->time_info = vmalloc(sizeof(struct time_info_list)*ip_list_tot);
+	if(curr_table->time_info == NULL) goto out5;
+
 	for(c = 0; c < ip_list_tot; c++) {
 		curr_table->time_info[c].position = c;
 		curr_table->time_info[c].time = 0;
@@ -659,13 +665,9 @@
 
 	/* Create our proc 'status' entry. */
 	curr_table->status_proc = create_proc_entry(curr_table->name, 0644, proc_net_ipt_recent);
-	if (curr_table->status_proc) curr_table->status_proc->owner = THIS_MODULE;
-	else {
-		vfree(curr_table->table);
-		vfree(curr_table);
-		vfree(hold);
-		return -ENOMEM;
-	}
+	if (curr_table->status_proc == NULL) goto out6;
+
+	curr_table->status_proc->owner = THIS_MODULE;
 	curr_table->status_proc->read_proc = ip_recent_get_info;
 	curr_table->status_proc->write_proc = ip_recent_ctrl;
 	curr_table->status_proc->data = curr_table;
@@ -678,6 +680,20 @@
 	if(debug) printk(KERN_INFO "ipt_recent: checkentry() left.\n");
 
 	return 1;
+
+out6:
+	vfree(curr_table->time_info);
+out5:
+	vfree(curr_table->hash_table);
+out4:
+	vfree(hold);
+out3:
+	vfree(curr_table->table);	
+out2:
+	vfree(curr_table);	
+out1:
+	spin_unlock_bh(&recent_lock);
+	return -ENOMEM;
 }
 
 /* This function is called in the event that a rule matching this module is
@@ -708,7 +724,7 @@
 		spin_unlock_bh(&recent_lock);
 		return;
 	}
-	while( strncmp(info->name,curr_table->name,200) && (last_table = curr_table) && (curr_table = curr_table->next) );
+	while( strncmp(info->name,curr_table->name,NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
 
 	/* If a table does not exist then do nothing and return */
 	if(!curr_table) { 

                 reply	other threads:[~2002-10-29 18:11 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=3DBECF6A.3040903@videotron.ca \
    --to=ouellettes@videotron.ca \
    --cc=netfilter-devel@lists.netfilter.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.