1 ext4: reinforce check of i_dtime when clearing high fields of uid and gid
3 From: Daeho Jeong <daeho.jeong@samsung.com>
5 Now, ext4_do_update_inode() clears high 16-bit fields of uid/gid
6 of deleted and evicted inode to fix up interoperability with old
7 kernels. However, it checks only i_dtime of an inode to determine
8 whether the inode was deleted and evicted, and this is very risky,
9 because i_dtime can be used for the pointer maintaining orphan inode
10 list, too. We need to further check whether the i_dtime is being
11 used for the orphan inode list even if the i_dtime is not NULL.
13 We found that high 16-bit fields of uid/gid of inode are unintentionally
14 and permanently cleared when the inode truncation is just triggered,
15 but not finished, and the inode metadata, whose high uid/gid bits are
16 cleared, is written on disk, and the sudden power-off follows that
19 Cc: stable@vger.kernel.org
20 Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
21 Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
22 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
24 fs/ext4/inode.c | 8 ++++----
25 1 file changed, 4 insertions(+), 4 deletions(-)
27 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
28 index f7140ca..bb5aede 100644
31 @@ -4785,14 +4785,14 @@ static int ext4_do_update_inode(handle_t *handle,
32 * Fix up interoperability with old kernels. Otherwise, old inodes get
33 * re-used with the upper 16 bits of the uid/gid intact
36 + if (ei->i_dtime && list_empty(&ei->i_orphan)) {
37 + raw_inode->i_uid_high = 0;
38 + raw_inode->i_gid_high = 0;
40 raw_inode->i_uid_high =
41 cpu_to_le16(high_16_bits(i_uid));
42 raw_inode->i_gid_high =
43 cpu_to_le16(high_16_bits(i_gid));
45 - raw_inode->i_uid_high = 0;
46 - raw_inode->i_gid_high = 0;
49 raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid));