>Synopsis: display bug and complex length bug in tcpdump/print-icmp.c >Category: system >Environment: System : OpenBSD 7.2 Details : OpenBSD 7.2 (GENERIC.MP) #2: Thu Nov 24 23:53:03 MST 2022 r...@syspatch-72-arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
Architecture: OpenBSD.arm64 Machine : arm64 >Description: In the print-icmp.c code there is a while() near line 316 that goes through Router Advertisements (icmp type 9 code 0) but doesn't advance struct idp. My patch adds this, yet I was unable to test it. Also I'm not satisfied with the -vv option and printing the IP packet and it's payload the way it is done. Basically it passes print_ip() length parameter with what's given on the wire (as payload of the icmp) which will run through so many length checks in print_ip() it's not funny. In fact you could use this similar to a GRE specially crafted packet to increase some length that may point beyond snaplen. I'm thinking of some high length like 0xffff being put in there. I have done a calculation on what length it should be instead only it looks ugly but is more correct. Let me show you the captured tcpdumps next section. >How-To-Repeat: Normal before: root@echo# tcpdump -vv -n -i bse0 -s 1500 ip and icmp tcpdump: listening on bse0, link-type EN10MB 17:51:32.250143 192.168.177.14 > 192.168.177.13: icmp: 192.168.177.14 udp port 999 unreachable [icmp cksum ok] for 192.168.177.13.11143 > 192.168.177.14.999: udp 6 (ttl 64, id 6174, len 34) (ttl 255, id 42263, len 56) With my patch: root@echo# obj/tcpdump -vv -n -i bse0 -s 1500 ip and icmp tcpdump: listening on bse0, link-type EN10MB 17:51:00.810291 192.168.177.14 > 192.168.177.13: icmp: 192.168.177.14 udp port 999 unreachable [icmp cksum ok] for truncated-ip - 6 bytes missing!192.168.177.13.36685 > 192.168.177.14.999: truncated-udp - 6 bytes missing![bad udp cksum 5445! -> 3689] udp 0 (ttl 64, id 52444, len 34) (ttl 255, id 58823, len 56) ^C As seen in the hexdump the packet is really missing data: Normal before: 17:55:22.936602 192.168.177.14 > 192.168.177.13: icmp: 192.168.177.14 udp port 999 unreachable [icmp cksum ok] for 192.168.177.13.37982 > 192.168.177.14.999: udp 6 (ttl 64, id 17991, len 34) (ttl 255, id 44077, len 56) 0000: 4500 0038 ac2d 0000 ff01 2c2a c0a8 b10e E..8.-....,*.... 0010: c0a8 b10d 0303 2466 0000 0000 4500 0022 ......$f....E.." 0020: 4647 0000 4011 5117 c0a8 b10d c0a8 b10e FG..@.Q......... 0030: 945e 03e7 000e 4043 .^....@C With my patch: 17:56:09.560294 192.168.177.14 > 192.168.177.13: icmp: 192.168.177.14 udp port 999 unreachable [icmp cksum ok] for truncated-ip - 6 bytes missing!192.168.177.13.22420 > 192.168.177.14.999: truncated-udp - 6 bytes missing![bad udp cksum 0d7d! -> efc0] udp 0 (ttl 64, id 316, len 34) (ttl 255, id 20015, len 56) 0000: 4500 0038 4e2f 0000 ff01 8a28 c0a8 b10e E..8N/.....(.... 0010: c0a8 b10d 0303 2466 0000 0000 4500 0022 ......$f....E.." 0020: 013c 0000 4011 9622 c0a8 b10d c0a8 b10e .<..@.."........ 0030: 5794 03e7 000e 7d0d W.....}. >Fix: The patch: Index: print-icmp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-icmp.c,v retrieving revision 1.27 diff -u -p -u -r1.27 print-icmp.c --- print-icmp.c 1 Dec 2021 18:28:46 -0000 1.27 +++ print-icmp.c 1 Mar 2023 16:49:55 -0000 @@ -319,6 +319,7 @@ icmp_print(const u_char *bp, u_int lengt ipaddr_string(&idp->ird_addr), EXTRACT_32BITS(&idp->ird_pref)); strlcat(buf, buf2, sizeof(buf)); + idp++; } } break; @@ -385,9 +386,13 @@ icmp_print(const u_char *bp, u_int lengt } if (vflag > 1 && !ICMP_INFOTYPE(dp->icmp_type) && TTEST(dp->icmp_ip)) { + int ilen; printf(" for "); oip = &dp->icmp_ip; - ip_print((u_char *)oip, ntohs(oip->ip_len)); + ilen = length - ((u_char *)oip - (u_char *)bp); + if (ilen <= 0 || ilen > length) + goto trunc; + ip_print((u_char *)oip, ilen); } return; trunc: dmesg: My host hasn't changed.