056dc8
From 4b05d4b5d70c1ba76d95f94f1f4821c4b715fefe Mon Sep 17 00:00:00 2001
056dc8
From: Richard Cochran <richardcochran@gmail.com>
056dc8
Date: Sat, 17 Apr 2021 15:15:18 -0700
056dc8
Subject: [PATCH 2/2] Validate the messageLength field of incoming messages.
056dc8
056dc8
The PTP messageLength field is redundant because the length of a PTP
056dc8
message is precisely determined by the message type and the appended
056dc8
TLVs.  The current implementation validates the sizes of both the main
056dc8
message (according to the fixed header length and fixed length by
056dc8
type) and the TLVs (by using the 'L' of the TLV).
056dc8
056dc8
However, when forwarding a message, the messageLength field is used.
056dc8
If a message arrives with a messageLength field larger than the actual
056dc8
message size, the code will read and possibly write data beyond the
056dc8
allocated buffer.
056dc8
056dc8
Fix the issue by validating the field on ingress.  This prevents
056dc8
reading and sending data past the message buffer when forwarding a
056dc8
management message or other messages when operating as a transparent
056dc8
clock, and it also prevents a memory corruption in msg_post_recv()
056dc8
after forwarding a management message.
056dc8
056dc8
Reported-by: Miroslav Lichvar <mlichvar@redhat.com>
056dc8
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
056dc8
---
056dc8
 msg.c | 18 ++++++++++++------
056dc8
 1 file changed, 12 insertions(+), 6 deletions(-)
056dc8
056dc8
diff --git a/msg.c b/msg.c
056dc8
index dcb397c..c2d358b 100644
056dc8
--- a/msg.c
056dc8
+++ b/msg.c
056dc8
@@ -184,7 +184,7 @@ static int suffix_post_recv(struct ptp_message *msg, int len)
056dc8
 {
056dc8
 	uint8_t *ptr = msg_suffix(msg);
056dc8
 	struct tlv_extra *extra;
056dc8
-	int err;
056dc8
+	int err, suffix_len = 0;
056dc8
 
056dc8
 	if (!ptr)
056dc8
 		return 0;
056dc8
@@ -202,12 +202,14 @@ static int suffix_post_recv(struct ptp_message *msg, int len)
056dc8
 			tlv_extra_recycle(extra);
056dc8
 			return -EBADMSG;
056dc8
 		}
056dc8
+		suffix_len += sizeof(struct TLV);
056dc8
 		len -= sizeof(struct TLV);
056dc8
 		ptr += sizeof(struct TLV);
056dc8
 		if (extra->tlv->length > len) {
056dc8
 			tlv_extra_recycle(extra);
056dc8
 			return -EBADMSG;
056dc8
 		}
056dc8
+		suffix_len += extra->tlv->length;
056dc8
 		len -= extra->tlv->length;
056dc8
 		ptr += extra->tlv->length;
056dc8
 		err = tlv_post_recv(extra);
056dc8
@@ -217,7 +219,7 @@ static int suffix_post_recv(struct ptp_message *msg, int len)
056dc8
 		}
056dc8
 		msg_tlv_attach(msg, extra);
056dc8
 	}
056dc8
-	return 0;
056dc8
+	return suffix_len;
056dc8
 }
056dc8
 
056dc8
 static void suffix_pre_send(struct ptp_message *msg)
056dc8
@@ -335,7 +337,7 @@ void msg_get(struct ptp_message *m)
056dc8
 
056dc8
 int msg_post_recv(struct ptp_message *m, int cnt)
056dc8
 {
056dc8
-	int pdulen, type, err;
056dc8
+	int err, pdulen, suffix_len, type;
056dc8
 
056dc8
 	if (cnt < sizeof(struct ptp_header))
056dc8
 		return -EBADMSG;
056dc8
@@ -420,9 +422,13 @@ int msg_post_recv(struct ptp_message *m, int cnt)
056dc8
 		break;
056dc8
 	}
056dc8
 
056dc8
-	err = suffix_post_recv(m, cnt - pdulen);
056dc8
-	if (err)
056dc8
-		return err;
056dc8
+	suffix_len = suffix_post_recv(m, cnt - pdulen);
056dc8
+	if (suffix_len < 0) {
056dc8
+		return suffix_len;
056dc8
+	}
056dc8
+	if (pdulen + suffix_len != m->header.messageLength) {
056dc8
+		return -EBADMSG;
056dc8
+	}
056dc8
 
056dc8
 	return 0;
056dc8
 }
056dc8
-- 
056dc8
2.20.1
056dc8