* [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer
[not found] <20260701231706.234715-1-mlbnkm1@gmail.com>
@ 2026-07-01 23:42 ` Melbin K Mathew
2026-07-18 20:04 ` Helge Deller
2026-07-01 23:42 ` [PATCH v3 2/3] fbdev: clear fb_info->mode before deleting a videomode Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
2 siblings, 1 reply; 4+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:42 UTC (permalink / raw)
To: deller; +Cc: linux-fbdev, dri-devel, linux-kernel, Melbin K Mathew, stable
mode_string() uses snprintf() which can return a value larger than the
remaining buffer space. show_modes() accumulates the return value into i
without checking whether i has reached PAGE_SIZE, causing the offset to
advance past the sysfs buffer if the modelist is long enough.
Add a size parameter to mode_string() and use scnprintf() to return
only the bytes actually written. Add an early return when offset
already exceeds the buffer. In show_modes(), stop accumulating once
the buffer is full.
Cc: stable@vger.kernel.org
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
---
drivers/video/fbdev/core/fbsysfs.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index ea196603c7..af21dc5052 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -27,12 +27,15 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
return 0;
}
-static int mode_string(char *buf, unsigned int offset,
+static int mode_string(char *buf, size_t size, unsigned int offset,
const struct fb_videomode *mode)
{
char m = 'U';
char v = 'p';
+ if (offset >= size)
+ return 0;
+
if (mode->flag & FB_MODE_IS_DETAILED)
m = 'D';
if (mode->flag & FB_MODE_IS_VESA)
@@ -45,7 +48,7 @@ static int mode_string(char *buf, unsigned int offset,
if (mode->vmode & FB_VMODE_DOUBLE)
v = 'd';
- return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d%c-%d\n",
+ return scnprintf(&buf[offset], size - offset, "%c:%dx%d%c-%d\n",
m, mode->xres, mode->yres, v, mode->refresh);
}
@@ -64,7 +67,7 @@ static ssize_t store_mode(struct device *device, struct device_attribute *attr,
list_for_each_entry(modelist, &fb_info->modelist, list) {
mode = &modelist->mode;
- i = mode_string(mstr, 0, mode);
+ i = mode_string(mstr, sizeof(mstr), 0, mode);
if (strncmp(mstr, buf, max(count, i)) == 0) {
var = fb_info->var;
@@ -86,7 +89,7 @@ static ssize_t show_mode(struct device *device, struct device_attribute *attr,
if (!fb_info->mode)
return 0;
- return mode_string(buf, 0, fb_info->mode);
+ return mode_string(buf, PAGE_SIZE, 0, fb_info->mode);
}
static ssize_t store_modes(struct device *device,
@@ -136,7 +139,9 @@ static ssize_t show_modes(struct device *device, struct device_attribute *attr,
i = 0;
list_for_each_entry(modelist, &fb_info->modelist, list) {
mode = &modelist->mode;
- i += mode_string(buf, i, mode);
+ i += mode_string(buf, PAGE_SIZE, i, mode);
+ if (i >= PAGE_SIZE - 1)
+ break;
}
return i;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/3] fbdev: clear fb_info->mode before deleting a videomode
[not found] <20260701231706.234715-1-mlbnkm1@gmail.com>
2026-07-01 23:42 ` [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
@ 2026-07-01 23:42 ` Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
2 siblings, 0 replies; 4+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:42 UTC (permalink / raw)
To: deller; +Cc: linux-fbdev, dri-devel, linux-kernel, Melbin K Mathew, stable
fb_set_var() can delete a mode from info->modelist when userspace
passes FB_ACTIVATE_INV_MODE through FBIOPUT_VSCREENINFO. The code
checks that the mode being deleted is not the current info->var and
that fbcon is not using it, but it does not check fb_info->mode.
fb_info->mode may still point into the modelist entry being deleted.
If the entry is freed, later mode sysfs reads through show_mode() can
dereference a stale pointer.
Clear fb_info->mode before calling fb_delete_videomode() when it
matches the mode being removed.
Cc: stable@vger.kernel.org
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
---
drivers/video/fbdev/core/fbmem.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 2f1c56e5a7..c8aa163b0e 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -246,8 +246,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
ret = fb_mode_is_equal(&mode1, &mode2);
if (!ret) {
ret = fbcon_mode_deleted(info, &mode1);
- if (!ret)
+ if (!ret) {
+ if (info->mode && fb_mode_is_equal(info->mode, &mode1))
+ info->mode = NULL;
fb_delete_videomode(&mode1, &info->modelist);
+ }
}
return ret ? -EINVAL : 0;
--
2.39.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info()
[not found] <20260701231706.234715-1-mlbnkm1@gmail.com>
2026-07-01 23:42 ` [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 2/3] fbdev: clear fb_info->mode before deleting a videomode Melbin K Mathew
@ 2026-07-01 23:42 ` Melbin K Mathew
2 siblings, 0 replies; 4+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:42 UTC (permalink / raw)
To: deller; +Cc: linux-fbdev, dri-devel, linux-kernel, Melbin K Mathew, stable
show_mode(), show_modes(), and store_mode() access fb_info->modelist
and fb_info->mode without holding lock_fb_info(). store_modes() takes
lock_fb_info() while replacing the modelist and freeing the old one.
A concurrent reader or writer can load a pointer to an old modelist
entry before store_modes() frees it, then dereference freed memory or
store a stale freed pointer in fb_info->mode.
Take lock_fb_info() in show_mode(), show_modes(), and store_mode() to
serialize with store_modes(). In show_mode(), copy the mode to the
stack and format after dropping the lock. In store_mode(), split
activate() into a _locked variant to avoid double-locking, and hold
the locks for the modelist walk, mode conversion, activation, and
fb_info->mode assignment together.
Cc: stable@vger.kernel.org
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
---
drivers/video/fbdev/core/fbsysfs.c | 46 ++++++++++++++++++++++++------
1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index af21dc5052..d3d60c555b 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -12,19 +12,24 @@
#include "fb_internal.h"
#include "fbcon.h"
+static int activate_locked(struct fb_info *fb_info,
+ struct fb_var_screeninfo *var)
+{
+ var->activate |= FB_ACTIVATE_FORCE;
+ return fb_set_var_from_user(fb_info, var);
+}
+
static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
{
int err;
- var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var_from_user(fb_info, var);
+ err = activate_locked(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
- if (err)
- return err;
- return 0;
+
+ return err;
}
static int mode_string(char *buf, size_t size, unsigned int offset,
@@ -65,6 +70,9 @@ static ssize_t store_mode(struct device *device, struct device_attribute *attr,
memset(&var, 0, sizeof(var));
+ console_lock();
+ lock_fb_info(fb_info);
+
list_for_each_entry(modelist, &fb_info->modelist, list) {
mode = &modelist->mode;
i = mode_string(mstr, sizeof(mstr), 0, mode);
@@ -72,12 +80,22 @@ static ssize_t store_mode(struct device *device, struct device_attribute *attr,
var = fb_info->var;
fb_videomode_to_var(&var, mode);
- if ((err = activate(fb_info, &var)))
+ err = activate_locked(fb_info, &var);
+ if (err) {
+ unlock_fb_info(fb_info);
+ console_unlock();
return err;
+ }
fb_info->mode = mode;
+ unlock_fb_info(fb_info);
+ console_unlock();
return count;
}
}
+
+ unlock_fb_info(fb_info);
+ console_unlock();
+
return -EINVAL;
}
@@ -85,11 +103,20 @@ static ssize_t show_mode(struct device *device, struct device_attribute *attr,
char *buf)
{
struct fb_info *fb_info = dev_get_drvdata(device);
+ struct fb_videomode mode;
+ bool have_mode = false;
- if (!fb_info->mode)
+ lock_fb_info(fb_info);
+ if (fb_info->mode) {
+ mode = *fb_info->mode;
+ have_mode = true;
+ }
+ unlock_fb_info(fb_info);
+
+ if (!have_mode)
return 0;
- return mode_string(buf, PAGE_SIZE, 0, fb_info->mode);
+ return mode_string(buf, PAGE_SIZE, 0, &mode);
}
static ssize_t store_modes(struct device *device,
@@ -137,12 +164,15 @@ static ssize_t show_modes(struct device *device, struct device_attribute *attr,
const struct fb_videomode *mode;
i = 0;
+ lock_fb_info(fb_info);
list_for_each_entry(modelist, &fb_info->modelist, list) {
mode = &modelist->mode;
i += mode_string(buf, PAGE_SIZE, i, mode);
if (i >= PAGE_SIZE - 1)
break;
}
+ unlock_fb_info(fb_info);
+
return i;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer
2026-07-01 23:42 ` [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
@ 2026-07-18 20:04 ` Helge Deller
0 siblings, 0 replies; 4+ messages in thread
From: Helge Deller @ 2026-07-18 20:04 UTC (permalink / raw)
To: Melbin K Mathew; +Cc: linux-fbdev, dri-devel, linux-kernel, stable
On 7/2/26 01:42, Melbin K Mathew wrote:
> mode_string() uses snprintf() which can return a value larger than the
> remaining buffer space. show_modes() accumulates the return value into i
> without checking whether i has reached PAGE_SIZE, causing the offset to
> advance past the sysfs buffer if the modelist is long enough.
>
> Add a size parameter to mode_string() and use scnprintf() to return
> only the bytes actually written. Add an early return when offset
> already exceeds the buffer. In show_modes(), stop accumulating once
> the buffer is full.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
> ---
> drivers/video/fbdev/core/fbsysfs.c | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
I've applied the series to fbdev git tree for further testing.
Thanks!
Helge
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-18 20:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260701231706.234715-1-mlbnkm1@gmail.com>
2026-07-01 23:42 ` [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
2026-07-18 20:04 ` Helge Deller
2026-07-01 23:42 ` [PATCH v3 2/3] fbdev: clear fb_info->mode before deleting a videomode Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox