diff mbox series

[v3] ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206)

Message ID 20220407081712.345609-1-mcascell@redhat.com
State New
Headers show
Series [v3] ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) | expand

Commit Message

Mauro Matteo Cascella April 7, 2022, 8:17 a.m. UTC
Prevent potential integer overflow by limiting 'width' and 'height' to
512x512. Also change 'datasize' type to size_t. Refer to security
advisory https://starlabs.sg/advisories/22-4206/ for more information.

Fixes: CVE-2021-4206
Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
---
v3:
- fix CVE id (CVE-2021-4206 instead of CVE-2022-4206)

 hw/display/qxl-render.c | 7 +++++++
 hw/display/vmware_vga.c | 2 ++
 ui/cursor.c             | 8 +++++++-
 3 files changed, 16 insertions(+), 1 deletion(-)

Comments

Marc-André Lureau April 7, 2022, 9:17 a.m. UTC | #1
On Thu, Apr 7, 2022 at 12:23 PM Mauro Matteo Cascella <mcascell@redhat.com>
wrote:

> Prevent potential integer overflow by limiting 'width' and 'height' to
> 512x512. Also change 'datasize' type to size_t. Refer to security
> advisory https://starlabs.sg/advisories/22-4206/ for more information.
>
> Fixes: CVE-2021-4206
>

