Re: [Linux kernel ipv6_setsockopt integer overflow]

From: Dan Yefimov (dan_at_lightwave.net.ru)
Date: 02/03/05

  • Next message: Ill will: "Re: [Full-Disclosure] Re: Cain and Abel"
    Date: Fri, 4 Feb 2005 00:47:58 +0300 (MSK)
    To: qobaiashi <qobaiashi@gmx.net>
    
    

    On Thu, 3 Feb 2005, qobaiashi wrote:

    There's no integer overflow here since there's the test for optlen < 0 in
    linux/net/socket.c

    >
    > 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!
    >
    >

    -- 
        Sincerely Your, Dan.
    

  • Next message: Ill will: "Re: [Full-Disclosure] Re: Cain and Abel"

    Relevant Pages