crypto: propagate errors from TLS session I/O callbacks

GNUTLS doesn't know how to perform I/O on anything other than plain
FDs, so the TLS session provides it with some I/O callbacks. The
GNUTLS API design requires these callbacks to return a unix errno
value, which means we're currently loosing the useful QEMU "Error"
object.

This changes the I/O callbacks in QEMU to stash the "Error" object
in the QCryptoTLSSession class, and fetch it when seeing an I/O
error returned from GNUTLS, thus preserving useful error messages.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2024-03-15 14:29:11 +00:00
parent 57941c9c86
commit 97f7bf113e
4 changed files with 108 additions and 26 deletions

View file

@ -28,17 +28,16 @@
static ssize_t qio_channel_tls_write_handler(const char *buf,
size_t len,
void *opaque)
void *opaque,
Error **errp)
{
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
ssize_t ret;
ret = qio_channel_write(tioc->master, buf, len, NULL);
ret = qio_channel_write(tioc->master, buf, len, errp);
if (ret == QIO_CHANNEL_ERR_BLOCK) {
errno = EAGAIN;
return -1;
return QCRYPTO_TLS_SESSION_ERR_BLOCK;
} else if (ret < 0) {
errno = EIO;
return -1;
}
return ret;
@ -46,17 +45,16 @@ static ssize_t qio_channel_tls_write_handler(const char *buf,
static ssize_t qio_channel_tls_read_handler(char *buf,
size_t len,
void *opaque)
void *opaque,
Error **errp)
{
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
ssize_t ret;
ret = qio_channel_read(tioc->master, buf, len, NULL);
ret = qio_channel_read(tioc->master, buf, len, errp);
if (ret == QIO_CHANNEL_ERR_BLOCK) {
errno = EAGAIN;
return -1;
return QCRYPTO_TLS_SESSION_ERR_BLOCK;
} else if (ret < 0) {
errno = EIO;
return -1;
}
return ret;