Modify

#1229 closed defect (fixed)

Use-after-free when leaving invited (temporary) channels

Reported by: dx Owned by:
Priority: normal Milestone:
Component: BitlBee Version: 3.4
Keywords: Cc:
IRC client+version: Client-independent Operating System: Public server
OS version/distro:

Description

Originally reported by belak, with hipchat, but probably happens to any jabber invited channel.

Valgrind:

==3237== Invalid read of size 8
==3237==    at 0x125BB4: irc_channel_has_user (irc_channel.c:297)
==3237==    by 0x125A49: irc_channel_del_user (irc_channel.c:256)
==3237==    by 0x124249: bee_irc_chat_remove_user (irc_im.c:668)
==3237==    by 0x143F7F: imcb_chat_remove_buddy (bee_chat.c:232)
==3237==    by 0x14EA6F: jabber_chat_pkt_presence (conference.c:378)
==3237==    by 0x157841: jabber_pkt_presence (presence.c:110)
==3237==    by 0x140F76: xt_handle (xmltree.c:195)
==3237==    by 0x140DCF: xt_handle (xmltree.c:174)
==3237==    by 0x140D93: xt_handle (xmltree.c:169)
==3237==    by 0x14F376: jabber_feed_input (io.c:167)
==3237==    by 0x14F5C6: jabber_read_callback (io.c:237)
==3237==    by 0x136753: gaim_io_invoke (events_glib.c:86)
==3237==    by 0x537C90C: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x537CCDF: ??? (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x537D001: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x1366C3: b_main_run (events_glib.c:59)
==3237==    by 0x134381: main (unix.c:170)
==3237==  Address 0x9fc2598 is 56 bytes inside a block of size 112 free'd
==3237==    at 0x4C2A65B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3237==    by 0x125719: irc_channel_free (irc_channel.c:163)
==3237==    by 0x1257A4: irc_channel_free_callback (irc_channel.c:181)
==3237==    by 0x537D3A2: ??? (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x537C90C: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x537CCDF: ??? (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x537D001: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.4400.1)
==3237==    by 0x1366C3: b_main_run (events_glib.c:59)
==3237==    by 0x134381: main (unix.c:170)

What happens here, step by step:

1. User gets invite
2. User joins to temporary channel
3. User leaves channel
4. irc_cmd_part
4.1. irc_channel_del_user
4.1.1. irc_channel_free_soon (adds a timeout until the main loop is free)
4.2. When irc_channel_del_user returns 1, bee_irc_channel_chat_part
4.2.1. jabber_chat_leave, only sends a presence unavailable message to the server
4.2.2. "ic->data = NULL", comment says
       "/* Remove the reference. We don't need it anymore. */"
5. Main loop is free now, irc_channel_free_callback
5.1. irc_channel_free
5.1.1. bee_irc_channel_free, which finds that ic->data is null
       and can't set ic->data->ui_data to null.
5.2. the irc channel is freed, ic->data (struct groupchat) isn't
6. jabber_chat_pkt_presence (Reply from the jabber server arrives)
6.1. imcb_chat_remove_buddy
6.1.1. bee_irc_chat_remove_user
6.1.1.1. "irc_channel_t *ic = c->ui_data;", that's a non-null already freed value
6.1.1.2. irc_channel_del_user gets called, and at this point stuff breaks

4.2.2 seems to be the delicate part. That's irc_im.c:866, in bee_irc_channel_chat_part.

Relevant commits here, just click the three things and admire the diffs:

cc20520bd29c88d424f44ac5669c3026e9fd99fb

6963230895c26d054cc3543b03787118e2334c32

664bac38fcdf6889d3ceb29b73a0c3a4e27820ce

Second commit there references #780, which is suspiciously similar to this issue

FWIW, my fix idea was this:

-       /* Remove the reference. We don't need it anymore. */
-       ic->data = NULL;
+
+       if (!(ic->flags & IRC_CHANNEL_TEMP)) {
+               /* Remove the reference.
+                * We only need it for temp channels that are being freed */
+               ic->data = NULL;
+       }

After looking at those commits i linked above, i'm not so sure

Attachments (0)

Change History (3)

comment:1 Changed at 2015-09-13T08:45:05Z by dx

I just noticed, third commit (jgeboski's) is essentially just a revert of the second one (which fixes exactly the same issue i'm reporting here, which is the same as #780)

I'll have to dig irc logs for more context of the issue jgeboski was trying to fix there.

Having a serious case of deja vu right now.

comment:2 Changed at 2015-09-13T09:06:15Z by dx

From my irc logs back when jgeboski was implementing the twitter thing and made that commit that introduced this regression:

<jgeboski> https://github.com/dequis/bitlbee-old/blob/68a11dd/irc_im.c#L906
<jgeboski> so, prpl->chat_leave() is support to free the groupchat
<jgeboski> since c, still has the free'd address below the call to
           chat_leave(), c->ui_data is still modified
==6977== Invalid write of size 8
==6977==    at 0x124C3A: bee_irc_channel_chat_part (irc_im.c:916)
==6977==    by 0x127D2D: irc_cmd_part (irc_commands.c:238)
==6977==    by 0x1297EC: irc_exec (irc_commands.c:798)
==6977==    by 0x120FDB: irc_process (irc.c:401)
==6977==    by 0x11B33C: bitlbee_io_current_client_read (bitlbee.c:222)
==6977==    by 0x136AA6: gaim_io_invoke (events_glib.c:82)
==6977==    by 0x5382924: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977==    by 0x5382C87: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977==    by 0x5382F49: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977==    by 0x136A18: b_main_run (events_glib.c:58)
==6977==    by 0x134683: main (unix.c:178)
==6977==  Address 0x88a19d0 is 48 bytes inside a block of size 56 free'd
==6977==    at 0x4C2A20C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==6977==    by 0x14669E: imcb_chat_free (bee_chat.c:79)
==6977==    by 0x18DE0D: twitter_chat_leave (twitter.c:737)
==6977==    by 0x124C22: bee_irc_channel_chat_part (irc_im.c:911)
==6977==    by 0x127D2D: irc_cmd_part (irc_commands.c:238)
==6977==    by 0x1297EC: irc_exec (irc_commands.c:798)
==6977==    by 0x120FDB: irc_process (irc.c:401)
==6977==    by 0x11B33C: bitlbee_io_current_client_read (bitlbee.c:222)
==6977==    by 0x136AA6: gaim_io_invoke (events_glib.c:82)
==6977==    by 0x5382924: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977==    by 0x5382C87: g_main_context_iterate.isra.24 (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977==    by 0x5382F49: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.4002.0)
==6977== 

(line numbers above apply to 68a11dd in bitlbee-old, or fed4f76 in the current repo)

comment:3 Changed at 2015-10-08T09:43:41Z by dx

Resolution: fixed
Status: newclosed

Applied my original patch idea in e1bea35419d0851323fb9d90b6284ded0bae802c

Let's see how this goes.

Modify Ticket

Action
as closed The ticket will remain with no owner.
The resolution will be deleted.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.