Skip to content

Commit 9ff5549

Browse files
kelleymhliuw
authored andcommitted
video: hyperv_fb: Fix validation of screen resolution
In the WIN10 version of the Synthetic Video protocol with Hyper-V, Hyper-V reports a list of supported resolutions as part of the protocol negotiation. The driver calculates the maximum width and height from the list of resolutions, and uses those maximums to validate any screen resolution specified in the video= option on the kernel boot line. This method of validation is incorrect. For example, the list of supported resolutions could contain 1600x1200 and 1920x1080, both of which fit in an 8 Mbyte frame buffer. But calculating the max width and height yields 1920 and 1200, and 1920x1200 resolution does not fit in an 8 Mbyte frame buffer. Unfortunately, this resolution is accepted, causing a kernel fault when the driver accesses memory outside the frame buffer. Instead, validate the specified screen resolution by calculating its size, and comparing against the frame buffer size. Delete the code for calculating the max width and height from the list of resolutions, since these max values have no use. Also add the frame buffer size to the info message to aid in understanding why a resolution might be rejected. Fixes: 67e7cdb ("video: hyperv: hyperv_fb: Obtain screen resolution from Hyper-V host") Signed-off-by: Michael Kelley <mikelley@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Acked-by: Helge Deller <deller@gmx.de> Link: https://lore.kernel.org/r/1642360711-2335-1-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent 96d9d1f commit 9ff5549

File tree

1 file changed

+3
-13
lines changed

1 file changed

+3
-13
lines changed

drivers/video/fbdev/hyperv_fb.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,6 @@ struct hvfb_par {
287287

288288
static uint screen_width = HVFB_WIDTH;
289289
static uint screen_height = HVFB_HEIGHT;
290-
static uint screen_width_max = HVFB_WIDTH;
291-
static uint screen_height_max = HVFB_HEIGHT;
292290
static uint screen_depth;
293291
static uint screen_fb_size;
294292
static uint dio_fb_size; /* FB size for deferred IO */
@@ -582,7 +580,6 @@ static int synthvid_get_supported_resolution(struct hv_device *hdev)
582580
int ret = 0;
583581
unsigned long t;
584582
u8 index;
585-
int i;
586583

587584
memset(msg, 0, sizeof(struct synthvid_msg));
588585
msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST;
@@ -613,13 +610,6 @@ static int synthvid_get_supported_resolution(struct hv_device *hdev)
613610
goto out;
614611
}
615612

616-
for (i = 0; i < msg->resolution_resp.resolution_count; i++) {
617-
screen_width_max = max_t(unsigned int, screen_width_max,
618-
msg->resolution_resp.supported_resolution[i].width);
619-
screen_height_max = max_t(unsigned int, screen_height_max,
620-
msg->resolution_resp.supported_resolution[i].height);
621-
}
622-
623613
screen_width =
624614
msg->resolution_resp.supported_resolution[index].width;
625615
screen_height =
@@ -941,7 +931,7 @@ static void hvfb_get_option(struct fb_info *info)
941931

942932
if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
943933
(synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) &&
944-
(x > screen_width_max || y > screen_height_max)) ||
934+
(x * y * screen_depth / 8 > screen_fb_size)) ||
945935
(par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
946936
x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
947937
(par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
@@ -1194,8 +1184,8 @@ static int hvfb_probe(struct hv_device *hdev,
11941184
}
11951185

11961186
hvfb_get_option(info);
1197-
pr_info("Screen resolution: %dx%d, Color depth: %d\n",
1198-
screen_width, screen_height, screen_depth);
1187+
pr_info("Screen resolution: %dx%d, Color depth: %d, Frame buffer size: %d\n",
1188+
screen_width, screen_height, screen_depth, screen_fb_size);
11991189

12001190
ret = hvfb_getmem(hdev, info);
12011191
if (ret) {

0 commit comments

Comments
 (0)