[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] Fix PVFB backend to validate frontend's frame buffer description



Markus Armbruster wrote:
> A buggy or malicious frontend can describe its shared framebuffer to
> the backend in a way that makes the backend map an arbitrary amount of
>
>   
snipped out, see inline question below.
>
> diff -r 0a8fc1a62796 tools/ioemu/hw/xenfb.c
> --- a/tools/ioemu/hw/xenfb.c  Mon May 12 11:19:09 2008 +0100
> +++ b/tools/ioemu/hw/xenfb.c  Tue May 13 14:53:58 2008 +0200
> @@ -28,8 +28,6 @@
>  #ifndef BTN_LEFT
>  #define BTN_LEFT 0x110 /* from <linux/input.h> */
>  #endif
> -
> -// FIXME defend against malicious frontend?
>  
>  struct xenfb;
>  
> @@ -484,6 +482,68 @@ void xenfb_shutdown(struct xenfb *xenfb)
>       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 > 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);
>   
Do we need to set fb_len to fb_len_lim here?
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)
>  {
> @@ -514,16 +574,18 @@ static void xenfb_on_fb_event(struct xen
>                           || h != event->update.height) {
>                               fprintf(stderr, "%s bogus update clipped\n",
>                                       xenfb->fb.nodename);
> -                             break;
>                       }
>                       xenfb_guest_copy(xenfb, x, y, w, h);
>                       break;
>               case XENFB_TYPE_RESIZE:
> -                     xenfb->width  = event->resize.width;
> -                     xenfb->height = event->resize.height;
> -                     xenfb->depth = event->resize.depth;
> -                     xenfb->row_stride = event->resize.stride;
> -                     xenfb->offset = event->resize.offset;
> +                     if (xenfb_configure_fb(xenfb, xenfb->fb_len,
> +                                            event->resize.width,
> +                                            event->resize.height,
> +                                            event->resize.depth,
> +                                            xenfb->fb_len,
> +                                            event->resize.offset,
> +                                            event->resize.stride) < 0)
> +                             break;
>                       dpy_colourdepth(xenfb->ds, xenfb->depth);
>                       dpy_resize(xenfb->ds, xenfb->width, xenfb->height, 
> xenfb->row_stride);
>                       if (xenfb->ds->shared_buf)
> @@ -745,29 +807,18 @@ static int xenfb_read_frontend_fb_config
>          xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", 
> "1");
>          xenfb->refresh_period = -1;
>  
> -        /* TODO check for permitted ranges */
> -        fb_page = xenfb->fb.page;
> -        xenfb->depth = fb_page->depth;
> -        xenfb->width = fb_page->width;
> -        xenfb->height = fb_page->height;
> -        /* TODO check for consistency with the above */
> -        xenfb->fb_len = fb_page->mem_length;
> -        xenfb->row_stride = fb_page->line_length;
> -
> -        /* Protect against hostile frontend, limit fb_len to max allowed */
>          if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.nodename, "videoram", "%d",
>                              &videoram) < 0)
>                  videoram = 0;
> -        videoram = videoram * 1024 * 1024;
> -        if (videoram && xenfb->fb_len > videoram) {
> -                fprintf(stderr, "Framebuffer requested length of %zd 
> exceeded allowed %d\n",
> -                        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;
> -        }
> -        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);
> +     fb_page = xenfb->fb.page;
> +     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;
> +     }
> +
>          if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)
>               return -1;
>  
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
>   


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.