Commit 985214af authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik
Browse files

s390/zcrypt: CEX8S exploitation support



This patch adds CEX8 exploitation support for the AP bus code,
the zcrypt device driver zoo and the vfio device driver.

Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarJürgen Christ <jchrist@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent d64e5e91
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ struct zcrypt_device_matrix_ext {
 *	 0x08: CEX3A
 *	 0x0a: CEX4
 *	 0x0b: CEX5
 *	 0x0c: CEX6 and CEX7
 *	 0x0c: CEX6, CEX7 or CEX8
 *	 0x0d: device is disabled
 *
 *   ZCRYPT_QDEPTH_MASK
+6 −6
Original line number Diff line number Diff line
@@ -1589,24 +1589,24 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
			    AP_QID_QUEUE(qid), rawtype);
		return 0;
	}
	/* up to CEX7 known and fully supported */
	if (rawtype <= AP_DEVICE_TYPE_CEX7)
	/* up to CEX8 known and fully supported */
	if (rawtype <= AP_DEVICE_TYPE_CEX8)
		return rawtype;
	/*
	 * unknown new type > CEX7, check for compatibility
	 * unknown new type > CEX8, check for compatibility
	 * to the highest known and supported type which is
	 * currently CEX7 with the help of the QACT function.
	 * currently CEX8 with the help of the QACT function.
	 */
	if (ap_qact_available()) {
		struct ap_queue_status status;
		union ap_qact_ap_info apinfo = {0};

		apinfo.mode = (func >> 26) & 0x07;
		apinfo.cat = AP_DEVICE_TYPE_CEX7;
		apinfo.cat = AP_DEVICE_TYPE_CEX8;
		status = ap_qact(qid, 0, &apinfo);
		if (status.response_code == AP_RESPONSE_NORMAL
		    && apinfo.cat >= AP_DEVICE_TYPE_CEX2A
		    && apinfo.cat <= AP_DEVICE_TYPE_CEX7)
		    && apinfo.cat <= AP_DEVICE_TYPE_CEX8)
			comp_type = apinfo.cat;
	}
	if (!comp_type)
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX5	11
#define AP_DEVICE_TYPE_CEX6	12
#define AP_DEVICE_TYPE_CEX7	13
#define AP_DEVICE_TYPE_CEX8	14

/*
 * Known function facilities
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ static struct ap_device_id ap_queue_ids[] = {
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX7,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX8,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ /* end of sibling */ },
};

+51 −20
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright IBM Corp. 2012, 2019
 *  Copyright IBM Corp. 2012, 2022
 *  Author(s): Holger Dengler <hd@linux.vnet.ibm.com>
 */

@@ -36,8 +36,8 @@
#define CEX4_CLEANUP_TIME	(900*HZ)

MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("CEX4/CEX5/CEX6/CEX7 Cryptographic Card device driver, " \
		   "Copyright IBM Corp. 2019");
MODULE_DESCRIPTION("CEX[45678] Cryptographic Card device driver, " \
		   "Copyright IBM Corp. 2022");
MODULE_LICENSE("GPL");

static struct ap_device_id zcrypt_cex4_card_ids[] = {
@@ -49,6 +49,8 @@ static struct ap_device_id zcrypt_cex4_card_ids[] = {
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX7,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX8,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ /* end of list */ },
};

@@ -63,6 +65,8 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = {
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX7,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX8,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ /* end of list */ },
};

@@ -395,7 +399,7 @@ static const struct attribute_group ep11_queue_attr_grp = {
};

/*
 * Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always
 * Probe function for CEX[45678] card device. It always
 * accepts the AP device since the bus_match already checked
 * the hardware type.
 * @ap_dev: pointer to the AP device.
@@ -414,6 +418,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
		  6,   9,  20, 17,  65,	 438, 0, 0};
	static const int CEX7A_SPEED_IDX[NUM_OPS] = {
		  6,   8,  17, 15,  54,	 362, 0, 0};
	static const int CEX8A_SPEED_IDX[NUM_OPS] = {
		  6,   8,  17, 15,  54,	 362, 0, 0};

	static const int CEX4C_SPEED_IDX[NUM_OPS] = {
		 59,  69, 308, 83, 278, 2204, 209, 40};
@@ -423,6 +429,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
		 16,  20,  32, 27,  77,	 455,  24,  9};
	static const int CEX7C_SPEED_IDX[NUM_OPS] = {
		 14,  16,  26, 23,  64,	 376,  23,  8};
	static const int CEX8C_SPEED_IDX[NUM_OPS] = {
		 14,  16,  26, 23,  64,	 376,  23,  8};

	static const int CEX4P_SPEED_IDX[NUM_OPS] = {
		  0,   0,   0,	 0,   0,   0,	0,  50};
@@ -432,6 +440,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
		  0,   0,   0,	 0,   0,   0,	0,   9};
	static const int CEX7P_SPEED_IDX[NUM_OPS] = {
		  0,   0,   0,	 0,   0,   0,	0,   8};
	static const int CEX8P_SPEED_IDX[NUM_OPS] = {
		  0,   0,   0,	 0,   0,   0,	0,   8};

	struct ap_card *ac = to_ap_card(&ap_dev->device);
	struct zcrypt_card *zc;
@@ -455,13 +465,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
			zc->type_string = "CEX6A";
			zc->user_space_type = ZCRYPT_CEX6;
			zc->speed_rating = CEX6A_SPEED_IDX;
		} else {
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
			zc->type_string = "CEX7A";
			zc->speed_rating = CEX7A_SPEED_IDX;
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
		} else {
			zc->type_string = "CEX8A";
			zc->speed_rating = CEX8A_SPEED_IDX;
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
			zc->speed_rating = CEX7A_SPEED_IDX;
		}
		zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
		if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
@@ -477,32 +494,39 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
	} else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
			zc->type_string = "CEX4C";
			/* wrong user space type, must be CEX4
			zc->speed_rating = CEX4C_SPEED_IDX;
			/* wrong user space type, must be CEX3C
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			zc->speed_rating = CEX4C_SPEED_IDX;
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
			zc->type_string = "CEX5C";
			/* wrong user space type, must be CEX5
			zc->speed_rating = CEX5C_SPEED_IDX;
			/* wrong user space type, must be CEX3C
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			zc->speed_rating = CEX5C_SPEED_IDX;
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
			zc->type_string = "CEX6C";
			/* wrong user space type, must be CEX6
			zc->speed_rating = CEX6C_SPEED_IDX;
			/* wrong user space type, must be CEX3C
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			zc->speed_rating = CEX6C_SPEED_IDX;
		} else {
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
			zc->type_string = "CEX7C";
			/* wrong user space type, must be CEX7
			zc->speed_rating = CEX7C_SPEED_IDX;
			/* wrong user space type, must be CEX3C
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
		} else {
			zc->type_string = "CEX8C";
			zc->speed_rating = CEX8C_SPEED_IDX;
			/* wrong user space type, must be CEX3C
			 * just keep it for cca compatibility
			 */
			zc->user_space_type = ZCRYPT_CEX3C;
			zc->speed_rating = CEX7C_SPEED_IDX;
		}
		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
@@ -520,13 +544,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
			zc->type_string = "CEX6P";
			zc->user_space_type = ZCRYPT_CEX6;
			zc->speed_rating = CEX6P_SPEED_IDX;
		} else {
		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
			zc->type_string = "CEX7P";
			zc->speed_rating = CEX7P_SPEED_IDX;
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
		} else {
			zc->type_string = "CEX8P";
			zc->speed_rating = CEX8P_SPEED_IDX;
			/* wrong user space type, just for compatibility
			 * with the ZCRYPT_STATUS_MASK ioctl.
			 */
			zc->user_space_type = ZCRYPT_CEX6;
			zc->speed_rating = CEX7P_SPEED_IDX;
		}
		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
@@ -563,7 +594,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
}

/*
 * This is called to remove the CEX4/CEX5/CEX6/CEX7 card driver
 * This is called to remove the CEX[45678] card driver
 * information if an AP card device is removed.
 */
static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
@@ -587,7 +618,7 @@ static struct ap_driver zcrypt_cex4_card_driver = {
};

/*
 * Probe function for CEX4/CEX5/CEX6/CEX7 queue device. It always
 * Probe function for CEX[45678] queue device. It always
 * accepts the AP device since the bus_match already checked
 * the hardware type.
 * @ap_dev: pointer to the AP device.
@@ -653,7 +684,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
}

/*
 * This is called to remove the CEX4/CEX5/CEX6/CEX7 queue driver
 * This is called to remove the CEX[45678] queue driver
 * information if an AP queue device is removed.
 */
static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)