Skip to content

Commit 00c0801

Browse files
GUIDINGLIxiaoxiang781216
authored andcommitted
local socket: fix accept used after free
==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 apache#3 0x3548f8c in net_sem_wait utils/net_lock.c:318 apache#4 0x350124d in local_accept local/local_accept.c:246 apache#5 0x3492719 in psock_accept socket/accept.c:149 apache#6 0x3492bcc in accept4 socket/accept.c:280 apache#7 0x662dc04 in accept net/lib_accept.c:50 apache#8 0x55c81ab in kvdb_loop kvdb/server.c:415 apache#9 0x55c860a in kvdbd_main kvdb/server.c:458 apache#10 0x33d968b in nxtask_startup sched/task_startup.c:70 apache#11 0x32ec039 in nxtask_start task/task_start.c:134 apache#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 apache#3 0x3409388 in free umm_heap/umm_free.c:49 apache#4 0x35631f3 in local_free local/local_conn.c:225 apache#5 0x3563f75 in local_release local/local_release.c:129 apache#6 0x34f5a32 in local_close local/local_sockif.c:785 apache#7 0x3496ee8 in psock_close socket/net_close.c:102 apache#8 0x36500bc in sock_file_close socket/socket.c:115 apache#9 0x3635f6c in file_close vfs/fs_close.c:74 apache#10 0x3632439 in nx_close_from_tcb inode/fs_files.c:670 apache#11 0x36324f3 in nx_close inode/fs_files.c:697 apache#12 0x3632557 in close inode/fs_files.c:735 apache#13 0x55be289 in property_set_ kvdb/client.c:210 apache#14 0x55c0309 in property_set_int32_ kvdb/common.c:226 apache#15 0x55c03f5 in property_set_int32_oneway kvdb/common.c:236 Signed-off-by: ligd <liguiding1@xiaomi.com>
1 parent 13f0051 commit 00c0801

File tree

4 files changed

+94
-26
lines changed

4 files changed

+94
-26
lines changed

net/local/local.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,40 @@ FAR struct local_conn_s *local_alloc(void);
223223

224224
void local_free(FAR struct local_conn_s *conn);
225225

226+
/****************************************************************************
227+
* Name: local_addref
228+
*
229+
* Description:
230+
* Increment the reference count on the underlying connection structure.
231+
*
232+
* Input Parameters:
233+
* conn - Socket structure of the socket whose reference count will be
234+
* incremented.
235+
*
236+
* Returned Value:
237+
* None
238+
*
239+
****************************************************************************/
240+
241+
void local_addref(FAR struct local_conn_s *conn);
242+
243+
/****************************************************************************
244+
* Name: local_subref
245+
*
246+
* Description:
247+
* Subtract the reference count on the underlying connection structure.
248+
*
249+
* Input Parameters:
250+
* conn - Socket structure of the socket whose reference count will be
251+
* incremented.
252+
*
253+
* Returned Value:
254+
* None
255+
*
256+
****************************************************************************/
257+
258+
void local_subref(FAR struct local_conn_s *conn);
259+
226260
/****************************************************************************
227261
* Name: local_nextconn
228262
*

net/local/local_accept.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
144144
client = container_of(waiter, struct local_conn_s,
145145
u.client.lc_waiter);
146146

147+
local_addref(client);
148+
147149
/* Decrement the number of pending clients */
148150

149151
DEBUGASSERT(server->u.server.lc_pending > 0);
@@ -163,7 +165,8 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
163165
{
164166
/* Initialize the new connection structure */
165167

166-
conn->lc_crefs = 1;
168+
local_addref(conn);
169+
167170
conn->lc_proto = SOCK_STREAM;
168171
conn->lc_type = LOCAL_TYPE_PATHNAME;
169172
conn->lc_state = LOCAL_STATE_CONNECTED;
@@ -246,6 +249,8 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
246249
ret = net_sem_wait(&client->lc_donesem);
247250
}
248251

252+
local_subref(client);
253+
249254
return ret;
250255
}
251256

net/local/local_conn.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,51 @@ void local_free(FAR struct local_conn_s *conn)
225225
kmm_free(conn);
226226
}
227227

