From: Miaohe Lin <linmiaohe@huawei.com> Date: 2020-08-10 12:18:20
If we failed to assign proto idx, we free the twsk_slab_name but forget to
free the twsk_slab. Add a helper function tw_prot_cleanup() to free these
together and also use this helper function in proto_unregister().
Fixes: b45ce32135d1 ("sock: fix potential memory leak in proto_register()")
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
---
net/core/sock.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
@@ -3406,6 +3406,16 @@ static void sock_inuse_add(struct net *net, int val)}#endif+staticvoidtw_prot_cleanup(structtimewait_sock_ops*twsk_prot)+{+if(!twsk_prot)+return;+kfree(twsk_prot->twsk_slab_name);+twsk_prot->twsk_slab_name=NULL;+kmem_cache_destroy(twsk_prot->twsk_slab);+twsk_prot->twsk_slab=NULL;+}+staticvoidreq_prot_cleanup(structrequest_sock_ops*rsk_prot){if(!rsk_prot)
@@ -3476,7 +3486,7 @@ int proto_register(struct proto *prot, int alloc_slab)prot->slab_flags,NULL);if(prot->twsk_prot->twsk_slab==NULL)-gotoout_free_timewait_sock_slab_name;+gotoout_free_timewait_sock_slab;}}
@@ -3484,15 +3494,15 @@ int proto_register(struct proto *prot, int alloc_slab)ret=assign_proto_idx(prot);if(ret){mutex_unlock(&proto_list_mutex);-gotoout_free_timewait_sock_slab_name;+gotoout_free_timewait_sock_slab;}list_add(&prot->node,&proto_list);mutex_unlock(&proto_list_mutex);returnret;-out_free_timewait_sock_slab_name:+out_free_timewait_sock_slab:if(alloc_slab&&prot->twsk_prot)-kfree(prot->twsk_prot->twsk_slab_name);+tw_prot_cleanup(prot->twsk_prot);out_free_request_sock_slab:if(alloc_slab){req_prot_cleanup(prot->rsk_prot);
@@ -3516,12 +3526,7 @@ void proto_unregister(struct proto *prot)prot->slab=NULL;req_prot_cleanup(prot->rsk_prot);--if(prot->twsk_prot!=NULL&&prot->twsk_prot->twsk_slab!=NULL){-kmem_cache_destroy(prot->twsk_prot->twsk_slab);-kfree(prot->twsk_prot->twsk_slab_name);-prot->twsk_prot->twsk_slab=NULL;-}+tw_prot_cleanup(prot->twsk_prot);}EXPORT_SYMBOL(proto_unregister);
From: David Miller <davem@davemloft.net> Date: 2020-08-11 22:37:27
From: Miaohe Lin <linmiaohe@huawei.com>
Date: Mon, 10 Aug 2020 08:16:58 -0400
If we failed to assign proto idx, we free the twsk_slab_name but forget to
free the twsk_slab. Add a helper function tw_prot_cleanup() to free these
together and also use this helper function in proto_unregister().
Fixes: b45ce32135d1 ("sock: fix potential memory leak in proto_register()")
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
From: Cong Wang <hidden> Date: 2020-08-11 23:03:05
On Mon, Aug 10, 2020 at 5:19 AM Miaohe Lin [off-list ref] wrote:
quoted hunk
If we failed to assign proto idx, we free the twsk_slab_name but forget to
free the twsk_slab. Add a helper function tw_prot_cleanup() to free these
together and also use this helper function in proto_unregister().
Fixes: b45ce32135d1 ("sock: fix potential memory leak in proto_register()")
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
---
net/core/sock.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
@@ -3406,6 +3406,16 @@ static void sock_inuse_add(struct net *net, int val)}#endif+staticvoidtw_prot_cleanup(structtimewait_sock_ops*twsk_prot)+{+if(!twsk_prot)+return;+kfree(twsk_prot->twsk_slab_name);+twsk_prot->twsk_slab_name=NULL;+kmem_cache_destroy(twsk_prot->twsk_slab);
Hmm, are you sure you can free the kmem cache name before
kmem_cache_destroy()? To me, it seems kmem_cache_destroy()
frees the name via slab_kmem_cache_release() via kfree_const().
With your patch, we have a double-free on the name?
Or am I missing anything?
Thanks.
From: David Miller <davem@davemloft.net> Date: 2020-08-11 23:10:35
From: Cong Wang <redacted>
Date: Tue, 11 Aug 2020 16:02:51 -0700
quoted
@@ -3406,6 +3406,16 @@ static void sock_inuse_add(struct net *net, int val) } #endif+static void tw_prot_cleanup(struct timewait_sock_ops *twsk_prot)+{+ if (!twsk_prot)+ return;+ kfree(twsk_prot->twsk_slab_name);+ twsk_prot->twsk_slab_name = NULL;+ kmem_cache_destroy(twsk_prot->twsk_slab);
Hmm, are you sure you can free the kmem cache name before
kmem_cache_destroy()? To me, it seems kmem_cache_destroy()
frees the name via slab_kmem_cache_release() via kfree_const().
With your patch, we have a double-free on the name?
Or am I missing anything?
Yep, there is a double free here.
Please fix this.