On Mon Sep 21, 2026 at 2:26 PM CEST, Eelco Chaudron via dev wrote:
> Hi Eli/Gaetan,
>
> Ilya has been working on some Sashiko code review scripts, and as part of
> his tests, he was running them on the netdev-doca series. He shared the
> results with me, and I'm going over them to filter out the ones that seem
> relevant.
>
> See the one for this patch below. So be prepared to see some more review
> comments from Sashiko AI on the series ;)
>
> Cheers,
>
> Eelco
>
>
> commit 174078f14e26 ("refmap: Introduce reference map.")
> Author: Gaetan Rivet <[email protected]>
>
> This patch introduces a reference-counted concurrent map (refmap)
> with RCU-based lookups and deferred node freeing.
>
> >     if (!ovs_refcount_try_ref_rcu(&node->refcount)) {
> >         log_node(rfm, "try_ref-fail", node);
> >         return NULL;
> >     }
>
> In refmap_try_ref(), when ovs_refcount_try_ref_rcu() returns false,
> log_node() is called on a node whose value may have already been
> invalidated by a concurrent refmap_unref(). The race looks like
> this: thread A finds the node via refmap_lookup(), then thread B
> completes refmap_unref() -- transitioning the refcount from 1 to 0
> under map_lock and calling value_uninit() on the value:
>
> >     if (old_refcount == 1) {
> >         /* We transitioned 1->0 under lock.  Safe to cleanup. */
> >         rfm->value_uninit(refmap_node_value(rfm, node));
> >         cmap_remove(&rfm->map, &node->map_node, node->hash);
> >         [...]
> >         ovsrcu_postpone(free, node);
>
> Thread A then enters log_node(), which calls rfm->value_format()
> on the now-uninited value:
>
> >     key = refmap_node_key(node);
> >     value = refmap_node_value(rfm, node);
> >     [...]
> >     rfm->value_format(&s, key, value);
>
> The node memory itself is still valid (RCU-deferred free), but
> value_uninit() may have nullified or freed pointers within the
> value structure. Can value_format() then dereference an invalid
> pointer inside the value, causing a null-pointer dereference or
> use-after-free?
>
> This only triggers when debug logging is enabled and value_format
> is non-null, so it is a cold path under default configuration.
> Would it make sense to skip the log_node() call on the try-ref
> failure path, or copy the needed fields before the try-ref
> attempt?
>

Hi Eelco,

I think either we skip log_node(), or an alternative is in log_node()
to only call value_format() if refcount is not zero.

This should be safe, as the only possibility to call log_node() with
ref == 0 is after the last unref, as the try-ref failed. At this point
there is no possibility of the refcount getting back above 0.

As such, within log_node() we can still print the value pointer,
which as I recall has been very useful to grep and trace the lifecycle
of one element -- here we would then see even the last try-ref that
failed, which I think is a pretty valuable information.

Let me know if you'd prefer we completely remove the call.

--
Gaetan
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to