releng/13.1 context: sys/contrib/openzfs/module/avl/avl.c 's avl_destroy_nodes : lack of appropriately locked context for its use? Wild pointer?

From: Mark Millard <marklmi_at_yahoo.com>
Date: Sun, 26 Feb 2023 21:44:13 UTC
Note: This question came up while looking at one type of crash
backtrace reported in:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=267028

There is the code:

void *
avl_destroy_nodes(avl_tree_t *tree, void **cookie)
{
. . .
        /*
         * If we just removed a right child or there isn't one, go up to parent.
         */
        if (child == 1 || parent->avl_child[1] == NULL) {
                node = parent;
                parent = AVL_XPARENT(parent);
                goto done;
        }

        /*
         * Do parent's right child, then leftmost descendent.
         */
        node = parent->avl_child[1];
        while (node->avl_child[0] != NULL) {
                parent = node;
                node = node->avl_child[0];
        }
. . .

some gdb backtraces report that the "while" line above had
a "signal handler called" result.

If the avl tree were invariant over avl_destroy_nodes it
looks like a wild pointer would need to be the value in
a accessed node->avl_child[0] in order for the code to
fail.

But, if the avl tree was being separately updated during
the avl_destroy_nodes activity, that could substitute in
a NULL that "node = node->avl_child[0];" could get a copy
of.

Does anyone know which of these is a possibility? Both?
The information would be good to add to the bugzilla
submittal's comments if it helps narrow down anything.

(I supposed a failed context synchronization across some
context change, say a cpu migration, could be another way
to get an odd value.)

For reference, one of the example backtraces is:

#6 <signal handler called>
#7 avl_destroy_nodes (tree=tree@entry=0xfffff8003fa1bea0, 
cookie=cookie@entry=0xfffffe0075f2fdd0)
at /usr/src/sys/contrib/openzfs/module/avl/avl.c:1023
#8 0xffffffff823dd768 in mze_destroy (zap=0xfffff8003fa1bd80)
at /usr/src/sys/contrib/openzfs/module/zfs/zap_micro.c:402
#9 zap_evict_sync (dbu=0xfffff8003fa1bd80)
at /usr/src/sys/contrib/openzfs/module/zfs/zap_micro.c:887
#10 0xffffffff822ae74a in dbuf_evict_user (db=0xfffff800391f3378)
at /usr/src/sys/contrib/openzfs/module/zfs/dbuf.c:570
#11 dbuf_clear_data (db=0xfffff800391f3378)
at /usr/src/sys/contrib/openzfs/module/zfs/dbuf.c:1131
#12 dbuf_destroy (db=0xfffff800391f3378)
at /usr/src/sys/contrib/openzfs/module/zfs/dbuf.c:2804
#13 0xffffffff822b4129 in dbuf_evict_one ()
at /usr/src/sys/contrib/openzfs/module/zfs/dbuf.c:704
#14 0xffffffff822ac43d in dbuf_evict_thread (unused=unused@entry=0x0)
at /usr/src/sys/contrib/openzfs/module/zfs/dbuf.c:742
#15 0xffffffff80bd8a9e in fork_exit (
callout=0xffffffff822ac120 <dbuf_evict_thread>, arg=0x0, 
frame=0xfffffe0075f2ff40) at /usr/src/sys/kern/kern_fork.c:1093
#16 <signal handler called>
#17 mi_startup () at /usr/src/sys/kern/init_main.c:322
#18 0xffffffff80f76c49 in swapper () at /usr/src/sys/vm/vm_swapout.c:755
#19 0xffffffff80385022 in btext () at /usr/src/sys/amd64/amd64/locore.S:80

===
Mark Millard
marklmi at yahoo.com