Skip to content

Commit 00d6df7

Browse files
deepanshu406gregkh
authored andcommitted
netfs: Fix kernel BUG in netfs_limit_iter() for ITER_KVEC iterators
[ Upstream commit 67e467a ] When a process crashes and the kernel writes a core dump to a 9P filesystem, __kernel_write() creates an ITER_KVEC iterator. This iterator reaches netfs_limit_iter() via netfs_unbuffered_write(), which only handles ITER_FOLIOQ, ITER_BVEC and ITER_XARRAY iterator types, hitting the BUG() for any other type. Fix this by adding netfs_limit_kvec() following the same pattern as netfs_limit_bvec(), since both kvec and bvec are simple segment arrays with pointer and length fields. Dispatch it from netfs_limit_iter() when the iterator type is ITER_KVEC. Fixes: cae932d ("netfs: Add func to calculate pagecount/size-limited span of an iterator") Reported-by: syzbot+9c058f0d63475adc97fd@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=9c058f0d63475adc97fd Tested-by: syzbot+9c058f0d63475adc97fd@syzkaller.appspotmail.com Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com> Link: https://patch.msgid.link/20260307090041.359870-1-kartikey406@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 59f6ccd commit 00d6df7

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

fs/netfs/iterator.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,47 @@ static size_t netfs_limit_bvec(const struct iov_iter *iter, size_t start_offset,
142142
return min(span, max_size);
143143
}
144144

145+
/*
146+
* Select the span of a kvec iterator we're going to use. Limit it by both
147+
* maximum size and maximum number of segments. Returns the size of the span
148+
* in bytes.
149+
*/
150+
static size_t netfs_limit_kvec(const struct iov_iter *iter, size_t start_offset,
151+
size_t max_size, size_t max_segs)
152+
{
153+
const struct kvec *kvecs = iter->kvec;
154+
unsigned int nkv = iter->nr_segs, ix = 0, nsegs = 0;
155+
size_t len, span = 0, n = iter->count;
156+
size_t skip = iter->iov_offset + start_offset;
157+
158+
if (WARN_ON(!iov_iter_is_kvec(iter)) ||
159+
WARN_ON(start_offset > n) ||
160+
n == 0)
161+
return 0;
162+
163+
while (n && ix < nkv && skip) {
164+
len = kvecs[ix].iov_len;
165+
if (skip < len)
166+
break;
167+
skip -= len;
168+
n -= len;
169+
ix++;
170+
}
171+
172+
while (n && ix < nkv) {
173+
len = min3(n, kvecs[ix].iov_len - skip, max_size);
174+
span += len;
175+
nsegs++;
176+
ix++;
177+
if (span >= max_size || nsegs >= max_segs)
178+
break;
179+
skip = 0;
180+
n -= len;
181+
}
182+
183+
return min(span, max_size);
184+
}
185+
145186
/*
146187
* Select the span of an xarray iterator we're going to use. Limit it by both
147188
* maximum size and maximum number of segments. It is assumed that segments
@@ -245,6 +286,8 @@ size_t netfs_limit_iter(const struct iov_iter *iter, size_t start_offset,
245286
return netfs_limit_bvec(iter, start_offset, max_size, max_segs);
246287
if (iov_iter_is_xarray(iter))
247288
return netfs_limit_xarray(iter, start_offset, max_size, max_segs);
289+
if (iov_iter_is_kvec(iter))
290+
return netfs_limit_kvec(iter, start_offset, max_size, max_segs);
248291
BUG();
249292
}
250293
EXPORT_SYMBOL(netfs_limit_iter);

0 commit comments

Comments
 (0)