net/poll: fix race condition if connect free before poll teardown
Net poll teardown is not protected by net lock, if the conn is released before teardown, the assertion failure will be triggered during free dev callback, this patch will add the net lock around net poll teardown to fix race condition nuttx/libs/libc/assert/lib_assert.c:36 nuttx/net/devif/devif_callback.c:85 nuttx/net/tcp/tcp_netpoll.c:405 nuttx/fs/vfs/fs_poll.c:244 nuttx/fs/vfs/fs_poll.c:500 Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
da69b013bc
commit
8ae8c10954
@ -142,17 +142,25 @@ static uint16_t icmp_poll_eventhandler(FAR struct net_driver_s *dev,
|
||||
|
||||
int icmp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct icmp_conn_s *conn = psock->s_conn;
|
||||
FAR struct icmp_conn_s *conn;
|
||||
FAR struct icmp_poll_s *info;
|
||||
FAR struct devif_callback_s *cb;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(conn != NULL && fds != NULL);
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!conn || !fds)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Find a container to hold the poll information */
|
||||
|
||||
info = conn->pollinfo;
|
||||
@ -250,15 +258,24 @@ int icmp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
FAR struct icmp_conn_s *conn;
|
||||
FAR struct icmp_poll_s *info;
|
||||
|
||||
DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
|
||||
fds != NULL && fds->priv != NULL);
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!conn || !fds->priv)
|
||||
{
|
||||
net_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Recover the socket descriptor poll state info from the poll structure */
|
||||
|
||||
info = (FAR struct icmp_poll_s *)fds->priv;
|
||||
DEBUGASSERT(info != NULL && info->fds != NULL && info->cb != NULL);
|
||||
DEBUGASSERT(info->fds != NULL && info->cb != NULL);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
@ -275,5 +292,7 @@ int icmp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
info->psock = NULL;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -142,17 +142,25 @@ static uint16_t icmpv6_poll_eventhandler(FAR struct net_driver_s *dev,
|
||||
|
||||
int icmpv6_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct icmpv6_conn_s *conn = psock->s_conn;
|
||||
FAR struct icmpv6_conn_s *conn;
|
||||
FAR struct icmpv6_poll_s *info;
|
||||
FAR struct devif_callback_s *cb;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(conn != NULL && fds != NULL);
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!conn || !fds)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Find a container to hold the poll information */
|
||||
|
||||
info = conn->pollinfo;
|
||||
@ -250,15 +258,24 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
FAR struct icmpv6_conn_s *conn;
|
||||
FAR struct icmpv6_poll_s *info;
|
||||
|
||||
DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
|
||||
fds != NULL && fds->priv != NULL);
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!conn || !fds->priv)
|
||||
{
|
||||
net_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Recover the socket descriptor poll state info from the poll structure */
|
||||
|
||||
info = (FAR struct icmpv6_poll_s *)fds->priv;
|
||||
DEBUGASSERT(info != NULL && info->fds != NULL && info->cb != NULL);
|
||||
DEBUGASSERT(info->fds != NULL && info->cb != NULL);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
@ -275,5 +292,7 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
info->psock = NULL;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -198,25 +198,26 @@ static uint16_t tcp_poll_eventhandler(FAR struct net_driver_s *dev,
|
||||
|
||||
int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn = psock->s_conn;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
FAR struct tcp_poll_s *info;
|
||||
FAR struct devif_callback_s *cb;
|
||||
bool nonblock_conn;
|
||||
int ret = OK;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!conn || !fds)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (!conn || !fds)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Non-blocking connection ? */
|
||||
|
||||
nonblock_conn = (conn->tcpstateflags == TCP_SYN_SENT &&
|
||||
@ -382,22 +383,27 @@ errout_with_lock:
|
||||
|
||||
int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn = psock->s_conn;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
FAR struct tcp_poll_s *info;
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!conn || !fds->priv)
|
||||
{
|
||||
net_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Recover the socket descriptor poll state info from the poll structure */
|
||||
|
||||
info = (FAR struct tcp_poll_s *)fds->priv;
|
||||
DEBUGASSERT(info != NULL && info->fds != NULL && info->cb != NULL);
|
||||
DEBUGASSERT(info->fds != NULL && info->cb != NULL);
|
||||
if (info != NULL)
|
||||
{
|
||||
/* Release the callback */
|
||||
@ -413,5 +419,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
info->conn = NULL;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -132,24 +132,25 @@ static uint16_t udp_poll_eventhandler(FAR struct net_driver_s *dev,
|
||||
|
||||
int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct udp_conn_s *conn = psock->s_conn;
|
||||
FAR struct udp_conn_s *conn;
|
||||
FAR struct udp_poll_s *info;
|
||||
FAR struct devif_callback_s *cb;
|
||||
int ret = OK;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (conn == NULL || fds == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (conn == NULL || fds == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Find a container to hold the poll information */
|
||||
|
||||
info = conn->pollinfo;
|
||||
@ -257,22 +258,27 @@ errout_with_lock:
|
||||
|
||||
int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct udp_conn_s *conn = psock->s_conn;
|
||||
FAR struct udp_conn_s *conn;
|
||||
FAR struct udp_poll_s *info;
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!conn || !fds->priv)
|
||||
{
|
||||
net_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Recover the socket descriptor poll state info from the poll structure */
|
||||
|
||||
info = (FAR struct udp_poll_s *)fds->priv;
|
||||
DEBUGASSERT(info != NULL && info->fds != NULL && info->cb != NULL);
|
||||
DEBUGASSERT(info->fds != NULL && info->cb != NULL);
|
||||
if (info != NULL)
|
||||
{
|
||||
/* Release the callback */
|
||||
@ -288,5 +294,7 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
info->conn = NULL;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user