From f460c85cb3f6c168dfa4471756ab058a3271bce1 Mon Sep 17 00:00:00 2001 From: sommerfeld Date: Sat, 27 May 2000 21:00:25 +0000 Subject: [PATCH] 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. --- sys/kern/sysv_sem.c | 170 ++++---------------------------------------- 1 file changed, 13 insertions(+), 157 deletions(-) diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 7f43a2ac47ff..4674cfc18819 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -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 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); - } }