rhashtable: Fix use-after-free in rhashtable_walk_stop
authorHerbert Xu <herbert@gondor.apana.org.au>
Sun, 15 Mar 2015 10:12:04 +0000 (21:12 +1100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Mar 2015 02:22:08 +0000 (22:22 -0400)
The commit c4db8848af6af92f90462258603be844baeab44d ("rhashtable:
Move future_tbl into struct bucket_table") introduced a use-after-
free bug in rhashtable_walk_stop because it dereferences tbl after
droping the RCU read lock.

This patch fixes it by moving the RCU read unlock down to the bottom
of rhashtable_walk_stop.  In fact this was how I had it originally
but it got dropped while rearranging patches because this one
depended on the async freeing of bucket_table.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
lib/rhashtable.c

index 9d53a46dcca9c14f5394a7b088a290a3e5ae0b2e..b916679b3e3b74a54e3e5b33a2a853f6a72e9605 100644 (file)
@@ -854,10 +854,8 @@ void rhashtable_walk_stop(struct rhashtable_iter *iter)
        struct rhashtable *ht;
        struct bucket_table *tbl = iter->walker->tbl;
 
-       rcu_read_unlock();
-
        if (!tbl)
-               return;
+               goto out;
 
        ht = iter->ht;
 
@@ -869,6 +867,9 @@ void rhashtable_walk_stop(struct rhashtable_iter *iter)
        mutex_unlock(&ht->mutex);
 
        iter->p = NULL;
+
+out:
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(rhashtable_walk_stop);