diff options
-rw-r--r-- | net/ipv4/raw.c | 17 | ||||
-rw-r--r-- | net/ipv6/raw.c | 17 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 5 |
3 files changed, 25 insertions, 14 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index b430cf2a4f66..5c31dead2bdc 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -329,7 +329,7 @@ error: | |||
329 | return err; | 329 | return err; |
330 | } | 330 | } |
331 | 331 | ||
332 | static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | 332 | static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) |
333 | { | 333 | { |
334 | struct iovec *iov; | 334 | struct iovec *iov; |
335 | u8 __user *type = NULL; | 335 | u8 __user *type = NULL; |
@@ -338,7 +338,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
338 | unsigned int i; | 338 | unsigned int i; |
339 | 339 | ||
340 | if (!msg->msg_iov) | 340 | if (!msg->msg_iov) |
341 | return; | 341 | return 0; |
342 | 342 | ||
343 | for (i = 0; i < msg->msg_iovlen; i++) { | 343 | for (i = 0; i < msg->msg_iovlen; i++) { |
344 | iov = &msg->msg_iov[i]; | 344 | iov = &msg->msg_iov[i]; |
@@ -360,8 +360,9 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
360 | code = iov->iov_base; | 360 | code = iov->iov_base; |
361 | 361 | ||
362 | if (type && code) { | 362 | if (type && code) { |
363 | get_user(fl->fl_icmp_type, type); | 363 | if (get_user(fl->fl_icmp_type, type) || |
364 | get_user(fl->fl_icmp_code, code); | 364 | get_user(fl->fl_icmp_code, code)) |
365 | return -EFAULT; | ||
365 | probed = 1; | 366 | probed = 1; |
366 | } | 367 | } |
367 | break; | 368 | break; |
@@ -372,6 +373,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
372 | if (probed) | 373 | if (probed) |
373 | break; | 374 | break; |
374 | } | 375 | } |
376 | return 0; | ||
375 | } | 377 | } |
376 | 378 | ||
377 | static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 379 | static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
@@ -480,8 +482,11 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
480 | .proto = inet->hdrincl ? IPPROTO_RAW : | 482 | .proto = inet->hdrincl ? IPPROTO_RAW : |
481 | sk->sk_protocol, | 483 | sk->sk_protocol, |
482 | }; | 484 | }; |
483 | if (!inet->hdrincl) | 485 | if (!inet->hdrincl) { |
484 | raw_probe_proto_opt(&fl, msg); | 486 | err = raw_probe_proto_opt(&fl, msg); |
487 | if (err) | ||
488 | goto done; | ||
489 | } | ||
485 | 490 | ||
486 | security_sk_classify_flow(sk, &fl); | 491 | security_sk_classify_flow(sk, &fl); |
487 | err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); | 492 | err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); |
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 | ||
607 | static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | 607 | static 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 | ||
669 | static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | 672 | static 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)) |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d56e0d21f919..d527c8977b1f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1075,8 +1075,9 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, | |||
1075 | return -EINVAL; | 1075 | return -EINVAL; |
1076 | len = sizeof(int); | 1076 | len = sizeof(int); |
1077 | val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0; | 1077 | val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0; |
1078 | put_user(len, optlen); | 1078 | if (put_user(len, optlen) || |
1079 | put_user(val, optval); | 1079 | put_user(val, optval)) |
1080 | return -EFAULT; | ||
1080 | err = 0; | 1081 | err = 0; |
1081 | break; | 1082 | break; |
1082 | default: | 1083 | default: |