Writer (nf_remove_net_hook) assigns to the field value using WRITE_ONCE(), appropriately call READ_ONCE() to make sure reader (nfnl_hook_dump) sees either the old or new value, not both. Fixes: b010e2a4a9ac ("netfilter: nfnetlink_hook: Dump nat type chains") Signed-off-by: Phil Sutter --- Changes since v1: - Cover for previously missed ops[i]->priority parameter - Also cover for nat_ops field access, adjust patch subject - Declare temporary variable as const --- net/netfilter/nfnetlink_hook.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nfnetlink_hook.c b/net/netfilter/nfnetlink_hook.c index e47a2add4d5b..644070c8b456 100644 --- a/net/netfilter/nfnetlink_hook.c +++ b/net/netfilter/nfnetlink_hook.c @@ -353,7 +353,8 @@ static int nfnl_hook_dump_nat(struct sk_buff *nlskb, nat_ops = nf_hook_entries_get_hook_ops(e); for (i = 0; i < e->num_hook_entries; i++) { - err = nfnl_hook_dump_one(nlskb, ctx, nat_ops[i], + err = nfnl_hook_dump_one(nlskb, ctx, + READ_ONCE(nat_ops[i]), ops->priority, family, cb->nlh->nlmsg_seq); if (err) @@ -390,11 +391,13 @@ static int nfnl_hook_dump(struct sk_buff *nlskb, ops = nf_hook_entries_get_hook_ops(e); for (; i < e->num_hook_entries; i++) { - if (ops[i]->hook_ops_type == NF_HOOK_OP_NAT) - err = nfnl_hook_dump_nat(nlskb, cb, ops[i], family); + const struct nf_hook_ops *cur = READ_ONCE(ops[i]); + + if (cur->hook_ops_type == NF_HOOK_OP_NAT) + err = nfnl_hook_dump_nat(nlskb, cb, cur, family); else - err = nfnl_hook_dump_one(nlskb, ctx, ops[i], - ops[i]->priority, family, + err = nfnl_hook_dump_one(nlskb, ctx, cur, + cur->priority, family, cb->nlh->nlmsg_seq); if (err) break; -- 2.54.0