kernel panic in free() called from semop()

Don Lewis truckman at
Fri Nov 12 15:12:05 PST 2004

I cvsup'ed around 18:12 UTC today and got the following kernel panic
with the new kernel right after moused started.

Starting default moused:.
panic: free: address 0xe902ecb0(0xe902e000) has not been allocated.

cpuid = 0
KDB: enter: panic
[thread 100082]
Stopped at      kdb_enter+0x2c: leave   
db> tr
kdb_enter(c082a57e,100,c26c8300,e902ecb0,c26c8300) at kdb_enter+0x2c
panic(c0828c9f,e902ecb0,e902e000,e902ecb6,c26c8300) at panic+0x17f
free(e902ecb0,c088f900,c082dd62,685,e902ecb6) at free+0xd4
semop(c26c8300,e902ed18,5,4,283) at semop+0x150
syscall(2f,2f,2f,805c010,bfbfed56) at syscall+0x128
Xint0x80_syscall() at Xint0x80_syscall+0x1f
--- syscall (169, FreeBSD ELF32, semsys), eip = 0x480dd5f8, esp = 0xbfbfeb04, ebp = 0xbfbfeb40 ---

I suspect that the culprit is the sysv_sema.c:1.71.

This particular part of the change looks like a mistake:

@@ -900,7 +901,7 @@ semop(td, uap)
 	semid = IPCID_TO_IX(semid);	/* Convert back to zero origin */
 	if (semid < 0 || semid >= seminfo.semmni)
-		return (EINVAL);
+		error = EINVAL;
 	/* Allocate memory for sem_ops */
 	if (nsops <= SMALL_SOPS)

Falling through instead of returning looks dangerous because a little
futher down there is the following code:

	semakptr = &sema[semid];
        sema_mtxp = &sema_mtx[semid];

Oh, this looks bad, too:

@@ -1152,6 +1153,7 @@ done2:
 	if (sops != small_sops)
 		free(sops, M_SEM);
+	free(sops, M_SEM);
 	return (error);

sops can either point to small_sops, which is located on the stack, or
it call by allocated dynamically with malloc().  Depending on where sops
points, it will either get freed twice, or it we will pass a stack
address to free().  It looks like the latter is happening in this case.

More information about the freebsd-current mailing list