Enable HW File Based Encryption on ext4 file system

HW File Based Encryption (FBE) uses Crypto Engine to
encrypt the user data with unique key for each file.
File name and data both are encrypted with this feature.
1. security/pfk: New module to support per file
   encryption using CE.
2. fs/ext4: changes made to support using crypto engine
   to encyrpt the data.
Other changes made to provide support framework for per
file encryption.

Change-Id: I90d1a6df69ab30fd2476d9aad661e3ae1375e01d
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
This commit is contained in:
Neeraj Soni 2017-11-15 16:31:27 +05:30
commit 7b939265f4
39 changed files with 2418 additions and 92 deletions

View file

@ -589,7 +589,7 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
bio->bi_opf = bio_src->bi_opf;
bio->bi_iter = bio_src->bi_iter;
bio->bi_io_vec = bio_src->bi_io_vec;
bio->bi_dio_inode = bio_src->bi_dio_inode;
bio_clone_blkcg_association(bio, bio_src);
}
EXPORT_SYMBOL(__bio_clone_fast);

View file

@ -6,7 +6,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
#include <linux/pfk.h>
#include <trace/events/block.h>
#include "blk.h"
@ -725,6 +725,11 @@ static void blk_account_io_merge(struct request *req)
}
}
static bool crypto_not_mergeable(const struct bio *bio, const struct bio *nxt)
{
return (!pfk_allow_merge_bio(bio, nxt));
}
/*
* Has to be called with the request spinlock acquired
*/
@ -752,6 +757,8 @@ static int attempt_merge(struct request_queue *q, struct request *req,
!blk_write_same_mergeable(req->bio, next->bio))
return 0;
if (crypto_not_mergeable(req->bio, next->bio))
return 0;
/*
* If we are allowed to merge, then append bio list
* from next to rq and release next. merge_requests_fn
@ -862,6 +869,8 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
!blk_write_same_mergeable(rq->bio, bio))
return false;
if (crypto_not_mergeable(rq->bio, bio))
return false;
return true;
}

View file

@ -25,26 +25,8 @@
#include <soc/qcom/scm.h>
#include <soc/qcom/qseecomi.h>
#include "iceregs.h"
#ifdef CONFIG_PFK
#include <linux/pfk.h>
#else
#include <linux/bio.h>
static inline int pfk_load_key_start(const struct bio *bio,
struct ice_crypto_setting *ice_setting, bool *is_pfe, bool async)
{
return 0;
}
static inline int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
{
return 0;
}
static inline void pfk_clear_on_reset(void)
{
}
#endif
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
@ -144,6 +126,9 @@ static int qti_ice_setting_config(struct request *req,
return -EPERM;
}
if (!setting)
return -EINVAL;
if ((short)(crypto_data->key_index) >= 0) {
memcpy(&setting->crypto_data, crypto_data,
@ -1451,7 +1436,7 @@ static int qcom_ice_config_start(struct platform_device *pdev,
int ret = 0;
bool is_pfe = false;
if (!pdev || !req || !setting) {
if (!pdev || !req) {
pr_err("%s: Invalid params passed\n", __func__);
return -EINVAL;
}
@ -1470,6 +1455,7 @@ static int qcom_ice_config_start(struct platform_device *pdev,
/* It is not an error to have a request with no bio */
return 0;
}
//pr_err("%s bio is %pK\n", __func__, req->bio);
ret = pfk_load_key_start(req->bio, &pfk_crypto_data, &is_pfe, async);
if (is_pfe) {
@ -1633,7 +1619,7 @@ static struct ice_device *get_ice_device_from_storage_type
list_for_each_entry(ice_dev, &ice_devices, list) {
if (!strcmp(ice_dev->ice_instance_type, storage_type)) {
pr_info("%s: found ice device %p\n", __func__, ice_dev);
pr_debug("%s: ice device %pK\n", __func__, ice_dev);
return ice_dev;
}
}

View file

@ -170,17 +170,15 @@ out:
static void ufs_qcom_ice_cfg_work(struct work_struct *work)
{
unsigned long flags;
struct ice_data_setting ice_set;
struct ufs_qcom_host *qcom_host =
container_of(work, struct ufs_qcom_host, ice_cfg_work);
struct request *req_pending = NULL;
if (!qcom_host->ice.vops->config_start)
return;
spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
req_pending = qcom_host->req_pending;
if (!req_pending) {
if (!qcom_host->req_pending) {
qcom_host->work_pending = false;
spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
return;
}
@ -189,24 +187,15 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
/*
* config_start is called again as previous attempt returned -EAGAIN,
* this call shall now take care of the necessary key setup.
* 'ice_set' will not actually be used, instead the next call to
* config_start() for this request, in the normal call flow, will
* succeed as the key has now been setup.
*/
qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
qcom_host->req_pending, &ice_set, false);
qcom_host->req_pending, NULL, false);
spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
qcom_host->req_pending = NULL;
qcom_host->work_pending = false;
spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
/*
* Resume with requests processing. We assume config_start has been
* successful, but even if it wasn't we still must resume in order to
* allow for the request to be retried.
*/
ufshcd_scsi_unblock_requests(qcom_host->hba);
}
/**
@ -285,18 +274,14 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
* requires a non-atomic context, this means we should
* call the function again from the worker thread to do
* the configuration. For this request the error will
* propagate so it will be re-queued and until the
* configuration is is completed we block further
* request processing.
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
__func__);
if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
qcom_host->hba);
if (!qcom_host->work_pending) {
qcom_host->req_pending = cmd->request;
if (!schedule_work(
@ -307,10 +292,9 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
&qcom_host->ice_work_lock,
flags);
ufshcd_scsi_unblock_requests(
qcom_host->hba);
return err;
}
qcom_host->work_pending = true;
}
} else {
@ -409,9 +393,7 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
* requires a non-atomic context, this means we should
* call the function again from the worker thread to do
* the configuration. For this request the error will
* propagate so it will be re-queued and until the
* configuration is is completed we block further
* request processing.
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
@ -419,9 +401,8 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
"%s: scheduling task for ice setup\n",
__func__);
if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
qcom_host->hba);
if (!qcom_host->work_pending) {
qcom_host->req_pending = cmd->request;
if (!schedule_work(
&qcom_host->ice_cfg_work)) {
@ -431,10 +412,9 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
&qcom_host->ice_work_lock,
flags);
ufshcd_scsi_unblock_requests(
qcom_host->hba);
return err;
}
qcom_host->work_pending = true;
}
} else {

View file

@ -375,6 +375,7 @@ struct ufs_qcom_host {
struct work_struct ice_cfg_work;
struct request *req_pending;
struct ufs_vreg *vddp_ref_clk;
bool work_pending;
};
static inline u32

View file

@ -1,3 +1,4 @@
obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o
ccflags-y += -Ifs/ext4
fscrypto-y := crypto.o fname.o policy.o keyinfo.o

View file

@ -28,6 +28,7 @@
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/fscrypto.h>
#include "ext4_ice.h"
static unsigned int num_prealloc_crypto_pages = 32;
static unsigned int num_prealloc_crypto_ctxs = 128;
@ -406,6 +407,9 @@ static void completion_pages(struct work_struct *work)
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
if (ext4_is_ice_enabled())
SetPageUptodate(page);
else {
int ret = fscrypt_decrypt_page(page);
if (ret) {
@ -414,6 +418,7 @@ static void completion_pages(struct work_struct *work)
} else {
SetPageUptodate(page);
}
}
unlock_page(page);
}
fscrypt_release_ctx(ctx);

View file

@ -11,6 +11,7 @@
#include <keys/user-type.h>
#include <linux/scatterlist.h>
#include <linux/fscrypto.h>
#include "ext4_ice.h"
static void derive_crypt_complete(struct crypto_async_request *req, int rc)
{
@ -135,13 +136,17 @@ out:
}
static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode,
const char **cipher_str_ret, int *keysize_ret)
const char **cipher_str_ret, int *keysize_ret, int *fname)
{
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;
} else if (ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE) {
*cipher_str_ret = "bugon";
*keysize_ret = FS_AES_256_XTS_KEY_SIZE;
return 0;
}
pr_warn_once("fscrypto: unsupported contents encryption mode "
"%d for inode %lu\n",
@ -153,6 +158,7 @@ static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode,
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;
*fname = 1;
return 0;
}
pr_warn_once("fscrypto: unsupported filenames encryption mode "
@ -172,9 +178,26 @@ static void put_crypt_info(struct fscrypt_info *ci)
return;
crypto_free_skcipher(ci->ci_ctfm);
memzero_explicit(ci->ci_raw_key,
sizeof(ci->ci_raw_key));
kmem_cache_free(fscrypt_info_cachep, ci);
}
static int fs_data_encryption_mode(void)
{
return ext4_is_ice_enabled() ? FS_ENCRYPTION_MODE_PRIVATE :
FS_ENCRYPTION_MODE_AES_256_XTS;
}
int fs_using_hardware_encryption(struct inode *inode)
{
struct fscrypt_info *ci = inode->i_crypt_info;
return S_ISREG(inode->i_mode) && ci &&
ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE;
}
EXPORT_SYMBOL(fs_using_hardware_encryption);
int fscrypt_get_encryption_info(struct inode *inode)
{
struct fscrypt_info *crypt_info;
@ -182,8 +205,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
struct crypto_skcipher *ctfm;
const char *cipher_str;
int keysize;
u8 *raw_key = NULL;
int res;
int fname = 0;
if (inode->i_crypt_info)
return 0;
@ -200,7 +223,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
if (!fscrypt_dummy_context_enabled(inode))
return res;
ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
ctx.contents_encryption_mode = fs_data_encryption_mode();
ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
ctx.flags = 0;
} else if (res != sizeof(ctx)) {
@ -224,7 +247,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
sizeof(crypt_info->ci_master_key));
res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize);
res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize,
&fname);
if (res)
goto out;
@ -233,24 +257,21 @@ int fscrypt_get_encryption_info(struct inode *inode)
* 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)) {
memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
memset(crypt_info->ci_raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
goto got_key;
}
res = validate_user_key(crypt_info, &ctx, raw_key,
res = validate_user_key(crypt_info, &ctx, crypt_info->ci_raw_key,
FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE);
if (res && inode->i_sb->s_cop->key_prefix) {
u8 *prefix = NULL;
int prefix_size, res2;
prefix_size = inode->i_sb->s_cop->key_prefix(inode, &prefix);
res2 = validate_user_key(crypt_info, &ctx, raw_key,
prefix, prefix_size);
res2 = validate_user_key(crypt_info, &ctx,
crypt_info->ci_raw_key, prefix, prefix_size);
if (res2) {
if (res2 == -ENOKEY)
res = -ENOKEY;
@ -260,28 +281,33 @@ int fscrypt_get_encryption_info(struct inode *inode)
goto out;
}
got_key:
ctfm = crypto_alloc_skcipher(cipher_str, 0, 0);
if (!ctfm || IS_ERR(ctfm)) {
res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
printk(KERN_DEBUG
"%s: error %d (inode %u) allocating crypto tfm\n",
__func__, res, (unsigned) inode->i_ino);
if (crypt_info->ci_data_mode != FS_ENCRYPTION_MODE_PRIVATE || fname) {
ctfm = crypto_alloc_skcipher(cipher_str, 0, 0);
if (!ctfm || IS_ERR(ctfm)) {
res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
pr_err("%s: error %d inode %u allocating crypto tfm\n",
__func__, res, (unsigned int) inode->i_ino);
goto out;
}
crypt_info->ci_ctfm = ctfm;
crypto_skcipher_clear_flags(ctfm, ~0);
crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY);
res = crypto_skcipher_setkey(ctfm, crypt_info->ci_raw_key,
keysize);
if (res)
goto out;
} else if (!ext4_is_ice_enabled()) {
pr_warn("%s: ICE support not available\n",
__func__);
res = -EINVAL;
goto out;
}
crypt_info->ci_ctfm = ctfm;
crypto_skcipher_clear_flags(ctfm, ~0);
crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY);
res = crypto_skcipher_setkey(ctfm, raw_key, keysize);
if (res)
goto out;
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
crypt_info = NULL;
out:
if (res == -ENOKEY)
res = 0;
put_crypt_info(crypt_info);
kzfree(raw_key);
return res;
}
EXPORT_SYMBOL(fscrypt_get_encryption_info);

View file

@ -411,6 +411,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty)
bio_set_pages_dirty(bio);
bio->bi_dio_inode = dio->inode;
dio->bio_bdev = bio->bi_bdev;
if (sdio->submit_io) {
@ -424,6 +425,18 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
sdio->logical_offset_in_bio = 0;
}
struct inode *dio_bio_get_inode(struct bio *bio)
{
struct inode *inode = NULL;
if (bio == NULL)
return NULL;
inode = bio->bi_dio_inode;
return inode;
}
EXPORT_SYMBOL(dio_bio_get_inode);
/*
* Release any resources in case of a failure
*/

