b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | commit f0ff5817d0647bdecd1ec99488db9378e304cf83 |
| 2 | Author: sauwming <ming@teluu.com> |
| 3 | Date: Mon May 17 09:56:27 2021 +0800 |
| 4 | |
| 5 | Fix double free of stun session (#2709) |
| 6 | |
| 7 | --- a/pjnath/include/pjnath/stun_session.h |
| 8 | +++ b/pjnath/include/pjnath/stun_session.h |
| 9 | @@ -341,6 +341,7 @@ struct pj_stun_tx_data |
| 10 | pj_pool_t *pool; /**< Pool. */ |
| 11 | pj_stun_session *sess; /**< The STUN session. */ |
| 12 | pj_stun_msg *msg; /**< The STUN message. */ |
| 13 | + pj_bool_t is_destroying; /**< Is destroying? */ |
| 14 | |
| 15 | void *token; /**< The token. */ |
| 16 | |
| 17 | --- a/pjnath/src/pjnath/stun_session.c |
| 18 | +++ b/pjnath/src/pjnath/stun_session.c |
| 19 | @@ -167,16 +167,27 @@ static void tdata_on_destroy(void *arg) |
| 20 | { |
| 21 | pj_stun_tx_data *tdata = (pj_stun_tx_data*)arg; |
| 22 | |
| 23 | + if (tdata->grp_lock) { |
| 24 | + pj_grp_lock_dec_ref(tdata->sess->grp_lock); |
| 25 | + } |
| 26 | + |
| 27 | pj_pool_safe_release(&tdata->pool); |
| 28 | } |
| 29 | |
| 30 | static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force) |
| 31 | { |
| 32 | - TRACE_((THIS_FILE, "tdata %p destroy request, force=%d, tsx=%p", tdata, |
| 33 | - force, tdata->client_tsx)); |
| 34 | + TRACE_((THIS_FILE, |
| 35 | + "tdata %p destroy request, force=%d, tsx=%p, destroying=%d", |
| 36 | + tdata, force, tdata->client_tsx, tdata->is_destroying)); |
| 37 | + |
| 38 | + /* Just return if destroy has been requested before */ |
| 39 | + if (tdata->is_destroying) |
| 40 | + return; |
| 41 | |
| 42 | /* STUN session may have been destroyed, except when tdata is cached. */ |
| 43 | |
| 44 | + tdata->is_destroying = PJ_TRUE; |
| 45 | + |
| 46 | if (tdata->res_timer.id != PJ_FALSE) { |
| 47 | pj_timer_heap_cancel_if_active(tdata->sess->cfg->timer_heap, |
| 48 | &tdata->res_timer, PJ_FALSE); |
| 49 | @@ -189,7 +200,6 @@ static void destroy_tdata(pj_stun_tx_dat |
| 50 | pj_stun_client_tsx_set_data(tdata->client_tsx, NULL); |
| 51 | } |
| 52 | if (tdata->grp_lock) { |
| 53 | - pj_grp_lock_dec_ref(tdata->sess->grp_lock); |
| 54 | pj_grp_lock_dec_ref(tdata->grp_lock); |
| 55 | } else { |
| 56 | tdata_on_destroy(tdata); |
| 57 | @@ -200,11 +210,11 @@ static void destroy_tdata(pj_stun_tx_dat |
| 58 | /* "Probably" this is to absorb retransmission */ |
| 59 | pj_time_val delay = {0, 300}; |
| 60 | pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay); |
| 61 | + tdata->is_destroying = PJ_FALSE; |
| 62 | |
| 63 | } else { |
| 64 | pj_list_erase(tdata); |
| 65 | if (tdata->grp_lock) { |
| 66 | - pj_grp_lock_dec_ref(tdata->sess->grp_lock); |
| 67 | pj_grp_lock_dec_ref(tdata->grp_lock); |
| 68 | } else { |
| 69 | tdata_on_destroy(tdata); |
| 70 | @@ -238,7 +248,7 @@ static void on_cache_timeout(pj_timer_he |
| 71 | sess = tdata->sess; |
| 72 | |
| 73 | pj_grp_lock_acquire(sess->grp_lock); |
| 74 | - if (sess->is_destroying) { |
| 75 | + if (sess->is_destroying || tdata->is_destroying) { |
| 76 | pj_grp_lock_release(sess->grp_lock); |
| 77 | return; |
| 78 | } |