Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSD: Add array bounds-checking in nfsd_iter_read()

The *count parameter does not appear to be explicitly restricted
to being smaller than rsize, so it might be possible to overrun
the rq_bvec or rq_pages arrays.

Rather than overrunning these arrays (damage done!) and then WARNING
once, let's harden the loop so that it terminates before the end of
the arrays are reached. This should result in a short read, which is
OK -- clients recover by sending additional READ requests for the
remaining unread bytes.

Reported-by: NeilBrown <neil@brown.name>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+7 -5
+7 -5
fs/nfsd/vfs.c
··· 1115 1115 1116 1116 v = 0; 1117 1117 total = *count; 1118 - while (total) { 1118 + while (total && v < rqstp->rq_maxpages && 1119 + rqstp->rq_next_page < rqstp->rq_page_end) { 1119 1120 len = min_t(size_t, total, PAGE_SIZE - base); 1120 - bvec_set_page(&rqstp->rq_bvec[v], *(rqstp->rq_next_page++), 1121 + bvec_set_page(&rqstp->rq_bvec[v], *rqstp->rq_next_page, 1121 1122 len, base); 1123 + 1122 1124 total -= len; 1125 + ++rqstp->rq_next_page; 1123 1126 ++v; 1124 1127 base = 0; 1125 1128 } 1126 - WARN_ON_ONCE(v > rqstp->rq_maxpages); 1127 1129 1128 - trace_nfsd_read_vector(rqstp, fhp, offset, *count); 1129 - iov_iter_bvec(&iter, ITER_DEST, rqstp->rq_bvec, v, *count); 1130 + trace_nfsd_read_vector(rqstp, fhp, offset, *count - total); 1131 + iov_iter_bvec(&iter, ITER_DEST, rqstp->rq_bvec, v, *count - total); 1130 1132 host_err = vfs_iocb_iter_read(file, &kiocb, &iter); 1131 1133 return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err); 1132 1134 }