From b5286611c3438b406e8b42aabeaf8780d0a7b917 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 5 Sep 2014 21:42:23 -0400 Subject: [PATCH] Update to 9/5's version of the encryption patches from mhalcrow --- add-callback-support-for-bio-read-completion | 2 +- add-ext4-encryption-facilities | 16 +- add-ext4-encryption-read-callback-support | 78 ++++---- add-more-granular-errors-to-set-key-path | 209 +++++++++++++++++++++ crypto-debugging-sb-page-zero-check | 58 ++++++ crypto-trace-events | 153 +++++++++++++++ remove-extra-unlock-page | 25 +++ ...eval-failure-and-retry-crypto-after-interrupted | 44 +++++ series | 4 + timestamps | 33 ++-- 10 files changed, 568 insertions(+), 54 deletions(-) create mode 100644 add-more-granular-errors-to-set-key-path create mode 100644 crypto-debugging-sb-page-zero-check create mode 100644 crypto-trace-events create mode 100644 remove-extra-unlock-page create mode 100644 return-error-code-on-key-retrieval-failure-and-retry-crypto-after-interrupted diff --git a/add-callback-support-for-bio-read-completion b/add-callback-support-for-bio-read-completion index b65915ff..e0367d58 100644 --- a/add-callback-support-for-bio-read-completion +++ b/add-callback-support-for-bio-read-completion @@ -1,6 +1,6 @@ ext4: add callback support for bio read completion -From: Michael Halcrow +From: Make Halcrow Adds callback support for bio read completion. This supports data transformation such as encryption. diff --git a/add-ext4-encryption-facilities b/add-ext4-encryption-facilities index 4f1a69a7..b132509f 100644 --- a/add-ext4-encryption-facilities +++ b/add-ext4-encryption-facilities @@ -1,6 +1,6 @@ ext4: add EXT4 encryption facilities -From: Michael Halcrow +From: Mike Halcrow On encrypt, we will re-assign the buffer_heads to point to a bounce page rather than the control_page (which is the original page to write @@ -21,12 +21,12 @@ Signed-off-by: Michael Halcrow Signed-off-by: Theodore Ts'o --- fs/ext4/Makefile | 9 +- - fs/ext4/crypto.c | 1132 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/ext4/crypto.c | 1135 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4/ext4.h | 25 ++ fs/ext4/ext4_crypto.h | 175 ++++++++ fs/ext4/super.c | 38 +- fs/ext4/xattr.h | 1 + - 6 files changed, 1374 insertions(+), 6 deletions(-) + 6 files changed, 1377 insertions(+), 6 deletions(-) create mode 100644 fs/ext4/crypto.c create mode 100644 fs/ext4/ext4_crypto.h @@ -52,10 +52,10 @@ index 0310fec..de4de1c 100644 ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c new file mode 100644 -index 0000000..f81b804 +index 0000000..ead3111 --- /dev/null +++ b/fs/ext4/crypto.c -@@ -0,0 +1,1132 @@ +@@ -0,0 +1,1135 @@ +/* + * linux/fs/ext4/crypto.c + * @@ -687,7 +687,7 @@ index 0000000..f81b804 + } + BUG_ON(sig[EXT4_WRAPPING_KEY_SIG_NULL_TERMINATED_SIZE - 1] != '\0'); + res = ext4_get_wrapping_key_from_keyring(wrapping_key, sig); -+ return 0; ++ return res; +} + +/** @@ -1106,6 +1106,7 @@ index 0000000..f81b804 + struct ext4_inode_info *ei = EXT4_I(inode); + int res = 0; + ++try_again: + ext4_generate_encryption_key(dentry); + res = ext4_wrap_key(wrapped_key_packet, &wrapped_key_packet_size, + &ei->i_encryption_key, inode); @@ -1120,6 +1121,8 @@ index 0000000..f81b804 + root_packet, root_packet_size, 0); +out: + if (res) { ++ if (res == -EINTR) ++ goto try_again; + ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID; + printk_ratelimited(KERN_ERR "%s: res = [%d]\n", __func__, res); + } @@ -1549,3 +1552,4 @@ index 29bedf5..29d47c7 100644 -- 2.1.0.rc2.206.gedb03e5 + diff --git a/add-ext4-encryption-read-callback-support b/add-ext4-encryption-read-callback-support index ada4643a..5f6a7de1 100644 --- a/add-ext4-encryption-read-callback-support +++ b/add-ext4-encryption-read-callback-support @@ -1,8 +1,6 @@ ext4: add EXT4 encryption read callback support -From: Michael Halcrow - -Adds EXT4 encryption read callback support. +From: Mike Halcrow Copies block_read_full_page() to ext4_read_full_page() and adds some callback logic near the end. @@ -10,24 +8,30 @@ callback logic near the end. Signed-off-by: Michael Halcrow Signed-off-by: Theodore Ts'o --- - fs/ext4/file.c | 9 ++- - fs/ext4/inode.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++-- - include/linux/bio.h | 3 + - 3 files changed, 191 insertions(+), 6 deletions(-) + fs/ext4/file.c | 16 ++++++- + fs/ext4/inode.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + include/linux/bio.h | 3 ++ + 3 files changed, 199 insertions(+), 6 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 8695f70..c8bb4db 100644 +index aca7b24..6958f1a 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c -@@ -206,6 +206,7 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) - return -ENOEXEC; +@@ -200,8 +200,13 @@ static const struct vm_operations_struct ext4_file_vm_ops = { + + static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) + { ++ int res; ++ file_accessed(file); vma->vm_ops = &ext4_file_vm_ops; -+ ext4_get_crypto_key(file); ++ res = ext4_get_crypto_key(file); ++ if (res == -EACCES) /* If it's encrypted and we don't have the key */ ++ return res; return 0; } -@@ -216,6 +217,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) +@@ -212,6 +217,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) struct vfsmount *mnt = filp->f_path.mnt; struct path path; char buf[64], *cp; @@ -35,7 +39,7 @@ index 8695f70..c8bb4db 100644 if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) && !(sb->s_flags & MS_RDONLY))) { -@@ -254,11 +256,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp) +@@ -250,11 +256,17 @@ static int ext4_file_open(struct inode * inode, struct file * filp) * writing and the journal is present */ if (filp->f_mode & FMODE_WRITE) { @@ -46,26 +50,37 @@ index 8695f70..c8bb4db 100644 } - return dquot_file_open(inode, filp); + ret = dquot_file_open(inode, filp); -+ if (!ret) -+ ext4_get_crypto_key(filp); ++ if (!ret) { ++ ret = ext4_get_crypto_key(filp); ++ if (ret != -EACCES) ++ ret = 0; ++ } + return ret; } /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 42385c9..14585c5 100644 +index 3aedf18..bd7a7d5 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c -@@ -837,6 +837,8 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, - ext4_lblk_t block, int create, int *err) +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #include "ext4_jbd2.h" + #include "xattr.h" +@@ -784,6 +785,8 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, + ext4_lblk_t block, int create) { struct buffer_head *bh; + struct ext4_inode_info *ei = EXT4_I(inode); + struct ext4_crypto_ctx *ctx; - bh = ext4_getblk(handle, inode, block, create, err); - if (!bh) -@@ -845,8 +847,16 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, + bh = ext4_getblk(handle, inode, block, create); + if (IS_ERR(bh)) +@@ -792,8 +795,16 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, return bh; ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh); wait_on_buffer(bh); @@ -81,9 +96,9 @@ index 42385c9..14585c5 100644 return bh; + } put_bh(bh); - *err = -EIO; - return NULL; -@@ -2951,20 +2961,152 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) + return ERR_PTR(-EIO); + } +@@ -2799,20 +2810,152 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping, block, ext4_get_block); } @@ -238,7 +253,7 @@ index 42385c9..14585c5 100644 } static int -@@ -2972,12 +3114,35 @@ ext4_readpages(struct file *file, struct address_space *mapping, +@@ -2820,12 +2963,35 @@ ext4_readpages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { struct inode *inode = mapping->host; @@ -275,7 +290,7 @@ index 42385c9..14585c5 100644 } static void ext4_invalidatepage(struct page *page, unsigned int offset, -@@ -3236,9 +3401,13 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, +@@ -3084,9 +3250,13 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; @@ -289,7 +304,7 @@ index 42385c9..14585c5 100644 /* * If we are doing data journalling we don't support O_DIRECT */ -@@ -3361,8 +3530,10 @@ static int ext4_block_zero_page_range(handle_t *handle, +@@ -3209,8 +3379,10 @@ static int ext4_block_zero_page_range(handle_t *handle, unsigned blocksize, max, pos; ext4_lblk_t iblock; struct inode *inode = mapping->host; @@ -300,7 +315,7 @@ index 42385c9..14585c5 100644 int err = 0; page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT, -@@ -3418,6 +3589,12 @@ static int ext4_block_zero_page_range(handle_t *handle, +@@ -3266,6 +3438,12 @@ static int ext4_block_zero_page_range(handle_t *handle, /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) goto unlock; @@ -314,10 +329,10 @@ index 42385c9..14585c5 100644 if (ext4_should_journal_data(inode)) { BUFFER_TRACE(bh, "get write access"); diff --git a/include/linux/bio.h b/include/linux/bio.h -index d2633ee..6ec3bee 100644 +index b39e500..6b42e2a 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h -@@ -375,6 +375,9 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask) +@@ -376,6 +376,9 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask) } @@ -327,6 +342,3 @@ index d2633ee..6ec3bee 100644 extern void bio_endio(struct bio *, int); extern void bio_endio_nodec(struct bio *, int); struct request_queue; --- -2.1.0.rc2.206.gedb03e5 - diff --git a/add-more-granular-errors-to-set-key-path b/add-more-granular-errors-to-set-key-path new file mode 100644 index 00000000..204a48d5 --- /dev/null +++ b/add-more-granular-errors-to-set-key-path @@ -0,0 +1,209 @@ +ext4 crypto: adds more granular error messages to the set key path + +From: Michael Halcrow + +Signed-off-by: Michael Halcrow +Signed-off-by: Theodore Ts'o +--- + fs/ext4/crypto.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 67 insertions(+), 10 deletions(-) + +diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c +index 904974c..e892d68 100644 +--- a/fs/ext4/crypto.c ++++ b/fs/ext4/crypto.c +@@ -606,11 +606,18 @@ static int ext4_get_wrapping_key_from_keyring( + payload = (struct encrypted_key_payload *)create_key->payload.data; + if (WARN_ON_ONCE(create_key->datalen != + sizeof(struct ecryptfs_auth_tok))) { ++ printk(KERN_ERR ++ "%s: Got auth tok length [%d], expected [%ld]\n", ++ __func__, create_key->datalen, ++ sizeof(struct ecryptfs_auth_tok)); + return -EINVAL; + } + auth_tok = (struct ecryptfs_auth_tok *)(&(payload)->payload_data); + if (WARN_ON_ONCE(!(auth_tok->token.password.flags & + ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET))) { ++ printk(KERN_ERR ++ "%s: ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET not set in auth_tok->token.password.flags\n", ++ __func__); + return -EINVAL; + } + BUILD_BUG_ON(EXT4_MAX_KEY_SIZE < EXT4_AES_256_XTS_KEY_SIZE); +@@ -742,8 +749,11 @@ static int ext4_hmac(bool derivation, const char *key, size_t key_size, + int res = 0; + + BUG_ON(dst_size > SHA512_DIGEST_SIZE); +- if (IS_ERR(tfm)) ++ if (IS_ERR(tfm)) { ++ printk(KERN_ERR "%s: crypto_alloc_ahash() returned [%ld]\n", ++ __func__, PTR_ERR(tfm)); + return PTR_ERR(tfm); ++ } + req = ahash_request_alloc(tfm, GFP_NOFS); + if (!req) { + res = -ENOMEM; +@@ -755,8 +765,11 @@ static int ext4_hmac(bool derivation, const char *key, size_t key_size, + ext4_hmac_complete, &ehr); + + res = crypto_ahash_setkey(tfm, key, key_size); +- if (res) ++ if (res) { ++ printk(KERN_ERR "%s: crypto_ahash_setkey() returned [%d]\n", ++ __func__, res); + goto out; ++ } + sg_init_one(&sg, src, src_size); + ahash_request_set_crypt(req, &sg, hmac, src_size); + init_completion(&ehr.completion); +@@ -766,13 +779,18 @@ static int ext4_hmac(bool derivation, const char *key, size_t key_size, + wait_for_completion(&ehr.completion); + res = ehr.res; + } +- if (res) ++ if (res) { ++ printk(KERN_ERR "%s: crypto_ahash_digest() returned [%d]\n", ++ __func__, res); + goto out; ++ } + memcpy(dst, hmac, dst_size); + out: + crypto_free_ahash(tfm); + if (req) + ahash_request_free(req); ++ if (res) ++ printk(KERN_ERR "%s: returning [%d]\n", __func__, res); + return res; + } + +@@ -836,8 +854,11 @@ static int ext4_crypt_wrapper_virt(const char *enc_key, const char *iv, + int res = 0; + + desc.tfm = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR(desc.tfm)) ++ if (IS_ERR(desc.tfm)) { ++ printk(KERN_ERR "%s: crypto_alloc_blkcipher() returned [%ld]\n", ++ __func__, PTR_ERR(desc.tfm)); + return PTR_ERR(desc.tfm); ++ } + if (!desc.tfm) + return -ENOMEM; + crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); +@@ -846,12 +867,21 @@ static int ext4_crypt_wrapper_virt(const char *enc_key, const char *iv, + crypto_blkcipher_set_iv(desc.tfm, iv, EXT4_WRAPPING_IV_SIZE); + res = crypto_blkcipher_setkey(desc.tfm, enc_key, + EXT4_AES_256_CTR_KEY_SIZE); +- if (res) ++ if (res) { ++ printk(KERN_ERR ++ "%s: crypto_blkcipher_setkey() returned [%d]\n", ++ __func__, res); + goto out; ++ } + if (enc) + res = crypto_blkcipher_encrypt(&desc, &dst, &src, size); + else + res = crypto_blkcipher_decrypt(&desc, &dst, &src, size); ++ if (res) { ++ printk(KERN_ERR ++ "%s: crypto_blkcipher_*crypt() returned [%d]\n", ++ __func__, res); ++ } + out: + crypto_free_blkcipher(desc.tfm); + return res; +@@ -988,8 +1018,12 @@ static int ext4_wrap_key(char *wrapped_key_packet, size_t *key_packet_size, + return 0; + } + res = ext4_get_wrapping_key(wrapping_key, packet->sig, inode); +- if (res) ++ if (res) { ++ ext4_error(inode->i_sb, ++ "%s: ext4_get_wrapping_key() with packet->sig [%s] returned [%d]\n", ++ __func__, packet->sig, res); + return res; ++ } + BUG_ON(*key_packet_size != EXT4_FULL_WRAPPED_KEY_PACKET_V0_SIZE); + + /* Size, type, nonce, and IV */ +@@ -1005,8 +1039,12 @@ static int ext4_wrap_key(char *wrapped_key_packet, size_t *key_packet_size, + packet->nonce, + EXT4_DERIVATION_TWEAK_NONCE_SIZE, + enc_key, EXT4_AES_256_CTR_KEY_SIZE); +- if (res) ++ if (res) { ++ ext4_error(inode->i_sb, ++ "%s: ext4_hmac_derive_key() returned [%d]\n", ++ __func__, res); + goto out; ++ } + + /* Wrap the data key with the wrapping encryption key */ + *((uint32_t *)key_packet.mode) = htonl(key->mode); +@@ -1019,8 +1057,12 @@ static int ext4_wrap_key(char *wrapped_key_packet, size_t *key_packet_size, + EXT4_V0_SERIALIZED_KEY_SIZE, true); + memset(enc_key, 0, EXT4_AES_256_CTR_KEY_SIZE); + memset(key_packet.raw, 0, EXT4_MAX_KEY_SIZE); +- if (res) ++ if (res) { ++ ext4_error(inode->i_sb, ++ "%s: ext4_crypt_wrapper_virt() returned [%d]\n", ++ __func__, res); + goto out; ++ } + + /* Calculate the HMAC over the entire packet (except, of + * course, the HMAC buffer at the end) */ +@@ -1029,8 +1071,12 @@ static int ext4_wrap_key(char *wrapped_key_packet, size_t *key_packet_size, + packet->nonce, + EXT4_DERIVATION_TWEAK_NONCE_SIZE, + int_key, EXT4_HMAC_KEY_SIZE); +- if (res) ++ if (res) { ++ ext4_error(inode->i_sb, ++ "%s: ext4_hmac_derive_key() returned [%d]\n", ++ __func__, res); + goto out; ++ } + BUILD_BUG_ON(EXT4_FULL_WRAPPED_KEY_PACKET_V0_SIZE < EXT4_HMAC_SIZE); + res = ext4_hmac_integrity(int_key, EXT4_HMAC_KEY_SIZE, + wrapped_key_packet, +@@ -1041,6 +1087,8 @@ static int ext4_wrap_key(char *wrapped_key_packet, size_t *key_packet_size, + memset(int_key, 0, EXT4_HMAC_KEY_SIZE); + out: + memset(wrapping_key, 0, EXT4_AES_256_XTS_KEY_SIZE); ++ if (res) ++ ext4_error(inode->i_sb, "%s: returning [%d]\n", __func__, res); + return res; + } + +@@ -1084,8 +1132,12 @@ try_again: + ext4_generate_encryption_key(dentry); + res = ext4_wrap_key(wrapped_key_packet, &wrapped_key_packet_size, + &ei->i_encryption_key, inode); +- if (res) ++ if (res) { ++ ext4_error(dentry->d_inode->i_sb, ++ "%s: ext4_wrap_key() returned [%d]\n", __func__, ++ res); + goto out; ++ } + root_packet[0] = EXT4_PACKET_SET_VERSION_V0; + BUILD_BUG_ON(EXT4_PACKET_SET_V0_MAX_SIZE != + (EXT4_PACKET_HEADER_SIZE + +@@ -1093,6 +1145,11 @@ try_again: + BUG_ON(sizeof(root_packet) != root_packet_size); + res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION_METADATA, "", + root_packet, root_packet_size, 0); ++ if (res) { ++ ext4_error(dentry->d_inode->i_sb, ++ "%s: ext4_xattr_set() returned [%d]\n", __func__, ++ res); ++ } + out: + if (res) { + if (res == -EINTR) +-- +2.1.0.rc2.206.gedb03e5 + diff --git a/crypto-debugging-sb-page-zero-check b/crypto-debugging-sb-page-zero-check new file mode 100644 index 00000000..88bb3bbf --- /dev/null +++ b/crypto-debugging-sb-page-zero-check @@ -0,0 +1,58 @@ +ext4 crypto: Debugging: SB zero check and zero page check + +From: Michael Halcrow + +--- + fs/ext4/crypto.c | 14 ++++++++++++++ + fs/ext4/extents.c | 2 ++ + 2 files changed, 16 insertions(+) + +diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c +index ead3111..e16170f 100644 +--- a/fs/ext4/crypto.c ++++ b/fs/ext4/crypto.c +@@ -522,6 +522,19 @@ out: + return res; + } + ++bool __ext4_debug_is_page_zero(struct page *page) ++{ ++ char *page_virt = kmap(page); ++ int is_not_zero = 0; ++ int i; ++ ++ BUG_ON(!page_virt); ++ for (i = 0; i < PAGE_CACHE_SIZE; ++i) ++ is_not_zero |= page_virt[i]; ++ kunmap(page); ++ return !is_not_zero; ++} ++ + /** + * ext4_decrypt() - Decrypts a page in-place + * @ctx: The encryption context. +@@ -538,6 +551,7 @@ int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page) + int res = 0; + + BUG_ON(!PageLocked(page)); ++ BUG_ON(__ext4_debug_is_page_zero(page)); + switch (ctx->mode) { + case EXT4_ENCRYPTION_MODE_AES_256_XTS: + res = ext4_xts_decrypt(ctx, page); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 9ab757f..6c74a25 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3099,6 +3099,8 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) + ee_len = ext4_ext_get_actual_len(ex); + ee_pblock = ext4_ext_pblock(ex); + ++ printk_ratelimited(KERN_ERR "%s: Calling sb_issue_zeroout(ee_pblock = [%lld], ee_len = [%d])\n", __func__, ee_pblock, ee_len); ++ + ret = sb_issue_zeroout(inode->i_sb, ee_pblock, ee_len, GFP_NOFS); + if (ret > 0) + ret = 0; +-- +2.1.0.rc2.206.gedb03e5 + + diff --git a/crypto-trace-events b/crypto-trace-events new file mode 100644 index 00000000..3e11ba4b --- /dev/null +++ b/crypto-trace-events @@ -0,0 +1,153 @@ +ext4 crypto: trace events for encrypt and decrypt + +From: Michael Halcrow + +Signed-off-by: Michael Halcrow +Signed-off-by: Theodore Ts'o +--- + fs/ext4/crypto.c | 34 ++++++++++++++++++++++++++++++++- + include/trace/events/ext4.h | 46 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c +index e16170f..30cfaa9 100644 +--- a/fs/ext4/crypto.c ++++ b/fs/ext4/crypto.c +@@ -31,6 +31,8 @@ + #include "ext4.h" + #include "xattr.h" + ++#include ++ + /* Encryption added and removed here! (L: */ + + mempool_t *ext4_bounce_page_pool = NULL; +@@ -447,6 +449,13 @@ struct page *ext4_encrypt(struct ext4_crypto_ctx *ctx, + struct page *plaintext_page) + { + struct page *ciphertext_page = NULL; ++ char c0, c4095, p0, p4095; ++ char *page_virt; ++ ++ page_virt = kmap(plaintext_page); ++ p0 = page_virt[0]; ++ p4095 = page_virt[PAGE_CACHE_SIZE - 1]; ++ kunmap(plaintext_page); + + BUG_ON(!PageLocked(plaintext_page)); + switch (ctx->mode) { +@@ -464,8 +473,16 @@ struct page *ext4_encrypt(struct ext4_crypto_ctx *ctx, + default: + BUG(); + } +- if (!IS_ERR_OR_NULL(ciphertext_page)) ++ if (!IS_ERR_OR_NULL(ciphertext_page)) { + ext4_prep_pages_for_write(ciphertext_page, plaintext_page, ctx); ++ ++ page_virt = kmap(ciphertext_page); ++ c0 = page_virt[0]; ++ c4095 = page_virt[PAGE_CACHE_SIZE - 1]; ++ kunmap(ciphertext_page); ++ ++ trace_ext4_encrypt(plaintext_page, p0, p4095, c0, c4095); ++ } + return ciphertext_page; + } + +@@ -549,6 +566,13 @@ bool __ext4_debug_is_page_zero(struct page *page) + int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page) + { + int res = 0; ++ char c0, c4095, p0, p4095; ++ char *page_virt; ++ ++ page_virt = kmap(page); ++ c0 = page_virt[0]; ++ c4095 = page_virt[PAGE_CACHE_SIZE - 1]; ++ kunmap(page); + + BUG_ON(!PageLocked(page)); + BUG_ON(__ext4_debug_is_page_zero(page)); +@@ -564,6 +588,14 @@ int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page) + default: + BUG(); + } ++ ++ page_virt = kmap(page); ++ p0 = page_virt[0]; ++ p4095 = page_virt[PAGE_CACHE_SIZE - 1]; ++ kunmap(page); ++ ++ trace_ext4_decrypt(page, p0, p4095, c0, c4095); ++ + return res; + } + +diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h +index d4f70a7..91835b1 100644 +--- a/include/trace/events/ext4.h ++++ b/include/trace/events/ext4.h +@@ -494,6 +494,38 @@ DECLARE_EVENT_CLASS(ext4__page_op, + (unsigned long) __entry->index) + ); + ++DECLARE_EVENT_CLASS(ext4__page_crypt_op, ++ TP_PROTO(struct page *page, char p0, char p4095, char c0, char c4095), ++ ++ TP_ARGS(page, p0, p4095, c0, c4095), ++ ++ TP_STRUCT__entry( ++ __field( ino_t, ino ) ++ __field( pgoff_t, index ) ++ __field( char, p0 ) ++ __field( char, p4095 ) ++ __field( char, c0 ) ++ __field( char, c4095 ) ++ ), ++ ++ TP_fast_assign( ++ __entry->ino = page->mapping->host->i_ino; ++ __entry->index = page->index; ++ __entry->p0 = p0; ++ __entry->p4095 = p4095; ++ __entry->c0 = c0; ++ __entry->c4095 = c4095; ++ ), ++ ++ TP_printk("ino %lu page_index %lu p0 %.2x p4095 %.2x c0 %.2x c4095 %.2x", ++ (unsigned long) __entry->ino, ++ (unsigned long) __entry->index, ++ (unsigned char) __entry->p0, ++ (unsigned char) __entry->p4095, ++ (unsigned char) __entry->c0, ++ (unsigned char) __entry->c4095) ++); ++ + DEFINE_EVENT(ext4__page_op, ext4_writepage, + + TP_PROTO(struct page *page), +@@ -515,6 +547,20 @@ DEFINE_EVENT(ext4__page_op, ext4_releasepage, + TP_ARGS(page) + ); + ++DEFINE_EVENT(ext4__page_crypt_op, ext4_encrypt, ++ ++ TP_PROTO(struct page *page, char p0, char p4095, char c0, char c4095), ++ ++ TP_ARGS(page, p0, p4095, c0, c4095) ++); ++ ++DEFINE_EVENT(ext4__page_crypt_op, ext4_decrypt, ++ ++ TP_PROTO(struct page *page, char p0, char p4095, char c0, char c4095), ++ ++ TP_ARGS(page, p0, p4095, c0, c4095) ++); ++ + DECLARE_EVENT_CLASS(ext4_invalidatepage_op, + TP_PROTO(struct page *page, unsigned int offset, unsigned int length), + +-- +2.1.0.rc2.206.gedb03e5 + + diff --git a/remove-extra-unlock-page b/remove-extra-unlock-page new file mode 100644 index 00000000..f593e549 --- /dev/null +++ b/remove-extra-unlock-page @@ -0,0 +1,25 @@ +ext4 crypto: remove extra unlock_page() + +From: Michael Halcrow + +This unlock was mistakenly duplicated during a previous refactor. It +races with other page locks to result in several BUG_ON(!PageLocked()) +instances to get hit. + +Signed-off-by: Michael Halcrow +Signed-off-by: Theodore Ts'o +--- + fs/ext4/page-io.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 872503d..918726a 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -598,6 +598,5 @@ int ext4_bio_write_page(struct ext4_io_submit *io, + ret = ext4_bio_encrypt_and_write(io, page, wbc); + else + ret = ext4_bio_write_buffers(io, page, NULL, len, wbc); +- unlock_page(page); + return ret; + } diff --git a/return-error-code-on-key-retrieval-failure-and-retry-crypto-after-interrupted b/return-error-code-on-key-retrieval-failure-and-retry-crypto-after-interrupted new file mode 100644 index 00000000..41e12897 --- /dev/null +++ b/return-error-code-on-key-retrieval-failure-and-retry-crypto-after-interrupted @@ -0,0 +1,44 @@ +ext4 crypto: Return error code on key retrieval failure and retry crypto after interrupted + +From: Michael Halcrow + +Signed-of-by: Michael Halcrow +Signed-off-by: Theodore Ts'o +--- + fs/ext4/crypto.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c +index f81b804..ead3111 100644 +--- a/fs/ext4/crypto.c ++++ b/fs/ext4/crypto.c +@@ -629,7 +629,7 @@ static int ext4_get_wrapping_key( + } + BUG_ON(sig[EXT4_WRAPPING_KEY_SIG_NULL_TERMINATED_SIZE - 1] != '\0'); + res = ext4_get_wrapping_key_from_keyring(wrapping_key, sig); +- return 0; ++ return res; + } + + /** +@@ -1048,6 +1048,7 @@ int ext4_set_crypto_key(struct dentry *dentry) + struct ext4_inode_info *ei = EXT4_I(inode); + int res = 0; + ++try_again: + ext4_generate_encryption_key(dentry); + res = ext4_wrap_key(wrapped_key_packet, &wrapped_key_packet_size, + &ei->i_encryption_key, inode); +@@ -1062,6 +1063,8 @@ int ext4_set_crypto_key(struct dentry *dentry) + root_packet, root_packet_size, 0); + out: + if (res) { ++ if (res == -EINTR) ++ goto try_again; + ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID; + printk_ratelimited(KERN_ERR "%s: res = [%d]\n", __func__, res); + } +-- +2.1.0.rc2.206.gedb03e5 + + diff --git a/series b/series index bb703972..9dcdad52 100644 --- a/series +++ b/series @@ -54,6 +54,10 @@ add-ext4-encryption-facilities implement-the-ext4-encryption-write-path add-ext4-encryption-read-callback-support disable-fallocate-for-encrypted-inodes +#crypto-debugging-sb-page-zero-check +crypto-trace-events +add-more-granular-errors-to-set-key-path +remove-extra-unlock-page cache-extent-hole-in-extent-status-tree-for-ext4_da_map_blocks change-lru-to-round-rubin-in-extent-status-tree diff --git a/timestamps b/timestamps index b69f2960..5ef5466b 100755 --- a/timestamps +++ b/timestamps @@ -5,8 +5,6 @@ touch -d @1403748509 replace-builtin_log-with-ilog2 touch -d @1403791913 decrement-counters-on-bitmap-error touch -d @1403800273 fix-32bit-breakage-in-block-device touch -d @1406642254 save-goal-location-struct-ext4_allocation_context.ac_g_ex -touch -d @1409338546 add-fallocate-mode-blocking-for-debugging -touch -d @1409338606 use-discard-if-possible-in-blkdev_issue_zeroout touch -d @1409338666 add-blkdiscard-ioctl touch -d @1409338726 block-dio-during-truncate touch -d @1409338786 delalloc-debug @@ -43,26 +41,33 @@ touch -d @1409621649 enable-block-validity-by-default touch -d @1409624130 fix-comments-about-get_blocks touch -d @1409624533 improve-extents-status-tree-trace-point touch -d @1409624809 track-extent-status-tree-shrinker-delay-stats -touch -d @1409707592 cache-extent-hole-in-extent-status-tree-for-ext4_da_map_blocks touch -d @1409868385 pass-allocation_request-struct-to-ext4_alloc_branch touch -d @1409868445 prepare-to-drop-state_dellaloc_reserved-flag touch -d @1409868502 drop-ext4_state-delalloc-reserved touch -d @1409868562 dont-elevate-b_count-before-calling-__jbd2_journal_remove_checkpoint -touch -d @1409868569 change-lru-to-round-rubin-in-extent-status-tree touch -d @1409868569 optimize-jbd2_log_do_checkpoint-a-bit touch -d @1409868569 renumber-ext4_ex-flags -touch -d @1409868569 use-a-list-to-track-all-reclaimable-objects-for-extent-status-tree -touch -d @1409868570 use-a-garbage-collection-algorithm-to-manage-object touch -d @1409882682 support-buffer-cache-allocations-with-gfp-modifiers touch -d @1409884575 use-non-moveable-memory-for-the-ext4-superblock touch -d @1409884595 use-non-moveable-memory-for-the-jbd-superblock touch -d @1409884655 stable-boundary touch -d @1409884715 stable-boundary-undo.patch -touch -d @1409888271 add-callback-support-for-bio-read-completion -touch -d @1409888551 add-ext4-encryption-facilities -touch -d @1409888656 implement-the-ext4-encryption-write-path -touch -d @1409888765 add-ext4-encryption-read-callback-support -touch -d @1409888831 series -touch -d @1409889282 disable-fallocate-for-encrypted-inodes -touch -d @1409889282 status -touch -d @1409892592 timestamps +touch -d @1409921516 add-callback-support-for-bio-read-completion +touch -d @1409924002 use-discard-if-possible-in-blkdev_issue_zeroout +touch -d @1409924195 add-ext4-encryption-facilities +touch -d @1409924255 implement-the-ext4-encryption-write-path +touch -d @1409924293 add-ext4-encryption-read-callback-support +touch -d @1409924294 crypto-debugging-sb-page-zero-check +touch -d @1409924294 crypto-trace-events +touch -d @1409924294 disable-fallocate-for-encrypted-inodes +touch -d @1409953204 use-a-garbage-collection-algorithm-to-manage-object +touch -d @1409953205 add-fallocate-mode-blocking-for-debugging +touch -d @1409965630 return-error-code-on-key-retrieval-failure-and-retry-crypto-after-interrupted +touch -d @1409965690 cache-extent-hole-in-extent-status-tree-for-ext4_da_map_blocks +touch -d @1409965750 change-lru-to-round-rubin-in-extent-status-tree +touch -d @1409965810 use-a-list-to-track-all-reclaimable-objects-for-extent-status-tree +touch -d @1409967315 series +touch -d @1409967437 add-more-granular-errors-to-set-key-path +touch -d @1409967471 remove-extra-unlock-page +touch -d @1409967471 status +touch -d @1409967488 timestamps -- 2.11.4.GIT