Uh,


Forgot to change the subject.



Feel free to use:

  gatmux: take reference to mux object in received_data()



// Martin



On 30/09/2019 19.35, Martin Hundebøll wrote:
When closing down a cmux object, the address sanitizer detects a
use-after-free in gatmux.c (see below).

Avoid this by taking a reference to the mux object during the processing
in received_data().

ofonod[3640549]: ../git/plugins/quectel.c:cfun_disable() 0x610000000b40
ofonod[3640549]: ../git/plugins/quectel.c:close_serial() 0x610000000b40
ofonod[3640549]: ../git/plugins/quectel.c:close_mux() 0x610000000b40
ofonod[3640549]: ../git/examples/emulator.c:powered_watch() Removing modem 
0x610000000b40 from the list
ofonod[3640549]: ../git/examples/emulator.c:powered_watch() Removing server 
watch: 106
ofonod[3640549]: ../git/src/modem.c:modem_change_state() old state: 0, new 
state: 0

=================================================================
==3640549==ERROR: AddressSanitizer: heap-use-after-free on address 
0x62100073dd28 at pc 0x5566b6402a21 bp 0x7ffe7a2db0e0 sp 0x7ffe7a2db0d0
READ of size 8 at 0x62100073dd28 thread T0
     #0 0x5566b6402a20 in debug ../git/gatchat/gatmux.c:109
     #1 0x5566b6404bd7 in channel_close ../git/gatchat/gatmux.c:525
     #2 0x7fa0516e44a6 in g_io_channel_shutdown 
(/usr/lib/libglib-2.0.so.0+0x774a6)
     #3 0x7fa0516e4644 in g_io_channel_unref (/usr/lib/libglib-2.0.so.0+0x77644)
     #4 0x5566b64048a4 in watch_finalize ../git/gatchat/gatmux.c:474
     #5 0x7fa0516d6f6f  (/usr/lib/libglib-2.0.so.0+0x69f6f)
     #6 0x7fa0516ac6a7 in g_slist_foreach (/usr/lib/libglib-2.0.so.0+0x3f6a7)
     #7 0x7fa0516b277b in g_slist_free_full (/usr/lib/libglib-2.0.so.0+0x4577b)
     #8 0x5566b6403413 in dispatch_sources ../git/gatchat/gatmux.c:224
     #9 0x5566b64039ea in received_data ../git/gatchat/gatmux.c:268
     #10 0x7fa0516d727e in g_main_context_dispatch 
(/usr/lib/libglib-2.0.so.0+0x6a27e)
     #11 0x7fa0516d91c0  (/usr/lib/libglib-2.0.so.0+0x6c1c0)
     #12 0x7fa0516da0d2 in g_main_loop_run (/usr/lib/libglib-2.0.so.0+0x6d0d2)
     #13 0x5566b6429b1b in main ../git/src/main.c:286
     #14 0x7fa05147fee2 in __libc_start_main (/usr/lib/libc.so.6+0x26ee2)
     #15 0x5566b62531ad in _start 
(/home/martin/projects/ofono/x86/src/ofonod+0xfc1ad)

0x62100073dd28 is located 40 bytes inside of 4672-byte region 
[0x62100073dd00,0x62100073ef40)
freed by thread T0 here:
     #0 0x7fa0519256c0 in __interceptor_free 
/build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
     #1 0x5566b64052d7 in g_at_mux_unref ../git/gatchat/gatmux.c:645
     #2 0x5566b63d6d19 in close_mux ../git/plugins/quectel.c:199
     #3 0x5566b63d7047 in close_serial ../git/plugins/quectel.c:223
     #4 0x5566b63db62a in cfun_disable ../git/plugins/quectel.c:1056
     #5 0x5566b63f6ae1 in at_chat_finish_command ../git/gatchat/gatchat.c:459
     #6 0x5566b63f701b in at_chat_handle_command_response 
../git/gatchat/gatchat.c:521
     #7 0x5566b63f785b in have_line ../git/gatchat/gatchat.c:600
     #8 0x5566b63f87f1 in new_bytes ../git/gatchat/gatchat.c:759
     #9 0x5566b640174c in received_data ../git/gatchat/gatio.c:122
     #10 0x5566b64047b4 in watch_dispatch ../git/gatchat/gatmux.c:464
     #11 0x5566b640313b in dispatch_sources ../git/gatchat/gatmux.c:183
     #12 0x5566b64039ea in received_data ../git/gatchat/gatmux.c:268
     #13 0x7fa0516d727e in g_main_context_dispatch 
(/usr/lib/libglib-2.0.so.0+0x6a27e)

previously allocated by thread T0 here:
     #0 0x7fa051925ce8 in __interceptor_calloc 
/build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153
     #1 0x5566b6405009 in g_at_mux_new ../git/gatchat/gatmux.c:606
     #2 0x5566b6407f6b in g_at_mux_new_gsm0710_basic 
../git/gatchat/gatmux.c:1165
     #3 0x5566b63da9ba in cmux_cb ../git/plugins/quectel.c:882
     #4 0x5566b63f6ae1 in at_chat_finish_command ../git/gatchat/gatchat.c:459
     #5 0x5566b63f701b in at_chat_handle_command_response 
