* FAILED: patch "[PATCH] fbdev: serialize mode sysfs access with lock_fb_info()" failed to apply to 7.1-stable tree
@ 2026-08-20 11:01 gregkh
2026-08-24 18:10 ` [PATCH 7.1.y 1/2] fbdev: Wrap user-invoked calls to fb_set_var() in helper Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2026-08-20 11:01 UTC (permalink / raw)
To: mlbnkm1, deller; +Cc: stable
The patch below does not apply to the 7.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.1.y
git checkout FETCH_HEAD
git cherry-pick -x 061db6b7a910b8378f3b2df64f8c0a3ddc6e85f2
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026082036-chili-glider-8a45@gregkh' --subject-prefix 'PATCH 7.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 061db6b7a910b8378f3b2df64f8c0a3ddc6e85f2 Mon Sep 17 00:00:00 2001
From: Melbin K Mathew <mlbnkm1@gmail.com>
Date: Thu, 2 Jul 2026 01:42:48 +0200
Subject: [PATCH] fbdev: serialize mode sysfs access with lock_fb_info()
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 # v7.1+
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index af21dc5052df..d3d60c555bb8 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;
}
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 7.1.y 1/2] fbdev: Wrap user-invoked calls to fb_set_var() in helper
2026-08-20 11:01 FAILED: patch "[PATCH] fbdev: serialize mode sysfs access with lock_fb_info()" failed to apply to 7.1-stable tree gregkh
@ 2026-08-24 18:10 ` Sasha Levin
2026-08-24 18:10 ` [PATCH 7.1.y 2/2] fbdev: serialize mode sysfs access with lock_fb_info() Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-08-24 18:10 UTC (permalink / raw)
To: stable; +Cc: Thomas Zimmermann, Helge Deller, Sasha Levin
From: Thomas Zimmermann <tzimmermann@suse.de>
[ Upstream commit 6f611e5e5f3327cf2e2daabe6ee5acac58cc784e ]
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>
Stable-dep-of: 061db6b7a910 ("fbdev: serialize mode sysfs access with lock_fb_info()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8d..54f926fb411bd 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 666293f0864f3..6691e0f8ff41a 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2706,7 +2706,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2734,7 +2733,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 0ea182314b89b..a3af47e103b0d 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -349,6 +349,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index fa12e5da9bbdc..49d886c2dd7c8 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -20,9 +20,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a67..1376d19b19aeb 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e5134..e8324b01700f6 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c6..88680a7cabd55 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 7.1.y 2/2] fbdev: serialize mode sysfs access with lock_fb_info()
2026-08-24 18:10 ` [PATCH 7.1.y 1/2] fbdev: Wrap user-invoked calls to fb_set_var() in helper Sasha Levin
@ 2026-08-24 18:10 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-08-24 18:10 UTC (permalink / raw)
To: stable; +Cc: Melbin K Mathew, Helge Deller, Sasha Levin
From: Melbin K Mathew <mlbnkm1@gmail.com>
[ Upstream commit 061db6b7a910b8378f3b2df64f8c0a3ddc6e85f2 ]
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 # v7.1+
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
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 49d886c2dd7c8..c32dd71a38e1c 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -13,19 +13,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,
@@ -66,6 +71,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);
@@ -73,12 +81,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;
}
@@ -86,11 +104,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,
@@ -138,12 +165,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.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-24 18:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 11:01 FAILED: patch "[PATCH] fbdev: serialize mode sysfs access with lock_fb_info()" failed to apply to 7.1-stable tree gregkh
2026-08-24 18:10 ` [PATCH 7.1.y 1/2] fbdev: Wrap user-invoked calls to fb_set_var() in helper Sasha Levin
2026-08-24 18:10 ` [PATCH 7.1.y 2/2] fbdev: serialize mode sysfs access with lock_fb_info() Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox