X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..55e303ae13a4cf49d70f2294092726f2fffb9ef2:/bsd/kern/sys_generic.c diff --git a/bsd/kern/sys_generic.c b/bsd/kern/sys_generic.c index eb721f871..5e2545890 100644 --- a/bsd/kern/sys_generic.c +++ b/bsd/kern/sys_generic.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include @@ -109,13 +110,10 @@ #if KTRACE #include #endif +#include -static int dofileread __P((struct proc *, struct file *, int, void *, - size_t, off_t, int, int*)); -static int dofilewrite __P((struct proc *, struct file *, int, - const void *, size_t, off_t, int, int*)); -static struct file* +__private_extern__ struct file* holdfp(fdp, fd, flag) struct filedesc* fdp; int fd, flag; @@ -191,13 +189,18 @@ pread(p, uap, retval) uap->offset, FOF_OFFSET, retval); } frele(fp); + + if (!error) + KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO, SYS_pread) | DBG_FUNC_NONE), + uap->fd, uap->nbyte, (unsigned int)((uap->offset >> 32)), (unsigned int)(uap->offset), 0); + return(error); } /* * Code common for read and pread */ -int +__private_extern__ int dofileread(p, fp, fd, buf, nbyte, offset, flags, retval) struct proc *p; struct file *fp; @@ -357,10 +360,15 @@ pwrite(p, uap, retval) uap->offset, FOF_OFFSET, retval); } frele(fp); + + if (!error) + KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO, SYS_pwrite) | DBG_FUNC_NONE), + uap->fd, uap->nbyte, (unsigned int)((uap->offset >> 32)), (unsigned int)(uap->offset), 0); + return(error); } -static int +__private_extern__ int dofilewrite(p, fp, fd, buf, nbyte, offset, flags, retval) struct proc *p; struct file *fp; @@ -407,8 +415,9 @@ dofilewrite(p, fp, fd, buf, nbyte, offset, flags, retval) if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; - if (error == EPIPE) - psignal(p, SIGPIPE); + /* The socket layer handles SIGPIPE */ + if (error == EPIPE && fp->f_type != DTYPE_SOCKET) + psignal(p, SIGPIPE); } cnt -= auio.uio_resid; #if KTRACE @@ -1031,6 +1040,7 @@ selscan(p, sel, nfd, retval, sel_pass) int nfunnel = 0; int count, nfcount; char * wql_ptr; + struct vnode *vp; /* * Problems when reboot; due to MacOSX signal probs @@ -1072,7 +1082,18 @@ selscan(p, sel, nfd, retval, sel_pass) wql_ptr = (char *)0; else wql_ptr = (wql+ nc * SIZEOF_WAITQUEUE_LINK); - if (fp->f_ops && (fp->f_type != DTYPE_SOCKET) + /* + * Merlot: need to remove the bogus f_data check + * from the following "if" statement. It's there + * because of various problems stemming from + * races due to the split-funnels and lack of real + * referencing on sockets... + */ + if (fp->f_ops && (fp->f_type != DTYPE_SOCKET) + && (fp->f_data != (caddr_t)-1) + && !(fp->f_type == DTYPE_VNODE + && (vp = (struct vnode *)fp->f_data) + && vp->v_type == VFIFO) && fo_select(fp, flag[msk], wql_ptr, p)) { optr[fd/NFDBITS] |= (1 << (fd % NFDBITS)); n++; @@ -1105,8 +1126,13 @@ selscan(p, sel, nfd, retval, sel_pass) wql_ptr = (char *)0; else wql_ptr = (wql+ nc * SIZEOF_WAITQUEUE_LINK); - if (fp->f_ops && (fp->f_type == DTYPE_SOCKET) && - fo_select(fp, flag[msk], wql_ptr, p)) { + if (fp->f_ops + && (fp->f_type == DTYPE_SOCKET + || (fp->f_type == DTYPE_VNODE + && (vp = (struct vnode *)fp->f_data) + && vp != (struct vnode *)-1 + && vp->v_type == VFIFO)) + && fo_select(fp, flag[msk], wql_ptr, p)) { optr[fd/NFDBITS] |= (1 << (fd % NFDBITS)); n++; } @@ -1150,6 +1176,7 @@ selcount(p, ibits, obits, nfd, count, nfcount) static int flag[3] = { FREAD, FWRITE, 0 }; u_int32_t *iptr, *fptr, *fbits; u_int nw; + struct vnode *vp; /* * Problems when reboot; due to MacOSX signal probs @@ -1177,7 +1204,10 @@ selcount(p, ibits, obits, nfd, count, nfcount) *nfcount=0; return(EBADF); } - if (fp->f_type == DTYPE_SOCKET) + if (fp->f_type == DTYPE_SOCKET || + (fp->f_type == DTYPE_VNODE + && (vp = (struct vnode *)fp->f_data) + && vp->v_type == VFIFO)) nfc++; n++; } @@ -1212,7 +1242,7 @@ selrecord(selector, sip, p_wql) } if ((sip->si_flags & SI_INITED) == 0) { - wait_queue_init(&sip->wait_queue, SYNC_POLICY_FIFO); + wait_queue_init(&sip->si_wait_queue, SYNC_POLICY_FIFO); sip->si_flags |= SI_INITED; sip->si_flags &= ~SI_CLEAR; } @@ -1223,8 +1253,8 @@ selrecord(selector, sip, p_wql) sip->si_flags &= ~SI_COLL; sip->si_flags |= SI_RECORDED; - if (!wait_queue_member(&sip->wait_queue, ut->uu_wqsub)) - wait_queue_link_noalloc(&sip->wait_queue, ut->uu_wqsub, (wait_queue_link_t)p_wql); + if (!wait_queue_member(&sip->si_wait_queue, ut->uu_wqsub)) + wait_queue_link_noalloc(&sip->si_wait_queue, ut->uu_wqsub, (wait_queue_link_t)p_wql); return; } @@ -1248,7 +1278,7 @@ selwakeup(sip) } if (sip->si_flags & SI_RECORDED) { - wait_queue_wakeup_all(&sip->wait_queue, &selwait, THREAD_AWAKENED); + wait_queue_wakeup_all(&sip->si_wait_queue, &selwait, THREAD_AWAKENED); sip->si_flags &= ~SI_RECORDED; } @@ -1267,7 +1297,7 @@ selthreadclear(sip) sip->si_flags &= ~(SI_RECORDED | SI_COLL); } sip->si_flags |= SI_CLEAR; - wait_queue_unlinkall_nofree(&sip->wait_queue); + wait_queue_unlinkall_nofree(&sip->si_wait_queue); } @@ -1644,7 +1674,7 @@ retry: } if (interval != 0) - clock_absolutetime_interval_to_deadline(interval, &abstime) + clock_absolutetime_interval_to_deadline(interval, &abstime); KERNEL_DEBUG(DBG_MISC_WAIT, 1,&p->p_evlist,0,0,0); error = tsleep1(&p->p_evlist, PSOCK | PCATCH, @@ -1702,8 +1732,10 @@ modwatch(p, uap, retval) return(EBADF); if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock sp = (struct socket *)fp->f_data; - assert(sp != NULL); + /* soo_close sets f_data to 0 before switching funnel */ + if (sp == (struct socket *)0) + return(EBADF); // locate event if possible for (evq = sp->so_evlist.tqh_first;