linux-staging.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] staging: fbtft: cleanup fbtft_framebuffer_alloc()
@ 2025-06-28  4:59 Abdun Nihaal
  2025-06-28  4:59 ` [PATCH v2 1/2] staging: fbtft: fix potential memory leak in fbtft_framebuffer_alloc() Abdun Nihaal
  2025-06-28  4:59 ` [PATCH v2 2/2] staging: fbtft: cleanup error handling " Abdun Nihaal
  0 siblings, 2 replies; 5+ messages in thread
From: Abdun Nihaal @ 2025-06-28  4:59 UTC (permalink / raw)
  To: andy
  Cc: Abdun Nihaal, dan.carpenter, gregkh, lorenzo.stoakes, tzimmermann,
	riyandhiman14, willy, notro, thomas.petazzoni, dri-devel,
	linux-fbdev, linux-staging, linux-kernel

v2:
- Change the earlier patch to also handle the error code returned by
  fb_deferred_io_init() and update Fixes tag to point to the commit that
  introduced the memory allocation (which leads to leak).
- Add second patch to make the error handling order symmetric to
  fbtft_framebuffer_release() and also remove managed allocation for
  txbuf as suggested by Andy and Dan.

Link to v1: https://lore.kernel.org/all/20250626172412.18355-1-abdun.nihaal@gmail.com/

Abdun Nihaal (2):
  staging: fbtft: fix potential memory leak in fbtft_framebuffer_alloc()
  staging: fbtft: cleanup error handling in fbtft_framebuffer_alloc()

 drivers/staging/fbtft/fbtft-core.c | 39 +++++++++++++++++-------------
 1 file changed, 22 insertions(+), 17 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] staging: fbtft: fix potential memory leak in fbtft_framebuffer_alloc()
  2025-06-28  4:59 [PATCH v2 0/2] staging: fbtft: cleanup fbtft_framebuffer_alloc() Abdun Nihaal
@ 2025-06-28  4:59 ` Abdun Nihaal
  2025-06-28  4:59 ` [PATCH v2 2/2] staging: fbtft: cleanup error handling " Abdun Nihaal
  1 sibling, 0 replies; 5+ messages in thread
From: Abdun Nihaal @ 2025-06-28  4:59 UTC (permalink / raw)
  To: andy
  Cc: Abdun Nihaal, dan.carpenter, gregkh, lorenzo.stoakes, tzimmermann,
	riyandhiman14, willy, notro, thomas.petazzoni, dri-devel,
	linux-fbdev, linux-staging, linux-kernel

