Commit 6e22c691 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs crypto: add filename encryption for f2fs_lookup

This patch implements filename encryption support for f2fs_lookup.

Note that, f2fs_find_entry should be outside of f2fs_(un)lock_op().
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent d8c6822a
...@@ -76,20 +76,10 @@ static unsigned long dir_block_index(unsigned int level, ...@@ -76,20 +76,10 @@ static unsigned long dir_block_index(unsigned int level,
return bidx; return bidx;
} }
static bool early_match_name(size_t namelen, f2fs_hash_t namehash,
struct f2fs_dir_entry *de)
{
if (le16_to_cpu(de->name_len) != namelen)
return false;
if (de->hash_code != namehash)
return false;
return true;
}
static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
struct qstr *name, int *max_slots, struct f2fs_filename *fname,
f2fs_hash_t namehash,
int *max_slots,
struct page **res_page) struct page **res_page)
{ {
struct f2fs_dentry_block *dentry_blk; struct f2fs_dentry_block *dentry_blk;
...@@ -99,8 +89,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, ...@@ -99,8 +89,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page); dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page);
make_dentry_ptr(NULL, &d, (void *)dentry_blk, 1); make_dentry_ptr(NULL, &d, (void *)dentry_blk, 1);
de = find_target_dentry(name, max_slots, &d); de = find_target_dentry(fname, namehash, max_slots, &d);
if (de) if (de)
*res_page = dentry_page; *res_page = dentry_page;
else else
...@@ -114,13 +103,15 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, ...@@ -114,13 +103,15 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
return de; return de;
} }
struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, struct f2fs_dir_entry *find_target_dentry(struct f2fs_filename *fname,
struct f2fs_dentry_ptr *d) f2fs_hash_t namehash, int *max_slots,
struct f2fs_dentry_ptr *d)
{ {
struct f2fs_dir_entry *de; struct f2fs_dir_entry *de;
unsigned long bit_pos = 0; unsigned long bit_pos = 0;
f2fs_hash_t namehash = f2fs_dentry_hash(name);
int max_len = 0; int max_len = 0;
struct f2fs_str de_name = FSTR_INIT(NULL, 0);
struct f2fs_str *name = &fname->disk_name;
if (max_slots) if (max_slots)
*max_slots = 0; *max_slots = 0;
...@@ -132,8 +123,18 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, ...@@ -132,8 +123,18 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots,
} }
de = &d->dentry[bit_pos]; de = &d->dentry[bit_pos];
if (early_match_name(name->len, namehash, de) &&
!memcmp(d->filename[bit_pos], name->name, name->len)) /* encrypted case */
de_name.name = d->filename[bit_pos];
de_name.len = le16_to_cpu(de->name_len);
/* show encrypted name */
if (fname->hash) {
if (de->hash_code == fname->hash)
goto found;
} else if (de_name.len == name->len &&
de->hash_code == namehash &&
!memcmp(de_name.name, name->name, name->len))
goto found; goto found;
if (max_slots && max_len > *max_slots) if (max_slots && max_len > *max_slots)
...@@ -155,16 +156,21 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, ...@@ -155,16 +156,21 @@ struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots,
} }
static struct f2fs_dir_entry *find_in_level(struct inode *dir, static struct f2fs_dir_entry *find_in_level(struct inode *dir,
unsigned int level, struct qstr *name, unsigned int level,
f2fs_hash_t namehash, struct page **res_page) struct f2fs_filename *fname,
struct page **res_page)
{ {
int s = GET_DENTRY_SLOTS(name->len); struct qstr name = FSTR_TO_QSTR(&fname->disk_name);
int s = GET_DENTRY_SLOTS(name.len);
unsigned int nbucket, nblock; unsigned int nbucket, nblock;
unsigned int bidx, end_block; unsigned int bidx, end_block;
struct page *dentry_page; struct page *dentry_page;
struct f2fs_dir_entry *de = NULL; struct f2fs_dir_entry *de = NULL;
bool room = false; bool room = false;
int max_slots; int max_slots;
f2fs_hash_t namehash;
namehash = f2fs_dentry_hash(&name);
f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH); f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);
...@@ -183,7 +189,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, ...@@ -183,7 +189,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
continue; continue;
} }
de = find_in_block(dentry_page, name, &max_slots, res_page); de = find_in_block(dentry_page, fname, namehash, &max_slots,
res_page);
if (de) if (de)
break; break;
...@@ -211,30 +218,34 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, ...@@ -211,30 +218,34 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
{ {
unsigned long npages = dir_blocks(dir); unsigned long npages = dir_blocks(dir);
struct f2fs_dir_entry *de = NULL; struct f2fs_dir_entry *de = NULL;
f2fs_hash_t name_hash;
unsigned int max_depth; unsigned int max_depth;
unsigned int level; unsigned int level;
struct f2fs_filename fname;
int err;
*res_page = NULL; *res_page = NULL;
if (f2fs_has_inline_dentry(dir)) err = f2fs_fname_setup_filename(dir, child, 1, &fname);
return find_in_inline_dir(dir, child, res_page); if (err)
return NULL;
if (f2fs_has_inline_dentry(dir)) {
de = find_in_inline_dir(dir, &fname, res_page);
goto out;
}
if (npages == 0) if (npages == 0)
return NULL; goto out;
name_hash = f2fs_dentry_hash(child);
max_depth = F2FS_I(dir)->i_current_depth; max_depth = F2FS_I(dir)->i_current_depth;
for (level = 0; level < max_depth; level++) { for (level = 0; level < max_depth; level++) {
de = find_in_level(dir, level, child, name_hash, res_page); de = find_in_level(dir, level, &fname, res_page);
if (de) if (de)
break; break;
} }
if (!de && F2FS_I(dir)->chash != name_hash) { out:
F2FS_I(dir)->chash = name_hash; f2fs_fname_free_filename(&fname);
F2FS_I(dir)->clevel = level - 1;
}
return de; return de;
} }
......
...@@ -1584,8 +1584,9 @@ struct dentry *f2fs_get_parent(struct dentry *child); ...@@ -1584,8 +1584,9 @@ struct dentry *f2fs_get_parent(struct dentry *child);
*/ */
extern unsigned char f2fs_filetype_table[F2FS_FT_MAX]; extern unsigned char f2fs_filetype_table[F2FS_FT_MAX];
void set_de_type(struct f2fs_dir_entry *, umode_t); void set_de_type(struct f2fs_dir_entry *, umode_t);
struct f2fs_dir_entry *find_target_dentry(struct qstr *, int *,
struct f2fs_dentry_ptr *); struct f2fs_dir_entry *find_target_dentry(struct f2fs_filename *,
f2fs_hash_t, int *, struct f2fs_dentry_ptr *);
bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *, bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
unsigned int, struct f2fs_str *); unsigned int, struct f2fs_str *);
void do_make_empty_dir(struct inode *, struct inode *, void do_make_empty_dir(struct inode *, struct inode *,
...@@ -1931,8 +1932,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *, struct page *); ...@@ -1931,8 +1932,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *, struct page *);
int f2fs_convert_inline_inode(struct inode *); int f2fs_convert_inline_inode(struct inode *);
int f2fs_write_inline_data(struct inode *, struct page *); int f2fs_write_inline_data(struct inode *, struct page *);
bool recover_inline_data(struct inode *, struct page *); bool recover_inline_data(struct inode *, struct page *);
struct f2fs_dir_entry *find_in_inline_dir(struct inode *, struct qstr *, struct f2fs_dir_entry *find_in_inline_dir(struct inode *,
struct page **); struct f2fs_filename *, struct page **);
struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *, struct page **); struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *, struct page **);
int make_empty_inline_dir(struct inode *inode, struct inode *, struct page *); int make_empty_inline_dir(struct inode *inode, struct inode *, struct page *);
int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *, int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
......
...@@ -284,23 +284,26 @@ bool recover_inline_data(struct inode *inode, struct page *npage) ...@@ -284,23 +284,26 @@ bool recover_inline_data(struct inode *inode, struct page *npage)
} }
struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
struct qstr *name, struct page **res_page) struct f2fs_filename *fname, struct page **res_page)
{ {
struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
struct f2fs_inline_dentry *inline_dentry; struct f2fs_inline_dentry *inline_dentry;
struct qstr name = FSTR_TO_QSTR(&fname->disk_name);
struct f2fs_dir_entry *de; struct f2fs_dir_entry *de;
struct f2fs_dentry_ptr d; struct f2fs_dentry_ptr d;
struct page *ipage; struct page *ipage;
f2fs_hash_t namehash;
ipage = get_node_page(sbi, dir->i_ino); ipage = get_node_page(sbi, dir->i_ino);
if (IS_ERR(ipage)) if (IS_ERR(ipage))
return NULL; return NULL;
namehash = f2fs_dentry_hash(&name);
inline_dentry = inline_data_addr(ipage); inline_dentry = inline_data_addr(ipage);
make_dentry_ptr(NULL, &d, (void *)inline_dentry, 2); make_dentry_ptr(NULL, &d, (void *)inline_dentry, 2);
de = find_target_dentry(name, NULL, &d); de = find_target_dentry(fname, namehash, NULL, &d);
unlock_page(ipage); unlock_page(ipage);
if (de) if (de)
*res_page = ipage; *res_page = ipage;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment