[Pkg-privacy-maintainers] Bug#932927: libotr: buggy unit test: test_auth.c: test_auth_clear()

Aurelien Jarno aurel32 at debian.org
Wed Jul 24 21:45:13 BST 2019


Source: libotr
Version: 4.1.1-3
Severity: normal
Tags: patch upstream
User: debian-riscv at lists.debian.org
Usertags: riscv64

I have been investigating while test_auth fails with a segmentation
fault on riscv64:

| aurel32 at riscv64:~/libotr/libotr-4.1.1/tests/unit$ ./test_auth
| 1..5
| ok 1 - OTR auth info init is valid
| Segmentation fault

Here is the corresponding backtrace:

| #0  _gcry_mpi_free_limb_space (a=0x100f30003, nlimbs=1179403647) at ../../mpi/mpiutil.c:142
| #1  0x00000020000c531c in _gcry_mpi_free (a=0x2000000000) at ../../mpi/mpiutil.c:224
| #2  0x00000020000471e8 in otrl_dh_keypair_free (kp=kp at entry=0x3fffa95170) at dh.c:89
| #3  0x000000200004adc4 in otrl_auth_clear (auth=0x3fffa95160) at auth.c:107
| #4  0x0000002aaaaab0f6 in test_auth_clear () at test_auth.c:70
| #5  0x0000002aaaaaaed2 in main (argc=<optimized out>, argv=<optimized out>) at test_auth.c:176

It happens that test_auth_clear() uses for its test a struct context
allocated on the stack. As such its contents is random. 
otrl_auth_clear() is called on this random data, which in turns call
otrl_dh_keypair_free() on this random data. The DH_keypair structure
contains 2 gcry_mpi_t fields, which are pointers. otrl_dh_keypair_free()
calls gcry_mpi_release() on those pointers, which ends up calling
_gcry_mpi_free_limb_space() to free the memory. Boom.

It seems this test only works by chance on other architectures as the
struct context in test_auth_new() and test_auth_clear() are at the same
location on the stack, and thus its contents is not random anymore when
entering test_auth_clear(). This seems to be confirmed by the last test
of this function: auth->context == &ctx. There is no way that
otrl_auth_clear() can set this value correctly, and it doesn't get
passed a pointer to ctx.

Therefore I believe that otrl_auth_new() should be called before
otrl_auth_clear(), like in the following patch:

--- a/tests/unit/test_auth.c
+++ b/tests/unit/test_auth.c
@@ -67,6 +67,7 @@
 	OtrlAuthInfo *auth = &ctx.auth;
 
 	/* API call. */
+	otrl_auth_new(&ctx);
 	otrl_auth_clear(auth);
 
 	ok(auth->authstate == OTRL_AUTHSTATE_NONE &&

Note that the issue can be easily reproduced on other architectures like
amd64 by making sure that ctx is random:

--- libotr-4.1.1.orig/tests/unit/test_auth.c
+++ libotr-4.1.1/tests/unit/test_auth.c
@@ -66,6 +66,11 @@ static void test_auth_clear(void)
 	struct context ctx;
 	OtrlAuthInfo *auth = &ctx.auth;
 
+	/* Initialize some fields to random values */
+	auth->our_dh.pub = (gcry_mpi_t) 0xc0ffee;
+	auth->our_dh.priv = (gcry_mpi_t) 0x0c0ffee;
+	auth->context = NULL;
+
 	/* API call. */
 	otrl_auth_clear(auth);
 



More information about the Pkg-privacy-maintainers mailing list