Skip to content

Commit 641bd6e

Browse files
committed
IP6OPTS: Modernize packet parsing and make fixes
Define ND_LONGJMP_FROM_TCHECK and remove four 'trunc' labels. Report invalid packets as invalid with a reason, not truncated. Use ND_ICHECKMSG_U() for some length tests and add four 'invalid' labels. Update the output for unknown options/suboptions. Use some unsigned when needed. Add some 'const'. Update the outputs of some tests accordingly.
1 parent f8d50ec commit 641bd6e

8 files changed

+52
-83
lines changed

print-ip6opts.c

Lines changed: 45 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -33,114 +33,92 @@
3333

3434
#include "netdissect-stdinc.h"
3535

36+
#define ND_LONGJMP_FROM_TCHECK
3637
#include "netdissect.h"
3738
#include "addrtoname.h"
3839
#include "extract.h"
3940

4041
#include "ip6.h"
4142

4243
static int
43-
ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len)
44+
ip6_sopt_print(netdissect_options *ndo, const u_char *bp, const u_int len)
4445
{
45-
int i;
46-
int optlen;
46+
unsigned int i, opttype, optlen;
4747

4848
for (i = 0; i < len; i += optlen) {
49-
if (GET_U_1(bp + i) == IP6OPT_PAD1)
49+
opttype = GET_U_1(bp + i);
50+
if (opttype == IP6OPT_PAD1)
5051
optlen = 1;
5152
else {
52-
if (i + 1 < len)
53-
optlen = GET_U_1(bp + i + 1) + 2;
54-
else
55-
goto trunc;
53+
ND_ICHECKMSG_U("remaining length", (u_int)(len - i), <,
54+
IP6OPT_MINLEN);
55+
optlen = GET_U_1(bp + i + 1) + 2;
5656
}
57-
if (i + optlen > len)
58-
goto trunc;
57+
ND_ICHECKMSG_U("remaining length", (u_int)(len - i), <, optlen);
58+
ND_TCHECK_LEN(bp + i, optlen);
5959

60-
switch (GET_U_1(bp + i)) {
60+
switch (opttype) {
6161
case IP6OPT_PAD1:
6262
ND_PRINT(", pad1");
6363
break;
6464
case IP6OPT_PADN:
65-
if (len - i < IP6OPT_MINLEN) {
66-
ND_PRINT(", padn: trunc");
67-
goto trunc;
68-
}
6965
ND_PRINT(", padn");
7066
break;
7167
default:
72-
if (len - i < IP6OPT_MINLEN) {
73-
ND_PRINT(", sopt_type %u: trunc)", GET_U_1(bp + i));
74-
goto trunc;
75-
}
76-
ND_PRINT(", sopt_type 0x%02x: len=%u", GET_U_1(bp + i),
77-
GET_U_1(bp + i + 1));
68+
ND_PRINT(", unknown subopt-type 0x%02x len=%u", opttype, optlen - 2);
7869
break;
7970
}
8071
}
8172
return 0;
8273

83-
trunc:
74+
invalid:
8475
return -1;
8576
}
8677

8778
static int
88-
ip6_opt_process(netdissect_options *ndo, const u_char *bp, int len,
79+
ip6_opt_process(netdissect_options *ndo, const u_char *bp, const u_int len,
8980
int *found_jumbop, uint32_t *payload_len)
9081
{
91-
int i;
92-
int optlen = 0;
82+
unsigned int i, opttype, optlen;
9383
int found_jumbo = 0;
9484
uint32_t jumbolen = 0;
9585

9686
if (len == 0)
9787
return 0;
9888
for (i = 0; i < len; i += optlen) {
99-
if (GET_U_1(bp + i) == IP6OPT_PAD1)
89+
opttype = GET_U_1(bp + i);
90+
if (opttype == IP6OPT_PAD1)
10091
optlen = 1;
10192
else {
102-
if (i + 1 < len)
103-
optlen = GET_U_1(bp + i + 1) + 2;
104-
else
105-
goto trunc;
93+
ND_ICHECKMSG_U("remaining length", (u_int)(len - i), <,
94+
IP6OPT_MINLEN);
95+
optlen = GET_U_1(bp + i + 1) + 2;
10696
}
107-
if (i + optlen > len)
108-
goto trunc;
97+
ND_ICHECKMSG_U("remaining length", (u_int)(len - i), <, optlen);
98+
ND_TCHECK_LEN(bp + i, optlen);
10999

110-
switch (GET_U_1(bp + i)) {
100+
switch (opttype) {
111101
case IP6OPT_PAD1:
112102
if (ndo->ndo_vflag)
113103
ND_PRINT("(pad1)");
114104
break;
115105
case IP6OPT_PADN:
116-
if (len - i < IP6OPT_MINLEN) {
117-
ND_PRINT("(padn: trunc)");
118-
goto trunc;
119-
}
120106
if (ndo->ndo_vflag)
121107
ND_PRINT("(padn)");
122108
break;
123109
case IP6OPT_ROUTER_ALERT:
124-
if (len - i < IP6OPT_RTALERT_LEN) {
125-
ND_PRINT("(rtalert: trunc)");
126-
goto trunc;
127-
}
128-
if (GET_U_1(bp + i + 1) != IP6OPT_RTALERT_LEN - 2) {
129-
ND_PRINT("(rtalert: invalid len %u)", GET_U_1(bp + i + 1));
130-
goto trunc;
131-
}
110+
ND_ICHECKMSG_U("(rtalert) remaining length", (u_int)(len - i), <,
111+
IP6OPT_RTALERT_LEN);
112+
ND_ICHECKMSG_U("(rtalert) length", optlen - 2, !=,
113+
IP6OPT_RTALERT_LEN - 2);
132114
if (ndo->ndo_vflag)
133115
ND_PRINT("(rtalert: 0x%04x) ", GET_BE_U_2(bp + i + 2));
134116
break;
135117
case IP6OPT_JUMBO:
136-
if (len - i < IP6OPT_JUMBO_LEN) {
137-
ND_PRINT("(jumbo: trunc)");
138-
goto trunc;
139-
}
140-
if (GET_U_1(bp + i + 1) != IP6OPT_JUMBO_LEN - 2) {
141-
ND_PRINT("(jumbo: invalid len %u)", GET_U_1(bp + i + 1));
142-
goto trunc;
143-
}
118+
ND_ICHECKMSG_U("(jumbo) remaining length", (u_int)(len - i), <,
119+
IP6OPT_JUMBO_LEN);
120+
ND_ICHECKMSG_U("(jumbo) length", optlen - 2, !=,
121+
IP6OPT_JUMBO_LEN - 2);
144122
jumbolen = GET_BE_U_4(bp + i + 2);
145123
if (found_jumbo) {
146124
/* More than one Jumbo Payload option */
@@ -176,40 +154,31 @@ ip6_opt_process(netdissect_options *ndo, const u_char *bp, int len,
176154
}
177155
break;
178156
case IP6OPT_HOME_ADDRESS:
179-
if (len - i < IP6OPT_HOMEADDR_MINLEN) {
180-
ND_PRINT("(homeaddr: trunc)");
181-
goto trunc;
182-
}
183-
if (GET_U_1(bp + i + 1) < IP6OPT_HOMEADDR_MINLEN - 2) {
184-
ND_PRINT("(homeaddr: invalid len %u)", GET_U_1(bp + i + 1));
185-
goto trunc;
186-
}
157+
ND_ICHECKMSG_U("(homeaddr) remaining length", (u_int)(len - i), <,
158+
IP6OPT_HOMEADDR_MINLEN);
159+
ND_ICHECKMSG_U("(homeaddr) length", optlen - 2, <,
160+
IP6OPT_HOMEADDR_MINLEN - 2);
187161
if (ndo->ndo_vflag) {
188162
ND_PRINT("(homeaddr: %s", GET_IP6ADDR_STRING(bp + i + 2));
189-
if (GET_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
163+
if (optlen > IP6OPT_HOMEADDR_MINLEN) {
190164
if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
191165
(optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
192-
goto trunc;
166+
goto invalid;
193167
}
194168
ND_PRINT(")");
195169
}
196170
break;
197171
default:
198-
if (len - i < IP6OPT_MINLEN) {
199-
ND_PRINT("(type %u: trunc)", GET_U_1(bp + i));
200-
goto trunc;
201-
}
202172
if (ndo->ndo_vflag)
203-
ND_PRINT("(opt_type 0x%02x: len=%u)", GET_U_1(bp + i),
204-
GET_U_1(bp + i + 1));
173+
ND_PRINT("(unknown opt-type 0x%02x len=%u)", opttype, optlen - 2);
205174
break;
206175
}
207176
}
208177
if (ndo->ndo_vflag)
209178
ND_PRINT(" ");
210179
return 0;
211180

212-
trunc:
181+
invalid:
213182
return -1;
214183
}
215184

@@ -227,11 +196,11 @@ hbhopt_process(netdissect_options *ndo, const u_char *bp, int *found_jumbo,
227196
ND_PRINT(" ");
228197
if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
229198
hbhlen - sizeof(*dp), found_jumbo, jumbolen) == -1)
230-
goto trunc;
199+
goto invalid;
231200
return hbhlen;
232201

233-
trunc:
234-
nd_print_trunc(ndo);
202+
invalid:
203+
nd_print_invalid(ndo);
235204
return -1;
236205
}
237206

@@ -254,12 +223,12 @@ dstopt_process(netdissect_options *ndo, const u_char *bp)
254223
*/
255224
if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
256225
dstoptlen - sizeof(*dp), NULL, NULL) == -1)
257-
goto trunc;
226+
goto invalid;
258227
}
259228

260229
return dstoptlen;
261230

262-
trunc:
263-
nd_print_trunc(ndo);
231+
invalid:
232+
nd_print_invalid(ndo);
264233
return -1;
265234
}

