From 464f0a710d4677b0e83d160a41e8c69a7f4a614f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 17 Jul 2020 23:05:20 +0200 Subject: [KERNEL] Fix leaks, check return codes in module init --- src/kernel/core.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/kernel/core.c b/src/kernel/core.c index 8da2b39..a0854dd 100644 --- a/src/kernel/core.c +++ b/src/kernel/core.c @@ -55,12 +55,12 @@ -struct workqueue_struct *dnbd3_wq; +struct workqueue_struct *dnbd3_wq = NULL; DEFINE_IDR(dnbd3_index_idr); DEFINE_MUTEX(dnbd3_index_mutex); static unsigned int max_devs = NUMBER_DEVICES; -static struct dnbd3_device *device; +static struct dnbd3_device *device = NULL; int major; /** @@ -350,8 +350,20 @@ out_free_dnbd3: */ static int __init dnbd3_init(void) { - int i; - debug("starting kernel module"); + int i, retval; + debug("initializing dnbd3 kernel module"); + + if (max_devs <= 0 || max_devs >= 256) { + error("max_devs must be between 1 and 255"); + return -EINVAL; + } + + device = kcalloc(max_devs, sizeof(*device), GFP_KERNEL); + if (!device) { + error("failed to allocate memory for dnbd3 device structs"); + retval = -ENOMEM; + goto error; + } /* * allocate a workqueue/thread for this modul @@ -361,28 +373,20 @@ static int __init dnbd3_init(void) */ dnbd3_wq = alloc_workqueue("kdnbd3", WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND, 0); - - if (max_devs < 0) { - error("max_devs must be >= 0"); - return -EINVAL; - } - - - device = kcalloc(max_devs, sizeof(*device), GFP_KERNEL); - if (!device) { - error("failed to create dnbd3 device"); - return -ENOMEM; + if (!dnbd3_wq) { + error("error allocating workqueue"); + retval = -ENOMEM; + goto error; } // initialize block device major = register_blkdev(0, "dnbd3"); if (major == 0) { error("register_blkdev failed"); - return -EIO; + retval = -EIO; + goto error; } - debug("kernel module loaded. Machine type: " ENDIAN_MODE); - // add MAX_NUMBER_DEVICES devices mutex_lock(&dnbd3_index_mutex); for (i = 0; i < max_devs; i++) { @@ -393,6 +397,13 @@ static int __init dnbd3_init(void) info("init successful (%i devices)", max_devs); return 0; +error: + if (device) { + kfree(device); + } + if (dnbd3_wq) { + destroy_workqueue(dnbd3_wq); + } } /** @@ -465,7 +476,6 @@ static void __exit dnbd3_exit(void) unregister_blkdev(major, "dnbd3"); kfree(device); - destroy_workqueue(dnbd3_wq); info("stopped kernel module"); -- cgit v1.2.3-55-g7522