View file

@ -109,10 +109,16 @@ config EXT4_ENCRYPTION
decrypted pages in the page cache.
config EXT4_FS_ENCRYPTION
bool
default y
bool "Ext4 FS Encryption"
default n
depends on EXT4_ENCRYPTION
config EXT4_FS_ICE_ENCRYPTION
bool "Ext4 Encryption with ICE support"
default n
depends on EXT4_FS_ENCRYPTION
depends on PFK
config EXT4_DEBUG
bool "EXT4 debugging support"
depends on EXT4_FS

View file

@ -1,6 +1,7 @@
#
# Makefile for the linux ext4-filesystem routines.
#
ccflags-y += -Ifs/crypto
obj-$(CONFIG_EXT4_FS) += ext4.o
@ -12,3 +13,4 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
ext4-$(CONFIG_EXT4_FS_ICE_ENCRYPTION) += ext4_ice.o

View file

@ -2352,6 +2352,7 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
#define fscrypt_fname_free_buffer fscrypt_notsupp_fname_free_buffer
#define fscrypt_fname_disk_to_usr fscrypt_notsupp_fname_disk_to_usr
#define fscrypt_fname_usr_to_disk fscrypt_notsupp_fname_usr_to_disk
#define fs_using_hardware_encryption fs_notsupp_using_hardware_encryption
#endif
/* dir.c */

