diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-08-31 17:52:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-08-31 17:52:17 -0400 |
commit | 99c7bc0133b875280fdd2bf78e4ffbd58cc609e3 (patch) | |
tree | bf66fa8252c23145730e6efceffe19af4c7b002c /net/ipv6/exthdrs.c | |
parent | dd1a47c21ee4f4f682285ad9d4624d2cec436f93 (diff) |
[IPV6]: Fix kernel OOPs when setting sticky socket options.
Bug noticed by Remi Denis-Courmont <rdenis@simphalempin.com>.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r-- | net/ipv6/exthdrs.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 9d0ee7f0eeb..86dac106873 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -635,14 +635,17 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | |||
635 | struct ipv6_txoptions *opt2; | 635 | struct ipv6_txoptions *opt2; |
636 | int err; | 636 | int err; |
637 | 637 | ||
638 | if (newtype != IPV6_HOPOPTS && opt->hopopt) | 638 | if (opt) { |
639 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); | 639 | if (newtype != IPV6_HOPOPTS && opt->hopopt) |
640 | if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) | 640 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); |
641 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); | 641 | if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) |
642 | if (newtype != IPV6_RTHDR && opt->srcrt) | 642 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); |
643 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); | 643 | if (newtype != IPV6_RTHDR && opt->srcrt) |
644 | if (newtype != IPV6_DSTOPTS && opt->dst1opt) | 644 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); |
645 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); | 645 | if (newtype != IPV6_DSTOPTS && opt->dst1opt) |
646 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); | ||
647 | } | ||
648 | |||
646 | if (newopt && newoptlen) | 649 | if (newopt && newoptlen) |
647 | tot_len += CMSG_ALIGN(newoptlen); | 650 | tot_len += CMSG_ALIGN(newoptlen); |
648 | 651 | ||
@@ -659,25 +662,25 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | |||
659 | opt2->tot_len = tot_len; | 662 | opt2->tot_len = tot_len; |
660 | p = (char *)(opt2 + 1); | 663 | p = (char *)(opt2 + 1); |
661 | 664 | ||
662 | err = ipv6_renew_option(opt->hopopt, newopt, newoptlen, | 665 | err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen, |
663 | newtype != IPV6_HOPOPTS, | 666 | newtype != IPV6_HOPOPTS, |
664 | &opt2->hopopt, &p); | 667 | &opt2->hopopt, &p); |
665 | if (err) | 668 | if (err) |
666 | goto out; | 669 | goto out; |
667 | 670 | ||
668 | err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen, | 671 | err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen, |
669 | newtype != IPV6_RTHDRDSTOPTS, | 672 | newtype != IPV6_RTHDRDSTOPTS, |
670 | &opt2->dst0opt, &p); | 673 | &opt2->dst0opt, &p); |
671 | if (err) | 674 | if (err) |
672 | goto out; | 675 | goto out; |
673 | 676 | ||
674 | err = ipv6_renew_option(opt->srcrt, newopt, newoptlen, | 677 | err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen, |
675 | newtype != IPV6_RTHDR, | 678 | newtype != IPV6_RTHDR, |
676 | (struct ipv6_opt_hdr **)opt2->srcrt, &p); | 679 | (struct ipv6_opt_hdr **)&opt2->srcrt, &p); |
677 | if (err) | 680 | if (err) |
678 | goto out; | 681 | goto out; |
679 | 682 | ||
680 | err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen, | 683 | err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen, |
681 | newtype != IPV6_DSTOPTS, | 684 | newtype != IPV6_DSTOPTS, |
682 | &opt2->dst1opt, &p); | 685 | &opt2->dst1opt, &p); |
683 | if (err) | 686 | if (err) |