Driver: spi: fix compiling err for rk3288
[firefly-linux-kernel-4.4.55.git] / fs / ext4 / crypto.c
index 1a0835073663ff3f1dad1f376328de5e2b1332ce..f240cef8b3265a38b218bdf0e8b8306a7d1587f0 100644 (file)
@@ -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"
@@ -93,7 +94,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
  * 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;
@@ -120,7 +122,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
                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;
@@ -257,7 +259,8 @@ static int ext4_page_crypto(struct inode *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];
@@ -268,7 +271,7 @@ static int ext4_page_crypto(struct inode *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",
@@ -309,9 +312,10 @@ static int ext4_page_crypto(struct inode *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;
@@ -334,7 +338,8 @@ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
  * 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;
@@ -342,17 +347,17 @@ struct page *ext4_encrypt(struct inode *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:
@@ -380,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)
@@ -402,11 +407,11 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
 
        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;
@@ -414,11 +419,12 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
 
        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;
@@ -469,3 +475,61 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
                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 dentry *dir;
+       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);
+               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
+        * 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,
+};