Remove existing semaphore system locking mechanism and turn

sys_semconfig into a placebo system call, to avoid giving folks an
easy way to wedge processes which use semaphores.

NOTE: unlike 386bsd and freebsd, processes which did not have
semaphore undo records would not be affected by this problem (reducing
it from a serious local denial-of-service problem to a largely
cosmetic problem, since virtually nobody uses semaphores).  But the
code is just Wrong so we're ripping it out anyway.
This commit is contained in:
sommerfeld 2000-05-27 21:00:25 +00:00
parent 22519583f3
commit f460c85cb3
1 changed files with 13 additions and 157 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysv_sem.c,v 1.36 2000/05/27 04:52:37 thorpej Exp $ */
/* $NetBSD: sysv_sem.c,v 1.37 2000/05/27 21:00:25 sommerfeld Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -58,7 +58,6 @@
#include <sys/syscallargs.h>
int semtot = 0;
struct proc *semlock_holder = NULL;
#ifdef SEM_DEBUG
#define SEM_PRINTF(a) printf a
@ -66,11 +65,15 @@ struct proc *semlock_holder = NULL;
#define SEM_PRINTF(a)
#endif
void semlock __P((struct proc *));
struct sem_undo *semu_alloc __P((struct proc *));
int semundo_adjust __P((struct proc *, struct sem_undo **, int, int, int));
void semundo_clear __P((int, int));
/*
* XXXSMP Once we go MP, there needs to be a lock for the semaphore system.
* Until then, we're saved by being a non-preemptive kernel.
*/
void
seminit()
{
@ -92,29 +95,8 @@ seminit()
semu_list = NULL;
}
void
semlock(p)
struct proc *p;
{
while (semlock_holder != NULL && semlock_holder != p)
(void) tsleep(&semlock_holder, (PZERO - 4),
"semlock", 0);
}
/*
* Lock or unlock the entire semaphore facility.
*
* This will probably eventually evolve into a general purpose semaphore
* facility status enquiry mechanism (I don't like the "read /dev/kmem"
* approach currently taken by ipcs and the amount of info that we want
* to be able to extract for ipcs is probably beyond the capability of
* the getkerninfo facility.
*
* At the time that the current version of semconfig was written, ipcs is
* the only user of the semconfig facility. It uses it to ensure that the
* semaphore facility data structures remain static while it fishes around
* in /dev/kmem.
* Placebo.
*/
int
@ -123,33 +105,8 @@ sys_semconfig(p, v, retval)
void *v;
register_t *retval;
{
struct sys_semconfig_args /* {
syscallarg(int) flag;
} */ *uap = v;
int eval = 0;
semlock(p);
switch (SCARG(uap, flag)) {
case SEM_CONFIG_FREEZE:
semlock_holder = p;
break;
case SEM_CONFIG_THAW:
semlock_holder = NULL;
wakeup((caddr_t)&semlock_holder);
break;
default:
printf(
"semconfig: unknown flag parameter value (%d) - ignored\n",
SCARG(uap, flag));
eval = EINVAL;
break;
}
*retval = 0;
return(eval);
return 0;
}
/*
@ -392,8 +349,6 @@ semctl1(p, semid, semnum, cmd, v, retval)
SEM_PRINTF(("call to semctl(%d, %d, %d, %p)\n",
semid, semnum, cmd, v));
semlock(p);
ix = IPCID_TO_IX(semid);
if (ix < 0 || ix >= seminfo.semmsl)
return (EINVAL);
@ -531,8 +486,6 @@ sys_semget(p, v, retval)
SEM_PRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg));
semlock(p);
if (key != IPC_PRIVATE) {
for (semid = 0; semid < seminfo.semmni; semid++) {
if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
@ -628,8 +581,6 @@ sys_semop(p, v, retval)
SEM_PRINTF(("call to semop(%d, %p, %d)\n", semid, sops, nsops));
semlock(p);
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
if (semid < 0 || semid >= seminfo.semmsl)
@ -868,99 +819,14 @@ semexit(p)
}
/*
* There are a few possibilities to consider here ...
*
* 1) The semaphore facility isn't currently locked. In this case,
* this call should proceed normally.
* 2) The semaphore facility is locked by this process (i.e. the one
* that is exiting). In this case, this call should proceed as
* usual and the facility should be unlocked at the end of this
* routine (since the locker is exiting).
* 3) The semaphore facility is locked by some other process and this
* process doesn't have an undo structure allocated for it. In this
* case, this call should proceed normally (i.e. not accomplish
* anything and, most importantly, not block since that is
* unnecessary and could result in a LOT of processes blocking in
* here if the facility is locked for a long time).
* 4) The semaphore facility is locked by some other process and this
* process has an undo structure allocated for it. In this case,
* this call should block until the facility has been unlocked since
* the holder of the lock may be examining this process's proc entry
* (the ipcs utility does this when printing out the information
* from the allocated sem undo elements).
*
* This leads to the conclusion that we should not block unless we
* discover that the someone else has the semaphore facility locked and
* this process has an undo structure. Let's do that...
*
* Note that we do this in a separate pass from the one that processes
* any existing undo structure since we don't want to risk blocking at
* that time (it would make the actual unlinking of the element from
* the chain of allocated undo structures rather messy).
* If there is no undo vector, skip to the end.
*/
if (suptr == NULL)
return;
/*
* Does someone else hold the semaphore facility's lock?
*/
if (semlock_holder != NULL && semlock_holder != p) {
/*
* Yes (i.e. we are in case 3 or 4).
*
* If we didn't find an undo vector associated with this
* process than we can just return (i.e. we are in case 3).
*
* Note that we know that someone else is holding the lock so
* we don't even have to see if we're holding it...
*/
if (suptr == NULL)
return;
/*
* We are in case 4.
*
* Go to sleep as long as someone else is locking the semaphore
* facility (note that we won't get here if we are holding the
* lock so we don't need to check for that possibility).
*/
while (semlock_holder != NULL)
(void) tsleep(&semlock_holder, (PZERO - 4),
"semlock", 0);
/*
* Nobody is holding the facility (i.e. we are now in case 1).
* We can proceed safely according to the argument outlined
* above.
*
* We look up the undo vector again, in case the list changed
* while we were asleep, and the parent is now different.
*/
for (supptr = &semu_list; (suptr = *supptr) != NULL;
supptr = &suptr->un_next) {
if (suptr->un_proc == p)
break;
}
if (suptr == NULL)
panic("semexit: undo vector disappeared");
} else {
/*
* No (i.e. we are in case 1 or 2).
*
* If there is no undo vector, skip to the end and unlock the
* semaphore facility if necessary.
*/
if (suptr == NULL)
goto unlock;
}
/*
* We are now in case 1 or 2, and we have an undo vector for this
* process.
* We now have an undo vector for this process.
*/
SEM_PRINTF(("proc @%p has undo structure with %d entries\n", p,
@ -1011,14 +877,4 @@ semexit(p)
SEM_PRINTF(("removing vector\n"));
suptr->un_proc = NULL;
*supptr = suptr->un_next;
unlock:
/*
* If the exiting process is holding the global semaphore facility
* lock (i.e. we are in case 2) then release it.
*/
if (semlock_holder == p) {
semlock_holder = NULL;
wakeup((caddr_t)&semlock_holder);
}
}