Eric Biggers
2020-07-14 09:31:24 -07:00
parent e12d1275e6
commit 27b2ed4395
13 changed files with 124 additions and 95 deletions

View File

@@ -396,10 +396,11 @@ When mounting an ext4 filesystem, the following option are accepted:
incompatible with data=journal.
inlinecrypt
Encrypt/decrypt the contents of encrypted files using the blk-crypto
framework rather than filesystem-layer encryption. This allows the use
of inline encryption hardware. The on-disk format is unaffected. For
more details, see Documentation/block/inline-encryption.rst.
When possible, encrypt/decrypt the contents of encrypted files using the
blk-crypto framework rather than filesystem-layer encryption. This
allows the use of inline encryption hardware. The on-disk format is
unaffected. For more details, see
Documentation/block/inline-encryption.rst.
Data Mode
=========

View File

@@ -259,11 +259,13 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
these file by default rather than to enable it via ioctl.
For other files, we can still enable compression via ioctl.
inlinecrypt
Encrypt/decrypt the contents of encrypted files using the
blk-crypto framework rather than filesystem-layer encryption.
This allows the use of inline encryption hardware. The on-disk
format is unaffected. For more details, see
When possible, encrypt/decrypt the contents of encrypted
files using the blk-crypto framework rather than
filesystem-layer encryption. This allows the use of
inline encryption hardware. The on-disk format is
unaffected. For more details, see
Documentation/block/inline-encryption.rst.
====================== ============================================================
Debugfs Entries
===============

View File

@@ -1255,6 +1255,7 @@ f2fs encryption using `kvm-xfstests
<https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md>`_::
kvm-xfstests -c ext4,f2fs -g encrypt
kvm-xfstests -c ext4,f2fs -g encrypt -m inlinecrypt
UBIFS encryption can also be tested this way, but it should be done in
a separate command, and it takes some time for kvm-xfstests to set up
@@ -1276,6 +1277,7 @@ This tests the encrypted I/O paths more thoroughly. To do this with
kvm-xfstests, use the "encrypt" filesystem configuration::
kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt
Because this runs many more tests than "-g encrypt" does, it takes
much longer to run; so also consider using `gce-xfstests
@@ -1283,3 +1285,4 @@ much longer to run; so also consider using `gce-xfstests
instead of kvm-xfstests::
gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt

View File

