Skip to content

Commit 84eef2b

Browse files
kcp-gitdavem330
authored andcommitted
rds: Incorrect reference counting in TCP socket creation
Commit 0933a57 ("rds: tcp: use sock_create_lite() to create the accept socket") has a reference counting issue in TCP socket creation when accepting a new connection. The code uses sock_create_lite() to create a kernel socket. But it does not do __module_get() on the socket owner. When the connection is shutdown and sock_release() is called to free the socket, the owner's reference count is decremented and becomes incorrect. Note that this bug only shows up when the socket owner is configured as a kernel module. v2: Update comments Fixes: 0933a57 ("rds: tcp: use sock_create_lite() to create the accept socket") Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com> Acked-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a5f7b0e commit 84eef2b

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

net/rds/tcp_listen.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006 Oracle. All rights reserved.
2+
* Copyright (c) 2006, 2018 Oracle. All rights reserved.
33
*
44
* This software is available to you under a choice of one of two
55
* licenses. You may choose to be licensed under the terms of the GNU
@@ -142,12 +142,20 @@ int rds_tcp_accept_one(struct socket *sock)
142142
if (ret)
143143
goto out;
144144

145-
new_sock->type = sock->type;
146-
new_sock->ops = sock->ops;
147145
ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, true);
148146
if (ret < 0)
149147
goto out;
150148

149+
/* sock_create_lite() does not get a hold on the owner module so we
150+
* need to do it here. Note that sock_release() uses sock->ops to
151+
* determine if it needs to decrement the reference count. So set
152+
* sock->ops after calling accept() in case that fails. And there's
153+
* no need to do try_module_get() as the listener should have a hold
154+
* already.
155+
*/
156+
new_sock->ops = sock->ops;
157+
__module_get(new_sock->ops->owner);
158+
151159
ret = rds_tcp_keepalive(new_sock);
152160
if (ret < 0)
153161
goto out;

0 commit comments

Comments
 (0)