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
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <7bbc9419-5c56-450a-b5a0-efeae7457113@gmail.com>
Date: Thu, 27 Nov 2025 16:53:43 +0300
From: Vyacheslav Kovalevsky <slava.kovalevskiy.2014@...il.com>
To: clm@...com, dsterba@...e.com
Cc: linux-btrfs@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: File system corruption after renaming directory and creating a new
 file with same name if system crashes

File system becomes corrupted after renaming directory, creating and 
syncing a new file with the same name if system crashes.


Detailed description
====================

Hello, we have found another issue with btrfs crash behavior.

In short, two directories are created and synced. Then, first directory 
is renamed as subdirectory of the second directory. A new file is 
created with name that was previously associated with the first 
directory. The file is fsync'ed and moved under the renamed directory 
and fsync'ed again. After a crash, file system cannot be mounted, 
reporting block corruption.

It seems that the directory entry becomes corrupted when the `nlink` 
value is erroneously set to 2, somehow.


System info
===========

Linux version 6.18.0-rc7, also tested on 6.18.0-rc2 and 6.14.11.


How to reproduce
================

Test:

```
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   int status;
   int file_fd;

   status = mkdir("dir1", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
   printf("MKDIR: %d\n", status);

   status = mkdir("dir2", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
   printf("MKDIR: %d\n", status);

   sync();

   status = rename("dir1", "dir2/dir3");
   printf("RENAME: %d\n", status);

   // create regular file with the name directory had before rename
   status = open("dir1", O_RDWR | O_CREAT);
   printf("OPEN: %d\n", status);
   file_fd = status;

   status = fsync(file_fd);
   printf("FSYNC: %d\n", status);

   status = rename("dir1", "dir2/dir3/not-dir");
   printf("RENAME: %d\n", status);

   status = fsync(file_fd);
   printf("FSYNC: %d\n", status);
}
```

dmesg:

