Переглянути джерело

totempg: Fix fragmentation segfault

The problem was that two or more messages were concatenated
together during fragmentation in mcast_msg() function. In specific case,
message of just short of 1MB was provided for mcast_msg() and it
happened so, that the remainder (212 bytes to be exact) left some free
space in packet, therefore branch

  if ((copy_len + fragment_size) <
    (max_packet_size - sizeof (unsigned short))) {
...

was selected and this was the last mesage in provided iovec.
Then, on the second call, came another big message (about 300KB ) and
during fragmentation mcast.fragmented was set to 1.

On the other end, while receiving messages, due to missing
mcast.fragmentation==0 those two messages were concatenated and
therefore assembly->data array overflowed overwriting linked list
pointers and offset (which happened to be set to 0 and that 300KB
message was being copied from the beginning again).
After whole 300KB message has been sent, mcast.fragmentation==0 arrived
and totempg_deliver_fn() tried to move assembly structure to
assembly_list_free list, but as linked list pointers has been overriden,
segfault occured.

(backported from master 0ebae6b47d39940c62dcbd9185b9af2f265a47ff)

Signed-off-by: Rytis Karpuška <rytisk@neurotechnology.com>
Reviewed-by: Jan Friesse <jfriesse@redhat.com>
Rytis Karpuška 8 роки тому
батько
коміт
0dec7fa589
1 змінених файлів з 2 додано та 2 видалено
  1. 2 2
      exec/totempg.c

+ 2 - 2
exec/totempg.c

@@ -915,7 +915,7 @@ static int mcast_msg (
 		 * fragment_buffer on exit so that max_packet_size + fragment_size
 		 * doesn't exceed the size of the fragment_buffer on the next call.
 		 */
-		if ((copy_len + fragment_size) <
+		if ((iovec[i].iov_len + fragment_size) <
 			(max_packet_size - sizeof (unsigned short))) {
 
 			memcpy (&fragmentation_data[fragment_size],
@@ -973,7 +973,7 @@ static int mcast_msg (
 			iovecs[1].iov_len = mcast_packed_msg_count *
 				sizeof(unsigned short);
 			iovecs[2].iov_base = (void *)data_ptr;
-			iovecs[2].iov_len = max_packet_size;
+			iovecs[2].iov_len = fragment_size + copy_len;
 			assert (totemmrp_avail() > 0);
 			res = totemmrp_mcast (iovecs, 3, guarantee);
 			if (res == -1) {