* [PATCH] fbdev: protect mode sysfs reads with lock_fb_info()
@ 2026-07-01 22:17 Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Melbin K Mathew @ 2026-07-01 22:17 UTC (permalink / raw)
To: deller
Cc: linux-fbdev, dri-devel, linux-kernel, security, Melbin K Mathew,
stable
show_mode() dereferences fb_info->mode and show_modes() walks
fb_info->modelist without holding lock_fb_info(). store_modes() takes
lock_fb_info() while replacing the modelist and freeing the old one.
A concurrent reader can load a pointer to an old modelist entry before
store_modes() frees it, then dereference freed memory in mode_string().
Take lock_fb_info() in both show_mode() and show_modes() to serialize
with store_modes(). In show_mode(), copy the mode to the stack and
format the stack copy after dropping the lock.
Impact: local kernel UAF read when a privileged writer races with
sysfs readers of /sys/class/graphics/fb*/mode and modes.
Cc: stable@vger.kernel.org
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
---
A userspace reproducer triggering the race is available to maintainers on request.
drivers/video/fbdev/core/fbsysfs.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index ea196603c7..6bdb25f7be 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -82,11 +82,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, 0, fb_info->mode);
+ return mode_string(buf, 0, &mode);
}
static ssize_t store_modes(struct device *device,
@@ -134,10 +143,13 @@ 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, i, mode);
}
+ unlock_fb_info(fb_info);
+
return i;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues
2026-07-01 22:17 [PATCH] fbdev: protect mode sysfs reads with lock_fb_info() Melbin K Mathew
@ 2026-07-01 23:17 ` Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 0/3] " Melbin K Mathew
` (3 more replies)
2026-07-01 23:17 ` [PATCH v2 1/2] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 2/2] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
2 siblings, 4 replies; 8+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:17 UTC (permalink / raw)
To: deller; +Cc: linux-fbdev, dri-devel, linux-kernel, Melbin K Mathew
This v2 addresses the remaining fbdev mode sysfs lifetime issues noted
during review.
Patch 1 bounds mode sysfs output so show_modes() cannot advance the
sysfs buffer offset past PAGE_SIZE. mode_string() is given a size
parameter and switched to scnprintf().
Patch 2 serializes mode sysfs access with lock_fb_info(), including
store_mode(), show_mode(), and show_modes(), so these paths cannot race
with store_modes() while it replaces and frees the old modelist.
Changes in v2:
- Add bounds handling for mode_string()/show_modes().
- Extend locking to store_mode() via activate_locked().
- Keep show_mode() using a stack copy after dropping lock_fb_info().
- Avoid overclaiming unprivileged impact in the commit text.
Melbin K Mathew (2):
fbdev: bound mode sysfs output to the sysfs buffer
fbdev: serialize mode sysfs access with lock_fb_info()
drivers/video/fbdev/core/fbsysfs.c | 59 ++++++++++++++++++++++++------
1 file changed, 47 insertions(+), 12 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/2] fbdev: bound mode sysfs output to the sysfs buffer
2026-07-01 22:17 [PATCH] fbdev: protect mode sysfs reads with lock_fb_info() Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
@ 2026-07-01 23:17 ` Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 2/2] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
2 siblings, 0 replies; 8+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:17 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] 8+ messages in thread
* [PATCH v2 2/2] fbdev: serialize mode sysfs access with lock_fb_info()
2026-07-01 22:17 [PATCH] fbdev: protect mode sysfs reads with lock_fb_info() Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 1/2] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
@ 2026-07-01 23:17 ` Melbin K Mathew
2 siblings, 0 replies; 8+ messages in thread
From: Melbin K Mathew @ 2026-07-01 23:17 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] 8+ messages in thread
* [PATCH v3 0/3] fbdev: fix mode sysfs lifetime and bounds issues
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
@ 2026-07-01 23:42 ` Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ 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
This v3 adds a patch to clear fb_info->mode before deleting a
videomode through FBIOPUT_VSCREENINFO with FB_ACTIVATE_INV_MODE.
Patch 1 bounds mode sysfs output so show_modes() cannot advance the
sysfs buffer offset past PAGE_SIZE.
Patch 2 clears fb_info->mode before fb_delete_videomode() when it
matches the mode being removed via the FBIOPUT_VSCREENINFO ioctl.
Patch 3 serializes mode sysfs access with lock_fb_info(), including
store_mode(), show_mode(), and show_modes().
Changes in v3:
- Add patch to clear fb_info->mode in fb_set_var() INV_MODE path.
Melbin K Mathew (3):
fbdev: bound mode sysfs output to the sysfs buffer
fbdev: clear fb_info->mode before deleting a videomode
fbdev: serialize mode sysfs access with lock_fb_info()
drivers/video/fbdev/core/fbmem.c | 5 ++-
drivers/video/fbdev/core/fbsysfs.c | 59 ++++++++++++++++++++++++------
2 files changed, 51 insertions(+), 13 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/3] fbdev: bound mode sysfs output to the sysfs buffer
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 0/3] " Melbin K Mathew
@ 2026-07-01 23:42 ` 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 ` [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
3 siblings, 0 replies; 8+ 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] 8+ messages in thread
* [PATCH v3 2/3] fbdev: clear fb_info->mode before deleting a videomode
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 0/3] " Melbin K Mathew
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
3 siblings, 0 replies; 8+ 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] 8+ messages in thread
* [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info()
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
` (2 preceding siblings ...)
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
3 siblings, 0 replies; 8+ 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] 8+ messages in thread
end of thread, other threads:[~2026-07-01 23:43 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 22:17 [PATCH] fbdev: protect mode sysfs reads with lock_fb_info() Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 0/2] fbdev: fix mode sysfs lifetime and bounds issues Melbin K Mathew
2026-07-01 23:42 ` [PATCH v3 0/3] " Melbin K Mathew
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 ` [PATCH v3 3/3] fbdev: serialize mode sysfs access with lock_fb_info() Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 1/2] fbdev: bound mode sysfs output to the sysfs buffer Melbin K Mathew
2026-07-01 23:17 ` [PATCH v2 2/2] 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