107
fs/ext4/ext4_ice.c Normal file
View file

@ -0,0 +1,107 @@
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ext4_ice.h"
/*
* Retrieves encryption key from the inode
*/
char *ext4_get_ice_encryption_key(const struct inode *inode)
{
struct fscrypt_info *ci = NULL;
if (!inode)
return NULL;
ci = inode->i_crypt_info;
if (!ci)
return NULL;
return &(ci->ci_raw_key[0]);
}
/*
* Retrieves encryption salt from the inode
*/
char *ext4_get_ice_encryption_salt(const struct inode *inode)
{
struct fscrypt_info *ci = NULL;
if (!inode)
return NULL;
ci = inode->i_crypt_info;
if (!ci)
return NULL;
return &(ci->ci_raw_key[ext4_get_ice_encryption_key_size(inode)]);
}
/*
* returns true if the cipher mode in inode is AES XTS
*/
int ext4_is_aes_xts_cipher(const struct inode *inode)
{
struct fscrypt_info *ci = NULL;
ci = inode->i_crypt_info;
if (!ci)
return 0;
return (ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE);
}
/*
* returns true if encryption info in both inodes is equal
*/
int ext4_is_ice_encryption_info_equal(const struct inode *inode1,
const struct inode *inode2)
{
char *key1 = NULL;
char *key2 = NULL;
char *salt1 = NULL;
char *salt2 = NULL;
if (!inode1 || !inode2)
return 0;
if (inode1 == inode2)
return 1;
/* both do not belong to ice, so we don't care, they are equal for us */
if (!ext4_should_be_processed_by_ice(inode1) &&
!ext4_should_be_processed_by_ice(inode2))
return 1;
/* one belongs to ice, the other does not -> not equal */
if (ext4_should_be_processed_by_ice(inode1) ^
ext4_should_be_processed_by_ice(inode2))
return 0;
key1 = ext4_get_ice_encryption_key(inode1);
key2 = ext4_get_ice_encryption_key(inode2);
salt1 = ext4_get_ice_encryption_salt(inode1);
salt2 = ext4_get_ice_encryption_salt(inode2);
/* key and salt should not be null by this point */
if (!key1 || !key2 || !salt1 || !salt2 ||
(ext4_get_ice_encryption_key_size(inode1) !=
ext4_get_ice_encryption_key_size(inode2)) ||
(ext4_get_ice_encryption_salt_size(inode1) !=
ext4_get_ice_encryption_salt_size(inode2)))
return 0;
return ((memcmp(key1, key2,
ext4_get_ice_encryption_key_size(inode1)) == 0) &&
(memcmp(salt1, salt2,
ext4_get_ice_encryption_salt_size(inode1)) == 0));
}

