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

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