aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d09329ca3267..d6dedc4aec77 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -604,7 +604,7 @@ error:
604 return err; 604 return err;
605} 605}
606 606
607static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 607static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
608{ 608{
609 struct iovec *iov; 609 struct iovec *iov;
610 u8 __user *type = NULL; 610 u8 __user *type = NULL;
@@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
616 int i; 616 int i;
617 617
618 if (!msg->msg_iov) 618 if (!msg->msg_iov)
619 return; 619 return 0;
620 620
621 for (i = 0; i < msg->msg_iovlen; i++) { 621 for (i = 0; i < msg->msg_iovlen; i++) {
622 iov = &msg->msg_iov[i]; 622 iov = &msg->msg_iov[i];
@@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
638 code = iov->iov_base; 638 code = iov->iov_base;
639 639
640 if (type && code) { 640 if (type && code) {
641 get_user(fl->fl_icmp_type, type); 641 if (get_user(fl->fl_icmp_type, type) ||
642 get_user(fl->fl_icmp_code, code); 642 get_user(fl->fl_icmp_code, code))
643 return -EFAULT;
643 probed = 1; 644 probed = 1;
644 } 645 }
645 break; 646 break;
@@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
650 /* check if type field is readable or not. */ 651 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) { 652 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base; 653 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]); 654 if (get_user(fl->fl_mh_type, &p[2 - len]))
655 return -EFAULT;
654 probed = 1; 656 probed = 1;
655 } else 657 } else
656 len += iov->iov_len; 658 len += iov->iov_len;
@@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
664 if (probed) 666 if (probed)
665 break; 667 break;
666 } 668 }
669 return 0;
667} 670}
668 671
669static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, 672static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
787 opt = ipv6_fixup_options(&opt_space, opt); 790 opt = ipv6_fixup_options(&opt_space, opt);
788 791
789 fl.proto = proto; 792 fl.proto = proto;
790 rawv6_probe_proto_opt(&fl, msg); 793 err = rawv6_probe_proto_opt(&fl, msg);
794 if (err)
795 goto out;
791 796
792 ipv6_addr_copy(&fl.fl6_dst, daddr); 797 ipv6_addr_copy(&fl.fl6_dst, daddr);
793 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 798 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))