Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxx> wrote: > Linkui Xiao reported that there's a race condition when ipset swap and destroy is > called, which can lead to crash in add/del/test element operations. Swap then > destroy are usual operations to replace a set with another one in a production > system. The issue can in some cases be reproduced with the script: > > ipset create hash_ip1 hash:net family inet hashsize 1024 maxelem 1048576 > ipset add hash_ip1 172.20.0.0/16 > ipset add hash_ip1 192.168.0.0/16 > iptables -A INPUT -m set --match-set hash_ip1 src -j ACCEPT > while [ 1 ] > do > # ... Ongoing traffic... > ipset create hash_ip2 hash:net family inet hashsize 1024 maxelem 1048576 > ipset add hash_ip2 172.20.0.0/16 > ipset swap hash_ip1 hash_ip2 > ipset destroy hash_ip2 > sleep 0.05 > done > > In the race case the possible order of the operations are > > CPU0 CPU1 > ip_set_test > ipset swap hash_ip1 hash_ip2 > ipset destroy hash_ip2 > hash_net_kadt > > Swap replaces hash_ip1 with hash_ip2 and then destroy removes hash_ip2 which > is the original hash_ip1. ip_set_test was called on hash_ip1 and because destroy > removed it, hash_net_kadt crashes. > > The fix is to force ip_set_swap() to wait for all readers to finish accessing the > old set pointers by calling synchronize_rcu(). Patch LGTM, thanks Jozsef!