Since prefaulting moved to the slow write path, a buffered write can reach ->write_begin() and ->write_end() before discovering that its source buffer is unreadable. Several filesystems can extend i_size in these callbacks even when no data was copied. For example, a one-byte pwrite() at offset 4096 into an empty file can fail with EFAULT but leave a 4096-byte file. Prefault the source before ->write_begin() when the write position is beyond EOF, and return EFAULT if no source bytes can be made readable. Overwrites and appends continue to skip this prefault. Keep the existing slow-path faulting for forward progress after a failed atomic copy. This also leaves intentional zero-length ->write_end() calls used by generic_cont_expand_simple() unchanged. As with the previous prefaulting behavior, a concurrent userspace unmap can still race with the later copy. Fixes: 665575cff098 ("filemap: move prefaulting out of hot write path") Reported-by: Kiryl Shutsemau Closes: https://lore.kernel.org/linux-mm/at9xXRhD2xZhszEj@thinkstation/ Suggested-by: Kiryl Shutsemau Link: https://lore.kernel.org/all/at-XtWBQg3jv3H8Z@thinkstation/ Cc: stable@vger.kernel.org Signed-off-by: Hungyu Lin --- mm/filemap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index b74bc1e5015c6f318333427f223b9f42061a6213..30414d55412b84f11ebe98b8eea607ee8c04eef5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -4389,6 +4389,16 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) break; } + /* + * Some filesystems can extend i_size even when nothing was copied. + * Prefault writes beyond EOF to catch unreadable source buffers. + */ + if (unlikely(pos > i_size_read(mapping->host)) && + fault_in_iov_iter_readable(i, bytes) == bytes) { + status = -EFAULT; + break; + } + status = a_ops->write_begin(iocb, mapping, pos, bytes, &folio, &fsdata); if (unlikely(status < 0)) base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4 -- 2.43.0