Package: libetpan17
Version: 1.5-1
Severity: important
Tags: upstream patch

Hi there,

Claws Mail (all versions since 3.9.3-2+b3, inclusive) reliably
segfaults seconds after startup on my system. I have attached a full
backtrace taken after such an event.

I have tracked the problem down to a corner case in the interaction
between claws-mail and libetpan17, which seems simplest to fix in
libetpan. The trigger for the bug is that claws-mail links directly
against libgnutls26, but also against libetpan17, which links against
libgnutls-deb0-28.

This problem does not occur with versions of claws-mail prior to
3.9.3-2+b3, which all link against libetpan16 (which links against
libgnutls26).

claws-mail first calls gnutls_global_init, which initialises
libgnutls26, and then calls mailstream_gnutls_init_not_required in
libetpan17, which causes libetpan not to initialise libgnutls-deb0-28.
The result of this is that libetpan calls gnutls with an uninitialised
session handle, resulting in a segfault.

However, since gnutls_global_init is reentrant, it is perfectly safe to
ignore any calls to mailstream_gnutls_init_not_required and initialise
gnutls anyway. In the case where gnutls has already been initialised,
doing so will simply increment a counter; and in the case where this
bug is triggered, gnutls will be properly initialised before use.

OpenSSL's SSL_library_init is not reentrant, and therefore this change
can only apply to gnutls.

I am attaching a patch which implements this change, and I have
confirmed that it fixes the segfaulting behaviour described above.
Please let me know if you think it needs to be revised, or if you need
any further information.

Thanks,
Steven.

-- System Information:
Debian Release: jessie/sid
  APT prefers unstable
  APT policy: (800, 'unstable'), (700, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.14-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_AU.utf8, LC_CTYPE=en_AU.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages libetpan17 depends on:
ii  libc6              2.19-1
ii  libdb5.3           5.3.28-3
ii  libgcc1            1:4.9.0-6
ii  libgnutls-deb0-28  3.2.15-2
ii  liblockfile1       1.09-6
ii  libsasl2-2         2.1.26.dfsg1-9
ii  libstdc++6         4.9.0-6
ii  multiarch-support  2.19-1
ii  zlib1g             1:1.2.8.dfsg-1

libetpan17 recommends no packages.

libetpan17 suggests no packages.

-- no debconf information
#0  __GI___pthread_mutex_lock (mutex=0x3) at ../nptl/pthread_mutex_lock.c:66
        __PRETTY_FUNCTION__ = "__pthread_mutex_lock"
        type = 3968189784
#1  0x00007fffec59068c in gnutls_system_mutex_lock (priv=<optimized out>) at 
system.c:228
No locals.
#2  0x00007fffec6214c7 in wrap_nettle_rnd (_ctx=<optimized out>, level=0, 
data=0x7fffd0002b9b, datasize=29) at rnd.c:441
        ret = <optimized out>
        reseed = 0
        event = {now = {tv_sec = 4, tv_nsec = 140733193388127}, count = 0, err 
= 0, pid = 3071, rusage = {ru_utime = {tv_sec = 472446402560, 
              tv_usec = 119}, ru_stime = {tv_sec = 532575944704, tv_usec = 
-1403518415238332416}, {ru_maxrss = 32767, __ru_maxrss_word = 32767}, {
              ru_ixrss = -1403546487144579072, __ru_ixrss_word = 
-1403546487144579072}, {ru_idrss = 32767, __ru_idrss_word = 32767}, {
              ru_isrss = 58552705030815744, __ru_isrss_word = 
58552705030815744}, {ru_minflt = -3089299401110192128, 
              __ru_minflt_word = -3089299401110192128}, {ru_majflt = 
-585856942451163137, __ru_majflt_word = -585856942451163137}, {
              ru_nswap = 21474869247, __ru_nswap_word = 21474869247}, 
{ru_inblock = 0, __ru_inblock_word = 0}, {ru_oublock = -3089299469829668864, 
              __ru_oublock_word = -3089299469829668864}, {ru_msgsnd = 
-1417224274355126273, __ru_msgsnd_word = -1417224274355126273}, {
              ru_msgrcv = -3458716891223130113, __ru_msgrcv_word = 
-3458716891223130113}, {ru_nsignals = -3089299401110159361, 
              __ru_nsignals_word = -3089299401110159361}, {ru_nvcsw = 
8589967359, __ru_nvcsw_word = 8589967359}, {ru_nivcsw = -585745419330387968, 
              __ru_nivcsw_word = -585745419330387968}}}
#3  0x00007fffec578252 in _gnutls_rnd (len=29, data=0x7fffd0002b9b, 
level=GNUTLS_RND_NONCE) at ./random.h:37
        data = 0x7fffd0002b9b
#4  _gnutls_tls_create_random (dst=0x7fffd0002b98 "S\231\212\206") at 
gnutls_handshake.c:207
        tim = <optimized out>
#5  0x00007fffec578573 in _gnutls_set_client_random (session=0x0, rnd=0x0) at 
gnutls_handshake.c:232
        ret = -805295280
#6  0x00007fffec579dfd in _gnutls_send_client_hello (again=<optimized out>, 
session=0x7fffd0002b50) at gnutls_handshake.c:1994
        ret = 2
        extdata = {allocd = 0x7fffd00046b0 "\003\003", data = 0x7fffd00046b0 
"\003\003", max_length = 2048, length = 2}
        session_id_len = 0 '\000'
        bufel = 0x0
        hver = 0x7fffec8599e8 <sup_versions+72>
        tver = "\003\003"
        rehandshake = <optimized out>
#7  _gnutls_send_hello (session=session@entry=0x7fffd0002b50, again=<optimized 
out>) at gnutls_handshake.c:2207
        ret = <optimized out>
#8  0x00007fffec57c308 in _gnutls_handshake_client (session=0x7fffd0002b50) at 
gnutls_handshake.c:2664
        ret = 0
#9  gnutls_handshake (session=0x7fffd0002b50) at gnutls_handshake.c:2535
        ret = <optimized out>
        params = 0x7fffec58cba5 <gnutls_dh_set_prime_bits+37>
#10 0x00007ffff2d27629 in ssl_data_new (fd=fd@entry=16, 
timeout=timeout@entry=0, callback=0x5c3390 <etpan_connect_ssl_context_cb>, 
cb_data=0xd00560, 
    cb_data@entry=0x5c3390 <etpan_connect_ssl_context_cb>) at 
mailstream_ssl.c:597
        ssl_data = <optimized out>
        session = 0x7fffd0002b50
        cancel = <optimized out>
        xcred = 0x7fffd0001270
        r = <optimized out>
        ssl_context = 0x7fffd0004270
        timeout_value = <optimized out>
#11 0x00007ffff2d27755 in tls_data_new (cb_data=0x5c3390 
<etpan_connect_ssl_context_cb>, callback=<optimized out>, timeout=0, 
fd=fd@entry=16)
    at mailstream_ssl.c:638
No locals.
#12 mailstream_low_ssl_open_full (fd=fd@entry=16, starttls=starttls@entry=0, 
timeout=0, 
    callback=callback@entry=0x5c3390 <etpan_connect_ssl_context_cb>, 
cb_data=cb_data@entry=0xd00560) at mailstream_ssl.c:693
        s = <optimized out>
        ssl_data = <optimized out>
#13 0x00007ffff2d279a0 in mailstream_low_ssl_open_with_callback_timeout 
(fd=fd@entry=16, timeout=<optimized out>, 
    callback=callback@entry=0x5c3390 <etpan_connect_ssl_context_cb>, 
data=data@entry=0xd00560) at mailstream_ssl.c:1181
No locals.
#14 0x00007ffff2d279a6 in mailstream_ssl_open_with_callback_timeout 
(fd=fd@entry=16, timeout=<optimized out>, 
    callback=callback@entry=0x5c3390 <etpan_connect_ssl_context_cb>, 
data=data@entry=0xd00560) at mailstream_ssl.c:1071
        low = <optimized out>
        s = <optimized out>
#15 0x00007ffff2d3c645 in mailimap_ssl_connect_voip_with_callback 
(f=0x2e43ed70, server=<optimized out>, port=<optimized out>, 
    voip_enabled=<optimized out>, callback=0x5c3390 
<etpan_connect_ssl_context_cb>, data=0xd00560) at mailimap_ssl.c:94
        s = 16
        stream = <optimized out>
#16 0x00007ffff2d3c6c7 in mailimap_ssl_connect_with_callback (f=<optimized 
out>, server=<optimized out>, port=<optimized out>, 
    callback=<optimized out>, data=<optimized out>) at mailimap_ssl.c:65
No locals.
#17 0x00000000005bd159 in connect_ssl_run (op=<optimized out>) at 
imap-thread.c:538
        r = <optimized out>
        param = <optimized out>
        result = 0x7fffffffb260
#18 0x00000000005e0139 in thread_run (data=0x2e43a100) at 
etpan-thread-manager.c:351
        do_quit = 0
        op = 0x2e43efd0
        thread = 0x2e43a100
        r = <optimized out>
#19 0x00007ffff43540ca in start_thread (arg=0x7fffd520a700) at 
pthread_create.c:312
        __res = <optimized out>
        pd = 0x7fffd520a700
        now = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140736769074944, 
1956691914992824913, 1, 140737354125408, 993, 140736769074944, 
                -1956749513846246831, -1956681527595322799}, mask_was_saved = 
0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, 
              cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
        pagesize_m1 = <optimized out>
        sp = <optimized out>
        freesize = <optimized out>
        __PRETTY_FUNCTION__ = "start_thread"
#20 0x00007ffff1d85ffd in clone () at 
../sysdeps/unix/sysv/linux/x86_64/clone.S:111
No locals.
Always initialise gnutls, regardless of being told not to

gnutls_global_init is reentrant, unlike SSL_library_init, so we can
safely ignore any calls to mailstream_gnutls_init_not_required. This
fixes broken behaviour in cases where our caller links against a
different version of gnutls and we end up using an uninitialised
library.
--- a/src/data-types/mailstream_ssl.c
+++ b/src/data-types/mailstream_ssl.c
@@ -152,7 +152,6 @@
 #	define MUTEX_LOCK(x)
 #	define MUTEX_UNLOCK(x)
 #endif
-static int gnutls_init_not_required = 0;
 static int openssl_init_done = 0;
 #endif
 
@@ -242,11 +241,7 @@
 
 void mailstream_gnutls_init_not_required(void)
 {
-#ifdef USE_SSL
-  MUTEX_LOCK(&ssl_lock);
-  gnutls_init_not_required = 1;
-  MUTEX_UNLOCK(&ssl_lock);
-#endif
+  return;
 }
 
 void mailstream_openssl_init_not_required(void)
@@ -282,8 +277,7 @@
     openssl_init_done = 1;
   }
 #else
-  if (!gnutls_init_not_required)
-    gnutls_global_init();
+  gnutls_global_init();
 #endif
   MUTEX_UNLOCK(&ssl_lock);
 #endif
@@ -666,8 +660,7 @@
   gnutls_deinit(ssl_data->session);
 
   MUTEX_LOCK(&ssl_lock);
-  if(!gnutls_init_not_required)
-    gnutls_global_deinit();
+  gnutls_global_deinit();
   MUTEX_UNLOCK(&ssl_lock);
 
   ssl_data->session = NULL;

Reply via email to