104
fs/ext4/ext4_ice.h Normal file
View file

@ -0,0 +1,104 @@
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _EXT4_ICE_H
#define _EXT4_ICE_H
#include "ext4.h"
#include <linux/fscrypto.h>
#ifdef CONFIG_EXT4_FS_ICE_ENCRYPTION
static inline int ext4_should_be_processed_by_ice(const struct inode *inode)
{
if (!ext4_encrypted_inode((struct inode *)inode))
return 0;
return fs_using_hardware_encryption((struct inode *)inode);
}
static inline int ext4_is_ice_enabled(void)
{
return 1;
}
int ext4_is_aes_xts_cipher(const struct inode *inode);
char *ext4_get_ice_encryption_key(const struct inode *inode);
char *ext4_get_ice_encryption_salt(const struct inode *inode);
int ext4_is_ice_encryption_info_equal(const struct inode *inode1,
const struct inode *inode2);
static inline size_t ext4_get_ice_encryption_key_size(
const struct inode *inode)
{
return FS_AES_256_XTS_KEY_SIZE / 2;
}
static inline size_t ext4_get_ice_encryption_salt_size(
const struct inode *inode)
{
return FS_AES_256_XTS_KEY_SIZE / 2;
}
#else
static inline int ext4_should_be_processed_by_ice(const struct inode *inode)
{
return 0;
}
static inline int ext4_is_ice_enabled(void)
{
return 0;
}
static inline char *ext4_get_ice_encryption_key(const struct inode *inode)
{
return NULL;
}
static inline char *ext4_get_ice_encryption_salt(const struct inode *inode)
{
return NULL;
}
static inline size_t ext4_get_ice_encryption_key_size(
const struct inode *inode)
{
return 0;
}
static inline size_t ext4_get_ice_encryption_salt_size(
const struct inode *inode)
{
return 0;
}
static inline int ext4_is_xts_cipher(const struct inode *inode)
{
return 0;
}
static inline int ext4_is_ice_encryption_info_equal(
const struct inode *inode1,
const struct inode *inode2)
{
return 0;
}
static inline int ext4_is_aes_xts_cipher(const struct inode *inode)
{
return 0;
}
#endif
#endif /* _EXT4_ICE_H */

