On Fri, Oct 31, 2025 at 03:23:51PM +0400, Marc-André Lureau wrote:
> Hi
> 
> On Thu, Oct 30, 2025 at 6:49 PM Daniel P. Berrangé <[email protected]>
> wrote:
> 
> > The gnutls_credentials_set() method has a very suprising API contract
> > that requires the caller to preserve the passed in credentials pointer
> > for as long as the gnutls_session_t object is alive. QEMU is failing
> > to ensure this happens.
> >
> > In QEMU the GNUTLS credentials object is owned by the QCryptoTLSCreds
> > object instance while the GNUTLS session object is owned by the
> > QCryptoTLSSession object instance. Their lifetimes are not guaranteed
> > to be the same, though in most common usage the credentials will outlive
> > the session. This is notably not the case, however, after the VNC server
> > gained the ability to reload credentials on the fly with:
> >
> >   commit 1f08e3415120637cad7f540d9ceb4dba3136dbdd
> >   Author: Zihao Chang <[email protected]>
> >   Date:   Tue Mar 16 15:58:44 2021 +0800
> >
> >     vnc: support reload x509 certificates for vnc
> >
> > If that is triggered while a VNC client is in the middle of performing
> > a TLS handshake, we might hit a use-after-free.
> >
> > It is difficult to correct this problem because there's no way to deep-
> > clone a GNUTLS credentials object, nor is it reference counted. Thus we
> > introduce a QCryptoTLSCredsBox object whose only purpose is to add
> > reference counting around the GNUTLS credentials object.
> >
> > The DH parameters set against a credentials object also have to be kept
> > alive for as long as the credentials exist. So the box must also hold
> > the DH parameters pointer.
> >
> > Signed-off-by: Daniel P. Berrangé <[email protected]>
> >
> 
> Reviewed-by: Marc-André Lureau <[email protected]>


> > +#ifndef QCRYPTO_TLSCREDS_BOX_H
> > +#define QCRYPTO_TLSCREDS_BOX_H
> > +
> > +#include "qom/object.h"
> > +
> > +#ifdef CONFIG_GNUTLS
> > +#include <gnutls/gnutls.h>
> > +#endif
> > +
> > +typedef struct QCryptoTLSCredsBox QCryptoTLSCredsBox;
> > +
> > +struct QCryptoTLSCredsBox {
> > +    uint32_t ref;
> > +    bool server;
> > +    int type;
> > +    union {
> > +        void *any;
> >
> 
> since any is used in code to cast the variant to a void *, it may be worth
> a comment to say that all fields are expected to be pointers.

Yep, in practice almost all gnutls _t types are pointers, but
I'll explain that here since it is not obvious to casual
observers.

> 
> 
> > +#ifdef CONFIG_GNUTLS
> > +        gnutls_anon_server_credentials_t anonserver;
> > +        gnutls_anon_client_credentials_t anonclient;
> > +        gnutls_psk_server_credentials_t pskserver;
> > +        gnutls_psk_client_credentials_t pskclient;
> > +        gnutls_certificate_credentials_t cert;
> > +#endif
> > +    } data;
> > +#ifdef CONFIG_GNUTLS
> > +    gnutls_dh_params_t dh_params;
> > +#endif
> > +};
> > +

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Reply via email to