gthreadresolver: do_lookup_records does res_ninit with an uninitialized state
On FreeBSD (12.0-RELEASE) libc, res_ninit(..)
fails with SIGSEGV when passed an uninitialized state pointer. Following is the gdb backtrace from Gajim which was segfaulting:
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/local/bin/python3.6...(no debugging symbols found)...done.
(gdb) run /usr/local/bin/gajim
Starting program: /usr/local/bin/python3.6 /usr/local/bin/gajim
[Detaching after fork from child process 8200]
[Detaching after fork from child process 8722]
Found default language: en
No translations found
Dirs searched: [PosixPath('/usr/local/share'), PosixPath('/usr/share')]
[Detaching after fork from child process 8877]
[Detaching after fork from child process 9550]
[Detaching after fork from child process 10109]
[New LWP 101529 of process 419]
[New LWP 101530 of process 419]
[Detaching after fork from child process 10470]
/usr/local/lib/python3.6/site-packages/gajim/common/app.py:263: Warning: g_param_spec_int64: assertion 'default_value >= minimum && default_value <= maximum' failed
conference.new_session(Farstream.MediaType.AUDIO)
/usr/local/lib/python3.6/site-packages/gajim/common/app.py:263: Warning: validate_pspec_to_install: assertion 'G_IS_PARAM_SPEC (pspec)' failed
conference.new_session(Farstream.MediaType.AUDIO)
[Detaching after fork from child process 10978]
[Detaching after fork from child process 12077]
[New LWP 101531 of process 419]
[New LWP 101539 of process 419]
[LWP 101531 of process 419 exited]
Thread 5 received signal SIGSEGV, Segmentation fault.
[Switching to LWP 101539 of process 419]
0x00000008006bd54d in tcache_dalloc_large (tsd=<optimized out>, tcache=<optimized out>, ptr=<optimized out>,
binind=<optimized out>, slow_path=false) at /usr/src/contrib/jemalloc/include/jemalloc/internal/tcache_inlines.h:203
203 if (unlikely(bin->ncached == bin_info->ncached_max)) {
(gdb) bt
#0 0x00000008006bd54d in tcache_dalloc_large (tsd=<optimized out>, tcache=<optimized out>, ptr=<optimized out>,
binind=<optimized out>, slow_path=false) at /usr/src/contrib/jemalloc/include/jemalloc/internal/tcache_inlines.h:203
#1 arena_dalloc (tcache=0x8087dc250, slow_path=false, tsdn=<optimized out>, ptr=<optimized out>, alloc_ctx=<optimized out>)
at /usr/src/contrib/jemalloc/include/jemalloc/internal/arena_inlines_b.h:232
#2 idalloctm (slow_path=false, tsdn=<optimized out>, ptr=<optimized out>, tcache=<optimized out>, alloc_ctx=<optimized out>,
is_internal=<optimized out>) at /usr/src/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h:118
#3 ifree (tsd=<optimized out>, ptr=<optimized out>, tcache=0x8087dc250, slow_path=false) at jemalloc_jemalloc.c:2226
#4 __free (ptr=<optimized out>) at jemalloc_jemalloc.c:2397
#5 0x0000000800703fd3 in __res_ndestroy (statp=0x7fffdf9fad00) at /usr/src/lib/libc/resolv/res_init.c:829
#6 0x0000000800702f10 in __res_vinit (statp=0x7fffdf9fad00, preinit=0) at /usr/src/lib/libc/resolv/res_init.c:192
#7 0x0000000802914a27 in do_lookup_records (task=0x80f9d1100, source_object=0x80126ef10, task_data=0x80f962ac0,
cancellable=0x0) at gthreadedresolver.c:839
#8 0x00000008029104be in g_task_thread_pool_thread (thread_data=0x80f9d1100, pool_data=0x0) at gtask.c:1331
#9 0x00000008027a3027 in g_thread_pool_thread_proxy (data=0x806f79c60) at gthreadpool.c:307
#10 0x00000008027a1aed in g_thread_proxy (data=0x80e3de9e0) at gthread.c:784
#11 0x0000000800254776 in thread_start (curthread=0x80e98be00) at /usr/src/lib/libthr/thread/thr_create.c:292
#12 0x0000000000000000 in ?? ()
Backtrace stopped: Cannot access memory at address 0x7fffdf9fb000
(gdb) frame 7
#7 0x0000000802914a27 in do_lookup_records (task=0x80f9d1100, source_object=0x80126ef10, task_data=0x80f962ac0,
cancellable=0x0) at gthreadedresolver.c:839
839 gthreadedresolver.c: No such file or directory.
(gdb) directory /usr/ports/devel/glib20/work/glib-2.56.3
Source directories searched: /usr/ports/devel/glib20/work/glib-2.56.3:$cdir:$cwd
(gdb) frame 7
#7 0x0000000802914a27 in do_lookup_records (task=0x80f9d1100, source_object=0x80126ef10, task_data=0x80f962ac0, cancellable=0x0) at gthreadedresolver.c:839
839 gthreadedresolver.c: No such file or directory.
(gdb) directory /usr/ports/devel/glib20/work/glib-2.56.3/gio
Source directories searched: /usr/ports/devel/glib20/work/glib-2.56.3/gio:/usr/ports/devel/glib20/work/glib-2.56.3:$cdir:$cwd
(gdb) frame 7
#7 0x0000000802914a27 in do_lookup_records (task=0x80f9d1100, source_object=0x80126ef10, task_data=0x80f962ac0, cancellable=0x0) at gthreadedresolver.c:839
839 if (res_ninit (&res) != 0)
(gdb) print lrd
$1 = (LookupRecordsData *) 0x80f962ac0
(gdb) print lrd->rrname;
Invalid character ';' in expression.
(gdb) print lrd->rrname
$2 = 0x80f9db1c0 "_xmppconnect.lostca.se"
(gdb) print lrd->record_type
$3 = G_RESOLVER_RECORD_TXT
Following is the fix for the issue w.r.t. GLib 2.56.3, which I'm running:
--- gio/gthreadedresolver.c.orig
+++ gio/gthreadedresolver.c
@@ -836,6 +836,7 @@
* worker thread. (Although the workers would get reused by the
* #GThreadPool.) */
struct __res_state res;
+ memset( &res, 0, sizeof( res ));
if (res_ninit (&res) != 0)
{
g_task_return_new_error (task, G_RESOLVER_ERROR, G_RESOLVER_ERROR_INTERNAL,
On git HEAD this translates to https://gitlab.gnome.org/GNOME/glib/blob/master/gio/gthreadedresolver.c#L945
From Oracle Solaris manpage:
State information is kept in statp and is used to control the behavior of these functions. Set statp to all zeros prior to making the first call to any of these functions.
On FreeBSD, unfortunately I failed to find such verbose documentation, so I'll have to point to source code:
- https://svnweb.freebsd.org/base/releng/12.0/lib/libc/resolv/res_init.c?view=markup#l191
- https://svnweb.freebsd.org/base/releng/12.0/lib/libc/resolv/res_init.c?view=markup#l826
Please let me know if you need more information.
Thanks in advance for taking a look