Skip to content

Commit e92053a

Browse files
author
Trond Myklebust
committed
SUNRPC: Handle zero length fragments correctly
A zero length fragment is really a bug, but let's ensure we don't go nuts when one turns up. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent ae05355 commit e92053a

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

net/sunrpc/xprtsock.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
405405
size_t want, seek_init = seek, offset = 0;
406406
ssize_t ret;
407407

408-
if (seek < buf->head[0].iov_len) {
409-
want = min_t(size_t, count, buf->head[0].iov_len);
408+
want = min_t(size_t, count, buf->head[0].iov_len);
409+
if (seek < want) {
410410
ret = xs_read_kvec(sock, msg, flags, &buf->head[0], want, seek);
411411
if (ret <= 0)
412412
goto sock_err;
@@ -417,8 +417,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
417417
goto out;
418418
seek = 0;
419419
} else {
420-
seek -= buf->head[0].iov_len;
421-
offset += buf->head[0].iov_len;
420+
seek -= want;
421+
offset += want;
422422
}
423423

424424
want = xs_alloc_sparse_pages(buf,
@@ -443,8 +443,8 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
443443
offset += want;
444444
}
445445

446-
if (seek < buf->tail[0].iov_len) {
447-
want = min_t(size_t, count - offset, buf->tail[0].iov_len);
446+
want = min_t(size_t, count - offset, buf->tail[0].iov_len);
447+
if (seek < want) {
448448
ret = xs_read_kvec(sock, msg, flags, &buf->tail[0], want, seek);
449449
if (ret <= 0)
450450
goto sock_err;
@@ -454,7 +454,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
454454
if (ret != want)
455455
goto out;
456456
} else
457-
offset += buf->tail[0].iov_len;
457+
offset = seek_init;
458458
ret = -EMSGSIZE;
459459
out:
460460
*read = offset - seek_init;
@@ -482,6 +482,14 @@ xs_read_stream_request_done(struct sock_xprt *transport)
482482
return transport->recv.fraghdr & cpu_to_be32(RPC_LAST_STREAM_FRAGMENT);
483483
}
484484

485+
static void
486+
xs_read_stream_check_eor(struct sock_xprt *transport,
487+
struct msghdr *msg)
488+
{
489+
if (xs_read_stream_request_done(transport))
490+
msg->msg_flags |= MSG_EOR;
491+
}
492+
485493
static ssize_t
486494
xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
487495
int flags, struct rpc_rqst *req)
@@ -493,17 +501,24 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
493501
xs_read_header(transport, buf);
494502

495503
want = transport->recv.len - transport->recv.offset;
496-
ret = xs_read_xdr_buf(transport->sock, msg, flags, buf,
497-
transport->recv.copied + want, transport->recv.copied,
498-
&read);
499-
transport->recv.offset += read;
500-
transport->recv.copied += read;
504+
if (want != 0) {
505+
ret = xs_read_xdr_buf(transport->sock, msg, flags, buf,
506+
transport->recv.copied + want,
507+
transport->recv.copied,
508+
&read);
509+
transport->recv.offset += read;
510+
transport->recv.copied += read;
511+
} else
512+
read = 0;
513+
501514
if (transport->recv.offset == transport->recv.len) {
502-
if (xs_read_stream_request_done(transport))
503-
msg->msg_flags |= MSG_EOR;
515+
xs_read_stream_check_eor(transport, msg);
504516
return read;
505517
}
506518

519+
if (want == 0)
520+
return 0;
521+
507522
switch (ret) {
508523
default:
509524
break;

0 commit comments

Comments
 (0)