Message ID | 20230306160016.4459-23-tzimmermann@suse.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | fbdev: Fix memory leak in option parsing | expand |
On Mon, Mar 6, 2023 at 10:01 AM Thomas Zimmermann <tzimmermann@suse.de> wrote: > > Assume that the driver does not own the option string or its substrings > and hence duplicate the option string for the video mode. The driver only > parses the option string once as part of module initialization, so use > a static buffer to store the duplicated mode option. Linux automatically > frees the memory upon releasing the module. So after module_init is finished, mode_option_buf[] no longer exists? > + static char mode_option_buf[256]; > + int ret; > + > + ret = snprintf(mode_option_buf, sizeof(mode_option_buf), "%s", opt); > + if (WARN(ret < 0, "fsl-diu-fb: ignoring invalid option, ret=%d\n", ret)) > + continue; > + if (WARN(ret >= sizeof(mode_option_buf), "fsl-diu-fb: option too long\n")) > + continue; > + fb_mode = mode_option_buf; If so, then I'm not sure that's going to work. fb_mode is used after module_init, in install_fb(), which is called by fsl_diu_probe().
Hi Am 06.03.23 um 21:04 schrieb Timur Tabi: > On Mon, Mar 6, 2023 at 10:01 AM Thomas Zimmermann <tzimmermann@suse.de> wrote: >> >> Assume that the driver does not own the option string or its substrings >> and hence duplicate the option string for the video mode. The driver only >> parses the option string once as part of module initialization, so use >> a static buffer to store the duplicated mode option. Linux automatically >> frees the memory upon releasing the module. > > So after module_init is finished, mode_option_buf[] no longer exists? Does the __init attribute on a function affect the static variables in that function? Best regards Thomas > >> + static char mode_option_buf[256]; >> + int ret; >> + >> + ret = snprintf(mode_option_buf, sizeof(mode_option_buf), "%s", opt); >> + if (WARN(ret < 0, "fsl-diu-fb: ignoring invalid option, ret=%d\n", ret)) >> + continue; >> + if (WARN(ret >= sizeof(mode_option_buf), "fsl-diu-fb: option too long\n")) >> + continue; >> + fb_mode = mode_option_buf; > > If so, then I'm not sure that's going to work. fb_mode is used after > module_init, in install_fb(), which is called by fsl_diu_probe().
On Tue, Mar 7, 2023 at 2:28 AM Thomas Zimmermann <tzimmermann@suse.de> wrote: > > So after module_init is finished, mode_option_buf[] no longer exists? > > Does the __init attribute on a function affect the static variables in > that function? That is an excellent question. https://stackoverflow.com/questions/64558614/what-happens-to-local-static-identifiers-in-init-function I don't think the compiler is naturally aware of whatever section a variable or function is placed in, so it can't really know that mode_option_buf[] is suppose to have a limited lifetime. Either way, the code seems wrong. If mode_option_buf[] is marked as __initdata, then it will disappear before the probe() function is called. If mode_option_buf[] remains resident, then we are wasting 256 bytes.
Hi Am 08.03.23 um 17:26 schrieb Timur Tabi: > On Tue, Mar 7, 2023 at 2:28 AM Thomas Zimmermann <tzimmermann@suse.de> wrote: >>> So after module_init is finished, mode_option_buf[] no longer exists? >> >> Does the __init attribute on a function affect the static variables in >> that function? > > That is an excellent question. > > https://stackoverflow.com/questions/64558614/what-happens-to-local-static-identifiers-in-init-function > > I don't think the compiler is naturally aware of whatever section a > variable or function is placed in, so it can't really know that > mode_option_buf[] is suppose to have a limited lifetime. > > Either way, the code seems wrong. If mode_option_buf[] is marked as > __initdata, then it will disappear before the probe() function is > called. > > If mode_option_buf[] remains resident, then we are wasting 256 bytes. I'm preparing an update to this series. The string will be allocated and freed with kstrdup() and kfree(). So these issues should be resolved then. Best regards Thomas
diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c index e332017c6af6..e01281959062 100644 --- a/drivers/video/fbdev/fsl-diu-fb.c +++ b/drivers/video/fbdev/fsl-diu-fb.c @@ -1858,8 +1858,17 @@ static int __init fsl_diu_setup(char *options) } else if (!strncmp(opt, "bpp=", 4)) { if (!kstrtoul(opt + 4, 10, &val)) default_bpp = val; - } else - fb_mode = opt; + } else { + static char mode_option_buf[256]; + int ret; + + ret = snprintf(mode_option_buf, sizeof(mode_option_buf), "%s", opt); + if (WARN(ret < 0, "fsl-diu-fb: ignoring invalid option, ret=%d\n", ret)) + continue; + if (WARN(ret >= sizeof(mode_option_buf), "fsl-diu-fb: option too long\n")) + continue; + fb_mode = mode_option_buf; + } } return 0;
Assume that the driver does not own the option string or its substrings and hence duplicate the option string for the video mode. The driver only parses the option string once as part of module initialization, so use a static buffer to store the duplicated mode option. Linux automatically frees the memory upon releasing the module. Done in preparation of switching the driver to struct option_iter and constifying the option string. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/video/fbdev/fsl-diu-fb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)