Skip to content

Commit

Permalink
s390/zcrypt: fix reply buffer calculations for CCA replies
Browse files Browse the repository at this point in the history
commit 4cfca53 upstream.

The length information for available buffer space for CCA
replies is covered with two fields in the T6 header prepended
on each CCA reply: fromcardlen1 and fromcardlen2. The sum of
these both values must not exceed the AP bus limit for this
card (24KB for CEX8, 12KB CEX7 and older) minus the always
present headers.

The current code adjusted the fromcardlen2 value in case
of exceeding the AP bus limit when there was a non-zero
value given from userspace. Some tests now showed that this
was the wrong assumption. Instead the userspace value given for
this field should always be trusted and if the sum of the
two fields exceeds the AP bus limit for this card the first
field fromcardlen1 should be adjusted instead.

So now the calculation is done with this new insight in mind.
Also some additional checks for overflow have been introduced
and some comments to provide some documentation for future
maintainers of this complicated calculation code.

Furthermore the 128 bytes of fix overhead which is used
in the current code is not correct. Investigations showed
that for a reply always the same two header structs are
prepended before a possible payload. So this is also fixed
with this patch.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
hfreude authored and gregkh committed Jul 27, 2023
1 parent 4a3d22e commit 9e12b9c
Showing 1 changed file with 24 additions and 11 deletions.
35 changes: 24 additions & 11 deletions drivers/s390/crypto/zcrypt_msgtype6.c
Expand Up @@ -1111,23 +1111,36 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
struct ica_xcRB *xcrb,
struct ap_message *ap_msg)
{
int rc;
struct response_type *rtype = ap_msg->private;
struct {
struct type6_hdr hdr;
struct CPRBX cprbx;
/* ... more data blocks ... */
} __packed * msg = ap_msg->msg;

/*
* Set the queue's reply buffer length minus 128 byte padding
* as reply limit for the card firmware.
*/
msg->hdr.fromcardlen1 = min_t(unsigned int, msg->hdr.fromcardlen1,
zq->reply.bufsize - 128);
if (msg->hdr.fromcardlen2)
msg->hdr.fromcardlen2 =
zq->reply.bufsize - msg->hdr.fromcardlen1 - 128;
unsigned int max_payload_size;
int rc, delta;

/* calculate maximum payload for this card and msg type */
max_payload_size = zq->reply.bufsize - sizeof(struct type86_fmt2_msg);

/* limit each of the two from fields to the maximum payload size */
msg->hdr.fromcardlen1 = min(msg->hdr.fromcardlen1, max_payload_size);
msg->hdr.fromcardlen2 = min(msg->hdr.fromcardlen2, max_payload_size);

/* calculate delta if the sum of both exceeds max payload size */
delta = msg->hdr.fromcardlen1 + msg->hdr.fromcardlen2
- max_payload_size;
if (delta > 0) {
/*
* Sum exceeds maximum payload size, prune fromcardlen1
* (always trust fromcardlen2)
*/
if (delta > msg->hdr.fromcardlen1) {
rc = -EINVAL;
goto out;
}
msg->hdr.fromcardlen1 -= delta;
}

init_completion(&rtype->work);
rc = ap_queue_message(zq->queue, ap_msg);
Expand Down

0 comments on commit 9e12b9c

Please sign in to comment.