netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] SCTP: fix race between sctp_bind_addr_free() and sctp_bind_addr_conflict()
@ 2011-05-18  7:01 Jacek Luczak
  2011-05-18  7:48 ` Eric Dumazet
  0 siblings, 1 reply; 16+ messages in thread
From: Jacek Luczak @ 2011-05-18  7:01 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 1717 bytes --]

During the sctp_close() call, we do not use rcu primitives to
destroy the address list attached to the endpoint.  At the same
time, we do the removal of addresses from this list before
attempting to remove the socket from the port hash

As a result, it is possible for another process to find the socket
in the port hash that is in the process of being closed.  It then
proceeds to traverse the address list to find the conflict, only
to have that address list suddenly disappear without rcu() critical
section.

This can result in a kernel crash with general protection fault or
kernel NULL pointer dereference.

Fix issue by closing address list removal inside RCU critical
section.

Signed-off-by: Jacek Luczak <luczak.jacek@gmail.com>
Acked-by: Vlad Yasevich <vladislav.yasevich@hp.com>

---
 bind_addr.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index faf71d1..19d1329 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -155,8 +155,16 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
 /* Dispose of an SCTP_bind_addr structure  */
 void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 {
-       /* Empty the bind address list. */
-       sctp_bind_addr_clean(bp);
+       struct sctp_sockaddr_entry *addr;
+
+       /* Empty the bind address list inside RCU section. */
+       rcu_read_lock();
+       list_for_each_entry_rcu(addr, &bp->address_list, list) {
+               list_del_rcu(&addr->list);
+               call_rcu(&addr->rcu, sctp_local_addr_free);
+               SCTP_DBG_OBJCNT_DEC(addr);
+       }
+       rcu_read_unlock();

        if (bp->malloced) {
                kfree(bp);

[-- Attachment #2: sctp_fix_close_vs_conflict_race_in_bind_addr.patch --]
[-- Type: application/octet-stream, Size: 732 bytes --]

diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index faf71d1..19d1329 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -155,8 +155,16 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
 /* Dispose of an SCTP_bind_addr structure  */
 void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 {
-	/* Empty the bind address list. */
-	sctp_bind_addr_clean(bp);
+	struct sctp_sockaddr_entry *addr;
+
+	/* Empty the bind address list inside RCU section. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(addr, &bp->address_list, list) {
+		list_del_rcu(&addr->list);
+		call_rcu(&addr->rcu, sctp_local_addr_free);
+		SCTP_DBG_OBJCNT_DEC(addr);
+	}
+	rcu_read_unlock();
 
 	if (bp->malloced) {
 		kfree(bp);

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-05-18 13:44 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-18  7:01 [PATCH] SCTP: fix race between sctp_bind_addr_free() and sctp_bind_addr_conflict() Jacek Luczak
2011-05-18  7:48 ` Eric Dumazet
2011-05-18  8:06   ` Jacek Luczak
2011-05-18  8:29     ` Eric Dumazet
2011-05-18  9:02       ` Wei Yongjun
2011-05-18 11:01         ` Jacek Luczak
2011-05-18 11:41           ` Eric Dumazet
2011-05-18 11:58             ` Jacek Luczak
2011-05-18 12:33         ` Vladislav Yasevich
2011-05-18 12:47           ` Jacek Luczak
2011-05-18 12:50             ` Eric Dumazet
2011-05-18 13:11               ` Jacek Luczak
2011-05-18 13:20                 ` Eric Dumazet
2011-05-18 13:32                 ` Vladislav Yasevich
2011-05-18 13:39                   ` Jacek Luczak
2011-05-18 12:06       ` Jacek Luczak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).