git: 26b23f07fb98 - main - sendfile: Ensure that sfio->npages is initialized
Mark Johnston
markj at FreeBSD.org
Sat Dec 26 21:14:46 UTC 2020
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=26b23f07fb981662debd69b9969f78864c262466
commit 26b23f07fb981662debd69b9969f78864c262466
Author: Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2020-12-26 21:07:40 +0000
Commit: Mark Johnston <markj at FreeBSD.org>
CommitDate: 2020-12-26 21:07:40 +0000
sendfile: Ensure that sfio->npages is initialized
We initialize sfio->npages only when some I/O is required to satisfy the
request. However, sendfile_iodone() contains an INVARIANTS-only check
that references sfio->npages, and this check is executed even if no I/O
is performed, so the check may use an uninitialized value.
Fix the problem by initializing sfio->npages earlier. Note that
sendfile_swapin() always initializes the page array. In some rare cases
we need to trim the page array so ensure that sfio->npages gets updated
accordingly.
Reported by: syzkaller (with KASAN)
Reviewed by: kib
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D27726
---
sys/kern/kern_sendfile.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index e0b9b0e261d4..18c9ade721a9 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -413,12 +413,13 @@ out_with_ref:
*/
static int
sendfile_swapin(vm_object_t obj, struct sf_io *sfio, int *nios, off_t off,
- off_t len, int npages, int rhpages, int flags)
+ off_t len, int rhpages, int flags)
{
vm_page_t *pa;
- int a, count, count1, grabbed, i, j, rv;
+ int a, count, count1, grabbed, i, j, npages, rv;
pa = sfio->pa;
+ npages = sfio->npages;
*nios = 0;
flags = (flags & SF_NODISKIO) ? VM_ALLOC_NOWAIT : 0;
sfio->pindex0 = OFF_TO_IDX(off);
@@ -905,6 +906,7 @@ retry_space:
sfio->obj = obj;
sfio->error = 0;
sfio->m = NULL;
+ sfio->npages = npages;
#ifdef KERN_TLS
/*
* This doesn't use ktls_hold() because sfio->m will
@@ -914,8 +916,8 @@ retry_space:
sfio->tls = tls;
#endif
vm_object_pip_add(obj, 1);
- error = sendfile_swapin(obj, sfio, &nios, off, space, npages,
- rhpages, flags);
+ error = sendfile_swapin(obj, sfio, &nios, off, space, rhpages,
+ flags);
if (error != 0) {
if (vp != NULL)
VOP_UNLOCK(vp);
@@ -963,7 +965,7 @@ retry_space:
if (pa[i] == NULL) {
SFSTAT_INC(sf_busy);
fixspace(npages, i, off, &space);
- npages = i;
+ sfio->npages = i;
softerr = EBUSY;
break;
}
@@ -1042,12 +1044,14 @@ retry_space:
if (sf == NULL) {
SFSTAT_INC(sf_allocfail);
sendfile_iowait(sfio, "sfnosf");
- for (int j = i; j < npages; j++)
+ for (int j = i; j < npages; j++) {
vm_page_unwire(pa[j], PQ_INACTIVE);
+ pa[j] = NULL;
+ }
if (m == NULL)
softerr = ENOBUFS;
fixspace(npages, i, off, &space);
- npages = i;
+ sfio->npages = i;
break;
}
@@ -1152,7 +1156,6 @@ prepend_header:
} else {
sfio->so = so;
sfio->m = m0;
- sfio->npages = npages;
soref(so);
error = (*so->so_proto->pr_usrreqs->pru_send)
(so, PRUS_NOTREADY, m, NULL, NULL, td);
More information about the dev-commits-src-all
mailing list