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

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