Hung kernel from sysv semaphore semu_list corruption

Ed Maste emaste at phaedrus.sandvine.ca
Thu Mar 8 14:42:49 UTC 2007


On Thu, Mar 08, 2007 at 10:55:22AM +0100, Divacky Roman wrote:

> this is wrong.. you cannot remove element from a *LIST when its iterated using *LIST_FOREACH.
> Use *LIST_FOREACH_SAFE instead... 

We're not freeing the item in the loop so it would work unless
QUEUE_MACRO_DEBUG is turned on to intentionally trash the link
pointer on _REMOVE.  You're right though it's not the correct approach.
There's an efficiency issue with the previous patch anyhow in that
SLIST_REMOVE walks the list again to find the element to remove.

How about the patch below instead:

Index: sysv_sem.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/sysv_sem.c,v
retrieving revision 1.85
diff -u -r1.85 sysv_sem.c
--- sysv_sem.c  22 Oct 2006 11:52:13 -0000      1.85
+++ sysv_sem.c  8 Mar 2007 14:22:43 -0000
@@ -1301,8 +1301,10 @@
         */
        SEMUNDO_LOCK();
        SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) {
-               if (suptr->un_proc == p)
+               if (suptr->un_proc == p) {
+                       *supptr = SLIST_NEXT(suptr, un_next);
                        break;
+               }
        }
        SEMUNDO_UNLOCK();

@@ -1362,8 +1364,9 @@
         * Deallocate the undo vector.
         */
        DPRINTF(("removing vector\n"));
+       SEMUNDO_LOCK();
        suptr->un_proc = NULL;
-       *supptr = SLIST_NEXT(suptr, un_next);
+       SEMUNDO_UNLOCK();
 }


More information about the freebsd-hackers mailing list