Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bc7df8e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "defconfig: Enable virtualized PFK on GVM"

parents 36d324b9 ec1003e8
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -446,11 +446,19 @@ CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
CONFIG_EXT4_FS_ENCRYPTION=y
CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_EFIVAR_FS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_SDCARD_FS=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
@@ -462,6 +470,9 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_PANIC_TIMEOUT=-1
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_PFK=y
CONFIG_PFK_WRAPPED_KEY_SUPPORTED=y
CONFIG_PFK_VIRTUALIZED=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
+11 −0
Original line number Diff line number Diff line
@@ -461,11 +461,19 @@ CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
CONFIG_EXT4_FS_ENCRYPTION=y
CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_EFIVAR_FS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_SDCARD_FS=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
@@ -511,6 +519,9 @@ CONFIG_ATOMIC64_SELFTEST=m
CONFIG_TEST_USER_COPY=m
CONFIG_MEMTEST=y
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_PFK=y
CONFIG_PFK_WRAPPED_KEY_SUPPORTED=y
CONFIG_PFK_VIRTUALIZED=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
+159 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <linux/blk-mq.h>
#include <linux/blk-mq-virtio.h>
#include <linux/numa.h>
#include <linux/pfk.h>
#include <crypto/ice.h>

#define PART_BITS 4
#define VQ_NAME_LEN 16
@@ -23,6 +25,9 @@ static int major;
static DEFINE_IDA(vd_index_ida);

static struct workqueue_struct *virtblk_wq;
#ifdef CONFIG_PFK_VIRTUALIZED
static struct workqueue_struct *ice_workqueue;
#endif

struct virtio_blk_vq {
	struct virtqueue *vq;
@@ -42,6 +47,14 @@ struct virtio_blk {
	/* Process context for config space updates */
	struct work_struct config_work;

#ifdef CONFIG_PFK_VIRTUALIZED
	/* Process context for virtual ICE configuration */
	spinlock_t ice_work_lock;
	struct work_struct ice_cfg_work;
	struct request *req_pending;
	bool work_pending;
#endif

	/* What host tells us, plus 2 for header & tailer. */
	unsigned int sg_elems;

@@ -176,6 +189,7 @@ static inline void virtblk_request_done(struct request *req)
{
	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);


	switch (req_op(req)) {
	case REQ_OP_SCSI_IN:
	case REQ_OP_SCSI_OUT:
@@ -183,6 +197,16 @@ static inline void virtblk_request_done(struct request *req)
		break;
	}

#ifdef CONFIG_PFK_VIRTUALIZED
{
	bool ice_activated;
	int ret = pfk_load_key_end(req->bio, &ice_activated);

	if (ice_activated && ret != 0)
		pr_err("%s:  pfk_load_key_end returned %d\n", __func__, ret);
}
#endif

	blk_mq_end_request(req, virtblk_result(vbr));
}

@@ -214,6 +238,68 @@ static void virtblk_done(struct virtqueue *vq)
	spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
}

static blk_status_t virtblk_handle_ice(struct virtio_blk *vblk,
		struct request *req)
{
	blk_status_t retval = BLK_STS_OK;
#ifdef CONFIG_PFK_VIRTUALIZED
	int err;
	bool activate_ice = false;
	struct ice_crypto_setting pfk_crypto_data = {0};
	unsigned long flags;
	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);

	spin_lock_irqsave(&vblk->ice_work_lock, flags);
	do {
		err = pfk_load_key_start(req->bio, &pfk_crypto_data,
				&activate_ice, true);
		if (activate_ice) {
			/* ice is activated - error flow */
			if (err) {
				if (err != -EAGAIN) {
					retval = BLK_STS_IOERR;
					if (err != -EBUSY)
						pr_err("%s: pfk_load_key_start err = %d\n",
								__func__, err);
					break;
				}
				/* ice is activated -
				 * need to rerun in non atomic context
				 */
				if (!ice_workqueue) {
					pr_err("%s: error %d workqueue NULL\n",
							__func__, err);
					retval = BLK_STS_NOTSUPP;
					break;
				}
				if (!vblk->work_pending) {
					vblk->req_pending = req;

					if (!queue_work(ice_workqueue,
							&vblk->ice_cfg_work)) {
						vblk->req_pending = NULL;
						retval = BLK_STS_IOERR;
						break;
					}
					vblk->work_pending = true;
				}
				retval = BLK_STS_RESOURCE;
				break;
			}
			/* ice is activated - successful flow */
			vbr->out_hdr.ice_info.ice_slot =
					pfk_crypto_data.key_index;
			vbr->out_hdr.ice_info.activate = true;
		} else {
			/* ice is not activated */
			vbr->out_hdr.ice_info.activate = false;
		}
	} while (0);
	spin_unlock_irqrestore(&vblk->ice_work_lock, flags);
#endif
	return retval;
}

static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
			   const struct blk_mq_queue_data *bd)
{
@@ -226,6 +312,7 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
	int err;
	bool notify = false;
	u32 type;
	blk_status_t retval;

	BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);

@@ -254,6 +341,10 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
		0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req));
	vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req));

	retval = virtblk_handle_ice(vblk, req);
	if (retval != BLK_STS_OK)
		return retval;

	blk_mq_start_request(req);

	num = blk_rq_map_sg(hctx->queue, req, vbr->sg);
@@ -413,6 +504,42 @@ static void virtblk_config_changed_work(struct work_struct *work)
	kobject_uevent_env(&disk_to_dev(vblk->disk)->kobj, KOBJ_CHANGE, envp);
}

#ifdef CONFIG_PFK_VIRTUALIZED
static void virtblk_ice_work(struct work_struct *work)
{
	bool activate_ice = false;
	struct ice_crypto_setting pfk_crypto_data = {0};
	int err;
	unsigned long flags;
	struct bio *bio;
	struct virtio_blk *vblk =
			container_of(work, struct virtio_blk, ice_cfg_work);

	spin_lock_irqsave(&vblk->ice_work_lock, flags);

	if (!vblk->req_pending) {
		vblk->work_pending = false;
		spin_unlock_irqrestore(&vblk->ice_work_lock, flags);
		return;
	}

	bio = vblk->req_pending->bio;
	spin_unlock_irqrestore(&vblk->ice_work_lock, flags);

	/* config_start is called again as previous attempt returned -EAGAIN,
	 * this call shall now take care of the necessary key setup.
	 */

	err = pfk_load_key_start(bio, &pfk_crypto_data,
			&activate_ice, false);

	spin_lock_irqsave(&vblk->ice_work_lock, flags);
	vblk->req_pending = NULL;
	vblk->work_pending = false;
	spin_unlock_irqrestore(&vblk->ice_work_lock, flags);
}
#endif

static void virtblk_config_changed(struct virtio_device *vdev)
{
	struct virtio_blk *vblk = vdev->priv;
@@ -468,6 +595,10 @@ static int init_vq(struct virtio_blk *vblk)
	}
	vblk->num_vqs = num_vqs;

#ifdef CONFIG_PFK_VIRTUALIZED
	spin_lock_init(&vblk->ice_work_lock);
#endif

out:
	kfree(vqs);
	kfree(callbacks);
@@ -662,6 +793,11 @@ static int virtblk_probe(struct virtio_device *vdev)

	INIT_WORK(&vblk->config_work, virtblk_config_changed_work);

#ifdef CONFIG_PFK_VIRTUALIZED
	INIT_WORK(&vblk->ice_cfg_work, virtblk_ice_work);
	vblk->work_pending = false;
#endif

	err = init_vq(vblk);
	if (err)
		goto out_free_vblk;
@@ -738,6 +874,11 @@ static int virtblk_probe(struct virtio_device *vdev)
	/* No real sector limit. */
	blk_queue_max_hw_sectors(q, -1U);

	/* Set inline encryption. */
#ifdef CONFIG_PFK_VIRTUALIZED
	queue_flag_set_unlocked(QUEUE_FLAG_INLINECRYPT, q);
#endif

	/* Host can optionally specify maximum segment size and number of
	 * segments. */
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
@@ -920,9 +1061,18 @@ static int __init init(void)
{
	int error;

	virtblk_wq = alloc_workqueue("virtio-blk", 0, 0);
	if (!virtblk_wq)
#ifdef CONFIG_PFK_VIRTUALIZED
	ice_workqueue = alloc_workqueue("virtio-blk-ice",
			WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 0);
	if (!ice_workqueue)
		return -ENOMEM;
#endif

	virtblk_wq = alloc_workqueue("virtio-blk", 0, 0);
	if (!virtblk_wq) {
		error = -ENOMEM;
		goto out_destroy_ice_workqueue;
	}

	major = register_blkdev(0, "virtblk");
	if (major < 0) {
@@ -939,6 +1089,10 @@ static int __init init(void)
	unregister_blkdev(major, "virtblk");
out_destroy_workqueue:
	destroy_workqueue(virtblk_wq);
out_destroy_ice_workqueue:
#ifdef CONFIG_PFK_VIRTUALIZED
	destroy_workqueue(ice_workqueue);
#endif
	return error;
}

@@ -947,6 +1101,9 @@ static void __exit fini(void)
	unregister_virtio_driver(&virtio_blk);
	unregister_blkdev(major, "virtblk");
	destroy_workqueue(virtblk_wq);
#ifdef CONFIG_PFK_VIRTUALIZED
	destroy_workqueue(ice_workqueue);
#endif
}
module_init(init);
module_exit(fini);
+8 −1
Original line number Diff line number Diff line
@@ -131,7 +131,14 @@ struct virtio_blk_outhdr {
	__virtio32 ioprio;
	/* Sector (ie. 512 byte offset) */
	__virtio64 sector;
};
#ifdef CONFIG_PFK_VIRTUALIZED
	struct virtio_ice_info {
		__u8  ice_slot;
		__u8  activate;
		__u16 reserved;
	} ice_info;
#endif
} __attribute__ ((packed));

#ifndef VIRTIO_BLK_NO_LEGACY
struct virtio_scsi_inhdr {
+11 −0
Original line number Diff line number Diff line
@@ -36,4 +36,15 @@ config PFK_WRAPPED_KEY_SUPPORTED
		Adds wrapped key support in PFK driver. Instead of setting
		the key directly in ICE, it unwraps the key and sets the key
		in ICE.

config PFK_VIRTUALIZED
	bool "Per-File-Key driver virtualized version"
	depends on SECURITY
	depends on SECURITY_SELINUX
	depends on QSEECOM
	depends on PFK
	depends on MSM_HAB
	help
		Makes the driver to use the hypervisor back end for ICE HW
		operation virtualization instead of calling directly to TZ.
endmenu
Loading