From 4358dcf4e2112c37f4147f9a7e5771f0d7799110 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 9 Nov 2020 12:49:32 -0800 Subject: [PATCH] ANDROID: ext4: fix encrypt+casefold support When syncing ext4 with upstream commit f8f4acb6cded ("ext4: use generic casefolding support"), we forgot to take into account that some additional checks for the encryption key are needed for the encrypt+casefold support which isn't upstream yet. (These checks for the encryption key are still racy since they happen too late, but apparently they worked well enough...) This bug made it impossible to delete encrypted+casefolded directories without the encryption key, due to errors like: W : EXT4-fs warning (device vdc): __ext4fs_dirhash:270: inode #49202: comm Binder:378_4: Siphash requires key Fixes: 76bfcb2dc2f3 ("ANDROID: sync generic casefolding code with patches going upstream") Bug: 161184936 Bug: 172809853 Test: in kvm-xfstests test appliance: mkfs.ext4 -F -E encoding=utf8 -O encrypt /dev/vdc mount /vdc mkdir /vdc/dir chattr +F /vdc/dir keyid=$(head -c 64 /dev/zero | xfs_io -c add_enckey /vdc | awk '{print $NF}') xfs_io -c "set_encpolicy $keyid" /vdc/dir for i in `seq 1 100`; do mkdir /vdc/dir/$i done xfs_io -c "rm_enckey $keyid" /vdc rm -rf /vdc/dir # fails with the bug Change-Id: I67fbc9e34778519b229835e1d1b784bd42006ce7 Signed-off-by: Eric Biggers --- fs/ext4/hash.c | 3 ++- fs/ext4/namei.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c index 6b04bf2a6a9d..aeec7a2162e8 100644 --- a/fs/ext4/hash.c +++ b/fs/ext4/hash.c @@ -296,7 +296,8 @@ 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 && IS_CASEFOLDED(dir) && um && + (!IS_ENCRYPTED(dir) || fscrypt_has_encryption_key(dir))) { buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); if (!buff) return -ENOMEM; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 92479aa08b7a..5b85aa15882b 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1377,7 +1377,8 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, struct dx_hash_info *hinfo = &name->hinfo; int len; - if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding) { + if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding || + (IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir))) { cf_name->name = NULL; return 0; } @@ -1428,7 +1429,8 @@ static bool ext4_match(struct inode *parent, #endif #ifdef CONFIG_UNICODE - if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent)) { + if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent) && + (!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) { if (fname->cf_name.name) { struct qstr cf = {.name = fname->cf_name.name, .len = fname->cf_name.len};