On Fri, 10 Mar 2000, Alan Cox wrote:
> Ok everyone promptly found lots of bugs. The good thing is almost all of
> these are small but long standing issues, so we are starting to really shake
> out the obscure bugs the bigger ones masked.
Ok. The following patch is supposed to fix two more, minor problems in the
System V semaphore code:
* A moderatly serious local DoS caused by "leaking" semundo structures.
A program that demonstrates the Problem is availiable upon request.
The fix is taken from the semaphore code in newer 2.3 kernels.
* A suspected race that might cause a kernel NULL pointer dereference
under some rare circumstances.
The patch is against 2.2.15pre6 but should apply cleanly against any
2.2.15preX kernel. The code works here for some time but I only have a
single machine to test it on and this machine doesn't used SysV semaphores
heavily so some additional testing might be necessary. Ok, here we go:
--- linux-2.2.15pre/ipc/sem.c.orig Mon Feb 21 11:11:47 2000
+++ linux-2.2.15pre/ipc/sem.c Mon Feb 28 00:55:28 2000
@@ -528,9 +528,7 @@
}
err = -EIDRM;
- if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
- goto out;
- if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+ if ((sma != semary[id]) || (sma->sem_perm.seq != (unsigned int) semid / SEMMNI))
goto out;
switch (cmd) {
@@ -601,6 +599,25 @@
return err;
}
+
+static struct sem_undo* freeundos(struct sem_undo* un)
+{
+ struct sem_undo* u;
+ struct sem_undo** up;
+
+ for (up = ¤t->semundo;(u=*up);up=&u->proc_next) {
+ if(un==u) {
+ un=u->proc_next;
+ *up=un;
+ kfree(u);
+ return un;
+ }
+ }
+ printk ("freeundos undo list error id=%d\n", un->semid);
+ return un->proc_next;
+}
+
+
asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
{
int id, size, error = -EINVAL;
@@ -647,9 +664,15 @@
/* Make sure we have an undo structure
* for this process and this semaphore set.
*/
- for (un = current->semundo; un; un = un->proc_next)
- if (un->semid == semid)
+ un = current->semundo;
+ while(un != NULL) {
+ if(un->semid==semid)
break;
+ if(un->semid==-1)
+ un=freeundos(un);
+ else
+ un=un->proc_next;
+ }
if (!un) {
size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
best regards Christian
-- **************************************************************************** ** Christian Ehrhardt ** e-Mail: ehrhardt@mathematik.uni-ulm.de ********* **************************************************************************** THAT'S ALL FOLKS!- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Wed Mar 15 2000 - 21:00:17 EST