More IP option length validation.
Includes the following revisions from KAME (two of these were actually committed previously but the CVS revisions weren't documented): 1.40 kame/kame/sys/netinet6/ah_core.c (committed in previous rev) 1.41 kame/kame/sys/netinet6/ah_core.c 1.28 kame/kame/sys/netinet6/ah_output.c (committed in previous rev) 1.29 kame/kame/sys/netinet6/ah_output.c 1.30 kame/kame/sys/netinet6/ah_output.c 1.129 kame/kame/sys/netinet6/nd6.c 1.130 kame/kame/sys/netinet6/nd6.c 1.24 kame/kame/sys/netinet6/dest6.c 1.25 kame/kame/sys/netinet6/dest6.c Obtained from: KAME
This commit is contained in:
parent
c33f8c177f
commit
19391949fb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=73059
@ -788,6 +788,8 @@ ah4_calccksum(m, ahdat, len, algo, sav)
|
||||
i = sizeof(struct ip);
|
||||
while (i < hlen) {
|
||||
if (i + IPOPT_OPTVAL >= hlen) {
|
||||
ipseclog((LOG_ERR, "ah4_calccksum: "
|
||||
"invalid IP option\n"));
|
||||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
@ -796,6 +798,10 @@ ah4_calccksum(m, ahdat, len, algo, sav)
|
||||
i + IPOPT_OLEN < hlen)
|
||||
;
|
||||
else {
|
||||
ipseclog((LOG_ERR,
|
||||
"ah4_calccksum: invalid IP option "
|
||||
"(type=%02x)\n",
|
||||
p[i + IPOPT_OPTVAL]));
|
||||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
@ -813,14 +819,19 @@ ah4_calccksum(m, ahdat, len, algo, sav)
|
||||
case 0x94: /* Router alert */
|
||||
case 0x95: /* RFC1770 */
|
||||
l = p[i + IPOPT_OLEN];
|
||||
if (l < 2)
|
||||
goto invalopt;
|
||||
skip = 0;
|
||||
break;
|
||||
default:
|
||||
l = p[i + IPOPT_OLEN];
|
||||
if (l < 2)
|
||||
goto invalopt;
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
if (l <= 0 || hlen - i < l) {
|
||||
if (l < 1 || hlen - i < l) {
|
||||
invalopt:
|
||||
ipseclog((LOG_ERR,
|
||||
"ah4_calccksum: invalid IP option "
|
||||
"(type=%02x len=%02x)\n",
|
||||
|
@ -539,8 +539,8 @@ ah4_finaldst(m)
|
||||
break;
|
||||
case IPOPT_LSRR:
|
||||
case IPOPT_SSRR:
|
||||
if (q[i + IPOPT_OLEN] <= 0
|
||||
|| optlen - i < q[i + IPOPT_OLEN]) {
|
||||
if (q[i + IPOPT_OLEN] < 2 + sizeof(struct in_addr) ||
|
||||
optlen - i < q[i + IPOPT_OLEN]) {
|
||||
ipseclog((LOG_ERR,
|
||||
"ip_finaldst: invalid IP option "
|
||||
"(code=%02x len=%02x)\n",
|
||||
@ -550,8 +550,8 @@ ah4_finaldst(m)
|
||||
i += q[i + IPOPT_OLEN] - sizeof(struct in_addr);
|
||||
return (struct in_addr *)(q + i);
|
||||
default:
|
||||
if (q[i + IPOPT_OLEN] <= 0
|
||||
|| optlen - i < q[i + IPOPT_OLEN]) {
|
||||
if (q[i + IPOPT_OLEN] < 2 ||
|
||||
optlen - i < q[i + IPOPT_OLEN]) {
|
||||
ipseclog((LOG_ERR,
|
||||
"ip_finaldst: invalid IP option "
|
||||
"(code=%02x len=%02x)\n",
|
||||
|
@ -89,22 +89,20 @@ dest6_input(mp, offp, proto)
|
||||
|
||||
/* search header for all options. */
|
||||
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
|
||||
switch(*opt) {
|
||||
case IP6OPT_PAD1:
|
||||
optlen = 1;
|
||||
break;
|
||||
case IP6OPT_PADN:
|
||||
if (dstoptlen < IP6OPT_MINLEN) {
|
||||
ip6stat.ip6s_toosmall++;
|
||||
goto bad;
|
||||
}
|
||||
optlen = *(opt + 1) + 2;
|
||||
break;
|
||||
if (*opt != IP6OPT_PAD1 &&
|
||||
(dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) {
|
||||
ip6stat.ip6s_toosmall++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
switch (*opt) {
|
||||
case IP6OPT_PAD1:
|
||||
optlen = 1;
|
||||
break;
|
||||
case IP6OPT_PADN:
|
||||
optlen = *(opt + 1) + 2;
|
||||
break;
|
||||
default: /* unknown option */
|
||||
if (dstoptlen < IP6OPT_MINLEN) {
|
||||
ip6stat.ip6s_toosmall++;
|
||||
goto bad;
|
||||
}
|
||||
if ((optlen = ip6_unknown_opt(opt, m,
|
||||
opt-mtod(m, u_int8_t *))) == -1)
|
||||
return(IPPROTO_DONE);
|
||||
|
@ -274,6 +274,12 @@ nd6_option(ndopts)
|
||||
|
||||
nd_opt = ndopts->nd_opts_search;
|
||||
|
||||
/* make sure nd_opt_len is inside the buffer */
|
||||
if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
|
||||
bzero(ndopts, sizeof(*ndopts));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
olen = nd_opt->nd_opt_len << 3;
|
||||
if (olen == 0) {
|
||||
/*
|
||||
@ -285,7 +291,12 @@ nd6_option(ndopts)
|
||||
}
|
||||
|
||||
ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
|
||||
if (!(ndopts->nd_opts_search < ndopts->nd_opts_last)) {
|
||||
if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
|
||||
/* option overruns the end of buffer, invalid */
|
||||
bzero(ndopts, sizeof(*ndopts));
|
||||
return NULL;
|
||||
} else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
|
||||
/* reached the end of options chain */
|
||||
ndopts->nd_opts_done = 1;
|
||||
ndopts->nd_opts_search = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user