]> git.baikalelectronics.ru Git - kernel.git/commit
tipc: switch to rhashtable iterator
authorCong Wang <xiyou.wangcong@gmail.com>
Fri, 24 Aug 2018 19:28:06 +0000 (12:28 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Aug 2018 01:04:54 +0000 (18:04 -0700)
commit536544e3308d072b2945606192d62892fe116ed1
treef557853b702648e5497483065b96bc332e9d68de
parentf80d79538169f6d3a75cf1b77f51056433ae9182
tipc: switch to rhashtable iterator

syzbot reported a use-after-free in tipc_group_fill_sock_diag(),
where tipc_group_fill_sock_diag() still reads tsk->group meanwhile
tipc_group_delete() just deletes it in tipc_release().

tipc_nl_sk_walk() aims to lock this sock when walking each sock
in the hash table to close race conditions with sock changes like
this one, by acquiring tsk->sk.sk_lock.slock spinlock, unfortunately
this doesn't work at all. All non-BH call path should take
lock_sock() instead to make it work.

tipc_nl_sk_walk() brutally iterates with raw rht_for_each_entry_rcu()
where RCU read lock is required, this is the reason why lock_sock()
can't be taken on this path. This could be resolved by switching to
rhashtable iterator API's, where taking a sleepable lock is possible.
Also, the iterator API's are friendly for restartable calls like
diag dump, the last position is remembered behind the scence,
all we need to do here is saving the iterator into cb->args[].

I tested this with parallel tipc diag dump and thousands of tipc
socket creation and release, no crash or memory leak.

Reported-by: syzbot+b9c8f3ab2994b7cd1625@syzkaller.appspotmail.com
Cc: Jon Maloy <jon.maloy@ericsson.com>
Cc: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/diag.c
net/tipc/netlink.c
net/tipc/socket.c
net/tipc/socket.h