fs/crypto: catch up 4.9-rc6

commit d117b9acaeada0b243f31e0fe83e111fcc9a6644 upstream.

Merge tag 'ext4_for_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
"A security fix (so a maliciously corrupted file system image won't
panic the kernel) and some fixes for CONFIG_VMAP_STACK"

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Jaegeuk Kim 2016-12-01 10:44:44 -08:00 committed by Jaegeuk Kim
parent b3441f8c71
commit d4ec990d25
7 changed files with 141 additions and 142 deletions

View file

@ -28,7 +28,6 @@
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/fscrypto.h> #include <linux/fscrypto.h>
#include <linux/ecryptfs.h>
static unsigned int num_prealloc_crypto_pages = 32; static unsigned int num_prealloc_crypto_pages = 32;
static unsigned int num_prealloc_crypto_ctxs = 128; static unsigned int num_prealloc_crypto_ctxs = 128;
@ -128,11 +127,11 @@ struct fscrypt_ctx *fscrypt_get_ctx(struct inode *inode, gfp_t gfp_flags)
EXPORT_SYMBOL(fscrypt_get_ctx); EXPORT_SYMBOL(fscrypt_get_ctx);
/** /**
* fscrypt_complete() - The completion callback for page encryption * page_crypt_complete() - completion callback for page crypto
* @req: The asynchronous encryption request context * @req: The asynchronous cipher request context
* @res: The result of the encryption operation * @res: The result of the cipher operation
*/ */
static void fscrypt_complete(struct crypto_async_request *req, int res) static void page_crypt_complete(struct crypto_async_request *req, int res)
{ {
struct fscrypt_completion_result *ecr = req->data; struct fscrypt_completion_result *ecr = req->data;
@ -152,7 +151,10 @@ static int do_page_crypto(struct inode *inode,
struct page *src_page, struct page *dest_page, struct page *src_page, struct page *dest_page,
gfp_t gfp_flags) gfp_t gfp_flags)
{ {
u8 xts_tweak[FS_XTS_TWEAK_SIZE]; struct {
__le64 index;
u8 padding[FS_XTS_TWEAK_SIZE - sizeof(__le64)];
} xts_tweak;
struct skcipher_request *req = NULL; struct skcipher_request *req = NULL;
DECLARE_FS_COMPLETION_RESULT(ecr); DECLARE_FS_COMPLETION_RESULT(ecr);
struct scatterlist dst, src; struct scatterlist dst, src;
@ -170,19 +172,17 @@ static int do_page_crypto(struct inode *inode,
skcipher_request_set_callback( skcipher_request_set_callback(
req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
fscrypt_complete, &ecr); page_crypt_complete, &ecr);
BUILD_BUG_ON(FS_XTS_TWEAK_SIZE < sizeof(index)); BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE);
memcpy(xts_tweak, &index, sizeof(index)); xts_tweak.index = cpu_to_le64(index);
memset(&xts_tweak[sizeof(index)], 0, memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
FS_XTS_TWEAK_SIZE - sizeof(index));
sg_init_table(&dst, 1); sg_init_table(&dst, 1);
sg_set_page(&dst, dest_page, PAGE_SIZE, 0); sg_set_page(&dst, dest_page, PAGE_SIZE, 0);
sg_init_table(&src, 1); sg_init_table(&src, 1);
sg_set_page(&src, src_page, PAGE_SIZE, 0); sg_set_page(&src, src_page, PAGE_SIZE, 0);
skcipher_request_set_crypt(req, &src, &dst, PAGE_SIZE, skcipher_request_set_crypt(req, &src, &dst, PAGE_SIZE, &xts_tweak);
xts_tweak);
if (rw == FS_DECRYPT) if (rw == FS_DECRYPT)
res = crypto_skcipher_decrypt(req); res = crypto_skcipher_decrypt(req);
else else

View file

@ -10,21 +10,16 @@
* This has not yet undergone a rigorous security audit. * This has not yet undergone a rigorous security audit.
*/ */
#include <keys/encrypted-type.h>
#include <keys/user-type.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/fscrypto.h> #include <linux/fscrypto.h>
static u32 size_round_up(size_t size, size_t blksize)
{
return ((size + blksize - 1) / blksize) * blksize;
}
/** /**
* dir_crypt_complete() - * fname_crypt_complete() - completion callback for filename crypto
* @req: The asynchronous cipher request context
* @res: The result of the cipher operation
*/ */
static void dir_crypt_complete(struct crypto_async_request *req, int res) static void fname_crypt_complete(struct crypto_async_request *req, int res)
{ {
struct fscrypt_completion_result *ecr = req->data; struct fscrypt_completion_result *ecr = req->data;
@ -35,90 +30,80 @@ static void dir_crypt_complete(struct crypto_async_request *req, int res)
} }
/** /**
* fname_encrypt() - * fname_encrypt() - encrypt a filename
* *
* This function encrypts the input filename, and returns the length of the * The caller must have allocated sufficient memory for the @oname string.
* ciphertext. Errors are returned as negative numbers. We trust the caller to *
* allocate sufficient memory to oname string. * Return: 0 on success, -errno on failure
*/ */
static int fname_encrypt(struct inode *inode, static int fname_encrypt(struct inode *inode,
const struct qstr *iname, struct fscrypt_str *oname) const struct qstr *iname, struct fscrypt_str *oname)
{ {
u32 ciphertext_len;
struct skcipher_request *req = NULL; struct skcipher_request *req = NULL;
DECLARE_FS_COMPLETION_RESULT(ecr); DECLARE_FS_COMPLETION_RESULT(ecr);
struct fscrypt_info *ci = inode->i_crypt_info; struct fscrypt_info *ci = inode->i_crypt_info;
struct crypto_skcipher *tfm = ci->ci_ctfm; struct crypto_skcipher *tfm = ci->ci_ctfm;
int res = 0; int res = 0;
char iv[FS_CRYPTO_BLOCK_SIZE]; char iv[FS_CRYPTO_BLOCK_SIZE];
struct scatterlist src_sg, dst_sg; struct scatterlist sg;
int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK);
char *workbuf, buf[32], *alloc_buf = NULL; unsigned int lim;
unsigned lim; unsigned int cryptlen;
lim = inode->i_sb->s_cop->max_namelen(inode); lim = inode->i_sb->s_cop->max_namelen(inode);
if (iname->len <= 0 || iname->len > lim) if (iname->len <= 0 || iname->len > lim)
return -EIO; return -EIO;
ciphertext_len = (iname->len < FS_CRYPTO_BLOCK_SIZE) ? /*
FS_CRYPTO_BLOCK_SIZE : iname->len; * Copy the filename to the output buffer for encrypting in-place and
ciphertext_len = size_round_up(ciphertext_len, padding); * pad it with the needed number of NUL bytes.
ciphertext_len = (ciphertext_len > lim) ? lim : ciphertext_len; */
cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE);
cryptlen = round_up(cryptlen, padding);
cryptlen = min(cryptlen, lim);
memcpy(oname->name, iname->name, iname->len);
memset(oname->name + iname->len, 0, cryptlen - iname->len);
if (ciphertext_len <= sizeof(buf)) { /* Initialize the IV */
workbuf = buf; memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
} else {
alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
if (!alloc_buf)
return -ENOMEM;
workbuf = alloc_buf;
}
/* Allocate request */ /* Set up the encryption request */
req = skcipher_request_alloc(tfm, GFP_NOFS); req = skcipher_request_alloc(tfm, GFP_NOFS);
if (!req) { if (!req) {
printk_ratelimited(KERN_ERR printk_ratelimited(KERN_ERR
"%s: crypto_request_alloc() failed\n", __func__); "%s: skcipher_request_alloc() failed\n", __func__);
kfree(alloc_buf);
return -ENOMEM; return -ENOMEM;
} }
skcipher_request_set_callback(req, skcipher_request_set_callback(req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
dir_crypt_complete, &ecr); fname_crypt_complete, &ecr);
sg_init_one(&sg, oname->name, cryptlen);
skcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv);
/* Copy the input */ /* Do the encryption */
memcpy(workbuf, iname->name, iname->len);
if (iname->len < ciphertext_len)
memset(workbuf + iname->len, 0, ciphertext_len - iname->len);
/* Initialize IV */
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
/* Create encryption request */
sg_init_one(&src_sg, workbuf, ciphertext_len);
sg_init_one(&dst_sg, oname->name, ciphertext_len);
skcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
res = crypto_skcipher_encrypt(req); res = crypto_skcipher_encrypt(req);
if (res == -EINPROGRESS || res == -EBUSY) { if (res == -EINPROGRESS || res == -EBUSY) {
/* Request is being completed asynchronously; wait for it */
wait_for_completion(&ecr.completion); wait_for_completion(&ecr.completion);
res = ecr.res; res = ecr.res;
} }
kfree(alloc_buf);
skcipher_request_free(req); skcipher_request_free(req);
if (res < 0) if (res < 0) {
printk_ratelimited(KERN_ERR printk_ratelimited(KERN_ERR
"%s: Error (error code %d)\n", __func__, res); "%s: Error (error code %d)\n", __func__, res);
oname->len = ciphertext_len;
return res; return res;
}
oname->len = cryptlen;
return 0;
} }
/* /**
* fname_decrypt() * fname_decrypt() - decrypt a filename
* This function decrypts the input filename, and returns *
* the length of the plaintext. * The caller must have allocated sufficient memory for the @oname string.
* Errors are returned as negative numbers. *
* We trust the caller to allocate sufficient memory to oname string. * Return: 0 on success, -errno on failure
*/ */
static int fname_decrypt(struct inode *inode, static int fname_decrypt(struct inode *inode,
const struct fscrypt_str *iname, const struct fscrypt_str *iname,
@ -146,7 +131,7 @@ static int fname_decrypt(struct inode *inode,
} }
skcipher_request_set_callback(req, skcipher_request_set_callback(req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
dir_crypt_complete, &ecr); fname_crypt_complete, &ecr);
/* Initialize IV */ /* Initialize IV */
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
@ -168,7 +153,7 @@ static int fname_decrypt(struct inode *inode,
} }
oname->len = strnlen(oname->name, iname->len); oname->len = strnlen(oname->name, iname->len);
return oname->len; return 0;
} }
static const char *lookup_table = static const char *lookup_table =
@ -231,9 +216,8 @@ u32 fscrypt_fname_encrypted_size(struct inode *inode, u32 ilen)
if (ci) if (ci)
padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK);
if (ilen < FS_CRYPTO_BLOCK_SIZE) ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE);
ilen = FS_CRYPTO_BLOCK_SIZE; return round_up(ilen, padding);
return size_round_up(ilen, padding);
} }
EXPORT_SYMBOL(fscrypt_fname_encrypted_size); EXPORT_SYMBOL(fscrypt_fname_encrypted_size);
@ -279,6 +263,10 @@ EXPORT_SYMBOL(fscrypt_fname_free_buffer);
/** /**
* fscrypt_fname_disk_to_usr() - converts a filename from disk space to user * fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
* space * space
*
* The caller must have allocated sufficient memory for the @oname string.
*
* Return: 0 on success, -errno on failure
*/ */
int fscrypt_fname_disk_to_usr(struct inode *inode, int fscrypt_fname_disk_to_usr(struct inode *inode,
u32 hash, u32 minor_hash, u32 hash, u32 minor_hash,
@ -287,13 +275,12 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
{ {
const struct qstr qname = FSTR_TO_QSTR(iname); const struct qstr qname = FSTR_TO_QSTR(iname);
char buf[24]; char buf[24];
int ret;
if (fscrypt_is_dot_dotdot(&qname)) { if (fscrypt_is_dot_dotdot(&qname)) {
oname->name[0] = '.'; oname->name[0] = '.';
oname->name[iname->len - 1] = '.'; oname->name[iname->len - 1] = '.';
oname->len = iname->len; oname->len = iname->len;
return oname->len; return 0;
} }
if (iname->len < FS_CRYPTO_BLOCK_SIZE) if (iname->len < FS_CRYPTO_BLOCK_SIZE)
@ -303,9 +290,9 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
return fname_decrypt(inode, iname, oname); return fname_decrypt(inode, iname, oname);
if (iname->len <= FS_FNAME_CRYPTO_DIGEST_SIZE) { if (iname->len <= FS_FNAME_CRYPTO_DIGEST_SIZE) {
ret = digest_encode(iname->name, iname->len, oname->name); oname->len = digest_encode(iname->name, iname->len,
oname->len = ret; oname->name);
return ret; return 0;
} }
if (hash) { if (hash) {
memcpy(buf, &hash, 4); memcpy(buf, &hash, 4);
@ -315,15 +302,18 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
} }
memcpy(buf + 8, iname->name + iname->len - 16, 16); memcpy(buf + 8, iname->name + iname->len - 16, 16);
oname->name[0] = '_'; oname->name[0] = '_';
ret = digest_encode(buf, 24, oname->name + 1); oname->len = 1 + digest_encode(buf, 24, oname->name + 1);
oname->len = ret + 1; return 0;
return ret + 1;
} }
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
/** /**
* fscrypt_fname_usr_to_disk() - converts a filename from user space to disk * fscrypt_fname_usr_to_disk() - converts a filename from user space to disk
* space * space
*
* The caller must have allocated sufficient memory for the @oname string.
*
* Return: 0 on success, -errno on failure
*/ */
int fscrypt_fname_usr_to_disk(struct inode *inode, int fscrypt_fname_usr_to_disk(struct inode *inode,
const struct qstr *iname, const struct qstr *iname,
@ -333,7 +323,7 @@ int fscrypt_fname_usr_to_disk(struct inode *inode,
oname->name[0] = '.'; oname->name[0] = '.';
oname->name[iname->len - 1] = '.'; oname->name[iname->len - 1] = '.';
oname->len = iname->len; oname->len = iname->len;
return oname->len; return 0;
} }
if (inode->i_crypt_info) if (inode->i_crypt_info)
return fname_encrypt(inode, iname, oname); return fname_encrypt(inode, iname, oname);
@ -367,10 +357,10 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
if (dir->i_crypt_info) { if (dir->i_crypt_info) {
ret = fscrypt_fname_alloc_buffer(dir, iname->len, ret = fscrypt_fname_alloc_buffer(dir, iname->len,
&fname->crypto_buf); &fname->crypto_buf);
if (ret < 0) if (ret)
return ret; return ret;
ret = fname_encrypt(dir, iname, &fname->crypto_buf); ret = fname_encrypt(dir, iname, &fname->crypto_buf);
if (ret < 0) if (ret)
goto errout; goto errout;
fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.name = fname->crypto_buf.name;
fname->disk_name.len = fname->crypto_buf.len; fname->disk_name.len = fname->crypto_buf.len;

View file

@ -8,11 +8,8 @@
* Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
*/ */
#include <keys/encrypted-type.h>
#include <keys/user-type.h> #include <keys/user-type.h>
#include <linux/random.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <uapi/linux/keyctl.h>
#include <linux/fscrypto.h> #include <linux/fscrypto.h>
static void derive_crypt_complete(struct crypto_async_request *req, int rc) static void derive_crypt_complete(struct crypto_async_request *req, int rc)
@ -139,6 +136,38 @@ out:
return res; return res;
} }
static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode,
const char **cipher_str_ret, int *keysize_ret)
{
if (S_ISREG(inode->i_mode)) {
if (ci->ci_data_mode == FS_ENCRYPTION_MODE_AES_256_XTS) {
*cipher_str_ret = "xts(aes)";
*keysize_ret = FS_AES_256_XTS_KEY_SIZE;
return 0;
}
pr_warn_once("fscrypto: unsupported contents encryption mode "
"%d for inode %lu\n",
ci->ci_data_mode, inode->i_ino);
return -ENOKEY;
}
if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
if (ci->ci_filename_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
*cipher_str_ret = "cts(cbc(aes))";
*keysize_ret = FS_AES_256_CTS_KEY_SIZE;
return 0;
}
pr_warn_once("fscrypto: unsupported filenames encryption mode "
"%d for inode %lu\n",
ci->ci_filename_mode, inode->i_ino);
return -ENOKEY;
}
pr_warn_once("fscrypto: unsupported file type %d for inode %lu\n",
(inode->i_mode & S_IFMT), inode->i_ino);
return -ENOKEY;
}
static void put_crypt_info(struct fscrypt_info *ci) static void put_crypt_info(struct fscrypt_info *ci)
{ {
if (!ci) if (!ci)
@ -155,8 +184,8 @@ int get_crypt_info(struct inode *inode)
struct fscrypt_context ctx; struct fscrypt_context ctx;
struct crypto_skcipher *ctfm; struct crypto_skcipher *ctfm;
const char *cipher_str; const char *cipher_str;
u8 raw_key[FS_MAX_KEY_SIZE]; int keysize;
u8 mode; u8 *raw_key = NULL;
int res; int res;
res = fscrypt_initialize(); res = fscrypt_initialize();
@ -179,13 +208,19 @@ retry:
if (res < 0) { if (res < 0) {
if (!fscrypt_dummy_context_enabled(inode)) if (!fscrypt_dummy_context_enabled(inode))
return res; return res;
ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
ctx.flags = 0; ctx.flags = 0;
} else if (res != sizeof(ctx)) { } else if (res != sizeof(ctx)) {
return -EINVAL; return -EINVAL;
} }
res = 0;
if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
return -EINVAL;
if (ctx.flags & ~FS_POLICY_FLAGS_VALID)
return -EINVAL;
crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS); crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS);
if (!crypt_info) if (!crypt_info)
@ -198,27 +233,20 @@ retry:
crypt_info->ci_keyring_key = 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));
if (S_ISREG(inode->i_mode))
mode = crypt_info->ci_data_mode;
else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
mode = crypt_info->ci_filename_mode;
else
BUG();
switch (mode) { res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize);
case FS_ENCRYPTION_MODE_AES_256_XTS: if (res)
cipher_str = "xts(aes)";
break;
case FS_ENCRYPTION_MODE_AES_256_CTS:
cipher_str = "cts(cbc(aes))";
break;
default:
printk_once(KERN_WARNING
"%s: unsupported key mode %d (ino %u)\n",
__func__, mode, (unsigned) inode->i_ino);
res = -ENOKEY;
goto out; goto out;
}
/*
* This cannot be a stack buffer because it is passed to the scatterlist
* crypto API as part of key derivation.
*/
res = -ENOMEM;
raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS);
if (!raw_key)
goto out;
if (fscrypt_dummy_context_enabled(inode)) { if (fscrypt_dummy_context_enabled(inode)) {
memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE); memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
goto got_key; goto got_key;
@ -253,11 +281,12 @@ got_key:
crypt_info->ci_ctfm = ctfm; crypt_info->ci_ctfm = ctfm;
crypto_skcipher_clear_flags(ctfm, ~0); crypto_skcipher_clear_flags(ctfm, ~0);
crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY);
res = crypto_skcipher_setkey(ctfm, raw_key, fscrypt_key_size(mode)); res = crypto_skcipher_setkey(ctfm, raw_key, keysize);
if (res) if (res)
goto out; goto out;
memzero_explicit(raw_key, sizeof(raw_key)); kzfree(raw_key);
raw_key = NULL;
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) { if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
put_crypt_info(crypt_info); put_crypt_info(crypt_info);
goto retry; goto retry;
@ -268,7 +297,7 @@ out:
if (res == -ENOKEY) if (res == -ENOKEY)
res = 0; res = 0;
put_crypt_info(crypt_info); put_crypt_info(crypt_info);
memzero_explicit(raw_key, sizeof(raw_key)); kzfree(raw_key);
return res; return res;
} }

