Browse code

interactive.c: Fix potential stack overflow issue

When reading message from the pipe, we first peek the pipe to get the size
of the message waiting to be read and then read the message. A compromised
OpenVPN process could send an excessively large message, which would result
in a stack-allocated message buffer overflow.

To address this, we terminate the misbehaving process if the peeked message
size exceeds the maximum allowable size.

This commit is backported from 9b2693f in release/2.6 branch, fixing
merge conflicts around &ring_buffer_handles and wins_cfg_message_t.

CVE: 2024-27459
Microsoft case number: 85932

Reported-by: Vladimir Tokarev <vtokarev@microsoft.com>
Change-Id: Ib5743cba0741ea11f9ee62c4978b2c6789b81ada
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Heiko Hund <heiko@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20240320082000.284-2-lev@openvpn.net>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28433.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Lev Stipakov authored on 2024/03/20 17:19:45
Showing 1 changed files
... ...
@@ -111,6 +111,17 @@ typedef struct {
111 111
     HANDLE device;
112 112
 } ring_buffer_handles_t;
113 113
 
114
+typedef union {
115
+    message_header_t header;
116
+    address_message_t address;
117
+    route_message_t route;
118
+    flush_neighbors_message_t flush_neighbors;
119
+    block_dns_message_t block_dns;
120
+    dns_cfg_message_t dns;
121
+    enable_dhcp_message_t dhcp;
122
+    register_ring_buffers_message_t rrb;
123
+    set_mtu_message_t mtu;
124
+} pipe_message_t;
114 125
 
115 126
 static DWORD
116 127
 AddListItem(list_item_t **pfirst, LPVOID data)
... ...
@@ -1444,18 +1455,7 @@ static VOID
1444 1444
 HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_handles,
1445 1445
               DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists)
1446 1446
 {
1447
-    DWORD read;
1448
-    union {
1449
-        message_header_t header;
1450
-        address_message_t address;
1451
-        route_message_t route;
1452
-        flush_neighbors_message_t flush_neighbors;
1453
-        block_dns_message_t block_dns;
1454
-        dns_cfg_message_t dns;
1455
-        enable_dhcp_message_t dhcp;
1456
-        register_ring_buffers_message_t rrb;
1457
-        set_mtu_message_t mtu;
1458
-    } msg;
1447
+    pipe_message_t msg;
1459 1448
     ack_message_t ack = {
1460 1449
         .header = {
1461 1450
             .type = msg_acknowledgement,
... ...
@@ -1465,7 +1465,7 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_
1465 1465
         .error_number = ERROR_MESSAGE_DATA
1466 1466
     };
1467 1467
 
1468
-    read = ReadPipeAsync(pipe, &msg, bytes, count, events);
1468
+    DWORD read = ReadPipeAsync(pipe, &msg, bytes, count, events);
1469 1469
     if (read != bytes || read < sizeof(msg.header) || read != msg.header.size)
1470 1470
     {
1471 1471
         goto out;
... ...
@@ -1884,6 +1884,13 @@ RunOpenvpn(LPVOID p)
1884 1884
             break;
1885 1885
         }
1886 1886
 
1887
+        if (bytes > sizeof(pipe_message_t))
1888
+        {
1889
+            /* process at the other side of the pipe is misbehaving, shut it down */
1890
+            MsgToEventLog(MSG_FLAGS_ERROR, TEXT("OpenVPN process sent too large payload length to the pipe (%lu bytes), it will be terminated"), bytes);
1891
+            break;
1892
+        }
1893
+
1887 1894
         HandleMessage(ovpn_pipe, proc_info.hProcess, &ring_buffer_handles, bytes, 1, &exit_event, &undo_lists);
1888 1895
     }
1889 1896