Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3063

kernel-2.6.18-194.11.1.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Fri, 27 Feb 2009 20:52:35 +0100
Subject: [s390] af_iucv: broken send_skb_q result in endless loop
Message-id: 20090227195235.GS2447@redhat.com
O-Subject: [RHEL5 U4 PATCH 5/7] s390 - af_iucv: broken send_skb_q results in endless loop
Bugzilla: 487697

Description
============

A race has been detected in iucv_callback_txdone().
skb_unlink has to be done inside the locked area.

In addition checkings for successful allocations are inserted.

Bugzilla
=========

BZ 487697
https://bugzilla.redhat.com/show_bug.cgi?id=487697

Upstream status of the patch:
=============================

This patch is included in linux-2.6 as
git commit d44447229e35115675d166b51a52e512c281475c

Test status:
============

The patch has been tested and fixes the problem.
The fix has been verified by the IBM test department.

Please ACK.

With best regards,

	--Hans

diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 86b1aa1..9130b17 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -489,6 +489,10 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
 	/* Create path. */
 	iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT,
 				     IPRMDATA, GFP_KERNEL);
+	if (!iucv->path) {
+		err = -ENOMEM;
+		goto done;
+	}
 	err = iucv_path_connect(iucv->path, &af_iucv_handler,
 				sa->siucv_user_id, NULL, user_data, sk);
 	if (err) {
@@ -1127,6 +1131,8 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
 
 save_message:
 	save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA);
+	if (!save_msg)
+		return;
 	save_msg->path = path;
 	save_msg->msg = *msg;
 
@@ -1151,10 +1157,10 @@ static void iucv_callback_txdone(struct iucv_path *path,
 			this = list_skb;
 			list_skb = list_skb->next;
 		} while (memcmp(&msg->tag, this->cb, 4) && list_skb);
+		__skb_unlink(this, list);
 
 		spin_unlock_irqrestore(&list->lock, flags);
 
-		skb_unlink(this, &iucv_sk(sk)->send_skb_q);
 		kfree_skb(this);
 	}