00c0801743
==1729315==ERROR: AddressSanitizer: heap-use-after-free on address 0xf0501d60 at pc 0x032ffe43 bp 0xef4ed158 sp 0xef4ed148 READ of size 2 at 0xf0501d60 thread T0 #0 0x32ffe42 in nxsem_wait semaphore/sem_wait.c:94 #1 0x3548cf5 in _net_timedwait utils/net_lock.c:97 #2 0x3548f48 in net_sem_timedwait utils/net_lock.c:236 #3 0x3548f8c in net_sem_wait utils/net_lock.c:318 #4 0x350124d in local_accept local/local_accept.c:246 #5 0x3492719 in psock_accept socket/accept.c:149 #6 0x3492bcc in accept4 socket/accept.c:280 #7 0x662dc04 in accept net/lib_accept.c:50 #8 0x55c81ab in kvdb_loop kvdb/server.c:415 #9 0x55c860a in kvdbd_main kvdb/server.c:458 #10 0x33d968b in nxtask_startup sched/task_startup.c:70 #11 0x32ec039 in nxtask_start task/task_start.c:134 #12 0x34109be in pre_start sim/sim_initialstate.c:52 0xf0501d60 is located 288 bytes inside of 420-byte region [0xf0501c40,0xf0501de4) freed by thread T0 here: #0 0xf7aa6a3f in __interceptor_free ../../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127 #1 0x73aa06e in host_free sim/posix/sim_hostmemory.c:192 #2 0x34131d6 in mm_free sim/sim_heap.c:230 #3 0x3409388 in free umm_heap/umm_free.c:49 #4 0x35631f3 in local_free local/local_conn.c:225 #5 0x3563f75 in local_release local/local_release.c:129 #6 0x34f5a32 in local_close local/local_sockif.c:785 #7 0x3496ee8 in psock_close socket/net_close.c:102 #8 0x36500bc in sock_file_close socket/socket.c:115 #9 0x3635f6c in file_close vfs/fs_close.c:74 #10 0x3632439 in nx_close_from_tcb inode/fs_files.c:670 #11 0x36324f3 in nx_close inode/fs_files.c:697 #12 0x3632557 in close inode/fs_files.c:735 #13 0x55be289 in property_set_ kvdb/client.c:210 #14 0x55c0309 in property_set_int32_ kvdb/common.c:226 #15 0x55c03f5 in property_set_int32_oneway kvdb/common.c:236 Signed-off-by: ligd <liguiding1@xiaomi.com>
276 lines
7.4 KiB
C
276 lines
7.4 KiB
C
/****************************************************************************
|
|
* net/local/local_conn.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
#include <unistd.h>
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
#include <nuttx/queue.h>
|
|
|
|
#include "local/local.h"
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/* A list of all allocated packet socket connections */
|
|
|
|
static dq_queue_t g_local_connections;
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: local_nextconn
|
|
*
|
|
* Description:
|
|
* Traverse the list of local connections
|
|
*
|
|
* Assumptions:
|
|
* This function must be called with the network locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct local_conn_s *local_nextconn(FAR struct local_conn_s *conn)
|
|
{
|
|
if (!conn)
|
|
{
|
|
return (FAR struct local_conn_s *)g_local_connections.head;
|
|
}
|
|
|
|
return (FAR struct local_conn_s *)conn->lc_conn.node.flink;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: local_peerconn
|
|
*
|
|
* Description:
|
|
* Traverse the connections list to find the peer
|
|
*
|
|
* Assumptions:
|
|
* This function must be called with the network locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct local_conn_s *local_peerconn(FAR struct local_conn_s *conn)
|
|
{
|
|
FAR struct local_conn_s *peer = NULL;
|
|
|
|
while ((peer = local_nextconn(peer)) != NULL)
|
|
{
|
|
if (conn->lc_proto == peer->lc_proto && conn != peer &&
|
|
!strncmp(conn->lc_path, peer->lc_path, UNIX_PATH_MAX - 1))
|
|
{
|
|
return peer;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: local_alloc()
|
|
*
|
|
* Description:
|
|
* Allocate a new, uninitialized Unix domain socket connection structure.
|
|
* This is normally something done by the implementation of the socket()
|
|
* API
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct local_conn_s *local_alloc(void)
|
|
{
|
|
FAR struct local_conn_s *conn =
|
|
kmm_zalloc(sizeof(struct local_conn_s));
|
|
|
|
if (conn != NULL)
|
|
{
|
|
/* Initialize non-zero elements the new connection structure. Since
|
|
* Since the memory was allocated with kmm_zalloc(), it is not
|
|
* necessary to zerio-ize any structure elements.
|
|
*/
|
|
|
|
#ifdef CONFIG_NET_LOCAL_STREAM
|
|
nxsem_init(&conn->lc_waitsem, 0, 0);
|
|
nxsem_init(&conn->lc_donesem, 0, 0);
|
|
|
|
#endif
|
|
|
|
/* This semaphore is used for sending safely in multithread.
|
|
* Make sure data will not be garbled when multi-thread sends.
|
|
*/
|
|
|
|
nxmutex_init(&conn->lc_sendlock);
|
|
nxmutex_init(&conn->lc_polllock);
|
|
|
|
#ifdef CONFIG_NET_LOCAL_SCM
|
|
conn->lc_cred.pid = nxsched_getpid();
|
|
conn->lc_cred.uid = getuid();
|
|
conn->lc_cred.gid = getgid();
|
|
#endif
|
|
|
|
/* Add the connection structure to the list of listeners */
|
|
|
|
net_lock();
|
|
dq_addlast(&conn->lc_conn.node, &g_local_connections);
|
|
net_unlock();
|
|
}
|
|
|
|
return conn;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: local_free()
|
|
*
|
|
* Description:
|
|
* Free a packet Unix domain connection structure that is no longer in use.
|
|
* This should be done by the implementation of close().
|
|
*
|
|
****************************************************************************/
|
|
|
|
void local_free(FAR struct local_conn_s *conn)
|
|
{
|
|
#ifdef CONFIG_NET_LOCAL_SCM
|
|
int i;
|
|
#endif /* CONFIG_NET_LOCAL_SCM */
|
|
|
|
DEBUGASSERT(conn != NULL);
|
|
|
|
/* Remove the server from the list of listeners. */
|
|
|
|
net_lock();
|
|
dq_rem(&conn->lc_conn.node, &g_local_connections);
|
|
|
|
if (local_peerconn(conn) && conn->lc_peer)
|
|
{
|
|
conn->lc_peer->lc_peer = NULL;
|
|
conn->lc_peer = NULL;
|
|
}
|
|
|
|
net_unlock();
|
|
|
|
/* Make sure that the read-only FIFO is closed */
|
|
|
|
if (conn->lc_infile.f_inode != NULL)
|
|
{
|
|
file_close(&conn->lc_infile);
|
|
conn->lc_infile.f_inode = NULL;
|
|
}
|
|
|
|
/* Make sure that the write-only FIFO is closed */
|
|
|
|
if (conn->lc_outfile.f_inode != NULL)
|
|
{
|
|
file_close(&conn->lc_outfile);
|
|
conn->lc_outfile.f_inode = NULL;
|
|
}
|
|
|
|
#ifdef CONFIG_NET_LOCAL_SCM
|
|
/* Free the pending control file pointer */
|
|
|
|
for (i = 0; i < conn->lc_cfpcount; i++)
|
|
{
|
|
if (conn->lc_cfps[i])
|
|
{
|
|
file_close(conn->lc_cfps[i]);
|
|
kmm_free(conn->lc_cfps[i]);
|
|
conn->lc_cfps[i] = NULL;
|
|
}
|
|
}
|
|
#endif /* CONFIG_NET_LOCAL_SCM */
|
|
|
|
#ifdef CONFIG_NET_LOCAL_STREAM
|
|
/* Destroy all FIFOs associted with the connection */
|
|
|
|
local_release_fifos(conn);
|
|
nxsem_destroy(&conn->lc_waitsem);
|
|
nxsem_destroy(&conn->lc_donesem);
|
|
#endif
|
|
|
|
/* Destory sem associated with the connection */
|
|
|
|
nxmutex_destroy(&conn->lc_sendlock);
|
|
nxmutex_destroy(&conn->lc_polllock);
|
|
|
|
/* And free the connection structure */
|
|
|
|
kmm_free(conn);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: local_addref
|
|
*
|
|
* Description:
|
|
* Increment the reference count on the underlying connection structure.
|
|
*
|
|
* Input Parameters:
|
|
* psock - Socket structure of the socket whose reference count will be
|
|
* incremented.
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
void local_addref(FAR struct local_conn_s *conn)
|
|
{
|
|
DEBUGASSERT(conn->lc_crefs >= 0 && conn->lc_crefs < 255);
|
|
conn->lc_crefs++;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: local_subref
|
|
*
|
|
* Description:
|
|
* Subtract the reference count on the underlying connection structure.
|
|
*
|
|
* Input Parameters:
|
|
* psock - Socket structure of the socket whose reference count will be
|
|
* incremented.
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
void local_subref(FAR struct local_conn_s *conn)
|
|
{
|
|
DEBUGASSERT(conn->lc_crefs > 0 && conn->lc_crefs < 255);
|
|
|
|
conn->lc_crefs--;
|
|
if (conn->lc_crefs == 0)
|
|
{
|
|
local_release(conn);
|
|
}
|
|
}
|
|
|
|
#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
|