]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_syscalls.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_syscalls.c
index d8dbc492e153003fbecdecde2e758c27ef662b48..998e44ec2784c0a074f8a9da5d518b3f880ff651 100644 (file)
@@ -1,24 +1,21 @@
 /*
- * Copyright (c) 1995-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1995-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 #include <sys/sysctl.h>
 #include <sys/ubc.h>
 #include <sys/quota.h>
-#include <sys/kern_audit.h>
-#include <sys/bsm_kevents.h>
+
+#include <bsm/audit_kernel.h>
+#include <bsm/audit_kevents.h>
+
 #include <machine/cons.h>
 #include <miscfs/specfs/specdev.h>
 
@@ -97,6 +96,7 @@ uid_t console_user;
 static int change_dir __P((struct nameidata *ndp, struct proc *p));
 static void checkdirs __P((struct vnode *olddp));
 static void enablequotas __P((struct proc *p, struct mount *mp));
+void notify_filemod_watchers(struct vnode *vp, struct proc *p);
 
 /* counts number of mount and unmount operations */
 unsigned int vfs_nummntops=0;
@@ -1754,7 +1754,7 @@ ostat(p, uap, retval)
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, UIO_USERSPACE,
            uap->path, p);
        if (error = namei(&nd))
                return (error);
@@ -1787,8 +1787,8 @@ olstat(p, uap, retval)
        int error;
        struct nameidata nd;
 
