Skip to content

Commit 9d801c4

Browse files
dnejezchlebaescolar
authored andcommitted
net: tcp: Fix possible deadlock in tcp
The mutex was removed in tcp_recv() where it doesn't seem to be needed anymore as tcp_conn_search() got tcp_mutex. In the other areas the tcp_mutex was narrowed down to protect only the list. Signed-off-by: Daniel Nejezchleb <[email protected]>
1 parent ebced02 commit 9d801c4

File tree

1 file changed

+9
-14
lines changed

1 file changed

+9
-14
lines changed

subsys/net/ip/tcp.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,6 @@ static void tcp_conn_release(struct k_work *work)
720720
}
721721
#endif
722722

723-
k_mutex_lock(&tcp_lock, K_FOREVER);
724-
725723
/* Application is no longer there, unref any remaining packets on the
726724
* fifo (although there shouldn't be any at this point.)
727725
*/
@@ -761,11 +759,11 @@ static void tcp_conn_release(struct k_work *work)
761759
net_context_unref(conn->context);
762760
conn->context = NULL;
763761

762+
k_mutex_lock(&tcp_lock, K_FOREVER);
764763
sys_slist_find_and_remove(&tcp_conns, &conn->next);
764+
k_mutex_unlock(&tcp_lock);
765765

766766
k_mem_slab_free(&tcp_conns_slab, (void *)conn);
767-
768-
k_mutex_unlock(&tcp_lock);
769767
}
770768

771769
#if defined(CONFIG_NET_TEST)
@@ -2092,7 +2090,9 @@ static struct tcp *tcp_conn_alloc(void)
20922090

20932091
tcp_conn_ref(conn);
20942092

2093+
k_mutex_lock(&tcp_lock, K_FOREVER);
20952094
sys_slist_append(&tcp_conns, &conn->next);
2095+
k_mutex_unlock(&tcp_lock);
20962096
out:
20972097
NET_DBG("conn: %p", conn);
20982098

@@ -2113,19 +2113,15 @@ int net_tcp_get(struct net_context *context)
21132113
int ret = 0;
21142114
struct tcp *conn;
21152115

2116-
k_mutex_lock(&tcp_lock, K_FOREVER);
2117-
21182116
conn = tcp_conn_alloc();
21192117
if (conn == NULL) {
21202118
ret = -ENOMEM;
2121-
goto out;
2119+
return ret;
21222120
}
21232121

21242122
/* Mutually link the net_context and tcp connection */
21252123
conn->context = context;
21262124
context->tcp = conn;
2127-
out:
2128-
k_mutex_unlock(&tcp_lock);
21292125

21302126
return ret;
21312127
}
@@ -2154,13 +2150,17 @@ static struct tcp *tcp_conn_search(struct net_pkt *pkt)
21542150
struct tcp *conn;
21552151
struct tcp *tmp;
21562152

2153+
k_mutex_lock(&tcp_lock, K_FOREVER);
2154+
21572155
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
21582156
found = tcp_conn_cmp(conn, pkt);
21592157
if (found) {
21602158
break;
21612159
}
21622160
}
21632161

2162+
k_mutex_unlock(&tcp_lock);
2163+
21642164
return found ? conn : NULL;
21652165
}
21662166

@@ -2179,8 +2179,6 @@ static enum net_verdict tcp_recv(struct net_conn *net_conn,
21792179
ARG_UNUSED(net_conn);
21802180
ARG_UNUSED(proto);
21812181

2182-
k_mutex_lock(&tcp_lock, K_FOREVER);
2183-
21842182
conn = tcp_conn_search(pkt);
21852183
if (conn) {
21862184
goto in;
@@ -2200,8 +2198,6 @@ static enum net_verdict tcp_recv(struct net_conn *net_conn,
22002198
conn->accepted_conn = conn_old;
22012199
}
22022200
in:
2203-
k_mutex_unlock(&tcp_lock);
2204-
22052201
if (conn) {
22062202
verdict = tcp_in(conn, pkt);
22072203
} else {
@@ -4270,7 +4266,6 @@ void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
42704266
k_mutex_lock(&tcp_lock, K_FOREVER);
42714267

42724268
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
4273-
42744269
if (atomic_get(&conn->ref_count) > 0) {
42754270
k_mutex_unlock(&tcp_lock);
42764271
cb(conn, user_data);

0 commit comments

Comments
 (0)