From faea24aa328dc5254a687f7f67fd78bbd7c1e7fd Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sun, 5 Apr 2020 18:08:27 -0700 Subject: [PATCH] Reject path trace TLVs with excessive elements. The current code truncates the size of path trace TLVs which exceed the expected maximum based on the largest possible message size. However if another TLV follows, then a gap would appear, that is, an area in the message buffer not pointed to by any TLV descriptor. In order to avoid forwarding such malformed messages, this patch changes the logic to reject them. Signed-off-by: Richard Cochran --- tlv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tlv.c b/tlv.c index 2440482..6ab54a5 100644 --- a/tlv.c +++ b/tlv.c @@ -18,6 +18,7 @@ */ #include #include +#include #include #include @@ -79,6 +80,17 @@ static int64_t net2host64_unaligned(int64_t *p) return v; } +static bool tlv_array_invalid(struct TLV *tlv, size_t base_size, size_t item_size) +{ + size_t expected_length, n_items; + + n_items = (tlv->length - base_size) / item_size; + + expected_length = base_size + n_items * item_size; + + return (tlv->length == expected_length) ? false : true; +} + static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, struct tlv_extra *extra) { @@ -678,11 +690,10 @@ void tlv_extra_recycle(struct tlv_extra *extra) int tlv_post_recv(struct tlv_extra *extra) { - int result = 0; - struct management_tlv *mgt; struct management_error_status *mes; struct TLV *tlv = extra->tlv; - struct path_trace_tlv *ptt; + struct management_tlv *mgt; + int result = 0; switch (tlv->type) { case TLV_MANAGEMENT: @@ -712,9 +723,8 @@ int tlv_post_recv(struct tlv_extra *extra) result = unicast_negotiation_post_recv(extra); break; case TLV_PATH_TRACE: - ptt = (struct path_trace_tlv *) tlv; - if (path_length(ptt) > PATH_TRACE_MAX) { - ptt->length = PATH_TRACE_MAX * sizeof(struct ClockIdentity); + if (tlv_array_invalid(tlv, 0, sizeof(struct ClockIdentity))) { + goto bad_length; } break; case TLV_ALTERNATE_TIME_OFFSET_INDICATOR: