Merge pull request #775 from micmac1/chan-dongle-iconv-update
[feed/telephony.git] / libs / pjproject / patches / 0110-tls-parent-listener-destroyed.patch
1 From bb92c97ea512aa0ef316c9b2335c7d57b84dfc9a Mon Sep 17 00:00:00 2001
2 From: Nanang Izzuddin <nanang@teluu.com>
3 Date: Wed, 16 Jun 2021 12:12:35 +0700
4 Subject: [PATCH 1/2] - Avoid SSL socket parent/listener getting destroyed
5 during handshake by increasing parent's reference count. - Add missing SSL
6 socket close when the newly accepted SSL socket is discarded in SIP TLS
7 transport.
8
9 ---
10 pjlib/src/pj/ssl_sock_imp_common.c | 44 +++++++++++++++++++++--------
11 pjsip/src/pjsip/sip_transport_tls.c | 23 ++++++++++++++-
12 2 files changed, 55 insertions(+), 12 deletions(-)
13
14 --- a/pjlib/src/pj/ssl_sock_imp_common.c
15 +++ b/pjlib/src/pj/ssl_sock_imp_common.c
16 @@ -224,6 +224,8 @@ static pj_bool_t on_handshake_complete(p
17
18 /* Accepting */
19 if (ssock->is_server) {
20 + pj_bool_t ret = PJ_TRUE;
21 +
22 if (status != PJ_SUCCESS) {
23 /* Handshake failed in accepting, destroy our self silently. */
24
25 @@ -241,6 +243,12 @@ static pj_bool_t on_handshake_complete(p
26 status);
27 }
28
29 + /* Decrement ref count of parent */
30 + if (ssock->parent->param.grp_lock) {
31 + pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
32 + ssock->parent = NULL;
33 + }
34 +
35 /* Originally, this is a workaround for ticket #985. However,
36 * a race condition may occur in multiple worker threads
37 * environment when we are destroying SSL objects while other
38 @@ -284,23 +292,29 @@ static pj_bool_t on_handshake_complete(p
39
40 return PJ_FALSE;
41 }
42 +
43 /* Notify application the newly accepted SSL socket */
44 if (ssock->param.cb.on_accept_complete2) {
45 - pj_bool_t ret;
46 ret = (*ssock->param.cb.on_accept_complete2)
47 (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
48 pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr),
49 status);
50 - if (ret == PJ_FALSE)
51 - return PJ_FALSE;
52 } else if (ssock->param.cb.on_accept_complete) {
53 - pj_bool_t ret;
54 ret = (*ssock->param.cb.on_accept_complete)
55 (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
56 pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
57 - if (ret == PJ_FALSE)
58 - return PJ_FALSE;
59 }
60 +
61 + /* Decrement ref count of parent and reset parent (we don't need it
62 + * anymore, right?).
63 + */
64 + if (ssock->parent->param.grp_lock) {
65 + pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
66 + ssock->parent = NULL;
67 + }
68 +
69 + if (ret == PJ_FALSE)
70 + return PJ_FALSE;
71 }
72
73 /* Connecting */
74 @@ -864,9 +878,13 @@ static pj_bool_t asock_on_accept_complet
75 if (status != PJ_SUCCESS)
76 goto on_return;
77
78 + /* Set parent and add ref count (avoid parent destroy during handshake) */
79 + ssock->parent = ssock_parent;
80 + if (ssock->parent->param.grp_lock)
81 + pj_grp_lock_add_ref(ssock->parent->param.grp_lock);
82 +
83 /* Update new SSL socket attributes */
84 ssock->sock = newsock;
85 - ssock->parent = ssock_parent;
86 ssock->is_server = PJ_TRUE;
87 if (ssock_parent->cert) {
88 status = pj_ssl_sock_set_certificate(ssock, ssock->pool,
89 @@ -913,16 +931,20 @@ static pj_bool_t asock_on_accept_complet
90 ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool,
91 ssock->param.async_cnt,
92 sizeof(void*));
93 - if (!ssock->asock_rbuf)
94 - return PJ_ENOMEM;
95 + if (!ssock->asock_rbuf) {
96 + status = PJ_ENOMEM;
97 + goto on_return;
98 + }
99
100 for (i = 0; i<ssock->param.async_cnt; ++i) {
101 - ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
102 + ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
103 ssock->pool,
104 ssock->param.read_buffer_size +
105 sizeof(read_data_t*));
106 - if (!ssock->asock_rbuf[i])
107 - return PJ_ENOMEM;
108 + if (!ssock->asock_rbuf[i]) {
109 + status = PJ_ENOMEM;
110 + goto on_return;
111 + }
112 }
113
114 /* Create active socket */
115 --- a/pjsip/src/pjsip/sip_transport_tls.c
116 +++ b/pjsip/src/pjsip/sip_transport_tls.c
117 @@ -1325,9 +1325,26 @@ static pj_bool_t on_accept_complete2(pj_
118 PJ_UNUSED_ARG(src_addr_len);
119
120 listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);
121 + if (!listener) {
122 + /* Listener already destroyed, e.g: after TCP accept but before SSL
123 + * handshake is completed.
124 + */
125 + if (new_ssock && accept_status == PJ_SUCCESS) {
126 + /* Close the SSL socket if the accept op is successful */
127 + PJ_LOG(4,(THIS_FILE,
128 + "Incoming TLS connection from %s (sock=%d) is discarded "
129 + "because listener is already destroyed",
130 + pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
131 + new_ssock));
132 +
133 + pj_ssl_sock_close(new_ssock);
134 + }
135 +
136 + return PJ_FALSE;
137 + }
138
139 if (accept_status != PJ_SUCCESS) {
140 - if (listener && listener->tls_setting.on_accept_fail_cb) {
141 + if (listener->tls_setting.on_accept_fail_cb) {
142 pjsip_tls_on_accept_fail_param param;
143 pj_ssl_sock_info ssi;
144
145 @@ -1350,6 +1367,8 @@ static pj_bool_t on_accept_complete2(pj_
146 PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);
147
148 if (!listener->is_registered) {
149 + pj_ssl_sock_close(new_ssock);
150 +
151 if (listener->tls_setting.on_accept_fail_cb) {
152 pjsip_tls_on_accept_fail_param param;
153 pj_bzero(&param, sizeof(param));
154 @@ -1401,6 +1420,8 @@ static pj_bool_t on_accept_complete2(pj_
155 ssl_info.grp_lock, &tls);
156
157 if (status != PJ_SUCCESS) {
158 + pj_ssl_sock_close(new_ssock);
159 +
160 if (listener->tls_setting.on_accept_fail_cb) {
161 pjsip_tls_on_accept_fail_param param;
162 pj_bzero(&param, sizeof(param));