Synopsis: System V Semaphore denial of service
NetBSD versions: NetBSD 1.4, 1.4.1, and 1.4.2
Thanks to: Artur Grabowski, Jason Thorpe, Bill Sommerfeld
Reported in NetBSD Security Advisory: SA2000-005
*** sys/sys/proc.h.orig 1999/03/25 04:45:56 1.74
--- sys/sys/proc.h 2000/04/30 20:12:04 1.74.2.2
***************
*** 230,235 ****
--- 230,252 ----
#define P_NOCLDWAIT 0x20000 /* No zombies if child dies */
/*
+ * These flags are kept in schedflags. schedflags may be modified
+ * only at splstatclock().
+ */
+ extern int schedflags;
+
+ #define PSCHED_SEENRR 0x0001 /* process has been in roundrobin() */
+ #define PSCHED_SHOULDYIELD 0x0002 /* process should yield */
+
+ #define PSCHED_SWITCHCLEAR (PSCHED_SEENRR|PSCHED_SHOULDYIELD)
+
+ /*
+ * Macro to compute the exit signal to be delivered.
+ */
+ #define P_EXITSIG(p) (((p)->p_flag & (P_TRACED|P_FSTRACE)) ? SIGCHLD : \
+ p->p_exitsig)
+
+ /*
* MOVE TO ucred.h?
*
* Shareable process credentials (always resident). This includes a reference
***************
*** 330,335 ****
--- 347,354 ----
void fixjobc __P((struct proc *p, struct pgrp *pgrp, int entering));
int inferior __P((struct proc *p));
int leavepgrp __P((struct proc *p));
+ void yield __P((void));
+ void preempt __P((struct proc *));
void mi_switch __P((void));
void pgdelete __P((struct pgrp *pgrp));
void procinit __P((void));
*** sys/kern/kern_subr.c.orig 2000/02/01 22:54:45 1.45.2.1
--- sys/kern/kern_subr.c 2000/04/30 20:12:42 1.45.2.3
***************
*** 125,135 ****
u_int cnt;
int error = 0;
char *cp = buf;
/*-
+ * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /*-
* Copyright (c) 1982, 1986, 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
***************
*** 68,73 ****
--- 105,111 ----
u_char curpriority; /* usrpri of curproc */
int lbolt; /* once a second sleep address */
+ int schedflags; /* preemption needed? */
+ if (curproc != NULL) {
+ s = splstatclock();
+ if (schedflags & PSCHED_SEENRR) {
+ /*
+ * The process has already been through a roundrobin
+ * without switching and may be hogging the CPU.
+ * Indicate that the process should yield.
+ */
+ schedflags |= PSCHED_SHOULDYIELD;
+ } else
+ schedflags |= PSCHED_SEENRR;
+ splx(s);
+ }
need_resched();
timeout(roundrobin, NULL, hz / 10);
}
***************
*** 569,574 ****
--- 621,671 ----
}
/*
+ * General yield call. Puts the current process back on its run queue and
+ * performs a voluntary context switch.
+ */
+ void
+ yield()
+ {
+ struct proc *p = curproc;
+ int s;
+
+ p->p_priority = p->p_usrpri;
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nvcsw++;
+ mi_switch();
+ splx(s);
+ }
+
+ /*
+ * General preemption call. Puts the current process back on its run queue
+ * and performs an involuntary context switch. If a process is supplied,
+ * we switch to that process. Otherwise, we use the normal process selection
+ * criteria.
+ */
+ void
+ preempt(newp)
+ struct proc *newp;
+ {
+ struct proc *p = curproc;
+ int s;
+
+ /*
+ * XXX Switching to a specific process is not supported yet.
+ */
+ if (newp != NULL)
+ panic("preempt: cpu_preempt not yet implemented");
+
+ p->p_priority = p->p_usrpri;
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ splx(s);
+ }
+
+ /*
* The machine independent parts of mi_switch().
* Must be called at splstatclock() or higher.
*/
***************
*** 625,630 ****
--- 722,733 ----
p->p_nice = autoniceval + NZERO;
resetpriority(p);
}
+
+ /*
+ * Process is about to yield the CPU; clear the appropriate
+ * scheduling flags.
+ */
+ schedflags &= ~PSCHED_SWITCHCLEAR;
/*
* Pick a new current process and record its start time.
*** sys/kern/kern_ktrace.c.orig 1998/09/11 12:50:10 1.33
--- sys/kern/kern_ktrace.c 2000/04/30 20:13:33 1.33.6.2
***************
*** 53,64 ****
#include <sys/mount.h>
#include <sys/syscallargs.h>
***************
*** 361,371 ****
error = ESRCH;
goto done;
}
! for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next)
if (descend)
ret |= ktrsetchildren(curp, p, ops, facs, fp);
else
ret |= ktrops(curp, p, ops, facs, fp);
} else {
/*
--- 374,386 ----
error = ESRCH;
goto done;
}
! for (p = LIST_FIRST(&pg->pg_members); p != NULL;
! p = LIST_NEXT(p, p_pglist)) {
if (descend)
ret |= ktrsetchildren(curp, p, ops, facs, fp);
else
ret |= ktrops(curp, p, ops, facs, fp);
+ }
} else {
/*
***************
*** 463,473 ****
error = ESRCH;
goto done;
}
! for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next)
if (descend)
ret |= ktrsetchildren(curp, p, ops, facs, vp);
else
ret |= ktrops(curp, p, ops, facs, vp);
} else {
/*
--- 478,490 ----
error = ESRCH;
goto done;
}
! for (p = LIST_FIRST(&pg->pg_members); p != NULL;
! p = LIST_NEXT(p, p_pglist)) {
if (descend)
ret |= ktrsetchildren(curp, p, ops, facs, vp);
else
ret |= ktrops(curp, p, ops, facs, vp);
+ }
} else {
/*
***************
*** 550,562 ****
* otherwise do any siblings, and if done with this level,
* follow back up the tree (but not past top).
*/
! if (p->p_children.lh_first)
! p = p->p_children.lh_first;
else for (;;) {
if (p == top)
return (ret);
! if (p->p_sibling.le_next) {
! p = p->p_sibling.le_next;
break;
}
p = p->p_pptr;
--- 567,579 ----
* otherwise do any siblings, and if done with this level,
* follow back up the tree (but not past top).
*/
! if (LIST_FIRST(&p->p_children) != NULL)
! p = LIST_FIRST(&p->p_children);
else for (;;) {
if (p == top)
return (ret);
! if (LIST_NEXT(p, p_sibling) != NULL) {
! p = LIST_NEXT(p, p_sibling);
break;
}
p = p->p_pptr;
***************
*** 565,571 ****
/*NOTREACHED*/
}