aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/raw.c17
-rw-r--r--net/ipv6/raw.c17
-rw-r--r--net/netlink/af_netlink.c5
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
332static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 332static 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
377static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 379static 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
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))
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: