diff options
author | bde <bde@FreeBSD.org> | 1999-02-02 12:11:01 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1999-02-02 12:11:01 +0000 |
commit | 0fd52730c216aa70c9761b100b73f0ec0ffab6ea (patch) | |
tree | c5b556662a4b50e4b3fc67821a352652ee54717e /sys/kern | |
parent | d8bfa57b5f8f231ac6d1d644df6f6b801593952a (diff) | |
download | FreeBSD-src-0fd52730c216aa70c9761b100b73f0ec0ffab6ea.zip FreeBSD-src-0fd52730c216aa70c9761b100b73f0ec0ffab6ea.tar.gz |
Switch context before doing some i/o operations that might block if
context would be switched on return to user mode. This fixes some
denial of service problems.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_subr.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index a96d554..d8e1f08 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 - * $Id: kern_subr.c,v 1.23 1999/01/08 17:31:10 eivind Exp $ + * $Id: kern_subr.c,v 1.24 1999/01/10 01:58:24 eivind Exp $ */ #include <sys/param.h> @@ -44,6 +44,7 @@ #include <sys/proc.h> #include <sys/malloc.h> #include <sys/lock.h> +#include <sys/resourcevar.h> #include <sys/vnode.h> #include <vm/vm.h> @@ -51,6 +52,10 @@ #include <vm/vm_page.h> #include <vm/vm_map.h> +#include <machine/cpu.h> + +static void uio_yield __P((void)); + int uiomove(cp, n, uio) register caddr_t cp; @@ -81,6 +86,8 @@ uiomove(cp, n, uio) case UIO_USERSPACE: case UIO_USERISPACE: + if (resched_wanted()) + uio_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else @@ -139,6 +146,8 @@ uiomoveco(cp, n, uio, obj) case UIO_USERSPACE: case UIO_USERISPACE: + if (resched_wanted()) + uio_yield(); if (uio->uio_rw == UIO_READ) { if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) && ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) && @@ -214,6 +223,8 @@ uioread(n, uio, obj, nread) cnt &= ~PAGE_MASK; + if (resched_wanted()) + uio_yield(); error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, uio->uio_offset, cnt, (vm_offset_t) iov->iov_base, &npagesmoved); @@ -389,3 +400,17 @@ phashinit(elements, type, nentries) *nentries = hashsize; return (hashtbl); } + +static void +uio_yield() +{ + struct proc *p; + int s; + + p = curproc; + s = splhigh(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + splx(s); +} |