(the Starlabs advisory has 2022, I guess it's wrong then)

Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>



> ---
> v3:
> - fix CVE id (CVE-2021-4206 instead of CVE-2022-4206)
>
>  hw/display/qxl-render.c | 7 +++++++
>  hw/display/vmware_vga.c | 2 ++
>  ui/cursor.c             | 8 +++++++-
>  3 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
> index d28849b121..dc3c4edd05 100644
> --- a/hw/display/qxl-render.c
> +++ b/hw/display/qxl-render.c
> @@ -247,6 +247,13 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl,
> QXLCursor *cursor,
>      size_t size;
>
>      c = cursor_alloc(cursor->header.width, cursor->header.height);
> +
> +    if (!c) {
> +        qxl_set_guest_bug(qxl, "%s: cursor %ux%u alloc error", __func__,
> +                cursor->header.width, cursor->header.height);
> +        goto fail;
> +    }
> +
>      c->hot_x = cursor->header.hot_spot_x;
>      c->hot_y = cursor->header.hot_spot_y;
>      switch (cursor->header.type) {
> diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
> index 98c83474ad..45d06cbe25 100644
> --- a/hw/display/vmware_vga.c
> +++ b/hw/display/vmware_vga.c
> @@ -515,6 +515,8 @@ static inline void vmsvga_cursor_define(struct
> vmsvga_state_s *s,
>      int i, pixels;
>
>      qc = cursor_alloc(c->width, c->height);
> +    assert(qc != NULL);
> +
>      qc->hot_x = c->hot_x;
>      qc->hot_y = c->hot_y;
>      switch (c->bpp) {
> diff --git a/ui/cursor.c b/ui/cursor.c
> index 1d62ddd4d0..835f0802f9 100644
> --- a/ui/cursor.c
> +++ b/ui/cursor.c
> @@ -46,6 +46,8 @@ static QEMUCursor *cursor_parse_xpm(const char *xpm[])
>
>      /* parse pixel data */
>      c = cursor_alloc(width, height);
> +    assert(c != NULL);
> +
>      for (pixel = 0, y = 0; y < height; y++, line++) {
>          for (x = 0; x < height; x++, pixel++) {
>              idx = xpm[line][x];
> @@ -91,7 +93,11 @@ QEMUCursor *cursor_builtin_left_ptr(void)
>  QEMUCursor *cursor_alloc(int width, int height)
>  {
>      QEMUCursor *c;
> -    int datasize = width * height * sizeof(uint32_t);
> +    size_t datasize = width * height * sizeof(uint32_t);
> +
> +    if (width > 512 || height > 512) {
> +        return NULL;
> +    }
>
>      c = g_malloc0(sizeof(QEMUCursor) + datasize);
>      c->width  = width;
> --
> 2.35.1
>
>
>
Mauro Matteo Cascella April 7, 2022, 9:26 a.m. UTC | #2
On Thu, Apr 7, 2022 at 11:17 AM Marc-André Lureau
<marcandre.lureau@gmail.com> wrote:
>
>
>
> On Thu, Apr 7, 2022 at 12:23 PM Mauro Matteo Cascella <mcascell@redhat.com> wrote:
>>
>> Prevent potential integer overflow by limiting 'width' and 'height' to
>> 512x512. Also change 'datasize' type to size_t. Refer to security
>> advisory https://starlabs.sg/advisories/22-4206/ for more information.
>>
>> Fixes: CVE-2021-4206
>
>
> (the Starlabs advisory has 2022, I guess it's wrong then)

Yep, that is wrong. I asked them to update the page.

Thanks.

>> Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
>
>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
>
>>
>> ---
>> v3:
>> - fix CVE id (CVE-2021-4206 instead of CVE-2022-4206)
>>
>>  hw/display/qxl-render.c | 7 +++++++
>>  hw/display/vmware_vga.c | 2 ++
>>  ui/cursor.c             | 8 +++++++-
>>  3 files changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
>> index d28849b121..dc3c4edd05 100644
>> --- a/hw/display/qxl-render.c
>> +++ b/hw/display/qxl-render.c
>> @@ -247,6 +247,13 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
>>      size_t size;
>>
>>      c = cursor_alloc(cursor->header.width, cursor->header.height);
>> +
>> +    if (!c) {
>> +        qxl_set_guest_bug(qxl, "%s: cursor %ux%u alloc error", __func__,
>> +                cursor->header.width, cursor->header.height);
>> +        goto fail;
>> +    }
>> +
>>      c->hot_x = cursor->header.hot_spot_x;
>>      c->hot_y = cursor->header.hot_spot_y;
>>      switch (cursor->header.type) {
>> diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
>> index 98c83474ad..45d06cbe25 100644
>> --- a/hw/display/vmware_vga.c
>> +++ b/hw/display/vmware_vga.c
>> @@ -515,6 +515,8 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
>>      int i, pixels;
>>
>>      qc = cursor_alloc(c->width, c->height);
>> +    assert(qc != NULL);
>> +
>>      qc->hot_x = c->hot_x;
>>      qc->hot_y = c->hot_y;
>>      switch (c->bpp) {
>> diff --git a/ui/cursor.c b/ui/cursor.c
>> index 1d62ddd4d0..835f0802f9 100644
>> --- a/ui/cursor.c
>> +++ b/ui/cursor.c
>> @@ -46,6 +46,8 @@ static QEMUCursor *cursor_parse_xpm(const char *xpm[])
>>
>>      /* parse pixel data */
>>      c = cursor_alloc(width, height);
>> +    assert(c != NULL);
>> +
>>      for (pixel = 0, y = 0; y < height; y++, line++) {
>>          for (x = 0; x < height; x++, pixel++) {
>>              idx = xpm[line][x];
>> @@ -91,7 +93,11 @@ QEMUCursor *cursor_builtin_left_ptr(void)
>>  QEMUCursor *cursor_alloc(int width, int height)
>>  {
>>      QEMUCursor *c;
>> -    int datasize = width * height * sizeof(uint32_t);
>> +    size_t datasize = width * height * sizeof(uint32_t);
>> +
>> +    if (width > 512 || height > 512) {
>> +        return NULL;
>> +    }
>>
>>      c = g_malloc0(sizeof(QEMUCursor) + datasize);
>>      c->width  = width;
>> --
>> 2.35.1
>>
>>
>
>
> --
> Marc-André Lureau
Peter Maydell April 7, 2022, 5:46 p.m. UTC | #3
On Thu, 7 Apr 2022 at 10:21, Marc-André Lureau
<marcandre.lureau@gmail.com> wrote:
>
>
>
> On Thu, Apr 7, 2022 at 12:23 PM Mauro Matteo Cascella <mcascell@redhat.com> wrote:
>>
>> Prevent potential integer overflow by limiting 'width' and 'height' to
>> 512x512. Also change 'datasize' type to size_t. Refer to security
>> advisory https://starlabs.sg/advisories/22-4206/ for more information.
>>
>> Fixes: CVE-2021-4206
>
>
> (the Starlabs advisory has 2022, I guess it's wrong then)
>
>> Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
>
>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Does this fix (or any of the other cursor-related stuff I've seen
floating past) need to go into 7.0 ? (ie is it release-critical?)

thanks
-- PMM
Gerd Hoffmann April 8, 2022, 5:11 a.m. UTC | #4
On Thu, Apr 07, 2022 at 06:46:00PM +0100, Peter Maydell wrote:
> On Thu, 7 Apr 2022 at 10:21, Marc-André Lureau
> <marcandre.lureau@gmail.com> wrote:
> >
> >
> >
> > On Thu, Apr 7, 2022 at 12:23 PM Mauro Matteo Cascella <mcascell@redhat.com> wrote:
> >>
> >> Prevent potential integer overflow by limiting 'width' and 'height' to
> >> 512x512. Also change 'datasize' type to size_t. Refer to security
> >> advisory https://starlabs.sg/advisories/22-4206/ for more information.
> >>
> >> Fixes: CVE-2021-4206
> >
> >
> > (the Starlabs advisory has 2022, I guess it's wrong then)
> >
> >> Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
> >
> >
> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Does this fix (or any of the other cursor-related stuff I've seen
> floating past) need to go into 7.0 ? (ie is it release-critical?)

Yes.  The integer overflow can be triggered easily by guests.  Hitting
the double read race condition is harder but probably possible too.
Pull request sent minutes ago.

take care,
  Gerd
diff mbox series

Patch

diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index d28849b121..dc3c4edd05 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -247,6 +247,13 @@  static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
     size_t size;
 
     c = cursor_alloc(cursor->header.width, cursor->header.height);
+
+    if (!c) {
+        qxl_set_guest_bug(qxl, "%s: cursor %ux%u alloc error", __func__,
+                cursor->header.width, cursor->header.height);
+        goto fail;
+    }
+
     c->hot_x = cursor->header.hot_spot_x;
     c->hot_y = cursor->header.hot_spot_y;
     switch (cursor->header.type) {
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 98c83474ad..45d06cbe25 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -515,6 +515,8 @@  static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
     int i, pixels;
 
     qc = cursor_alloc(c->width, c->height);
+    assert(qc != NULL);
+
     qc->hot_x = c->hot_x;
     qc->hot_y = c->hot_y;
     switch (c->bpp) {
diff --git a/ui/cursor.c b/ui/cursor.c
index 1d62ddd4d0..835f0802f9 100644
--- a/ui/cursor.c
+++ b/ui/cursor.c
@@ -46,6 +46,8 @@  static QEMUCursor *cursor_parse_xpm(const char *xpm[])
 
     /* parse pixel data */
     c = cursor_alloc(width, height);
+    assert(c != NULL);
+
     for (pixel = 0, y = 0; y < height; y++, line++) {
         for (x = 0; x < height; x++, pixel++) {
             idx = xpm[line][x];
@@ -91,7 +93,11 @@  QEMUCursor *cursor_builtin_left_ptr(void)
 QEMUCursor *cursor_alloc(int width, int height)
 {
     QEMUCursor *c;
-    int datasize = width * height * sizeof(uint32_t);
+    size_t datasize = width * height * sizeof(uint32_t);
+
+    if (width > 512 || height > 512) {
+        return NULL;
+    }
 
     c = g_malloc0(sizeof(QEMUCursor) + datasize);
     c->width  = width;