Bug 694455 (CVE-2011-0904) - CVE-2011-0904 vino: Out of bounds read flaw by processing certain client raw encoding framebuffer update requests
Summary: CVE-2011-0904 vino: Out of bounds read flaw by processing certain client raw ...
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2011-0904
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 696761 696762 696763 696764 696765 696766 696767 696768 696769 696770 701712 833986 888637 888638
Blocks: 857251
TreeView+ depends on / blocked
 
Reported: 2011-04-07 12:48 UTC by Jan Lieskovsky
Modified: 2021-02-24 16:11 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2015-03-05 12:50:57 UTC
Embargoed:


Attachments (Terms of Use)
Fix ported to libvnserver-0.9.7 (1.41 KB, patch)
2011-04-15 12:32 UTC, Petr Pisar
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2013:0169 0 normal SHIPPED_LIVE Moderate: vino security update 2013-01-22 03:34:50 UTC

Description Jan Lieskovsky 2011-04-07 12:48:12 UTC
An out of bounds read flaw was found in the way vino, remote desktop
system for GNOME processed certain framebuffer update requests from
VNC client, when raw encoding was used. An attacker could use this
flaw to send a specially-crafted request to vino, causing it to crash.

Upstream bug report:
[1] https://bugzilla.gnome.org/show_bug.cgi?id=641802

Relevant upstream commits (for gnome-2-28, gnome-2-30, gnome-2-32,
gnome-3-0 and master branches):

[2] http://git.gnome.org/browse/vino/commit/?id=dff52694a384fe95195f2211254026b752d63ec4
[3] http://git.gnome.org/browse/vino/commit/?id=0c2c9175963fc56bf2af10e42867181332f96ce0
[4] http://git.gnome.org/browse/vino/commit/?id=e17bd4e369f90748654e31a4867211dc7610975d
[5] http://git.gnome.org/browse/vino/commit/?id=456dadbb5c5971d3448763a44c05b9ad033e522f
[6] http://git.gnome.org/browse/vino/commit/?id=8beefcf7792d343c10c919ee0c928c81f73b1279

Comment 4 Jan Lieskovsky 2011-04-07 13:14:49 UTC
This issue affects the versions of the vino package, as shipped
with Red Hat Enterprise Linux 4, 5, and 6.

This issue affects the versions of the vino package, as shipped
with Fedora release of 13 and 14.

--

This issue did NOT affect the version of the libvncserver package,
as shipped with Red Hat Enterprise Linux 6.

This issue did NOT affect the version of the libvncserver package,
as present within EPEL-5 repository.

This issue did NOT affect the versions of the libvncserver package,
as shipped with Fedora release of 13 and 14.

Note: See also comment c#20 of this bug report for further information
      / explanation of conclusions from the above paragraph.      

--

This issue affects the versions of the kdenetwork package,
as shipped with Red Hat Enterprise Linux 4 and 5.

This issue did NOT affect the version of the kdenetwork package,
as shipped with Red Hat Enterprise Linux 6.

This issue did NOT affect the version of the kdenetwork package,
as shipped with Fedora release of 13 and 14.

Comment 8 Petr Pisar 2011-04-15 09:45:32 UTC
(In reply to comment #3)
> 
> The vulnerability is a out-of-bounds write. It is triggered by the memcpy
> function in rfbTranslateNone, when handling the "client framebuffer update
> request" packet from a vnc client:
> 
> void
> rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
>                  char *iptr, char *optr, int bytesBetweenInputLines,
>                  int width, int height)
> {
>     int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
> 
>     while (height > 0) {
>         memcpy(optr, iptr, bytesPerOutputLine); //out-of-bounds write
>         iptr += bytesBetweenInputLines;
>         optr += bytesPerOutputLine;
>         height--;
>     }
> }
> 
> Here 'optr' points out of the boundary, and 'optr' is from the caller:
> rfbSendRectEncodingRaw (rfbserver.c:1328)
> 
>         (*cl->translateFn)(cl->translateLookupTable,
>                &(cl->screen->rfbServerFormat),
>                            &cl->format, fbptr, &cl->updateBuf[cl->ublen],
>                            cl->screen->paddedWidthInBytes, w, nlines);
> 
> // (*cl->translateFn) is rfbTranslateNone, and the value of fbptr is passed to
> optr.
> 
No. The fbptr is passed as 4th argument to cl->translateFn() which is iptr (not optr) argument of rfbTranslateNone() which is dereferenced for reading.

