Blob Blame History Raw
Derived from
# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1210687697 -3600
# Node ID 53195719f7621110dab7a97a2bca292b73baa715
# Parent  65eec0554f39049eab354abe1ee4c305f6d1e0aa
ioemu: Fix PVFB backend to validate frontend's frame buffer description

diff --exclude '*~' -rup a/tools/xenfb/oldxenfb.c b/tools/xenfb/oldxenfb.c
--- a/tools/xenfb/oldxenfb.c	2008-05-05 15:52:35.000000000 +0200
+++ b/tools/xenfb/oldxenfb.c	2008-05-05 15:47:37.000000000 +0200
@@ -405,6 +405,54 @@ static void xenfb_dev_fatal(struct xenfb
 	xenfb_switch_state(dev, XenbusStateClosing);
 }
 
+static int xenfb_configure_fb(struct xenfb_private *xenfb,
+			      int width, int height, int depth,
+			      size_t fb_len, int row_stride)
+{
+	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
+	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
+	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
+	size_t fb_len_lim = fb_pages * XC_PAGE_SIZE;
+	int max_width, max_height;
+
+	if (fb_len > fb_len_lim) {
+		fprintf(stderr,
+			"FB: frontend fb size %zu limited to %zu\n",
+			fb_len, fb_len_lim);
+	}
+	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
+		fprintf(stderr,
+			"FB: can't handle frontend fb depth %d\n",
+			depth);
+		return -1;
+	}
+	if (row_stride < 0 || row_stride > fb_len) {
+		fprintf(stderr,
+			"FB: invalid frontend stride %d\n", row_stride);
+		return -1;
+	}
+	max_width = row_stride / (depth / 8);
+	if (width < 0 || width > max_width) {
+		fprintf(stderr,
+			"FB: invalid frontend width %d limited to %d\n",
+			width, max_width);
+		width = max_width;
+	}
+	max_height = fb_len / row_stride;
+	if (height < 0 || height > max_height) {
+		fprintf(stderr,
+			"FB: invalid frontend height %d limited to %d\n",
+			height, max_height);
+		height = max_height;
+	}
+	xenfb->fb_len = fb_len;
+	xenfb->pub.row_stride = row_stride;
+	xenfb->pub.depth = depth;
+	xenfb->pub.width = width;
+	xenfb->pub.height = height;
+	return 0;
+}
+
 int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
@@ -432,14 +480,14 @@ int xenfb_attach_dom(struct xenfb *xenfb
 			    xenfb->protocol) < 0)
 		xenfb->protocol[0] = '\0';
 
-	/* TODO check for permitted ranges */
 	fb_page = xenfb->fb.page;
-	xenfb->pub.depth = fb_page->depth;
-	xenfb->pub.width = fb_page->width;
-	xenfb->pub.height = fb_page->height;
-	/* TODO check for consistency with the above */
-	xenfb->fb_len = fb_page->mem_length;
-	xenfb->pub.row_stride = fb_page->line_length;
+	if (xenfb_configure_fb(xenfb,
+			       fb_page->width, fb_page->height, fb_page->depth,
+			       fb_page->mem_length, fb_page->line_length)
+	    < 0) {
+		errno = EINVAL;
+		goto error;
+	}
 
 	if (xenfb_map_fb(xenfb, domid) < 0)
 		goto error;
diff --exclude '*~' -rup a/tools/xenfb/xenfb.c b/tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c	2008-05-05 15:52:35.000000000 +0200
+++ b/tools/xenfb/xenfb.c	2008-05-05 15:46:57.000000000 +0200
@@ -570,6 +570,54 @@ static void xenfb_dev_fatal(struct xenfb
 	xenfb_switch_state(dev, XenbusStateClosing);
 }
 
+static int xenfb_configure_fb(struct xenfb_private *xenfb,
+			      int width, int height, int depth,
+			      size_t fb_len, int row_stride)
+{
+	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
+	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
+	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
+	size_t fb_len_lim = fb_pages * XC_PAGE_SIZE;
+	int max_width, max_height;
+
+	if (fb_len > fb_len_lim) {
+		fprintf(stderr,
+			"FB: frontend fb size %zu limited to %zu\n",
+			fb_len, fb_len_lim);
+	}
+	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
+		fprintf(stderr,
+			"FB: can't handle frontend fb depth %d\n",
+			depth);
+		return -1;
+	}
+	if (row_stride < 0 || row_stride > fb_len) {
+		fprintf(stderr,
+			"FB: invalid frontend stride %d\n", row_stride);
+		return -1;
+	}
+	max_width = row_stride / (depth / 8);
+	if (width < 0 || width > max_width) {
+		fprintf(stderr,
+			"FB: invalid frontend width %d limited to %d\n",
+			width, max_width);
+		width = max_width;
+	}
+	max_height = fb_len / row_stride;
+	if (height < 0 || height > max_height) {
+		fprintf(stderr,
+			"FB: invalid frontend height %d limited to %d\n",
+			height, max_height);
+		height = max_height;
+	}
+	xenfb->fb_len = fb_len;
+	xenfb->pub.row_stride = row_stride;
+	xenfb->pub.depth = depth;
+	xenfb->pub.width = width;
+	xenfb->pub.height = height;
+	return 0;
+}
+
 int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
@@ -630,14 +678,14 @@ int xenfb_attach_dom(struct xenfb *xenfb
 		xenfb->protocol[0] = '\0';
 	xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
 
-	/* TODO check for permitted ranges */
 	fb_page = xenfb->fb.page;
-	xenfb->pub.depth = fb_page->depth;
-	xenfb->pub.width = fb_page->width;
-	xenfb->pub.height = fb_page->height;
-	/* TODO check for consistency with the above */
-	xenfb->fb_len = fb_page->mem_length;
-	xenfb->pub.row_stride = fb_page->line_length;
+	if (xenfb_configure_fb(xenfb,
+			       fb_page->width, fb_page->height, fb_page->depth,
+			       fb_page->mem_length, fb_page->line_length)
+	    < 0) {
+		errno = EINVAL;
+		goto error;
+	}
 
 	if (xenfb_map_fb(xenfb, domid) < 0)
 		goto error;