net: tcp: Accept connections only in LISTENING state
Issue noticed with following scenario.
1) TCP server is listening for connections but will handle
only one connection at a time (e.g. echo-server sample)
2) Client A connects, and the connection is accepted.
3) Client B connects, instead of denying a connection,
it is "auto" accepted (this is the actual bug) even
if the application has not called accept().
4) After the connection A is closed, the connection B
gets accepted by application but now the closed
connection A will cause confusion in the net-stack
5) This confusion can cause memory leak or double free
in the TCP core.
It is not easy to trigger this issue because it depends
on timing of the connections A & B.
Fixes: #18308
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
parent
8fa6dfbe5a
commit
1a6f4a6368
@ -2266,6 +2266,11 @@ NET_CONN_CB(tcp_syn_rcvd)
|
||||
|
||||
switch (net_tcp_get_state(tcp)) {
|
||||
case NET_TCP_LISTEN:
|
||||
if (net_context_get_state(context) != NET_CONTEXT_LISTENING) {
|
||||
NET_DBG("Context %p is not listening", context);
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
net_context_set_iface(context, net_pkt_iface(pkt));
|
||||
break;
|
||||
case NET_TCP_SYN_RCVD:
|
||||
@ -2452,6 +2457,14 @@ NET_CONN_CB(tcp_syn_rcvd)
|
||||
0,
|
||||
context->user_data);
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
/* Set the context in CONNECTED state, so that it can not
|
||||
* accept any new connections. If application is ready to
|
||||
* accept the connection, zsock_accept_ctx() will set
|
||||
* the state back to LISTENING.
|
||||
*/
|
||||
net_context_set_state(context, NET_CONTEXT_CONNECTED);
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -385,6 +385,10 @@ int zsock_accept_ctx(struct net_context *parent, struct sockaddr *addr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (net_context_get_ip_proto(parent) == IPPROTO_TCP) {
|
||||
net_context_set_state(parent, NET_CONTEXT_LISTENING);
|
||||
}
|
||||
|
||||
struct net_context *ctx = k_fifo_get(&parent->accept_q, K_FOREVER);
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
||||
Loading…
Reference in New Issue
Block a user