aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2008-11-21 19:45:22 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-21 19:45:22 -0500
commit7e56b5d698707a9934833c47b24d78fb0bcaf764 (patch)
tree949d9320501fa64e3710acda83487d4c74e52247 /net
parent33cf71cee14743185305c61625c4544885055733 (diff)
net: Fix memory leak in the proto_register function
If the slub allocator is used, kmem_cache_create() may merge two or more kmem_cache's into one but the cache name pointer is not updated and kmem_cache_name() is no longer guaranteed to return the pointer passed to the former function. This patch stores the kmalloc'ed pointers in the corresponding request_sock_ops and timewait_sock_ops structures. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com> Reviewed-by: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/sock.c31
1 files changed, 12 insertions, 19 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 341e39456952..edf7220889a4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2035,9 +2035,6 @@ static inline void release_proto_idx(struct proto *prot)
2035 2035
2036int proto_register(struct proto *prot, int alloc_slab) 2036int proto_register(struct proto *prot, int alloc_slab)
2037{ 2037{
2038 char *request_sock_slab_name = NULL;
2039 char *timewait_sock_slab_name;
2040
2041 if (alloc_slab) { 2038 if (alloc_slab) {
2042 prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, 2039 prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
2043 SLAB_HWCACHE_ALIGN, NULL); 2040 SLAB_HWCACHE_ALIGN, NULL);
@@ -2051,12 +2048,12 @@ int proto_register(struct proto *prot, int alloc_slab)
2051 if (prot->rsk_prot != NULL) { 2048 if (prot->rsk_prot != NULL) {
2052 static const char mask[] = "request_sock_%s"; 2049 static const char mask[] = "request_sock_%s";
2053 2050
2054 request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2051 prot->rsk_prot->slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
2055 if (request_sock_slab_name == NULL) 2052 if (prot->rsk_prot->slab_name == NULL)
2056 goto out_free_sock_slab; 2053 goto out_free_sock_slab;
2057 2054
2058 sprintf(request_sock_slab_name, mask, prot->name); 2055 sprintf(prot->rsk_prot->slab_name, mask, prot->name);
2059 prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name, 2056 prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name,
2060 prot->rsk_prot->obj_size, 0, 2057 prot->rsk_prot->obj_size, 0,
2061 SLAB_HWCACHE_ALIGN, NULL); 2058 SLAB_HWCACHE_ALIGN, NULL);
2062 2059
@@ -2070,14 +2067,14 @@ int proto_register(struct proto *prot, int alloc_slab)
2070 if (prot->twsk_prot != NULL) { 2067 if (prot->twsk_prot != NULL) {
2071 static const char mask[] = "tw_sock_%s"; 2068 static const char mask[] = "tw_sock_%s";
2072 2069
2073 timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2070 prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
2074 2071
2075 if (timewait_sock_slab_name == NULL) 2072 if (prot->twsk_prot->twsk_slab_name == NULL)
2076 goto out_free_request_sock_slab; 2073 goto out_free_request_sock_slab;
2077 2074
2078 sprintf(timewait_sock_slab_name, mask, prot->name); 2075 sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name);
2079 prot->twsk_prot->twsk_slab = 2076 prot->twsk_prot->twsk_slab =
2080 kmem_cache_create(timewait_sock_slab_name, 2077 kmem_cache_create(prot->twsk_prot->twsk_slab_name,
2081 prot->twsk_prot->twsk_obj_size, 2078 prot->twsk_prot->twsk_obj_size,
2082 0, SLAB_HWCACHE_ALIGN, 2079 0, SLAB_HWCACHE_ALIGN,
2083 NULL); 2080 NULL);
@@ -2093,14 +2090,14 @@ int proto_register(struct proto *prot, int alloc_slab)
2093 return 0; 2090 return 0;
2094 2091
2095out_free_timewait_sock_slab_name: 2092out_free_timewait_sock_slab_name:
2096 kfree(timewait_sock_slab_name); 2093 kfree(prot->twsk_prot->twsk_slab_name);
2097out_free_request_sock_slab: 2094out_free_request_sock_slab:
2098 if (prot->rsk_prot && prot->rsk_prot->slab) { 2095 if (prot->rsk_prot && prot->rsk_prot->slab) {
2099 kmem_cache_destroy(prot->rsk_prot->slab); 2096 kmem_cache_destroy(prot->rsk_prot->slab);
2100 prot->rsk_prot->slab = NULL; 2097 prot->rsk_prot->slab = NULL;
2101 } 2098 }
2102out_free_request_sock_slab_name: 2099out_free_request_sock_slab_name:
2103 kfree(request_sock_slab_name); 2100 kfree(prot->rsk_prot->slab_name);
2104out_free_sock_slab: 2101out_free_sock_slab:
2105 kmem_cache_destroy(prot->slab); 2102 kmem_cache_destroy(prot->slab);
2106 prot->slab = NULL; 2103 prot->slab = NULL;
@@ -2123,18 +2120,14 @@ void proto_unregister(struct proto *prot)
2123 } 2120 }
2124 2121
2125 if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) { 2122 if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
2126 const char *name = kmem_cache_name(prot->rsk_prot->slab);
2127
2128 kmem_cache_destroy(prot->rsk_prot->slab); 2123 kmem_cache_destroy(prot->rsk_prot->slab);
2129 kfree(name); 2124 kfree(prot->rsk_prot->slab_name);
2130 prot->rsk_prot->slab = NULL; 2125 prot->rsk_prot->slab = NULL;
2131 } 2126 }
2132 2127
2133 if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) { 2128 if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) {
2134 const char *name = kmem_cache_name(prot->twsk_prot->twsk_slab);
2135
2136 kmem_cache_destroy(prot->twsk_prot->twsk_slab); 2129 kmem_cache_destroy(prot->twsk_prot->twsk_slab);
2137 kfree(name); 2130 kfree(prot->twsk_prot->twsk_slab_name);
2138 prot->twsk_prot->twsk_slab = NULL; 2131 prot->twsk_prot->twsk_slab = NULL;
2139 } 2132 }
2140} 2133}