Skip to content

Commit 12aea56

Browse files
author
Mete Durlu
committed
s390/ap: Fix CCA crypto card behavior within protected execution environment
JIRA: https://issues.redhat.com/browse/RHEL-62840 Upstream status: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Tested: by IBM Build-Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=65269984 Conflicts: Code changes necessary to adapt to existing differences to upstream - no functional change commit 78f636e A crypto card comes in 3 flavors: accelerator, CCA co-processor or EP11 co-processor. Within a protected execution environment only the accelerator and EP11 co-processor is supported. However, it is possible to set up a KVM guest with a CCA card and run it as a protected execution guest. There is nothing at the host side which prevents this. Within such a guest, a CCA card is shown as "illicit" and you can't do anything with such a crypto card. Regardless of the unsupported CCA card within a protected execution guest there are a couple of user space applications which unconditional try to run crypto requests to the zcrypt device driver. There was a bug within the AP bus code which allowed such a request to be forwarded to a CCA card where it is finally rejected and the driver reacts with -ENODEV but also triggers an AP bus scan. Together with a retry loop this caused some kind of "hang" of the KVM guest. On startup it caused timeouts and finally led the KVM guest startup fail. Fix that by closing the gap and make sure a CCA card is not usable within a protected execution environment. Another behavior within an protected execution environment with CCA cards was that the se_bind and se_associate AP queue sysfs attributes where shown. The implementation unconditional always added these attributes. Fix that by checking if the card mode is supported within a protected execution environment and only if valid, add the attribute group. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Mete Durlu <mdurlu@redhat.com>
1 parent 181997d commit 12aea56

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

drivers/s390/crypto/ap_bus.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,13 +1876,12 @@ static inline void ap_scan_domains(struct ap_card *ac)
18761876
}
18771877
/* if no queue device exists, create a new one */
18781878
if (!aq) {
1879-
aq = ap_queue_create(qid, ac->ap_dev.device_type);
1879+
aq = ap_queue_create(qid, ac);
18801880
if (!aq) {
18811881
AP_DBF_WARN("%s(%d,%d) ap_queue_create() failed\n",
18821882
__func__, ac->id, dom);
18831883
continue;
18841884
}
1885-
aq->card = ac;
18861885
aq->config = !decfg;
18871886
aq->chkstop = chkstop;
18881887
aq->se_bstate = hwinfo.bs;

drivers/s390/crypto/ap_bus.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ int ap_test_config_usage_domain(unsigned int domain);
272272
int ap_test_config_ctrl_domain(unsigned int domain);
273273

274274
void ap_queue_init_reply(struct ap_queue *aq, struct ap_message *ap_msg);
275-
struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
275+
struct ap_queue *ap_queue_create(ap_qid_t qid, struct ap_card *ac);
276276
void ap_queue_prepare_remove(struct ap_queue *aq);
277277
void ap_queue_remove(struct ap_queue *aq);
278278
void ap_queue_init_state(struct ap_queue *aq);

drivers/s390/crypto/ap_queue.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ static void __ap_flush_queue(struct ap_queue *aq);
2222
* some AP queue helper functions
2323
*/
2424

25+
static inline bool ap_q_supported_in_se(struct ap_queue *aq)
26+
{
27+
return aq->card->hwinfo.ep11 || aq->card->hwinfo.accel;
28+
}
29+
2530
static inline bool ap_q_supports_bind(struct ap_queue *aq)
2631
{
2732
return aq->card->hwinfo.ep11 || aq->card->hwinfo.accel;
@@ -1104,18 +1109,19 @@ static void ap_queue_device_release(struct device *dev)
11041109
kfree(aq);
11051110
}
11061111

1107-
struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
1112+
struct ap_queue *ap_queue_create(ap_qid_t qid, struct ap_card *ac)
11081113
{
11091114
struct ap_queue *aq;
11101115

11111116
aq = kzalloc(sizeof(*aq), GFP_KERNEL);
11121117
if (!aq)
11131118
return NULL;
1119+
aq->card = ac;
11141120
aq->ap_dev.device.release = ap_queue_device_release;
11151121
aq->ap_dev.device.type = &ap_queue_type;
1116-
aq->ap_dev.device_type = device_type;
1117-
// add optional SE secure binding attributes group
1118-
if (ap_sb_available() && is_prot_virt_guest())
1122+
aq->ap_dev.device_type = ac->ap_dev.device_type;
1123+
/* in SE environment add bind/associate attributes group */
1124+
if (ap_is_se_guest() && ap_q_supported_in_se(aq))
11191125
aq->ap_dev.device.groups = ap_queue_dev_sb_attr_groups;
11201126
aq->qid = qid;
11211127
spin_lock_init(&aq->lock);
@@ -1196,10 +1202,16 @@ bool ap_queue_usable(struct ap_queue *aq)
11961202
}
11971203

11981204
/* SE guest's queues additionally need to be bound */
1199-
if (ap_q_needs_bind(aq) &&
1200-
!(aq->se_bstate == AP_BS_Q_USABLE ||
1201-
aq->se_bstate == AP_BS_Q_USABLE_NO_SECURE_KEY))
1202-
rc = false;
1205+
if (ap_is_se_guest()) {
1206+
if (!ap_q_supported_in_se(aq)) {
1207+
rc = false;
1208+
goto unlock_and_out;
1209+
}
1210+
if (ap_q_needs_bind(aq) &&
1211+
!(aq->se_bstate == AP_BS_Q_USABLE ||
1212+
aq->se_bstate == AP_BS_Q_USABLE_NO_SECURE_KEY))
1213+
rc = false;
1214+
}
12031215

12041216
unlock_and_out:
12051217
spin_unlock_bh(&aq->lock);

0 commit comments

Comments
 (0)