blob: f1691b9dba9d9a13238b9d1b1feaa789251f304b [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001commit f0ff5817d0647bdecd1ec99488db9378e304cf83
2Author: sauwming <ming@teluu.com>
3Date: 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 }