]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: Fix an rcu race with rds_bin_lookup
authorTina Yang <tina.yang@oracle.com>
Fri, 3 Feb 2012 16:08:50 +0000 (11:08 -0500)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 23:41:31 +0000 (16:41 -0700)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Signed-off-by: Bang Nguyen <bang.nguyen@oracle.com>
net/rds/bind.c

index 2f6b3fcc79f81b9985ca5774a7fa3e070a105d11..4f0644c0e86b0346132d0a33b9d70b7d6f3271ae 100644 (file)
@@ -62,6 +62,7 @@ static struct rds_sock *rds_bind_lookup(__be32 addr, __be16 port,
                      be16_to_cpu(rs->rs_bound_port);
 
                if (cmp == needle) {
+                       rds_sock_addref(rs);
                        rcu_read_unlock();
                        return rs;
                }
@@ -96,10 +97,10 @@ struct rds_sock *rds_find_bound(__be32 addr, __be16 port)
 
        rs = rds_bind_lookup(addr, port, NULL);
 
-       if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
-               rds_sock_addref(rs);
-       else
+       if (rs && sock_flag(rds_rs_to_sk(rs), SOCK_DEAD)) {
+               rds_sock_put(rs);
                rs = NULL;
+       }
 
        rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
                ntohs(port));
@@ -124,15 +125,18 @@ static int rds_add_bound(struct rds_sock *rs, __be32 addr, __be16 *port)
        spin_lock_irqsave(&rds_bind_lock, flags);
 
        do {
+               struct rds_sock *rrs;
                if (rover == 0)
                        rover++;
-               if (!rds_bind_lookup(addr, cpu_to_be16(rover), rs)) {
+               if (!(rrs = rds_bind_lookup(addr, cpu_to_be16(rover), rs))) {
                        *port = rs->rs_bound_port;
                        ret = 0;
                        rdsdebug("rs %p binding to %pI4:%d\n",
                          rs, &addr, (int)ntohs(*port));
                        break;
                }
+               else
+                       rds_sock_put(rrs);
        } while (rover++ != last);
 
        spin_unlock_irqrestore(&rds_bind_lock, flags);