Sashiko thinks that cidr bookkeeping might be unsafe because the concurrent RCU reader in mtype_test_cidrs() uses the data without sequence locks or read-side barriers. However every right shift (add new entry) and left shift (delete entry) is performed by duplicating the entry just shifted. Therefore concurrent reader will just duplicate a test with the same values as just before: existing entries cannot be skipped. Signed-off-by: Jozsef Kadlecsik --- net/netfilter/ipset/ip_set_hash_gen.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index 9d1fcf6c8328..6838b46df9b8 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -342,6 +342,12 @@ mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) } } if (j != -1) { + /* We shift the cidr values to the right + * by duplicating the entries one by one, + * starting from the end. + * It means the same test can be repeated twice + * by a concurrent mtype_test_cidrs() reader. + */ for (; i > j; i--) h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; } @@ -363,6 +369,11 @@ mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n) h->nets[CIDR_POS(cidr)].nets[n]--; if (h->nets[CIDR_POS(cidr)].nets[n] > 0) goto unlock; + /* We shift the cidr values to the left + * by duplicating the remaining entries one by one. + * It means the same test can be repeated twice + * by a concurrent mtype_test_cidrs() reader. + */ for (j = i; j < net_end && h->nets[j].cidr[n]; j++) h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; h->nets[j].cidr[n] = 0; -- 2.39.5