linux-brain/fs
Filipe Manana 86f2a3e9aa btrfs: fix lost inode on log replay after mix of fsync, rename and inode eviction
[ Upstream commit ecc64fab7d49c678e70bd4c35fe64d2ab3e3d212 ]

When checking if we need to log the new name of a renamed inode, we are
checking if the inode and its parent inode have been logged before, and if
not we don't log the new name. The check however is buggy, as it directly
compares the logged_trans field of the inodes versus the ID of the current
transaction. The problem is that logged_trans is a transient field, only
stored in memory and never persisted in the inode item, so if an inode
was logged before, evicted and reloaded, its logged_trans field is set to
a value of 0, meaning the check will return false and the new name of the
renamed inode is not logged. If the old parent directory was previously
fsynced and we deleted the logged directory entries corresponding to the
old name, we end up with a log that when replayed will delete the renamed
inode.

The following example triggers the problem:

  $ mkfs.btrfs -f /dev/sdc
  $ mount /dev/sdc /mnt

  $ mkdir /mnt/A
  $ mkdir /mnt/B
  $ echo -n "hello world" > /mnt/A/foo

  $ sync

  # Add some new file to A and fsync directory A.
  $ touch /mnt/A/bar
  $ xfs_io -c "fsync" /mnt/A

  # Now trigger inode eviction. We are only interested in triggering
  # eviction for the inode of directory A.
  $ echo 2 > /proc/sys/vm/drop_caches

  # Move foo from directory A to directory B.
  # This deletes the directory entries for foo in A from the log, and
  # does not add the new name for foo in directory B to the log, because
  # logged_trans of A is 0, which is less than the current transaction ID.
  $ mv /mnt/A/foo /mnt/B/foo

  # Now make an fsync to anything except A, B or any file inside them,
  # like for example create a file at the root directory and fsync this
  # new file. This syncs the log that contains all the changes done by
  # previous rename operation.
  $ touch /mnt/baz
  $ xfs_io -c "fsync" /mnt/baz

  <power fail>

  # Mount the filesystem and replay the log.
  $ mount /dev/sdc /mnt

  # Check the filesystem content.
  $ ls -1R /mnt
  /mnt/:
  A
  B
  baz

  /mnt/A:
  bar

  /mnt/B:
  $

  # File foo is gone, it's neither in A/ nor in B/.

Fix this by using the inode_logged() helper at btrfs_log_new_name(), which
safely checks if an inode was logged before in the current transaction.

A test case for fstests will follow soon.

CC: stable@vger.kernel.org # 4.14+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2021-08-08 09:04:07 +02:00
..
9p 9P: Cast to loff_t before multiplying 2020-11-05 11:43:34 +01:00
adfs Merge branch 'work.adfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2019-07-19 11:33:22 -07:00
affs fs/affs: release old buffer head on error path 2021-03-04 10:26:48 +01:00
afs afs: Fix tracepoint string placement with built-in AFS 2021-07-28 13:30:58 +02:00
autofs autofs: fix a leak in autofs_expire_indirect() 2019-10-25 00:03:11 -04:00
befs fs: Fill in max and min timestamps in superblock 2019-08-30 07:27:17 -07:00
bfs bfs: don't use WARNING: string when it's just info. 2021-01-06 14:48:39 +01:00
btrfs btrfs: fix lost inode on log replay after mix of fsync, rename and inode eviction 2021-08-08 09:04:07 +02:00
cachefiles cachefiles: Handle readpage error correctly 2020-11-05 11:43:36 +01:00
ceph ceph: remove bogus checks and WARN_ONs from ceph_set_page_dirty 2021-07-20 16:10:48 +02:00
cifs cifs: fix the out of range assignment to bit fields in parse_server_interfaces 2021-07-31 08:19:38 +02:00
coda y2038: add inode timestamp clamping 2019-09-19 09:42:37 -07:00
configfs configfs: fix memleak in configfs_release_bin_file 2021-07-14 16:53:46 +02:00
cramfs cramfs: fix usage on non-MTD device 2019-11-23 21:44:49 -05:00
crypto fscrypt: don't ignore minor_hash when hash is 0 2021-07-19 08:53:14 +02:00
debugfs debugfs: do not attempt to create a new file before the filesystem is initalized 2021-03-04 10:26:10 +01:00
devpts devpts_pty_kill(): don't bother with d_delete() 2019-09-03 09:30:56 -04:00
dlm fs: dlm: fix memory leak when fenced 2021-07-14 16:53:17 +02:00
ecryptfs Revert "ecryptfs: replace BUG_ON with error handling code" 2021-05-26 12:05:19 +02:00
efivarfs efivarfs: revert "fix memory leak in efivarfs_create()" 2020-12-02 08:49:53 +01:00
efs fs: Fill in max and min timestamps in superblock 2019-08-30 07:27:17 -07:00
erofs erofs: add unsupported inode i_format check 2021-05-11 14:04:02 +02:00
exportfs exportfs_decode_fh(): negative pinned may become positive without the parent locked 2019-11-10 11:56:05 -05:00
ext2 ext2: don't update mtime on COW faults 2020-09-09 19:12:30 +02:00
ext4 ext4: use ext4_grp_locked_error in mb_find_extent 2021-07-14 16:53:03 +02:00
f2fs f2fs: Show casefolding support only when supported 2021-07-25 14:35:13 +02:00
fat fat: don't allow to mount if the FAT length == 0 2020-06-17 16:40:36 +02:00
freevxfs fs: Fill in max and min timestamps in superblock 2019-08-30 07:27:17 -07:00
fscache Revert "Merge tag 'keys-acl-20190703' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs" 2019-07-10 18:43:43 -07:00
fuse fuse: reject internal errno 2021-07-14 16:53:09 +02:00
gfs2 gfs2: Fix use-after-free in gfs2_glock_shrink_scan 2021-06-18 09:58:59 +02:00
hfs hfs: add lock nesting notation to hfs_find_init 2021-07-31 08:19:38 +02:00
hfsplus hfsplus: prevent corruption in shrinking truncate 2021-05-19 10:08:29 +02:00
hostfs hostfs: fix memory handling in follow_link() 2021-04-14 08:24:14 +02:00
hpfs fs: hpfs: Initialize filesystem timestamp ranges 2019-08-30 08:11:25 -07:00
hugetlbfs hugetlbfs: fix mount mode command line processing 2021-07-28 13:31:01 +02:00
iomap iomap: remove the length variable in iomap_seek_hole 2021-07-31 08:19:39 +02:00
isofs isofs: release buffer head before return 2021-03-04 10:26:30 +01:00
jbd2 jbd2: fix up sparse warnings in checkpoint code 2020-11-18 19:20:30 +01:00
jffs2 jffs2: check the validity of dstlen in jffs2_zlib_compress() 2021-05-11 14:04:16 +02:00
jfs fs/jfs: Fix missing error code in lmLogInit() 2021-07-20 16:10:42 +02:00
kernfs kernfs: do not call fsnotify() with name without a parent 2020-08-19 08:16:12 +02:00
lockd lockd: don't use interval-based rebinding over TCP 2020-12-30 11:51:16 +01:00
minix fs/minix: remove expected error message in block_to_path() 2020-08-21 13:05:37 +02:00
nfs NFSv4/pNFS: Don't call _nfs4_pnfs_v3_ds_connect multiple times 2021-07-20 16:10:50 +02:00
nfs_common nfs_common: need lock during iterate through the list 2020-12-30 11:51:22 +01:00
nfsd NFSD: fix error handling in NFSv4.0 callbacks 2021-04-07 14:47:39 +02:00
nilfs2 nilfs2: fix memory leak in nilfs_sysfs_delete_device_group 2021-06-30 08:47:50 -04:00
nls
notify fanotify: fix ignore mask logic for events on child and on dir 2020-06-17 16:40:24 +02:00
ntfs ntfs: fix validity check for file name attribute 2021-07-14 16:53:01 +02:00
ocfs2 ocfs2: issue zeroout to EOF blocks 2021-08-04 12:27:37 +02:00
omfs fs: omfs: Initialize filesystem timestamp ranges 2019-08-30 08:11:25 -07:00
openpromfs Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2019-07-19 10:42:02 -07:00
orangefs orangefs: fix orangefs df output. 2021-07-20 16:10:48 +02:00
overlayfs ovl: fix missing revert_creds() on error path 2021-05-14 09:44:16 +02:00
proc proc: Avoid mixing integer types in mem_rw() 2021-07-28 13:30:58 +02:00
pstore pstore: Fix typo in compression option name 2021-03-04 10:26:45 +01:00
qnx4 fs: Fill in max and min timestamps in superblock 2019-08-30 07:27:17 -07:00
qnx6 fs: Fill in max and min timestamps in superblock 2019-08-30 07:27:17 -07:00
quota quota: Fix memory leak when handling corrupted quota file 2021-03-04 10:26:26 +01:00
ramfs ramfs: fix nommu mmap with gaps in the page cache 2020-10-29 09:57:53 +01:00
reiserfs reiserfs: add check for invalid 1st journal block 2021-07-19 08:53:08 +02:00
romfs romfs: fix uninitialized memory leak in romfs_dev_read() 2020-08-26 10:40:51 +02:00
squashfs squashfs: fix divide error in calculate_skip() 2021-05-19 10:08:29 +02:00
sysfs sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output 2021-03-07 12:20:48 +01:00
sysv fs: sysv: Initialize filesystem timestamp ranges 2019-08-30 07:27:18 -07:00
tracefs tracing: Do not create tracefs files if tracefs lockdown is in effect 2019-10-12 20:49:07 -04:00
ubifs ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode 2021-07-20 16:10:50 +02:00
udf udf: Fix NULL pointer dereference in udf_symlink function 2021-07-19 08:53:08 +02:00
ufs fs/ufs: avoid potential u32 multiplication overflow 2020-08-21 13:05:37 +02:00
unicode unicode: make array 'token' static const, makes object smaller 2019-09-17 11:48:24 -04:00
verity fs-verity: support builtin file signatures 2019-08-12 19:33:50 -07:00
xfs xfs: Fix assert failure in xfs_setattr_size() 2021-03-07 12:20:42 +01:00
Kconfig fs-verity for 5.4 2019-09-18 16:59:14 -07:00
Kconfig.binfmt binfmt_flat: make support for old format binaries optional 2019-06-24 09:16:47 +10:00
Makefile fs-verity for 5.4 2019-09-18 16:59:14 -07:00
aio.c aio: fix async fsync creds 2020-06-17 16:40:24 +02:00
anon_inodes.c Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2019-07-19 10:42:02 -07:00
attr.c utimes: Clamp the timestamps in notify_change() 2020-02-11 04:35:12 -08:00
bad_inode.c
binfmt_aout.c
binfmt_elf.c fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() 2020-06-03 08:21:27 +02:00
binfmt_elf_fdpic.c
binfmt_em86.c
binfmt_flat.c binfmt_flat: revert "binfmt_flat: don't offset the data start" 2020-09-03 11:26:39 +02:00
binfmt_misc.c binfmt_misc: fix possible deadlock in bm_register_write 2021-03-17 17:03:57 +01:00
binfmt_script.c
block_dev.c block: reexpand iov_iter after read/write 2021-05-22 11:38:29 +02:00
buffer.c fs: Don't invalidate page buffers in block_write_full_page() 2020-11-05 11:43:24 +01:00
char_dev.c chardev: Avoid potential use-after-free in 'chrdev_open()' 2020-01-14 20:08:18 +01:00
compat.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
compat_binfmt_elf.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 193 2019-05-30 11:29:21 -07:00
compat_ioctl.c fix compat handling of FICLONERANGE, FIDEDUPERANGE and FS_IOC_FIEMAP 2020-01-09 10:20:05 +01:00
coredump.c coredump: fix core_pattern parse error 2020-12-11 13:23:30 +01:00
d_path.c fs: fix NULL dereference due to data race in prepend_path() 2020-10-29 09:57:45 +01:00
dax.c dax: fix ENOMEM handling in grab_mapping_entry() 2021-07-14 16:53:25 +02:00
dcache.c fix dget_parent() fastpath race 2020-10-01 13:17:19 +02:00
dcookies.c
direct-io.c fs: direct-io: fix missing sdio->boundary 2021-04-14 08:24:11 +02:00
drop_caches.c fs: avoid softlockups in s_inodes iterators 2020-01-12 12:21:37 +01:00
eventfd.c eventfd: track eventfd_signal() recursion depth 2020-02-11 04:35:37 -08:00
eventpoll.c ep_create_wakeup_source(): dentry name can change under you... 2020-10-07 08:01:31 +02:00
exec.c exec: Transform exec_update_mutex into a rw_semaphore 2021-01-09 13:44:55 +01:00
fcntl.c fcntl: Fix potential deadlock in send_sig{io, urg}() 2021-01-06 14:48:39 +01:00
fhandle.c fs/handle.c - fix up kerneldoc 2019-08-07 21:51:47 -04:00
file.c fix multiplication overflow in copy_fdtable() 2020-05-27 17:46:12 +02:00
file_table.c vfs: Export flush_delayed_fput for use by knfsd. 2019-08-19 11:00:39 -04:00
filesystems.c fs/filesystems.c: downgrade user-reachable WARN_ONCE() to pr_warn_once() 2020-04-17 10:50:21 +02:00
fs-writeback.c writeback: fix obtain a reference to a freeing memcg css 2021-07-14 16:53:35 +02:00
fs_context.c vfs: subtype handling moved to fuse 2019-09-06 21:28:49 +02:00
fs_parser.c vfs: Make fs_parse() handle fs_param_is_fd-type params better 2019-09-12 21:06:14 -04:00
fs_pin.c switch the remnants of releasing the mountpoint away from fs_pin 2019-07-16 22:52:37 -04:00
fs_struct.c
fs_types.c
fsopen.c Merge branch 'work.mount0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2019-07-19 10:42:02 -07:00
inode.c futex: Fix inode life-time issue 2020-03-25 08:25:58 +01:00
internal.h cgroup1: fix leaked context root causing sporadic NULL deref in LTP 2021-07-31 08:19:37 +02:00
io_uring.c io_uring: Fix current->fs handling in io_sq_wq_submit_work() 2021-01-30 13:54:10 +01:00
ioctl.c compat_ioctl: add compat_ptr_ioctl() 2019-12-17 19:55:30 +01:00
libfs.c libfs: fix error cast of negative value in simple_attr_write() 2020-11-24 13:29:19 +01:00
locks.c locks: reinstate locks_delete_block optimization 2020-03-25 08:25:41 +01:00
mbcache.c
mount.h switch the remnants of releasing the mountpoint away from fs_pin 2019-07-16 22:52:37 -04:00
mpage.c fs: move guard_bio_eod() after bio_set_op_attrs 2020-01-17 19:48:21 +01:00
namei.c namei: only return -ECHILD from follow_dotdot_rcu() 2020-03-05 16:43:48 +01:00
namespace.c fs/namespace.c: WARN if mnt_count has become negative 2021-01-06 14:48:40 +01:00
no-block.c
nsfs.c
open.c cifs_atomic_open(): fix double-put on late allocation failure 2020-03-18 07:17:51 +01:00
pipe.c
pnode.c propagate_one(): mnt_set_mountpoint() needs mount_lock 2020-05-02 08:48:44 +02:00
pnode.h mount: fix mounting of detached mounts onto targets that reside on shared mounts 2021-03-17 17:03:33 +01:00
posix_acl.c
proc_namespace.c vfs: subtype handling moved to fuse 2019-09-06 21:28:49 +02:00
read_write.c fs: allow deduplication of eof block into the end of the destination file 2020-02-11 04:35:23 -08:00
readdir.c readdir: make sure to verify directory entry for legacy interfaces too 2021-04-21 12:56:16 +02:00
select.c kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data() 2021-03-24 11:26:44 +01:00
seq_file.c seq_file: disallow extremely large seq buffer allocations 2021-07-20 16:10:54 +02:00
signalfd.c fs/signalfd.c: fix inconsistent return codes for signalfd4 2020-08-26 10:40:58 +02:00
splice.c splice: only read in as much information as there is pipe buffer space 2019-12-17 19:56:52 +01:00
stack.c
stat.c
statfs.c vfs: Fix EOVERFLOW testing in put_compat_statfs64 2019-10-03 14:21:35 -07:00
super.c vfs: remove lockdep bogosity in __sb_start_write 2020-11-24 13:29:01 +01:00
sync.c
timerfd.c timerfd: Prepare for PREEMPT_RT 2019-08-01 20:51:23 +02:00
userfaultfd.c userfaultfd: do not untag user pointers 2021-07-28 13:31:01 +02:00
utimes.c utimes: Clamp the timestamps in notify_change() 2020-02-11 04:35:12 -08:00
xattr.c xattr: break delegations in {set,remove}xattr 2020-08-11 15:33:39 +02:00