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.