Commit 71027d56 authored by Vinay Kumar Yadav's avatar Vinay Kumar Yadav Committed by Greg Kroah-Hartman

crypto: chtls - Fixed memory leak

[ Upstream commit 93e23eb2 ]

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: default avatarVinay Kumar Yadav <vinay.yadav@chelsio.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent af8eca60
...@@ -731,6 +731,14 @@ static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb) ...@@ -731,6 +731,14 @@ static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
return 0; 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) static void chtls_release_resources(struct sock *sk)
{ {
struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); struct chtls_sock *csk = rcu_dereference_sk_user_data(sk);
...@@ -745,6 +753,11 @@ static void chtls_release_resources(struct sock *sk) ...@@ -745,6 +753,11 @@ static void chtls_release_resources(struct sock *sk)
kfree_skb(csk->txdata_skb_cache); kfree_skb(csk->txdata_skb_cache);
csk->txdata_skb_cache = NULL; 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) { if (csk->l2t_entry) {
cxgb4_l2t_release(csk->l2t_entry); cxgb4_l2t_release(csk->l2t_entry);
csk->l2t_entry = NULL; csk->l2t_entry = NULL;
...@@ -1714,6 +1727,7 @@ static void chtls_peer_close(struct sock *sk, struct sk_buff *skb) ...@@ -1714,6 +1727,7 @@ static void chtls_peer_close(struct sock *sk, struct sk_buff *skb)
else else
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); 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) static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb)
...@@ -2041,19 +2055,6 @@ static int chtls_conn_cpl(struct chtls_dev *cdev, struct sk_buff *skb) ...@@ -2041,19 +2055,6 @@ static int chtls_conn_cpl(struct chtls_dev *cdev, struct sk_buff *skb)
return 0; 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) static void chtls_rx_ack(struct sock *sk, struct sk_buff *skb)
{ {
struct cpl_fw4_ack *hdr = cplhdr(skb) + RSS_HDR; struct cpl_fw4_ack *hdr = cplhdr(skb) + RSS_HDR;
......
...@@ -188,6 +188,12 @@ static inline void chtls_kfree_skb(struct sock *sk, struct sk_buff *skb) ...@@ -188,6 +188,12 @@ static inline void chtls_kfree_skb(struct sock *sk, struct sk_buff *skb)
kfree_skb(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) static inline void enqueue_wr(struct chtls_sock *csk, struct sk_buff *skb)
{ {
WR_SKB_CB(skb)->next_wr = NULL; WR_SKB_CB(skb)->next_wr = NULL;
...@@ -200,4 +206,19 @@ static inline void enqueue_wr(struct chtls_sock *csk, struct sk_buff *skb) ...@@ -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; WR_SKB_CB(csk->wr_skb_tail)->next_wr = skb;
csk->wr_skb_tail = 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 #endif
...@@ -361,6 +361,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) ...@@ -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.cmd_more = cpu_to_be32(ULPTX_CMD_V(ULP_TX_SC_IMM));
kwr->sc_imm.len = cpu_to_be32(klen); kwr->sc_imm.len = cpu_to_be32(klen);
lock_sock(sk);
/* key info */ /* key info */
kctx = (struct _key_ctx *)(kwr + 1); kctx = (struct _key_ctx *)(kwr + 1);
ret = chtls_key_info(csk, kctx, keylen, optname); ret = chtls_key_info(csk, kctx, keylen, optname);
...@@ -399,8 +400,10 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) ...@@ -399,8 +400,10 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname)
csk->tlshws.txkey = keyid; csk->tlshws.txkey = keyid;
} }
release_sock(sk);
return ret; return ret;
out_notcb: out_notcb:
release_sock(sk);
free_tls_keyid(sk); free_tls_keyid(sk);
out_nokey: out_nokey:
kfree_skb(skb); kfree_skb(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment