Re: kernel panic in free() called from semop()

From: Don Lewis <truckman_at_FreeBSD.org>
Date: Fri, 12 Nov 2004 16:33:22 -0800 (PST)
On 12 Nov, Conrad J. Sabatier wrote:
> On Fri, 12 Nov 2004 15:11:57 -0800 (PST), Don Lewis
> <truckman_at_freebsd.org> wrote:
> 
>> 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:
>> 
>> _at__at_ -900,7 +901,7 _at__at_ 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:
>> 
>> _at__at_ -1152,6 +1153,7 _at__at_ done2:
>>  	mtx_unlock(sema_mtxp);
>>  	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.
> 
> I was seeing the same thing, until I disabled the execution of the pgsql
> script in /usr/local/etc/rc.d.  Then the system booted fine.
> 
> I presume postgresql needs to be recompiled.

It shouldn't cause a kernel panic!

I'm up and running with the following patch.

Index: sys/kern/sysv_sem.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_sem.c,v
retrieving revision 1.71
diff -u -r1.71 sysv_sem.c
--- sys/kern/sysv_sem.c	12 Nov 2004 13:23:47 -0000	1.71
+++ sys/kern/sysv_sem.c	13 Nov 2004 00:27:36 -0000
_at__at_ -901,7 +901,7 _at__at_
 	semid = IPCID_TO_IX(semid);	/* Convert back to zero origin */
 
 	if (semid < 0 || semid >= seminfo.semmni)
-		error = EINVAL;
+		return (EINVAL);
 
 	/* Allocate memory for sem_ops */
 	if (nsops <= SMALL_SOPS)
_at__at_ -1153,7 +1153,6 _at__at_
 	mtx_unlock(sema_mtxp);
 	if (sops != small_sops)
 		free(sops, M_SEM);
-	free(sops, M_SEM);
 	return (error);
 }
 
Received on Fri Nov 12 2004 - 23:33:35 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:22 UTC