Markus Armbruster dfed210
Derived from
Markus Armbruster dfed210
# HG changeset patch
Markus Armbruster dfed210
# User Keir Fraser <keir.fraser@citrix.com>
Markus Armbruster dfed210
# Date 1210687697 -3600
Markus Armbruster dfed210
# Node ID 53195719f7621110dab7a97a2bca292b73baa715
Markus Armbruster dfed210
# Parent  65eec0554f39049eab354abe1ee4c305f6d1e0aa
Markus Armbruster dfed210
ioemu: Fix PVFB backend to validate frontend's frame buffer description
Markus Armbruster dfed210
Markus Armbruster dfed210
diff -rup a/tools/ioemu/hw/xenfb.c b/tools/ioemu/hw/xenfb.c
Markus Armbruster dfed210
--- a/tools/ioemu/hw/xenfb.c	2008-04-22 18:51:35.000000000 +0200
Markus Armbruster dfed210
+++ b/tools/ioemu/hw/xenfb.c	2008-04-22 18:52:07.000000000 +0200
Markus Armbruster dfed210
@@ -23,8 +23,6 @@
Markus Armbruster dfed210
 #define BTN_LEFT 0x110 /* from <linux/input.h> */
Markus Armbruster dfed210
 #endif
Markus Armbruster dfed210
 
Markus Armbruster dfed210
-// FIXME defend against malicious frontend?
Markus Armbruster dfed210
-
Markus Armbruster dfed210
 struct xenfb;
Markus Armbruster dfed210
 
Markus Armbruster dfed210
 struct xenfb_device {
Markus Armbruster 16e9d25
@@ -476,6 +474,56 @@ void xenfb_shutdown(struct xenfb *xenfb)
Markus Armbruster dfed210
 	free(xenfb);
Markus Armbruster dfed210
 }
Markus Armbruster dfed210
 
Markus Armbruster dfed210
+static int xenfb_configure_fb(struct xenfb *xenfb,
Markus Armbruster dfed210
+			      int width, int height, int depth,
Markus Armbruster dfed210
+			      size_t fb_len, int row_stride)
Markus Armbruster dfed210
+{
Markus Armbruster dfed210
+	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);
Markus Armbruster dfed210
+	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;
Markus Armbruster dfed210
+	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
Markus Armbruster dfed210
+	size_t fb_len_lim = fb_pages * XC_PAGE_SIZE;
Markus Armbruster dfed210
+	int max_width, max_height;
Markus Armbruster dfed210
+
Markus Armbruster dfed210
+	if (fb_len > fb_len_lim) {
Markus Armbruster dfed210
+		fprintf(stderr,
Markus Armbruster dfed210
+			"FB: frontend fb size %zu limited to %zu\n",
Markus Armbruster dfed210
+			fb_len, fb_len_lim);
Markus Armbruster 16e9d25
+		fb_len = fb_len_lim;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {
Markus Armbruster dfed210
+		fprintf(stderr,
Markus Armbruster dfed210
+			"FB: can't handle frontend fb depth %d\n",
Markus Armbruster dfed210
+			depth);
Markus Armbruster dfed210
+		return -1;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+	if (row_stride < 0 || row_stride > fb_len) {
Markus Armbruster dfed210
+		fprintf(stderr,
Markus Armbruster dfed210
+			"FB: invalid frontend stride %d\n", row_stride);
Markus Armbruster dfed210
+		return -1;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+	max_width = row_stride / (depth / 8);
Markus Armbruster dfed210
+	if (width < 0 || width > max_width) {
Markus Armbruster dfed210
+		fprintf(stderr,
Markus Armbruster dfed210
+			"FB: invalid frontend width %d limited to %d\n",
Markus Armbruster dfed210
+			width, max_width);
Markus Armbruster dfed210
+		width = max_width;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+	max_height = fb_len / row_stride;
Markus Armbruster dfed210
+	if (height < 0 || height > max_height) {
Markus Armbruster dfed210
+		fprintf(stderr,
Markus Armbruster dfed210
+			"FB: invalid frontend height %d limited to %d\n",
Markus Armbruster dfed210
+			height, max_height);
Markus Armbruster dfed210
+		height = max_height;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+	xenfb->fb_len = fb_len;
Markus Armbruster dfed210
+	xenfb->row_stride = row_stride;
Markus Armbruster dfed210
+	xenfb->depth = depth;
Markus Armbruster dfed210
+	xenfb->width = width;
Markus Armbruster dfed210
+	xenfb->height = height;
Markus Armbruster dfed210
+	fprintf(stderr, "Framebuffer %dx%dx%d stride %d\n",
Markus Armbruster dfed210
+		width, height, depth, row_stride);
Markus Armbruster dfed210
+	return 0;
Markus Armbruster dfed210
+}
Markus Armbruster dfed210
 
Markus Armbruster dfed210
 static void xenfb_on_fb_event(struct xenfb *xenfb)
Markus Armbruster dfed210
 {
Markus Armbruster dfed210
@@ -506,7 +553,6 @@ static void xenfb_on_fb_event(struct xen
Markus Armbruster dfed210
 			    || h != event->update.height) {
Markus Armbruster dfed210
 				fprintf(stderr, "%s bogus update clipped\n",
Markus Armbruster dfed210
 					xenfb->fb.nodename);
Markus Armbruster dfed210
-				break;
Markus Armbruster dfed210
 			}
Markus Armbruster dfed210
 			xenfb_guest_copy(xenfb, x, y, w, h);
Markus Armbruster dfed210
 			break;
Markus Armbruster dfed210
@@ -686,16 +732,15 @@ static int xenfb_read_frontend_fb_config
Markus Armbruster dfed210
                 xenfb->protocol[0] = '\0';
Markus Armbruster dfed210
         xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1");
Markus Armbruster dfed210
 
Markus Armbruster dfed210
-        /* TODO check for permitted ranges */
Markus Armbruster dfed210
         fb_page = xenfb->fb.page;
Markus Armbruster dfed210
-        xenfb->depth = fb_page->depth;
Markus Armbruster dfed210
-        xenfb->width = fb_page->width;
Markus Armbruster dfed210
-        xenfb->height = fb_page->height;
Markus Armbruster dfed210
-        /* TODO check for consistency with the above */
Markus Armbruster dfed210
-        xenfb->fb_len = fb_page->mem_length;
Markus Armbruster dfed210
-        xenfb->row_stride = fb_page->line_length;
Markus Armbruster dfed210
-        fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n",
Markus Armbruster dfed210
-                fb_page->depth, fb_page->width, fb_page->height, fb_page->line_length);
Markus Armbruster dfed210
+	if (xenfb_configure_fb(xenfb,
Markus Armbruster dfed210
+			       fb_page->width, fb_page->height, fb_page->depth,
Markus Armbruster dfed210
+			       fb_page->mem_length, fb_page->line_length)
Markus Armbruster dfed210
+	    < 0) {
Markus Armbruster dfed210
+		errno = EINVAL;
Markus Armbruster dfed210
+		return -1;
Markus Armbruster dfed210
+	}
Markus Armbruster dfed210
+
Markus Armbruster dfed210
         if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)
Markus Armbruster dfed210
 		return -1;
Markus Armbruster dfed210