Support for Casefolding and Encryption
Subsystems (5)
v2 cover Support for Casefolding and Encryption
Ext4 and F2FS currently both support casefolding and encryption, but not at the same time. These patches aim to rectify that.
Since directory names are stored case preserved, we cannot just take the hash of the ciphertext. Instead we use the siphash of the casefolded name. With this we no longer have a direct path from an encrypted name to the hash without the key. To deal with this, fscrypt now always includes the hash in the name it presents when the key is not present. There is a pre-existing bug where you can change parts of the hash and still match the name so long as the disruption to the hash does not happen to affect lookup on that filesystem. I'm not sure how to fix that without making ext4 lookups slower in the more common case.
I moved the identical dcache operations for ext4 and f2fs into the VFS, as any filesystem that uses casefolding will need the same code. This will also allow further optimizations to that path, although my current changes don't take advantage of that yet.
For Ext4, this also means that we need to store the hash on disk. We only do so for encrypted and casefolded directories to avoid on disk format changes. Previously encryption and casefolding could not live on the same filesystem, and we're relaxing that requirement. F2fs is a bit more straightforward since it already stores hashes on disk.
I've updated the related tools with just enough to enable the feature. I still need to adjust their respective fsck's, although without access to the keys, they won't be able to verify the hashes of casefolded and encrypted names.
changes:
fscrypt moved to separate thread to rebase on fscrypt dev branch addressed feedback, plus some minor fixes
Daniel Rosenberg (6):
TMP: fscrypt: Add support for casefolding with encryption
vfs: Fold casefolding into vfs
f2fs: Handle casefolding with Encryption
ext4: Use struct super_blocks' casefold data
ext4: Hande casefolding with encryption
ext4: Optimize match for casefolded encrypted dirs
Documentation/filesystems/ext4/directory.rst | 27 ++ fs/crypto/Kconfig | 1 + fs/crypto/fname.c | 234 ++++++++++--- fs/crypto/fscrypt_private.h | 9 + fs/crypto/keysetup.c | 32 +- fs/crypto/policy.c | 45 ++- fs/dcache.c | 28 ++ fs/ext4/dir.c | 75 +---- fs/ext4/ext4.h | 87 +++-- fs/ext4/hash.c | 26 +- fs/ext4/ialloc.c | 5 +- fs/ext4/inline.c | 41 ++- fs/ext4/namei.c | 326 ++++++++++++------- fs/ext4/super.c | 21 +- fs/f2fs/dir.c | 114 +++---- fs/f2fs/f2fs.h | 14 +- fs/f2fs/hash.c | 25 +- fs/f2fs/inline.c | 9 +- fs/f2fs/super.c | 17 +- fs/f2fs/sysfs.c | 8 +- fs/inode.c | 7 + fs/namei.c | 41 ++- include/linux/fs.h | 10 + include/linux/fscrypt.h | 96 ++---- include/linux/unicode.h | 14 + 25 files changed, 835 insertions(+), 477 deletions(-)
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 1/6 TMP: fscrypt: Add support for casefolding with encryption
This is a placeholder patch for the patches that were based on the fscypt dev patch. The only affect for the other patches is that they're missing a const or two that top of tree fscrypt would allow.
---
This patch is just a placeholder so the rest don't need to be applied to fscrypt's dev branch.
fs/crypto/Kconfig | 1 + fs/crypto/fname.c | 234 ++++++++++++++++++++++++++++-------- fs/crypto/fscrypt_private.h | 9 ++ fs/crypto/keysetup.c | 32 +++-- fs/crypto/policy.c | 45 ++++++- fs/inode.c | 7 ++ include/linux/fscrypt.h | 96 ++++----------- 7 files changed, 289 insertions(+), 135 deletions(-)
fs/crypto/Kconfig +1 -0
@@ -9,6 +9,7 @@ config FS_ENCRYPTION select CRYPTO_CTS select CRYPTO_SHA512 select CRYPTO_HMAC + select CRYPTO_SHA256 select KEYS help Enable encryption of files and directories. This
fs/crypto/fname.c +185 -49
303 lines not on this page · raw message
fs/crypto/fscrypt_private.h +9 -0
@@ -12,6 +12,7 @@#define _FSCRYPT_PRIVATE_H#include <linux/fscrypt.h> +#include <linux/siphash.h> #include <crypto/hash.h> #define CONST_STRLEN (str) (sizeof(str) - 1)
@@ -194,6 +195,13 @@ struct fscrypt_info {*/ struct fscrypt_direct_key *ci_direct_key; +/* +* With v2 policies, this can be used with siphash +* When the key has been set, ci_hash_key_initialized is set to true +*/ +siphash_key_t ci_hash_key; +bool ci_hash_key_initialized; +/* The encryption policy used by this inode */ union fscrypt_policy ci_policy;
@@ -286,6 +294,7 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,#define HKDF_CONTEXT_PER_FILE_KEY 2#define HKDF_CONTEXT_DIRECT_KEY 3#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 +#define HKDF_CONTEXT_FNAME_HASH_KEY 5 extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen,
fs/crypto/keysetup.c +23 -9
@@ -192,7 +192,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ci->ci_mode->friendly_name);return -EINVAL ; } -return setup_per_mode_key (ci, mk, mk->mk_direct_tfms, + err =setup_per_mode_key (ci, mk, mk->mk_direct_tfms,HKDF_CONTEXT_DIRECT_KEY , false); }else if (ci->ci_policy.v2.flags &FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 ) {
@@ -202,20 +202,34 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,* the IVs. This format is optimized for use with inline * encryption hardware compliant with the UFS or eMMC standards. */ -return setup_per_mode_key (ci, mk, mk->mk_iv_ino_lblk_64_tfms, + err =setup_per_mode_key (ci, mk, mk->mk_iv_ino_lblk_64_tfms,HKDF_CONTEXT_IV_INO_LBLK_64_KEY , true); + }else { + err =fscrypt_hkdf_expand (&mk->mk_secret.hkdf, +HKDF_CONTEXT_PER_FILE_KEY , + ci->ci_nonce, +FS_KEY_DERIVATION_NONCE_SIZE , + derived_key, ci->ci_mode->keysize); +if (err) +return err; + + err =fscrypt_set_derived_key (ci, derived_key); +memzero_explicit (derived_key, ci->ci_mode->keysize); } - - err =fscrypt_hkdf_expand (&mk->mk_secret.hkdf, -HKDF_CONTEXT_PER_FILE_KEY , - ci->ci_nonce,FS_KEY_DERIVATION_NONCE_SIZE , - derived_key, ci->ci_mode->keysize);if (err)return err; - err =fscrypt_set_derived_key (ci, derived_key); -memzero_explicit (derived_key, ci->ci_mode->keysize); +if (S_ISDIR (ci->ci_inode->i_mode)) { + err =fscrypt_hkdf_expand (&mk->mk_secret.hkdf, +HKDF_CONTEXT_FNAME_HASH_KEY , + ci->ci_nonce, +FS_KEY_DERIVATION_NONCE_SIZE , + (u8 *)&ci->ci_hash_key, +sizeof (ci->ci_hash_key)); +if (!err) + ci->ci_hash_key_initialized = true; + }return err; }
fs/crypto/policy.c +42 -3
60 lines not on this page · raw message
fs/inode.c +7 -0
@@ -20,6 +20,7 @@#include <linux/ratelimit.h> #include <linux/list_lru.h> #include <linux/iversion.h> +#include <linux/fscrypt.h> #include <trace/events/writeback.h> #include "internal.h"
@@ -2242,6 +2243,8 @@ EXPORT_SYMBOL(current_time);int vfs_ioc_setflags_prepare (struct inode *inode,unsigned int oldflags,unsigned int flags) { +int err; +/* * The IMMUTABLE and APPEND_ONLY flags can only be changed by * the relevant capability.
@@ -2252,6 +2255,10 @@ int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags, !capable(CAP_LINUX_IMMUTABLE))return -EPERM ; + err =fscrypt_ioc_setflags_prepare (inode, oldflags, flags); +if (err) +return err; +return 0 ; }EXPORT_SYMBOL (vfs_ioc_setflags_prepare);
include/linux/fscrypt.h +22 -74
133 lines not on this page · raw message
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 2/6 vfs: Fold casefolding into vfs
In reply to Daniel RosenbergExt4 and F2fs are both using casefolding, and they, along with any other filesystem that adds the feature, will be using identical dentry_ops. Additionally, those dentry ops interfere with the dentry_ops required for fscrypt once we add support for casefolding and encryption. Moving this into the vfs removes code duplication as well as the complication with encryption.
Currently this is pretty close to just moving the existing f2fs/ext4 code up a level into the vfs, although there is a lot of room for improvement now.
--- fs/dcache.c | 28 ++++++++++++++++++++++++++++ fs/namei.c | 41 ++++++++++++++++++++++++++++++++++++++--- include/linux/fs.h | 10 ++++++++++ include/linux/unicode.h | 14 ++++++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-)
fs/dcache.c +28 -0
@@ -32,6 +32,7 @@#include <linux/bit_spinlock.h> #include <linux/rculist_bl.h> #include <linux/list_lru.h> +#include <linux/unicode.h> #include "internal.h" #include "mount.h"
@@ -247,7 +248,19 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c* be no NUL in the ct/tcount data) */ const unsigned char *cs =READ_ONCE (dentry->d_name.name); +#ifdef CONFIG_UNICODE +struct inode *parent = dentry->d_parent->d_inode; +if (unlikely (needs_casefold (parent))) { +const struct qstr n1 =QSTR_INIT (cs, tcount); +const struct qstr n2 =QSTR_INIT (ct, tcount); +int result =utf8_strncasecmp (dentry->d_sb->s_encoding, + &n1, &n2); + +if (result >=0 ||sb_has_enc_strict_mode (dentry->d_sb)) +return result; + } +#endif return dentry_string_cmp (cs, ct, tcount); }
@@ -2406,7 +2419,22 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)* calculate the standard hash first, as the d_op->d_hash() * routine may choose to leave the hash value unchanged. */ +#ifdef CONFIG_UNICODE +unsigned char *hname =NULL ; +int hlen = name->len; + +if (IS_CASEFOLDED (dir->d_inode)) { + hname =kmalloc (PATH_MAX ,GFP_ATOMIC ); +if (!hname) +return ERR_PTR (-ENOMEM ); + hlen =utf8_casefold (dir->d_sb->s_encoding, + name, hname,PATH_MAX ); + } + name->hash =full_name_hash (dir, hname ?: name->name, hlen); +kfree (hname); +#else name->hash =full_name_hash (dir, name->name, name->len); +#endif if (dir->d_flags &DCACHE_OP_HASH ) {int err = dir->d_op->d_hash (dir, name);if (unlikely (err <0 ))
fs/namei.c +38 -3
68 lines not on this page · raw message
include/linux/fs.h +10 -0
@@ -1382,6 +1382,12 @@ extern int send_sigurg(struct fown_struct *fown);#define SB_ACTIVE (1<<30)#define SB_NOUSER (1<<31) +/* These flags relate to encoding and casefolding */ +#define SB_ENC_STRICT_MODE_FL (1 << 0) + +#define sb_has_enc_strict_mode (sb) \ + (sb->s_encoding_flags & SB_ENC_STRICT_MODE_FL) +/* * Umount options */
@@ -1449,6 +1455,10 @@ struct super_block {#endif #ifdef CONFIG_FS_VERITY const struct fsverity_operations *s_vop; +#endif +#ifdef CONFIG_UNICODE +struct unicode_map *s_encoding; +__u16 s_encoding_flags;#endif struct hlist_bl_head s_roots;/* alternate root dentries for NFS */ struct list_head s_mounts;/* list of mounts; _not_ for fs use */
include/linux/unicode.h +14 -0
@@ -4,6 +4,8 @@#include <linux/init.h> #include <linux/dcache.h> +#include <linux/fscrypt.h> +#include <linux/fs.h> struct unicode_map {const char *charset;
@@ -30,4 +32,16 @@ int utf8_casefold(const struct unicode_map *um, const struct qstr *str,struct unicode_map *utf8_load (const char *version);void utf8_unload (struct unicode_map *um); +#ifdef CONFIG_UNICODE +static inline bool needs_casefold (const struct inode *dir) +{ +return IS_CASEFOLDED (dir) && dir->i_sb->s_encoding && + (!IS_ENCRYPTED (dir) ||fscrypt_has_encryption_key (dir)); +} +#else +static inline bool needs_casefold (const struct inode *dir) +{ +return 0 ; +} +#endif #endif /* _LINUX_UNICODE_H */
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 3/6 f2fs: Handle casefolding with Encryption
In reply to Daniel RosenbergThis expands f2fs's casefolding support to include encrypted directories. For encrypted directories, we use the siphash of the casefolded name. This ensures there is no direct way to go from an unencrypted name to the stored hash on disk without knowledge of the encryption policy keys.
Additionally, we switch to using the vfs layer's casefolding support instead of storing this information inside of f2fs's private data.
---
After the fscrypt changes go in, f2fs_ci_compare can have parent made const again
fs/f2fs/dir.c | 114 ++++++++++++++++++----------------------------- fs/f2fs/f2fs.h | 14 +++--- fs/f2fs/hash.c | 25 +++++++---- fs/f2fs/inline.c | 9 ++-- fs/f2fs/super.c | 17 +++---- fs/f2fs/sysfs.c | 8 ++-- 6 files changed, 80 insertions(+), 107 deletions(-)
fs/f2fs/dir.c +44 -70
@@ -111,31 +111,50 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,* Returns: 0 if the directory entry matches, more than 0 if it * doesn't match or less than zero on error. */ -int f2fs_ci_compare (const struct inode *parent,const struct qstr *name, -const struct qstr *entry,bool quick) +int f2fs_ci_compare (struct inode *parent,const struct qstr *name, +unsigned char *name2,size_t len,bool quick) {const struct f2fs_sb_info *sbi =F2FS_SB (parent->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct unicode_map *um = sbi->sb->s_encoding; +const struct fscrypt_str crypt_entry =FSTR_INIT (name2, len); +struct fscrypt_str decrypted_entry; +struct qstr decrypted; +struct qstr entry =QSTR_INIT (name2, len);int ret; + decrypted_entry.name =NULL ; + +if (IS_ENCRYPTED (parent) &&fscrypt_has_encryption_key (parent)) { + decrypted_entry.name =kmalloc (len,GFP_ATOMIC ); + decrypted.name = decrypted_entry.name; + decrypted_entry.len = len; + decrypted.len = len; +if (!decrypted.name) +return -ENOMEM ; +fscrypt_fname_disk_to_usr (parent,0 ,0 , &crypt_entry, + &decrypted_entry); + } +if (quick) - ret =utf8_strncasecmp_folded (um, name, entry); + ret =utf8_strncasecmp_folded (um, name, decrypted_entry.name ? + &decrypted : &entry);else - ret =utf8_strncasecmp (um, name, entry); - + ret =utf8_strncasecmp (um, name, decrypted_entry.name ? + &decrypted : &entry);if (ret <0 ) {/* Handle invalid character sequence as either an error * or as an opaque byte sequence. */ -if (f2fs_has_strict_mode (sbi)) +if (sb_has_enc_strict_mode (sbi->sb))return -EINVAL ; -if (name->len != entry->len) +if (name->len != len)return 1 ; -return !!memcmp (name->name, entry->name, name->len); + ret = !!memcmp (name->name, + decrypted_entry.name ?: name2, name->len); } - +kfree (decrypted_entry.name);return ret; }
@@ -154,7 +173,7 @@ static void f2fs_fname_setup_ci_filename(struct inode *dir,if (!cf_name->name)return ; - cf_name->len =utf8_casefold (sbi->s_encoding, + cf_name->len =utf8_casefold (dir->i_sb->s_encoding, iname, cf_name->name,F2FS_NAME_LEN );if ((int )cf_name->len <=0 ) {
@@ -173,24 +192,24 @@ static inline bool f2fs_match_name(struct f2fs_dentry_ptr *d, {#ifdef CONFIG_UNICODE struct inode *parent = d->inode; -struct f2fs_sb_info *sbi =F2FS_I_SB (parent); -struct qstr entry; +unsigned char *name; +int len;#endif if (de->hash_code != namehash)return false;#ifdef CONFIG_UNICODE - entry.name = d->filename[bit_pos]; - entry.len = de->name_len; + name = d->filename[bit_pos]; + len = de->name_len; -if (sbi->s_encoding &&IS_CASEFOLDED (parent)) { +if (needs_casefold (parent)) {if (cf_str->name) {struct qstr cf = {.name = cf_str->name, .len = cf_str->len}; -return !f2fs_ci_compare (parent, &cf, &entry, true); +return !f2fs_ci_compare (parent, &cf, name, len, true); } -return !f2fs_ci_compare (parent, fname->usr_fname, &entry, +return !f2fs_ci_compare (parent, fname->usr_fname, name, len, false); }#endif
@@ -357,8 +376,8 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,int err;#ifdef CONFIG_UNICODE -if (f2fs_has_strict_mode (F2FS_I_SB (dir)) &&IS_CASEFOLDED (dir) && -utf8_validate (F2FS_I_SB (dir)->s_encoding, child)) { +if (sb_has_enc_strict_mode (dir->i_sb) &&IS_CASEFOLDED (dir) && +utf8_validate (dir->i_sb->s_encoding, child)) { *res_page =ERR_PTR (-EINVAL );return NULL ; }
@@ -602,13 +621,13 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,int f2fs_add_regular_entry (struct inode *dir,const struct qstr *new_name,const struct qstr *orig_name, +f2fs_hash_t dentry_hash,struct inode *inode,nid_t ino,umode_t mode) {unsigned int bit_pos;unsigned int level;unsigned int current_depth;unsigned long bidx, block; -f2fs_hash_t dentry_hash;unsigned int nbucket, nblock;struct page *dentry_page =NULL ;struct f2fs_dentry_block *dentry_blk =NULL ;
@@ -618,7 +637,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name, level =0 ; slots =GET_DENTRY_SLOTS (new_name->len); - dentry_hash =f2fs_dentry_hash (dir, new_name,NULL ); current_depth =F2FS_I (dir)->i_current_depth;if (F2FS_I (dir)->chash == dentry_hash) {
@@ -704,17 +722,19 @@ int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname, struct inode *inode, nid_t ino, umode_t mode) { struct qstr new_name; +f2fs_hash_t dentry_hash;int err = -EAGAIN ; new_name.name =fname_name (fname); new_name.len =fname_len (fname);if (f2fs_has_inline_dentry (dir)) - err =f2fs_add_inline_entry (dir, &new_name, fname->usr_fname, + err =f2fs_add_inline_entry (dir, &new_name, fname, inode, ino, mode); + dentry_hash =f2fs_dentry_hash (dir, &new_name, fname);if (err == -EAGAIN ) err =f2fs_add_regular_entry (dir, &new_name, fname->usr_fname, - inode, ino, mode); + dentry_hash, inode, ino, mode);f2fs_update_time (F2FS_I_SB (dir),REQ_TIME );return err;
@@ -1064,49 +1084,3 @@ const struct file_operations f2fs_dir_operations = {#endif }; -#ifdef CONFIG_UNICODE -static int f2fs_d_compare (const struct dentry *dentry,unsigned int len, -const char *str,const struct qstr *name) -{ -struct qstr qstr = {.name = str, .len = len }; - -if (!IS_CASEFOLDED (dentry->d_parent->d_inode)) { -if (len != name->len) -return -1 ; -return memcmp (str, name, len); - } - -return f2fs_ci_compare (dentry->d_parent->d_inode, name, &qstr, false); -} - -static int f2fs_d_hash (const struct dentry *dentry,struct qstr *str) -{ -struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb); -const struct unicode_map *um = sbi->s_encoding; -unsigned char *norm; -int len, ret =0 ; - -if (!IS_CASEFOLDED (dentry->d_inode)) -return 0 ; - - norm =f2fs_kmalloc (sbi,PATH_MAX ,GFP_ATOMIC ); -if (!norm) -return -ENOMEM ; - - len =utf8_casefold (um, str, norm,PATH_MAX ); -if (len <0 ) { -if (f2fs_has_strict_mode (sbi)) - ret = -EINVAL ; - goto out; - } - str->hash =full_name_hash (dentry, norm, len); -out: -kvfree (norm); -return ret; -} - -const struct dentry_operations f2fs_dentry_ops = { - .d_hash = f2fs_d_hash, - .d_compare = f2fs_d_compare, -}; -#endif
fs/f2fs/f2fs.h +5 -9
@@ -1184,10 +1184,6 @@ struct f2fs_sb_info {int valid_super_block;/* valid super block no */ unsigned long s_flag;/* flags for sbi */ struct mutex writepages;/* mutex for writepages() */ -#ifdef CONFIG_UNICODE -struct unicode_map *s_encoding; -__u16 s_encoding_flags; -#endif #ifdef CONFIG_BLK_DEV_ZONED unsigned int blocks_per_blkz;/* F2FS blocks per zone */
@@ -2969,9 +2965,9 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, bool hot, bool set);struct dentry *f2fs_get_parent (struct dentry *child); -extern int f2fs_ci_compare (const struct inode *parent, +extern int f2fs_ci_compare (struct inode *parent,const struct qstr *name, -const struct qstr *entry, +unsigned char *name2,size_t len,bool quick);/*
@@ -3005,7 +3001,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d, const struct qstr *name, f2fs_hash_t name_hash, unsigned int bit_pos);int f2fs_add_regular_entry (struct inode *dir,const struct qstr *new_name, -const struct qstr *orig_name, +const struct qstr *orig_name,f2fs_hash_t dentry_hash,struct inode *inode,nid_t ino,umode_t mode);int f2fs_add_dentry (struct inode *dir,struct fscrypt_name *fname,struct inode *inode,nid_t ino,umode_t mode);
@@ -3038,7 +3034,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);* hash.c */ f2fs_hash_t f2fs_dentry_hash (const struct inode *dir, -const struct qstr *name_info,struct fscrypt_name *fname); +const struct qstr *name_info,const struct fscrypt_name *fname);/* * node.c
@@ -3517,7 +3513,7 @@ struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,int f2fs_make_empty_inline_dir (struct inode *inode,struct inode *parent,struct page *ipage);int f2fs_add_inline_entry (struct inode *dir,const struct qstr *new_name, -const struct qstr *orig_name, +const struct fscrypt_name *fname,struct inode *inode,nid_t ino,umode_t mode); void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page, struct inode *dir,
fs/f2fs/hash.c +17 -8
@@ -68,8 +68,9 @@ static void str2hashbuf(const unsigned char *msg, size_t len, *buf++ = pad; } -static f2fs_hash_t __f2fs_dentry_hash (const struct qstr *name_info, -struct fscrypt_name *fname) +static f2fs_hash_t __f2fs_dentry_hash (const struct inode *dir, +const struct qstr *name_info, +const struct fscrypt_name *fname) {__u32 hash;f2fs_hash_t f2fs_hash;
@@ -85,6 +86,11 @@ static f2fs_hash_t __f2fs_dentry_hash(const struct qstr *name_info,if (is_dot_dotdot (name_info))return 0 ; +if (IS_CASEFOLDED (dir) &&IS_ENCRYPTED (dir)) { + f2fs_hash =fscrypt_fname_siphash (dir, name_info); +return f2fs_hash; + } +/* Initialize the default seed for the hash checksum functions */ buf[0 ] =0x67452301 ; buf[1 ] =0xefcdab89 ;
@@ -106,35 +112,38 @@ static f2fs_hash_t __f2fs_dentry_hash(const struct qstr *name_info, }f2fs_hash_t f2fs_dentry_hash (const struct inode *dir, -const struct qstr *name_info,struct fscrypt_name *fname) +const struct qstr *name_info,const struct fscrypt_name *fname) {#ifdef CONFIG_UNICODE struct f2fs_sb_info *sbi =F2FS_SB (dir->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct unicode_map *um = sbi->sb->s_encoding;int r, dlen;unsigned char *buff;struct qstr folded; +const struct qstr *name = fname ? fname->usr_fname : name_info;if (!name_info->len || !IS_CASEFOLDED (dir)) goto opaque_seq; +if (IS_ENCRYPTED (dir) && !fscrypt_has_encryption_key (dir)) + goto opaque_seq; + buff =f2fs_kzalloc (sbi,sizeof (char ) *PATH_MAX ,GFP_KERNEL );if (!buff)return -ENOMEM ; - - dlen =utf8_casefold (um, name_info, buff,PATH_MAX ); + dlen =utf8_casefold (um, name, buff,PATH_MAX );if (dlen <0 ) {kvfree (buff); goto opaque_seq; } folded.name = buff; folded.len = dlen; - r =__f2fs_dentry_hash (&folded, fname); + r =__f2fs_dentry_hash (dir, &folded, fname);kvfree (buff);return r; opaque_seq:#endif -return __f2fs_dentry_hash (name_info, fname); +return __f2fs_dentry_hash (dir, name_info, fname); }
fs/f2fs/inline.c +5 -4
@@ -465,8 +465,8 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry) ino =le32_to_cpu (de->ino); fake_mode =f2fs_get_de_type (de) <<S_SHIFT ; - err =f2fs_add_regular_entry (dir, &new_name,NULL ,NULL , - ino, fake_mode); + err =f2fs_add_regular_entry (dir, &new_name,NULL , + de->hash_code,NULL , ino, fake_mode);if (err) goto punch_dentry_pages;
@@ -540,7 +540,7 @@ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, }int f2fs_add_inline_entry (struct inode *dir,const struct qstr *new_name, -const struct qstr *orig_name, +const struct fscrypt_name *fname,struct inode *inode,nid_t ino,umode_t mode) {struct f2fs_sb_info *sbi =F2FS_I_SB (dir);
@@ -551,6 +551,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,struct f2fs_dentry_ptr d;int slots =GET_DENTRY_SLOTS (new_name->len);struct page *page =NULL ; +const struct qstr *orig_name = fname->usr_fname;int err =0 ; ipage =f2fs_get_node_page (sbi, dir->i_ino);
@@ -581,7 +582,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,f2fs_wait_on_page_writeback (ipage,NODE , true, true); - name_hash =f2fs_dentry_hash (dir, new_name,NULL ); + name_hash =f2fs_dentry_hash (dir, new_name, fname);f2fs_update_dentry (ino, mode, &d, new_name, name_hash, bit_pos);set_page_dirty (ipage);
fs/f2fs/super.c +5 -12
@@ -1144,7 +1144,7 @@ static void f2fs_put_super(struct super_block *sb)for (i =0 ; i <NR_PAGE_TYPE ; i++)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sbi->sb->s_encoding);#endif kvfree (sbi); }
@@ -3136,17 +3136,11 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)static int f2fs_setup_casefold (struct f2fs_sb_info *sbi) {#ifdef CONFIG_UNICODE -if (f2fs_sb_has_casefold (sbi) && !sbi->s_encoding) { +if (f2fs_sb_has_casefold (sbi) && !sbi->sb->s_encoding) {const struct f2fs_sb_encodings *encoding_info;struct unicode_map *encoding;__u16 encoding_flags; -if (f2fs_sb_has_encrypt (sbi)) { -f2fs_err (sbi, -"Can't mount with encoding and encryption" ); -return -EINVAL ; - } -if (f2fs_sb_read_encoding (sbi->raw_super, &encoding_info, &encoding_flags)) { f2fs_err(sbi,
@@ -3167,9 +3161,8 @@ static int f2fs_setup_casefold(struct f2fs_sb_info *sbi)"%s-%s with flags 0x%hx" , encoding_info->name, encoding_info->version?:"\b", encoding_flags); - sbi->s_encoding = encoding; - sbi->s_encoding_flags = encoding_flags; - sbi->sb->s_d_op = &f2fs_dentry_ops; + sbi->sb->s_encoding = encoding; + sbi->sb->s_encoding_flags = encoding_flags; }#else if (f2fs_sb_has_casefold (sbi)) {
@@ -3637,7 +3630,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)kvfree (sbi->write_io[i]);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sbi->sb->s_encoding);#endif free_options: #ifdef CONFIG_QUOTA
fs/f2fs/sysfs.c +4 -4
@@ -88,10 +88,10 @@ static ssize_t encoding_show(struct f2fs_attr *a,#ifdef CONFIG_UNICODE if (f2fs_sb_has_casefold (sbi))return snprintf (buf,PAGE_SIZE ,"%s (%d.%d.%d)\n" , - sbi->s_encoding->charset, - (sbi->s_encoding->version >>16 ) &0xff , - (sbi->s_encoding->version >>8 ) &0xff , - sbi->s_encoding->version &0xff ); + sbi->sb->s_encoding->charset, + (sbi->sb->s_encoding->version >>16 ) &0xff , + (sbi->sb->s_encoding->version >>8 ) &0xff , + sbi->sb->s_encoding->version &0xff );#endif return snprintf (buf,PAGE_SIZE ,"(none)" ); }
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 4/6 ext4: Use struct super_blocks' casefold data
In reply to Daniel RosenbergSwitch over to using the struct entries added to the VFS
--- fs/ext4/dir.c | 47 ----------------------------------------------- fs/ext4/ext4.h | 4 ---- fs/ext4/hash.c | 2 +- fs/ext4/namei.c | 20 ++++++++------------ fs/ext4/super.c | 15 +++++---------- 5 files changed, 14 insertions(+), 74 deletions(-)
fs/ext4/dir.c +0 -47
@@ -667,50 +667,3 @@ const struct file_operations ext4_dir_operations = { .release = ext4_release_dir, }; -#ifdef CONFIG_UNICODE -static int ext4_d_compare (const struct dentry *dentry,unsigned int len, -const char *str,const struct qstr *name) -{ -struct qstr qstr = {.name = str, .len = len }; -struct inode *inode = dentry->d_parent->d_inode; - -if (!IS_CASEFOLDED (inode) || !EXT4_SB (inode->i_sb)->s_encoding) { -if (len != name->len) -return -1 ; -return memcmp (str, name->name, len); - } - -return ext4_ci_compare (inode, name, &qstr, false); -} - -static int ext4_d_hash (const struct dentry *dentry,struct qstr *str) -{ -const struct ext4_sb_info *sbi =EXT4_SB (dentry->d_sb); -const struct unicode_map *um = sbi->s_encoding; -unsigned char *norm; -int len, ret =0 ; - -if (!IS_CASEFOLDED (dentry->d_inode) || !um) -return 0 ; - - norm =kmalloc (PATH_MAX ,GFP_ATOMIC ); -if (!norm) -return -ENOMEM ; - - len =utf8_casefold (um, str, norm,PATH_MAX ); -if (len <0 ) { -if (ext4_has_strict_mode (sbi)) - ret = -EINVAL ; - goto out; - } - str->hash =full_name_hash (dentry, norm, len); -out: -kfree (norm); -return ret; -} - -const struct dentry_operations ext4_dentry_ops = { - .d_hash = ext4_d_hash, - .d_compare = ext4_d_compare, -}; -#endif
fs/ext4/ext4.h +0 -4
@@ -1430,10 +1430,6 @@ struct ext4_sb_info {struct kobject s_kobj;struct completion s_kobj_unregister;struct super_block *s_sb; -#ifdef CONFIG_UNICODE -struct unicode_map *s_encoding; -__u16 s_encoding_flags; -#endif /* Journaling */ struct journal_s *s_journal;
fs/ext4/hash.c +1 -1
@@ -275,7 +275,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len, struct dx_hash_info *hinfo) {#ifdef CONFIG_UNICODE -const struct unicode_map *um =EXT4_SB (dir->i_sb)->s_encoding; +const struct unicode_map *um = dir->i_sb->s_encoding;int r, dlen;unsigned char *buff;struct qstr qstr = {.name = name, .len = len };
fs/ext4/namei.c +8 -12
@@ -1282,8 +1282,8 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)int ext4_ci_compare (const struct inode *parent,const struct qstr *name,const struct qstr *entry,bool quick) { -const struct ext4_sb_info *sbi =EXT4_SB (parent->i_sb); -const struct unicode_map *um = sbi->s_encoding; +const struct super_block *sb = parent->i_sb; +const struct unicode_map *um = sb->s_encoding;int ret;if (quick)
@@ -1295,7 +1295,7 @@ int ext4_ci_compare(const struct inode *parent, const struct qstr *name,/* Handle invalid character sequence as either an error * or as an opaque byte sequence. */ -if (ext4_has_strict_mode (sbi)) +if (sb_has_enc_strict_mode (sb))return -EINVAL ;if (name->len != entry->len)
@@ -1312,7 +1312,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, {int len; -if (!IS_CASEFOLDED (dir) || !EXT4_SB (dir->i_sb)->s_encoding) { +if (!needs_casefold (dir)) { cf_name->name =NULL ;return ; }
@@ -1321,7 +1321,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,if (!cf_name->name)return ; - len =utf8_casefold (EXT4_SB (dir->i_sb)->s_encoding, + len =utf8_casefold (dir->i_sb->s_encoding, iname, cf_name->name,EXT4_NAME_LEN );if (len <=0 ) {
@@ -1358,7 +1358,7 @@ static inline bool ext4_match(const struct inode *parent,#endif #ifdef CONFIG_UNICODE -if (EXT4_SB (parent->i_sb)->s_encoding &&IS_CASEFOLDED (parent)) { +if (needs_casefold (parent)) {if (fname->cf_name.name) {struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};
@@ -2164,9 +2164,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,struct buffer_head *bh =NULL ;struct ext4_dir_entry_2 *de;struct super_block *sb; -#ifdef CONFIG_UNICODE -struct ext4_sb_info *sbi; -#endif struct ext4_filename fname;int retval;int dx_fallback=0 ;
@@ -2183,9 +2180,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,return -EINVAL ;#ifdef CONFIG_UNICODE - sbi =EXT4_SB (sb); -if (ext4_has_strict_mode (sbi) &&IS_CASEFOLDED (dir) && - sbi->s_encoding &&utf8_validate (sbi->s_encoding, &dentry->d_name)) +if (sb_has_enc_strict_mode (sb) &&IS_CASEFOLDED (dir) && + sb->s_encoding &&utf8_validate (sb->s_encoding, &dentry->d_name))return -EINVAL ;#endif
fs/ext4/super.c +5 -10
@@ -1056,7 +1056,7 @@ static void ext4_put_super(struct super_block *sb)kfree (sbi->s_blockgroup_lock);fs_put_dax (sbi->s_daxdev);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif kfree (sbi); }
@@ -3850,7 +3850,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount;#ifdef CONFIG_UNICODE -if (ext4_has_feature_casefold (sb) && !sbi->s_encoding) { +if (ext4_has_feature_casefold (sb) && !sb->s_encoding) {const struct ext4_sb_encodings *encoding_info;struct unicode_map *encoding;__u16 encoding_flags;
@@ -3881,8 +3881,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)"%s-%s with flags 0x%hx" , encoding_info->name, encoding_info->version?:"\b", encoding_flags); - sbi->s_encoding = encoding; - sbi->s_encoding_flags = encoding_flags; + sb->s_encoding = encoding; + sb->s_encoding_flags = encoding_flags; }#endif
@@ -4497,11 +4497,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount4; } -#ifdef CONFIG_UNICODE -if (sbi->s_encoding) - sb->s_d_op = &ext4_dentry_ops; -#endif - sb->s_root =d_make_root (root);if (!sb->s_root) {ext4_msg (sb,KERN_ERR ,"get root dentry failed" );
@@ -4684,7 +4679,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)crypto_free_shash (sbi->s_chksum_driver);#ifdef CONFIG_UNICODE -utf8_unload (sbi->s_encoding); +utf8_unload (sb->s_encoding);#endif #ifdef CONFIG_QUOTA
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 5/6 ext4: Hande casefolding with encryption
In reply to Daniel RosenbergThis adds support for encryption with casefolding.
Since the name on disk is case preserving, and also encrypted, we can no longer just recompute the hash on the fly. Additionally, to avoid leaking extra information from the hash of the unencrypted name, we use siphash via an fscrypt v2 policy.
The hash is stored at the end of the directory entry for all entries inside of an encrypted and casefolded directory apart from those that deal with '.' and '..'. This way, the change is backwards compatible with existing ext4 filesystems.
---
After the fscrypt changes go in, ext4_ci_compare can have parent made const again
Documentation/filesystems/ext4/directory.rst | 27 ++ fs/ext4/dir.c | 28 +- fs/ext4/ext4.h | 66 ++++- fs/ext4/hash.c | 24 +- fs/ext4/ialloc.c | 5 +- fs/ext4/inline.c | 41 +-- fs/ext4/namei.c | 293 +++++++++++++------ fs/ext4/super.c | 6 - 8 files changed, 345 insertions(+), 145 deletions(-)
Documentation/filesystems/ext4/directory.rst +27 -0
@@ -121,6 +121,31 @@ The directory file type is one of the following values: * - 0x7 - Symbolic link. +To support directories that are both encrypted and casefolded directories, we +must also include hash information in the directory entry. We append +``ext4_extended_dir_entry_2`` to ``ext4_dir_entry_2`` except for the entries +for dot and dotdot, which are kept the same. The structure follows immediately +after ``name`` and is included in the size listed by ``rec_len`` If a directory +entry uses this extension, it may be up to 271 bytes. + +.. list-table:: + :widths: 8 8 24 40 + :header-rows: 1 + + * - Offset + - Size + - Name + - Description + * - 0x0 + - \_\_le32 + - hash + - The hash of the directory name + * - 0x4 + - \_\_le32 + - minor\_hash + - The minor hash of the directory name + + In order to add checksums to these classic directory blocks, a phony ``struct ext4_dir_entry`` is placed at the end of each leaf block to hold the checksum. The directory entry is 12 bytes long. The inode
@@ -322,6 +347,8 @@ The directory hash is one of the following values: - Half MD4, unsigned. * - 0x5 - Tea, unsigned. + * - 0x6 + - Siphash. Interior nodes of an htree are recorded as ``struct dx_node``, which is also the full length of a data block:
fs/ext4/dir.c +17 -11
@@ -26,10 +26,11 @@#include <linux/buffer_head.h> #include <linux/slab.h> #include <linux/iversion.h> -#include <linux/unicode.h> #include "ext4.h" #include "xattr.h" +#define DOTDOT_OFFSET 12 +static int ext4_dx_readdir (struct file *,struct dir_context *);/**
@@ -67,22 +68,26 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, struct inode *dir, struct file *filp, struct ext4_dir_entry_2 *de, struct buffer_head *bh, char *buf, int size, + ext4_lblk_t lblk, unsigned int offset) { const char *error_msg = NULL;const int rlen =ext4_rec_len_from_disk (de->rec_len, dir->i_sb->s_blocksize);const int next_offset = ((char *) de - buf) + rlen; +bool fake = (lblk ==0 ) && (offset <=DOTDOT_OFFSET ); -if (unlikely (rlen <EXT4_DIR_REC_LEN (1 ))) +if (unlikely (rlen <ext4_dir_rec_len (1 , fake ?NULL : dir))) error_msg ="rec_len is smaller than minimal" ;else if (unlikely (rlen %4 !=0 )) error_msg ="rec_len % 4 != 0" ; -else if (unlikely (rlen <EXT4_DIR_REC_LEN (de->name_len))) +else if (unlikely (rlen <ext4_dir_rec_len (de->name_len, + fake ?NULL : dir))) error_msg ="rec_len is too small for name_len" ;else if (unlikely (next_offset > size)) error_msg ="directory entry overrun" ; -else if (unlikely (next_offset > size -EXT4_DIR_REC_LEN (1 ) && +else if (unlikely (next_offset > size -ext4_dir_rec_len (1 , + fake ?NULL : dir) && next_offset != size)) error_msg ="directory entry too close to block end" ; else if (unlikely(le32_to_cpu(de->inode) >
@@ -94,15 +99,15 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,if (filp)ext4_error_file (filp, function, line, bh->b_blocknr,"bad entry in directory: %s - offset=%u, " -"inode=%u, rec_len=%d, name_len=%d, size=%d" , +"inode=%u, rec_len=%d, lblk=%d, size=%d" , error_msg, offset,le32_to_cpu (de->inode), - rlen, de->name_len, size); + rlen, lblk, size);else ext4_error_inode (dir, function, line, bh->b_blocknr,"bad entry in directory: %s - offset=%u, " -"inode=%u, rec_len=%d, name_len=%d, size=%d" , +"inode=%u, rec_len=%d, lblk=%d, size=%d" , error_msg, offset,le32_to_cpu (de->inode), - rlen, de->name_len, size); + rlen, lblk, size);return 1 ; }
@@ -224,7 +229,8 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)* failure will be detected in the * dirent test below. */ if (ext4_rec_len_from_disk (de->rec_len, - sb->s_blocksize) <EXT4_DIR_REC_LEN (1 )) + sb->s_blocksize) <ext4_dir_rec_len (1 , + inode))break ; i +=ext4_rec_len_from_disk (de->rec_len, sb->s_blocksize);
@@ -240,7 +246,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);if (ext4_check_dir_entry (inode, file, de, bh, bh->b_data, bh->b_size, - offset)) { + map.m_lblk, offset)) {/* * On error, skip to the next block */
@@ -642,7 +648,7 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf, top = buf + buf_size;while ((char *) de < top) {if (ext4_check_dir_entry (dir,NULL , de, bh, - buf, buf_size, offset)) + buf, buf_size,0 , offset))return -EFSCORRUPTED ; rlen =ext4_rec_len_from_disk (de->rec_len, buf_size); de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
fs/ext4/ext4.h +57 -9
134 lines not on this page · raw message
fs/ext4/hash.c +20 -4
@@ -197,7 +197,7 @@ static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)* represented, and whether or not the returned hash is 32 bits or 64 * bits. 32 bit hashes will return 0 for the minor hash. */ -static int __ext4fs_dirhash (const char *name,int len, +static int __ext4fs_dirhash (const struct inode *dir,const char *name,int len,struct dx_hash_info *hinfo) {__u32 hash;
@@ -259,6 +259,22 @@ static int __ext4fs_dirhash(const char *name, int len, hash = buf[0 ]; minor_hash = buf[1 ];break ; +case DX_HASH_SIPHASH : + { +struct qstr qname =QSTR_INIT (name, len); +__u64 combined_hash; + +if (fscrypt_has_encryption_key (dir)) { + combined_hash =fscrypt_fname_siphash (dir, &qname); + }else { +ext4_warning_inode (dir,"Siphash requires key" ); +return -1 ; + } + + hash = (__u32)(combined_hash >>32 ); + minor_hash = (__u32 )combined_hash; +break ; + }default : hinfo->hash =0 ;return -1 ;
@@ -280,7 +296,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,unsigned char *buff;struct qstr qstr = {.name = name, .len = len }; -if (len &&IS_CASEFOLDED (dir) && um) { +if (len &&needs_casefold (dir) && um) { buff =kzalloc (sizeof (char ) *PATH_MAX ,GFP_KERNEL );if (!buff)return -ENOMEM ;
@@ -291,12 +307,12 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len, goto opaque_seq; } - r =__ext4fs_dirhash (buff, dlen, hinfo); + r =__ext4fs_dirhash (dir, buff, dlen, hinfo);kfree (buff);return r; } opaque_seq: #endif -return __ext4fs_dirhash (name, len, hinfo); +return __ext4fs_dirhash (dir, name, len, hinfo); }
fs/ext4/ialloc.c +4 -1
@@ -448,7 +448,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,int ret =-1 ;if (qstr) { - hinfo.hash_version =DX_HASH_HALF_MD4 ; +if (ext4_hash_in_dirent (parent)) + hinfo.hash_version =DX_HASH_SIPHASH ; +else + hinfo.hash_version =DX_HASH_HALF_MD4 ; hinfo.seed = sbi->s_hash_seed;ext4fs_dirhash (parent, qstr->name, qstr->len, &hinfo); grp = hinfo.hash;
fs/ext4/inline.c +23 -18
130 lines not on this page · raw message
fs/ext4/namei.c +197 -96
808 lines not on this page · raw message
fs/ext4/super.c +0 -6
@@ -3855,12 +3855,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)struct unicode_map *encoding;__u16 encoding_flags; -if (ext4_has_feature_encrypt (sb)) { -ext4_msg (sb,KERN_ERR , -"Can't mount with encoding and encryption" ); - goto failed_mount; - } -if (ext4_sb_read_encoding (es, &encoding_info, &encoding_flags)) { ext4_msg(sb, KERN_ERR,
Signature · 1 line
2.24.1.735.g03f4e72817-goog
PATCH v2 6/6 ext4: Optimize match for casefolded encrypted dirs
In reply to Daniel RosenbergMatching names with casefolded encrypting directories requires decrypting entries to confirm case since we are case preserving. We can avoid needing to decrypt if our hash values don't match.
--- fs/ext4/ext4.h | 17 ++++++++------- fs/ext4/namei.c | 55 ++++++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 34 deletions(-)
fs/ext4/ext4.h +9 -8
@@ -2393,9 +2393,9 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb,ext4_fsblk_t ext4_inode_to_goal_block (struct inode *);#ifdef CONFIG_UNICODE -extern void ext4_fname_setup_ci_filename (struct inode *dir, +extern int ext4_fname_setup_ci_filename (struct inode *dir,const struct qstr *iname, -struct fscrypt_str *fname); +struct ext4_filename *fname);#endif #ifdef CONFIG_FS_ENCRYPTION
@@ -2426,9 +2426,9 @@ static inline int ext4_fname_setup_filename(struct inode *dir,ext4_fname_from_fscrypt_name (fname, &name);#ifdef CONFIG_UNICODE -ext4_fname_setup_ci_filename (dir, iname, &fname->cf_name); + err =ext4_fname_setup_ci_filename (dir, iname, fname);#endif -return 0 ; +return err; } static inline int ext4_fname_prepare_lookup(struct inode *dir,
@@ -2445,9 +2445,9 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir,ext4_fname_from_fscrypt_name (fname, &name);#ifdef CONFIG_UNICODE -ext4_fname_setup_ci_filename (dir, &dentry->d_name, &fname->cf_name); + err =ext4_fname_setup_ci_filename (dir, &dentry->d_name, fname);#endif -return 0 ; +return err; }static inline void ext4_fname_free_filename (struct ext4_filename *fname)
@@ -2472,15 +2472,16 @@ static inline int ext4_fname_setup_filename(struct inode *dir,int lookup, struct ext4_filename *fname) { + int err = 0; fname->usr_fname = iname; fname->disk_name.name = (unsigned char *) iname->name; fname->disk_name.len = iname->len;#ifdef CONFIG_UNICODE -ext4_fname_setup_ci_filename (dir, iname, &fname->cf_name); + err =ext4_fname_setup_ci_filename (dir, iname, fname);#endif -return 0 ; +return err; } static inline int ext4_fname_prepare_lookup(struct inode *dir,
fs/ext4/namei.c +29 -26
106 lines not on this page · raw message
Signature · 1 line
2.24.1.735.g03f4e72817-goog
Theodore Y. Ts'o
maintainerQuoted 3 lines · Daniel Rosenberg
changes:
fscrypt moved to separate thread to rebase on fscrypt dev branch addressed feedback, plus some minor fixes
What branch was this based on? There is no fscrypt dev branch, so I took the fscrypt master branch, and then applied your fscrypt patches, and then I tried to apply this patch series. I got patch conflicts starting with the very first patch.
Applying: TMP: fscrypt: Add support for casefolding with encryption
error: patch failed: fs/crypto/Kconfig:9
error: fs/crypto/Kconfig: patch does not apply
error: patch failed: fs/crypto/fname.c:12
error: fs/crypto/fname.c: patch does not apply
error: patch failed: fs/crypto/fscrypt_private.h:12
error: fs/crypto/fscrypt_private.h: patch does not apply
error: patch failed: fs/crypto/keysetup.c:192
error: fs/crypto/keysetup.c: patch does not apply
error: patch failed: fs/crypto/policy.c:67
error: fs/crypto/policy.c: patch does not apply
error: patch failed: fs/inode.c:20
error: fs/inode.c: patch does not apply
error: patch failed: include/linux/fscrypt.h:127
error: include/linux/fscrypt.h: patch does not apply
Patch failed at 0001 TMP: fscrypt: Add support for casefolding with encryption
hint: Use 'git am --show-current-patch' to see the failed patch When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
- Ted
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Quoted 32 lines · Theodore Y. Ts'o
Quoted 3 lines · Daniel Rosenberg
changes:
fscrypt moved to separate thread to rebase on fscrypt dev branch addressed feedback, plus some minor fixesWhat branch was this based on? There is no fscrypt dev branch, so I took the fscrypt master branch, and then applied your fscrypt patches, and then I tried to apply this patch series. I got patch conflicts starting with the very first patch.
Applying: TMP: fscrypt: Add support for casefolding with encryption
error: patch failed:fs/crypto/Kconfig:9
error:fs/crypto/Kconfig: patch does not apply
error: patch failed:fs/crypto/fname.c:12
error:fs/crypto/fname.c: patch does not apply
error: patch failed:fs/crypto/fscrypt_private.h:12
error:fs/crypto/fscrypt_private.h: patch does not apply
error: patch failed:fs/crypto/keysetup.c:192
error:fs/crypto/keysetup.c: patch does not apply
error: patch failed:fs/crypto/policy.c:67
error:fs/crypto/policy.c: patch does not apply
error: patch failed:fs/inode.c:20
error:fs/inode.c: patch does not apply
error: patch failed:include/linux/fscrypt.h:127
error:include/linux/fscrypt.h: patch does not apply
Patch failed at 0001 TMP: fscrypt: Add support for casefolding with encryption
hint: Use 'git am --show-current-patch' to see the failed patch When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Quoted 5 lines
- Ted
--
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
This is based off of ToT master. I put in a dummy fscrypt patch so you wouldn't need to rebase on top of fscrypt, but I could just do future patch sets all on top of fscrypt-dev. I guess my attempt to make it easier just made it more confusing :(