diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2009-04-23 19:31:25 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-04-28 13:54:25 -0400 |
commit | abc5c44d6284fab8fb21bcfc52c0f16f980637df (patch) | |
tree | 98825098d3f6488a1a8fb55ec40131313b1d25e9 /net/sunrpc/svcsock.c | |
parent | dcf1a3573eae69937fb14462369c4d3e6f4a37f1 (diff) |
SUNRPC: Fix error return value of svc_addr_len()
The svc_addr_len() helper function returns -EAFNOSUPPORT if it doesn't
recognize the address family of the passed-in socket address. However,
the return type of this function is size_t, which means -EAFNOSUPPORT
is turned into a very large positive value in this case.
The check in svc_udp_recvfrom() to see if the return value is less
than zero therefore won't work at all.
Additionally, handle_connect_req() passes this value directly to
memset(). This could cause memset() to clobber a large chunk of memory
if svc_addr_len() has returned an error. Currently the address family
of these addresses, however, is known to be supported long before
handle_connect_req() is called, so this isn't a real risk.
Change the error return value of svc_addr_len() to zero, which fits in
the range of size_t, and is safer to pass to memset() directly.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index af3198814c15..8b0832834135 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -426,13 +426,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
426 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | 426 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; |
427 | } buffer; | 427 | } buffer; |
428 | struct cmsghdr *cmh = &buffer.hdr; | 428 | struct cmsghdr *cmh = &buffer.hdr; |
429 | int err, len; | ||
430 | struct msghdr msg = { | 429 | struct msghdr msg = { |
431 | .msg_name = svc_addr(rqstp), | 430 | .msg_name = svc_addr(rqstp), |
432 | .msg_control = cmh, | 431 | .msg_control = cmh, |
433 | .msg_controllen = sizeof(buffer), | 432 | .msg_controllen = sizeof(buffer), |
434 | .msg_flags = MSG_DONTWAIT, | 433 | .msg_flags = MSG_DONTWAIT, |
435 | }; | 434 | }; |
435 | size_t len; | ||
436 | int err; | ||
436 | 437 | ||
437 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) | 438 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) |
438 | /* udp sockets need large rcvbuf as all pending | 439 | /* udp sockets need large rcvbuf as all pending |
@@ -464,8 +465,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
464 | return -EAGAIN; | 465 | return -EAGAIN; |
465 | } | 466 | } |
466 | len = svc_addr_len(svc_addr(rqstp)); | 467 | len = svc_addr_len(svc_addr(rqstp)); |
467 | if (len < 0) | 468 | if (len == 0) |
468 | return len; | 469 | return -EAFNOSUPPORT; |
469 | rqstp->rq_addrlen = len; | 470 | rqstp->rq_addrlen = len; |
470 | if (skb->tstamp.tv64 == 0) { | 471 | if (skb->tstamp.tv64 == 0) { |
471 | skb->tstamp = ktime_get_real(); | 472 | skb->tstamp = ktime_get_real(); |