From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C45401170E for ; Mon, 11 Sep 2023 14:24:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 419F0C433C8; Mon, 11 Sep 2023 14:24:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1694442288; bh=Q1ulY7JFjFIQiTUYgFgtdEJuHKzMnu5myjTqtY3NYMM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VzvB5Xg923J0dD6o9fUytSPUU+38VG7QBMrIZDtCHaV688o3p/9m49/uDaRlVJnNQ KNbak284Wmnu9fa130ziTVo32BNzUyF30KQb6SXeQVqu8BvsqEwsOq4OO/+xFuHqIJ 9VzoKGBf7IxC1iJ4AtKNtjW67X5QbHg4xY2nrlCM= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, David Howells , Christoph Hellwig , Christian Brauner , Jens Axboe , Al Viro , David Hildenbrand , John Hubbard , Linus Torvalds Subject: [PATCH 6.5 713/739] iov_iter: Fix iov_iter_extract_pages() with zero-sized entries Date: Mon, 11 Sep 2023 15:48:32 +0200 Message-ID: <20230911134710.994442678@linuxfoundation.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230911134650.921299741@linuxfoundation.org> References: <20230911134650.921299741@linuxfoundation.org> User-Agent: quilt/0.67 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.5-stable review patch. If anyone has any objections, please let me know. ------------------ From: David Howells commit f741bd7178c95abd7aeac5a9d933ee542f9a5509 upstream. iov_iter_extract_pages() doesn't correctly handle skipping over initial zero-length entries in ITER_KVEC and ITER_BVEC-type iterators. The problem is that it accidentally reduces maxsize to 0 when it skipping and thus runs to the end of the array and returns 0. Fix this by sticking the calculated size-to-copy in a new variable rather than back in maxsize. Fixes: 7d58fe731028 ("iov_iter: Add a function to extract a page list from an iterator") Signed-off-by: David Howells Reviewed-by: Christoph Hellwig Cc: Christian Brauner Cc: Jens Axboe Cc: Al Viro Cc: David Hildenbrand Cc: John Hubbard Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/iov_iter.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1640,14 +1640,14 @@ static ssize_t iov_iter_extract_bvec_pag size_t *offset0) { struct page **p, *page; - size_t skip = i->iov_offset, offset; + size_t skip = i->iov_offset, offset, size; int k; for (;;) { if (i->nr_segs == 0) return 0; - maxsize = min(maxsize, i->bvec->bv_len - skip); - if (maxsize) + size = min(maxsize, i->bvec->bv_len - skip); + if (size) break; i->iov_offset = 0; i->nr_segs--; @@ -1660,16 +1660,16 @@ static ssize_t iov_iter_extract_bvec_pag offset = skip % PAGE_SIZE; *offset0 = offset; - maxpages = want_pages_array(pages, maxsize, offset, maxpages); + maxpages = want_pages_array(pages, size, offset, maxpages); if (!maxpages) return -ENOMEM; p = *pages; for (k = 0; k < maxpages; k++) p[k] = page + k; - maxsize = min_t(size_t, maxsize, maxpages * PAGE_SIZE - offset); - iov_iter_advance(i, maxsize); - return maxsize; + size = min_t(size_t, size, maxpages * PAGE_SIZE - offset); + iov_iter_advance(i, size); + return size; } /* @@ -1684,14 +1684,14 @@ static ssize_t iov_iter_extract_kvec_pag { struct page **p, *page; const void *kaddr; - size_t skip = i->iov_offset, offset, len; + size_t skip = i->iov_offset, offset, len, size; int k; for (;;) { if (i->nr_segs == 0) return 0; - maxsize = min(maxsize, i->kvec->iov_len - skip); - if (maxsize) + size = min(maxsize, i->kvec->iov_len - skip); + if (size) break; i->iov_offset = 0; i->nr_segs--; @@ -1703,13 +1703,13 @@ static ssize_t iov_iter_extract_kvec_pag offset = (unsigned long)kaddr & ~PAGE_MASK; *offset0 = offset; - maxpages = want_pages_array(pages, maxsize, offset, maxpages); + maxpages = want_pages_array(pages, size, offset, maxpages); if (!maxpages) return -ENOMEM; p = *pages; kaddr -= offset; - len = offset + maxsize; + len = offset + size; for (k = 0; k < maxpages; k++) { size_t seg = min_t(size_t, len, PAGE_SIZE); @@ -1723,9 +1723,9 @@ static ssize_t iov_iter_extract_kvec_pag kaddr += PAGE_SIZE; } - maxsize = min_t(size_t, maxsize, maxpages * PAGE_SIZE - offset); - iov_iter_advance(i, maxsize); - return maxsize; + size = min_t(size_t, size, maxpages * PAGE_SIZE - offset); + iov_iter_advance(i, size); + return size; } /*