```
[ 17.559361] BTRFS: device fsid 17a75b88-e58e-457d-83db-ea6599920bc7 
devid 1 transid 9 /dev/vdb (253:16) scanned by mount (1095)
[ 17.559676] BTRFS info (device vdb): first mount of filesystem 
17a75b88-e58e-457d-83db-ea6599920bc7
[ 17.559690] BTRFS info (device vdb): using crc32c (crc32c-lib) checksum 
algorithm
[ 17.562785] BTRFS info (device vdb): start tree-log replay
[ 17.563301] page: refcount:2 mapcount:0 mapping:0000000077ae2817 
index:0x1d00 pfn:0x1057ac
[ 17.563305] memcg:ffff89a500340000
[ 17.563307] aops:btree_aops ino:1
[ 17.563311] flags: 
0x17ffffc800402a(uptodate|lru|private|writeback|node=0|zone=2|lastcpupid=0x1fffff)
[ 17.563315] raw: 0017ffffc800402a fffff9aa84135708 fffff9aa84073d88 
ffff89a51cb23a90
[ 17.563318] raw: 0000000000001d00 ffff89a502951b40 00000002ffffffff 
ffff89a500340000
[ 17.563319] page dumped because: eb page dump
[ 17.563320] BTRFS critical (device vdb): corrupt leaf: root=5 
block=30408704 slot=6 ino=257, invalid nlink: has 2 expect no more than 
1 for dir
[ 17.564768] BTRFS info (device vdb): leaf 30408704 gen 10 total ptrs 17 
free space 14869 owner 5
[ 17.564772] item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160
[ 17.564775] inode generation 3 transid 9 size 16 nbytes 16384
[ 17.564776] block group 0 mode 40755 links 1 uid 0 gid 0
[ 17.564778] rdev 0 sequence 2 flags 0x0
[ 17.564779] atime 1764249615.0
[ 17.564781] ctime 1764249645.130028300
[ 17.564782] mtime 1764249645.130028300
[ 17.564784] otime 1764249615.0
[ 17.564785] item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12
[ 17.564787] index 0 name_len 2
[ 17.564789] item 2 key (256 DIR_ITEM 2363071922) itemoff 16077 itemsize 34
[ 17.564791] location key (257 1 0) type 2
[ 17.564792] transid 9 data_len 0 name_len 4
[ 17.564794] item 3 key (256 DIR_ITEM 2676584006) itemoff 16043 itemsize 34
[ 17.564795] location key (258 1 0) type 2
[ 17.564797] transid 9 data_len 0 name_len 4
[ 17.564798] item 4 key (256 DIR_INDEX 2) itemoff 16009 itemsize 34
[ 17.564800] location key (257 1 0) type 2
[ 17.564801] transid 9 data_len 0 name_len 4
[ 17.564803] item 5 key (256 DIR_INDEX 3) itemoff 15975 itemsize 34
[ 17.564805] location key (258 1 0) type 2
[ 17.564806] transid 9 data_len 0 name_len 4
[ 17.564807] item 6 key (257 INODE_ITEM 0) itemoff 15815 itemsize 160
[ 17.564809] inode generation 9 transid 10 size 14 nbytes 0
[ 17.564811] block group 0 mode 40755 links 2 uid 0 gid 0
[ 17.564812] rdev 0 sequence 1 flags 0x0
[ 17.564813] atime 1764249645.130028300
[ 17.564815] ctime 1764249645.130028300
[ 17.564816] mtime 1764249645.130028300
[ 17.564818] otime 1764249645.130028300
[ 17.564819] item 7 key (257 INODE_REF 256) itemoff 15801 itemsize 14
[ 17.564821] index 2 name_len 4
[ 17.564822] item 8 key (257 INODE_REF 258) itemoff 15787 itemsize 14
[ 17.564824] index 2 name_len 4
[ 17.564825] item 9 key (257 DIR_ITEM 3753155587) itemoff 15750 itemsize 37
[ 17.564827] location key (259 1 0) type 1
[ 17.564828] transid 10 data_len 0 name_len 7
[ 17.564830] item 10 key (257 DIR_INDEX 2) itemoff 15713 itemsize 37
[ 17.564831] location key (259 1 0) type 1
[ 17.564833] transid 10 data_len 0 name_len 7
[ 17.564834] item 11 key (258 INODE_ITEM 0) itemoff 15553 itemsize 160
[ 17.564836] inode generation 9 transid 10 size 8 nbytes 0
[ 17.564837] block group 0 mode 40755 links 1 uid 0 gid 0
[ 17.564839] rdev 0 sequence 1 flags 0x0
[ 17.564840] atime 1764249645.130028300
[ 17.564842] ctime 1764249645.130028300
[ 17.564843] mtime 1764249645.130028300
[ 17.564844] otime 1764249645.130028300
[ 17.564846] item 12 key (258 INODE_REF 256) itemoff 15539 itemsize 14
[ 17.564847] index 3 name_len 4
[ 17.564849] item 13 key (258 DIR_ITEM 1843588421) itemoff 15505 itemsize 34
[ 17.564851] location key (257 1 0) type 2
[ 17.564852] transid 10 data_len 0 name_len 4
[ 17.564853] item 14 key (258 DIR_INDEX 2) itemoff 15471 itemsize 34
[ 17.564855] location key (257 1 0) type 2
[ 17.564856] transid 10 data_len 0 name_len 4
[ 17.564858] item 15 key (259 INODE_ITEM 0) itemoff 15311 itemsize 160
[ 17.564860] inode generation 10 transid 10 size 0 nbytes 0
[ 17.564861] block group 0 mode 100000 links 1 uid 0 gid 0
[ 17.564863] rdev 0 sequence 2 flags 0x0
[ 17.564864] atime 1764249645.139028211
[ 17.564865] ctime 1764249645.140028202
[ 17.564867] mtime 1764249645.139028211
[ 17.564868] otime 1764249645.139028211
[ 17.564869] item 16 key (259 INODE_REF 257) itemoff 15294 itemsize 17
[ 17.564870] index 2 name_len 7
[ 17.564872] BTRFS error (device vdb): block=30408704 write time tree 
block corruption detected
[ 17.566147] BTRFS: error (device vdb) in btrfs_commit_transaction:2535: 
errno=-5 IO failure (Error while writing out transaction)
[ 17.567374] BTRFS warning (device vdb state E): Skipping commit of 
aborted transaction.
[ 17.567377] BTRFS error (device vdb state EA): Transaction aborted 
(error -5)
[ 17.568502] BTRFS: error (device vdb state EA) in 
cleanup_transaction:2020: errno=-5 IO failure
[ 17.569956] BTRFS: error (device vdb state EA) in 
btrfs_replay_log:2093: errno=-5 IO failure (Failed to recover log tree)
[ 17.571778] BTRFS error (device vdb state EA): open_ctree failed: -5
```

Steps:
1. Create and mount new btrfs file system in default configuration.
2. Change directory to root of the file system and run the compiled test.
3. Cause hard system crash (e.g. QEMU `system_reset` command).
4. Remount file system after crash.
5. Observe that mount fails.

Notes:

- if path in open() is changed to any other name (instead of `dir1`) the 
bug will not manifest.


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