diff options
author | Ursula Braun <braunu@de.ibm.com> | 2008-02-07 21:07:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-07 21:07:19 -0500 |
commit | d44447229e35115675d166b51a52e512c281475c (patch) | |
tree | b968431fddcbb21fe0c3278c7545c22bdc2be4a4 /net | |
parent | 435bc9dfc6927eed9465e297d7aca1217aa61956 (diff) |
[AF_IUCV]: broken send_skb_q results in endless loop
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.
Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/iucv/af_iucv.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 2255e3c082ed..b3f5f840d067 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -482,6 +482,10 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
482 | /* Create path. */ | 482 | /* Create path. */ |
483 | iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT, | 483 | iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT, |
484 | IPRMDATA, GFP_KERNEL); | 484 | IPRMDATA, GFP_KERNEL); |
485 | if (!iucv->path) { | ||
486 | err = -ENOMEM; | ||
487 | goto done; | ||
488 | } | ||
485 | err = iucv_path_connect(iucv->path, &af_iucv_handler, | 489 | err = iucv_path_connect(iucv->path, &af_iucv_handler, |
486 | sa->siucv_user_id, NULL, user_data, sk); | 490 | sa->siucv_user_id, NULL, user_data, sk); |
487 | if (err) { | 491 | if (err) { |
@@ -1094,6 +1098,8 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) | |||
1094 | 1098 | ||
1095 | save_message: | 1099 | save_message: |
1096 | save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA); | 1100 | save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA); |
1101 | if (!save_msg) | ||
1102 | return; | ||
1097 | save_msg->path = path; | 1103 | save_msg->path = path; |
1098 | save_msg->msg = *msg; | 1104 | save_msg->msg = *msg; |
1099 | 1105 | ||
@@ -1118,10 +1124,10 @@ static void iucv_callback_txdone(struct iucv_path *path, | |||
1118 | this = list_skb; | 1124 | this = list_skb; |
1119 | list_skb = list_skb->next; | 1125 | list_skb = list_skb->next; |
1120 | } while (memcmp(&msg->tag, this->cb, 4) && list_skb); | 1126 | } while (memcmp(&msg->tag, this->cb, 4) && list_skb); |
1127 | __skb_unlink(this, list); | ||
1121 | 1128 | ||
1122 | spin_unlock_irqrestore(&list->lock, flags); | 1129 | spin_unlock_irqrestore(&list->lock, flags); |
1123 | 1130 | ||
1124 | skb_unlink(this, &iucv_sk(sk)->send_skb_q); | ||
1125 | kfree_skb(this); | 1131 | kfree_skb(this); |
1126 | } | 1132 | } |
1127 | 1133 | ||