| From 246405459dcf391a8b9362a0f28e31d8bcc41b18 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 19 Dec 2019 16:21:48 +0530 |
| Subject: crypto: chtls - Fixed memory leak |
| |
| From: Vinay Kumar Yadav <vinay.yadav@chelsio.com> |
| |
| [ Upstream commit 93e23eb2ed6c11b4f483c8111ac155ec2b1f3042 ] |
| |
| Freed work request skbs when connection terminates. |
| enqueue_wr()/ dequeue_wr() is shared between softirq |
| and application contexts, should be protected by socket |
| lock. Moved dequeue_wr() to appropriate file. |
| |
| Signed-off-by: Vinay Kumar Yadav <vinay.yadav@chelsio.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/crypto/chelsio/chtls/chtls_cm.c | 27 +++++++++++++------------ |
| drivers/crypto/chelsio/chtls/chtls_cm.h | 21 +++++++++++++++++++ |
| drivers/crypto/chelsio/chtls/chtls_hw.c | 3 +++ |
| 3 files changed, 38 insertions(+), 13 deletions(-) |
| |
| diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c |
| index 8b749c721c871..28d24118c6450 100644 |
| --- a/drivers/crypto/chelsio/chtls/chtls_cm.c |
| +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c |
| @@ -731,6 +731,14 @@ static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb) |
| return 0; |
| } |
| |
| +static void chtls_purge_wr_queue(struct sock *sk) |
| +{ |
| + struct sk_buff *skb; |
| + |
| + while ((skb = dequeue_wr(sk)) != NULL) |
| + kfree_skb(skb); |
| +} |
| + |
| static void chtls_release_resources(struct sock *sk) |
| { |
| struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); |
| @@ -745,6 +753,11 @@ static void chtls_release_resources(struct sock *sk) |
| kfree_skb(csk->txdata_skb_cache); |
| csk->txdata_skb_cache = NULL; |
| |
| + if (csk->wr_credits != csk->wr_max_credits) { |
| + chtls_purge_wr_queue(sk); |
| + chtls_reset_wr_list(csk); |
| + } |
| + |
| if (csk->l2t_entry) { |
| cxgb4_l2t_release(csk->l2t_entry); |
| csk->l2t_entry = NULL; |
| @@ -1714,6 +1727,7 @@ static void chtls_peer_close(struct sock *sk, struct sk_buff *skb) |
| else |
| sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
| } |
| + kfree_skb(skb); |
| } |
| |
| static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb) |
| @@ -2041,19 +2055,6 @@ rel_skb: |
| return 0; |
| } |
| |
| -static struct sk_buff *dequeue_wr(struct sock *sk) |
| -{ |
| - struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); |
| - struct sk_buff *skb = csk->wr_skb_head; |
| - |
| - if (likely(skb)) { |
| - /* Don't bother clearing the tail */ |
| - csk->wr_skb_head = WR_SKB_CB(skb)->next_wr; |
| - WR_SKB_CB(skb)->next_wr = NULL; |
| - } |
| - return skb; |
| -} |
| - |
| static void chtls_rx_ack(struct sock *sk, struct sk_buff *skb) |
| { |
| struct cpl_fw4_ack *hdr = cplhdr(skb) + RSS_HDR; |
| diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.h b/drivers/crypto/chelsio/chtls/chtls_cm.h |
| index 78eb3afa3a80d..4282d8a4eae48 100644 |
| --- a/drivers/crypto/chelsio/chtls/chtls_cm.h |
| +++ b/drivers/crypto/chelsio/chtls/chtls_cm.h |
| @@ -188,6 +188,12 @@ static inline void chtls_kfree_skb(struct sock *sk, struct sk_buff *skb) |
| kfree_skb(skb); |
| } |
| |
| +static inline void chtls_reset_wr_list(struct chtls_sock *csk) |
| +{ |
| + csk->wr_skb_head = NULL; |
| + csk->wr_skb_tail = NULL; |
| +} |
| + |
| static inline void enqueue_wr(struct chtls_sock *csk, struct sk_buff *skb) |
| { |
| WR_SKB_CB(skb)->next_wr = NULL; |
| @@ -200,4 +206,19 @@ static inline void enqueue_wr(struct chtls_sock *csk, struct sk_buff *skb) |
| WR_SKB_CB(csk->wr_skb_tail)->next_wr = skb; |
| csk->wr_skb_tail = skb; |
| } |
| + |
| +static inline struct sk_buff *dequeue_wr(struct sock *sk) |
| +{ |
| + struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); |
| + struct sk_buff *skb = NULL; |
| + |
| + skb = csk->wr_skb_head; |
| + |
| + if (likely(skb)) { |
| + /* Don't bother clearing the tail */ |
| + csk->wr_skb_head = WR_SKB_CB(skb)->next_wr; |
| + WR_SKB_CB(skb)->next_wr = NULL; |
| + } |
| + return skb; |
| +} |
| #endif |
| diff --git a/drivers/crypto/chelsio/chtls/chtls_hw.c b/drivers/crypto/chelsio/chtls/chtls_hw.c |
| index 4909607558644..64d24823c65aa 100644 |
| --- a/drivers/crypto/chelsio/chtls/chtls_hw.c |
| +++ b/drivers/crypto/chelsio/chtls/chtls_hw.c |
| @@ -361,6 +361,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) |
| kwr->sc_imm.cmd_more = cpu_to_be32(ULPTX_CMD_V(ULP_TX_SC_IMM)); |
| kwr->sc_imm.len = cpu_to_be32(klen); |
| |
| + lock_sock(sk); |
| /* key info */ |
| kctx = (struct _key_ctx *)(kwr + 1); |
| ret = chtls_key_info(csk, kctx, keylen, optname); |
| @@ -399,8 +400,10 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) |
| csk->tlshws.txkey = keyid; |
| } |
| |
| + release_sock(sk); |
| return ret; |
| out_notcb: |
| + release_sock(sk); |
| free_tls_keyid(sk); |
| out_nokey: |
| kfree_skb(skb); |
| -- |
| 2.20.1 |
| |