On 7/7/2019 3:04 PM, Florian Westphal wrote:
> Paul Blakey <pa...@mellanox.com> wrote:
>> +/* Determine whether skb->_nfct is equal to the result of conntrack lookup. 
>> */
>> +static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
>> +                               u16 zone_id, bool force)
>> +{
>> +    enum ip_conntrack_info ctinfo;
>> +    struct nf_conn *ct;
>> +
>> +    ct = nf_ct_get(skb, &ctinfo);
>> +    if (!ct)
>> +            return false;
>> +    if (!net_eq(net, read_pnet(&ct->ct_net)))
>> +            return false;
>> +    if (nf_ct_zone(ct)->id != zone_id)
>> +            return false;
>> +
>> +    /* Force conntrack entry direction. */
>> +    if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
>> +            nf_conntrack_put(&ct->ct_general);
>> +            nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
>> +
>> +            if (nf_ct_is_confirmed(ct))
>> +                    nf_ct_kill(ct);
> This looks like a possible UAF:
> nf_conntrack_put() may free the conntrack entry.
>
> It seems better to do do:
>       if (nf_ct_is_confirmed(ct))
>               nf_ct_kill(ct);
>
>       nf_conntrack_put(&ct->ct_general);
>       nf_ct_set(skb, ...

Like if conntrack has just timed it out (or conntrack flushed), and skb 
holds the last ref?

thanks, will reverse the order.

Reply via email to