diff options
Diffstat (limited to 'sys/security/lomac/lomacfs_vfsops.c')
-rw-r--r-- | sys/security/lomac/lomacfs_vfsops.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/sys/security/lomac/lomacfs_vfsops.c b/sys/security/lomac/lomacfs_vfsops.c new file mode 100644 index 0000000..c7ee93a --- /dev/null +++ b/sys/security/lomac/lomacfs_vfsops.c @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2001 Networks Associates Technologies, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by NAI Labs, the + * Security Research Division of Network Associates, Inc. under + * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA + * CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/mount.h> +#include <sys/namei.h> +#include <sys/vnode.h> + +#include "lomacfs.h" +#include "kernel_mediate.h" + +MALLOC_DEFINE(M_LOMACFS, "LOMACFS", "LOMAC filesystem objects"); + +static int lomacfs_mount(struct mount *mp, char *path, caddr_t data, + struct nameidata *ndp, struct thread *td); +static int lomacfs_statfs(struct mount *mp, struct statfs *sbp, + struct thread *td); +static int lomacfs_unmount(struct mount *mp, int mntflags, struct thread *td); + +static int +lomacfs_mount(struct mount *mp, char *path, caddr_t data, + struct nameidata *ndp, struct thread *td) { + + if (mp->mnt_flag & MNT_UPDATE || VISLOMAC(mp->mnt_vnodecovered)) + return (EOPNOTSUPP); + + mp->mnt_flag |= MNT_LOCAL; + mp->mnt_flag &= ~MNT_RDONLY; + mp->mnt_data = malloc(sizeof(struct lomac_mount), M_LOMACFS, + M_WAITOK | M_ZERO); + vfs_getnewfsid(mp); + + strncpy(mp->mnt_stat.f_mntfromname, "lomacfs", MNAMELEN); + (void)lomacfs_statfs(mp, &mp->mnt_stat, td); + + /* + * Keep around an extra ref for dounmount() to vrele() after the + * VFS_UNMOUNT()... (who knows...) + */ + vref(mp->mnt_vnodecovered); + if (VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) + VOP_UNLOCK(mp->mnt_vnodecovered, 0, td); + + return (0); +} + +static int +lomacfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) { + struct statfs tmpstat; + int error; + + bzero(&tmpstat, sizeof(tmpstat)); + + error = VFS_STATFS(mp->mnt_vnodecovered->v_mount, &tmpstat, td); + if (error) + return (error); + + sbp->f_type = tmpstat.f_type; + sbp->f_flags = tmpstat.f_flags; + sbp->f_bsize = tmpstat.f_bsize; + sbp->f_iosize = tmpstat.f_iosize; + sbp->f_blocks = tmpstat.f_blocks; + sbp->f_bfree = tmpstat.f_bfree; + sbp->f_bavail = tmpstat.f_bavail; + sbp->f_files = tmpstat.f_files; + sbp->f_ffree = tmpstat.f_ffree; + if (sbp != &mp->mnt_stat) { + bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); + bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); + bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); + } + return (0); +} + +static int +lomacfs_unmount(struct mount *mp, int mntflags, struct thread *td) { + struct vnode *crootvp = VFSTOLOMAC(mp)->lm_rootvp; + int error; + int flags = 0; + + if (mntflags & MNT_FORCE) + flags |= FORCECLOSE; + + if (VFSTOLOMAC(mp)->lm_flags & LM_TOOKROOT) { + mtx_lock(&crootvp->v_interlock); + crootvp->v_flag |= VROOT; + mtx_unlock(&crootvp->v_interlock); + } + + error = vflush(mp, 1, flags); /* have an extra root ref */ + if (error) + return (error); + + free(VFSTOLOMAC(mp), M_LOMACFS); + + /* bye, lomacfs. */ + return (0); +} + +static int +lomacfs_root(struct mount *mp, struct vnode **vpp) { + int error; + + if (VFSTOLOMAC(mp)->lm_rootvp == NULL) { + struct vnode *rootvp, *crootvp; + + crootvp = mp->mnt_vnodecovered; + error = lomacfs_node_alloc(mp, NULL, NULL, crootvp, &rootvp); + if (error) + return (error); + /* + * Reference twice to match the rest of the lomacfs vnodes. + */ + vref(crootvp); + vref(crootvp); + VFSTOLOMAC(mp)->lm_rootvp = rootvp; + /* + * This releases the lock on root, but it doesn't release + * the reference so that root won't "disappear" until + * unmount. + */ + error = VOP_UNLOCK(rootvp, 0, curthread); + if (error) + return (error); + /* + * This is some strange magic here... I need to pretend + * that the mounted-on directory isn't a root vnode if I + * want things like __getcwd() to just fail and not crash. + */ + mtx_lock(&crootvp->v_interlock); + if (crootvp->v_flag & VROOT && crootvp == rootvnode) { + crootvp->v_flag &= ~VROOT; + VFSTOLOMAC(mp)->lm_flags |= LM_TOOKROOT; + } + mtx_unlock(&crootvp->v_interlock); + } + *vpp = VFSTOLOMAC(mp)->lm_rootvp; + return (vget(*vpp, LK_EXCLUSIVE, curthread)); +} + +static struct vfsops lomacfs_vfsops = { + lomacfs_mount, + vfs_stdstart, + lomacfs_unmount, + lomacfs_root, + vfs_stdquotactl, + lomacfs_statfs, + vfs_stdsync, + vfs_stdvget, + vfs_stdfhtovp, + vfs_stdcheckexp, + vfs_stdvptofh, + vfs_stdinit, + vfs_stduninit, + vfs_stdextattrctl +}; +VFS_SET(lomacfs_vfsops, lomacfs, VFCF_LOOPBACK); +MODULE_VERSION(lomacfs, 1); +MODULE_DEPEND(lomacfs, lomac_plm, 1, 1, 1); |