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

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