@@ -18,16 +18,15 @@ static const struct ufs_crypto_alg_entry {
};
static int ufshcd_program_key(struct ufs_hba *hba,
const union ufs_crypto_cfg_entry *cfg,
int slot)
const union ufs_crypto_cfg_entry *cfg, int slot)
{
int i;
u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg);
int err;
int err = 0;
ufshcd_hold(hba, false);
if (hba->vops->program_key) {
if (hba->vops && hba->vops->program_key) {
err = hba->vops->program_key(hba, cfg, slot);
goto out;
}
@@ -44,7 +43,6 @@ static int ufshcd_program_key(struct ufs_hba *hba,
/* Dword 16 must be written last */
ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[16]),
slot_offset + 16 * sizeof(cfg->reg_val[0]));
err = 0;
out:
ufshcd_release(hba);
return err;
@@ -93,22 +91,18 @@ static int ufshcd_crypto_keyslot_program(struct blk_keyslot_manager *ksm,
err = ufshcd_program_key(hba, &cfg, slot);
memzero_explicit(&cfg, sizeof(cfg));
return err;
}
static void ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
{
union ufs_crypto_cfg_entry cfg = { 0 };
int err;
/*
* Clear the crypto cfg on the device. Clearing CFGE
* might not be sufficient, so just clear the entire cfg.
*/
err = ufshcd_program_key(hba, &cfg, slot);
WARN_ON_ONCE(err);
union ufs_crypto_cfg_entry cfg = { 0 };
return ufshcd_program_key(hba, &cfg, slot);
}
static int ufshcd_crypto_keyslot_evict(struct blk_keyslot_manager *ksm,
@@ -117,9 +111,7 @@ static int ufshcd_crypto_keyslot_evict(struct blk_keyslot_manager *ksm,
{
struct ufs_hba *hba = container_of(ksm, struct ufs_hba, ksm);
ufshcd_clear_keyslot(hba, slot);
return 0;
return ufshcd_clear_keyslot(hba, slot);
}
bool ufshcd_crypto_enable(struct ufs_hba *hba)
@@ -153,18 +145,17 @@ ufshcd_find_blk_crypto_mode(union ufs_crypto_cap_entry cap)
}
/**
* ufshcd_hba_init_crypto - Read crypto capabilities, init crypto fields in hba
* ufshcd_hba_init_crypto_capabilities - Read crypto capabilities, init crypto
* fields in hba
* @hba: Per adapter instance
*
* Return: 0 if crypto was initialized or is not supported, else a -errno value.
*/
int ufshcd_hba_init_crypto(struct ufs_hba *hba)
int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
{
int cap_idx = 0;
int cap_idx;
int err = 0;
enum blk_crypto_mode_num blk_mode_num;
int slot = 0;
int num_keyslots;
/*
* Don't use crypto if either the hardware doesn't advertise the
@@ -188,8 +179,8 @@ int ufshcd_hba_init_crypto(struct ufs_hba *hba)
}
/* The actual number of configurations supported is (CFGC+1) */
num_keyslots = hba->crypto_capabilities.config_count + 1;
err = blk_ksm_init(&hba->ksm, num_keyslots);
err = blk_ksm_init(&hba->ksm,
hba->crypto_capabilities.config_count + 1);
if (err)
goto out_free_caps;
@@ -216,9 +207,6 @@ int ufshcd_hba_init_crypto(struct ufs_hba *hba)
hba->crypto_cap_array[cap_idx].sdus_mask * 512;
}
for (slot = 0; slot < num_keyslots; slot++)
ufshcd_clear_keyslot(hba, slot);
return 0;
out_free_caps:
@@ -229,6 +217,22 @@ out:
return err;
}
/**
* ufshcd_init_crypto - Initialize crypto hardware
* @hba: Per adapter instance
*/
void ufshcd_init_crypto(struct ufs_hba *hba)
{
int slot;
if (!(hba->caps & UFSHCD_CAP_CRYPTO))
return;
/* Clear all keyslots - the number of keyslots is (CFGC + 1) */
for (slot = 0; slot < hba->crypto_capabilities.config_count + 1; slot++)
ufshcd_clear_keyslot(hba, slot);
}
void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
struct request_queue *q)
{

View File

@@ -10,23 +10,35 @@
#include "ufshcd.h"
#include "ufshci.h"
static inline void ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba,
struct scsi_cmnd *cmd,
static inline void ufshcd_prepare_lrbp_crypto(struct request *rq,
struct ufshcd_lrb *lrbp)
{
struct request *rq = cmd->request;
if (rq->crypt_keyslot) {
lrbp->crypto_key_slot = blk_ksm_get_slot_idx(rq->crypt_keyslot);
lrbp->data_unit_num = rq->crypt_ctx->bc_dun[0];
} else {
if (!rq || !rq->crypt_keyslot) {
lrbp->crypto_key_slot = -1;
return;
}
lrbp->crypto_key_slot = blk_ksm_get_slot_idx(rq->crypt_keyslot);
lrbp->data_unit_num = rq->crypt_ctx->bc_dun[0];
}
static inline void
ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0,
u32 *dword_1, u32 *dword_3)
{
if (lrbp->crypto_key_slot >= 0) {
*dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD;
*dword_0 |= lrbp->crypto_key_slot;
*dword_1 = lower_32_bits(lrbp->data_unit_num);
*dword_3 = upper_32_bits(lrbp->data_unit_num);
}
}
bool ufshcd_crypto_enable(struct ufs_hba *hba);
int ufshcd_hba_init_crypto(struct ufs_hba *hba);
int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba);
void ufshcd_init_crypto(struct ufs_hba *hba);
void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
struct request_queue *q);
@@ -35,20 +47,25 @@ void ufshcd_crypto_destroy_keyslot_manager(struct ufs_hba *hba);
#else /* CONFIG_SCSI_UFS_CRYPTO */
static inline void ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba,
struct scsi_cmnd *cmd,
static inline void ufshcd_prepare_lrbp_crypto(struct request *rq,
struct ufshcd_lrb *lrbp) { }
static inline void
ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0,
u32 *dword_1, u32 *dword_3) { }
static inline bool ufshcd_crypto_enable(struct ufs_hba *hba)
{
return false;
}
static inline int ufshcd_hba_init_crypto(struct ufs_hba *hba)
static inline int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
{
return 0;
}
static inline void ufshcd_init_crypto(struct ufs_hba *hba) { }
static inline void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
struct request_queue *q) { }

View File

