diff options
author | santosh.shilimkar@oracle.com <santosh.shilimkar@oracle.com> | 2015-08-22 18:45:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-25 16:35:31 -0400 |
commit | dfcec251d22bab947d10cf37e9ad67085cf7f097 (patch) | |
tree | dd9ef3f30a176b7aebe4dd24f9c73a1ff49939a9 /net/rds | |
parent | 1c3be624f40acd6f2bd0f22ade081ac2467e8617 (diff) |
RDS: make sure rds_send_drop_to properly takes the m_rs_lock
rds_send_drop_to() is used during socket tear down to find all the
messages on the socket and flush them . It can race with the
acking code unless it takes the m_rs_lock on each and every message.
This plugs a hole where we didn't take m_rs_lock on any message that
didn't have the RDS_MSG_ON_CONN set. Taking m_rs_lock avoids
double frees and other memory corruptions as the ack code trusts
the message m_rs pointer on a socket that had actually been freed.
We must take m_rs_lock to access m_rs. Because of lock nesting and
rs access, we also need to acquire rs_lock.
Reviewed-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
Signed-off-by: Santosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds')
-rw-r--r-- | net/rds/send.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/net/rds/send.c b/net/rds/send.c index faad1be61ab6..b40c2ea8e89a 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -778,8 +778,22 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
778 | while (!list_empty(&list)) { | 778 | while (!list_empty(&list)) { |
779 | rm = list_entry(list.next, struct rds_message, m_sock_item); | 779 | rm = list_entry(list.next, struct rds_message, m_sock_item); |
780 | list_del_init(&rm->m_sock_item); | 780 | list_del_init(&rm->m_sock_item); |
781 | |||
782 | rds_message_wait(rm); | 781 | rds_message_wait(rm); |
782 | |||
783 | /* just in case the code above skipped this message | ||
784 | * because RDS_MSG_ON_CONN wasn't set, run it again here | ||
785 | * taking m_rs_lock is the only thing that keeps us | ||
786 | * from racing with ack processing. | ||
787 | */ | ||
788 | spin_lock_irqsave(&rm->m_rs_lock, flags); | ||
789 | |||
790 | spin_lock(&rs->rs_lock); | ||
791 | __rds_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
792 | spin_unlock(&rs->rs_lock); | ||
793 | |||
794 | rm->m_rs = NULL; | ||
795 | spin_unlock_irqrestore(&rm->m_rs_lock, flags); | ||
796 | |||
783 | rds_message_put(rm); | 797 | rds_message_put(rm); |
784 | } | 798 | } |
785 | } | 799 | } |