From: qobaiashi <qobaiashi@gmx.net.>
To: [email protected], [email protected]Subject: [Linux kernel ipv6_setsockopt integer overflow]
Date: Thu, 3 Feb 2005 19:11:00 +0100
User-Agent: KMail/1.5.1
MIME-Version: 1.0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Message-Id: <200502031911.00336.qobaiashi@gmx.net.>
X-Y-GMX-Trusted: 0
X-Virus-Scanned: antivirus-gw at tyumen.ru
hiho!
there exists an integer bug in the ipv6 implementation of the linux kernel.
(at least in 2.4.20 and 2.6.4 )
in /linux/net/ipv6/ipv6_sockglue.c:
int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
int optlen)
{
struct ipv6_pinfo *np = inet6_sk(sk);
int val, valbool;
int retv = -ENOPROTOOPT;
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
return udp_prot.setsockopt(sk, level, optname, optval,optlen);
if(level!=SOL_IPV6)
goto out;
if (optval == NULL)
val=0;
else if (get_user(val, (int *) optval))
return -EFAULT;
valbool = (val!=0);
lock_sock(sk);
switch (optname) {
[...]
case IPV6_PKTOPTIONS:
{
struct ipv6_txoptions *opt = NULL;
struct msghdr msg;
struct flowi fl;
int junk;
fl.fl6_flowlabel = 0;
fl.oif = sk->sk_bound_dev_if;
[1] if (optlen == 0)
goto update;
/* 1K is probably excessive
* 1K is surely not enough, 2K per standard header is 16K.
*/
retv = -EINVAL;
[2] if (optlen > 64*1024)
break;
[3] opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
retv = -ENOBUFS; sizeof(*opt)+0xfffffff8
if (opt == NULL)
break;
[4] memset(opt, 0, sizeof(*opt));
opt->tot_len = sizeof(*opt) + optlen;
retv = -EFAULT;
[5] if (copy_from_user(opt+1, optval, optlen))
[...]
details:
condition [1] and [2] are easily passed for a value like -100, then at [3]
sock_kmalloc allocates a too small object of the size (sizeof(*opt) + (-100))
which is then overflowed in [4] and [5] leading to a dos of the kernel...
that's it
over and out!
--
-q/UNF