A code cleanup and bugfix for fs/crypto.

-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAljW4wYACgkQ8vlZVpUN
 gaPYugf9ExFbJhN+iYqUVbGXPvlr5VpEtDeVt7IfO3a37hqCEQ0IEPzksNIfUFul
 B8/rYXpz0B5gqCJeo66CGLkb1SVvSoSKCq9/BTQtugohxM7sGxDFTmdB+A+u0QJH
 leILfaMFuj0DhVOrdYVpGh7e1XPgSTUWy6/G42OJqf3SV2WxGRJtyBfmghZxEdiY
 XYCGqjq47yOIPvzB+ufKe1hnphKMgxlHeuPvByzPCvOs58GlxAYR3Ycuvjc/nz+8
 QVlAEPpGhf9ytEXELsxq/ZbsNj9xtXsNAzkAoMK+xZ2JCxIHRcS1ay/iAwxw+d9r
 bnlpI+8tQ79GIGCv3cusJSwq7j1iuQ==
 =wPlW
 -----END PGP SIGNATURE-----

Merge tag 'fscrypt-for-linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt

Pull fscrypto fixes from Ted Ts'o:
 "A code cleanup and bugfix for fs/crypto"

* tag 'fscrypt-for-linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt:
  fscrypt: eliminate ->prepare_context() operation
  fscrypt: remove broken support for detecting keyring key revocation
This commit is contained in:
Linus Torvalds 2017-03-25 15:36:56 -07:00
Родитель a00da40fc7 94840e3c80
Коммит a643f9054c
7 изменённых файлов: 15 добавлений и 71 удалений

Просмотреть файл

@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page);
static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
{ {
struct dentry *dir; struct dentry *dir;
struct fscrypt_info *ci;
int dir_has_key, cached_with_key; int dir_has_key, cached_with_key;
if (flags & LOOKUP_RCU) if (flags & LOOKUP_RCU)
@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
return 0; return 0;
} }
ci = d_inode(dir)->i_crypt_info;
if (ci && ci->ci_keyring_key &&
(ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED) |
(1 << KEY_FLAG_DEAD))))
ci = NULL;
/* this should eventually be an flag in d_flags */ /* this should eventually be an flag in d_flags */
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY; cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
dir_has_key = (ci != NULL); dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
dput(dir); dput(dir);
/* /*

Просмотреть файл

@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
fname->disk_name.len = iname->len; fname->disk_name.len = iname->len;
return 0; return 0;
} }
ret = fscrypt_get_crypt_info(dir); ret = fscrypt_get_encryption_info(dir);
if (ret && ret != -EOPNOTSUPP) if (ret && ret != -EOPNOTSUPP)
return ret; return ret;

Просмотреть файл

@ -67,7 +67,6 @@ struct fscrypt_info {
u8 ci_filename_mode; u8 ci_filename_mode;
u8 ci_flags; u8 ci_flags;
struct crypto_skcipher *ci_ctfm; struct crypto_skcipher *ci_ctfm;
struct key *ci_keyring_key;
u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
}; };
@ -101,7 +100,4 @@ extern int fscrypt_do_page_crypto(const struct inode *inode,
extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags); gfp_t gfp_flags);
/* keyinfo.c */
extern int fscrypt_get_crypt_info(struct inode *);
#endif /* _FSCRYPT_PRIVATE_H */ #endif /* _FSCRYPT_PRIVATE_H */

Просмотреть файл

