lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <174786678014.1383760.1321101978729586160.stgit@frogsfrogsfrogs> Date: Wed, 21 May 2025 15:41:43 -0700 From: "Darrick J. Wong" <djwong@...nel.org> To: tytso@....edu Cc: linux-ext4@...r.kernel.org Subject: [PATCH 26/29] fuse2fs: fix post-EOF preallocation clearing on truncation From: Darrick J. Wong <djwong@...nel.org> generic/092 shows that truncating a file to its current size does not clean out post-eof preallocations like the kernel does. Adopt the kernel's behavior for consistency. Signed-off-by: "Darrick J. Wong" <djwong@...nel.org> --- misc/fuse2fs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index 46ae73bd4e25bb..626e3a42181148 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -2068,9 +2068,30 @@ static int op_chown(const char *path, uid_t owner, gid_t group return ret; } -static int truncate_helper(ext2_filsys fs, ext2_ino_t ino, off_t new_size) +static int punch_posteof(struct fuse2fs *ff, ext2_ino_t ino, off_t new_size) { + ext2_filsys fs = ff->fs; + struct ext2_inode_large inode; + blk64_t truncate_block = (new_size + fs->blocksize - 1) / fs->blocksize; + errcode_t err; + + err = fuse2fs_read_inode(fs, ino, &inode); + if (err) + return translate_error(fs, ino, err); + + err = ext2fs_punch(fs, ino, EXT2_INODE(&inode), 0, truncate_block, + ~0ULL); + if (err) + return translate_error(fs, ino, err); + + return 0; +} + +static int truncate_helper(struct fuse2fs *ff, ext2_ino_t ino, off_t new_size) +{ + ext2_filsys fs = ff->fs; ext2_file_t file; + __u64 old_isize; errcode_t err; int ret = 0; @@ -2078,17 +2099,40 @@ static int truncate_helper(ext2_filsys fs, ext2_ino_t ino, off_t new_size) if (err) return translate_error(fs, ino, err); + err = ext2fs_file_get_lsize(file, &old_isize); + if (err) { + ret = translate_error(fs, ino, err); + goto out_close; + } + + dbg_printf(ff, "%s: ino=%u isize=0x%llx new_size=0x%llx\n", __func__, + ino, + (unsigned long long)old_isize, + (unsigned long long)new_size); + err = ext2fs_file_set_size2(file, new_size); if (err) ret = translate_error(fs, ino, err); +out_close: err = ext2fs_file_close(file); if (ret) return ret; if (err) return translate_error(fs, ino, err); - return update_mtime(fs, ino, NULL); + ret = update_mtime(fs, ino, NULL); + if (ret) + return ret; + + /* + * Truncating to the current size is usually understood to mean that + * we should clear out post-EOF preallocations. + */ + if (new_size == old_isize) + return punch_posteof(ff, ino, new_size); + + return 0; } static int op_truncate(const char *path, off_t len @@ -2122,7 +2166,7 @@ static int op_truncate(const char *path, off_t len if (ret) goto out; - ret = truncate_helper(fs, ino, len); + ret = truncate_helper(ff, ino, len); if (ret) goto out; @@ -2222,7 +2266,7 @@ static int __op_open(struct fuse2fs *ff, const char *path, } if (fp->flags & O_TRUNC) { - ret = truncate_helper(fs, file->ino, 0); + ret = truncate_helper(ff, file->ino, 0); if (ret) goto out; }
Powered by blists - more mailing lists