After commit 56c134f7f1b5 ("fbdev: Track deferred-I/O pages in pageref
struct"), fb_deferred_io_init() allocates memory for info->pagerefs as
well as return an error code on failure. However the error code is
ignored here and the memory allocated could leak because of not calling
fb_deferred_io_cleanup() on the error path.

Fix them by adding the cleanup function on the error path, and handling
the error code returned by fb_deferred_io_init().

Fixes: 56c134f7f1b5 ("fbdev: Track deferred-I/O pages in pageref struct")
Signed-off-by: Abdun Nihaal <abdun.nihaal@gmail.com>
---
v1->v2:
- Handle the error code returned by fb_deferred_io_init correctly
- Update Fixes tag to point to the commit that introduced the memory
  allocation which leads to the leak.

 drivers/staging/fbtft/fbtft-core.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index da9c64152a60..8538b6bab6a5 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -612,7 +612,8 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 	info->fix.line_length =    width * bpp / 8;
 	info->fix.accel =          FB_ACCEL_NONE;
 	info->fix.smem_len =       vmem_size;
-	fb_deferred_io_init(info);
+	if (fb_deferred_io_init(info))
+		goto release_framebuf;
 
 	info->var.rotate =         pdata->rotate;
 	info->var.xres =           width;
@@ -652,7 +653,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 	if (par->gamma.curves && gamma) {
 		if (fbtft_gamma_parse_str(par, par->gamma.curves, gamma,
 					  strlen(gamma)))
-			goto release_framebuf;
+			goto cleanup_deferred;
 	}
 
 	/* Transmit buffer */
@@ -669,7 +670,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 	if (txbuflen > 0) {
 		txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
 		if (!txbuf)
-			goto release_framebuf;
+			goto cleanup_deferred;
 		par->txbuf.buf = txbuf;
 		par->txbuf.len = txbuflen;
 	}
@@ -691,6 +692,8 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 
 	return info;
 
+cleanup_deferred:
+	fb_deferred_io_cleanup(info);
 release_framebuf:
 	framebuffer_release(info);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] staging: fbtft: cleanup error handling in fbtft_framebuffer_alloc()
  2025-06-28  4:59 [PATCH v2 0/2] staging: fbtft: cleanup fbtft_framebuffer_alloc() Abdun Nihaal
  2025-06-28  4:59 ` [PATCH v2 1/2] staging: fbtft: fix potential memory leak in fbtft_framebuffer_alloc() Abdun Nihaal
@ 2025-06-28  4:59 ` Abdun Nihaal
  2025-06-28 19:58   ` Andy Shevchenko
  1 sibling, 1 reply; 5+ messages in thread
From: Abdun Nihaal @ 2025-06-28  4:59 UTC (permalink / raw)
  To: andy
  Cc: Abdun Nihaal, dan.carpenter, gregkh, lorenzo.stoakes, tzimmermann,
	riyandhiman14, willy, notro, thomas.petazzoni, dri-devel,
	linux-fbdev, linux-staging, linux-kernel, Andy Shevchenko

The error handling in fbtft_framebuffer_alloc() mixes managed allocation
and plain allocation, and performs error handling in an order different
from the order in fbtft_framebuffer_release().

Fix them by moving vmem allocation closer to where it is used, and using
plain kzalloc() for txbuf allocation.

Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Suggested-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Abdun Nihaal <abdun.nihaal@gmail.com>
---
Newly added in v2

 drivers/staging/fbtft/fbtft-core.c | 32 ++++++++++++++++--------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 8538b6bab6a5..f6a147cf0717 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -568,18 +568,13 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 		height = display->height;
 	}
 
-	vmem_size = display->width * display->height * bpp / 8;
-	vmem = vzalloc(vmem_size);
-	if (!vmem)
-		goto alloc_fail;
-
 	fbdefio = devm_kzalloc(dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
 	if (!fbdefio)
-		goto alloc_fail;
+		return NULL;
 
 	buf = devm_kzalloc(dev, 128, GFP_KERNEL);
 	if (!buf)
-		goto alloc_fail;
+		return NULL;
 
 	if (display->gamma_num && display->gamma_len) {
 		gamma_curves = devm_kcalloc(dev,
@@ -588,12 +583,17 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 					    sizeof(gamma_curves[0]),
 					    GFP_KERNEL);
 		if (!gamma_curves)
-			goto alloc_fail;
+			return NULL;
 	}
 
 	info = framebuffer_alloc(sizeof(struct fbtft_par), dev);
 	if (!info)
-		goto alloc_fail;
+		return NULL;
+
+	vmem_size = display->width * display->height * bpp / 8;
+	vmem = vzalloc(vmem_size);
+	if (!vmem)
+		goto release_framebuf;
 
 	info->screen_buffer = vmem;
 	info->fbops = &fbtft_ops;
@@ -613,7 +613,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 	info->fix.accel =          FB_ACCEL_NONE;
 	info->fix.smem_len =       vmem_size;
 	if (fb_deferred_io_init(info))
-		goto release_framebuf;
+		goto release_screen_buffer;
 
 	info->var.rotate =         pdata->rotate;
 	info->var.xres =           width;
@@ -668,7 +668,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 #endif
 
 	if (txbuflen > 0) {
-		txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
+		txbuf = kzalloc(txbuflen, GFP_KERNEL);
 		if (!txbuf)
 			goto cleanup_deferred;
 		par->txbuf.buf = txbuf;
@@ -694,12 +694,10 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 
 cleanup_deferred:
 	fb_deferred_io_cleanup(info);
+release_screen_buffer:
+	vfree(info->screen_buffer);
 release_framebuf:
 	framebuffer_release(info);
-
-alloc_fail:
-	vfree(vmem);
-
 	return NULL;
 }
 EXPORT_SYMBOL(fbtft_framebuffer_alloc);
@@ -712,6 +710,10 @@ EXPORT_SYMBOL(fbtft_framebuffer_alloc);
  */
 void fbtft_framebuffer_release(struct fb_info *info)
 {
+	struct fbtft_par *par = info->par;
+
+	if (par->txbuf.len > 0)
+		kfree(par->txbuf.buf);
 	fb_deferred_io_cleanup(info);
 	vfree(info->screen_buffer);
 	framebuffer_release(info);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] staging: fbtft: cleanup error handling in fbtft_framebuffer_alloc()
  2025-06-28  4:59 ` [PATCH v2 2/2] staging: fbtft: cleanup error handling " Abdun Nihaal