@ -95,6 +95,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
kfree(description); kfree(description);
if (IS_ERR(keyring_key)) if (IS_ERR(keyring_key))
return PTR_ERR(keyring_key); return PTR_ERR(keyring_key);
down_read(&keyring_key->sem);
if (keyring_key->type != &key_type_logon) { if (keyring_key->type != &key_type_logon) {
printk_once(KERN_WARNING printk_once(KERN_WARNING
@ -102,11 +103,9 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
res = -ENOKEY; res = -ENOKEY;
goto out; goto out;
} }
down_read(&keyring_key->sem);
ukp = user_key_payload_locked(keyring_key); ukp = user_key_payload_locked(keyring_key);
if (ukp->datalen != sizeof(struct fscrypt_key)) { if (ukp->datalen != sizeof(struct fscrypt_key)) {
res = -EINVAL; res = -EINVAL;
up_read(&keyring_key->sem);
goto out; goto out;
} }
master_key = (struct fscrypt_key *)ukp->data; master_key = (struct fscrypt_key *)ukp->data;
@ -117,17 +116,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
"%s: key size incorrect: %d\n", "%s: key size incorrect: %d\n",
__func__, master_key->size); __func__, master_key->size);
res = -ENOKEY; res = -ENOKEY;
up_read(&keyring_key->sem);
goto out; goto out;
} }
res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
up_read(&keyring_key->sem);
if (res)
goto out;
crypt_info->ci_keyring_key = keyring_key;
return 0;
out: out:
up_read(&keyring_key->sem);
key_put(keyring_key); key_put(keyring_key);
return res; return res;
} }
@ -169,12 +162,11 @@ static void put_crypt_info(struct fscrypt_info *ci)
if (!ci) if (!ci)
return; return;
key_put(ci->ci_keyring_key);
crypto_free_skcipher(ci->ci_ctfm); crypto_free_skcipher(ci->ci_ctfm);
kmem_cache_free(fscrypt_info_cachep, ci); kmem_cache_free(fscrypt_info_cachep, ci);
} }
int fscrypt_get_crypt_info(struct inode *inode) int fscrypt_get_encryption_info(struct inode *inode)
{ {
struct fscrypt_info *crypt_info; struct fscrypt_info *crypt_info;
struct fscrypt_context ctx; struct fscrypt_context ctx;
@ -184,21 +176,15 @@ int fscrypt_get_crypt_info(struct inode *inode)
u8 *raw_key = NULL; u8 *raw_key = NULL;
int res; int res;
if (inode->i_crypt_info)
return 0;
res = fscrypt_initialize(inode->i_sb->s_cop->flags); res = fscrypt_initialize(inode->i_sb->s_cop->flags);
if (res) if (res)
return res; return res;
if (!inode->i_sb->s_cop->get_context) if (!inode->i_sb->s_cop->get_context)
return -EOPNOTSUPP; return -EOPNOTSUPP;
retry:
crypt_info = ACCESS_ONCE(inode->i_crypt_info);
if (crypt_info) {
if (!crypt_info->ci_keyring_key ||
key_validate(crypt_info->ci_keyring_key) == 0)
return 0;
fscrypt_put_encryption_info(inode, crypt_info);
goto retry;
}
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) { if (res < 0) {
@ -229,7 +215,6 @@ retry:
crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_data_mode = ctx.contents_encryption_mode;
crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
crypt_info->ci_ctfm = NULL; crypt_info->ci_ctfm = NULL;
crypt_info->ci_keyring_key = NULL;
memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
sizeof(crypt_info->ci_master_key)); sizeof(crypt_info->ci_master_key));
@ -273,14 +258,8 @@ retry:
if (res) if (res)
goto out; goto out;
kzfree(raw_key); if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
raw_key = NULL; crypt_info = NULL;
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
put_crypt_info(crypt_info);
goto retry;
}
return 0;
out: out:
if (res == -ENOKEY) if (res == -ENOKEY)
res = 0; res = 0;
@ -288,6 +267,7 @@ out:
kzfree(raw_key); kzfree(raw_key);
return res; return res;
} }
EXPORT_SYMBOL(fscrypt_get_encryption_info);
void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
{ {
@ -305,17 +285,3 @@ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
put_crypt_info(ci); put_crypt_info(ci);
} }
EXPORT_SYMBOL(fscrypt_put_encryption_info); EXPORT_SYMBOL(fscrypt_put_encryption_info);
int fscrypt_get_encryption_info(struct inode *inode)
{
struct fscrypt_info *ci = inode->i_crypt_info;
if (!ci ||
(ci->ci_keyring_key &&
(ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED) |
(1 << KEY_FLAG_DEAD)))))
return fscrypt_get_crypt_info(inode);
return 0;
}
EXPORT_SYMBOL(fscrypt_get_encryption_info);

Просмотреть файл

@ -33,17 +33,10 @@ static int create_encryption_context_from_policy(struct inode *inode,
const struct fscrypt_policy *policy) const struct fscrypt_policy *policy)
{ {
struct fscrypt_context ctx; struct fscrypt_context ctx;
int res;
if (!inode->i_sb->s_cop->set_context) if (!inode->i_sb->s_cop->set_context)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (inode->i_sb->s_cop->prepare_context) {
res = inode->i_sb->s_cop->prepare_context(inode);
if (res)
return res;
}
ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, memcpy(ctx.master_key_descriptor, policy->master_key_descriptor,
FS_KEY_DESCRIPTOR_SIZE); FS_KEY_DESCRIPTOR_SIZE);

Просмотреть файл

@ -1120,17 +1120,16 @@ static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len); EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
} }
static int ext4_prepare_context(struct inode *inode)
{
return ext4_convert_inline_data(inode);
}
static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
void *fs_data) void *fs_data)
{ {
handle_t *handle = fs_data; handle_t *handle = fs_data;
int res, res2, retries = 0; int res, res2, retries = 0;
res = ext4_convert_inline_data(inode);
if (res)
return res;
/* /*
* If a journal handle was specified, then the encryption context is * If a journal handle was specified, then the encryption context is
* being set on a new inode via inheritance and is part of a larger * being set on a new inode via inheritance and is part of a larger
@ -1196,7 +1195,6 @@ static unsigned ext4_max_namelen(struct inode *inode)
static const struct fscrypt_operations ext4_cryptops = { static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:", .key_prefix = "ext4:",
.get_context = ext4_get_context, .get_context = ext4_get_context,
.prepare_context = ext4_prepare_context,
.set_context = ext4_set_context, .set_context = ext4_set_context,
.dummy_context = ext4_dummy_context, .dummy_context = ext4_dummy_context,
.is_encrypted = ext4_encrypted_inode, .is_encrypted = ext4_encrypted_inode,

Просмотреть файл

@ -87,7 +87,6 @@ struct fscrypt_operations {
unsigned int flags; unsigned int flags;
const char *key_prefix; const char *key_prefix;
int (*get_context)(struct inode *, void *, size_t); int (*get_context)(struct inode *, void *, size_t);
int (*prepare_context)(struct inode *);
int (*set_context)(struct inode *, const void *, size_t, void *); int (*set_context)(struct inode *, const void *, size_t, void *);
int (*dummy_context)(struct inode *); int (*dummy_context)(struct inode *);
bool (*is_encrypted)(struct inode *); bool (*is_encrypted)(struct inode *);