1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
--- sys/netipsec/xform_ah.c.orig
+++ sys/netipsec/xform_ah.c
@@ -264,7 +264,7 @@
#ifdef INET6
struct ip6_ext *ip6e;
struct ip6_hdr ip6;
- int alloc, len, ad;
+ int ad, alloc, nxt, noff;
#endif /* INET6 */
switch (proto) {
@@ -293,7 +293,7 @@
else
ip->ip_off = htons(0);
- ptr = mtod(m, unsigned char *) + sizeof(struct ip);
+ ptr = mtod(m, unsigned char *);
/* IPv4 option processing */
for (off = sizeof(struct ip); off < skip;) {
@@ -374,7 +374,7 @@
/* Zeroize all other options. */
count = ptr[off + 1];
- bcopy(ipseczeroes, ptr, count);
+ bcopy(ipseczeroes, ptr + off, count);
off += count;
break;
}
@@ -447,61 +447,44 @@
} else
break;
- off = ip6.ip6_nxt & 0xff; /* Next header type. */
+ nxt = ip6.ip6_nxt & 0xff; /* Next header type. */
- for (len = 0; len < skip - sizeof(struct ip6_hdr);)
- switch (off) {
+ for (off = 0; off < skip - sizeof(struct ip6_hdr);)
+ switch (nxt) {
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
- ip6e = (struct ip6_ext *) (ptr + len);
+ ip6e = (struct ip6_ext *)(ptr + off);
+ noff = off + ((ip6e->ip6e_len + 1) << 3);
+ /* Sanity check. */
+ if (noff > skip - sizeof(struct ip6_hdr))
+ goto error6;
+
/*
- * Process the mutable/immutable
- * options -- borrows heavily from the
- * KAME code.
+ * Zero out mutable options.
*/
- for (count = len + sizeof(struct ip6_ext);
- count < len + ((ip6e->ip6e_len + 1) << 3);) {
+ for (count = off + sizeof(struct ip6_ext);
+ count < noff;) {
if (ptr[count] == IP6OPT_PAD1) {
count++;
continue; /* Skip padding. */
}
- /* Sanity check. */
- if (count > len +
- ((ip6e->ip6e_len + 1) << 3)) {
- m_freem(m);
+ ad = ptr[count + 1] + 2;
+ if (count + ad > noff)
+ goto error6;
- /* Free, if we allocated. */
- if (alloc)
- free(ptr, M_XDATA);
- return EINVAL;
- }
-
- ad = ptr[count + 1];
-
- /* If mutable option, zeroize. */
if (ptr[count] & IP6OPT_MUTABLE)
- bcopy(ipseczeroes, ptr + count,
- ptr[count + 1]);
-
+ memset(ptr + count, 0, ad);
count += ad;
+ }
- /* Sanity check. */
- if (count >
- skip - sizeof(struct ip6_hdr)) {
- m_freem(m);
+ if (count != noff)
+ goto error6;
- /* Free, if we allocated. */
- if (alloc)
- free(ptr, M_XDATA);
- return EINVAL;
- }
- }
-
/* Advance. */
- len += ((ip6e->ip6e_len + 1) << 3);
- off = ip6e->ip6e_nxt;
+ off += ((ip6e->ip6e_len + 1) << 3);
+ nxt = ip6e->ip6e_nxt;
break;
case IPPROTO_ROUTING:
@@ -509,14 +492,15 @@
* Always include routing headers in
* computation.
*/
- ip6e = (struct ip6_ext *) (ptr + len);
- len += ((ip6e->ip6e_len + 1) << 3);
- off = ip6e->ip6e_nxt;
+ ip6e = (struct ip6_ext *) (ptr + off);
+ off += ((ip6e->ip6e_len + 1) << 3);
+ nxt = ip6e->ip6e_nxt;
break;
default:
DPRINTF(("%s: unexpected IPv6 header type %d",
__func__, off));
+error6:
if (alloc)
free(ptr, M_XDATA);
m_freem(m);
|