Skip to content

Commit 9e73317

Browse files
committed
iucv: Remove SKB list assumptions.
Eliminate the assumption that SKBs and SKB list heads can be cast to eachother in SKB list handling code. This change also appears to fix a bug since the list->next pointer is sampled outside of holding the SKB queue lock. Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4a5a553 commit 9e73317

File tree

1 file changed

+15
-26
lines changed

1 file changed

+15
-26
lines changed

net/iucv/af_iucv.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,30 +1873,26 @@ static void iucv_callback_txdone(struct iucv_path *path,
18731873
struct sock *sk = path->private;
18741874
struct sk_buff *this = NULL;
18751875
struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q;
1876-
struct sk_buff *list_skb = list->next;
1876+
struct sk_buff *list_skb;
18771877
unsigned long flags;
18781878

18791879
bh_lock_sock(sk);
1880-
if (!skb_queue_empty(list)) {
1881-
spin_lock_irqsave(&list->lock, flags);
18821880

1883-
while (list_skb != (struct sk_buff *)list) {
1884-
if (msg->tag == IUCV_SKB_CB(list_skb)->tag) {
1885-
this = list_skb;
1886-
break;
1887-
}
1888-
list_skb = list_skb->next;
1881+
spin_lock_irqsave(&list->lock, flags);
1882+
skb_queue_walk(list, list_skb) {
1883+
if (msg->tag == IUCV_SKB_CB(list_skb)->tag) {
1884+
this = list_skb;
1885+
break;
18891886
}
1890-
if (this)
1891-
__skb_unlink(this, list);
1892-
1893-
spin_unlock_irqrestore(&list->lock, flags);
1887+
}
1888+
if (this)
1889+
__skb_unlink(this, list);
1890+
spin_unlock_irqrestore(&list->lock, flags);
18941891

1895-
if (this) {
1896-
kfree_skb(this);
1897-
/* wake up any process waiting for sending */
1898-
iucv_sock_wake_msglim(sk);
1899-
}
1892+
if (this) {
1893+
kfree_skb(this);
1894+
/* wake up any process waiting for sending */
1895+
iucv_sock_wake_msglim(sk);
19001896
}
19011897

19021898
if (sk->sk_state == IUCV_CLOSING) {
@@ -2284,11 +2280,7 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
22842280

22852281
list = &iucv->send_skb_q;
22862282
spin_lock_irqsave(&list->lock, flags);
2287-
if (skb_queue_empty(list))
2288-
goto out_unlock;
2289-
list_skb = list->next;
2290-
nskb = list_skb->next;
2291-
while (list_skb != (struct sk_buff *)list) {
2283+
skb_queue_walk_safe(list, list_skb, nskb) {
22922284
if (skb_shinfo(list_skb) == skb_shinfo(skb)) {
22932285
switch (n) {
22942286
case TX_NOTIFY_OK:
@@ -2321,10 +2313,7 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
23212313
}
23222314
break;
23232315
}
2324-
list_skb = nskb;
2325-
nskb = nskb->next;
23262316
}
2327-
out_unlock:
23282317
spin_unlock_irqrestore(&list->lock, flags);
23292318

23302319
if (sk->sk_state == IUCV_CLOSING) {

0 commit comments

Comments
 (0)