Commit 9e733177 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parent 4a5a553d
Loading
Loading
Loading
Loading
+15 −26
Original line number Diff line number Diff line
@@ -1873,23 +1873,20 @@ static void iucv_callback_txdone(struct iucv_path *path,
	struct sock *sk = path->private;
	struct sk_buff *this = NULL;
	struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q;
	struct sk_buff *list_skb = list->next;
	struct sk_buff *list_skb;
	unsigned long flags;

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

		while (list_skb != (struct sk_buff *)list) {
	spin_lock_irqsave(&list->lock, flags);
	skb_queue_walk(list, list_skb) {
		if (msg->tag == IUCV_SKB_CB(list_skb)->tag) {
			this = list_skb;
			break;
		}
			list_skb = list_skb->next;
	}
	if (this)
		__skb_unlink(this, list);

	spin_unlock_irqrestore(&list->lock, flags);

	if (this) {
@@ -1897,7 +1894,6 @@ static void iucv_callback_txdone(struct iucv_path *path,
		/* wake up any process waiting for sending */
		iucv_sock_wake_msglim(sk);
	}
	}

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

	list = &iucv->send_skb_q;
	spin_lock_irqsave(&list->lock, flags);
	if (skb_queue_empty(list))
		goto out_unlock;
	list_skb = list->next;
	nskb = list_skb->next;
	while (list_skb != (struct sk_buff *)list) {
	skb_queue_walk_safe(list, list_skb, nskb) {
		if (skb_shinfo(list_skb) == skb_shinfo(skb)) {
			switch (n) {
			case TX_NOTIFY_OK:
@@ -2321,10 +2313,7 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
			}
			break;
		}
		list_skb = nskb;
		nskb = nskb->next;
	}
out_unlock:
	spin_unlock_irqrestore(&list->lock, flags);

	if (sk->sk_state == IUCV_CLOSING) {