View file

@ -42,6 +42,7 @@
#include "xattr.h"
#include "acl.h"
#include "truncate.h"
#include "ext4_ice.h"
#include <trace/events/ext4.h>
#include <trace/events/android_fs.h>
@ -1152,7 +1153,8 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
ll_rw_block(REQ_OP_READ, 0, 1, &bh);
*wait_bh++ = bh;
decrypt = ext4_encrypted_inode(inode) &&
S_ISREG(inode->i_mode);
S_ISREG(inode->i_mode) &&
!ext4_is_ice_enabled();
}
}
/*
@ -3509,7 +3511,8 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter)
get_block_func = ext4_dio_get_block_unwritten_async;
dio_flags = DIO_LOCKING;
}
#ifdef CONFIG_EXT4_FS_ENCRYPTION
#if defined(CONFIG_EXT4_FS_ENCRYPTION) && \
!defined(CONFIG_EXT4_FS_ICE_ENCRYPTION)
BUG_ON(ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode));
#endif
if (IS_DAX(inode)) {
@ -3623,7 +3626,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
ssize_t ret;
int rw = iov_iter_rw(iter);
#ifdef CONFIG_EXT4_FS_ENCRYPTION
#if defined(CONFIG_EXT4_FS_ENCRYPTION) && \
!defined(CONFIG_EXT4_FS_ICE_ENCRYPTION)
if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
return 0;
#endif
@ -3820,7 +3824,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
if (!buffer_uptodate(bh))
goto unlock;
if (S_ISREG(inode->i_mode) &&
ext4_encrypted_inode(inode)) {
ext4_encrypted_inode(inode) &&
!fs_using_hardware_encryption(inode)) {
/* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode));
BUG_ON(blocksize != PAGE_SIZE);

View file

@ -773,10 +773,6 @@ resizefs_out:
case EXT4_IOC_SET_ENCRYPTION_POLICY: {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
struct fscrypt_policy policy;
if (!ext4_has_feature_encrypt(sb))
return -EOPNOTSUPP;
if (copy_from_user(&policy,
(struct fscrypt_policy __user *)arg,
sizeof(policy)))

View file

@ -29,6 +29,7 @@
#include "ext4_jbd2.h"
#include "xattr.h"
#include "acl.h"
#include "ext4_ice.h"
static struct kmem_cache *io_end_cachep;
@ -470,6 +471,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
gfp_t gfp_flags = GFP_NOFS;
retry_encrypt:
if (!fs_using_hardware_encryption(inode))
data_page = fscrypt_encrypt_page(inode, page, gfp_flags);
if (IS_ERR(data_page)) {
ret = PTR_ERR(data_page);

View file

@ -2903,6 +2903,11 @@ int vfs_create2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry,
if (error)
return error;
error = dir->i_op->create(dir, dentry, mode, want_excl);
if (error)
return error;
error = security_inode_post_create(dir, dentry, mode);
if (error)
return error;
if (!error)
fsnotify_create(dir, dentry);
return error;
@ -3712,6 +3717,13 @@ int vfs_mknod2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, u
return error;
error = dir->i_op->mknod(dir, dentry, mode, dev);
if (error)
return error;
error = security_inode_post_create(dir, dentry, mode);
if (error)
return error;
if (!error)
fsnotify_create(dir, dentry);
return error;

View file

@ -80,6 +80,12 @@ struct bio {
struct bio_set *bi_pool;
/*
* When using dircet-io (O_DIRECT), we can't get the inode from a bio
* by walking bio->bi_io_vec->bv_page->mapping->host
* since the page is anon.
*/
struct inode *bi_dio_inode;
/*
* We can inline a number of vecs at the end of the bio, to avoid
* double allocations for a small number of bio_vecs. This member

View file

@ -2925,6 +2925,8 @@ static inline void inode_dio_end(struct inode *inode)
wake_up_bit(&inode->i_state, __I_DIO_WAKEUP);
}
struct inode *dio_bio_get_inode(struct bio *bio);
extern void inode_set_flags(struct inode *inode, unsigned int flags,
unsigned int mask);

Some files were not shown because too many files have changed in this diff Show more