So this bug is about reading out of buffer, not about writing.

Comment 20 Jan Lieskovsky 2011-05-03 13:35:17 UTC
Analysis from Petr Pisar (Red Hat libvncserver package maintainer) why various libvncserver package versions, as shipped within different products are not vulnerable to this flaw:


The libvncserver warning is produced in
rfbserver.c:rfbProcessClientNormalMessage() when converting rectangle
coordinates just after processing client packet of rfbFramebufferUpdateRequest
type:

    case rfbFramebufferUpdateRequest:
        [...]
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
            [...]
        }
        [...]
        /* The values come in based on the scaled screen, we need to convert
         * them to values based on the main screen's coordinate system
         */
        if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl))
        {
                rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: "
                    "%dXx%dY-%dWx%dH\n",
                    msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h);
                return;
        }
        [...]

Not only the rectSwapIfLEAndClip() function converts values from network-order
and scales the coordinates, it also clips requested rectangle (msg.fur members)
to fit into server screen size:

rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
                rfbClientPtr cl)
{
        /* Convert */
        int x1=Swap16IfLE(*x);
        int y1=Swap16IfLE(*y);
        int w1=Swap16IfLE(*w);
        int h1=Swap16IfLE(*h);

        /* Scale */
        rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1,
            "rectSwapIfLEAndClip");
        *x = x1;
        *y = y1;
        *w = w1;
        *h = h1;

        /* Clip
        rfbLog("Clipping: region(%uXx%uY-%uWx%uH) to screen(%dWx%dH)\n",
                *x, *y, *w, *h,
                cl->screen->width, cl->screen->height);
        */
        if(*w>cl->screen->width-*x)
                *w=cl->screen->width-*x;
        /* possible underflow */
        if(*w>cl->screen->width-*x)
                return FALSE;
        if(*h>cl->screen->height-*y)
                *h=cl->screen->height-*y;
        if(*h>cl->screen->height-*y)
                return FALSE;

        return TRUE;
}

And see the comment /* possible underflow */ (other comments added by me). It
checks whether subtraction result fits into uint16_t. Otherwise it refuse the
conversion and warning is printed and client request is refused. This is the
output I get on server side with the Clipping log line:

Clipping: region(29696Xx32768Y-1Wx30975H) to screen(400Wx300H)
Warning, ignoring rfbFramebufferUpdateRequest: 29696Xx32768Y-36240Wx30975H

The Cliping values correspond to the run_00108.input3 packet content:
$ hexdump -C run_00108.input3
00000000  03 00 74 00 80 00 00 01  78 ff                    |..t.....x.|

03 00 is the request type probably
74 00 (29696) is X coordinate
80 00 (32768) is Y cooridnate
00 01 (1) is Width
78 ff (30975) is Height


Let's look on the clipping code closer and remember the *x and *w are uint16_t:
if(*w>cl->screen->width-*x)
        *w=cl->screen->width-*x;
/* possible underflow */
if(*w>cl->screen->width-*x)
        return FALSE;

If X fits into screen width, then substraction result is not negative and
request width is clamped properly.

If X is out of screen width, then subtraction underruns and *W will be
garbled (as can be seen in my output, 1W → 36240W), but still non-negative
(because unsigned type). However subsequent underrun test will compare garbled
non-negative value to negative subtraction result (the same as former one)
resulting is true condition and causing `return FALSE'.

The same applies to vertical clipping.

Thus I conclude LIBVNCSERVER IS NOT VULNERABLE because it performs the range
check on this place. One can see it's the same equation as in current patch:

+   /* Validate the rectangle given by the update packet. */
+   if (w + x > cl->scaledScreen->width || h + y > cl->scaledScreen->height)
+       goto updateFailed;


-- Petr

Comment 21 Jan Lieskovsky 2011-05-03 16:12:27 UTC
Created vino tracking bugs for this issue

Affects: fedora-all [bug 701712]

Comment 22 Jan Lieskovsky 2011-05-03 16:22:03 UTC
Statement:

(none)

Comment 25 errata-xmlrpc 2013-01-21 22:37:20 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6

Via RHSA-2013:0169 https://rhn.redhat.com/errata/RHSA-2013-0169.html


Note You need to log in before you can comment on or make changes to this bug.