diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2006-10-30 18:06:12 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-30 18:24:41 -0500 |
commit | a27b58fed90cc5654e2daf1d292cc5bc61be4dd7 (patch) | |
tree | 4f01c7b0bc168b9a73cd9d5406e7fbf426ab169c /net/ipv4/raw.c | |
parent | 28cd7752734563d5b0967b96a6bade7a1dc89c7f (diff) |
[NET]: fix uaccess handling
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r-- | net/ipv4/raw.c | 17 |
1 files changed, 11 insertions, 6 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)); |