View file

@ -109,6 +109,8 @@ int fscrypt_process_policy(struct file *filp,
if (ret) if (ret)
return ret; return ret;
inode_lock(inode);
if (!inode_has_encryption_context(inode)) { if (!inode_has_encryption_context(inode)) {
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
ret = -EINVAL; ret = -EINVAL;
@ -127,6 +129,8 @@ int fscrypt_process_policy(struct file *filp,
ret = -EINVAL; ret = -EINVAL;
} }
inode_unlock(inode);
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
return ret; return ret;
} }

View file

@ -814,12 +814,12 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
if (f2fs_encrypted_inode(d->inode)) { if (f2fs_encrypted_inode(d->inode)) {
int save_len = fstr->len; int save_len = fstr->len;
int ret; int err;
ret = fscrypt_fname_disk_to_usr(d->inode, err = fscrypt_fname_disk_to_usr(d->inode,
(u32)de->hash_code, 0, (u32)de->hash_code, 0,
&de_name, fstr); &de_name, fstr);
if (ret < 0) if (err)
return true; return true;
de_name = *fstr; de_name = *fstr;

View file

@ -451,7 +451,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
ostr.name = sd->encrypted_path; ostr.name = sd->encrypted_path;
ostr.len = disk_link.len; ostr.len = disk_link.len;
err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
if (err < 0) if (err)
goto err_out; goto err_out;
sd->len = cpu_to_le16(ostr.len); sd->len = cpu_to_le16(ostr.len);
@ -1047,7 +1047,7 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
goto errout; goto errout;
res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
if (res < 0) if (res)
goto errout; goto errout;
/* this is broken symlink case */ /* this is broken symlink case */
@ -1059,7 +1059,7 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
paddr = pstr.name; paddr = pstr.name;
/* Null-terminate the name */ /* Null-terminate the name */
paddr[res] = '\0'; paddr[pstr.len] = '\0';
put_page(cpage); put_page(cpage);
return *cookie = paddr; return *cookie = paddr;

View file

@ -111,23 +111,6 @@ struct fscrypt_completion_result {
struct fscrypt_completion_result ecr = { \ struct fscrypt_completion_result ecr = { \
COMPLETION_INITIALIZER((ecr).completion), 0 } COMPLETION_INITIALIZER((ecr).completion), 0 }
static inline int fscrypt_key_size(int mode)
{
switch (mode) {
case FS_ENCRYPTION_MODE_AES_256_XTS:
return FS_AES_256_XTS_KEY_SIZE;
case FS_ENCRYPTION_MODE_AES_256_GCM:
return FS_AES_256_GCM_KEY_SIZE;
case FS_ENCRYPTION_MODE_AES_256_CBC:
return FS_AES_256_CBC_KEY_SIZE;
case FS_ENCRYPTION_MODE_AES_256_CTS:
return FS_AES_256_CTS_KEY_SIZE;
default:
BUG();
}
return 0;
}
#define FS_FNAME_NUM_SCATTER_ENTRIES 4 #define FS_FNAME_NUM_SCATTER_ENTRIES 4
#define FS_CRYPTO_BLOCK_SIZE 16 #define FS_CRYPTO_BLOCK_SIZE 16
#define FS_FNAME_CRYPTO_DIGEST_SIZE 32 #define FS_FNAME_CRYPTO_DIGEST_SIZE 32
@ -202,13 +185,6 @@ static inline bool fscrypt_valid_filenames_enc_mode(u32 mode)
return (mode == FS_ENCRYPTION_MODE_AES_256_CTS); return (mode == FS_ENCRYPTION_MODE_AES_256_CTS);
} }
static inline u32 fscrypt_validate_encryption_key_size(u32 mode, u32 size)
{
if (size == fscrypt_key_size(mode))
return size;
return 0;
}
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
{ {
if (str->len == 1 && str->name[0] == '.') if (str->len == 1 && str->name[0] == '.')