Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2793

kernel-2.6.18-238.el5.src.rpm

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);