diff options
author | ume <ume@FreeBSD.org> | 2004-03-26 19:52:18 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2004-03-26 19:52:18 +0000 |
commit | 11f479f5193062dc4eb60f7c5964ffbd382dd52a (patch) | |
tree | e99a84e7b828e8e198ef8e99c89434dfc678ecac /sys | |
parent | b44e46cbe7c7547a45789778ba2daaf00635ae02 (diff) | |
download | FreeBSD-src-11f479f5193062dc4eb60f7c5964ffbd382dd52a.zip FreeBSD-src-11f479f5193062dc4eb60f7c5964ffbd382dd52a.tar.gz |
Validate IPv6 socket options more carefully to avoid a panic.
PR: kern/61513
Reviewed by: cperciva, nectar
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip6.h | 1 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 38 |
2 files changed, 38 insertions, 1 deletions
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h index 336ef48..bbc18df 100644 --- a/sys/netinet/ip6.h +++ b/sys/netinet/ip6.h @@ -213,6 +213,7 @@ struct ip6_frag { #define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */ #define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/ +#define IPV6_MAXOPTHDR 2048 /* max option header size, 256 64-bit words */ #ifdef _KERNEL /* diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 2dd5fc9..bdccf66 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1780,12 +1780,48 @@ do { \ break; } - optbuf = sopt->sopt_val; + switch (optname) { + case IPV6_HOPOPTS: + case IPV6_DSTOPTS: + case IPV6_RTHDRDSTOPTS: + case IPV6_NEXTHOP: + if (!privileged) + error = EPERM; + break; + } + 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; + } + optp = &in6p->in6p_outputopts; error = ip6_pcbopt(optname, optbuf, optlen, optp, privileged, uproto); + free(optbuf, M_TEMP); break; } #undef OPTSET |