--- /dev/null
+From 28b4c263961c47da84ed8b5be0b5116bad1133eb Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 7 Feb 2016 19:35:05 -0500
+Subject: ext4 crypto: revalidate dentry after adding or removing the key
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 28b4c263961c47da84ed8b5be0b5116bad1133eb upstream.
+
+Add a validation check for dentries for encrypted directory to make
+sure we're not caching stale data after a key has been added or removed.
+
+Also check to make sure that status of the encryption key is updated
+when readdir(2) is executed.
+
+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 | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/ext4/dir.c | 6 ++++++
+ fs/ext4/ext4.h | 1 +
+ fs/ext4/namei.c | 18 ++++++++++++++++++
+ 4 files changed, 75 insertions(+)
+
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -469,3 +469,53 @@ uint32_t ext4_validate_encryption_key_si
+ return size;
+ return 0;
+ }
++
++/*
++ * Validate dentries for encrypted directories to make sure we aren't
++ * potentially caching stale data after a key has been added or
++ * removed.
++ */
++static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
++{
++ struct inode *dir = d_inode(dentry->d_parent);
++ struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
++ int dir_has_key, cached_with_key;
++
++ if (!ext4_encrypted_inode(dir))
++ return 0;
++
++ /* this should eventually be an flag in d_flags */
++ cached_with_key = dentry->d_fsdata != NULL;
++ dir_has_key = (ci != NULL);
++
++ /*
++ * If the dentry was cached without the key, and it is a
++ * negative dentry, it might be a valid name. We can't check
++ * if the key has since been made available due to locking
++ * reasons, so we fail the validation so ext4_lookup() can do
++ * this check.
++ *
++ * We also fail the validation if the dentry was created with
++ * the key present, but we no longer have the key, or vice versa.
++ */
++ if ((!cached_with_key && d_is_negative(dentry)) ||
++ (!cached_with_key && dir_has_key) ||
++ (cached_with_key && !dir_has_key)) {
++#if 0 /* Revalidation debug */
++ char buf[80];
++ char *cp = simple_dname(dentry, buf, sizeof(buf));
++
++ if (IS_ERR(cp))
++ cp = (char *) "???";
++ pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata,
++ cached_with_key, d_is_negative(dentry),
++ dir_has_key);
++#endif
++ return 0;
++ }
++ return 1;
++}
++
++const struct dentry_operations ext4_encrypted_d_ops = {
++ .d_revalidate = ext4_d_revalidate,
++};
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *fil
+ int dir_has_error = 0;
+ struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+
++ if (ext4_encrypted_inode(inode)) {
++ err = ext4_get_encryption_info(inode);
++ if (err && err != -ENOKEY)
++ return err;
++ }
++
+ if (is_dx_dir(inode)) {
+ err = ext4_dx_readdir(file, ctx);
+ if (err != ERR_BAD_DX_DIR) {
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2268,6 +2268,7 @@ struct page *ext4_encrypt(struct inode *
+ struct page *plaintext_page);
+ 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;
+
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ int ext4_init_crypto(void);
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1557,6 +1557,24 @@ static struct dentry *ext4_lookup(struct
+ struct ext4_dir_entry_2 *de;
+ struct buffer_head *bh;
+
++ if (ext4_encrypted_inode(dir)) {
++ int res = ext4_get_encryption_info(dir);
++
++ /*
++ * This should be a properly defined flag for
++ * dentry->d_flags when we uplift this to the VFS.
++ * d_fsdata is set to (void *) 1 if if the dentry is
++ * created while the directory was encrypted and we
++ * don't have access to the key.
++ */
++ dentry->d_fsdata = NULL;
++ if (ext4_encryption_info(dir))
++ dentry->d_fsdata = (void *) 1;
++ d_set_d_op(dentry, &ext4_encrypted_d_ops);
++ if (res && res != -ENOKEY)
++ return ERR_PTR(res);
++ }
++
+ if (dentry->d_name.len > EXT4_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
--- /dev/null
+From 3d43bcfef5f0548845a425365011c499875491b0 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 26 Mar 2016 16:15:42 -0400
+Subject: ext4 crypto: use dget_parent() in ext4_d_revalidate()
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 3d43bcfef5f0548845a425365011c499875491b0 upstream.
+
+This avoids potential problems caused by a race where the inode gets
+renamed out from its parent directory and the parent directory is
+deleted while ext4_d_revalidate() is running.
+
+Fixes: 28b4c263961c
+Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
+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 | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -477,16 +477,21 @@ uint32_t ext4_validate_encryption_key_si
+ */
+ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+- struct inode *dir = d_inode(dentry->d_parent);
+- struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
++ struct dentry *dir;
++ struct ext4_crypt_info *ci;
+ int dir_has_key, cached_with_key;
+
+- if (!ext4_encrypted_inode(dir))
++ dir = dget_parent(dentry);
++ if (!ext4_encrypted_inode(d_inode(dir))) {
++ dput(dir);
+ return 0;
++ }
++ ci = EXT4_I(d_inode(dir))->i_crypt_info;
+
+ /* this should eventually be an flag in d_flags */
+ cached_with_key = dentry->d_fsdata != NULL;
+ dir_has_key = (ci != NULL);
++ dput(dir);
+
+ /*
+ * If the dentry was cached without the key, and it is a
--- /dev/null
+From 03a8bb0e53d9562276045bdfcf2b5de2e4cff5a1 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Tue, 12 Apr 2016 16:05:36 -0700
+Subject: ext4/fscrypto: avoid RCU lookup in d_revalidate
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 03a8bb0e53d9562276045bdfcf2b5de2e4cff5a1 upstream.
+
+As Al pointed, d_revalidate should return RCU lookup before using d_inode.
+This was originally introduced by:
+commit 34286d666230 ("fs: rcu-walk aware d_revalidate method").
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Cc: 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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -34,6 +34,7 @@
+ #include <linux/random.h>
+ #include <linux/scatterlist.h>
+ #include <linux/spinlock_types.h>
++#include <linux/namei.h>
+
+ #include "ext4_extents.h"
+ #include "xattr.h"
+@@ -481,6 +482,9 @@ static int ext4_d_revalidate(struct dent
+ struct ext4_crypt_info *ci;
+ int dir_has_key, cached_with_key;
+
++ if (flags & LOOKUP_RCU)
++ return -ECHILD;
++
+ dir = dget_parent(dentry);
+ if (!ext4_encrypted_inode(d_inode(dir))) {
+ dput(dir);
--- /dev/null
+From 9a200d075e5d05be1fcad4547a0f8aee4e2f9a04 Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Fri, 30 Sep 2016 01:49:55 -0400
+Subject: ext4: require encryption feature for EXT4_IOC_SET_ENCRYPTION_POLICY
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 9a200d075e5d05be1fcad4547a0f8aee4e2f9a04 upstream.
+
+...otherwise an user can enable encryption for certain files even
+when the filesystem is unable to support it.
+Such a case would be a filesystem created by mkfs.ext4's default
+settings, 1KiB block size. Ext4 supports encyption only when block size
+is equal to PAGE_SIZE.
+But this constraint is only checked when the encryption feature flag
+is set.
+
+Signed-off-by: Richard Weinberger <richard@nod.at>
+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/ioctl.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -622,6 +622,9 @@ resizefs_out:
+ struct ext4_encryption_policy policy;
+ int err = 0;
+
++ if (!ext4_has_feature_encrypt(sb))
++ return -EOPNOTSUPP;
++
+ if (copy_from_user(&policy,
+ (struct ext4_encryption_policy __user *)arg,
+ sizeof(policy))) {
--- /dev/null
+From 13bf9fbff0e5e099e2b6f003a0ab8ae145436309 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Fri, 21 Apr 2017 15:26:30 -0400
+Subject: nfsd: stricter decoding of write-like NFSv2/v3 ops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+commit 13bf9fbff0e5e099e2b6f003a0ab8ae145436309 upstream.
+
+The NFSv2/v3 code does not systematically check whether we decode past
+the end of the buffer. This generally appears to be harmless, but there
+are a few places where we do arithmetic on the pointers involved and
+don't account for the possibility that a length could be negative. Add
+checks to catch these.
+
+Reported-by: Tuomas Haanpää <thaan@synopsys.com>
+Reported-by: Ari Kauppi <ari@synopsys.com>
+Reviewed-by: NeilBrown <neilb@suse.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs3xdr.c | 4 ++++
+ fs/nfsd/nfsxdr.c | 2 ++
+ 2 files changed, 6 insertions(+)
+
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -368,6 +368,8 @@ nfs3svc_decode_writeargs(struct svc_rqst
+ args->count = ntohl(*p++);
+ args->stable = ntohl(*p++);
+ len = args->len = ntohl(*p++);
++ if ((void *)p > head->iov_base + head->iov_len)
++ return 0;
+ /*
+ * The count must equal the amount of data passed.
+ */
+@@ -471,6 +473,8 @@ nfs3svc_decode_symlinkargs(struct svc_rq
+ /* first copy and check from the first page */
+ old = (char*)p;
+ vec = &rqstp->rq_arg.head[0];
++ if ((void *)old > vec->iov_base + vec->iov_len)
++ return 0;
+ avail = vec->iov_len - (old - (char*)vec->iov_base);
+ while (len && avail && *old) {
+ *new++ = *old++;
+--- a/fs/nfsd/nfsxdr.c
++++ b/fs/nfsd/nfsxdr.c
+@@ -302,6 +302,8 @@ nfssvc_decode_writeargs(struct svc_rqst
+ * bytes.
+ */
+ hdr = (void*)p - head->iov_base;
++ if (hdr > head->iov_len)
++ return 0;
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
+
+ /*
--- /dev/null
+From db44bac41bbfc0c0d9dd943092d8bded3c9db19b Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Tue, 25 Apr 2017 16:21:34 -0400
+Subject: nfsd4: minor NFSv2/v3 write decoding cleanup
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+commit db44bac41bbfc0c0d9dd943092d8bded3c9db19b upstream.
+
+Use a couple shortcuts that will simplify a following bugfix.
+
+(Minor backporting required to account for a change from f34b95689d2c
+"The NFSv2/NFSv3 server does not handle zero length WRITE requests
+correctly".)
+
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/nfsd/nfs3xdr.c | 8 ++++----
+ fs/nfsd/nfsxdr.c | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -358,6 +358,7 @@ nfs3svc_decode_writeargs(struct svc_rqst
+ {
+ unsigned int len, v, hdr, dlen;
+ u32 max_blocksize = svc_max_payload(rqstp);
++ struct kvec *head = rqstp->rq_arg.head;
+
+ p = decode_fh(p, &args->fh);
+ if (!p)
+@@ -377,9 +378,8 @@ nfs3svc_decode_writeargs(struct svc_rqst
+ * Check to make sure that we got the right number of
+ * bytes.
+ */
+- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
+- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
+- - hdr;
++ hdr = (void*)p - head->iov_base;
++ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
+ /*
+ * Round the length of the data which was specified up to
+ * the next multiple of XDR units and then compare that
+@@ -396,7 +396,7 @@ nfs3svc_decode_writeargs(struct svc_rqst
+ len = args->len = max_blocksize;
+ }
+ rqstp->rq_vec[0].iov_base = (void*)p;
+- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
++ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
+ v = 0;
+ while (len > rqstp->rq_vec[v].iov_len) {
+ len -= rqstp->rq_vec[v].iov_len;
+--- a/fs/nfsd/nfsxdr.c
++++ b/fs/nfsd/nfsxdr.c
+@@ -280,6 +280,7 @@ nfssvc_decode_writeargs(struct svc_rqst
+ struct nfsd_writeargs *args)
+ {
+ unsigned int len, hdr, dlen;
++ struct kvec *head = rqstp->rq_arg.head;
+ int v;
+
+ p = decode_fh(p, &args->fh);
+@@ -300,9 +301,8 @@ nfssvc_decode_writeargs(struct svc_rqst
+ * Check to make sure that we got the right number of
+ * bytes.
+ */
+- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
+- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
+- - hdr;
++ hdr = (void*)p - head->iov_base;
++ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
+
+ /*
+ * Round the length of the data which was specified up to
+@@ -316,7 +316,7 @@ nfssvc_decode_writeargs(struct svc_rqst
+ return 0;
+
+ rqstp->rq_vec[0].iov_base = (void*)p;
+- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
++ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
+ v = 0;
+ while (len > rqstp->rq_vec[v].iov_len) {
+ len -= rqstp->rq_vec[v].iov_len;
netlink-allow-direct-reclaim-for-fallback-allocation.patch
ib-qib-rename-bits_per_page-to-rvt_bits_per_page.patch
ib-ehca-fix-maybe-uninitialized-warnings.patch
+ext4-require-encryption-feature-for-ext4_ioc_set_encryption_policy.patch
+ext4-crypto-revalidate-dentry-after-adding-or-removing-the-key.patch
+ext4-crypto-use-dget_parent-in-ext4_d_revalidate.patch
+ext4-fscrypto-avoid-rcu-lookup-in-d_revalidate.patch
+nfsd4-minor-nfsv2-v3-write-decoding-cleanup.patch
+nfsd-stricter-decoding-of-write-like-nfsv2-v3-ops.patch