tests/cve2015-0261-crash.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 1995-08-15 05:27:12.999999 IP6 (class 0x03, flowlabel 0x03030, hlim 48, next-header HBH (0), payload length 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 130:3030:3030:3030:3030:3030:3030:3030: HBH [|hbh]
1+
1 1995-08-15 05:27:12.999999 IP6 (class 0x03, flowlabel 0x03030, hlim 48, next-header HBH (0), payload length 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 130:3030:3030:3030:3030:3030:3030:3030: HBH [remaining length 6 < 50] (invalid)

tests/erspan-type-iii-pb-1.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1 1972-02-16 17:25:18.554240 IP6 (class 0x30, flowlabel 0x00001, hlim 1, next-header DSTOPT (60), payload length 288) 4120:7467:1700:4200:143:100:7f01:400e > 4591:bfd7:cd87:d7:68:38:101:e800: DSTOPT (padn)(pad1)(padn)(opt_type 0x40: len=1)(pad1)(opt_type 0x7f: len=0)(pad1)(pad1) GREv0, Flags [sequence# present, source routing present], seq 4280811777, length 272
1+
1 1972-02-16 17:25:18.554240 IP6 (class 0x30, flowlabel 0x00001, hlim 1, next-header DSTOPT (60), payload length 288) 4120:7467:1700:4200:143:100:7f01:400e > 4591:bfd7:cd87:d7:68:38:101:e800: DSTOPT (padn)(pad1)(padn)(unknown opt-type 0x40 len=1)(pad1)(unknown opt-type 0x7f len=0)(pad1)(pad1) GREv0, Flags [sequence# present, source routing present], seq 4280811777, length 272
22
erspan type3 session 0 bso Short cos 0 ft Ethernet [|erspan]

tests/ipv6-next-header-oobr-1.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|hbh]
1+
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [remaining length 6 < 50] (invalid)

tests/ipv6-next-header-oobr-2.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|hbh]
1+
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [remaining length 6 < 50] (invalid)

tests/ipv6-too-long-jumbo.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 2012-06-06 12:40:23.226395 IP6 (class 0xc0, hlim 0, next-header HBH (0), payload length 0) 1:6:1a28:312:d7cb:b318:34e5:d3ea > 2b7f:cd1f:ec3c:fb9c:e731:d16b:a8fe:ba8c: HBH (opt_type 0x1a: len=0)(padn)(opt_type 0x16: len=0)(opt_type 0x64: len=114)(jumbo: 3858694210) (opt_type 0x42: len=3)(opt_type 0xfe: len=6)(pad1)(jumbo: 248 - already seen) (opt_type 0x0e: len=8)(opt_type 0x07: len=4)(opt_type 0xf1: len=60) [header+payload length 3858694250 > length 476] (invalid) ip-proto-12 3858693802
1+
1 2012-06-06 12:40:23.226395 IP6 (class 0xc0, hlim 0, next-header HBH (0), payload length 0) 1:6:1a28:312:d7cb:b318:34e5:d3ea > 2b7f:cd1f:ec3c:fb9c:e731:d16b:a8fe:ba8c: HBH (unknown opt-type 0x1a len=0)(padn)(unknown opt-type 0x16 len=0)(unknown opt-type 0x64 len=114)(jumbo: 3858694210) (unknown opt-type 0x42 len=3)(unknown opt-type 0xfe len=6)(pad1)(jumbo: 248 - already seen) (unknown opt-type 0x0e len=8)(unknown opt-type 0x07 len=4)(unknown opt-type 0xf1 len=60) [header+payload length 3858694250 > length 476] (invalid) ip-proto-12 3858693802

tests/ipv6hdr-heapoverflow-v.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 1995-08-15 05:27:12.999999 IP6 (class 0x33, flowlabel 0x03030, hlim 48, next-header HBH (0), payload length 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|hbh]
1+
1 1995-08-15 05:27:12.999999 IP6 (class 0x33, flowlabel 0x03030, hlim 48, next-header HBH (0), payload length 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [remaining length 6 < 50] (invalid)

tests/ipv6hdr-heapoverflow.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|hbh]
1+
1 1995-08-15 05:27:12.999999 IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [remaining length 6 < 50] (invalid)

0 commit comments

Comments
 (0)