[PATCH 6.6.y 2/2] fbdev: hyperv_fb: Allow graceful removal of framebuffer
From: Artem Dinaburg
Date: Thu Oct 08 2026 - 15:14:28 EST
From: Saurabh Sengar <ssengar@xxxxxxxxxxxxxxxxxxx>
[ Upstream commit ea2f45ab0e53b255f72c85ccd99e2b394fc5fceb ]
When a Hyper-V framebuffer device is unbind, hyperv_fb driver tries to
release the framebuffer forcefully. If this framebuffer is in use it
produce the following WARN and hence this framebuffer is never released.
[ 44.111220] WARNING: CPU: 35 PID: 1882 at drivers/video/fbdev/core/fb_info.c:70 framebuffer_release+0x2c/0x40
< snip >
[ 44.111289] Call Trace:
[ 44.111290] <TASK>
[ 44.111291] ? show_regs+0x6c/0x80
[ 44.111295] ? __warn+0x8d/0x150
[ 44.111298] ? framebuffer_release+0x2c/0x40
[ 44.111300] ? report_bug+0x182/0x1b0
[ 44.111303] ? handle_bug+0x6e/0xb0
[ 44.111306] ? exc_invalid_op+0x18/0x80
[ 44.111308] ? asm_exc_invalid_op+0x1b/0x20
[ 44.111311] ? framebuffer_release+0x2c/0x40
[ 44.111313] ? hvfb_remove+0x86/0xa0 [hyperv_fb]
[ 44.111315] vmbus_remove+0x24/0x40 [hv_vmbus]
[ 44.111323] device_remove+0x40/0x80
[ 44.111325] device_release_driver_internal+0x20b/0x270
[ 44.111327] ? bus_find_device+0xb3/0xf0
Fix this by moving the release of framebuffer and assosiated memory
to fb_ops.fb_destroy function, so that framebuffer framework handles
it gracefully.
While we fix this, also replace manual registrations/unregistration of
framebuffer with devm_register_framebuffer.
[ Backport to 6.6.y: retain explicit unregister_framebuffer(), but call it
only after delayed work and the VMBus channel are shut down; defer
hvfb_putmem()/framebuffer_release() to fb_destroy. This preserves the
upstream teardown order without requiring devm_register_framebuffer(). ]
Fixes: 68a2d20b79b1 ("drivers/video: add Hyper-V Synthetic Video Frame Buffer Driver")
Signed-off-by: Saurabh Sengar <ssengar@xxxxxxxxxxxxxxxxxxx>
Reviewed-by: Michael Kelley <mhklinux@xxxxxxxxxxx>
Tested-by: Michael Kelley <mhklinux@xxxxxxxxxxx>
Link: https://lore.kernel.org/r/1740845791-19977-3-git-send-email-ssengar@xxxxxxxxxxxxxxxxxxx
Signed-off-by: Wei Liu <wei.liu@xxxxxxxxxx>
Message-ID: <1740845791-19977-3-git-send-email-ssengar@xxxxxxxxxxxxxxxxxxx>
Assisted-by: LLM
Signed-off-by: Artem Dinaburg <artem@xxxxxxxxxxxxxxx>
---
This is patch 2 of 2 in the ordered 6.6.y backport series.
This change addresses CVE-2025-21976. The target remove path unregisters the
framebuffer before completing driver cleanup and then directly frees its
memory even when another open reference keeps the framebuffer alive.
This needed a target-specific adjustment; I called it out in the bracketed
backport note above.
The fix is already present in 6.12.y, 6.18.y, and 7.2.y, but not in 6.6.y.
This fix also affects 6.1.y, which will need a separate backport; this
submission contains only the 6.6.y patch.
drivers/video/fbdev/hyperv_fb.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 80e6d9682179..e0d68953aa1a 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -283,6 +283,8 @@ static uint screen_depth;
static uint screen_fb_size;
static uint dio_fb_size; /* FB size for deferred IO */
+static void hvfb_putmem(struct fb_info *info);
+
/* Send message to Hyper-V host */
static inline int synthvid_send(struct hv_device *hdev,
struct synthvid_msg *msg)
@@ -887,6 +889,17 @@ static void hvfb_cfb_imageblit(struct fb_info *p,
image->width, image->height);
}
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
+ * of unregister_framebuffer() or fb_release(). Do any cleanup related to
+ * framebuffer here.
+ */
+static void hvfb_destroy(struct fb_info *info)
+{
+ hvfb_putmem(info);
+ framebuffer_release(info);
+}
+
static const struct fb_ops hvfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = hvfb_check_var,
@@ -897,6 +910,7 @@ static const struct fb_ops hvfb_ops = {
.fb_imageblit = hvfb_cfb_imageblit,
.fb_blank = hvfb_blank,
.fb_mmap = fb_deferred_io_mmap,
+ .fb_destroy = hvfb_destroy,
};
@@ -1246,14 +1260,11 @@ static void hvfb_remove(struct hv_device *hdev)
fb_deferred_io_cleanup(info);
- unregister_framebuffer(info);
cancel_delayed_work_sync(&par->dwork);
vmbus_close(hdev->channel);
hv_set_drvdata(hdev, NULL);
-
- hvfb_putmem(info);
- framebuffer_release(info);
+ unregister_framebuffer(info);
}
static int hvfb_suspend(struct hv_device *hdev)
--
2.39.5