[libvirt] [PATCHv2] build: avoid -lgcrypt with newer gnutls

Daniel P. Berrange berrange at redhat.com
Mon Jul 29 10:25:47 UTC 2013


On Fri, Jul 26, 2013 at 08:22:29PM -0500, Doug Goldstein wrote:
> On Fri, Jul 26, 2013 at 5:04 PM, Eric Blake <eblake at redhat.com> wrote:
> > https://bugzilla.redhat.com/show_bug.cgi?id=951637
> >
> > Newer gnutls uses nettle, rather than gcrypt, which is a lot nicer
> > regarding initialization.  Yet we were unconditionally initializing
> > gcrypt even when gnutls wouldn't be using it, and having two crypto
> > libraries linked into libvirt.so is pointless.
> >
> > Assume that the switch to gnutls 3.0 is a reliable witness, when
> > pkg-config is present; otherwise be pessimistic and use gcrypt.
> >
> > * configure.ac (WITH_GNUTLS): Probe whether to add -lgcrypt, and
> > define a witness WITH_GNUTLS_GCRYPT.
> > * src/libvirt.c (virTLSMutexInit, virTLSMutexDestroy)
> > (virTLSMutexLock, virTLSMutexUnlock, virTLSThreadImpl)
> > (virGlobalInit): Honor the witness.
> > * libvirt.spec.in (BuildRequires): Make gcrypt usage conditional,
> > no longer needed in Fedora 19.
> >
> > Signed-off-by: Eric Blake <eblake at redhat.com>
> > ---
> >
> > v2: use second pkg-config invocation rather than ldd to determine
> > whether gnutls uses gcrypt
> >
> >  configure.ac    | 27 +++++++++++++++++++--------
> >  libvirt.spec.in |  2 ++
> >  src/libvirt.c   | 10 ++++++----
> >  3 files changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/configure.ac b/configure.ac
> > index cc9942a..eb56b63 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -1076,12 +1076,19 @@ if test "x$with_gnutls" != "xno"; then
> >    LIBS="$LIBS $GNUTLS_LIBS"
> >
> >    GNUTLS_FOUND=no
> > +  GNUTLS_GCRYPT=no
> >    if test -x "$PKG_CONFIG" ; then
> > +    dnl double probe, since we know that gnutls 3.0 switched to nettle instead of
> > +    dnl gcrypt
> >      PKG_CHECK_MODULES(GNUTLS, gnutls >= $GNUTLS_REQUIRED,
> > -      [GNUTLS_FOUND=yes], [GNUTLS_FOUND=no])
> > +      [GNUTLS_FOUND=yes
> > +       PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.0], [], [GNUTLS_GCRYPT=yes])],
> > +      [GNUTLS_FOUND=no])
> >    fi
> >    if test "$GNUTLS_FOUND" = "no"; then
> > +    dnl pkg-config couldn't help us, assume gcrypt is necessary
> >      fail=0
> > +    GNUTLS_GCRYPT=yes
> >      AC_CHECK_HEADER([gnutls/gnutls.h], [], [fail=1])
> >      AC_CHECK_LIB([gnutls], [gnutls_handshake],[], [fail=1], [-lgcrypt])
> >
> > @@ -1098,13 +1105,17 @@ if test "x$with_gnutls" != "xno"; then
> >        AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt])
> >      fi
> >    else
> > -    dnl Not all versions of gnutls include -lgcrypt, and so we add
> > -    dnl it explicitly for the calls to gcry_control/check_version
> > -    GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
> > -
> > -    dnl We're not using gcrypt deprecated features so define
> > -    dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
> > -    GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
> > +    dnl If gnutls linked against -lgcrypt, then we must initialize gcrypt
> > +    dnl prior to using gnutls.  Newer versions of gnutls use -lnettle, in
> > +    dnl which case we don't want to drag in gcrypt ourselves.
> > +    if test "$GNUTLS_GCRYPT" = yes; then
> > +      GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
> > +      dnl We're not using gcrypt deprecated features so define
> > +      dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
> > +      GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
> > +      AC_DEFINE_UNQUOTED([WITH_GNUTLS_GCRYPT], 1,
> > +        [set to 1 if it is known or assumed that GNUTLS uses gcrypt])
> > +    fi
> >
> >      dnl gnutls 3.x moved some declarations to a new header
> >      AC_CHECK_HEADERS([gnutls/crypto.h], [], [], [[
> > diff --git a/libvirt.spec.in b/libvirt.spec.in
> > index e0e0004..4320281 100644
> > --- a/libvirt.spec.in
> > +++ b/libvirt.spec.in
> > @@ -422,7 +422,9 @@ BuildRequires: readline-devel
> >  BuildRequires: ncurses-devel
> >  BuildRequires: gettext
> >  BuildRequires: libtasn1-devel
> > +%if (0%{?rhel} && 0%{?rhel} < 7) || (0%{?fedora} && 0%{?fedora} < 19)
> >  BuildRequires: libgcrypt-devel
> > +%endif
> >  BuildRequires: gnutls-devel
> >  BuildRequires: libattr-devel
> >  %if %{with_libvirtd}
> > diff --git a/src/libvirt.c b/src/libvirt.c
> > index 8157488..66e8248 100644
> > --- a/src/libvirt.c
> > +++ b/src/libvirt.c
> > @@ -55,7 +55,9 @@
> >  #include "intprops.h"
> >  #include "virconf.h"
> >  #if WITH_GNUTLS
> > -# include <gcrypt.h>
> > +# if WITH_GNUTLS_GCRYPT
> > +#  include <gcrypt.h>
> > +# endif
> >  # include "rpc/virnettlscontext.h"
> >  #endif
> >  #include "vircommand.h"
> > @@ -270,7 +272,7 @@ winsock_init(void)
> >  #endif
> >
> >
> > -#ifdef WITH_GNUTLS
> > +#ifdef WITH_GNUTLS_GCRYPT
> >  static int virTLSMutexInit(void **priv)
> >  {
> >      virMutexPtr lock = NULL;
> > @@ -323,7 +325,7 @@ static struct gcry_thread_cbs virTLSThreadImpl = {
> >      virTLSMutexUnlock,
> >      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
> >  };
> > -#endif
> > +#endif /* WITH_GNUTLS_GCRYPT */
> >
> >  /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99.  This
> >   * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but
> > @@ -407,7 +409,7 @@ virGlobalInit(void)
> >          virErrorInitialize() < 0)
> >          goto error;
> >
> > -#ifdef WITH_GNUTLS
> > +#ifdef WITH_GNUTLS_GCRYPT
> >      /*
> >       * This sequence of API calls it copied exactly from
> >       * gnutls 2.12.23 source lib/gcrypt/init.c, with
> > --
> > 1.8.3.1
> >
> > --
> > libvir-list mailing list
> > libvir-list at redhat.com
> > https://www.redhat.com/mailman/listinfo/libvir-list
> 
> Hate to throw a monkey wrench in the plan, but GnuTLS 3.0 isn't the
> nettle cut over. On my stable Gentoo box with GnuTLS 2.12.23, its
> using nettle as seen by ldd.
> 
>  ldd /usr/lib64/libgnutls.so.26
> 	linux-vdso.so.1 (0x00007fffad3ff000)
> 	libnettle.so.4 => /usr/lib64/libnettle.so.4 (0x00007f60fa4f4000)
> 	libgmp.so.10 => /usr/lib64/libgmp.so.10 (0x00007f60fa284000)
> 	libhogweed.so.2 => /usr/lib64/libhogweed.so.2 (0x00007f60fa054000)
> 	libz.so.1 => /lib64/libz.so.1 (0x00007f60f9e3e000)
> 	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f60f9c21000)
> 	libtasn1.so.3 => /usr/lib64/libtasn1.so.3 (0x00007f60f9a0f000)
> 	libc.so.6 => /lib64/libc.so.6 (0x00007f60f9661000)
> 	/lib64/ld-linux-x86-64.so.2 (0x00007f60fa9ec000)
> 
> It appears it was an optional cutover and I guess Gentoo made the
> plunge. Another idea, that you might hate would be to use pkg-config
> directly and pass --static so we can get the private libraries. I'm
> not running Fedora 19 yet so the best I can do is give you Fedora 18
> as a comp, but that works out great since its using 2.12.23 as well.

Hmm, so Eric's patch is mostly just an optimization, to avoid uneccessarily
linking to libgcrypt.  If we link to libgcrypt when gnutls is using nettle
nothing bad really happens. We just unecessarily initialize gcrypt.

Conversely, if we do not link to libgcrypt, when gnutls is using libgcrypt,
then we are missing important initialization code, which *is* bad.

IOW, doing the check against version 3.0.0 or later does not cause any
problems, since we know that libgcrypt can never be used with that version.

If we do a check against 2.12 though, we could miss out linkage against
libgcrypt depending on how the distro built their packages.


So unless we can come up with an easy & reliable way to detect use of
nettle with 2.x versions, I'm inclined to just stick our heads in the
sand and pretend that no 2.x version ever used nettle. Worst case we
link to and initialize gcrypt, which is not a bad problem.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list