@@ -2002,15 +2002,26 @@ int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
/**
* ufshcd_hba_capabilities - Read controller capabilities
* @hba: per adapter instance
*
* Return: 0 on success, negative on error.
*/
static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
{
int err;
hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
/* nutrs and nutmrs are 0 based values */
hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
hba->nutmrs =
((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1;
/* Read crypto capabilities */
err = ufshcd_hba_init_crypto_capabilities(hba);
if (err)
dev_err(hba->dev, "crypto setup failed\n");
return err;
}
/**
@@ -2263,16 +2274,10 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
if (lrbp->intr_cmd)
dword_0 |= UTP_REQ_DESC_INT_CMD;
/* Transfer request descriptor header fields */
#ifdef CONFIG_SCSI_UFS_CRYPTO
if (lrbp->crypto_key_slot >= 0) {
dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD;
dword_0 |= lrbp->crypto_key_slot;
dword_1 = lower_32_bits(lrbp->data_unit_num);
dword_3 = upper_32_bits(lrbp->data_unit_num);
}
#endif /* CONFIG_SCSI_UFS_CRYPTO */
/* Prepare crypto related dwords */
ufshcd_prepare_req_desc_hdr_crypto(lrbp, &dword_0, &dword_1, &dword_3);
/* Transfer request descriptor header fields */
req_desc->header.dword_0 = cpu_to_le32(dword_0);
req_desc->header.dword_1 = cpu_to_le32(dword_1);
/*
@@ -2539,7 +2544,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
ufshcd_prepare_lrbp_crypto(hba, cmd, lrbp);
ufshcd_prepare_lrbp_crypto(cmd->request, lrbp);
lrbp->req_abort_skip = false;
@@ -2574,9 +2579,7 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
lrbp->task_tag = tag;
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
lrbp->intr_cmd = true; /* No interrupt aggregation */
#ifdef CONFIG_SCSI_UFS_CRYPTO
lrbp->crypto_key_slot = -1; /* No crypto operations */
#endif
ufshcd_prepare_lrbp_crypto(NULL, lrbp);
hba->dev_cmd.type = cmd_type;
return ufshcd_comp_devman_upiu(hba, lrbp);
@@ -4827,6 +4830,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
case OCS_MISMATCH_RESP_UPIU_SIZE:
case OCS_PEER_COMM_FAILURE:
case OCS_FATAL_ERROR:
case OCS_DEVICE_FATAL_ERROR:
case OCS_INVALID_CRYPTO_CONFIG:
case OCS_GENERAL_CRYPTO_ERROR:
default:
@@ -6149,9 +6153,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
lrbp->task_tag = tag;
lrbp->lun = 0;
lrbp->intr_cmd = true;
#ifdef CONFIG_SCSI_UFS_CRYPTO
lrbp->crypto_key_slot = -1; /* No crypto operations */
#endif
ufshcd_prepare_lrbp_crypto(NULL, lrbp);
hba->dev_cmd.type = cmd_type;
switch (hba->ufs_version) {
@@ -8801,7 +8803,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
goto out_error;
/* Read capabilities registers */
ufshcd_hba_capabilities(hba);
err = ufshcd_hba_capabilities(hba);
if (err)
goto out_disable;
/* Get UFS version supported by the controller */
hba->ufs_version = ufshcd_get_ufs_version(hba);
@@ -8911,12 +8915,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Reset the attached device */
ufshcd_vops_device_reset(hba);
/* Init crypto */
err = ufshcd_hba_init_crypto(hba);
if (err) {
dev_err(hba->dev, "crypto setup failed\n");
goto free_tmf_queue;
}
ufshcd_init_crypto(hba);
/* Host controller enable */
err = ufshcd_hba_enable(hba);

View File

@@ -293,8 +293,6 @@ struct ufs_pwr_mode_info {
struct ufs_pa_layer_attr info;
};
union ufs_crypto_cfg_entry;
/**
* struct ufs_hba_variant_ops - variant specific callbacks
* @name: variant name
@@ -322,7 +320,7 @@ union ufs_crypto_cfg_entry;
* @dbg_register_dump: used to dump controller debug information
* @phy_initialization: used to initialize phys
* @device_reset: called to issue a reset pulse on the UFS device
* @program_key: program an inline encryption key into a keyslot
* @program_key: program or evict an inline encryption key
*/
struct ufs_hba_variant_ops {
const char *name;

View File

@@ -192,12 +192,9 @@ struct fscrypt_prepared_key {
struct fscrypt_info {
/* The key in a form prepared for actual encryption/decryption */
struct fscrypt_prepared_key ci_enc_key;
struct fscrypt_prepared_key ci_enc_key;
/*
* True if the ci_enc_key should be freed when this fscrypt_info is
* freed
*/
/* True if ci_enc_key should be freed when this fscrypt_info is freed */
bool ci_owns_key;
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
@@ -380,8 +377,8 @@ static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
return 0;
}
static inline bool fscrypt_using_inline_encryption(
const struct fscrypt_info *ci)
static inline bool
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
{
return false;
}

View File

@@ -79,7 +79,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
if (!fscrypt_needs_contents_encryption(inode))
return 0;
/* The crypto mode must be valid */
/* The crypto mode must have a blk-crypto counterpart */
if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
return 0;
@@ -101,8 +101,8 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
return 0;
/*
* blk-crypto must support the crypto configuration we'll use for the
* inode on all devices in the sb
* On all the filesystem's devices, blk-crypto must support the crypto
* configuration that the file would use.
*/
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
crypto_cfg.data_unit_size = sb->s_blocksize;
@@ -122,6 +122,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
ci->ci_inlinecrypt = true;
out_free_devs:
kfree(devs);
return 0;
}
@@ -336,7 +337,7 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
*
* When building a bio which may contain data which should undergo inline
* encryption (or decryption) via fscrypt, filesystems should call this function
* to ensure that the resulting bio contains only logically contiguous data.
* to ensure that the resulting bio contains only contiguous data unit numbers.
* This will return false if the next part of the I/O cannot be merged with the
* bio because either the encryption key would be different or the encryption
* data unit numbers would be discontiguous.
@@ -441,6 +442,8 @@ EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
* targeting @pos, in order to avoid crossing a data unit number (DUN)
* discontinuity. This is only needed for certain IV generation methods.
*
* This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported().
*
* Return: the actual number of pages that can be submitted
*/
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages)
@@ -458,10 +461,6 @@ int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages)
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
return nr_pages;
/*
* fscrypt_select_encryption_impl() ensures that block_size == PAGE_SIZE
* when using FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32.
*/
if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE))
return 1;

