]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/sys_generic.c
xnu-517.12.7.tar.gz
[apple/xnu.git] / bsd / kern / sys_generic.c
index e02a30b866fee47ec0b76de697673b2da71dad8f..15fdf111fb85d2a6948de91e61cc074739ad0bae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -84,6 +84,9 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/errno.h>
+#include <sys/syscall.h>
+
+#include <bsm/audit_kernel.h>
 
 #include <net/if.h>
 #include <net/route.h>
 #if KTRACE 
 #include <sys/ktrace.h>
 #endif
+#include <sys/vnode.h>
 
-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;
@@ -124,7 +124,8 @@ holdfp(fdp, fd, flag)
                (fp->f_flag & flag) == 0) {
                        return (NULL);
        }
-       fref(fp);
+       if (fref(fp) == -1)
+               return (NULL);
        return (fp);   
 }
 
@@ -187,13 +188,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;
@@ -353,10 +359,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; 
@@ -403,8 +414,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 
@@ -572,9 +584,13 @@ ioctl(p, uap, retval)
 #define STK_PARAMS     128
        char stkbuf[STK_PARAMS];
 
+       AUDIT_ARG(fd, uap->fd);
+       AUDIT_ARG(cmd, uap->com); /* XXX cmd is int, uap->com is long */
+       AUDIT_ARG(addr, uap->data);
        if (error = fdgetf(p, uap->fd, &fp))
                return (error);
 
+       AUDIT_ARG(file, p, fp);
        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
                return (EBADF);
                
@@ -1027,6 +1043,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
@@ -1068,7 +1085,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++;
@@ -1101,8 +1129,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++;
                                        }
@@ -1146,6 +1179,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
@@ -1173,7 +1207,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++;
                        }
@@ -1208,7 +1245,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;
        }
@@ -1219,8 +1256,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;
 }
@@ -1244,7 +1281,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;
        }
 
@@ -1263,7 +1300,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);
 }
 
 
@@ -1640,7 +1677,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,
@@ -1698,8 +1735,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;