static int ll_get_context(struct inode *inode, void *ctx, size_t len)
{
- struct dentry *dentry = d_find_any_alias(inode);
int rc;
- rc = ll_vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
- ctx, len);
- if (dentry)
- dput(dentry);
+ /* Get enc context xattr directly instead of going through the VFS,
+ * as there is no xattr handler for "encryption.".
+ */
+ rc = ll_xattr_list(inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ XATTR_ENCRYPTION_T, ctx, len, OBD_MD_FLXATTR);
/* used as encryption unit size */
if (S_ISREG(inode->i_mode))
* op_data, so that it will be sent along to the server with the request that
* the caller is preparing, thus saving a setxattr request.
* - inode is not NULL:
- * normal case in which passed fs_data is a struct dentry *, letting proceed
- * with setxattr operation.
+ * normal case, letting proceed with setxattr operation.
* This use case should only be used when explicitly setting a new encryption
* policy on an existing, empty directory.
*/
static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
void *fs_data)
{
- struct dentry *dentry;
+ struct ptlrpc_request *req = NULL;
+ struct ll_sb_info *sbi;
int rc;
if (inode == NULL) {
if (is_root_inode(inode))
return -EPERM;
- dentry = (struct dentry *)fs_data;
- set_bit(LLIF_SET_ENC_CTX, &ll_i2info(inode)->lli_flags);
- rc = ll_vfs_setxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
- ctx, len, XATTR_CREATE);
+ sbi = ll_i2sbi(inode);
+ /* Send setxattr request to lower layers directly instead of going
+ * through the VFS, as there is no xattr handler for "encryption.".
+ */
+ rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
+ OBD_MD_FLXATTR, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ ctx, len, XATTR_CREATE, ll_i2suppgid(inode), &req);
if (rc)
return rc;
+ ptlrpc_req_finished(req);
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)
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)
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)
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;
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)
{
}