mirror of https://github.com/F-Stack/f-stack.git
Fix denial of service of ipsec.
Corresponding upstream changeset from https://www.freebsd.org/security/advisories/FreeBSD-SA-18:05.ipsec.asc.
This commit is contained in:
parent
b6e183603d
commit
441d416594
|
@ -301,7 +301,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
struct ip6_ext *ip6e;
|
struct ip6_ext *ip6e;
|
||||||
struct ip6_hdr ip6;
|
struct ip6_hdr ip6;
|
||||||
int alloc, len, ad;
|
int ad, alloc, nxt, noff;
|
||||||
#endif /* INET6 */
|
#endif /* INET6 */
|
||||||
|
|
||||||
switch (proto) {
|
switch (proto) {
|
||||||
|
@ -330,7 +330,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
|
||||||
else
|
else
|
||||||
ip->ip_off = htons(0);
|
ip->ip_off = htons(0);
|
||||||
|
|
||||||
ptr = mtod(m, unsigned char *) + sizeof(struct ip);
|
ptr = mtod(m, unsigned char *);
|
||||||
|
|
||||||
/* IPv4 option processing */
|
/* IPv4 option processing */
|
||||||
for (off = sizeof(struct ip); off < skip;) {
|
for (off = sizeof(struct ip); off < skip;) {
|
||||||
|
@ -411,7 +411,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
|
||||||
|
|
||||||
/* Zeroize all other options. */
|
/* Zeroize all other options. */
|
||||||
count = ptr[off + 1];
|
count = ptr[off + 1];
|
||||||
bcopy(ipseczeroes, ptr, count);
|
bcopy(ipseczeroes, ptr + off, count);
|
||||||
off += count;
|
off += count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -484,61 +484,45 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
|
||||||
} else
|
} else
|
||||||
break;
|
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);)
|
for (off = 0; off < skip - sizeof(struct ip6_hdr);)
|
||||||
switch (off) {
|
switch (nxt) {
|
||||||
case IPPROTO_HOPOPTS:
|
case IPPROTO_HOPOPTS:
|
||||||
case IPPROTO_DSTOPTS:
|
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
|
* Zero out mutable options.
|
||||||
* options -- borrows heavily from the
|
|
||||||
* KAME code.
|
|
||||||
*/
|
*/
|
||||||
for (count = len + sizeof(struct ip6_ext);
|
for (count = off + sizeof(struct ip6_ext);
|
||||||
count < len + ((ip6e->ip6e_len + 1) << 3);) {
|
count < noff;) {
|
||||||
if (ptr[count] == IP6OPT_PAD1) {
|
if (ptr[count] == IP6OPT_PAD1) {
|
||||||
count++;
|
count++;
|
||||||
continue; /* Skip padding. */
|
continue; /* Skip padding. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check. */
|
ad = ptr[count + 1] + 2;
|
||||||
if (count > len +
|
if (count + ad > noff)
|
||||||
((ip6e->ip6e_len + 1) << 3)) {
|
goto error6;
|
||||||
m_freem(m);
|
|
||||||
|
|
||||||
/* 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)
|
if (ptr[count] & IP6OPT_MUTABLE)
|
||||||
bcopy(ipseczeroes, ptr + count,
|
memset(ptr + count, 0, ad);
|
||||||
ptr[count + 1]);
|
|
||||||
|
|
||||||
count += ad;
|
count += ad;
|
||||||
|
|
||||||
/* Sanity check. */
|
|
||||||
if (count >
|
|
||||||
skip - sizeof(struct ip6_hdr)) {
|
|
||||||
m_freem(m);
|
|
||||||
|
|
||||||
/* Free, if we allocated. */
|
|
||||||
if (alloc)
|
|
||||||
free(ptr, M_XDATA);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count != noff)
|
||||||
|
goto error6;
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
len += ((ip6e->ip6e_len + 1) << 3);
|
off += ((ip6e->ip6e_len + 1) << 3);
|
||||||
off = ip6e->ip6e_nxt;
|
nxt = ip6e->ip6e_nxt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPPROTO_ROUTING:
|
case IPPROTO_ROUTING:
|
||||||
|
@ -546,14 +530,15 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out)
|
||||||
* Always include routing headers in
|
* Always include routing headers in
|
||||||
* computation.
|
* computation.
|
||||||
*/
|
*/
|
||||||
ip6e = (struct ip6_ext *) (ptr + len);
|
ip6e = (struct ip6_ext *) (ptr + off);
|
||||||
len += ((ip6e->ip6e_len + 1) << 3);
|
off += ((ip6e->ip6e_len + 1) << 3);
|
||||||
off = ip6e->ip6e_nxt;
|
nxt = ip6e->ip6e_nxt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINTF(("%s: unexpected IPv6 header type %d",
|
DPRINTF(("%s: unexpected IPv6 header type %d",
|
||||||
__func__, off));
|
__func__, off));
|
||||||
|
error6:
|
||||||
if (alloc)
|
if (alloc)
|
||||||
free(ptr, M_XDATA);
|
free(ptr, M_XDATA);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
|
Loading…
Reference in New Issue