mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 23:50:02 +02:00
block: Fix start and length check added to iov_iter_extract_bvecs()
Commit14b007e178added an address check using iter_iov_addr() and a length check using iter_iov_len() to iov_iter_extract_bvecs(), but these cannot be used so and are unsafe in this circumstance as the functions have hardwired assumptions about the iterator type. They should only be used with ITER_UBUF or ITER_IOVEC-type iterators; they shouldn't be used with ITER_BVEC, ITER_KVEC, ITER_FOLIOQ, ITER_XARRAY or ITER_DISCARD iterators. This proves to be a problem for cachefiles as an iterator of type ITER_FOLIOQ is passed and iter_iov_addr() and iter_iov_len() both malfunction because iter->__iov in iter_iov() is not pointing to an iovec array. Fix this by using iov_iter_alignment() instead. Fixes:14b007e178("block: validate user space vectors during extraction") Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Keith Busch <kbusch@kernel.org> cc: Hannes Reinecke <hare@kernel.org> cc: Christoph Hellwig <hch@infradead.org> cc: Jens Axboe <axboe@kernel.dk> cc: Alexander Viro <viro@zeniv.linux.org.uk> cc: Paulo Alcantara <pc@manguebit.org> cc: netfs@lists.linux.dev cc: linux-block@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/1667275.1788941191@warthog.procyon.org.uk Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
c4fa55f85c
commit
b0d8d56b7c
|
|
@ -1921,15 +1921,29 @@ ssize_t iov_iter_extract_bvecs(struct iov_iter *iter, struct bio_vec *bv,
|
|||
unsigned short max_vecs, unsigned mem_align_mask,
|
||||
iov_iter_extraction_t extraction_flags)
|
||||
{
|
||||
unsigned long start = (unsigned long)iter_iov_addr(iter);
|
||||
unsigned short entries_left = max_vecs - *nr_vecs;
|
||||
unsigned short nr_pages, i = 0;
|
||||
size_t left, offset, len;
|
||||
struct page **pages;
|
||||
ssize_t size;
|
||||
|
||||
if ((start | iter_iov_len(iter)) & mem_align_mask)
|
||||
/*
|
||||
* DMA engines typically have both memory address and length alignment
|
||||
* requirements, so check these against the alignment mask. For UBUF,
|
||||
* IOVEC and KVEC, only the current segment will be extracted from; for
|
||||
* everything else we might extract from multiple segments, so we need
|
||||
* to check those too.
|
||||
*/
|
||||
if (likely(iter_is_ubuf(iter) ||
|
||||
iter_is_iovec(iter) ||
|
||||
iov_iter_is_kvec(iter))) {
|
||||
unsigned long start = (unsigned long)iter_iov_addr(iter);
|
||||
|
||||
if ((start | iter_iov_len(iter)) & mem_align_mask)
|
||||
return -EINVAL;
|
||||
} else if (iov_iter_alignment(iter) & mem_align_mask) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move page array up in the allocated memory for the bio vecs as far as
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user