A TTv1 has a constant header part and two variable parts. One is the defined by the number of VLANs and the rest are the changes. The TVLV can only be parsed when there is enough room for the constant header. Also the number of VLANs must be validated. Otherwise the TVLV parser can read invalid data outside of the buffer.
This regression was introduced by 4c39fb823b86036df40187f8bd342fe5398c28ef ("batctl: tcpdump - parse TVLV containers").
Signed-off-by: Sven Eckelmann sven@narfation.org --- tcpdump.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tcpdump.c b/tcpdump.c index 361deb3..50ba010 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -142,13 +142,15 @@ static void batctl_tvlv_parse_nc_v1(void (*buff)__attribute__((unused)), printf("\tTVLV NCv1: enabled\n"); }
-static void batctl_tvlv_parse_tt_v1(void *buff, - ssize_t (buff_len)__attribute__((unused))) +static void batctl_tvlv_parse_tt_v1(void *buff, ssize_t buff_len) { struct batadv_tvlv_tt_data *tvlv = buff; struct batadv_tvlv_tt_vlan_data *vlan; int i, num_vlan, num_entry; const char *type; + size_t vlan_len; + + LEN_CHECK(buff_len, sizeof(*tvlv), "TVLV TTv1")
if (tvlv->flags & BATADV_TT_OGM_DIFF) type = "OGM DIFF"; @@ -160,7 +162,10 @@ static void batctl_tvlv_parse_tt_v1(void *buff, type = "UNKNOWN";
num_vlan = ntohs(tvlv->num_vlan); - buff_len -= sizeof(*tvlv) + sizeof(*vlan) * num_vlan; + vlan_len = sizeof(*tvlv) + sizeof(*vlan) * num_vlan; + LEN_CHECK(buff_len, vlan_len, "TVLV TTv1 VLAN") + + buff_len -= vlan_len; num_entry = buff_len / sizeof(struct batadv_tvlv_tt_change);
printf("\tTVLV TTv1: %s [%c] ttvn=%hhu vlan_num=%hu entry_num=%hu\n",