There is a data race between jump cache reading and updating
- Several threads execute ruleset simultaneously under RLOCK https://reviews.freebsd.org/source/src/browse/main/sys/netpfil/ipfw/ip_fw2.c$1785
- Let's say that two threads enter jump_fast, thread A stops there https://reviews.freebsd.org/source/src/browse/main/sys/netpfil/ipfw/ip_fw2.c$1258, thread B stops there https://reviews.freebsd.org/source/src/browse/main/sys/netpfil/ipfw/ip_fw2.c$1245
- Thread A writes correct id to f->cached_id
- Thread B reads f->cached_id, checks that it's correct, and reads f->cached_pos
- Thread A didn't write f->cached_pos, thread B returns incorrect rule position
To fix we need to ensure that cached_pos is updated before cached_id
- For 64-bit architectures, we write a 64-bit value composed of both cached_id and cached_pos
- For 32-bit ones, we enforce load/store ordering by adding release fence between writing pos and id, and acquire fence between reading id and pos