View File

@@ -2413,6 +2413,9 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
fscrypt_show_test_dummy_encryption(seq, sep, sb);
if (sb->s_flags & SB_INLINECRYPT)
SEQ_OPTS_PUTS("inlinecrypt");
if (test_opt(sb, DAX_ALWAYS)) {
if (IS_EXT2_SB(sb))
SEQ_OPTS_PUTS("dax");

View File

@@ -819,9 +819,10 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio,
found = true;
if (page_is_mergeable(sbi, *bio, *fio->last_block,
fio->new_blkaddr) &&
f2fs_crypt_mergeable_bio(*bio,
f2fs_bug_on(sbi, !page_is_mergeable(sbi, *bio,
*fio->last_block,
fio->new_blkaddr));
if (f2fs_crypt_mergeable_bio(*bio,
fio->page->mapping->host,
fio->page->index, fio) &&
bio_add_page(*bio, page, PAGE_SIZE, 0) ==
@@ -830,7 +831,7 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio,
break;
}
/* page can't be merged into bio; submit the bio */
/* page can't be merged into bio; submit the bio */
del_bio_entry(be);
__submit_bio(sbi, *bio, DATA);
break;
@@ -915,6 +916,9 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
trace_f2fs_submit_page_bio(page, fio);
f2fs_trace_ios(fio, 0);
if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block,
fio->new_blkaddr))
f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL);
alloc_new:
if (!bio) {
bio = __bio_alloc(fio, BIO_MAX_PAGES);
@@ -981,7 +985,7 @@ next:
(!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
fio->new_blkaddr) ||
!f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host,
fio->page->index, fio)))
bio_page->index, fio)))
__submit_merged_bio(io);
alloc_new:
if (io->bio == NULL) {
@@ -994,7 +998,7 @@ alloc_new:
}
io->bio = __bio_alloc(fio, BIO_MAX_PAGES);
f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host,
fio->page->index, fio, GFP_NOIO);
bio_page->index, fio, GFP_NOIO);
io->fio = *fio;
}

View File

@@ -1599,6 +1599,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
if (sbi->sb->s_flags & SB_INLINECRYPT)
seq_puts(seq, ",inlinecrypt");
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT)
seq_printf(seq, ",alloc_mode=%s", "default");
else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)

View File

@@ -49,7 +49,6 @@ static int show_sb_opts(struct seq_file *m, struct super_block *sb)
{ SB_DIRSYNC, ",dirsync" },
{ SB_MANDLOCK, ",mand" },
{ SB_LAZYTIME, ",lazytime" },
{ SB_INLINECRYPT, ",inlinecrypt" },
{ 0, NULL }
};
const struct proc_fs_opts *fs_infop;