If the number of hooks exceeds available sk_buff space, the function is called again for the remaining data. Make use of the second netlink_callback::args field to store the current index between invocations. Since this is an inner dump loop, it may run multiple times (for different hook types) with the same context buffer, so manually zero the stored value if complete array dump was possible. Fixes: b010e2a4a9ac ("netfilter: nfnetlink_hook: Dump nat type chains") Signed-off-by: Phil Sutter --- net/netfilter/nfnetlink_hook.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nfnetlink_hook.c b/net/netfilter/nfnetlink_hook.c index efc674fc5adf..0657fbb3e605 100644 --- a/net/netfilter/nfnetlink_hook.c +++ b/net/netfilter/nfnetlink_hook.c @@ -345,21 +345,26 @@ static int nfnl_hook_dump_nat(struct sk_buff *nlskb, struct nf_hook_entries *e = rcu_dereference(priv->entries); struct nfnl_dump_hook_data *ctx = cb->data; struct nf_hook_ops **nat_ops; - int i, err; + unsigned int i = cb->args[1]; + int err = 0; if (!e) return 0; nat_ops = nf_hook_entries_get_hook_ops(e); - for (i = 0; i < e->num_hook_entries; i++) { + for (; i < e->num_hook_entries; i++) { err = nfnl_hook_dump_one(nlskb, ctx, nat_ops[i], ops->priority, family, cb->nlh->nlmsg_seq); if (err) - return err; + break; } - return 0; + + if (!err) + i = 0; + cb->args[1] = i; + return err; } static int nfnl_hook_dump(struct sk_buff *nlskb, -- 2.54.0