net: dccp: fix kernel crash on module load
Subsystems (3)
PATCH 1/1 net: dccp: fix kernel crash on module load
Patch eedbbb0d98b2 "net: dccp: initialize (addr,port) ..." added calling to inet_hashinfo2_init() from dccp_init().
However, inet_hashinfo2_init() is marked as __init(), and thus the kernel panics when dccp is loaded as module. Removing __init() tag from inet_hashinfo2_init() is not feasible because it calls into __init functions in mm.
This patch adds inet_hashinfo2_init_mod() function that can be called after the init phase is done; changes dccp_init() to call the new function; un-marks inet_hashinfo2_init() as exported.
--- include/net/inet_hashtables.h | 1 + net/dccp/proto.c | 8 ++++---- net/ipv4/inet_hashtables.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 12 deletions(-)
include/net/inet_hashtables.h +1 -0
@@ -237,6 +237,7 @@ void inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, unsigned long numentries, int scale, unsigned long low_limit, unsigned long high_limit); +int inet_hashinfo2_init_mod (struct inet_hashinfo *h);bool inet_ehash_insert (struct sock *sk,struct sock *osk);bool inet_ehash_nolisten (struct sock *sk,struct sock *osk);
net/dccp/proto.c +4 -4
@@ -1139,11 +1139,11 @@ static int __init dccp_init(void) rc =percpu_counter_init (&dccp_orphan_count,0 ,GFP_KERNEL );if (rc) goto out_fail; - rc = -ENOBUFS ;inet_hashinfo_init (&dccp_hashinfo); -inet_hashinfo2_init (&dccp_hashinfo,"dccp_listen_portaddr_hash" , -INET_LHTABLE_SIZE ,21 ,/* one slot per 2 MB*/ -0 ,64 *1024 ); + rc =inet_hashinfo2_init_mod (&dccp_hashinfo); +if (rc) + goto out_fail; + rc = -ENOBUFS ; dccp_hashinfo.bind_bucket_cachep = kmem_cache_create("dccp_bind_bucket", sizeof(struct inet_bind_bucket), 0,
net/ipv4/inet_hashtables.c +26 -8
@@ -762,13 +762,22 @@ void inet_hashinfo_init(struct inet_hashinfo *h) }EXPORT_SYMBOL_GPL (inet_hashinfo_init); +static void init_hashinfo_lhash2 (struct inet_hashinfo *h) +{ +int i; + +for (i =0 ; i <= h->lhash2_mask; i++) { +spin_lock_init (&h->lhash2[i].lock); +INIT_HLIST_HEAD (&h->lhash2[i].head); + h->lhash2[i].count =0 ; + } +} +void __init inet_hashinfo2_init (struct inet_hashinfo *h,const char *name,unsigned long numentries,int scale,unsigned long low_limit,unsigned long high_limit) { -unsigned int i; - h->lhash2 = alloc_large_system_hash(name, sizeof(*h->lhash2), numentries,
@@ -778,14 +787,23 @@ void __init inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, &h->lhash2_mask, low_limit, high_limit); +init_hashinfo_lhash2 (h); +} -for (i =0 ; i <= h->lhash2_mask; i++) { -spin_lock_init (&h->lhash2[i].lock); -INIT_HLIST_HEAD (&h->lhash2[i].head); - h->lhash2[i].count =0 ; - } +int inet_hashinfo2_init_mod (struct inet_hashinfo *h) +{ + h->lhash2 =kmalloc_array (INET_LHTABLE_SIZE ,sizeof (*h->lhash2),GFP_KERNEL ); +if (!h->lhash2) +return -ENOMEM ; + + h->lhash2_mask =INET_LHTABLE_SIZE -1 ; +/* INET_LHTABLE_SIZE must be a power of 2 */ +BUG_ON (INET_LHTABLE_SIZE & h->lhash2_mask); + +init_hashinfo_lhash2 (h); +return 0 ; } -EXPORT_SYMBOL_GPL (inet_hashinfo2_init); +EXPORT_SYMBOL_GPL (inet_hashinfo2_init_mod);int inet_ehash_locks_alloc (struct inet_hashinfo *hashinfo) {
Signature · 1 line
2.20.1.415.g653613c723-goog
From: Peter Oskolkov <[email protected]>
Date: Mon, 24 Dec 2018 12:57:17 -0800
Quoted 8 lines
Patch
eedbbb0d98b2"net: dccp: initialize (addr,port) ..." added calling toinet_hashinfo2_init()fromdccp_init().However,
inet_hashinfo2_init()is marked as__init(), and thus the kernel panics when dccp is loaded as module. Removing__init()tag frominet_hashinfo2_init()is not feasible because it calls into__initfunctions in mm.
Quoted 8 lines
This patch adds
inet_hashinfo2_init_mod()function that can be called after the init phase is done; changesdccp_init()to call the new function; un-marksinet_hashinfo2_init()as exported.Fixes eedbbb0d98b2 ("net: dccp: initialize (addr,port) ...")Reported-by kernel test robot <[email protected]>Signed-off-by Peter Oskolkov <[email protected]>
Applied, thanks.