@ 2025-06-28 19:58   ` Andy Shevchenko
  2025-06-29 14:23     ` Abdun Nihaal
  0 siblings, 1 reply; 5+ messages in thread
From: Andy Shevchenko @ 2025-06-28 19:58 UTC (permalink / raw)
  To: Abdun Nihaal
  Cc: andy, dan.carpenter, gregkh, lorenzo.stoakes, tzimmermann,
	riyandhiman14, willy, notro, thomas.petazzoni, dri-devel,
	linux-fbdev, linux-staging, linux-kernel, Andy Shevchenko

On Sat, Jun 28, 2025 at 7:59 AM Abdun Nihaal <abdun.nihaal@gmail.com> wrote:
>
> The error handling in fbtft_framebuffer_alloc() mixes managed allocation
> and plain allocation, and performs error handling in an order different
> from the order in fbtft_framebuffer_release().
>
> Fix them by moving vmem allocation closer to where it is used, and using
> plain kzalloc() for txbuf allocation.

...

> +       struct fbtft_par *par = info->par;
> +
> +       if (par->txbuf.len > 0)

Do we really need this check? If txbuf.buf is kept NULL (please, check
this), the kfree() is NULL-aware.

> +               kfree(par->txbuf.buf);
>         fb_deferred_io_cleanup(info);
>         vfree(info->screen_buffer);
>         framebuffer_release(info);


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] staging: fbtft: cleanup error handling in fbtft_framebuffer_alloc()
  2025-06-28 19:58   ` Andy Shevchenko
@ 2025-06-29 14:23     ` Abdun Nihaal
  0 siblings, 0 replies; 5+ messages in thread
From: Abdun Nihaal @ 2025-06-29 14:23 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: andy, dan.carpenter, gregkh, lorenzo.stoakes, tzimmermann,
	riyandhiman14, willy, notro, thomas.petazzoni, dri-devel,
	linux-fbdev, linux-staging, linux-kernel, Andy Shevchenko

On Sat, Jun 28, 2025 at 10:58:20PM +0300, Andy Shevchenko wrote:
> > +       struct fbtft_par *par = info->par;
> > +
> > +       if (par->txbuf.len > 0)
> 
> Do we really need this check? If txbuf.buf is kept NULL (please, check
> this), the kfree() is NULL-aware.

I assumed that the par->txbuf.buf may be uninitialized, but I checked it
now and it uses kzalloc to allocate, so it must be NULL to begin with.

I'll remove the check, and send a v3.

Regards,
Nihaal

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-06-29 14:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-28  4:59 [PATCH v2 0/2] staging: fbtft: cleanup fbtft_framebuffer_alloc() Abdun Nihaal
2025-06-28  4:59 ` [PATCH v2 1/2] staging: fbtft: fix potential memory leak in fbtft_framebuffer_alloc() Abdun Nihaal
2025-06-28  4:59 ` [PATCH v2 2/2] staging: fbtft: cleanup error handling " Abdun Nihaal
2025-06-28 19:58   ` Andy Shevchenko
2025-06-29 14:23     ` Abdun Nihaal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).