228+
/****************************************************************************
229+
* Name: local_addref
230+
*
231+
* Description:
232+
* Increment the reference count on the underlying connection structure.
233+
*
234+
* Input Parameters:
235+
* psock - Socket structure of the socket whose reference count will be
236+
* incremented.
237+
*
238+
* Returned Value:
239+
* None
240+
*
241+
****************************************************************************/
242+
243+
void local_addref(FAR struct local_conn_s *conn)
244+
{
245+
DEBUGASSERT(conn->lc_crefs >= 0 && conn->lc_crefs < 255);
246+
conn->lc_crefs++;
247+
}
248+
249+
/****************************************************************************
250+
* Name: local_subref
251+
*
252+
* Description:
253+
* Subtract the reference count on the underlying connection structure.
254+
*
255+
* Input Parameters:
256+
* psock - Socket structure of the socket whose reference count will be
257+
* incremented.
258+
*
259+
* Returned Value:
260+
* None
261+
*
262+
****************************************************************************/
263+
264+
void local_subref(FAR struct local_conn_s *conn)
265+
{
266+
DEBUGASSERT(conn->lc_crefs > 0 && conn->lc_crefs < 255);
267+
268+
conn->lc_crefs--;
269+
if (conn->lc_crefs == 0)
270+
{
271+
local_release(conn);
272+
}
273+
}
274+
228275
#endif /* CONFIG_NET && CONFIG_NET_LOCAL */

net/local/local_sockif.c

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949

5050
static int local_setup(FAR struct socket *psock);
5151
static sockcaps_t local_sockcaps(FAR struct socket *psock);
52-
static void local_addref(FAR struct socket *psock);
52+
static void local_sockaddref(FAR struct socket *psock);
5353
static int local_bind(FAR struct socket *psock,
5454
FAR const struct sockaddr *addr, socklen_t addrlen);
5555
static int local_getsockname(FAR struct socket *psock,
@@ -80,7 +80,7 @@ const struct sock_intf_s g_local_sockif =
8080
{
8181
local_setup, /* si_setup */
8282
local_sockcaps, /* si_sockcaps */
83-
local_addref, /* si_addref */
83+
local_sockaddref, /* si_addref */
8484
local_bind, /* si_bind */
8585
local_getsockname, /* si_getsockname */
8686
local_getpeername, /* si_getpeername */
@@ -137,8 +137,7 @@ static int local_sockif_alloc(FAR struct socket *psock)
137137
* count will be incremented only if the socket is dup'ed
138138
*/
139139

140-
DEBUGASSERT(conn->lc_crefs == 0);
141-
conn->lc_crefs = 1;
140+
local_addref(conn);
142141

143142
/* Save the pre-allocated connection in the socket structure */
144143

@@ -243,7 +242,7 @@ static sockcaps_t local_sockcaps(FAR struct socket *psock)
243242
}
244243

245244
/****************************************************************************
246-
* Name: local_addref
245+
* Name: local_sockaddref
247246
*
248247
* Description:
249248
* Increment the reference count on the underlying connection structure.
@@ -257,15 +256,10 @@ static sockcaps_t local_sockcaps(FAR struct socket *psock)
257256
*
258257
****************************************************************************/
259258

260-
static void local_addref(FAR struct socket *psock)
259+
static void local_sockaddref(FAR struct socket *psock)
261260
{
262-
FAR struct local_conn_s *conn;
263-
264261
DEBUGASSERT(psock->s_domain == PF_LOCAL);
265-
266-
conn = psock->s_conn;
267-
DEBUGASSERT(conn->lc_crefs > 0 && conn->lc_crefs < 255);
268-
conn->lc_crefs++;
262+
local_addref(psock->s_conn);
269263
}
270264

271265
/****************************************************************************
@@ -773,23 +767,11 @@ static int local_close(FAR struct socket *psock)
773767
#endif
774768
case SOCK_CTRL:
775769
{
776-
FAR struct local_conn_s *conn = psock->s_conn;
777-
778770
/* Is this the last reference to the connection structure (there
779771
* could be more if the socket was dup'ed).
780772
*/
781773

782-
if (conn->lc_crefs <= 1)
783-
{
784-
conn->lc_crefs = 0;
785-
local_release(conn);
786-
}
787-
else
788-
{
789-
/* No.. Just decrement the reference count */
790-
791-
conn->lc_crefs--;
792-
}
774+
local_subref(psock->s_conn);
793775

794776
return OK;
795777
}

0 commit comments

Comments
 (0)