Hi List,

This is a patch for fixing the following problem-
if the application executes IPMICTL_SET_GETS_EVENTS_CMD and does
not execute IPMICTL_RECEIVE_MSG(_TRUNC), ie does not read
the message from the queue, which frees the
memory occupied by the messages in the queue, leads to
the infinite growth of the message queue and getting OOM
killing invoked.

Thanks
Amit Chaudhary.

This patch fixes the problem that occur if the
application executes IPMICTL_SET_GETS_EVENTS_CMD and does
not execute IPMICTL_RECEIVE_MSG(_TRUNC), ie does not read
the message from the queue, the receive operation frees the
memory occupied by the messages in the queue. This leads to
the infinite growth of the message queue and getting OOM
killing invoked.

Signed-off-by: Amit Chaudhary <[EMAIL PROTECTED]>

Index: linux-2.6.26/drivers/char/ipmi/ipmi_devintf.c
===================================================================
--- linux-2.6.26.orig/drivers/char/ipmi/ipmi_devintf.c
+++ linux-2.6.26/drivers/char/ipmi/ipmi_devintf.c
@@ -44,6 +44,9 @@
 #include <linux/device.h>
 #include <linux/compat.h>
 
+#define MAX_RECV_MSGS_QUEUE  100
+#define PRFX "IPMI device interface: "
+
 struct ipmi_file_private
 {
 	ipmi_user_t          user;
@@ -55,6 +58,10 @@ struct ipmi_file_private
 	struct mutex	     recv_mutex;
 	int                  default_retries;
 	unsigned int         default_retry_time_ms;
+	/* limit the queue at recv_msgs_count */
+	unsigned int         recv_msgs_count;
+	unsigned char        recv_msgs_printed;
+
 };
 
 static void file_receive_handler(struct ipmi_recv_msg *msg,
@@ -66,14 +73,33 @@ static void file_receive_handler(struct 
 
 	spin_lock_irqsave(&(priv->recv_msg_lock), flags);
 
+	if (priv->recv_msgs_count >= MAX_RECV_MSGS_QUEUE) {
+		ipmi_free_recv_msg(msg);
+		if (!priv->recv_msgs_printed) {
+			printk(KERN_WARNING PRFX "Recieve message queue is full"
+				" now, discarding incoming message(s).\n");
+			priv->recv_msgs_printed = 1;
+		}
+
+		goto out_unlock;
+	}
+
+	if (priv->recv_msgs_printed) {
+		printk(KERN_WARNING PRFX "Recieve message queue no longer full."
+			"\n");
+		priv->recv_msgs_printed = 0;
+	}
+
 	was_empty = list_empty(&(priv->recv_msgs));
 	list_add_tail(&(msg->link), &(priv->recv_msgs));
+	priv->recv_msgs_count++;
 
 	if (was_empty) {
 		wake_up_interruptible(&priv->wait);
 		kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
 	}
 
+out_unlock:
 	spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
 }
 
@@ -144,6 +170,10 @@ static int ipmi_open(struct inode *inode
 	priv->default_retries = -1;
 	priv->default_retry_time_ms = 0;
 
+	/* message queue overrun handling*/
+	priv->recv_msgs_count = 0;
+	priv->recv_msgs_printed = 0;
+
 	return 0;
 }
 
@@ -302,6 +332,7 @@ static int ipmi_ioctl(struct inode  *ino
 		entry = priv->recv_msgs.next;
 		msg = list_entry(entry, struct ipmi_recv_msg, link);
 		list_del(entry);
+		priv->recv_msgs_count--;
 		spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
 
 		addr_len = ipmi_addr_length(msg->addr.addr_type);
@@ -358,6 +389,7 @@ static int ipmi_ioctl(struct inode  *ino
 		   the head of the queue. */
 		spin_lock_irqsave(&(priv->recv_msg_lock), flags);
 		list_add(entry, &(priv->recv_msgs));
+		priv->recv_msgs_count++;
 		spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
 		mutex_unlock(&priv->recv_mutex);
 		break;
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to