summaryrefslogtreecommitdiff
path: root/sys/kern/sysv_sem.c
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2012-10-21 19:00:49 +0000
committerBob Beck <beck@cvs.openbsd.org>2012-10-21 19:00:49 +0000
commitea9e6de3fdeb45b92517bf22164f081a7cab4775 (patch)
tree188030413ea931e606b536f0dd07383ee3016e73 /sys/kern/sysv_sem.c
parent01aa05846272f1859e5882dcbdfa5a0fd6d0ee0a (diff)
Fix problem reported by Nathan Weeks <weeks@iastate.edu> where a userland
program could induce the kernel to panic by attempting to do a sempo with nsops > kern.seminfo.semume and the SEM_UNFO flag set. This fixes it so we return ENOSPC, like the man page says, rather than panicing. ok miod@, millert@
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r--sys/kern/sysv_sem.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 1a4caada430..2789670ddd7 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysv_sem.c,v 1.43 2012/04/11 13:29:14 naddy Exp $ */
+/* $OpenBSD: sysv_sem.c,v 1.44 2012/10/21 19:00:48 beck Exp $ */
/* $NetBSD: sysv_sem.c,v 1.26 1996/02/09 19:00:25 christos Exp $ */
/*
@@ -594,7 +594,7 @@ sys_semop(struct proc *p, void *v, register_t *retval)
do_wakeup = 1;
}
if (sopptr->sem_flg & SEM_UNDO)
- do_undos = 1;
+ do_undos++;
} else if (sopptr->sem_op == 0) {
if (semptr->semval > 0) {
DPRINTF(("semop: not zero now\n"));
@@ -605,14 +605,14 @@ sys_semop(struct proc *p, void *v, register_t *retval)
do_wakeup = 1;
semptr->semval += sopptr->sem_op;
if (sopptr->sem_flg & SEM_UNDO)
- do_undos = 1;
+ do_undos++;
}
}
/*
- * Did we get through the entire vector?
+ * Did we get through the entire vector and can we undo it?
*/
- if (i >= nsops)
+ if (i >= nsops && do_undos <= SEMUME)
goto done;
/*
@@ -624,6 +624,14 @@ sys_semop(struct proc *p, void *v, register_t *retval)
sops[j].sem_op;
/*
+ * Did we have too many SEM_UNDO's
+ */
+ if (do_undos > SEMUME) {
+ error = ENOSPC;
+ goto done2;
+ }
+
+ /*
* If the request that we couldn't satisfy has the
* NOWAIT flag set then return with EAGAIN.
*/