Blame SOURCES/0024-Fix-flexible-array-buffer-overflow.patch

b2d6b4
From c182f8e4a445e93842faf6c2bd8583894da36a1a Mon Sep 17 00:00:00 2001
b2d6b4
From: Frediano Ziglio <fziglio@redhat.com>
b2d6b4
Date: Fri, 18 May 2018 11:41:57 +0100
b2d6b4
Subject: [PATCH] Fix flexible array buffer overflow
b2d6b4
b2d6b4
This is kind of a DoS, possibly flexible array in the protocol
b2d6b4
causes the network size check to be ignored due to integer overflows.
b2d6b4
b2d6b4
The size of flexible array is computed as (message_end - position),
b2d6b4
then this size is added to the number of bytes before the array and
b2d6b4
this number is used to check if we overflow initial message.
b2d6b4
b2d6b4
An example is:
b2d6b4
b2d6b4
    message {
b2d6b4
        uint32 dummy[2];
b2d6b4
        uint8 data[] @end;
b2d6b4
    } LenMessage;
b2d6b4
b2d6b4
which generated this (simplified remove useless code) code:
b2d6b4
b2d6b4
    { /* data */
b2d6b4
        data__nelements = message_end - (start + 8);
b2d6b4
b2d6b4
        data__nw_size = data__nelements;
b2d6b4
    }
b2d6b4
b2d6b4
    nw_size = 8 + data__nw_size;
b2d6b4
b2d6b4
    /* Check if message fits in reported side */
b2d6b4
    if (nw_size > (uintptr_t) (message_end - start)) {
b2d6b4
        return NULL;
b2d6b4
    }
b2d6b4
b2d6b4
Following code:
b2d6b4
- data__nelements == message_end - (start + 8)
b2d6b4
- data__nw_size == data__nelements == message_end - (start + 8)
b2d6b4
- nw_size == 8 + data__nw_size == 8 + message_end - (start + 8) ==
b2d6b4
  8 + message_end - start - 8 == message_end -start
b2d6b4
- the check for overflow is (nw_size > (message_end - start)) but
b2d6b4
  nw_size == message_end - start so the check is doing
b2d6b4
  ((message_end - start) > (message_end - start)) which is always false.
b2d6b4
b2d6b4
If message_end - start < 8 then data__nelements (number of element
b2d6b4
on the array above) computation generate an integer underflow that
b2d6b4
later create a buffer overflow.
b2d6b4
b2d6b4
Add a check to make sure that the array starts before the message ends
b2d6b4
to avoid the overflow.
b2d6b4
b2d6b4
Difference is:
b2d6b4
    diff -u save/generated_client_demarshallers1.c common/generated_client_demarshallers1.c
b2d6b4
    --- save/generated_client_demarshallers1.c	2018-06-22 22:13:48.626793919 +0100
b2d6b4
    +++ common/generated_client_demarshallers1.c	2018-06-22 22:14:03.408163291 +0100
b2d6b4
    @@ -225,6 +225,9 @@
b2d6b4
         uint64_t data__nelements;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 0);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -243,6 +246,9 @@
b2d6b4
         *free_message = nofree;
b2d6b4
         return data;
b2d6b4
b2d6b4
    +   error:
b2d6b4
    +    free(data);
b2d6b4
    +    return NULL;
b2d6b4
     }
b2d6b4
b2d6b4
     static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
b2d6b4
    @@ -301,6 +307,9 @@
b2d6b4
         SpiceMsgPing *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 12) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 12);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -5226,6 +5235,9 @@
b2d6b4
             uint64_t cursor_data__nw_size;
b2d6b4
             uint64_t cursor_data__nelements;
b2d6b4
             { /* data */
b2d6b4
    +            if (SPICE_UNLIKELY((start2 + 22) > message_end)) {
b2d6b4
    +                goto error;
b2d6b4
    +            }
b2d6b4
                 cursor_data__nelements = message_end - (start2 + 22);
b2d6b4
b2d6b4
                 cursor_data__nw_size = cursor_data__nelements;
b2d6b4
    @@ -5305,6 +5317,9 @@
b2d6b4
             uint64_t cursor_data__nw_size;
b2d6b4
             uint64_t cursor_data__nelements;
b2d6b4
             { /* data */
b2d6b4
    +            if (SPICE_UNLIKELY((start2 + 22) > message_end)) {
b2d6b4
    +                goto error;
b2d6b4
    +            }
b2d6b4
                 cursor_data__nelements = message_end - (start2 + 22);
b2d6b4
b2d6b4
                 cursor_data__nw_size = cursor_data__nelements;
b2d6b4
    @@ -5540,6 +5555,9 @@
b2d6b4
         SpiceMsgPlaybackPacket *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 4);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -5594,6 +5612,9 @@
b2d6b4
         SpiceMsgPlaybackMode *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 8) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 8);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    diff -u save/generated_client_demarshallers.c common/generated_client_demarshallers.c
b2d6b4
    --- save/generated_client_demarshallers.c	2018-06-22 22:13:48.626793919 +0100
