lkml.org 
[lkml]   [2017]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 036/306] ext4: reinforce check of i_dtime when clearing high fields of uid and gid
    3.16.40-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Daeho Jeong <daeho.jeong@samsung.com>

    commit 93e3b4e6631d2a74a8cf7429138096862ff9f452 upstream.

    Now, ext4_do_update_inode() clears high 16-bit fields of uid/gid
    of deleted and evicted inode to fix up interoperability with old
    kernels. However, it checks only i_dtime of an inode to determine
    whether the inode was deleted and evicted, and this is very risky,
    because i_dtime can be used for the pointer maintaining orphan inode
    list, too. We need to further check whether the i_dtime is being
    used for the orphan inode list even if the i_dtime is not NULL.

    We found that high 16-bit fields of uid/gid of inode are unintentionally
    and permanently cleared when the inode truncation is just triggered,
    but not finished, and the inode metadata, whose high uid/gid bits are
    cleared, is written on disk, and the sudden power-off follows that
    in order.

    Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
    Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
    Signed-off-by: Theodore Ts'o <tytso@mit.edu>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    fs/ext4/inode.c | 8 ++++----
    1 file changed, 4 insertions(+), 4 deletions(-)

    --- a/fs/ext4/inode.c
    +++ b/fs/ext4/inode.c
    @@ -4422,14 +4422,14 @@ static int ext4_do_update_inode(handle_t
    * Fix up interoperability with old kernels. Otherwise, old inodes get
    * re-used with the upper 16 bits of the uid/gid intact
    */
    - if (!ei->i_dtime) {
    + if (ei->i_dtime && list_empty(&ei->i_orphan)) {
    + raw_inode->i_uid_high = 0;
    + raw_inode->i_gid_high = 0;
    + } else {
    raw_inode->i_uid_high =
    cpu_to_le16(high_16_bits(i_uid));
    raw_inode->i_gid_high =
    cpu_to_le16(high_16_bits(i_gid));
    - } else {
    - raw_inode->i_uid_high = 0;
    - raw_inode->i_gid_high = 0;
    }
    } else {
    raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid));
    \
     
     \ /
      Last update: 2017-02-16 01:00    [W:2.235 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site