--- /dev/null
+From c9af28fdd44922a6c10c9f8315718408af98e315 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 26 Mar 2016 16:14:34 -0400
+Subject: ext4 crypto: don't let data integrity writebacks fail with ENOMEM
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit c9af28fdd44922a6c10c9f8315718408af98e315 upstream.
+
+We don't want the writeback triggered from the journal commit (in
+data=writeback mode) to cause the journal to abort due to
+generic_writepages() returning an ENOMEM error. In addition, if
+fsync() fails with ENOMEM, most applications will probably not do the
+right thing.
+
+So if we are doing a data integrity sync, and ext4_encrypt() returns
+ENOMEM, we will submit any queued I/O to date, and then retry the
+allocation using GFP_NOFAIL.
+
+Google-Bug-Id: 27641567
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/crypto.c | 37 +++++++++++++++++++++----------------
+ fs/ext4/ext4.h | 6 ++++--
+ fs/ext4/page-io.c | 14 +++++++++++++-
+ fs/ext4/readpage.c | 2 +-
+ 4 files changed, 39 insertions(+), 20 deletions(-)
+
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -94,7 +94,8 @@ void ext4_release_crypto_ctx(struct ext4
+ * Return: An allocated and initialized encryption context on success; error
+ * value or NULL otherwise.
+ */
+-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
++struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
++ gfp_t gfp_flags)
+ {
+ struct ext4_crypto_ctx *ctx = NULL;
+ int res = 0;
+@@ -121,7 +122,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_
+ list_del(&ctx->free_list);
+ spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags);
+ if (!ctx) {
+- ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
++ ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags);
+ if (!ctx) {
+ res = -ENOMEM;
+ goto out;
+@@ -258,7 +259,8 @@ static int ext4_page_crypto(struct inode
+ ext4_direction_t rw,
+ pgoff_t index,
+ struct page *src_page,
+- struct page *dest_page)
++ struct page *dest_page,
++ gfp_t gfp_flags)
+
+ {
+ u8 xts_tweak[EXT4_XTS_TWEAK_SIZE];
+@@ -269,7 +271,7 @@ static int ext4_page_crypto(struct inode
+ struct crypto_ablkcipher *tfm = ci->ci_ctfm;
+ int res = 0;
+
+- req = ablkcipher_request_alloc(tfm, GFP_NOFS);
++ req = ablkcipher_request_alloc(tfm, gfp_flags);
+ if (!req) {
+ printk_ratelimited(KERN_ERR
+ "%s: crypto_request_alloc() failed\n",
+@@ -310,9 +312,10 @@ static int ext4_page_crypto(struct inode
+ return 0;
+ }
+
+-static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
++static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx,
++ gfp_t gfp_flags)
+ {
+- ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
++ ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags);
+ if (ctx->w.bounce_page == NULL)
+ return ERR_PTR(-ENOMEM);
+ ctx->flags |= EXT4_WRITE_PATH_FL;
+@@ -335,7 +338,8 @@ static struct page *alloc_bounce_page(st
+ * error value or NULL.
+ */
+ struct page *ext4_encrypt(struct inode *inode,
+- struct page *plaintext_page)
++ struct page *plaintext_page,
++ gfp_t gfp_flags)
+ {
+ struct ext4_crypto_ctx *ctx;
+ struct page *ciphertext_page = NULL;
+@@ -343,17 +347,17 @@ struct page *ext4_encrypt(struct inode *
+
+ BUG_ON(!PageLocked(plaintext_page));
+
+- ctx = ext4_get_crypto_ctx(inode);
++ ctx = ext4_get_crypto_ctx(inode, gfp_flags);
+ if (IS_ERR(ctx))
+ return (struct page *) ctx;
+
+ /* The encryption operation will require a bounce page. */
+- ciphertext_page = alloc_bounce_page(ctx);
++ ciphertext_page = alloc_bounce_page(ctx, gfp_flags);
+ if (IS_ERR(ciphertext_page))
+ goto errout;
+ ctx->w.control_page = plaintext_page;
+ err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index,
+- plaintext_page, ciphertext_page);
++ plaintext_page, ciphertext_page, gfp_flags);
+ if (err) {
+ ciphertext_page = ERR_PTR(err);
+ errout:
+@@ -381,8 +385,8 @@ int ext4_decrypt(struct page *page)
+ {
+ BUG_ON(!PageLocked(page));
+
+- return ext4_page_crypto(page->mapping->host,
+- EXT4_DECRYPT, page->index, page, page);
++ return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT,
++ page->index, page, page, GFP_NOFS);
+ }
+
+ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+@@ -403,11 +407,11 @@ int ext4_encrypted_zeroout(struct inode
+
+ BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
+
+- ctx = ext4_get_crypto_ctx(inode);
++ ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+- ciphertext_page = alloc_bounce_page(ctx);
++ ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT);
+ if (IS_ERR(ciphertext_page)) {
+ err = PTR_ERR(ciphertext_page);
+ goto errout;
+@@ -415,11 +419,12 @@ int ext4_encrypted_zeroout(struct inode
+
+ while (len--) {
+ err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk,
+- ZERO_PAGE(0), ciphertext_page);
++ ZERO_PAGE(0), ciphertext_page,
++ GFP_NOFS);
+ if (err)
+ goto errout;
+
+- bio = bio_alloc(GFP_KERNEL, 1);
++ bio = bio_alloc(GFP_NOWAIT, 1);
+ if (!bio) {
+ err = -ENOMEM;
+ goto errout;
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2261,11 +2261,13 @@ extern struct kmem_cache *ext4_crypt_inf
+ bool ext4_valid_contents_enc_mode(uint32_t mode);
+ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
+ extern struct workqueue_struct *ext4_read_workqueue;
+-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode);
++struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
++ gfp_t gfp_flags);
+ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx);
+ void ext4_restore_control_page(struct page *data_page);
+ struct page *ext4_encrypt(struct inode *inode,
+- struct page *plaintext_page);
++ struct page *plaintext_page,
++ gfp_t gfp_flags);
+ int ext4_decrypt(struct page *page);
+ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex);
+ extern const struct dentry_operations ext4_encrypted_d_ops;
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -23,6 +23,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/mm.h>
++#include <linux/backing-dev.h>
+
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -485,9 +486,20 @@ int ext4_bio_write_page(struct ext4_io_s
+
+ if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
+ nr_to_submit) {
+- data_page = ext4_encrypt(inode, page);
++ gfp_t gfp_flags = GFP_NOFS;
++
++ retry_encrypt:
++ data_page = ext4_encrypt(inode, page, gfp_flags);
+ if (IS_ERR(data_page)) {
+ ret = PTR_ERR(data_page);
++ if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
++ if (io->io_bio) {
++ ext4_io_submit(io);
++ congestion_wait(BLK_RW_ASYNC, HZ/50);
++ }
++ gfp_flags |= __GFP_NOFAIL;
++ goto retry_encrypt;
++ }
+ data_page = NULL;
+ goto out;
+ }
+--- a/fs/ext4/readpage.c
++++ b/fs/ext4/readpage.c
+@@ -279,7 +279,7 @@ int ext4_mpage_readpages(struct address_
+
+ if (ext4_encrypted_inode(inode) &&
+ S_ISREG(inode->i_mode)) {
+- ctx = ext4_get_crypto_ctx(inode);
++ ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
+ if (IS_ERR(ctx))
+ goto set_error_page;
+ }
--- /dev/null
+From 4762cc3fbbd89e5fd316d6e4d3244a8984444f8d Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Sat, 2 Apr 2016 18:13:38 -0400
+Subject: ext4 crypto: fix some error handling
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 4762cc3fbbd89e5fd316d6e4d3244a8984444f8d upstream.
+
+We should be testing for -ENOMEM but the minus sign is missing.
+
+Fixes: c9af28fdd449 ('ext4 crypto: don't let data integrity writebacks fail with ENOMEM')
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/page-io.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -492,7 +492,7 @@ int ext4_bio_write_page(struct ext4_io_s
+ data_page = ext4_encrypt(inode, page, gfp_flags);
+ if (IS_ERR(data_page)) {
+ ret = PTR_ERR(data_page);
+- if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
++ if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
+ if (io->io_bio) {
+ ext4_io_submit(io);
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
--- /dev/null
+From 6332cd32c8290a80e929fc044dc5bdba77396e33 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Mon, 24 Apr 2017 10:00:08 -0700
+Subject: f2fs: check entire encrypted bigname when finding a dentry
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+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
+
+Cc: <stable@vger.kernel.org>
+Reported-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+(fixed f2fs_dentry_hash() to work even when the hash is 0)
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ 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(-)
+
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -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_le
+ int 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) {
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -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
+--- a/fs/f2fs/hash.c
++++ b/fs/f2fs/hash.c
+@@ -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 struc
+ const 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;
+
+--- a/fs/f2fs/inline.c
++++ b/fs/f2fs/inline.c
+@@ -303,7 +303,7 @@ struct f2fs_dir_entry *find_in_inline_di
+ if (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);
+
--- /dev/null
+From 6b06cdee81d68a8a829ad8e8d0f31d6836744af9 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 24 Apr 2017 10:00:09 -0700
+Subject: fscrypt: avoid collisions when presenting long encrypted filenames
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 6b06cdee81d68a8a829ad8e8d0f31d6836744af9 upstream.
+
+When accessing an encrypted directory without the key, userspace must
+operate on filenames derived from the ciphertext names, which contain
+arbitrary bytes. Since we must support filenames as long as NAME_MAX,
+we can't always just base64-encode the ciphertext, since that may make
+it too long. Currently, this is solved by presenting long names in an
+abbreviated form containing any needed filesystem-specific hashes (e.g.
+to identify a directory block), then the last 16 bytes of ciphertext.
+This needs to be sufficient to identify the actual name on lookup.
+
+However, there is a bug. It seems to have been assumed that due to the
+use of a CBC (ciphertext block chaining)-based encryption mode, the last
+16 bytes (i.e. the AES block size) of ciphertext would depend on the
+full plaintext, preventing collisions. However, we actually use CBC
+with ciphertext stealing (CTS), which handles the last two blocks
+specially, causing them to appear "flipped". Thus, it's actually the
+second-to-last block which depends on the full plaintext.
+
+This caused long filenames that differ only near the end of their
+plaintexts to, when observed without the key, point to the wrong inode
+and be undeletable. For example, with ext4:
+
+ # echo pass | e4crypt add_key -p 16 edir/
+ # 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
+ 2004
+ # rm -rf edir/
+ rm: cannot remove 'edir/_A7nNFi3rhkEQlJ6P,hdzluhODKOeWx5V': Structure needs cleaning
+ ...
+
+To fix this, when presenting long encrypted filenames, encode the
+second-to-last block of ciphertext rather than the last 16 bytes.
+
+Although it would be nice to solve this without depending on a specific
+encryption mode, that would mean doing a cryptographic hash like SHA-256
+which would be much less efficient. This way is sufficient for now, and
+it's still compatible with encryption modes like HEH which are strong
+pseudorandom permutations. Also, changing the presented names is still
+allowed at any time because they are only provided to allow applications
+to do things like delete encrypted directories. They're not designed to
+be used to persistently identify files --- which would be hard to do
+anyway, given that they're encrypted after all.
+
+For ease of backports, this patch only makes the minimal fix to both
+ext4 and f2fs. It leaves ubifs as-is, since ubifs doesn't compare the
+ciphertext block yet. Follow-on patches will clean things up properly
+and make the filesystems use a shared helper function.
+
+Fixes: 5de0b4d0cd15 ("ext4 crypto: simplify and speed up filename encryption")
+Reported-by: Gwendal Grignou <gwendal@chromium.org>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/crypto_fname.c | 2 +-
+ fs/ext4/namei.c | 4 ++--
+ fs/f2fs/crypto_fname.c | 2 +-
+ fs/f2fs/dir.c | 4 ++--
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -343,7 +343,7 @@ int _ext4_fname_disk_to_usr(struct inode
+ memcpy(buf+4, &hinfo->minor_hash, 4);
+ } else
+ memset(buf, 0, 8);
+- memcpy(buf + 8, iname->name + iname->len - 16, 16);
++ memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
+ oname->name[0] = '_';
+ ret = digest_encode(buf, 24, oname->name+1);
+ oname->len = ret + 1;
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1243,9 +1243,9 @@ static inline int ext4_match(struct ext4
+ if (unlikely(!name)) {
+ if (fname->usr_fname->name[0] == '_') {
+ int ret;
+- if (de->name_len < 16)
++ if (de->name_len <= 32)
+ return 0;
+- ret = memcmp(de->name + de->name_len - 16,
++ ret = memcmp(de->name + ((de->name_len - 17) & ~15),
+ fname->crypto_buf.name + 8, 16);
+ return (ret == 0) ? 1 : 0;
+ }
+--- a/fs/f2fs/crypto_fname.c
++++ b/fs/f2fs/crypto_fname.c
+@@ -333,7 +333,7 @@ int f2fs_fname_disk_to_usr(struct inode
+ memset(buf + 4, 0, 4);
+ } else
+ memset(buf, 0, 8);
+- memcpy(buf + 8, iname->name + iname->len - 16, 16);
++ memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
+ oname->name[0] = '_';
+ ret = digest_encode(buf, 24, oname->name + 1);
+ oname->len = ret + 1;
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -133,8 +133,8 @@ struct f2fs_dir_entry *find_target_dentr
+ #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,
++ if (de_name.len > 32 &&
++ !memcmp(de_name.name + ((de_name.len - 17) & ~15),
+ fname->crypto_buf.name + 8, 16))
+ goto found;
+ goto not_match;
--- /dev/null
+From 272f98f6846277378e1758a49a49d7bf39343c02 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Fri, 7 Apr 2017 10:58:37 -0700
+Subject: fscrypt: fix context consistency check when key(s) unavailable
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 272f98f6846277378e1758a49a49d7bf39343c02 upstream.
+
+To mitigate some types of offline attacks, filesystem encryption is
+designed to enforce that all files in an encrypted directory tree use
+the same encryption policy (i.e. the same encryption context excluding
+the nonce). However, the fscrypt_has_permitted_context() function which
+enforces this relies on comparing struct fscrypt_info's, which are only
+available when we have the encryption keys. This can cause two
+incorrect behaviors:
+
+1. If we have the parent directory's key but not the child's key, or
+ vice versa, then fscrypt_has_permitted_context() returned false,
+ causing applications to see EPERM or ENOKEY. This is incorrect if
+ the encryption contexts are in fact consistent. Although we'd
+ normally have either both keys or neither key in that case since the
+ master_key_descriptors would be the same, this is not guaranteed
+ because keys can be added or removed from keyrings at any time.
+
+2. If we have neither the parent's key nor the child's key, then
+ fscrypt_has_permitted_context() returned true, causing applications
+ to see no error (or else an error for some other reason). This is
+ incorrect if the encryption contexts are in fact inconsistent, since
+ in that case we should deny access.
+
+To fix this, retrieve and compare the fscrypt_contexts if we are unable
+to set up both fscrypt_infos.
+
+While this slightly hurts performance when accessing an encrypted
+directory tree without the key, this isn't a case we really need to be
+optimizing for; access *with* the key is much more important.
+Furthermore, the performance hit is barely noticeable given that we are
+already retrieving the fscrypt_context and doing two keyring searches in
+fscrypt_get_encryption_info(). If we ever actually wanted to optimize
+this case we might start by caching the fscrypt_contexts.
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/crypto_policy.c | 66 ++++++++++++++++++++++++++++++++++--------------
+ fs/f2fs/crypto_policy.c | 65 ++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 96 insertions(+), 35 deletions(-)
+
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -148,26 +148,38 @@ int ext4_get_policy(struct inode *inode,
+ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
+ struct inode *child)
+ {
+- struct ext4_crypt_info *parent_ci, *child_ci;
++ const struct ext4_crypt_info *parent_ci, *child_ci;
++ struct ext4_encryption_context parent_ctx, child_ctx;
+ int res;
+
+- if ((parent == NULL) || (child == NULL)) {
+- pr_err("parent %p child %p\n", parent, child);
+- WARN_ON(1); /* Should never happen */
+- return 0;
+- }
+-
+ /* No restrictions on file types which are never encrypted */
+ if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
+ !S_ISLNK(child->i_mode))
+ return 1;
+
+- /* no restrictions if the parent directory is not encrypted */
++ /* No restrictions if the parent directory is unencrypted */
+ if (!ext4_encrypted_inode(parent))
+ return 1;
+- /* if the child directory is not encrypted, this is always a problem */
++
++ /* Encrypted directories must not contain unencrypted files */
+ if (!ext4_encrypted_inode(child))
+ return 0;
++
++ /*
++ * Both parent and child are encrypted, so verify they use the same
++ * encryption policy. Compare the fscrypt_info structs if the keys are
++ * available, otherwise retrieve and compare the fscrypt_contexts.
++ *
++ * Note that the fscrypt_context retrieval will be required frequently
++ * when accessing an encrypted directory tree without the key.
++ * Performance-wise this is not a big deal because we already don't
++ * really optimize for file access without the key (to the extent that
++ * such access is even possible), given that any attempted access
++ * already causes a fscrypt_context retrieval and keyring search.
++ *
++ * In any case, if an unexpected error occurs, fall back to "forbidden".
++ */
++
+ res = ext4_get_encryption_info(parent);
+ if (res)
+ return 0;
+@@ -176,17 +188,35 @@ int ext4_is_child_context_consistent_wit
+ return 0;
+ parent_ci = EXT4_I(parent)->i_crypt_info;
+ child_ci = EXT4_I(child)->i_crypt_info;
+- if (!parent_ci && !child_ci)
+- return 1;
+- if (!parent_ci || !child_ci)
++ if (parent_ci && child_ci) {
++ return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
++ EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
++ (parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
++ (parent_ci->ci_filename_mode ==
++ child_ci->ci_filename_mode) &&
++ (parent_ci->ci_flags == child_ci->ci_flags);
++ }
++
++ res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION,
++ EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
++ &parent_ctx, sizeof(parent_ctx));
++ if (res != sizeof(parent_ctx))
++ return 0;
++
++ res = ext4_xattr_get(child, EXT4_XATTR_INDEX_ENCRYPTION,
++ EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
++ &child_ctx, sizeof(child_ctx));
++ if (res != sizeof(child_ctx))
+ return 0;
+
+- return (memcmp(parent_ci->ci_master_key,
+- child_ci->ci_master_key,
+- EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
+- (parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
+- (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
+- (parent_ci->ci_flags == child_ci->ci_flags));
++ return memcmp(parent_ctx.master_key_descriptor,
++ child_ctx.master_key_descriptor,
++ EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
++ (parent_ctx.contents_encryption_mode ==
++ child_ctx.contents_encryption_mode) &&
++ (parent_ctx.filenames_encryption_mode ==
++ child_ctx.filenames_encryption_mode) &&
++ (parent_ctx.flags == child_ctx.flags);
+ }
+
+ /**
+--- a/fs/f2fs/crypto_policy.c
++++ b/fs/f2fs/crypto_policy.c
+@@ -141,25 +141,38 @@ int f2fs_get_policy(struct inode *inode,
+ int f2fs_is_child_context_consistent_with_parent(struct inode *parent,
+ struct inode *child)
+ {
+- struct f2fs_crypt_info *parent_ci, *child_ci;
++ const struct f2fs_crypt_info *parent_ci, *child_ci;
++ struct f2fs_encryption_context parent_ctx, child_ctx;
+ int res;
+
+- if ((parent == NULL) || (child == NULL)) {
+- pr_err("parent %p child %p\n", parent, child);
+- BUG_ON(1);
+- }
+-
+ /* No restrictions on file types which are never encrypted */
+ if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
+ !S_ISLNK(child->i_mode))
+ return 1;
+
+- /* no restrictions if the parent directory is not encrypted */
++ /* No restrictions if the parent directory is unencrypted */
+ if (!f2fs_encrypted_inode(parent))
+ return 1;
+- /* if the child directory is not encrypted, this is always a problem */
++
++ /* Encrypted directories must not contain unencrypted files */
+ if (!f2fs_encrypted_inode(child))
+ return 0;
++
++ /*
++ * Both parent and child are encrypted, so verify they use the same
++ * encryption policy. Compare the fscrypt_info structs if the keys are
++ * available, otherwise retrieve and compare the fscrypt_contexts.
++ *
++ * Note that the fscrypt_context retrieval will be required frequently
++ * when accessing an encrypted directory tree without the key.
++ * Performance-wise this is not a big deal because we already don't
++ * really optimize for file access without the key (to the extent that
++ * such access is even possible), given that any attempted access
++ * already causes a fscrypt_context retrieval and keyring search.
++ *
++ * In any case, if an unexpected error occurs, fall back to "forbidden".
++ */
++
+ res = f2fs_get_encryption_info(parent);
+ if (res)
+ return 0;
+@@ -168,17 +181,35 @@ int f2fs_is_child_context_consistent_wit
+ return 0;
+ parent_ci = F2FS_I(parent)->i_crypt_info;
+ child_ci = F2FS_I(child)->i_crypt_info;
+- if (!parent_ci && !child_ci)
+- return 1;
+- if (!parent_ci || !child_ci)
++ if (parent_ci && child_ci) {
++ return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
++ F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
++ (parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
++ (parent_ci->ci_filename_mode ==
++ child_ci->ci_filename_mode) &&
++ (parent_ci->ci_flags == child_ci->ci_flags);
++ }
++
++ res = f2fs_getxattr(parent, F2FS_XATTR_INDEX_ENCRYPTION,
++ F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
++ &parent_ctx, sizeof(parent_ctx), NULL);
++ if (res != sizeof(parent_ctx))
++ return 0;
++
++ res = f2fs_getxattr(child, F2FS_XATTR_INDEX_ENCRYPTION,
++ F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
++ &child_ctx, sizeof(child_ctx), NULL);
++ if (res != sizeof(child_ctx))
+ return 0;
+
+- return (memcmp(parent_ci->ci_master_key,
+- child_ci->ci_master_key,
+- F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
+- (parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
+- (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
+- (parent_ci->ci_flags == child_ci->ci_flags));
++ return memcmp(parent_ctx.master_key_descriptor,
++ child_ctx.master_key_descriptor,
++ F2FS_KEY_DESCRIPTOR_SIZE) == 0 &&
++ (parent_ctx.contents_encryption_mode ==
++ child_ctx.contents_encryption_mode) &&
++ (parent_ctx.filenames_encryption_mode ==
++ child_ctx.filenames_encryption_mode) &&
++ (parent_ctx.flags == child_ctx.flags);
+ }
+
+ /**
--- /dev/null
+From 18715b261541f35ccede9b8686ee3ebaac697d38 Mon Sep 17 00:00:00 2001
+From: Kristian Evensen <kristian.evensen@gmail.com>
+Date: Thu, 7 Jan 2016 16:41:33 +0100
+Subject: net: qmi_wwan: Add SIMCom 7230E
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kristian Evensen <kristian.evensen@gmail.com>
+
+commit 18715b261541f35ccede9b8686ee3ebaac697d38 upstream.
+
+SIMCom 7230E is a QMI LTE module with support for most "normal" bands.
+Manual testing has showed that only interface five works.
+
+Cc: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/qmi_wwan.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -754,6 +754,7 @@ static const struct usb_device_id produc
+ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
++ {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
+
+ /* 4. Gobi 1000 devices */
+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
pid_ns-fix-race-between-setns-ed-fork-and-zap_pid_ns_processes.patch
usb-serial-ftdi_sio-fix-setting-latency-for-unprivileged-users.patch
usb-serial-ftdi_sio-add-olimex-arm-usb-tiny-h-pids.patch
+ext4-crypto-don-t-let-data-integrity-writebacks-fail-with-enomem.patch
+ext4-crypto-fix-some-error-handling.patch
+net-qmi_wwan-add-simcom-7230e.patch
+fscrypt-fix-context-consistency-check-when-key-s-unavailable.patch
+f2fs-check-entire-encrypted-bigname-when-finding-a-dentry.patch
+fscrypt-avoid-collisions-when-presenting-long-encrypted-filenames.patch