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 Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
20 Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
21 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
23 fs/ext4/inode.c | 8 ++++----
24 1 file changed, 4 insertions(+), 4 deletions(-)
26 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
27 index f7140ca..bb5aede 100644
30 @@ -4785,14 +4785,14 @@ static int ext4_do_update_inode(handle_t *handle,
31 * Fix up interoperability with old kernels. Otherwise, old inodes get
32 * re-used with the upper 16 bits of the uid/gid intact
35 + if (ei->i_dtime && list_empty(&ei->i_orphan)) {
36 + raw_inode->i_uid_high = 0;
37 + raw_inode->i_gid_high = 0;
39 raw_inode->i_uid_high =
40 cpu_to_le16(high_16_bits(i_uid));
41 raw_inode->i_gid_high =
42 cpu_to_le16(high_16_bits(i_gid));
44 - raw_inode->i_uid_high = 0;
45 - raw_inode->i_gid_high = 0;
48 raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid));