Whamcloud - gitweb
LU-14677 sec: no encryption key migrate/extend/resync/split
[fs/lustre-release.git] / lustre / llite / crypto.c
index 89917c7..cc80aea 100644 (file)
 static int ll_get_context(struct inode *inode, void *ctx, size_t len)
 {
        struct dentry *dentry = d_find_any_alias(inode);
+       struct lu_env *env;
+       __u16 refcheck;
        int rc;
 
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               return PTR_ERR(env);
+
+       /* Set lcc_getencctx=1 to allow this thread to read
+        * LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr, as requested by llcrypt.
+        */
+       ll_cl_add(inode, env, NULL, LCC_RW);
+       ll_env_info(env)->lti_io_ctx.lcc_getencctx = 1;
+
        rc = ll_vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
                             ctx, len);
+
+       ll_cl_remove(inode, env);
+       cl_env_put(env, &refcheck);
+
        if (dentry)
                dput(dentry);
 
@@ -115,6 +131,34 @@ static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
        return ll_set_encflags(inode, (void *)ctx, len, false);
 }
 
+/**
+ * ll_file_open_encrypt() - overlay to llcrypt_file_open
+ * @inode: the inode being opened
+ * @filp: the struct file being set up
+ *
+ * This overlay function is necessary to handle encrypted file open without
+ * the key. We allow this access pattern to applications that know what they
+ * are doing, by using the specific flag O_FILE_ENC.
+ * This flag is only compatible with O_DIRECT IOs, to make sure ciphertext
+ * data is wiped from page cache once IOs are finished.
+ */
+int ll_file_open_encrypt(struct inode *inode, struct file *filp)
+{
+       int rc;
+
+       rc = llcrypt_file_open(inode, filp);
+       if (likely(rc != -ENOKEY))
+               return rc;
+
+       if (rc == -ENOKEY &&
+           (filp->f_flags & O_FILE_ENC) == O_FILE_ENC &&
+           filp->f_flags & O_DIRECT)
+               /* allow file open with O_FILE_ENC flag when we have O_DIRECT */
+               rc = 0;
+
+       return rc;
+}
+
 void llcrypt_free_ctx(void *encctx, __u32 size)
 {
        if (encctx)
@@ -123,7 +167,7 @@ void llcrypt_free_ctx(void *encctx, __u32 size)
 
 bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
 {
-       return unlikely(sbi->ll_flags & LL_SBI_TEST_DUMMY_ENCRYPTION);
+       return unlikely(test_bit(LL_SBI_TEST_DUMMY_ENCRYPTION, sbi->ll_flags));
 }
 
 static bool ll_dummy_context(struct inode *inode)
@@ -135,16 +179,17 @@ static bool ll_dummy_context(struct inode *inode)
 
 bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
 {
-       return sbi->ll_flags & LL_SBI_ENCRYPT;
+       return test_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
 }
 
 void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
 {
-       if (set)
-               sbi->ll_flags |= LL_SBI_ENCRYPT;
-       else
-               sbi->ll_flags &=
-                       ~(LL_SBI_ENCRYPT | LL_SBI_TEST_DUMMY_ENCRYPTION);
+       if (set) {
+               set_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
+       } else {
+               clear_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
+               clear_bit(LL_SBI_TEST_DUMMY_ENCRYPTION, sbi->ll_flags);
+       }
 }
 
 static bool ll_empty_dir(struct inode *inode)
@@ -201,6 +246,17 @@ int ll_setup_filename(struct inode *dir, const struct qstr *iname,
                fid->f_ver = 0;
        }
        rc = llcrypt_setup_filename(dir, &dname, lookup, fname);
+       if (rc == -ENOENT && lookup &&
+           !llcrypt_has_encryption_key(dir) &&
+           unlikely(filename_is_volatile(iname->name, iname->len, NULL))) {
+               /* For purpose of migration or mirroring without enc key, we
+                * allow lookup of volatile file without enc context.
+                */
+               memset(fname, 0, sizeof(struct llcrypt_name));
+               fname->disk_name.name = (unsigned char *)iname->name;
+               fname->disk_name.len = iname->len;
+               rc = 0;
+       }
        if (rc)
                return rc;
 
@@ -401,6 +457,11 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
        return 0;
 }
 
+int ll_file_open_encrypt(struct inode *inode, struct file *filp)
+{
+       return llcrypt_file_open(inode, filp);
+}
+
 void llcrypt_free_ctx(void *encctx, __u32 size)
 {
 }