Skip to contentSkip to conversation

batctl: tcpdump - parse TVLV containers

PATCH Applied Antonio Quartulli 3 participants 4 messages Nov 2, 2014 – Nov 12, 2014

lore
Share & tools
lore
#0 lore raw

PATCH v5 1/1 batctl: tcpdump - parse TVLV containers

From: Antonio Quartulli <[email protected]>

OGMs and unicast TVLV packets carry TVLV containers as payload.
With this patch such containers are now parsed and the relevant information is printed to screen.

---

changes since v4:
- avoid warning in LEN_CHECK macro

changes since v3:
- undo unneeded style change in tcpdump.c
- remove unneeded sentence about style change sin commit message

changes since v2:
- extended doc in README and manpage

changes since v1:
- remove all the style changes
- make tvlv_len of type ssize_t in dump_batman_iv_ogm()

 README       |   1 +
 main.h       |   7 +++
 man/batctl.8 |   3 ++
 tcpdump.c    | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 tcpdump.h    |   1 +
 5 files changed, 177 insertions(+), 4 deletions(-)
README +1 -0
index b5fd259..f87c551 100644
@@ -161,6 +161,7 @@ packet types:
                   2 - batman icmp packets
                   4 - batman unicast packets
                   8 - batman broadcast packets
+                 16 - batman unicast tvlv packets
                  32 - batman fragmented packets
                  64 - batman tt / roaming packets
                 128 - non batman packets
main.h +7 -0
index 839c1c7..b16afb6 100644
@@ -49,4 +49,11 @@
 
 extern char module_ver_path[];
 
+#ifndef VLAN_VID_MASK
+#define VLAN_VID_MASK   0xfff
+#endif
+
+#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \
+			       (int)(vid & VLAN_VID_MASK) : -1)
+
 #endif
man/batctl.8 +3 -0
index 110020e..8d2de19 100644
@@ -288,6 +288,9 @@ except specified). The following packet types are available:
 8 - batman broadcast packets
 .RE
 .RS 16
+16 - batman unicast tvlv packets
+.RE
+.RS 16
 32 - batman fragmented packets
 .RE
 .RS 16
tcpdump.c +165 -4

212 lines not on this page · raw message

tcpdump.h +1 -0
index cfb1c69..5d936f2 100644
@@ -41,6 +41,7 @@
 #define DUMP_TYPE_BATICMP 2
 #define DUMP_TYPE_BATUCAST 4
 #define DUMP_TYPE_BATBCAST 8
+#define DUMP_TYPE_BATUTVLV 16
 #define DUMP_TYPE_BATFRAG 32
 #define DUMP_TYPE_NONBAT 128
 
Signature · 1 line
2.1.3
#1 lore raw
Quoted 8 lines · On Sunday 02 November 2014 09:38:04 Antonio Quartulli wrote:

From: Antonio Quartulli <[email protected]>

OGMs and unicast TVLV packets carry TVLV containers as payload.
With this patch such containers are now parsed and the relevant information is printed to screen.

Applied in revision 4c39fb8.

Thanks,
Marek

#2 lore raw
In reply to Antonio Quartulli
Quoted 12 lines
tcpdump.c +12 -0
+typedef void (*batctl_tvlv_parser_t)(void *buff, ssize_t buff_len);
+
+/* location [i][j] contains the parsing function for TVLV of type 'i' and
+ * version 'j + 1'
+ */
+batctl_tvlv_parser_t tvlv_parsers[][1] = {
+       [BATADV_TVLV_GW][0] = batctl_tvlv_parse_gw_v1,
+       [BATADV_TVLV_DAT][0] = batctl_tvlv_parse_dat_v1,
+       [BATADV_TVLV_NC][0] = batctl_tvlv_parse_nc_v1,
+       [BATADV_TVLV_TT][0] = batctl_tvlv_parse_tt_v1,
+       [BATADV_TVLV_ROAM][0] = batctl_tvlv_parse_roam_v1,
+};

[....]

Quoted 13 lines
tcpdump.c +13 -0
+       while (tvlv_len > 0) {
+               tvlv_hdr = (struct batadv_tvlv_hdr *)ptr;
+               len = ntohs(tvlv_hdr->len);
+
+               parser = tvlv_parsers[tvlv_hdr->type][tvlv_hdr->version - 1];
+               parser(tvlv_hdr + 1, len);
+
+               /* go to the next container */
+               ptr = (uint8_t *)(tvlv_hdr + 1) + len;
+               tvlv_len -= sizeof(*tvlv_hdr) + len;
+       }
+}
+

