Fix uio_prefaultpages for 0 length iovec

Userspace can freely pass in whatever iovec it feels like, and it's perfectly
legal to pass an iovec which contains a zero length segment. In the current
implementation, uio_prefaultpages would touch an out of bound byte in the
"last byte" logic. While this probably wouldn't cause any critical error, we
would like uio_prefaultpages to be able to continue gracefully.

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4078
This commit is contained in:
Chunwei Chen 2015-12-08 12:26:18 -08:00 committed by Brian Behlendorf
parent eba9e745dc
commit 502923bb44

View File

@ -164,7 +164,7 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
caddr_t p;
uint8_t tmp;
int iovcnt;
size_t skip = uio->uio_skip;
size_t skip;
/* no need to fault in kernel pages */
switch (uio->uio_segflg) {
@ -180,9 +180,13 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
iov = uio->uio_iov;
iovcnt = uio->uio_iovcnt;
skip = uio->uio_skip;
while ((n > 0) && (iovcnt > 0)) {
for (; n > 0 && iovcnt > 0; iov++, iovcnt--, skip = 0) {
cnt = MIN(iov->iov_len - skip, n);
/* empty iov */
if (cnt == 0)
continue;
n -= cnt;
/*
* touch each page in this segment.
@ -201,9 +205,6 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
p--;
if (fuword8((uint8_t *) p, &tmp))
return;
iov++;
iovcnt--;
skip = 0;
}
}
EXPORT_SYMBOL(uio_prefaultpages);