Re: Linux 2.2.15pre14

From: Christian Ehrhardt (ehrhardt@mathematik.uni-ulm.de)
Date: Fri Mar 10 2000 - 09:00:35 EST


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 = &current->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