[PATCH v2 098/101] staging/sm750fb: Release g_settings in module-exit function

From: Thomas Zimmermann
Date: Thu Mar 09 2023 - 11:11:35 EST


Free g_settings in module-exit function for symmetry with its
allocation in module-init function. Fixes a possible undefined
dereference of the pointer.

The string g_settings is initialized ifrom within the module-init
function lynxfb_init() and used from within the PCI probe function.
It is later freed in the PCI device's remove function. Probing another
PCI device afterwards accesses g_settings in an undefined state.

Fix this by freeing g_settings in lynxfb_exit(). Also streamline the
code that creates g_settings in the first place.

Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx>
---
drivers/staging/sm750fb/sm750.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index effc7fcc3703..fa8ae20bb688 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -1093,13 +1093,12 @@ static void lynxfb_pci_remove(struct pci_dev *pdev)

iounmap(sm750_dev->pvReg);
iounmap(sm750_dev->pvMem);
- kfree(g_settings);
}

static int __init lynxfb_setup(char *options)
{
- int len;
- char *opt, *tmp;
+ size_t len;
+ char *opt, *outbuf;

if (!options || !*options) {
pr_warn("no options.\n");
@@ -1109,11 +1108,10 @@ static int __init lynxfb_setup(char *options)
pr_info("options:%s\n", options);

len = strlen(options) + 1;
- g_settings = kzalloc(len, GFP_KERNEL);
- if (!g_settings)
+ outbuf = kzalloc(len, GFP_KERNEL);
+ if (!outbuf)
return -ENOMEM;
-
- tmp = g_settings;
+ g_settings = outbuf;

/*
* Notes:
@@ -1133,12 +1131,11 @@ static int __init lynxfb_setup(char *options)
} else if (!strncmp(opt, "dual", strlen("dual"))) {
g_dualview = 1;
} else {
- strcat(tmp, opt);
- tmp += strlen(opt);
- if (options)
- *tmp++ = ':';
- else
- *tmp++ = 0;
+ if (outbuf != g_settings)
+ *outbuf++ = ':'; // add separator
+ len = strlen(opt);
+ memcpy(outbuf, opt, len);
+ outbuf += len;
}
}

@@ -1186,6 +1183,7 @@ module_init(lynxfb_init);
static void __exit lynxfb_exit(void)
{
pci_unregister_driver(&lynxfb_driver);
+ kfree(g_settings);
}
module_exit(lynxfb_exit);

--
2.39.2