@@ -68,35 +68,47 @@ static struct remote_header_v0 *
68
68
localized_remote_header (pcmk__remote_t * remote )
69
69
{
70
70
struct remote_header_v0 * header = NULL ;
71
- uint32_t endian_swapped = 0 ;
72
71
73
72
if ((remote == NULL ) || (remote -> buffer == NULL )
74
73
|| (remote -> buffer_offset < sizeof (struct remote_header_v0 ))) {
74
+
75
+ // Caller error or we haven't received the full header yet
75
76
return NULL ;
76
77
}
77
78
78
79
header = (struct remote_header_v0 * ) remote -> buffer ;
79
- if (header -> endian == ENDIAN_LOCAL ) {
80
- return header ;
81
- }
82
-
83
- endian_swapped = GUINT32_SWAP_LE_BE (header -> endian );
84
- CRM_CHECK (endian_swapped == ENDIAN_LOCAL ,
85
- crm_err ("Invalid message detected (endian mismatch): local magic "
86
- "number %" PRIx32 " matches neither the header's magic "
87
- "number %" PRIx32 " nor the byte-swapped form %" PRIx32 ,
88
- ENDIAN_LOCAL , header -> endian , endian_swapped );
89
- return NULL );
90
-
91
- header -> endian = endian_swapped ;
92
- header -> version = GUINT32_SWAP_LE_BE (header -> version );
93
- header -> id = GUINT64_SWAP_LE_BE (header -> id );
94
- header -> flags = GUINT64_SWAP_LE_BE (header -> flags );
95
- header -> size_total = GUINT32_SWAP_LE_BE (header -> size_total );
96
- header -> payload_offset = GUINT32_SWAP_LE_BE (header -> payload_offset );
97
- header -> payload_compressed = GUINT32_SWAP_LE_BE (header -> payload_compressed );
98
- header -> payload_uncompressed =
99
- GUINT32_SWAP_LE_BE (header -> payload_uncompressed );
80
+ if (header -> endian != ENDIAN_LOCAL ) {
81
+ uint32_t endian_swapped = GUINT32_SWAP_LE_BE (header -> endian );
82
+
83
+ CRM_CHECK (endian_swapped == ENDIAN_LOCAL ,
84
+ crm_err ("Invalid message detected (endian mismatch): local "
85
+ "magic number %" PRIx32 " matches neither the "
86
+ "header's magic number %" PRIx32 " nor the "
87
+ "byte-swapped form %" PRIx32 ,
88
+ ENDIAN_LOCAL , header -> endian , endian_swapped );
89
+ return NULL );
90
+
91
+ header -> endian = endian_swapped ;
92
+ header -> version = GUINT32_SWAP_LE_BE (header -> version );
93
+ header -> id = GUINT64_SWAP_LE_BE (header -> id );
94
+ header -> flags = GUINT64_SWAP_LE_BE (header -> flags );
95
+ header -> size_total = GUINT32_SWAP_LE_BE (header -> size_total );
96
+ header -> payload_offset = GUINT32_SWAP_LE_BE (header -> payload_offset );
97
+ header -> payload_compressed =
98
+ GUINT32_SWAP_LE_BE (header -> payload_compressed );
99
+ header -> payload_uncompressed =
100
+ GUINT32_SWAP_LE_BE (header -> payload_uncompressed );
101
+ }
102
+
103
+ // Sanity checks
104
+ if (header -> payload_offset != sizeof (struct remote_header_v0 )) {
105
+ return NULL ;
106
+ }
107
+ if ((header -> payload_offset
108
+ + header -> payload_compressed
109
+ + header -> payload_uncompressed ) != header -> size_total ) {
110
+ return NULL ;
111
+ }
100
112
101
113
return header ;
102
114
}
@@ -268,6 +280,8 @@ xmlNode *
268
280
pcmk__remote_message_xml (pcmk__remote_t * remote )
269
281
{
270
282
xmlNode * xml = NULL ;
283
+ size_t data_size = 0 ;
284
+ char * payload = NULL ;
271
285
struct remote_header_v0 * header = localized_remote_header (remote );
272
286
273
287
if (header == NULL ) {
@@ -315,18 +329,33 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
315
329
/* take ownership of the buffer */
316
330
remote -> buffer_offset = 0 ;
317
331
318
- CRM_LOG_ASSERT ( remote -> buffer [ sizeof ( struct remote_header_v0 ) + header -> payload_uncompressed - 1 ] == 0 ) ;
332
+ data_size = ( size_t ) header -> payload_offset + header -> payload_uncompressed ;
319
333
320
- xml = pcmk__xml_parse (remote -> buffer + header -> payload_offset );
321
- if (xml == NULL && header -> version > REMOTE_MSG_VERSION ) {
322
- crm_warn ("Couldn't parse v%d message, we only understand v%d" ,
323
- header -> version , REMOTE_MSG_VERSION );
334
+ // Ensure the buffer is as big as it should be
335
+ CRM_CHECK (remote -> buffer_size >= data_size , return NULL );
324
336
325
- } else if (xml == NULL ) {
326
- crm_err ("Couldn't parse: '%.120s'" , remote -> buffer + header -> payload_offset );
327
- }
337
+ /* Ensure the buffer is null-terminated (see
338
+ * pcmk__read_available_remote_data()).
339
+ *
340
+ * Note that payload_uncompressed contains the payload size including the
341
+ * null byte (see pcmk__remote_send_xml()).
342
+ */
343
+ CRM_CHECK (remote -> buffer [data_size ] == '\0' , return NULL );
344
+
345
+ payload = remote -> buffer + header -> payload_offset ;
346
+
347
+ xml = pcmk__xml_parse (payload );
348
+ if (xml == NULL ) {
349
+ if (header -> version > REMOTE_MSG_VERSION ) {
350
+ crm_warn ("Couldn't parse v%d message, we only understand v%d" ,
351
+ header -> version , REMOTE_MSG_VERSION );
352
+ } else {
353
+ crm_err ("Couldn't parse: '%.120s'" , payload );
354
+ }
328
355
329
- crm_log_xml_trace (xml , "[remote msg]" );
356
+ } else {
357
+ crm_log_xml_trace (xml , "[remote msg]" );
358
+ }
330
359
return xml ;
331
360
}
332
361
0 commit comments