The driver may sleep while holding a spinlock. The function call path (from bottom to top) in Linux 4.19 is: drivers/crypto/chelsio/chtls/chtls_cm.c, 1806: alloc_skb(GFP_KERNEL) in send_abort_rpl drivers/crypto/chelsio/chtls/chtls_cm.c, 1925: send_abort_rpl in abort_syn_rcv drivers/crypto/chelsio/chtls/chtls_cm.c, 1920: spin_lock in abort_syn_rcv drivers/crypto/chelsio/chtls/chtls_cm.c, 1787: alloc_skb(GFP_KERNEL) in send_defer_abort_rpl drivers/crypto/chelsio/chtls/chtls_cm.c, 1811: send_defer_abort_rpl in send_abort_rpl drivers/crypto/chelsio/chtls/chtls_cm.c, 1925: send_abort_rpl in abort_syn_rcv drivers/crypto/chelsio/chtls/chtls_cm.c, 1920: spin_lock in abort_syn_rcv alloc_skb(GFP_KERNEL) can sleep at runtime. To fix these possible bugs, GFP_KERNEL is replaced with GFP_ATOMIC. Besides, in send_defer_abort_rpl(), error handling code is added to handle the failure of alloc_skb(). These bugs are found by a static analysis tool STCheck written by myself. Signed-off-by: Jia-Ju Bai <baijiaju1990@xxxxxxxxx> --- drivers/crypto/chelsio/chtls/chtls_cm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index aca75237bbcf..e6e4c3ddc368 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -1805,8 +1805,11 @@ static void send_defer_abort_rpl(struct chtls_dev *cdev, struct sk_buff *skb) struct cpl_abort_req_rss *req = cplhdr(skb); struct sk_buff *reply_skb; - reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl), - GFP_KERNEL | __GFP_NOFAIL); + reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl), GFP_ATOMIC); + if (!reply_skb) { + kfree_skb(skb); + return; + } __skb_put(reply_skb, sizeof(struct cpl_abort_rpl)); set_abort_rpl_wr(reply_skb, GET_TID(req), (req->status & CPL_ABORT_NO_RST)); @@ -1825,7 +1828,7 @@ static void send_abort_rpl(struct sock *sk, struct sk_buff *skb, csk = rcu_dereference_sk_user_data(sk); reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl), - GFP_KERNEL); + GFP_ATOMIC); if (!reply_skb) { req->status = (queue << 1); -- 2.17.1