From: David S. Miller <davem@redhat.com> Subject: [RHEL5 1/2]: IPV6 security holes in ipv6_sockglue.c Date: Tue, 13 Mar 2007 17:30:02 -0400 (EDT) Bugzilla: 231668 Message-Id: <20070313.173002.115304153.davem@redhat.com> Changelog: [net] IPV6 security holes in ipv6_sockglue.c ipv6_getsockopt_sticky() call blindly dereferences opt->hdr. opt can be NULL, in fact it will be for a new socket. This one is killer on x86 and friends because you can use this NULL pointer dereference to read arbitrary kernel memory. Map page zero in userspace, and set: ((struct ipv6_txoptions *)0)->hdr to whatever kernel address you'd like to read, and this code will happily copy it back into your userspace buffer for you :-/ Fixed by passing in 'opt' and checking it for NULL. Please ACK. commit 286930797d74b2c9a5beae84836044f6a836235f [IPV6]: Handle np->opt being NULL in ipv6_getsockopt_sticky(). Signed-off-by: David S. Miller <davem@davemloft.net> --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -782,11 +782,15 @@ EXPORT_SYMBOL(compat_ipv6_setsockopt); #endif -static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, +static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, char __user *optval, int len) { - if (!hdr) + struct ipv6_opt_hdr *hdr; + + if (!opt || !opt->hopopt) return 0; + hdr = opt->hopopt; + len = min_t(int, len, ipv6_optlen(hdr)); if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) return -EFAULT; @@ -926,7 +930,7 @@ { lock_sock(sk); - len = ipv6_getsockopt_sticky(sk, np->opt->hopopt, + len = ipv6_getsockopt_sticky(sk, np->opt, optval, len); release_sock(sk); return put_user(len, optlen);