b2d6b4
    +++ common/generated_client_demarshallers.c	2018-06-22 22:14:03.004153195 +0100
b2d6b4
    @@ -225,6 +225,9 @@
b2d6b4
         uint64_t data__nelements;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 0);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -243,6 +246,9 @@
b2d6b4
         *free_message = nofree;
b2d6b4
         return data;
b2d6b4
b2d6b4
    +   error:
b2d6b4
    +    free(data);
b2d6b4
    +    return NULL;
b2d6b4
     }
b2d6b4
b2d6b4
     static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
b2d6b4
    @@ -301,6 +307,9 @@
b2d6b4
         SpiceMsgPing *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 12) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 12);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -6574,6 +6583,9 @@
b2d6b4
             }
b2d6b4
b2d6b4
             { /* data */
b2d6b4
    +            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
b2d6b4
    +                goto error;
b2d6b4
    +            }
b2d6b4
                 cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);
b2d6b4
b2d6b4
                 cursor_data__nw_size = cursor_data__nelements;
b2d6b4
    @@ -6670,6 +6682,9 @@
b2d6b4
             }
b2d6b4
b2d6b4
             { /* data */
b2d6b4
    +            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
b2d6b4
    +                goto error;
b2d6b4
    +            }
b2d6b4
                 cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);
b2d6b4
b2d6b4
                 cursor_data__nw_size = cursor_data__nelements;
b2d6b4
    @@ -6907,6 +6922,9 @@
b2d6b4
         SpiceMsgPlaybackPacket *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 4);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -6961,6 +6979,9 @@
b2d6b4
         SpiceMsgPlaybackMode *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 6) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 6);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -7559,6 +7580,9 @@
b2d6b4
         SpiceMsgTunnelSocketData *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 2) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 2);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -7840,6 +7864,9 @@
b2d6b4
         }
b2d6b4
b2d6b4
         { /* compressed_data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             compressed_data__nelements = message_end - (start + 1 + u__nw_size);
b2d6b4
b2d6b4
             compressed_data__nw_size = compressed_data__nelements;
b2d6b4
    diff -u save/generated_server_demarshallers.c common/generated_server_demarshallers.c
b2d6b4
    --- save/generated_server_demarshallers.c	2018-06-22 22:13:48.627793944 +0100
b2d6b4
    +++ common/generated_server_demarshallers.c	2018-06-22 22:14:05.231208847 +0100
b2d6b4
    @@ -306,6 +306,9 @@
b2d6b4
         uint64_t data__nelements;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 0);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -324,6 +327,9 @@
b2d6b4
         *free_message = nofree;
b2d6b4
         return data;
b2d6b4
b2d6b4
    +   error:
b2d6b4
    +    free(data);
b2d6b4
    +    return NULL;
b2d6b4
     }
b2d6b4
b2d6b4
     static uint8_t * parse_msgc_disconnecting(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
b2d6b4
    @@ -1259,6 +1265,9 @@
b2d6b4
         SpiceMsgcRecordPacket *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 4);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -1313,6 +1322,9 @@
b2d6b4
         SpiceMsgcRecordMode *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 6) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 6);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -1841,6 +1853,9 @@
b2d6b4
         SpiceMsgcTunnelSocketData *out;
b2d6b4
b2d6b4
         { /* data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 2) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             data__nelements = message_end - (start + 2);
b2d6b4
b2d6b4
             data__nw_size = data__nelements;
b2d6b4
    @@ -2057,6 +2072,9 @@
b2d6b4
         }
b2d6b4
b2d6b4
         { /* compressed_data */
b2d6b4
    +        if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
b2d6b4
    +            goto error;
b2d6b4
    +        }
b2d6b4
             compressed_data__nelements = message_end - (start + 1 + u__nw_size);
b2d6b4
b2d6b4
             compressed_data__nw_size = compressed_data__nelements;
b2d6b4
b2d6b4
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
b2d6b4
---
b2d6b4
 spice-common/python_modules/demarshal.py | 1 +
b2d6b4
 1 file changed, 1 insertion(+)
b2d6b4
b2d6b4
diff --git a/spice-common/python_modules/demarshal.py b/spice-common/python_modules/demarshal.py
b2d6b4
index 1ea131d..7172762 100644
b2d6b4
--- a/spice-common/python_modules/demarshal.py
b2d6b4
+++ b/spice-common/python_modules/demarshal.py
b2d6b4
@@ -318,6 +318,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
b2d6b4
         writer.assign(nelements, array.size)
b2d6b4
     elif array.is_remaining_length():
b2d6b4
         if element_type.is_fixed_nw_size():
b2d6b4
+            writer.error_check("%s > message_end" % item.get_position())
b2d6b4
             if element_type.get_fixed_nw_size() == 1:
b2d6b4
                 writer.assign(nelements, "message_end - %s" % item.get_position())
b2d6b4
             else:
b2d6b4
-- 
b2d6b4
2.17.1
b2d6b4