I think I've found a bug in ip_set_nethash.c. Within nethash_add(), we have: if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX) return -ERANGE; if (cidr <= 0 || cidr >= 32) return -EINVAL; First, this does bounds checking on "cidr" only after we have already used "cidr" to do a lookup in "nets". Second, the bounds check itself is insufficient, because "nets" has length 30: struct ip_set_nethash { ... uint16_t nets[30]; /* nr of nets by CIDR sizes */ ... } Therefore, any block of size /31 causes us to read off the end of the array. Later in the function, we write to this location too, causing undefined behavior. I went looking for bugs here because I was seeing inconsistent behavior when adding /31 blocks to a nethash. Sometimes I can add them, and sometimes they fail with ERANGE. -Ed -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html