Re: [PATCH net 6/6] net/sched: act_ct: fix helper UAF due to extensions realloc

From: Jamal Hadi Salim

Date: Tue Sep 22 2026 - 17:36:51 EST


On Mon, Sep 21, 2026 at 10:57 AM Ilya Maximets <i.maximets@xxxxxxx> wrote:
>
> While calling the helpers, a raw pointer to the extensions area is
> wired into expectations list:
>
> -> nf_ct_helper()
> -> helper->help()
> -> nf_ct_expect_related_report()
> -> nf_ct_expect_insert()
> -> hlist_add_head_rcu(&exp->lnode, &master_help->expectations)
>
> In case the connection is not confirmed yet, more extensions can be
> added afterwards with *_ext_add() calls reallocating the extension
> space and leaving the now invalid pointer in the expectations list
> that is later accessed while removing the expectation.
>
> Make sure that helpers are called at the end after all the other
> extensions are already added.
>
> Note that the helper rejection now leaves the mark and labels set,
> but that's not different from how the NAT was handled before or how
> the mark and the labels were handled on confirmation failure. And
> there are no atomicity guarantees provided by the API anyway.
>
> Fixes: a21b06e73191 ("net: sched: add helper support in act_ct")
> Cc: stable@xxxxxxxxxxxxxxx
> Reported-by: Axel Mierczuk <axel.mierczuk@xxxxxxxxxxxxx>
> Signed-off-by: Ilya Maximets <i.maximets@xxxxxxx>

Reviewed-by: Jamal Hadi Salim <jhs@xxxxxxxxxxxx>

cheers,
jamal

> ---
> net/sched/act_ct.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> index f62051ec9d57d..411e3dd92d072 100644
> --- a/net/sched/act_ct.c
> +++ b/net/sched/act_ct.c
> @@ -1102,19 +1102,25 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
> }
> }
>
> - if (nf_ct_is_confirmed(ct) ? (!cached && !skip_add) : commit) {
> - err = nf_ct_helper(skb, ct, ctinfo, family);
> - if (err != NF_ACCEPT)
> - goto nf_error;
> - }
> -
> if (commit) {
> tcf_ct_act_set_mark(ct, p->mark, p->mark_mask);
> tcf_ct_act_set_labels(ct, p->labels, p->labels_mask);
>
> if (!nf_ct_is_confirmed(ct))
> nf_conn_act_ct_ext_add(skb, ct, ctinfo);
> + }
>
> + /* Run helpers for the connection if nf_conntrack_in() was executed
> + * or if we're about to commit. This has to be done after all the
> + * extensions are already added.
> + */
> + if (nf_ct_is_confirmed(ct) ? (!cached && !skip_add) : commit) {
> + err = nf_ct_helper(skb, ct, ctinfo, family);
> + if (err != NF_ACCEPT)
> + goto nf_error;
> + }
> +
> + if (commit) {
> /* This will take care of sending queued events
> * even if the connection is already confirmed.
> */
> --
> 2.55.0
>