X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fcrypto.c;h=3d7b63e2e7291073558a245241809eca88a407b6;hb=4231fab66eab3e984499bf0c6bd4514692a409fa;hp=e8d87d6c361af3f926a21d83eda7386fc269fc39;hpb=efb66de719329ce4d96b40f00ad592cca1e432fd;p=fs%2Flustre-release.git diff --git a/lustre/llite/crypto.c b/lustre/llite/crypto.c index e8d87d6..3d7b63e 100644 --- a/lustre/llite/crypto.c +++ b/lustre/llite/crypto.c @@ -33,29 +33,13 @@ 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. + /* Get enc context xattr directly instead of going through the VFS, + * as there is no xattr handler for "encryption.". */ - 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); + 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)) @@ -92,15 +76,15 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen, * 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) { @@ -121,16 +105,48 @@ static int ll_set_context(struct inode *inode, const void *ctx, size_t len, 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) @@ -139,7 +155,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) @@ -151,16 +167,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) @@ -217,6 +234,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; @@ -417,6 +445,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) { }