A cross rename between two encrypted files, the disk level filenames aren't updated for the file_enc_name(to) checking.
Also, cross rename between encrypted file and non-encrypted file under a non-encrypted file, the enc name flags should update at same time as the disk level filename. This patch, 1. make sure update the disk level filename in update_dent_inode, 2. a new function exchange_dent_inode for the disk-level filename update, 3. only set the enc name flags in init_inode_metadata. Fixes: e7d5545285ed ("f2fs crypto: add filename encryption for roll-forward recovery") Signed-off-by: Kinglong Mee <kinglong...@gmail.com> --- fs/f2fs/dir.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- fs/f2fs/f2fs.h | 1 + fs/f2fs/inline.c | 2 -- fs/f2fs/namei.c | 19 ++---------- 4 files changed, 88 insertions(+), 25 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 295a223..b1bb0b1 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -337,17 +337,93 @@ static void init_dent_inode(const struct qstr *name, struct page *ipage) int update_dent_inode(struct inode *inode, struct inode *to, const struct qstr *name) { - struct page *page; + struct page *topage = NULL, *page; + struct f2fs_inode *tori; + struct qstr newname = *name; + int err = 0; - if (file_enc_name(to)) + if (file_enc_name(to) && (inode == to)) return 0; page = get_node_page(F2FS_I_SB(inode), inode->i_ino); if (IS_ERR(page)) return PTR_ERR(page); - init_dent_inode(name, page); + file_clear_enc_name(inode); + if (file_enc_name(to)) { + topage = get_node_page(F2FS_I_SB(to), to->i_ino); + if (IS_ERR(topage)) { + f2fs_put_page(page, 1); + return PTR_ERR(topage); + } + + tori = F2FS_INODE(topage); + newname.name = tori->i_name; + newname.len = tori->i_namelen; + + file_set_enc_name(inode); + } + + init_dent_inode(&newname, page); + f2fs_put_page(page, 1); + if (file_enc_name(to)) + f2fs_put_page(topage, 1); + + return err; +} + +int exchange_dent_inode(struct inode *src, struct inode *dst, + const struct qstr *srcname, const struct qstr *dstname) +{ + struct page *srcpage = NULL, *dstpage = NULL; + char tmp_srcname[F2FS_NAME_LEN], tmp_dstname[F2FS_NAME_LEN]; + struct qstr new_srcname = *srcname; + struct qstr new_dstname = *dstname; + + if (src == dst) + return 0; + + srcpage = get_node_page(F2FS_I_SB(src), src->i_ino); + if (IS_ERR(srcpage)) + return PTR_ERR(srcpage); + + dstpage = get_node_page(F2FS_I_SB(dst), dst->i_ino); + if (IS_ERR(dstpage)) { + f2fs_put_page(srcpage, 1); + return PTR_ERR(dstpage); + } + + f2fs_wait_on_page_writeback(srcpage, NODE, true); + f2fs_wait_on_page_writeback(dstpage, NODE, true); + + file_clear_enc_name(dst); + if (file_enc_name(src)) { + struct f2fs_inode *srcri = F2FS_INODE(srcpage); + + memcpy(tmp_srcname, srcri->i_name, srcri->i_namelen); + new_srcname.name = tmp_srcname; + new_srcname.len = srcri->i_namelen; + + file_set_enc_name(dst); + } + + file_clear_enc_name(src); + if (file_enc_name(dst)) { + struct f2fs_inode *dstri = F2FS_INODE(dstpage); + + memcpy(tmp_dstname, dstri->i_name, dstri->i_namelen); + new_dstname.name = tmp_dstname; + new_dstname.len = dstri->i_namelen; + + file_set_enc_name(src); + } + + init_dent_inode(&new_dstname, srcpage); + init_dent_inode(&new_srcname, dstpage); + + f2fs_put_page(srcpage, 1); + f2fs_put_page(dstpage, 1); return 0; } @@ -435,9 +511,14 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, set_cold_node(inode, page); } - if (new_name) + if (new_name) { init_dent_inode(new_name, page); + file_clear_enc_name(inode); + if (f2fs_encrypted_inode(dir)) + file_set_enc_name(inode); + } + /* * This file should be checkpointed during fsync. * We lost i_pino from now on. @@ -596,8 +677,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, err = PTR_ERR(page); goto fail; } - if (f2fs_encrypted_inode(dir)) - file_set_enc_name(inode); } make_dentry_ptr(NULL, &d, (void *)dentry_blk, 1); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7e29249..52ea953 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -440,6 +440,7 @@ struct f2fs_map_blocks { #define file_clear_encrypt(inode) clear_file(inode, FADVISE_ENCRYPT_BIT) #define file_enc_name(inode) is_file(inode, FADVISE_ENC_NAME_BIT) #define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT) +#define file_clear_enc_name(inode) clear_file(inode, FADVISE_ENC_NAME_BIT) #define file_keep_isize(inode) is_file(inode, FADVISE_KEEP_SIZE_BIT) #define file_set_keep_isize(inode) set_file(inode, FADVISE_KEEP_SIZE_BIT) diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index e32a9e5..41fe27d 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -527,8 +527,6 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, err = PTR_ERR(page); goto fail; } - if (f2fs_encrypted_inode(dir)) - file_set_enc_name(inode); } f2fs_wait_on_page_writeback(ipage, NODE, true); diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 3231a0a..57050ff 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -779,8 +779,6 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, down_write(&F2FS_I(old_inode)->i_sem); file_lost_pino(old_inode); - if (new_inode && file_enc_name(new_inode)) - file_set_enc_name(old_inode); up_write(&F2FS_I(old_inode)->i_sem); old_inode->i_ctime = current_time(old_inode); @@ -917,17 +915,10 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, f2fs_lock_op(sbi); - err = update_dent_inode(old_inode, new_inode, &new_dentry->d_name); + err = exchange_dent_inode(old_inode, new_inode, + &old_dentry->d_name, &new_dentry->d_name); if (err) goto out_unlock; - if (file_enc_name(new_inode)) - file_set_enc_name(old_inode); - - err = update_dent_inode(new_inode, old_inode, &old_dentry->d_name); - if (err) - goto out_undo; - if (file_enc_name(old_inode)) - file_set_enc_name(new_inode); /* update ".." directory entry info of old dentry */ if (old_dir_entry) @@ -972,12 +963,6 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) f2fs_sync_fs(sbi->sb, 1); return 0; -out_undo: - /* - * Still we may fail to recover name info of f2fs_inode here - * Drop it, once its name is set as encrypted - */ - update_dent_inode(old_inode, old_inode, &old_dentry->d_name); out_unlock: f2fs_unlock_op(sbi); out_new_dir: -- 2.9.3 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel