Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

atm: solos-pci: Fix potential deadlock on &tx_queue_lock

As &card->tx_queue_lock is acquired under softirq context along the
following call chain from solos_bh(), other acquisition of the same
lock inside process context should disable at least bh to avoid double
lock.

<deadlock #2>
pclose()
--> spin_lock(&card->tx_queue_lock)
<interrupt>
--> solos_bh()
--> fpga_tx()
--> spin_lock(&card->tx_queue_lock)

This flaw was found by an experimental static analysis tool I am
developing for irq-related deadlock.

To prevent the potential deadlock, the patch uses spin_lock_bh()
on &card->tx_queue_lock under process context code consistently to
prevent the possible deadlock scenario.

Fixes: 213e85d38912 ("solos-pci: clean up pclose() function")
Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Chengfeng Ye and committed by
David S. Miller
15319a4e d5dba32b

+2 -2
+2 -2
drivers/atm/solos-pci.c
··· 956 956 struct pkt_hdr *header; 957 957 958 958 /* Remove any yet-to-be-transmitted packets from the pending queue */ 959 - spin_lock(&card->tx_queue_lock); 959 + spin_lock_bh(&card->tx_queue_lock); 960 960 skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) { 961 961 if (SKB_CB(skb)->vcc == vcc) { 962 962 skb_unlink(skb, &card->tx_queue[port]); 963 963 solos_pop(vcc, skb); 964 964 } 965 965 } 966 - spin_unlock(&card->tx_queue_lock); 966 + spin_unlock_bh(&card->tx_queue_lock); 967 967 968 968 skb = alloc_skb(sizeof(*header), GFP_KERNEL); 969 969 if (!skb) {