Note: Versions mentioned in the description apply only to the upstream kernel-devel
package and not the kernel-devel
package as distributed by Centos
.
See How to fix?
for Centos:6
relevant fixed versions and status.
In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix removed dentries still existing after log is synced
When we move one inode from one directory to another and both the inode
and its previous parent directory were logged before, we are not supposed
to have the dentry for the old parent if we have a power failure after the
log is synced. Only the new dentry is supposed to exist.
Generally this works correctly, however there is a scenario where this is
not currently working, because the old parent of the file/directory that
was moved is not authoritative for a range that includes the dir index and
dir item keys of the old dentry. This case is better explained with the
following example and reproducer:
The test requires a very specific layout of keys and items in the
fs/subvolume btree to trigger the bug. So we want to make sure that
on whatever platform we are, we have the same leaf/node size.
Currently in btrfs the node/leaf size can not be smaller than the page
size (but it can be greater than the page size). So use the largest
supported node/leaf size (64K).
$ mkfs.btrfs -f -n 65536 /dev/sdc
$ mount /dev/sdc /mnt
"testdir" is inode 257.
$ mkdir /mnt/testdir
$ chmod 755 /mnt/testdir
Create several empty files to have the directory "testdir" with its
items spread over several leaves (7 in this case).
$ for ((i = 1; i <= 1200; i++)); do
echo -n > /mnt/testdir/file$i
done
Create our test directory "dira", inode number 1458, which gets all
its items in leaf 7.
The BTRFS_DIR_ITEM_KEY item for inode 257 ("testdir") that points to
the entry named "dira" is in leaf 2, while the BTRFS_DIR_INDEX_KEY
item that points to that entry is in leaf 3.
For this particular filesystem node size (64K), file count and file
names, we endup with the directory entry items from inode 257 in
leaves 2 and 3, as previously mentioned - what matters for triggering
the bug exercised by this test case is that those items are not placed
in leaf 1, they must be placed in a leaf different from the one
containing the inode item for inode 257.
The corresponding BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items for
the parent inode (257) are the following:
item 460 key (257 DIR_ITEM 3724298081) itemoff 48344 itemsize 34
location key (1458 INODE_ITEM 0) type DIR
transid 6 data_len 0 name_len 4
name: dira
and:
item 771 key (257 DIR_INDEX 1202) itemoff 36673 itemsize 34
location key (1458 INODE_ITEM 0) type DIR
transid 6 data_len 0 name_len 4
name: dira
$ mkdir /mnt/testdir/dira
Make sure everything done so far is durably persisted.
$ sync
Now do a change to inode 257 ("testdir") that does not result in
COWing leaves 2 and 3 - the leaves that contain the directory items
pointing to inode 1458 (directory "dira").
Changing permissions, the owner/group, updating or adding a xattr,
etc, will not change (COW) leaves 2 and 3. So for the sake of
simplicity change the permissions of inode 257, which results in
updating its inode item and therefore change (COW) only leaf 1.
$ chmod 700 /mnt/testdir
Now fsync directory inode 257.
Since only the first leaf was changed/COWed, we log the inode item of
inode 257 and only the dentries found in the first leaf, all have a
key type of BTRFS_DIR_ITEM_KEY, and no keys of type
BTRFS_DIR_INDEX_KEY, because they sort after the former type and none
exist in the first leaf.
We also log 3 items that represent ranges for dir items and dir
indexes for which the log is authoritative:
1) a key of type BTRFS_DIR_LOG_ITEM_KEY, which indicates the log is
authoritative for all BTRFS_DIR_ITEM_KEY keys that have an offset
in the range [0, 2285968570] (the offset here is th
---truncated---