Sometimes when RFCOMM creates underlying L2CAP socket it happens that rfcomm_security_cfm is called before DLC is linked to session thus reference count for session struct is 0. As a result rfcomm_session_put will close session and connection will not be completed. __rfcomm_dlc_open will now hold reference to rfcomm_session until DLC is linked to session to prevent the above from happening. Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@xxxxxxxxx> --- net/bluetooth/rfcomm/core.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 8743f36..461ce08 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -406,13 +406,17 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, s = rfcomm_session_create(src, dst, d->sec_level, &err); if (!s) return err; + } else { + rfcomm_session_hold(s); } dlci = __dlci(!s->initiator, channel); /* Check if DLCI already exists */ - if (rfcomm_dlc_get(s, dlci)) + if (rfcomm_dlc_get(s, dlci)) { + rfcomm_session_put(s); return -EBUSY; + } rfcomm_dlc_clear_state(d); @@ -428,6 +432,9 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, d->mtu = s->mtu; d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc; + /* Release internal reference to session */ + rfcomm_session_put(s); + if (s->state == BT_CONNECTED) { if (rfcomm_check_security(d)) rfcomm_send_pn(s, 1, d); @@ -720,6 +727,8 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, goto failed; } + rfcomm_session_hold(s); + s->initiator = 1; bacpy(&addr.l2_bdaddr, dst); -- on behalf of ST-Ericsson -- 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