clockintr_dispatch: copy cl_func to cq_shadow.cl_func before calling it
authorcheloha <cheloha@openbsd.org>
Sat, 9 Sep 2023 03:03:45 +0000 (03:03 +0000)
committercheloha <cheloha@openbsd.org>
Sat, 9 Sep 2023 03:03:45 +0000 (03:03 +0000)
When we add support for disestablishing clockintrs in the near future,
the current call to cl->cl_func will be in a race with free(9) on
another CPU.  Copying cl_func to cq_shadow.cl_func before leaving the
mutex and then calling the copy eliminates the race.

Correcting the race has a negligible performance impact and simplifies
the forthcoming clockintr_disestablish() patch.

Requested by dlg@ back in March.

sys/kern/kern_clockintr.c

index d22ad2b..b91c7b6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_clockintr.c,v 1.40 2023/09/08 22:23:30 cheloha Exp $ */
+/* $OpenBSD: kern_clockintr.c,v 1.41 2023/09/09 03:03:45 cheloha Exp $ */
 /*
  * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -258,10 +258,11 @@ clockintr_dispatch(void *frame)
                }
                clockqueue_pend_delete(cq, cl);
                cq->cq_shadow.cl_expiration = cl->cl_expiration;
+               cq->cq_shadow.cl_func = cl->cl_func;
                cq->cq_running = cl;
                mtx_leave(&cq->cq_mtx);
 
-               cl->cl_func(&cq->cq_shadow, frame);
+               cq->cq_shadow.cl_func(&cq->cq_shadow, frame);
 
                mtx_enter(&cq->cq_mtx);
                cq->cq_running = NULL;