Skip to content

Commit

Permalink
rds: fix two RCU related problems
Browse files Browse the repository at this point in the history
When a rds sock is bound, it is inserted into the bind_hash_table
which is protected by RCU. But when releasing rds sock, after it
is removed from this hash table, it is freed immediately without
respecting RCU grace period. This could cause some use-after-free
as reported by syzbot.

Mark the rds sock with SOCK_RCU_FREE before inserting it into the
bind_hash_table, so that it would be always freed after a RCU grace
period.

The other problem is in rds_find_bound(), the rds sock could be
freed in between rhashtable_lookup_fast() and rds_sock_addref(),
so we need to extend RCU read lock protection in rds_find_bound()
to close this race condition.

Reported-and-tested-by: [email protected]
Reported-by: [email protected]
Cc: Sowmini Varadhan <[email protected]>
Cc: Santosh Shilimkar <[email protected]>
Cc: [email protected]
Signed-off-by: Cong Wang <[email protected]>
Acked-by: Santosh Shilimkar <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed Sep 12, 2018
1 parent 6ad5690 commit cc4dfb7
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion net/rds/bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
struct rds_sock *rs;

__rds_create_bind_key(key, addr, port, scope_id);
rs = rhashtable_lookup_fast(&bind_hash_table, key, ht_parms);
rcu_read_lock();
rs = rhashtable_lookup(&bind_hash_table, key, ht_parms);
if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
rds_sock_addref(rs);
else
rs = NULL;
rcu_read_unlock();

rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
ntohs(port));
Expand Down Expand Up @@ -235,6 +237,7 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out;
}

sock_set_flag(sk, SOCK_RCU_FREE);
ret = rds_add_bound(rs, binding_addr, &port, scope_id);
if (ret)
goto out;
Expand Down

0 comments on commit cc4dfb7

Please sign in to comment.