[....]

tcpdump.c static void dump_batman_iv_ogm(unsigned char *packet_buff, ssize_t buff_len, int · line 661

Quoted 12 lines
tcpdump.c +11 -0
+       while (tvlv_len > 0) {
+               tvlv_hdr = (struct batadv_tvlv_hdr *)ptr;
+               len = ntohs(tvlv_hdr->len);
+
+               parser = tvlv_parsers[tvlv_hdr->type][tvlv_hdr->version - 1];
+               parser(tvlv_hdr + 1, len);
+
+               /* go to the next container */
+               ptr = (uint8_t *)(tvlv_hdr + 1) + len;
+               tvlv_len -= sizeof(*tvlv_hdr) + len;
+       }
 }

I've already explained this to Antonio but here again in public:

* neither type nor version are validated
* the type can point in tvlv_parsers to an invalid (non-existing) entry
* the version of this entry can also point to an invalid parser
* this is a big problem because I can crash batctl td with data packets send from other people (even valid data packets with mcast tvlv)
* I've already experienced this problem when using nodes from a company which ships this patch since a while (> 4 months)

Maybe it can be redone with some switch statements or
(more space consuming) full tables which can handle all input data. Of course a check of the returned parser is still necessary inside the loops.

Kind regards,
Sven

#3 lore raw

On Tuesday 11 November 2014 23:56:03 Sven Eckelmann wrote:
[...]

Quoted 10 lines

I've already explained this to Antonio but here again in public:

* neither type nor version are validated
* the type can point in tvlv_parsers to an invalid (non-existing) entry
* the version of this entry can also point to an invalid parser
* this is a big problem because I can crash batctl td with data packets send from other people (even valid data packets with mcast tvlv)
* I've already experienced this problem when using nodes from a company which ships this patch since a while (> 4 months)

Quoted 6 lines

Maybe it can be redone with some switch statements or
(more space consuming) full tables which can handle all input data. Of course a check of the returned parser is still necessary inside the loops.

Kind regards,
Sven

For people who require a direct experience of the crash with normal traffic send by batman-adv:

1. compile batctl:
CFLAGS="-g3 -fsanitize=address -fsanitize=undefined -fsanitize=leak" make
2. Start it on some interfaceL
sudo ./batctl td eth0
3. run on another console tcpreplay on the same interface:
sudo tcpreplay -i eth0 v15_iv_ogm.pcapng
4. experience the crash:

10:17:28.724487 BAT 00:21:cc:b4:82:33: OGM IV via neigh 00:21:cc:b4:82:33, seq 3093200194, tq 255, ttl 50, v 15, flags [..F], length 68, tvlv_len 44

        TVLV TTv1: OGM DIFF [.] ttvn=4 vlan_num=1 entry_num=0
                VLAN ID -1, crc 0xb8d4beb4
        TVLV GWv1: down 10.0Mbps, up 2.0Mbps
=================================================================
==4213==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000639410 at pc 0x415f75 bp 0x7ffff4a02c70 sp 0x7ffff4a02c68
READ of size 8 at 0x000000639410 thread T0
    #0 0x415f74 in dump_batman_iv_ogm batctl/tcpdump.c:654
    #1 0x41710e in parse_eth_hdr batctl/tcpdump.c:825
    #2 0x4195c8 in tcpdump batctl/tcpdump.c:1118
    #3 0x403b7a in main batctl/main.c:146
    #4 0x7fd0f52dbb44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #5 0x4029d8 (batctl+0x4029d8)

0x000000639410 is located 0 bytes to the right of global variable 'tvlv_parsers' from 'tcpdump.c' (0x6393e0) of size 48 0x000000639410 is located 48 bytes to the left of global variable '*.Lubsan_type7' from 'tcpdump.c' (0x639440) of size 4
SUMMARY: AddressSanitizer: global-buffer-overflow batctl/tcpdump.c:654 dump_batman_iv_ogm
Shadow bytes around the buggy address:
0x0000800bf230: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 f9 f9 f9
0x0000800bf240: f9 f9 f9 f9 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
0x0000800bf250: 00 00 00 f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
0x0000800bf260: 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
0x0000800bf270: 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
=>0x0000800bf280: 00 00[f9]f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
0x0000800bf290: 00 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9
0x0000800bf2a0: f9 f9 f9 f9 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
0x0000800bf2b0: 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
0x0000800bf2c0: 00 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
0x0000800bf2d0: 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07

  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7

Contiguous container OOB:fc
ASan internal: fe
==4213==ABORTING

Kind regards,
Sven