../git/gatchat/gatchat.c:521
     #6 0x5566b63f785b in have_line ../git/gatchat/gatchat.c:600
     #7 0x5566b63f87f1 in new_bytes ../git/gatchat/gatchat.c:759
     #8 0x5566b640174c in received_data ../git/gatchat/gatio.c:122
     #9 0x7fa0516d727e in g_main_context_dispatch 
(/usr/lib/libglib-2.0.so.0+0x6a27e)

SUMMARY: AddressSanitizer: heap-use-after-free ../git/gatchat/gatmux.c:109 in 
debug
Shadow bytes around the buggy address:
   0x0c42800dfb50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
   0x0c42800dfb60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
   0x0c42800dfb70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
   0x0c42800dfb80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
   0x0c42800dfb90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c42800dfba0: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
   0x0c42800dfbb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
   0x0c42800dfbc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
   0x0c42800dfbd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
   0x0c42800dfbe0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
   0x0c42800dfbf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
   Addressable:           00
   Partially addressable: 01 02 03 04 05 06 07
   Heap left redzone:       fa
   Freed heap region:       fd
   Stack left redzone:      f1
   Stack mid redzone:       f2
   Stack right redzone:     f3
   Stack after return:      f5
   Stack use after scope:   f8
   Global redzone:          f9
   Global init order:       f6
   Poisoned by user:        f7
   Container overflow:      fc
   Array cookie:            ac
   Intra object redzone:    bb
   ASan internal:           fe
   Left alloca redzone:     ca
   Right alloca redzone:    cb
   Shadow gap:              cc
==3640549==ABORTING
---
  gatchat/gatmux.c | 32 +++++++++++++++++++++++++++-----
  1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/gatchat/gatmux.c b/gatchat/gatmux.c
index 757a5123..eabaa4db 100644
--- a/gatchat/gatmux.c
+++ b/gatchat/gatmux.c
@@ -227,12 +227,15 @@ static void dispatch_sources(GAtMuxChannel *channel, 
GIOCondition condition)
  static gboolean received_data(GIOChannel *channel, GIOCondition cond,
                                                        gpointer data)
  {
-       GAtMux *mux = data;
+       GAtMux *mux = g_at_mux_ref(data);
        int i;
        GIOStatus status;
        gsize bytes_read;
if (cond & G_IO_NVAL)
+               goto out_done;
+
+       if (mux->shutdown)
                return FALSE;
debug(mux, "received data");
@@ -270,15 +273,22 @@ static gboolean received_data(GIOChannel *channel, 
GIOCondition cond,
        }
if (cond & (G_IO_HUP | G_IO_ERR))
-               return FALSE;
+               goto out_done;
if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
-               return FALSE;
+               goto out_done;
if (mux->buf_used == sizeof(mux->buf))
-               return FALSE;
+               goto out_done;
+
+       g_at_mux_unref(mux);
return TRUE;
+
+out_done:
+       g_at_mux_unref(mux);
+
+       return FALSE;
  }
static void write_watcher_destroy_notify(gpointer user_data)
@@ -286,6 +296,9 @@ static void write_watcher_destroy_notify(gpointer user_data)
        GAtMux *mux = user_data;
mux->write_watch = 0;
+
+       if (mux->read_watch <= 0 && mux->write_watch <= 0)
+               g_free(mux);
  }
static gboolean can_write_data(GIOChannel *chan, GIOCondition cond,
@@ -297,6 +310,9 @@ static gboolean can_write_data(GIOChannel *chan, 
GIOCondition cond,
        if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
                return FALSE;
+ if (mux->shutdown)
+               return FALSE;
+
        debug(mux, "can write data");
for (dlc = 0; dlc < MAX_CHANNELS; dlc += 1) {
@@ -607,6 +623,7 @@ GAtMux *g_at_mux_new(GIOChannel *channel, const 
GAtMuxDriver *driver)
        if (mux == NULL)
                return NULL;
+
        mux->ref_count = 1;
        mux->driver = driver;
        mux->shutdown = TRUE;
@@ -642,7 +659,8 @@ void g_at_mux_unref(GAtMux *mux)
                if (mux->driver->remove)
                        mux->driver->remove(mux);
- g_free(mux);
+               if (mux->read_watch <= 0 && mux->write_watch <= 0)
+                       g_free(mux);
        }
  }
@@ -651,6 +669,9 @@ static void read_watcher_destroy_notify(gpointer user_data)
        GAtMux *mux = user_data;
mux->read_watch = 0;
+
+       if (mux->read_watch <= 0 && mux->write_watch <= 0)
+               g_free(mux);
  }
gboolean g_at_mux_start(GAtMux *mux)
@@ -695,6 +716,7 @@ gboolean g_at_mux_shutdown(GAtMux *mux)
                        continue;
channel_close((GIOChannel *) mux->dlcs[i], NULL);
+               mux->dlcs[i] = NULL;
        }
if (mux->driver->shutdown)

_______________________________________________
ofono mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to