Patch "f2fs: check entire encrypted bigname when finding a dentry" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
f2fs: check entire encrypted bigname when finding a dentry
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
f2fs-check-entire-encrypted-bigname-when-finding-a-dentry.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
6332cd32c8290a80e929fc044dc5bdba77396e33Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim <[email protected]>
Date: Mon, 24 Apr 2017 10:00:08 -0700
Subject: f2fs: check entire encrypted bigname when finding a dentry
From: Jaegeuk Kim <[email protected]>
commit 6332cd32c8290a80e929fc044dc5bdba77396e33 upstream.
If user has no key under an encrypted dir, fscrypt gives digested dentries. Previously, when looking up a dentry, f2fs only checks its hash value with first 4 bytes of the digested dentry, which didn't handle hash collisions fully. This patch enhances to check entire dentry bytes likewise ext4.
Eric reported how to reproduce this issue by:
# seq -f "edir/abcdefghijklmnopqrstuvwxyz012345%.0f" 100000 | xargs touch # find edir -type f | xargs stat -c %i | sort | uniq | wc -l 100000 # sync # echo 3 > /proc/sys/vm/drop_caches # keyctl new_session # find edir -type f | xargs stat -c %i | sort | uniq | wc -l 99999
(fixed f2fs_dentry_hash() to work even when the hash is 0)
--- fs/f2fs/dir.c | 32 +++++++++++++++++++++----------- fs/f2fs/f2fs.h | 3 ++- fs/f2fs/hash.c | 7 ++++++- fs/f2fs/inline.c | 4 ++-- 4 files changed, 31 insertions(+), 15 deletions(-)
fs/f2fs/dir.c +21 -11
@@ -124,19 +124,29 @@ struct f2fs_dir_entry *find_target_dentr de = &d->dentry[bit_pos]; -/* encrypted case */ +if (de->hash_code != namehash) + goto not_match; + 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)) +#ifdef CONFIG_F2FS_FS_ENCRYPTION +if (unlikely (!name->name)) { +if (fname->usr_fname->name[0 ] =='_' ) { +if (de_name.len >=16 && + !memcmp (de_name.name + de_name.len -16 , + fname->crypto_buf.name +8 ,16 )) + goto found; + goto not_match; + } + name->name = fname->crypto_buf.name; + name->len = fname->crypto_buf.len; + } +#endif +if (de_name.len == name->len && + !memcmp (de_name.name, name->name, name->len)) goto found; - +not_match:if (max_slots && max_len > *max_slots) *max_slots = max_len; max_len =0 ;
@@ -170,7 +180,7 @@ static struct f2fs_dir_entry *find_in_leint max_slots;f2fs_hash_t namehash; - namehash =f2fs_dentry_hash (&name); + namehash =f2fs_dentry_hash (&name, fname);f2fs_bug_on (F2FS_I_SB (dir), level >MAX_DIR_HASH_DEPTH );
@@ -547,7 +557,7 @@ int __f2fs_add_link(struct inode *dir, c level =0 ; slots =GET_DENTRY_SLOTS (new_name.len); - dentry_hash =f2fs_dentry_hash (&new_name); + dentry_hash =f2fs_dentry_hash (&new_name,NULL ); current_depth =F2FS_I (dir)->i_current_depth;if (F2FS_I (dir)->chash == dentry_hash) {
fs/f2fs/f2fs.h +2 -1
@@ -1722,7 +1722,8 @@ void f2fs_msg(struct super_block *, cons/* * hash.c */ -f2fs_hash_t f2fs_dentry_hash (const struct qstr *); +f2fs_hash_t f2fs_dentry_hash (const struct qstr *name_info, +struct f2fs_filename *fname);/* * node.c
fs/f2fs/hash.c +6 -1
@@ -70,7 +70,8 @@ static void str2hashbuf(const unsigned c *buf++ = pad; } -f2fs_hash_t f2fs_dentry_hash (const struct qstr *name_info) +f2fs_hash_t f2fs_dentry_hash (const struct qstr *name_info, +struct f2fs_filename *fname) {__u32 hash;f2fs_hash_t f2fs_hash;
@@ -79,6 +80,10 @@ f2fs_hash_t f2fs_dentry_hash(const strucconst unsigned char *name = name_info->name;size_t len = name_info->len; +/* encrypted bigname case */ +if (fname && !fname->disk_name.name) +return cpu_to_le32 (fname->hash); +if (is_dot_dotdot (name_info))return 0 ;
fs/f2fs/inline.c +2 -2
@@ -303,7 +303,7 @@ struct f2fs_dir_entry *find_in_inline_diif (IS_ERR (ipage))return NULL ; - namehash =f2fs_dentry_hash (&name); + namehash =f2fs_dentry_hash (&name, fname); inline_dentry =inline_data_addr (ipage);
@@ -468,7 +468,7 @@ int f2fs_add_inline_entry(struct inode *f2fs_wait_on_page_writeback (ipage,NODE ); - name_hash =f2fs_dentry_hash (name); + name_hash =f2fs_dentry_hash (name,NULL );make_dentry_ptr (NULL , &d, (void *)dentry_blk,2 );f2fs_update_dentry (ino, mode, &d, name, name_hash, bit_pos);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/f2fs-check-entire-encrypted-bigname-when-finding-a-dentry.patch