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

Message ID 20230309160201.5163-99-tzimmermann@suse.de
State New
Headers
Series fbdev: Fix memory leak in option parsing |

Commit Message

Thomas Zimmermann March 9, 2023, 4:01 p.m. UTC
  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@suse.de>
---
 drivers/staging/sm750fb/sm750.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
  

Patch

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);