* [PULL 1/8] seccomp: report EPERM instead of killing process for spawn set
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 2/8] chardev: lower priority of the HUP GSource in socket chardev Daniel P. Berrangé
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel; +Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini
When something tries to run one of the spawn syscalls (eg clone),
our seccomp deny filter is set to cause a fatal trap which kills
the process.
This is found to be unhelpful when QEMU has loaded the nvidia
GL library. This tries to spawn a process to modprobe the nvidia
kmod. This is a dubious thing to do, but at the same time, the
code will gracefully continue if this fails. Our seccomp filter
rightly blocks the spawning, but prevent the graceful continue.
Switching to reporting EPERM will make QEMU behave more gracefully
without impacting the level of protect we have.
https://gitlab.com/qemu-project/qemu/-/issues/2116
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
system/qemu-seccomp.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/system/qemu-seccomp.c b/system/qemu-seccomp.c
index 4d7439e7f7..98ffce075c 100644
--- a/system/qemu-seccomp.c
+++ b/system/qemu-seccomp.c
@@ -74,7 +74,7 @@ const struct scmp_arg_cmp sched_setscheduler_arg[] = {
#define RULE_CLONE_FLAG(flag) \
{ SCMP_SYS(clone), QEMU_SECCOMP_SET_SPAWN, \
- ARRAY_SIZE(clone_arg ## flag), clone_arg ## flag, SCMP_ACT_TRAP }
+ ARRAY_SIZE(clone_arg ## flag), clone_arg ## flag, SCMP_ACT_ERRNO(EPERM) }
/* If no CLONE_* flags are set, except CSIGNAL, deny */
const struct scmp_arg_cmp clone_arg_none[] = {
@@ -214,13 +214,13 @@ static const struct QemuSeccompSyscall denylist[] = {
0, NULL, SCMP_ACT_TRAP },
/* spawn */
{ SCMP_SYS(fork), QEMU_SECCOMP_SET_SPAWN,
- 0, NULL, SCMP_ACT_TRAP },
+ 0, NULL, SCMP_ACT_ERRNO(EPERM) },
{ SCMP_SYS(vfork), QEMU_SECCOMP_SET_SPAWN,
- 0, NULL, SCMP_ACT_TRAP },
+ 0, NULL, SCMP_ACT_ERRNO(EPERM) },
{ SCMP_SYS(execve), QEMU_SECCOMP_SET_SPAWN,
- 0, NULL, SCMP_ACT_TRAP },
+ 0, NULL, SCMP_ACT_ERRNO(EPERM) },
{ SCMP_SYS(clone), QEMU_SECCOMP_SET_SPAWN,
- ARRAY_SIZE(clone_arg_none), clone_arg_none, SCMP_ACT_TRAP },
+ ARRAY_SIZE(clone_arg_none), clone_arg_none, SCMP_ACT_ERRNO(EPERM) },
RULE_CLONE_FLAG(CLONE_VM),
RULE_CLONE_FLAG(CLONE_FS),
RULE_CLONE_FLAG(CLONE_FILES),
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 2/8] chardev: lower priority of the HUP GSource in socket chardev
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 1/8] seccomp: report EPERM instead of killing process for spawn set Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 3/8] Revert "chardev/char-socket: Fix TLS io channels sending too much data to the backend" Daniel P. Berrangé
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Thomas Huth
The socket chardev often has 2 GSource object registered against the
same FD. One is registered all the time and is just intended to handle
POLLHUP events, while the other gets registered & unregistered on the
fly as the frontend is ready to receive more data or not.
It is very common for poll() to signal a POLLHUP event at the same time
as there is pending incoming data from the disconnected client. It is
therefore essential to process incoming data prior to processing HUP.
The problem with having 2 GSource on the same FD is that there is no
guaranteed ordering of execution between them, so the chardev code may
process HUP first and thus discard data.
This failure scenario is non-deterministic but can be seen fairly
reliably by reverting a7077b8e354d90fec26c2921aa2dea85b90dff90, and
then running 'tests/unit/test-char', which will sometimes fail with
missing data.
Ideally QEMU would only have 1 GSource, but that's a complex code
refactoring job. The next best solution is to try to ensure ordering
between the 2 GSource objects. This can be achieved by lowering the
priority of the HUP GSource, so that it is never dispatched if the
main GSource is also ready to dispatch. Counter-intuitively, lowering
the priority of a GSource is done by raising its priority number.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
chardev/char-socket.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 8a0406cc1e..2c4dffc0e6 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -601,6 +601,22 @@ static void update_ioc_handlers(SocketChardev *s)
remove_hup_source(s);
s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
+ /*
+ * poll() is liable to return POLLHUP even when there is
+ * still incoming data available to read on the FD. If
+ * we have the hup_source at the same priority as the
+ * main io_add_watch_poll GSource, then we might end up
+ * processing the POLLHUP event first, closing the FD,
+ * and as a result silently discard data we should have
+ * read.
+ *
+ * By setting the hup_source to G_PRIORITY_DEFAULT + 1,
+ * we ensure that io_add_watch_poll GSource will always
+ * be dispatched first, thus guaranteeing we will be
+ * able to process all incoming data before closing the
+ * FD
+ */
+ g_source_set_priority(s->hup_source, G_PRIORITY_DEFAULT + 1);
g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
chr, NULL);
g_source_attach(s->hup_source, chr->gcontext);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 3/8] Revert "chardev/char-socket: Fix TLS io channels sending too much data to the backend"
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 1/8] seccomp: report EPERM instead of killing process for spawn set Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 2/8] chardev: lower priority of the HUP GSource in socket chardev Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 4/8] Revert "chardev: use a child source for qio input source" Daniel P. Berrangé
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Thomas Huth
This commit results in unexpected termination of the TLS connection.
When 'fd_can_read' returns 0, the code goes on to pass a zero length
buffer to qio_channel_read. The TLS impl calls into gnutls_recv()
with this zero length buffer, at which point GNUTLS returns an error
GNUTLS_E_INVALID_REQUEST. This is treated as fatal by QEMU's TLS code
resulting in the connection being torn down by the chardev.
Simply skipping the qio_channel_read when the buffer length is zero
is also not satisfactory, as it results in a high CPU burn busy loop
massively slowing QEMU's functionality.
The proper solution is to avoid tcp_chr_read being called at all
unless the frontend is able to accept more data. This will be done
in a followup commit.
This reverts commit 462945cd22d2bcd233401ed3aa167d83a8e35b05
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
chardev/char-socket.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 2c4dffc0e6..812d7aa38a 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -496,9 +496,9 @@ static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
s->max_size <= 0) {
return TRUE;
}
- len = tcp_chr_read_poll(opaque);
- if (len > sizeof(buf)) {
- len = sizeof(buf);
+ len = sizeof(buf);
+ if (len > s->max_size) {
+ len = s->max_size;
}
size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0 || (size == -1 && errno != EAGAIN)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 4/8] Revert "chardev: use a child source for qio input source"
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (2 preceding siblings ...)
2024-03-19 20:21 ` [PULL 3/8] Revert "chardev/char-socket: Fix TLS io channels sending too much data to the backend" Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 5/8] crypto: factor out conversion of QAPI to gcrypt constants Daniel P. Berrangé
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Thomas Huth
This reverts commit a7077b8e354d90fec26c2921aa2dea85b90dff90,
and add comments to explain why child sources cannot be used.
When a GSource is added as a child of another GSource, if its
'prepare' function indicates readiness, then the parent's
'prepare' function will never be run. The io_watch_poll_prepare
absolutely *must* be run on every iteration of the main loop,
to ensure that the chardev backend doesn't feed data to the
frontend that it is unable to consume.
At the time a7077b8e354d90fec26c2921aa2dea85b90dff90 was made,
all the child GSource impls were relying on poll'ing an FD,
so their 'prepare' functions would never indicate readiness
ahead of poll() being invoked. So the buggy behaviour was
not noticed and lay dormant.
Relatively recently the QIOChannelTLS impl introduced a
level 2 child GSource, which checks with GNUTLS whether it
has cached any data that was decoded but not yet consumed:
commit ffda5db65aef42266a5053a4be34515106c4c7ee
Author: Antoine Damhet <antoine.damhet@shadow.tech>
Date: Tue Nov 15 15:23:29 2022 +0100
io/channel-tls: fix handling of bigger read buffers
Since the TLS backend can read more data from the underlying QIOChannel
we introduce a minimal child GSource to notify if we still have more
data available to be read.
Signed-off-by: Antoine Damhet <antoine.damhet@shadow.tech>
Signed-off-by: Charles Frey <charles.frey@shadow.tech>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
With this, it is now quite common for the 'prepare' function
on a QIOChannelTLS GSource to indicate immediate readiness,
bypassing the parent GSource 'prepare' function. IOW, the
critical 'io_watch_poll_prepare' is being skipped on some
iterations of the main loop. As a result chardev frontend
asserts are now being triggered as they are fed data they
are not ready to consume.
A reproducer is as follows:
* In terminal 1 run a GNUTLS *echo* server
$ gnutls-serv --echo \
--x509cafile ca-cert.pem \
--x509keyfile server-key.pem \
--x509certfile server-cert.pem \
-p 9000
* In terminal 2 run a QEMU guest
$ qemu-system-s390x \
-nodefaults \
-display none \
-object tls-creds-x509,id=tls0,dir=$PWD,endpoint=client \
-chardev socket,id=con0,host=localhost,port=9000,tls-creds=tls0 \
-device sclpconsole,chardev=con0 \
-hda Fedora-Cloud-Base-39-1.5.s390x.qcow2
After the previous patch revert, but before this patch revert,
this scenario will crash:
qemu-system-s390x: ../hw/char/sclpconsole.c:73: chr_read: Assertion
`size <= SIZE_BUFFER_VT220 - scon->iov_data_len' failed.
This assert indicates that 'tcp_chr_read' was called without
'tcp_chr_read_poll' having first been checked for ability to
receive more data
QEMU's use of a 'prepare' function to create/delete another
GSource is rather a hack and not normally the kind of thing that
is expected to be done by a GSource. There is no mechanism to
force GLib to always run the 'prepare' function of a parent
GSource. The best option is to simply not use the child source
concept, and go back to the functional approach previously
relied on.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
chardev/char-io.c | 56 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 51 insertions(+), 5 deletions(-)
diff --git a/chardev/char-io.c b/chardev/char-io.c
index 4451128cba..dab77b112e 100644
--- a/chardev/char-io.c
+++ b/chardev/char-io.c
@@ -33,6 +33,7 @@ typedef struct IOWatchPoll {
IOCanReadHandler *fd_can_read;
GSourceFunc fd_read;
void *opaque;
+ GMainContext *context;
} IOWatchPoll;
static IOWatchPoll *io_watch_poll_from_source(GSource *source)
@@ -50,28 +51,59 @@ static gboolean io_watch_poll_prepare(GSource *source,
return FALSE;
}
+ /*
+ * We do not register the QIOChannel watch as a child GSource.
+ * The 'prepare' function on the parent GSource will be
+ * skipped if a child GSource's 'prepare' function indicates
+ * readiness. We need this prepare function be guaranteed
+ * to run on *every* iteration of the main loop, because
+ * it is critical to ensure we remove the QIOChannel watch
+ * if 'fd_can_read' indicates the frontend cannot receive
+ * more data.
+ */
if (now_active) {
iwp->src = qio_channel_create_watch(
iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
- g_source_add_child_source(source, iwp->src);
- g_source_unref(iwp->src);
+ g_source_attach(iwp->src, iwp->context);
} else {
- g_source_remove_child_source(source, iwp->src);
+ g_source_destroy(iwp->src);
+ g_source_unref(iwp->src);
iwp->src = NULL;
}
return FALSE;
}
+static gboolean io_watch_poll_check(GSource *source)
+{
+ return FALSE;
+}
+
static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
gpointer user_data)
{
- return G_SOURCE_CONTINUE;
+ abort();
+}
+
+static void io_watch_poll_finalize(GSource *source)
+{
+ /*
+ * Due to a glib bug, removing the last reference to a source
+ * inside a finalize callback causes recursive locking (and a
+ * deadlock). This is not a problem inside other callbacks,
+ * including dispatch callbacks, so we call io_remove_watch_poll
+ * to remove this source. At this point, iwp->src must
+ * be NULL, or we would leak it.
+ */
+ IOWatchPoll *iwp = io_watch_poll_from_source(source);
+ assert(iwp->src == NULL);
}
static GSourceFuncs io_watch_poll_funcs = {
.prepare = io_watch_poll_prepare,
+ .check = io_watch_poll_check,
.dispatch = io_watch_poll_dispatch,
+ .finalize = io_watch_poll_finalize,
};
GSource *io_add_watch_poll(Chardev *chr,
@@ -91,6 +123,7 @@ GSource *io_add_watch_poll(Chardev *chr,
iwp->ioc = ioc;
iwp->fd_read = (GSourceFunc) fd_read;
iwp->src = NULL;
+ iwp->context = context;
name = g_strdup_printf("chardev-iowatch-%s", chr->label);
g_source_set_name((GSource *)iwp, name);
@@ -101,10 +134,23 @@ GSource *io_add_watch_poll(Chardev *chr,
return (GSource *)iwp;
}
+static void io_remove_watch_poll(GSource *source)
+{
+ IOWatchPoll *iwp;
+
+ iwp = io_watch_poll_from_source(source);
+ if (iwp->src) {
+ g_source_destroy(iwp->src);
+ g_source_unref(iwp->src);
+ iwp->src = NULL;
+ }
+ g_source_destroy(&iwp->parent);
+}
+
void remove_fd_in_watch(Chardev *chr)
{
if (chr->gsource) {
- g_source_destroy(chr->gsource);
+ io_remove_watch_poll(chr->gsource);
chr->gsource = NULL;
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 5/8] crypto: factor out conversion of QAPI to gcrypt constants
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (3 preceding siblings ...)
2024-03-19 20:21 ` [PULL 4/8] Revert "chardev: use a child source for qio input source" Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 6/8] crypto: query gcrypt for cipher availability Daniel P. Berrangé
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Philippe Mathieu-Daudé, Thomas Huth
The conversion of cipher mode will shortly be required in more
than one place.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
crypto/cipher-gcrypt.c.inc | 116 +++++++++++++++++++------------------
1 file changed, 60 insertions(+), 56 deletions(-)
diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
index 1377cbaf14..6b82280f90 100644
--- a/crypto/cipher-gcrypt.c.inc
+++ b/crypto/cipher-gcrypt.c.inc
@@ -20,6 +20,56 @@
#include <gcrypt.h>
+static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg)
+{
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_DES:
+ return GCRY_CIPHER_DES;
+ case QCRYPTO_CIPHER_ALG_3DES:
+ return GCRY_CIPHER_3DES;
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ return GCRY_CIPHER_AES128;
+ case QCRYPTO_CIPHER_ALG_AES_192:
+ return GCRY_CIPHER_AES192;
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ return GCRY_CIPHER_AES256;
+ case QCRYPTO_CIPHER_ALG_CAST5_128:
+ return GCRY_CIPHER_CAST5;
+ case QCRYPTO_CIPHER_ALG_SERPENT_128:
+ return GCRY_CIPHER_SERPENT128;
+ case QCRYPTO_CIPHER_ALG_SERPENT_192:
+ return GCRY_CIPHER_SERPENT192;
+ case QCRYPTO_CIPHER_ALG_SERPENT_256:
+ return GCRY_CIPHER_SERPENT256;
+ case QCRYPTO_CIPHER_ALG_TWOFISH_128:
+ return GCRY_CIPHER_TWOFISH128;
+ case QCRYPTO_CIPHER_ALG_TWOFISH_256:
+ return GCRY_CIPHER_TWOFISH;
+#ifdef CONFIG_CRYPTO_SM4
+ case QCRYPTO_CIPHER_ALG_SM4:
+ return GCRY_CIPHER_SM4;
+#endif
+ default:
+ return GCRY_CIPHER_NONE;
+ }
+}
+
+static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode)
+{
+ switch (mode) {
+ case QCRYPTO_CIPHER_MODE_ECB:
+ return GCRY_CIPHER_MODE_ECB;
+ case QCRYPTO_CIPHER_MODE_XTS:
+ return GCRY_CIPHER_MODE_XTS;
+ case QCRYPTO_CIPHER_MODE_CBC:
+ return GCRY_CIPHER_MODE_CBC;
+ case QCRYPTO_CIPHER_MODE_CTR:
+ return GCRY_CIPHER_MODE_CTR;
+ default:
+ return GCRY_CIPHER_MODE_NONE;
+ }
+}
+
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
@@ -188,72 +238,26 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
return NULL;
}
- switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES:
- gcryalg = GCRY_CIPHER_DES;
- break;
- case QCRYPTO_CIPHER_ALG_3DES:
- gcryalg = GCRY_CIPHER_3DES;
- break;
- case QCRYPTO_CIPHER_ALG_AES_128:
- gcryalg = GCRY_CIPHER_AES128;
- break;
- case QCRYPTO_CIPHER_ALG_AES_192:
- gcryalg = GCRY_CIPHER_AES192;
- break;
- case QCRYPTO_CIPHER_ALG_AES_256:
- gcryalg = GCRY_CIPHER_AES256;
- break;
- case QCRYPTO_CIPHER_ALG_CAST5_128:
- gcryalg = GCRY_CIPHER_CAST5;
- break;
- case QCRYPTO_CIPHER_ALG_SERPENT_128:
- gcryalg = GCRY_CIPHER_SERPENT128;
- break;
- case QCRYPTO_CIPHER_ALG_SERPENT_192:
- gcryalg = GCRY_CIPHER_SERPENT192;
- break;
- case QCRYPTO_CIPHER_ALG_SERPENT_256:
- gcryalg = GCRY_CIPHER_SERPENT256;
- break;
- case QCRYPTO_CIPHER_ALG_TWOFISH_128:
- gcryalg = GCRY_CIPHER_TWOFISH128;
- break;
- case QCRYPTO_CIPHER_ALG_TWOFISH_256:
- gcryalg = GCRY_CIPHER_TWOFISH;
- break;
-#ifdef CONFIG_CRYPTO_SM4
- case QCRYPTO_CIPHER_ALG_SM4:
- gcryalg = GCRY_CIPHER_SM4;
- break;
-#endif
- default:
+ gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg);
+ if (gcryalg == GCRY_CIPHER_NONE) {
error_setg(errp, "Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_str(alg));
return NULL;
}
- drv = &qcrypto_gcrypt_driver;
- switch (mode) {
- case QCRYPTO_CIPHER_MODE_ECB:
- gcrymode = GCRY_CIPHER_MODE_ECB;
- break;
- case QCRYPTO_CIPHER_MODE_XTS:
- gcrymode = GCRY_CIPHER_MODE_XTS;
- break;
- case QCRYPTO_CIPHER_MODE_CBC:
- gcrymode = GCRY_CIPHER_MODE_CBC;
- break;
- case QCRYPTO_CIPHER_MODE_CTR:
- drv = &qcrypto_gcrypt_ctr_driver;
- gcrymode = GCRY_CIPHER_MODE_CTR;
- break;
- default:
+ gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode);
+ if (gcrymode == GCRY_CIPHER_MODE_NONE) {
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_str(mode));
return NULL;
}
+ if (mode == QCRYPTO_CIPHER_MODE_CTR) {
+ drv = &qcrypto_gcrypt_ctr_driver;
+ } else {
+ drv = &qcrypto_gcrypt_driver;
+ }
+
ctx = g_new0(QCryptoCipherGcrypt, 1);
ctx->base.driver = drv;
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 6/8] crypto: query gcrypt for cipher availability
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (4 preceding siblings ...)
2024-03-19 20:21 ` [PULL 5/8] crypto: factor out conversion of QAPI to gcrypt constants Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 7/8] crypto: use error_abort for unexpected failures Daniel P. Berrangé
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Philippe Mathieu-Daudé, Thomas Huth
Just because a cipher is defined in the gcrypt header file, does not
imply that it can be used. Distros can filter the list of ciphers when
building gcrypt. For example, RHEL-9 disables the SM4 cipher. It is
also possible that running in FIPS mode might dynamically change what
ciphers are available at runtime.
qcrypto_cipher_supports must therefore query gcrypt directly to check
for cipher availability.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
crypto/cipher-gcrypt.c.inc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
index 6b82280f90..4a8314746d 100644
--- a/crypto/cipher-gcrypt.c.inc
+++ b/crypto/cipher-gcrypt.c.inc
@@ -93,6 +93,11 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
return false;
}
+ if (gcry_cipher_algo_info(qcrypto_cipher_alg_to_gcry_alg(alg),
+ GCRYCTL_TEST_ALGO, NULL, NULL) != 0) {
+ return false;
+ }
+
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
case QCRYPTO_CIPHER_MODE_CBC:
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 7/8] crypto: use error_abort for unexpected failures
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (5 preceding siblings ...)
2024-03-19 20:21 ` [PULL 6/8] crypto: query gcrypt for cipher availability Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-19 20:21 ` [PULL 8/8] crypto: report which ciphers are being skipped during tests Daniel P. Berrangé
2024-03-20 15:04 ` [PULL 0/8] Misc fixes patches Peter Maydell
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Philippe Mathieu-Daudé, Thomas Huth
This improves the error diagnosis from the unit test when a cipher
is unexpected not available from
ERROR:../tests/unit/test-crypto-cipher.c:683:test_cipher: assertion failed: (err == NULL)
Bail out! ERROR:../tests/unit/test-crypto-cipher.c:683:test_cipher: assertion failed: (err == NULL)
Aborted (core dumped)
to
Unexpected error in qcrypto_cipher_ctx_new() at ../crypto/cipher-gcrypt.c.inc:262:
./build//tests/unit/test-crypto-cipher: Cannot initialize cipher: Invalid cipher algorithm
Aborted (core dumped)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tests/unit/test-crypto-cipher.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c
index 11ab1a54fc..d0ea7b4d8e 100644
--- a/tests/unit/test-crypto-cipher.c
+++ b/tests/unit/test-crypto-cipher.c
@@ -676,9 +676,8 @@ static void test_cipher(const void *opaque)
cipher = qcrypto_cipher_new(
data->alg, data->mode,
key, nkey,
- &err);
+ data->plaintext ? &error_abort : &err);
if (data->plaintext) {
- g_assert(err == NULL);
g_assert(cipher != NULL);
} else {
error_free_or_abort(&err);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PULL 8/8] crypto: report which ciphers are being skipped during tests
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (6 preceding siblings ...)
2024-03-19 20:21 ` [PULL 7/8] crypto: use error_abort for unexpected failures Daniel P. Berrangé
@ 2024-03-19 20:21 ` Daniel P. Berrangé
2024-03-20 15:04 ` [PULL 0/8] Misc fixes patches Peter Maydell
8 siblings, 0 replies; 10+ messages in thread
From: Daniel P. Berrangé @ 2024-03-19 20:21 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Philippe Mathieu-Daudé, Thomas Huth
Since the ciphers can be dynamically disabled at runtime, when running
unit tests it is helpful to report which ciphers we can skipped for
testing.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tests/unit/test-crypto-cipher.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c
index d0ea7b4d8e..f5152e569d 100644
--- a/tests/unit/test-crypto-cipher.c
+++ b/tests/unit/test-crypto-cipher.c
@@ -821,6 +821,10 @@ int main(int argc, char **argv)
for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
if (qcrypto_cipher_supports(test_data[i].alg, test_data[i].mode)) {
g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
+ } else {
+ g_printerr("# skip unsupported %s:%s\n",
+ QCryptoCipherAlgorithm_str(test_data[i].alg),
+ QCryptoCipherMode_str(test_data[i].mode));
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PULL 0/8] Misc fixes patches
2024-03-19 20:21 [PULL 0/8] Misc fixes patches Daniel P. Berrangé
` (7 preceding siblings ...)
2024-03-19 20:21 ` [PULL 8/8] crypto: report which ciphers are being skipped during tests Daniel P. Berrangé
@ 2024-03-20 15:04 ` Peter Maydell
8 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2024-03-20 15:04 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: qemu-devel, Marc-André Lureau, Paolo Bonzini
On Tue, 19 Mar 2024 at 20:22, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> The following changes since commit c62d54d0a8067ffb3d5b909276f7296d7df33fa7:
>
> Update version for v9.0.0-rc0 release (2024-03-19 19:13:52 +0000)
>
> are available in the Git repository at:
>
> https://gitlab.com/berrange/qemu tags/misc-fixes-pull-request
>
> for you to fetch changes up to c3b1aa1c1ae66e0174704072b1fb7d10d6e4a4b7:
>
> crypto: report which ciphers are being skipped during tests (2024-03-19 20:17:12 +0000)
>
> ----------------------------------------------------------------
> * Use EPERM for seccomp filter instead of killing QEMU when
> an attempt to spawn child process is made
> * Reduce priority of POLLHUP handling for socket chardevs
> to increase likelihood of pending data being processed
> * Fix chardev I/O main loop integration when TLS is enabled
> * Fix broken crypto test suite when distro disables
> SM4 algorithm
> * Improve diagnosis of failed crypto tests
>
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/9.0
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 10+ messages in thread