From d24f1bb16d6b4e48c8317700021fa037c482054c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 28 Apr 2015 14:27:18 -0700 Subject: [PATCH] fsck.f2fs: add hash conversion for encrypted dentries If dentry is encrypted, we should convert its hash value. Signed-off-by: Jaegeuk Kim --- fsck/fsck.c | 91 ++++++++++++++++++++++++++++++++++++++++--------------- fsck/fsck.h | 7 +++-- include/f2fs_fs.h | 9 ++++++ 3 files changed, 80 insertions(+), 27 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index f3fbdfa..b15edbe 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -583,7 +583,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, ret = fsck_chk_data_blk(sbi, le32_to_cpu(node_blk->i.i_addr[idx]), &child, (i_blocks == *blk_cnt), - ftype, nid, idx, ni->version); + ftype, nid, idx, ni->version, + file_is_encrypt(node_blk->i.i_advise)); if (!ret) { *blk_cnt = *blk_cnt + 1; } else if (config.fix_on) { @@ -695,7 +696,8 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, ret = fsck_chk_data_blk(sbi, le32_to_cpu(node_blk->dn.addr[idx]), child, le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype, - nid, idx, ni->version); + nid, idx, ni->version, + file_is_encrypt(inode->i_advise)); if (!ret) { *blk_cnt = *blk_cnt + 1; } else if (config.fix_on) { @@ -753,16 +755,37 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, return 0; } +static void convert_encrypted_name(unsigned char *name, int len, + unsigned char *new, int encrypted) +{ + if (!encrypted) { + memcpy(new, name, len); + new[len] = 0; + return; + } + + while (len--) { + *new = *name++; + if (*new > 128) + *new -= 128; + if (*new < 32 || *new == 0x7f) + *new ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ + new++; + } + *new = 0; +} + static void print_dentry(__u32 depth, __u8 *name, unsigned long *bitmap, struct f2fs_dir_entry *dentry, - int max, int idx, int last_blk) + int max, int idx, int last_blk, int encrypted) { int last_de = 0; int next_idx = 0; int name_len; unsigned int i; int bit_offset; + unsigned char new[F2FS_NAME_LEN + 1]; if (config.dbg_lv != -1) return; @@ -787,25 +810,49 @@ static void print_dentry(__u32 depth, __u8 *name, if (tree_mark[depth - 1] == '`') tree_mark[depth - 1] = ' '; - for (i = 1; i < depth; i++) printf("%c ", tree_mark[i]); - printf("%c-- %s 0x%x\n", last_de ? '`' : '|', - name, le32_to_cpu(dentry[idx].ino)); + + convert_encrypted_name(name, name_len, new, encrypted); + + printf("%c-- %s , \n", + last_de ? '`' : '|', + new, le32_to_cpu(dentry[idx].ino), + encrypted); +} + +static int f2fs_check_hash_code(struct f2fs_dir_entry *dentry, + const unsigned char *name, u32 len, int encrypted) +{ + f2fs_hash_t hash_code = f2fs_dentry_hash(name, len); + + /* fix hash_code made by old buggy code */ + if (dentry->hash_code != hash_code) { + unsigned char new[F2FS_NAME_LEN + 1]; + + convert_encrypted_name((unsigned char *)name, len, + new, encrypted); + FIX_MSG("Mismatch hash_code for \"%s\" [%x:%x]", + new, le32_to_cpu(dentry->hash_code), + hash_code); + dentry->hash_code = cpu_to_le32(hash_code); + return 1; + } + return 0; } static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child, unsigned long *bitmap, struct f2fs_dir_entry *dentry, __u8 (*filenames)[F2FS_SLOT_LEN], - int max, int last_blk) + int max, int last_blk, int encrypted) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); enum FILE_TYPE ftype; int dentries = 0; u32 blk_cnt; u8 *name; - u32 hash_code, ino; + u32 ino; u16 name_len;; int ret = 0; int fixed = 0; @@ -875,20 +922,10 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child, i++; continue; } - name = calloc(name_len + 1, 1); memcpy(name, filenames[i], name_len); - hash_code = f2fs_dentry_hash((const unsigned char *)name, - name_len); slots = (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; - /* fix hash_code made by old buggy code */ - if (le32_to_cpu(dentry[i].hash_code) != hash_code) { - dentry[i].hash_code = hash_code; - fixed = 1; - FIX_MSG("hash_code[%d] of %s", i, name); - } - /* Becareful. 'dentry.file_type' is not imode. */ if (ftype == F2FS_FT_DIR) { if ((name[0] == '.' && name_len == 1) || @@ -901,13 +938,16 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child, } } + if (f2fs_check_hash_code(dentry + i, name, name_len, encrypted)) + fixed = 1; + DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", fsck->dentry_depth, i, name, name_len, le32_to_cpu(dentry[i].ino), dentry[i].file_type); print_dentry(fsck->dentry_depth, name, bitmap, - dentry, max, i, last_blk); + dentry, max, i, last_blk, encrypted); blk_cnt = 1; ret = fsck_chk_node_blk(sbi, @@ -951,7 +991,8 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi, dentries = __chk_dentries(sbi, child, (unsigned long *)de_blk->dentry_bitmap, de_blk->dentry, de_blk->filename, - NR_INLINE_DENTRY, 1); + NR_INLINE_DENTRY, 1, + file_is_encrypt(node_blk->i.i_advise)); if (dentries < 0) { DBG(1, "[%3d] Inline Dentry Block Fixed hash_codes\n\n", fsck->dentry_depth); @@ -966,7 +1007,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi, } int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, - struct child_info *child, int last_blk) + struct child_info *child, int last_blk, int encrypted) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); struct f2fs_dentry_block *de_blk; @@ -982,7 +1023,7 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, dentries = __chk_dentries(sbi, child, (unsigned long *)de_blk->dentry_bitmap, de_blk->dentry, de_blk->filename, - NR_DENTRY_IN_BLOCK, last_blk); + NR_DENTRY_IN_BLOCK, last_blk, encrypted); if (dentries < 0) { ret = dev_write_block(de_blk, blk_addr); @@ -1002,7 +1043,8 @@ int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, u32 blk_addr, int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, struct child_info *child, int last_blk, - enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver) + enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver, + int encrypted) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); @@ -1035,7 +1077,8 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, if (ftype == F2FS_FT_DIR) { f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_HOT_DATA); - return fsck_chk_dentry_blk(sbi, blk_addr, child, last_blk); + return fsck_chk_dentry_blk(sbi, blk_addr, child, + last_blk, encrypted); } else { f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_WARM_DATA); } diff --git a/fsck/fsck.h b/fsck/fsck.h index 5eac45c..37a25ba 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -87,7 +87,8 @@ enum seg_type { extern void fsck_chk_orphan_node(struct f2fs_sb_info *); extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, - u8 *, enum FILE_TYPE, enum NODE_TYPE, u32 *, struct child_info *); + u8 *, enum FILE_TYPE, enum NODE_TYPE, u32 *, + struct child_info *); extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE, struct f2fs_node *, u32 *, struct node_info *); extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, @@ -98,9 +99,9 @@ extern int fsck_chk_idnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, extern int fsck_chk_didnode_blk(struct f2fs_sb_info *, struct f2fs_inode *, enum FILE_TYPE, struct f2fs_node *, u32 *, struct child_info *); extern int fsck_chk_data_blk(struct f2fs_sb_info *sbi, u32, struct child_info *, - int, enum FILE_TYPE, u32, u16, u8); + int, enum FILE_TYPE, u32, u16, u8, int); extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, u32, struct child_info *, - int); + int, int); int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *, struct child_info *); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 6aefa5d..59cc0d1 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -453,6 +453,15 @@ struct f2fs_extent { #define DEF_DIR_LEVEL 0 +/* + * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. + */ +#define FADVISE_COLD_BIT 0x01 +#define FADVISE_LOST_PINO_BIT 0x02 +#define FADVISE_ENCRYPT_BIT 0x04 + +#define file_is_encrypt(i_advise) ((i_advise) & FADVISE_ENCRYPT_BIT) + struct f2fs_inode { __le16 i_mode; /* file mode */ __u8 i_advise; /* file hints */ -- 2.7.4