Description
If building against libvncclient 0.9.12 or newer, a double-free error occurs upon VNC disconnect:
guacd_1 | guacd[13]: INFO: User "@f4557a45-771a-49c3-a9fd-74f6a3d64ec2" disconnected (0 users remain) guacd_1 | guacd[13]: INFO: Last user of connection "$5373b0f7-be98-4941-9d4c-8643cc29b647" disconnected guacd_1 | guacd[13]: INFO: Internal VNC client disconnected guacd_1 | *** Error in `/opt/glyptodon/sbin/guacd': double free or corruption (out): 0x00007fb698089820 *** guacd_1 | ======= Backtrace: ========= guacd_1 | /lib64/libc.so.6(+0x81299)[0x7fb6afa3a299] guacd_1 | /opt/glyptodon/lib64/libvncclient.so.1(rfbClientCleanup+0x5b)[0x7fb6aad4e24b] guacd_1 | /opt/glyptodon/lib64/libguac-client-vnc.so(guac_vnc_client_free_handler+0x90)[0x7fb6aaf60800] guacd_1 | /opt/glyptodon/lib64/libguac.so.19(guac_client_free+0x32)[0x7fb6b14902a2] guacd_1 | /opt/glyptodon/sbin/guacd[0x404375] guacd_1 | /lib64/libpthread.so.0(+0x7ea5)[0x7fb6b08b8ea5] guacd_1 | /lib64/libc.so.6(clone+0x6d)[0x7fb6afab796d]
From gdb:
(gdb) bt #0 __GI___libc_free (mem=0x7fbd9806e010) at malloc.c:2941 #1 0x00007fbd935f524b in rfbClientCleanup (client=client@entry=0x7fbd9f088010) at /usr/src/debug/libvncserver-LibVNCServer-0.9.13/libvncclient/vncviewer.c:527 #2 0x00007fbd980d7800 in guac_vnc_client_free_handler (client=0x7fbd9400b8a0) at client.c:92 #3 0x00007fbd9ee062a2 in guac_client_free (client=0x7fbd9400b8a0) at client.c:195 #4 0x0000000000404375 in guacd_client_free_thread (data=0x7fbd992e6b50) at proc.c:219 #5 0x00007fbd9e22edd5 in start_thread (arg=0x7fbd899c0700) at pthread_create.c:307 #6 0x00007fbd9d42dead in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 (gdb)
Checking vncviewer.c within libvncclient, the free in question is:
if (client->raw_buffer) free(client->raw_buffer);
We are indeed freeing this internally, apparently due to old behavior of libvncclient. From client.c within guacamole-server's VNC support:
/* Free memory not free'd by libvncclient's rfbClientCleanup() */ if (rfb_client->frameBuffer != NULL) free(rfb_client->frameBuffer); if (rfb_client->raw_buffer != NULL) free(rfb_client->raw_buffer); if (rfb_client->rcSource != NULL) free(rfb_client->rcSource);