147 lines
4.9 KiB
Diff
147 lines
4.9 KiB
Diff
Index: xen-3.2-testing/tools/ioemu/hw/xenfb.c
|
|
===================================================================
|
|
--- xen-3.2-testing.orig/tools/ioemu/hw/xenfb.c 2008-04-29 08:52:06.000000000 -0600
|
|
+++ xen-3.2-testing/tools/ioemu/hw/xenfb.c 2008-04-29 10:12:41.000000000 -0600
|
|
@@ -23,8 +23,6 @@
|
|
#define BTN_LEFT 0x110 /* from <linux/input.h> */
|
|
#endif
|
|
|
|
-// FIXME defend against malicious frontend?
|
|
-
|
|
struct xenfb;
|
|
|
|
struct xenfb_device {
|
|
@@ -50,6 +48,7 @@
|
|
int depth; /* colour depth of guest framebuffer */
|
|
int width; /* pixel width of guest framebuffer */
|
|
int height; /* pixel height of guest framebuffer */
|
|
+ int offset; /* offset of the framebuffer */
|
|
int abs_pointer_wanted; /* Whether guest supports absolute pointer */
|
|
int button_state; /* Last seen pointer button state */
|
|
char protocol[64]; /* frontend protocol */
|
|
@@ -476,6 +475,75 @@
|
|
free(xenfb);
|
|
}
|
|
|
|
+static int xenfb_configure_fb(struct xenfb *xenfb, size_t fb_len_lim,
|
|
+ int width, int height, int depth,
|
|
+ size_t fb_len, int offset, 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_max = fb_pages * XC_PAGE_SIZE;
|
|
+ int max_width, max_height;
|
|
+
|
|
+ if (fb_len_lim == 0) {
|
|
+ fprintf(stderr,
|
|
+ "FB: No fb size limit, limit set to %zu\n",
|
|
+ fb_len_max);
|
|
+ fb_len_lim = fb_len_max;
|
|
+ }
|
|
+ if (fb_len_lim > fb_len_max) {
|
|
+ fprintf(stderr,
|
|
+ "FB: fb size limit %zu exceeds %zu, corrected\n",
|
|
+ fb_len_lim, fb_len_max);
|
|
+ fb_len_lim = fb_len_max;
|
|
+ }
|
|
+ if (fb_len > fb_len_lim) {
|
|
+ fprintf(stderr,
|
|
+ "FB: frontend fb size %zu limited to %zu\n",
|
|
+ fb_len, fb_len_lim);
|
|
+ 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;
|
|
+ }
|
|
+ if (offset < 0 || offset >= fb_len) {
|
|
+ fprintf(stderr,
|
|
+ "FB: invalid frontend offset %d (max %zu)\n",
|
|
+ offset, fb_len - 1);
|
|
+ return -1;
|
|
+ }
|
|
+ max_height = (fb_len - offset) / 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->row_stride = row_stride;
|
|
+ xenfb->depth = depth;
|
|
+ xenfb->width = width;
|
|
+ xenfb->height = height;
|
|
+ xenfb->offset = offset;
|
|
+ fprintf(stderr, "Framebuffer %dx%dx%d offset %d stride %d\n",
|
|
+ width, height, depth, offset, row_stride);
|
|
+ return 0;
|
|
+}
|
|
|
|
static void xenfb_on_fb_event(struct xenfb *xenfb)
|
|
{
|
|
@@ -511,10 +579,17 @@
|
|
xenfb_guest_copy(xenfb, x, y, w, h);
|
|
break;
|
|
case XENFB_TYPE_RESIZE:
|
|
- xenfb->width = event->resize.width;
|
|
- xenfb->height = event->resize.height;
|
|
- xenfb->row_stride = event->resize.stride;
|
|
+ if (xenfb_configure_fb(xenfb, xenfb->fb_len,
|
|
+ event->resize.width,
|
|
+ event->resize.height,
|
|
+ event->resize.depth,
|
|
+ xenfb->fb_len,
|
|
+ 0,
|
|
+ event->resize.stride) < 0)
|
|
+ break;
|
|
+
|
|
dpy_resize(xenfb->ds, xenfb->width, xenfb->height);
|
|
+ xenfb_invalidate(xenfb);
|
|
break;
|
|
}
|
|
}
|
|
@@ -695,22 +770,14 @@
|
|
|
|
if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.nodename, "videoram", "%d", &videoram) < 0)
|
|
videoram = 0;
|
|
- videoram = videoram * 1024 * 1024;
|
|
|
|
fb_page = xenfb->fb.page;
|
|
- xenfb->depth = fb_page->depth;
|
|
- xenfb->width = fb_page->width;
|
|
- xenfb->height = fb_page->height;
|
|
- xenfb->fb_len = fb_page->mem_length;
|
|
- xenfb->row_stride = fb_page->line_length;
|
|
- /* Protect against hostile frontend, limit fb_len to configured */
|
|
- if (videoram && xenfb->fb_len > videoram) {
|
|
- xenfb->fb_len = videoram;
|
|
- if (xenfb->row_stride * xenfb->height > xenfb->fb_len)
|
|
- xenfb->height = xenfb->fb_len / xenfb->row_stride;
|
|
+ if (xenfb_configure_fb(xenfb, videoram * 1024 * 1024U,
|
|
+ fb_page->width, fb_page->height, fb_page->depth,
|
|
+ fb_page->mem_length, 0, fb_page->line_length) < 0) {
|
|
+ errno = EINVAL;
|
|
+ return -1;
|
|
}
|
|
- fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n",
|
|
- fb_page->depth, fb_page->width, fb_page->height, fb_page->line_length);
|
|
if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)
|
|
return -1;
|
|
|