From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Daeho Jeong <daehojeong@google.com>,
stable@kernel.org, Chao Yu <chao@kernel.org>,
Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.1.y] f2fs: disallow mmap write and data-modifying fallocate on atomic files
Date: Tue, 10 Nov 2026 13:06:28 -0500 [thread overview]
Message-ID: <20261110180356.3017239-1-sashal@kernel.org> (raw)
In-Reply-To: <20261107054834-failed-6.1-06dfe4a7eb69@kernel.org>
From: Daeho Jeong <daehojeong@google.com>
[ Upstream commit 06dfe4a7eb696d868b196c2a49873142f19bd862 ]
Stores through a shared writable mapping and fallocate with
FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE, FALLOC_FL_COLLAPSE_RANGE or
FALLOC_FL_INSERT_RANGE do not go through ->write_begin, so they bypass
the COW inode and modify the original inode directly. Reject them while
the file is in atomic write mode, as fallocate already does for pinned
and compressed files. A write fault gets SIGBUS and fallocate gets
-EOPNOTSUPP.
fallocate without these flags only preallocates blocks and stays
allowed.
f2fs_vm_page_mkwrite() cannot take inode_lock, so check the flag under
invalidate_lock, and hold invalidate_lock in
f2fs_ioc_start_atomic_write() from the flush until the flag is set.
Otherwise a fault could check the flag, then start_atomic_write could
flush and set the flag, and the fault would dirty the folio afterwards.
Cc: stable@kernel.org
Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
[ sashal: replaced the shared out_unlock cleanup with explicit invalidate_lock releases on all error exits ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/f2fs/file.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index bde1c9cfe1df4..13a61e6ef448f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -102,6 +102,18 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
file_update_time(vmf->vma->vm_file);
filemap_invalidate_lock_shared(inode->i_mapping);
+
+ /*
+ * mmap stores bypass the COW inode and would break atomicity. Check
+ * under invalidate_lock: f2fs_ioc_start_atomic_write() holds it while
+ * flushing dirty pages and setting FI_ATOMIC_FILE, so either it sees
+ * our dirty page and writes it back, or we see the flag.
+ */
+ if (unlikely(f2fs_is_atomic_file(inode))) {
+ err = -EOPNOTSUPP;
+ goto out_sem;
+ }
+
lock_page(page);
if (unlikely(page->mapping != inode->i_mapping ||
page_offset(page) > i_size_read(inode) ||
@@ -1888,9 +1900,11 @@ static long f2fs_fallocate(struct file *file, int mode,
/*
* Pinned file should not support partial truncation since the block
- * can be used by applications.
+ * can be used by applications. Atomic files should not either, since
+ * these modify the original inode directly and break atomicity.
*/
- if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) &&
+ if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode) ||
+ f2fs_is_atomic_file(inode)) &&
(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE))) {
ret = -EOPNOTSUPP;
@@ -2174,6 +2188,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
goto out;
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
+ /* serialize with f2fs_vm_page_mkwrite(), see the comment there */
+ filemap_invalidate_lock(inode->i_mapping);
/*
* Should wait end_io to count F2FS_WB_CP_DATA correctly by
@@ -2184,6 +2200,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
inode->i_ino, get_dirty_pages(inode));
ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
if (ret) {
+ filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
goto out;
}
@@ -2193,6 +2210,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
/* Create a COW inode for atomic write */
pinode = f2fs_iget(inode->i_sb, fi->i_pino);
if (IS_ERR(pinode)) {
+ filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
ret = PTR_ERR(pinode);
goto out;
@@ -2201,6 +2219,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
ret = f2fs_get_tmpfile(mnt_userns, pinode, &fi->cow_inode);
iput(pinode);
if (ret) {
+ filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
goto out;
}
@@ -2215,6 +2234,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true);
if (ret) {
+ filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
goto out;
}
@@ -2229,6 +2249,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
stat_inc_atomic_inode(inode);
set_inode_flag(inode, FI_ATOMIC_FILE);
+ filemap_invalidate_unlock(inode->i_mapping);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
f2fs_update_time(sbi, REQ_TIME);
--
2.53.0
prev parent reply other threads:[~2026-11-10 18:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 10:48 FAILED: patch "[PATCH] f2fs: disallow mmap write and data-modifying fallocate on atomic files" failed to apply to 6.1-stable tree Sasha Levin
2026-11-10 18:06 ` Sasha Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110180356.3017239-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=chao@kernel.org \
--cc=daehojeong@google.com \
--cc=jaegeuk@kernel.org \
--cc=stable@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.