forked from luck/tmp_suning_uos_patched
rds: Incorrect reference counting in TCP socket creation
Commit0933a578cd
("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:0933a578cd
("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>
This commit is contained in:
parent
a5f7b0eeb2
commit
84eef2b218
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Oracle. All rights reserved.
|
||||
* Copyright (c) 2006, 2018 Oracle. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* 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)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
new_sock->type = sock->type;
|
||||
new_sock->ops = sock->ops;
|
||||
ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, true);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* sock_create_lite() does not get a hold on the owner module so we
|
||||
* need to do it here. Note that sock_release() uses sock->ops to
|
||||
* determine if it needs to decrement the reference count. So set
|
||||
* sock->ops after calling accept() in case that fails. And there's
|
||||
* no need to do try_module_get() as the listener should have a hold
|
||||
* already.
|
||||
*/
|
||||
new_sock->ops = sock->ops;
|
||||
__module_get(new_sock->ops->owner);
|
||||
|
||||
ret = rds_tcp_keepalive(new_sock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
|
Loading…
Reference in New Issue
Block a user