Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Catalin Marinas and committed by
David S. Miller
7e56b5d6 33cf71ce

+14 -19
+1
include/net/request_sock.h
··· 31 31 int family; 32 32 int obj_size; 33 33 struct kmem_cache *slab; 34 + char *slab_name; 34 35 int (*rtx_syn_ack)(struct sock *sk, 35 36 struct request_sock *req); 36 37 void (*send_ack)(struct sock *sk, struct sk_buff *skb,
+1
include/net/timewait_sock.h
··· 16 16 17 17 struct timewait_sock_ops { 18 18 struct kmem_cache *twsk_slab; 19 + char *twsk_slab_name; 19 20 unsigned int twsk_obj_size; 20 21 int (*twsk_unique)(struct sock *sk, 21 22 struct sock *sktw, void *twp);
+12 -19
net/core/sock.c
··· 2035 2035 2036 2036 int 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 2038 if (alloc_slab) { 2042 2039 prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, 2043 2040 SLAB_HWCACHE_ALIGN, NULL); ··· 2048 2051 if (prot->rsk_prot != NULL) { 2049 2052 static const char mask[] = "request_sock_%s"; 2050 2053 2051 - request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2052 - if (request_sock_slab_name == NULL) 2054 + prot->rsk_prot->slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2055 + if (prot->rsk_prot->slab_name == NULL) 2053 2056 goto out_free_sock_slab; 2054 2057 2055 - sprintf(request_sock_slab_name, mask, prot->name); 2056 - prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name, 2058 + sprintf(prot->rsk_prot->slab_name, mask, prot->name); 2059 + prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name, 2057 2060 prot->rsk_prot->obj_size, 0, 2058 2061 SLAB_HWCACHE_ALIGN, NULL); 2059 2062 ··· 2067 2070 if (prot->twsk_prot != NULL) { 2068 2071 static const char mask[] = "tw_sock_%s"; 2069 2072 2070 - timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2073 + prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); 2071 2074 2072 - if (timewait_sock_slab_name == NULL) 2075 + if (prot->twsk_prot->twsk_slab_name == NULL) 2073 2076 goto out_free_request_sock_slab; 2074 2077 2075 - sprintf(timewait_sock_slab_name, mask, prot->name); 2078 + sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name); 2076 2079 prot->twsk_prot->twsk_slab = 2077 - kmem_cache_create(timewait_sock_slab_name, 2080 + kmem_cache_create(prot->twsk_prot->twsk_slab_name, 2078 2081 prot->twsk_prot->twsk_obj_size, 2079 2082 0, SLAB_HWCACHE_ALIGN, 2080 2083 NULL); ··· 2090 2093 return 0; 2091 2094 2092 2095 out_free_timewait_sock_slab_name: 2093 - kfree(timewait_sock_slab_name); 2096 + kfree(prot->twsk_prot->twsk_slab_name); 2094 2097 out_free_request_sock_slab: 2095 2098 if (prot->rsk_prot && prot->rsk_prot->slab) { 2096 2099 kmem_cache_destroy(prot->rsk_prot->slab); 2097 2100 prot->rsk_prot->slab = NULL; 2098 2101 } 2099 2102 out_free_request_sock_slab_name: 2100 - kfree(request_sock_slab_name); 2103 + kfree(prot->rsk_prot->slab_name); 2101 2104 out_free_sock_slab: 2102 2105 kmem_cache_destroy(prot->slab); 2103 2106 prot->slab = NULL; ··· 2120 2123 } 2121 2124 2122 2125 if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) { 2123 - const char *name = kmem_cache_name(prot->rsk_prot->slab); 2124 - 2125 2126 kmem_cache_destroy(prot->rsk_prot->slab); 2126 - kfree(name); 2127 + kfree(prot->rsk_prot->slab_name); 2127 2128 prot->rsk_prot->slab = NULL; 2128 2129 } 2129 2130 2130 2131 if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) { 2131 - const char *name = kmem_cache_name(prot->twsk_prot->twsk_slab); 2132 - 2133 2132 kmem_cache_destroy(prot->twsk_prot->twsk_slab); 2134 - kfree(name); 2133 + kfree(prot->twsk_prot->twsk_slab_name); 2135 2134 prot->twsk_prot->twsk_slab = NULL; 2136 2135 } 2137 2136 }