[gnutls-devel] GnuTLS | GNUTLS 3.8.0 public API has broken ABI compatibility on 32-bit platforms with glibc >= 2.34 (#1466)
Read-only notification of GnuTLS library development activities
gnutls-devel at lists.gnutls.org
Thu Mar 2 10:22:56 CET 2023
Daniel P_ Berrangé created an issue: https://gitlab.com/gnutls/gnutls/-/issues/1466
With the 3.8.0 release of GNUTLS, the public API has broken ABI compatibility on 32-bit platforms which have glibc >= 2.34 present.
The issue affects any GNUTLS API that uses the `time_t` type. We detected this because it broken all the libvirt and QEMU unit tests which generate certificates, with errors about the certificate not being active yet.
A condensed snippet from the QEMU tests to reproduce the problem is as follows:
```
$ cat demo.c
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
# define PRIVATE_KEY \
"-----BEGIN RSA PRIVATE KEY-----\n" \
"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\n" \
"-----END RSA PRIVATE KEY-----\n"
static gnutls_x509_privkey_t load_key(void)
{
gnutls_x509_privkey_t key;
const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY,
strlen(PRIVATE_KEY) };
assert(gnutls_x509_privkey_init(&key) >= 0);
assert(gnutls_x509_privkey_import(key, &data,
GNUTLS_X509_FMT_PEM) >= 0);
return key;
}
int main(int argc, char **argv) {
gnutls_x509_crt_t crt;
int err;
static char buffer[1024 * 1024];
size_t size = sizeof(buffer);
char serial[5] = { 1, 2, 3, 4, 0 };
gnutls_datum_t der;
time_t start = time(NULL);
time_t expire = time(NULL) + (60 * 60 * 24);
gnutls_x509_privkey_t privkey = load_key();
assert(gnutls_x509_crt_init(&crt) >= 0);
assert(gnutls_x509_crt_set_key(crt, privkey) >= 0);
assert(gnutls_x509_crt_set_version(crt, 3) >= 0);
assert(gnutls_x509_crt_set_serial(crt, serial, 5) >= 0);
assert(gnutls_x509_crt_set_activation_time(crt, start) >= 0);
assert(gnutls_x509_crt_set_expiration_time(crt, expire) >= 0);
assert(gnutls_x509_crt_sign2(crt, crt, privkey,
GNUTLS_DIG_SHA256, 0) >= 0);
assert(gnutls_x509_crt_export(
crt, GNUTLS_X509_FMT_PEM, buffer, &size) >= 0);
assert(start == gnutls_x509_crt_get_activation_time(crt));
printf("%s\n", buffer);
return 0;
}
```
Compile this on a 32-bit host, (or 64-bit host passing -m32) and then query the certificate contents:
```
$ gcc -g -lgnutls -m32 -o demo demo.c
$ ./demo | certtool -i | grep Not
Not Before: Sat Sep 05 17:30:22 UTC 2703
Not After: Sun Sep 06 17:30:22 UTC 2703
```
Notice that instead of having a validity/expiry date of today + 1 day, it has a date ~700 years into the future.
This did not happen with gnutls 3.7.8 / 3.7.9
I ran a git bisect in gnutls and narrowed it down to this change
```
commit 61fa36ca4ea84ca3bc42918690151eec8dfc1148
Author: Daiki Ueno <ueno at gnu.org>
Date: Sat Jan 8 18:14:16 2022 +0100
gnulib: update git submodule
Signed-off-by: Daiki Ueno <ueno at gnu.org>
```
The problem arose because GNULIB has changed the 'largefile' module so that it probes for the C library exposing _TIME_BITS=64, and if available will set that define. This results in time_t changing from 32-bit in size to 64-bit when gnutls is built.
Meanwhile essentially no application that uses GNUTLS will have _TIME_BITS=64 set, and thus they will all be passing/receiving time with a 32-bit time_t.
This means that any application interacting with GNUTLS APIs that involve time_t will be broken on 32-bit hosts with glibc >= 2.34 (when _TIME_BITS=64 arrived).
GNULIB did provide a '--disable-year2038' flag for configure which can be used at build time to disable 64-bit time_t. Essentially everyone who builds GNUTLS today needs to be sure to pass --disable-year2038 to avoid the silent ABI change.
See also this thread https://sourceware.org/pipermail/libc-alpha/2023-March/146002.html
Both Gentoo and Fedora have hit this ABI incompatibility, and any other distro which still has 32-bit builds will do so too.
I'm not sure what the best course of action for GNUTLS is right now. IMHO, ideally GNULIB should not have forced 64-bit time_t on every application using 'largefile', it should have remained strictly opt-in, as GLibC had made it. I don't see a way for GNUTLS to get away from the 'largefile' change because 'largefile' is an important GNULIB module that every app needs.
The best I can see is to prominently document the importance of setting '--disable-year2038' when building GNUTLS, unless GNULIB wants to revert their change to 'largefile' and make it opt-in.
--
Reply to this email directly or view it on GitLab: https://gitlab.com/gnutls/gnutls/-/issues/1466
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gnutls-devel/attachments/20230302/363f2498/attachment-0001.html>
More information about the Gnutls-devel
mailing list