-       NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
-           uap->path, p);
+       NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT | AUDITVNPATH1,
+              UIO_USERSPACE, uap->path, p);
        if (error = namei(&nd))
                return (error);
        /*
@@ -2061,10 +2061,11 @@ fchflags(p, uap, retval)
 
        vp = (struct vnode *)fp->f_data;
 
-       AUDIT_ARG(vnpath, vp, ARG_VNODE1);
-
        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+
+       AUDIT_ARG(vnpath, vp, ARG_VNODE1);
+
        VATTR_NULL(&vattr);
        vattr.va_flags = uap->flags;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
@@ -2103,6 +2104,7 @@ chmod(p, uap, retval)
        VATTR_NULL(&vattr);
        vattr.va_mode = uap->mode & ALLPERMS;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
        vput(vp);
        return (error);
 }
@@ -2141,6 +2143,7 @@ fchmod(p, uap, retval)
        vattr.va_mode = uap->mode & ALLPERMS;
        AUDIT_ARG(mode, (mode_t)vattr.va_mode);
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
        VOP_UNLOCK(vp, 0, p);
 
        return (error);
@@ -2190,6 +2193,7 @@ chown(p, uap, retval)
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
        vput(vp);
        return (error);
 }
@@ -2230,6 +2234,7 @@ fchown(p, uap, retval)
        vattr.va_uid = uap->uid;
        vattr.va_gid = uap->gid;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
        VOP_UNLOCK(vp, 0, p);
        return (error);
 }
@@ -2269,12 +2274,16 @@ setutimes(p, vp, ts, nullflag)
        error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        if (error)
                goto out;
+
+       AUDIT_ARG(vnpath, vp, ARG_VNODE1);
+
        VATTR_NULL(&vattr);
        vattr.va_atime = ts[0];
        vattr.va_mtime = ts[1];
        if (nullflag)
                vattr.va_vaflags |= VA_UTIMES_NULL;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
        VOP_UNLOCK(vp, 0, p);
 out:
        return error;
@@ -2343,8 +2352,6 @@ futimes(p, uap, retval)
        if ((error = getvnode(p, uap->fd, &fp)) != 0)
                return (error);
 
-       AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
-
        return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
 }
 
@@ -2419,14 +2426,14 @@ ftruncate(p, uap, retval)
        if (error = fdgetf(p, uap->fd, &fp))
                return (error);
 
-       AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
-
        if (fp->f_type == DTYPE_PSXSHM) {
                return(pshm_truncate(p, fp, uap->fd, uap->length, retval));
        }
        if (fp->f_type != DTYPE_VNODE) 
                return (EINVAL);
 
+       AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
+
        if ((fp->f_flag & FWRITE) == 0)
                return (EINVAL);
        vp = (struct vnode *)fp->f_data;
@@ -2557,14 +2564,14 @@ copyfile(p, uap, retval)
                return(EINVAL);
        }
 
-       NDINIT(&fromnd, LOOKUP, SAVESTART, UIO_USERSPACE,
-           uap->from, p);
+       NDINIT(&fromnd, LOOKUP, SAVESTART | AUDITVNPATH1,
+              UIO_USERSPACE, uap->from, p);
        if (error = namei(&fromnd))
                return (error);
        fvp = fromnd.ni_vp;
 
-       NDINIT(&tond, CREATE,  LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
-           UIO_USERSPACE, uap->to, p);
+       NDINIT(&tond, CREATE, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | AUDITVNPATH2,
+              UIO_USERSPACE, uap->to, p);
        if (error = namei(&tond)) {
                vrele(fvp);
                goto out1;
@@ -3017,8 +3024,12 @@ ogetdirentries(p, uap, retval)
        int error, eofflag, readcnt;
        long loff;
 
+       AUDIT_ARG(fd, uap->fd);
        if (error = getvnode(p, uap->fd, &fp))
                return (error);
+
+       AUDIT_ARG(vnpath, (struct vnode *)fp->f_data, ARG_VNODE1);
+
        if ((fp->f_flag & FREAD) == 0)
                return (EBADF);
        vp = (struct vnode *)fp->f_data;
@@ -3855,7 +3866,7 @@ checkuseraccess (p,uap,retval)
 
        nameiflags = LOCKLEAF;
        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
-       NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, (char *)uap->path, p);
+       NDINIT(&nd, LOOKUP, nameiflags | AUDITVNPATH1, UIO_USERSPACE, (char *)uap->path, p);
 
        if (error = namei(&nd))
                         return (error);
@@ -4142,6 +4153,7 @@ sync_internal(void)
 #define NUM_CHANGE_NODES 256
 static int                    changed_init=0;
 static volatile int           fmod_watch_enabled = 0;
+static pid_t                  fmod_watch_owner;
 static simple_lock_data_t     changed_nodes_lock;    // guard access
 static volatile struct vnode *changed_nodes[NUM_CHANGE_NODES];
 static volatile pid_t         changed_nodes_pid[NUM_CHANGE_NODES];
@@ -4155,7 +4167,7 @@ notify_filemod_watchers(struct vnode *vp, struct proc *p)
     int ret;
     
     // only want notification on regular files.
-    if (vp->v_type != VREG || fmod_watch_enabled == 0) {
+    if (fmod_watch_enabled == 0 || (vp->v_type != VREG && vp->v_type != VDIR)) {
        return;
     }
 
@@ -4254,8 +4266,10 @@ fmod_watch(struct proc *p, struct fmod_watch_args *uap, register_t *retval)
     changed_rd_index = (changed_rd_index + 1) % NUM_CHANGE_NODES;
 
     if (vp == NULL) {
-       panic("watch_file_changes: Someone put a null vnode in my table! (%d %d)\n",
-             changed_rd_index, changed_wr_index);
+       printf("watch_file_changes: Someone put a null vnode in my table! (%d %d)\n",
+              changed_rd_index, changed_wr_index);
+       error = EINVAL;
+       goto err0;
     }
 
     simple_unlock(&changed_nodes_lock);
@@ -4266,7 +4280,7 @@ fmod_watch(struct proc *p, struct fmod_watch_args *uap, register_t *retval)
        wakeup((caddr_t)&changed_wr_index);
     }
 
-    if (vp->v_type != VREG) {
+    if (vp->v_type != VREG && vp->v_type != VDIR) {
        error = EBADF;
        goto err1;
     }
@@ -4351,6 +4365,7 @@ fmod_watch(struct proc *p, struct fmod_watch_args *uap, register_t *retval)
   err1:
     vrele(vp);    // undoes the vref() in notify_filemod_watchers()
 
+  err0:
     *retval = -1;
     return error;
 }
@@ -4370,6 +4385,8 @@ enable_fmod_watching(register_t *retval)
     }
     
     fmod_watch_enabled++;
+    fmod_watch_owner = current_proc()->p_pid;
+
     *retval = 0;
     return 0;
 }
@@ -4377,11 +4394,17 @@ enable_fmod_watching(register_t *retval)
 static int
 disable_fmod_watching(register_t *retval)
 {
-    fmod_watch_enabled--;
-    if (fmod_watch_enabled < 0) {
-       panic("fmod_watching: too many disables! (%d)\n", fmod_watch_enabled);
+    if (!is_suser()) {
+       return EPERM;
     }
     
+    if (fmod_watch_enabled < 1) {
+       printf("fmod_watching: too many disables! (%d)\n", fmod_watch_enabled);
+       return EINVAL;
+    }
+
+    fmod_watch_enabled--;
+    
     // if we're the last guy, clear out any remaining vnodes
     // in the table so they don't remain referenced.
     //
@@ -4396,6 +4419,8 @@ disable_fmod_watching(register_t *retval)
            i = (i + 1) % NUM_CHANGE_NODES;
        }
        changed_wr_index = changed_rd_index = 0;
+
+       fmod_watch_owner = 0;
     }
 
     // wake up anyone that may be waiting for the
@@ -4430,3 +4455,13 @@ fmod_watch_enable(struct proc *p, struct fmod_watch_enable_args *uap, register_t
 
     return ret;
 }
+
+void
+clean_up_fmod_watch(struct proc *p)
+{
+    if (fmod_watch_enabled && fmod_watch_owner == p->p_pid) {
+       register_t *retval;
+       
+       disable_fmod_watching(&retval);
+    }
+}