/*
- * 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>
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;
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);
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);
/*
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);
VATTR_NULL(&vattr);
vattr.va_mode = uap->mode & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
vput(vp);
return (error);
}
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);
vattr.va_uid = uap->uid;
vattr.va_gid = uap->gid;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+
vput(vp);
return (error);
}
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);
}
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;
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);
}
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;
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;
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;
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);
#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];
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;
}
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);
wakeup((caddr_t)&changed_wr_index);
}
- if (vp->v_type != VREG) {
+ if (vp->v_type != VREG && vp->v_type != VDIR) {
error = EBADF;
goto err1;
}
err1:
vrele(vp); // undoes the vref() in notify_filemod_watchers()
+ err0:
*retval = -1;
return error;
}
}
fmod_watch_enabled++;
+ fmod_watch_owner = current_proc()->p_pid;
+
*retval = 0;
return 0;
}
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.
//
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
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);
+ }
+}