Skip to content

Commit 2c80929

Browse files
Miklos SzerediAl Viro
authored andcommitted
fuse: honour max_read and max_write in direct_io mode
The third argument of fuse_get_user_pages() "nbytesp" refers to the number of bytes a caller asked to pack into fuse request. This value may be lesser than capacity of fuse request or iov_iter. So fuse_get_user_pages() must ensure that *nbytesp won't grow. Now, when helper iov_iter_get_pages() performs all hard work of extracting pages from iov_iter, it can be done by passing properly calculated "maxsize" to the helper. The other caller of iov_iter_get_pages() (dio_refill_pages()) doesn't need this capability, so pass LONG_MAX as the maxsize argument here. Fixes: c9c37e2 ("fuse: switch to iov_iter_get_pages()") Reported-by: Werner Baumann <werner.baumann@onlinehome.de> Tested-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent b928095 commit 2c80929

File tree

4 files changed

+12
-7
lines changed

4 files changed

+12
-7
lines changed

fs/direct-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
158158
{
159159
ssize_t ret;
160160

161-
ret = iov_iter_get_pages(sdio->iter, dio->pages, DIO_PAGES,
161+
ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES,
162162
&sdio->from);
163163

164164
if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) {

fs/fuse/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
13051305
size_t start;
13061306
ssize_t ret = iov_iter_get_pages(ii,
13071307
&req->pages[req->num_pages],
1308+
*nbytesp - nbytes,
13081309
req->max_pages - req->num_pages,
13091310
&start);
13101311
if (ret < 0)

include/linux/uio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ unsigned long iov_iter_alignment(const struct iov_iter *i);
8484
void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov,
8585
unsigned long nr_segs, size_t count);
8686
ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages,
87-
unsigned maxpages, size_t *start);
87+
size_t maxsize, unsigned maxpages, size_t *start);
8888
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages,
8989
size_t maxsize, size_t *start);
9090
int iov_iter_npages(const struct iov_iter *i, int maxpages);

mm/iov_iter.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void iov_iter_init(struct iov_iter *i, int direction,
310310
EXPORT_SYMBOL(iov_iter_init);
311311

312312
static ssize_t get_pages_iovec(struct iov_iter *i,
313-
struct page **pages, unsigned maxpages,
313+
struct page **pages, size_t maxsize, unsigned maxpages,
314314
size_t *start)
315315
{
316316
size_t offset = i->iov_offset;
@@ -323,6 +323,8 @@ static ssize_t get_pages_iovec(struct iov_iter *i,
323323
len = iov->iov_len - offset;
324324
if (len > i->count)
325325
len = i->count;
326+
if (len > maxsize)
327+
len = maxsize;
326328
addr = (unsigned long)iov->iov_base + offset;
327329
len += *start = addr & (PAGE_SIZE - 1);
328330
if (len > maxpages * PAGE_SIZE)
@@ -588,13 +590,15 @@ static unsigned long alignment_bvec(const struct iov_iter *i)
588590
}
589591

590592
static ssize_t get_pages_bvec(struct iov_iter *i,
591-
struct page **pages, unsigned maxpages,
593+
struct page **pages, size_t maxsize, unsigned maxpages,
592594
size_t *start)
593595
{
594596
const struct bio_vec *bvec = i->bvec;
595597
size_t len = bvec->bv_len - i->iov_offset;
596598
if (len > i->count)
597599
len = i->count;
600+
if (len > maxsize)
601+
len = maxsize;
598602
/* can't be more than PAGE_SIZE */
599603
*start = bvec->bv_offset + i->iov_offset;
600604

@@ -711,13 +715,13 @@ unsigned long iov_iter_alignment(const struct iov_iter *i)
711715
EXPORT_SYMBOL(iov_iter_alignment);
712716

713717
ssize_t iov_iter_get_pages(struct iov_iter *i,
714-
struct page **pages, unsigned maxpages,
718+
struct page **pages, size_t maxsize, unsigned maxpages,
715719
size_t *start)
716720
{
717721
if (i->type & ITER_BVEC)
718-
return get_pages_bvec(i, pages, maxpages, start);
722+
return get_pages_bvec(i, pages, maxsize, maxpages, start);
719723
else
720-
return get_pages_iovec(i, pages, maxpages, start);
724+
return get_pages_iovec(i, pages, maxsize, maxpages, start);
721725
}
722726
EXPORT_SYMBOL(iov_iter_get_pages);
723727

0 commit comments

Comments
 (0)