diff options
author | ume <ume@FreeBSD.org> | 2005-07-28 18:07:07 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2005-07-28 18:07:07 +0000 |
commit | aef495bf5290643874511b6f0e0f7809990dabe2 (patch) | |
tree | bc11dea367785b7a56ff4a128ac6e6670f331702 /sys/netinet6 | |
parent | abb41f91bc29bb3400791c7ea47a1e93b15f4ebf (diff) | |
download | FreeBSD-src-aef495bf5290643874511b6f0e0f7809990dabe2.zip FreeBSD-src-aef495bf5290643874511b6f0e0f7809990dabe2.tar.gz |
simplied the fix to FreeBSD-SA-04:06.ipv6. The previous one worried
too much even though we actually validate the parameters. This code
also is more compatible with other *BSDs, which do copyin within
setsockopt().
Submitted by: Keiichi SHIMA <keiichi__at__iijlab.net>
Reviewed by: security-officer (nectar)
Obtained from: KAME
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/ip6_output.c | 44 |
1 files changed, 9 insertions, 35 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index e2c9361..f207307 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1764,6 +1764,7 @@ do { \ { /* new advanced API (RFC3542) */ u_char *optbuf; + u_char optbuf_storage[MCLBYTES]; int optlen; struct ip6_pktopts **optp; @@ -1773,48 +1774,21 @@ do { \ break; } - switch (optname) { - case IPV6_HOPOPTS: - case IPV6_DSTOPTS: - case IPV6_RTHDRDSTOPTS: - case IPV6_NEXTHOP: - if (!privileged) - error = EPERM; - break; - } + /* + * We only ensure valsize is not too large + * here. Further validation will be done + * later. + */ + error = sooptcopyin(sopt, optbuf_storage, + sizeof(optbuf_storage), 0); if (error) break; - - switch (optname) { - case IPV6_PKTINFO: - optlen = sizeof(struct in6_pktinfo); - break; - case IPV6_NEXTHOP: - optlen = SOCK_MAXADDRLEN; - break; - default: - optlen = IPV6_MAXOPTHDR; - break; - } - if (sopt->sopt_valsize > optlen) { - error = EINVAL; - break; - } - optlen = sopt->sopt_valsize; - optbuf = malloc(optlen, M_TEMP, M_WAITOK); - error = sooptcopyin(sopt, optbuf, optlen, - optlen); - if (error) { - free(optbuf, M_TEMP); - break; - } - + optbuf = optbuf_storage; optp = &in6p->in6p_outputopts; error = ip6_pcbopt(optname, optbuf, optlen, optp, privileged, uproto); - free(optbuf, M_TEMP); break; } #undef OPTSET |