Skip to content

Commit

Permalink
Fix uio_prefaultpages for 0 length iovec
Browse files Browse the repository at this point in the history
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 openzfs#4078
  • Loading branch information
Chunwei Chen authored and ryao committed Jan 4, 2016
1 parent 21bb20d commit 1ed1252
Showing 1 changed file with 6 additions and 5 deletions.
11 changes: 6 additions & 5 deletions module/zcommon/zfs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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.
Expand All @@ -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);
Expand Down

0 comments on commit 1ed1252

Please sign in to comment.