Re: [PATCH] avdtp: Fix crash on connection lost

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Szymon,

On Tue, Oct 16, 2012 at 2:37 PM, Szymon Janc <szymon.janc@xxxxxxxxx> wrote:
> This fix avdtp session reference counting. avdtp_unref has a special
> case when ref==1 and due to nested calls session could be free in
> consecutive call resulting in accesing already freed memory.
>
> Instead of having extra free lock keep extra local reference. This also
> make avdtp_unref easier to undertand as there is no double ref
> decrement inside one unref call.
>
> avdtp_unref will set session state to disconnected when reference count
> drops to 1 so there is no need to explicite set it in connection_lost.
>
> bluetoothd[29474]: audio/avdtp.c:avdtp_ref() 0x555555856aa0: ref=2
> bluetoothd[29474]: audio/source.c:source_connect() stream creation in progress
> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 31 bytes from management socket
> bluetoothd[29474]: src/mgmt.c:mgmt_device_connected() hci0 device 84:00:D2:DB:F7:8C connected eir_len 12
> bluetoothd[29474]: src/adapter.c:adapter_get_device() 84:00:D2:DB:F7:8C
> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 14 bytes from management socket
> bluetoothd[29474]: src/mgmt.c:mgmt_auth_failed() hci0 auth failed status 6
> bluetoothd[29474]: src/device.c:device_bonding_complete() bonding (nil) status 0x06
> bluetoothd[29474]: connect error: Invalid exchange (52)
> bluetoothd[29474]: audio/avdtp.c:connection_lost() Disconnected from 84:00:D2:DB:F7:8C
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=1
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=0
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
>
> Program received signal SIGSEGV, Segmentation fault.
> avdtp_unref (session=0x555555856aa0) at audio/avdtp.c:1239
> 1239            server->sessions = g_slist_remove(server->sessions, session);
>
> ---
>  audio/avdtp.c |   10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/audio/avdtp.c b/audio/avdtp.c
> index bd91cb6..4109be9 100644
> --- a/audio/avdtp.c
> +++ b/audio/avdtp.c
> @@ -388,7 +388,6 @@ struct avdtp_stream {
>
>  struct avdtp {
>         int ref;
> -       int free_lock;
>
>         uint16_t version;
>
> @@ -1158,14 +1157,14 @@ static void connection_lost(struct avdtp *session, int err)
>         if (err != EACCES)
>                 avdtp_cancel_authorization(session);
>
> -       session->free_lock = 1;
> +       avdtp_ref(session);
>
>         finalize_discovery(session, err);
>
>         g_slist_foreach(session->streams, (GFunc) release_stream, session);
>         session->streams = NULL;
>
> -       session->free_lock = 0;
> +       avdtp_unref(session);
>
>         if (session->io) {
>                 g_io_channel_shutdown(session->io, FALSE, NULL);
> @@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
>                 session->io = NULL;
>         }
>
> -       avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);

This is actually the one that we need in case we got disconnect by
remote after discovery completes. avctp.c has a similar structure to
handler such states, but without the refcounting all is much simpler.

>         if (session->io_id) {
>                 g_source_remove(session->io_id);
>                 session->io_id = 0;
> @@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
>
>                 if (session->io)
>                         set_disconnect_timer(session);
> -               else if (!session->free_lock) /* Drop the local ref if we
> -                                                aren't connected */
> -                       session->ref--;
>         }
>
>         if (session->ref > 0)
> --
> 1.7.9.5

We should probably get rid of the free_lock as well.

-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux