X-Git-Url: https://gitweb.dragonflybsd.org/~syl/dragonfly.git/blobdiff_plain/c112ebcaf1a66cb7139f44d2ab183be934cbdace..3185a7fd6ab8c6851af39ae997b715e52cf683d7:/sys/kern/sys_generic.c diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index af8b68719b..5403dec299 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -68,7 +68,9 @@ #endif #include #include + #include +#include #include @@ -82,8 +84,8 @@ static int doselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, static int pollscan (struct proc *, struct pollfd *, u_int, int *); static int selscan (struct proc *, fd_mask **, fd_mask **, int, int *); -static int dofileread(int, struct file *, struct uio *, int, int *); -static int dofilewrite(int, struct file *, struct uio *, int, int *); +static int dofileread(int, struct file *, struct uio *, int, size_t *); +static int dofilewrite(int, struct file *, struct uio *, int, size_t *); /* * Read system call. @@ -98,6 +100,9 @@ sys_read(struct read_args *uap) struct iovec aiov; int error; + if ((ssize_t)uap->nbyte < 0) + error = EINVAL; + aiov.iov_base = uap->buf; aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; @@ -108,10 +113,7 @@ sys_read(struct read_args *uap) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - if (auio.uio_resid < 0) - error = EINVAL; - else - error = kern_preadv(uap->fd, &auio, 0, &uap->sysmsg_result); + error = kern_preadv(uap->fd, &auio, 0, &uap->sysmsg_szresult); return(error); } @@ -129,6 +131,9 @@ sys_extpread(struct extpread_args *uap) int error; int flags; + if ((ssize_t)uap->nbyte < 0) + return(EINVAL); + aiov.iov_base = uap->buf; aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; @@ -143,10 +148,7 @@ sys_extpread(struct extpread_args *uap) if (uap->offset != (off_t)-1) flags |= O_FOFFSET; - if (auio.uio_resid < 0) - error = EINVAL; - else - error = kern_preadv(uap->fd, &auio, flags, &uap->sysmsg_result); + error = kern_preadv(uap->fd, &auio, flags, &uap->sysmsg_szresult); return(error); } @@ -174,7 +176,7 @@ sys_readv(struct readv_args *uap) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - error = kern_preadv(uap->fd, &auio, 0, &uap->sysmsg_result); + error = kern_preadv(uap->fd, &auio, 0, &uap->sysmsg_szresult); iovec_free(&iov, aiov); return (error); @@ -210,7 +212,7 @@ sys_extpreadv(struct extpreadv_args *uap) if (uap->offset != (off_t)-1) flags |= O_FOFFSET; - error = kern_preadv(uap->fd, &auio, flags, &uap->sysmsg_result); + error = kern_preadv(uap->fd, &auio, flags, &uap->sysmsg_szresult); iovec_free(&iov, aiov); return(error); @@ -220,7 +222,7 @@ sys_extpreadv(struct extpreadv_args *uap) * MPSAFE */ int -kern_preadv(int fd, struct uio *auio, int flags, int *res) +kern_preadv(int fd, struct uio *auio, int flags, size_t *res) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -234,8 +236,6 @@ kern_preadv(int fd, struct uio *auio, int flags, int *res) return (EBADF); if (flags & O_FOFFSET && fp->f_type != DTYPE_VNODE) { error = ESPIPE; - } else if (auio->uio_resid < 0) { - error = EINVAL; } else { error = dofileread(fd, fp, auio, flags, res); } @@ -250,12 +250,12 @@ kern_preadv(int fd, struct uio *auio, int flags, int *res) * MPALMOSTSAFE - ktrace needs help */ static int -dofileread(int fd, struct file *fp, struct uio *auio, int flags, int *res) +dofileread(int fd, struct file *fp, struct uio *auio, int flags, size_t *res) { - struct thread *td = curthread; int error; - int len; + size_t len; #ifdef KTRACE + struct thread *td = curthread; struct iovec *ktriov = NULL; struct uio ktruio; #endif @@ -310,6 +310,9 @@ sys_write(struct write_args *uap) struct iovec aiov; int error; + if ((ssize_t)uap->nbyte < 0) + error = EINVAL; + aiov.iov_base = (void *)(uintptr_t)uap->buf; aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; @@ -320,10 +323,7 @@ sys_write(struct write_args *uap) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - if (auio.uio_resid < 0) - error = EINVAL; - else - error = kern_pwritev(uap->fd, &auio, 0, &uap->sysmsg_result); + error = kern_pwritev(uap->fd, &auio, 0, &uap->sysmsg_szresult); return(error); } @@ -342,6 +342,9 @@ sys_extpwrite(struct extpwrite_args *uap) int error; int flags; + if ((ssize_t)uap->nbyte < 0) + error = EINVAL; + aiov.iov_base = (void *)(uintptr_t)uap->buf; aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; @@ -355,12 +358,7 @@ sys_extpwrite(struct extpwrite_args *uap) flags = uap->flags & O_FMASK; if (uap->offset != (off_t)-1) flags |= O_FOFFSET; - - if (auio.uio_resid < 0) - error = EINVAL; - else - error = kern_pwritev(uap->fd, &auio, flags, &uap->sysmsg_result); - + error = kern_pwritev(uap->fd, &auio, flags, &uap->sysmsg_szresult); return(error); } @@ -386,7 +384,7 @@ sys_writev(struct writev_args *uap) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - error = kern_pwritev(uap->fd, &auio, 0, &uap->sysmsg_result); + error = kern_pwritev(uap->fd, &auio, 0, &uap->sysmsg_szresult); iovec_free(&iov, aiov); return (error); @@ -422,7 +420,7 @@ sys_extpwritev(struct extpwritev_args *uap) if (uap->offset != (off_t)-1) flags |= O_FOFFSET; - error = kern_pwritev(uap->fd, &auio, flags, &uap->sysmsg_result); + error = kern_pwritev(uap->fd, &auio, flags, &uap->sysmsg_szresult); iovec_free(&iov, aiov); return(error); @@ -432,7 +430,7 @@ sys_extpwritev(struct extpwritev_args *uap) * MPSAFE */ int -kern_pwritev(int fd, struct uio *auio, int flags, int *res) +kern_pwritev(int fd, struct uio *auio, int flags, size_t *res) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -461,12 +459,12 @@ kern_pwritev(int fd, struct uio *auio, int flags, int *res) * MPALMOSTSAFE - ktrace needs help */ static int -dofilewrite(int fd, struct file *fp, struct uio *auio, int flags, int *res) +dofilewrite(int fd, struct file *fp, struct uio *auio, int flags, size_t *res) { struct thread *td = curthread; struct lwp *lp = td->td_lwp; int error; - int len; + size_t len; #ifdef KTRACE struct iovec *ktriov = NULL; struct uio ktruio; @@ -517,12 +515,18 @@ dofilewrite(int fd, struct file *fp, struct uio *auio, int flags, int *res) /* * Ioctl system call + * + * MPALMOSTSAFE */ -/* ARGSUSED */ int sys_ioctl(struct ioctl_args *uap) { - return(mapped_ioctl(uap->fd, uap->com, uap->data, NULL)); + int error; + + get_mplock(); + error = mapped_ioctl(uap->fd, uap->com, uap->data, NULL, &uap->sysmsg); + rel_mplock(); + return (error); } struct ioctl_map_entry { @@ -537,7 +541,8 @@ struct ioctl_map_entry { * and appropriate conversions/conversion functions will be utilized. */ int -mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) +mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map, + struct sysmsg *msg) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -556,7 +561,7 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) } ubuf; KKASSERT(p); - cred = p->p_ucred; + cred = td->td_ucred; fp = holdfp(p->p_fd, fd, FREAD|FWRITE); if (fp == NULL) @@ -653,7 +658,7 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) } if ((com & IOC_IN) != 0) { if (size != 0) { - error = copyin(uspc_data, data, (u_int)size); + error = copyin(uspc_data, data, (size_t)size); if (error) { if (memp != NULL) kfree(memp, M_IOCTLOPS); @@ -667,7 +672,7 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) * Zero the buffer so the user always * gets back something deterministic. */ - bzero(data, size); + bzero(data, (size_t)size); } else if ((com & IOC_VOID) != 0) { *(caddr_t *)data = uspc_data; } @@ -686,7 +691,7 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) fp->f_flag |= FASYNC; else fp->f_flag &= ~FASYNC; - error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, cred); + error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, cred, msg); break; default: @@ -697,13 +702,13 @@ mapped_ioctl(int fd, u_long com, caddr_t uspc_data, struct ioctl_map *map) if (map != NULL && iomc->wrapfunc != NULL) error = iomc->wrapfunc(fp, com, ocom, data, cred); else - error = fo_ioctl(fp, com, data, cred); + error = fo_ioctl(fp, com, data, cred, msg); /* * Copy any data to user, size was * already set and checked above. */ if (error == 0 && (com & IOC_OUT) != 0 && size != 0) - error = copyout(data, uspc_data, (u_int)size); + error = copyout(data, uspc_data, (size_t)size); break; } if (memp != NULL) @@ -754,6 +759,8 @@ SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, ""); /* * Select system call. + * + * MPALMOSTSAFE */ int sys_select(struct select_args *uap) @@ -780,8 +787,10 @@ sys_select(struct select_args *uap) /* * Do real work. */ + get_mplock(); error = doselect(uap->nd, uap->in, uap->ou, uap->ex, ktvp, &uap->sysmsg_result); + rel_mplock(); return (error); } @@ -789,6 +798,8 @@ sys_select(struct select_args *uap) /* * Pselect system call. + * + * MPALMOSTSAFE */ int sys_pselect(struct pselect_args *uap) @@ -826,9 +837,12 @@ sys_pselect(struct pselect_args *uap) error = copyin(uap->sigmask, &sigmask, sizeof(sigmask)); if (error) return (error); + get_mplock(); lp->lwp_oldsigmask = lp->lwp_sigmask; SIG_CANTMASK(sigmask); lp->lwp_sigmask = sigmask; + } else { + get_mplock(); } /* @@ -855,6 +869,7 @@ sys_pselect(struct pselect_args *uap) lp->lwp_sigmask = lp->lwp_oldsigmask; } } + rel_mplock(); return (error); } @@ -959,15 +974,15 @@ retry: 24 * 60 * 60 * hz : tvtohz_high(&ttv); } crit_enter(); + tsleep_interlock(&selwait, PCATCH); if ((lp->lwp_flag & LWP_SELECT) == 0 || nselcoll != ncoll) { crit_exit(); goto retry; } lp->lwp_flag &= ~LWP_SELECT; - - error = tsleep((caddr_t)&selwait, PCATCH, "select", timo); - + error = tsleep(&selwait, PCATCH | PINTERLOCKED, "select", timo); crit_exit(); + if (error == 0) goto retry; done: @@ -1030,6 +1045,8 @@ selscan(struct proc *p, fd_mask **ibits, fd_mask **obits, int nfd, int *res) /* * Poll system call. + * + * MPALMOSTSAFE */ int sys_poll(struct poll_args *uap) @@ -1060,13 +1077,13 @@ sys_poll(struct poll_args *uap) bits = smallbits; error = copyin(uap->fds, bits, ni); if (error) - goto done; + goto done2; if (uap->timeout != INFTIM) { atv.tv_sec = uap->timeout / 1000; atv.tv_usec = (uap->timeout % 1000) * 1000; if (itimerfix(&atv)) { error = EINVAL; - goto done; + goto done2; } getmicrouptime(&rtv); timevaladd(&atv, &rtv); @@ -1075,32 +1092,37 @@ sys_poll(struct poll_args *uap) atv.tv_usec = 0; } timo = 0; + get_mplock(); retry: ncoll = nselcoll; lp->lwp_flag |= LWP_SELECT; error = pollscan(p, bits, nfds, &uap->sysmsg_result); if (error || uap->sysmsg_result) - goto done; + goto done1; if (atv.tv_sec || atv.tv_usec) { getmicrouptime(&rtv); if (timevalcmp(&rtv, &atv, >=)) - goto done; + goto done1; ttv = atv; timevalsub(&ttv, &rtv); timo = ttv.tv_sec > 24 * 60 * 60 ? 24 * 60 * 60 * hz : tvtohz_high(&ttv); } crit_enter(); + tsleep_interlock(&selwait, PCATCH); if ((lp->lwp_flag & LWP_SELECT) == 0 || nselcoll != ncoll) { crit_exit(); goto retry; } lp->lwp_flag &= ~LWP_SELECT; - error = tsleep((caddr_t)&selwait, PCATCH, "poll", timo); + error = tsleep(&selwait, PCATCH | PINTERLOCKED, "poll", timo); crit_exit(); + if (error == 0) goto retry; -done: +done1: + rel_mplock(); +done2: lp->lwp_flag &= ~LWP_SELECT; /* poll is not restarted after signals... */ if (error == ERESTART) @@ -1156,6 +1178,8 @@ pollscan(struct proc *p, struct pollfd *fds, u_int nfd, int *res) /* * OpenBSD poll system call. * XXX this isn't quite a true representation.. OpenBSD uses select ops. + * + * MPSAFE */ int sys_openbsd_poll(struct openbsd_poll_args *uap) @@ -1220,8 +1244,16 @@ selwakeup(struct selinfo *sip) if (lp == NULL) return; + /* + * This is a temporary hack until the code can be rewritten. + * Check LWP_SELECT before assuming we can setrunnable(). + * Otherwise we might catch the lwp before it actually goes to + * sleep. + */ crit_enter(); - if (lp->lwp_wchan == (caddr_t)&selwait) { + if (lp->lwp_flag & LWP_SELECT) { + lp->lwp_flag &= ~LWP_SELECT; + } else if (lp->lwp_wchan == (caddr_t)&selwait) { /* * Flag the process to break the tsleep when * setrunnable is called, but only call setrunnable @@ -1230,8 +1262,6 @@ selwakeup(struct selinfo *sip) lp->lwp_flag |= LWP_BREAKTSLEEP; if (p->p_stat != SSTOP) setrunnable(lp); - } else if (lp->lwp_flag & LWP_SELECT) { - lp->lwp_flag &= ~LWP_SELECT; } crit_exit(); }