Module Name: src Committed By: rmind Date: Sun Apr 24 21:35:30 UTC 2011
Modified Files: src/sys/fs/nilfs: nilfs_vnops.c src/sys/fs/tmpfs: tmpfs_vnops.c src/sys/fs/udf: udf_vnops.c src/sys/kern: vfs_syscalls.c src/sys/nfs: nfs_vnops.c src/sys/ufs/ext2fs: ext2fs_vnops.c src/sys/ufs/ufs: ufs_vnops.c Log Message: sys_link: prevent hard links on directories (cross-mount operations are already prevented). File systems are no longer responsible to check this. Clean up and add asserts (note that dvp == vp cannot happen in vop_link). OK dholland@ To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/fs/nilfs/nilfs_vnops.c cvs rdiff -u -r1.76 -r1.77 src/sys/fs/tmpfs/tmpfs_vnops.c cvs rdiff -u -r1.62 -r1.63 src/sys/fs/udf/udf_vnops.c cvs rdiff -u -r1.422 -r1.423 src/sys/kern/vfs_syscalls.c cvs rdiff -u -r1.289 -r1.290 src/sys/nfs/nfs_vnops.c cvs rdiff -u -r1.97 -r1.98 src/sys/ufs/ext2fs/ext2fs_vnops.c cvs rdiff -u -r1.187 -r1.188 src/sys/ufs/ufs/ufs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/nilfs/nilfs_vnops.c diff -u src/sys/fs/nilfs/nilfs_vnops.c:1.9 src/sys/fs/nilfs/nilfs_vnops.c:1.10 --- src/sys/fs/nilfs/nilfs_vnops.c:1.9 Tue Nov 30 10:43:03 2010 +++ src/sys/fs/nilfs/nilfs_vnops.c Sun Apr 24 21:35:29 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: nilfs_vnops.c,v 1.9 2010/11/30 10:43:03 dholland Exp $ */ +/* $NetBSD: nilfs_vnops.c,v 1.10 2011/04/24 21:35:29 rmind Exp $ */ /* * Copyright (c) 2008, 2009 Reinoud Zandijk @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.9 2010/11/30 10:43:03 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.10 2011/04/24 21:35:29 rmind Exp $"); #endif /* not lint */ @@ -1159,15 +1159,9 @@ int error; DPRINTF(VFSCALL, ("nilfs_link called\n")); - error = 0; - - /* some quick checks */ - if (vp->v_type == VDIR) - return EPERM; /* can't link a directory */ - if (dvp->v_mount != vp->v_mount) - return EXDEV; /* can't link across devices */ - if (dvp == vp) - return EPERM; /* can't be the same */ + KASSERT(dvp != vp); + KASSERT(vp->v_type != VDIR); + KASSERT(dvp->v_mount == vp->v_mount); /* lock node */ error = vn_lock(vp, LK_EXCLUSIVE); Index: src/sys/fs/tmpfs/tmpfs_vnops.c diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.76 src/sys/fs/tmpfs/tmpfs_vnops.c:1.77 --- src/sys/fs/tmpfs/tmpfs_vnops.c:1.76 Thu Jan 13 13:35:12 2011 +++ src/sys/fs/tmpfs/tmpfs_vnops.c Sun Apr 24 21:35:29 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: tmpfs_vnops.c,v 1.76 2011/01/13 13:35:12 pooka Exp $ */ +/* $NetBSD: tmpfs_vnops.c,v 1.77 2011/04/24 21:35:29 rmind Exp $ */ /* * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.76 2011/01/13 13:35:12 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.77 2011/04/24 21:35:29 rmind Exp $"); #include <sys/param.h> #include <sys/dirent.h> @@ -737,44 +737,34 @@ return error; } -/* --------------------------------------------------------------------- */ - +/* + * tmpfs:link: create hard link. + */ int tmpfs_link(void *v) { - struct vnode *dvp = ((struct vop_link_args *)v)->a_dvp; - struct vnode *vp = ((struct vop_link_args *)v)->a_vp; - struct componentname *cnp = ((struct vop_link_args *)v)->a_cnp; - - int error; + struct vop_link_args /* { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; + } */ *ap = v; + struct vnode *dvp = ap->a_dvp; + struct vnode *vp = ap->a_vp; + struct componentname *cnp = ap->a_cnp;; + struct tmpfs_node *dnode, *node; struct tmpfs_dirent *de; - struct tmpfs_node *dnode; - struct tmpfs_node *node; + int error; + KASSERT(dvp != vp); KASSERT(VOP_ISLOCKED(dvp)); - KASSERT(dvp != vp); /* XXX When can this be false? */ + KASSERT(vp->v_type != VDIR); + KASSERT(dvp->v_mount == vp->v_mount); dnode = VP_TO_TMPFS_DIR(dvp); node = VP_TO_TMPFS_NODE(vp); - /* Lock vp because we will need to run tmpfs_update over it, which - * needs the vnode to be locked. */ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - /* XXX: Why aren't the following two tests done by the caller? */ - - /* Hard links of directories are forbidden. */ - if (vp->v_type == VDIR) { - error = EPERM; - goto out; - } - - /* Cannot create cross-device links. */ - if (dvp->v_mount != vp->v_mount) { - error = EXDEV; - goto out; - } - /* Ensure that we do not overflow the maximum number of links imposed * by the system. */ KASSERT(node->tn_links <= LINK_MAX); Index: src/sys/fs/udf/udf_vnops.c diff -u src/sys/fs/udf/udf_vnops.c:1.62 src/sys/fs/udf/udf_vnops.c:1.63 --- src/sys/fs/udf/udf_vnops.c:1.62 Sun Jan 2 05:09:30 2011 +++ src/sys/fs/udf/udf_vnops.c Sun Apr 24 21:35:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: udf_vnops.c,v 1.62 2011/01/02 05:09:30 dholland Exp $ */ +/* $NetBSD: udf_vnops.c,v 1.63 2011/04/24 21:35:30 rmind Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -32,7 +32,7 @@ #include <sys/cdefs.h> #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.62 2011/01/02 05:09:30 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.63 2011/04/24 21:35:30 rmind Exp $"); #endif /* not lint */ @@ -1481,15 +1481,9 @@ int error; DPRINTF(CALL, ("udf_link called\n")); - error = 0; - - /* some quick checks */ - if (vp->v_type == VDIR) - return EPERM; /* can't link a directory */ - if (dvp->v_mount != vp->v_mount) - return EXDEV; /* can't link across devices */ - if (dvp == vp) - return EPERM; /* can't be the same */ + KASSERT(dvp != vp); + KASSERT(vp->v_type != VDIR); + KASSERT(dvp->v_mount == vp->v_mount); /* lock node */ error = vn_lock(vp, LK_EXCLUSIVE); Index: src/sys/kern/vfs_syscalls.c diff -u src/sys/kern/vfs_syscalls.c:1.422 src/sys/kern/vfs_syscalls.c:1.423 --- src/sys/kern/vfs_syscalls.c:1.422 Sun Apr 10 15:45:33 2011 +++ src/sys/kern/vfs_syscalls.c Sun Apr 24 21:35:29 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_syscalls.c,v 1.422 2011/04/10 15:45:33 christos Exp $ */ +/* $NetBSD: vfs_syscalls.c,v 1.423 2011/04/24 21:35:29 rmind Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.422 2011/04/10 15:45:33 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.423 2011/04/24 21:35:29 rmind Exp $"); #ifdef _KERNEL_OPT #include "opt_fileassoc.h" @@ -1767,9 +1767,12 @@ error = EEXIST; goto abortop; } - /* - * Prevent cross-mount operation. - */ + /* Prevent hard links on directories. */ + if (vp->v_type == VDIR) { + error = EPERM; + goto abortop; + } + /* Prevent cross-mount operation. */ if (nd.ni_dvp->v_mount != vp->v_mount) { error = EXDEV; goto abortop; Index: src/sys/nfs/nfs_vnops.c diff -u src/sys/nfs/nfs_vnops.c:1.289 src/sys/nfs/nfs_vnops.c:1.290 --- src/sys/nfs/nfs_vnops.c:1.289 Tue Dec 14 16:58:58 2010 +++ src/sys/nfs/nfs_vnops.c Sun Apr 24 21:35:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_vnops.c,v 1.289 2010/12/14 16:58:58 cegger Exp $ */ +/* $NetBSD: nfs_vnops.c,v 1.290 2011/04/24 21:35:30 rmind Exp $ */ /* * Copyright (c) 1989, 1993 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.289 2010/12/14 16:58:58 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.290 2011/04/24 21:35:30 rmind Exp $"); #ifdef _KERNEL_OPT #include "opt_nfs.h" @@ -2050,18 +2050,11 @@ struct componentname *cnp = ap->a_cnp; int error = 0; - if (dvp->v_mount != vp->v_mount) { + error = vn_lock(vp, LK_EXCLUSIVE); + if (error != 0) { VOP_ABORTOP(dvp, cnp); vput(dvp); - return (EXDEV); - } - if (dvp != vp) { - error = vn_lock(vp, LK_EXCLUSIVE); - if (error != 0) { - VOP_ABORTOP(dvp, cnp); - vput(dvp); - return error; - } + return error; } /* @@ -2074,10 +2067,10 @@ error = nfs_linkrpc(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_cred, curlwp); - if (error == 0) + if (error == 0) { cache_purge1(dvp, cnp, 0); - if (dvp != vp) - VOP_UNLOCK(vp); + } + VOP_UNLOCK(vp); VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(dvp, NOTE_WRITE); vput(dvp); Index: src/sys/ufs/ext2fs/ext2fs_vnops.c diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.97 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.98 --- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.97 Sun Jan 2 05:09:32 2011 +++ src/sys/ufs/ext2fs/ext2fs_vnops.c Sun Apr 24 21:35:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vnops.c,v 1.97 2011/01/02 05:09:32 dholland Exp $ */ +/* $NetBSD: ext2fs_vnops.c,v 1.98 2011/04/24 21:35:30 rmind Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.97 2011/01/02 05:09:32 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.98 2011/04/24 21:35:30 rmind Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -552,7 +552,7 @@ } /* - * link vnode call + * ext2fs_link: create hard link. */ int ext2fs_link(void *v) @@ -568,17 +568,12 @@ struct inode *ip; int error; - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - error = EISDIR; - goto out2; - } - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - error = EXDEV; - goto out2; - } - if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { + KASSERT(dvp != vp); + KASSERT(vp->v_type != VDIR); + KASSERT(dvp->v_mount == vp->v_mount); + + error = vn_lock(vp, LK_EXCLUSIVE); + if (error) { VOP_ABORTOP(dvp, cnp); goto out2; } @@ -603,8 +598,7 @@ ip->i_flag |= IN_CHANGE; } out1: - if (dvp != vp) - VOP_UNLOCK(vp); + VOP_UNLOCK(vp); out2: VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(dvp, NOTE_WRITE); Index: src/sys/ufs/ufs/ufs_vnops.c diff -u src/sys/ufs/ufs/ufs_vnops.c:1.187 src/sys/ufs/ufs/ufs_vnops.c:1.188 --- src/sys/ufs/ufs/ufs_vnops.c:1.187 Sun Mar 6 17:08:39 2011 +++ src/sys/ufs/ufs/ufs_vnops.c Sun Apr 24 21:35:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_vnops.c,v 1.187 2011/03/06 17:08:39 bouyer Exp $ */ +/* $NetBSD: ufs_vnops.c,v 1.188 2011/04/24 21:35:30 rmind Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.187 2011/03/06 17:08:39 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.188 2011/04/24 21:35:30 rmind Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -786,7 +786,7 @@ } /* - * link vnode call + * ufs_link: create hard link. */ int ufs_link(void *v) @@ -796,28 +796,20 @@ struct vnode *a_vp; struct componentname *a_cnp; } */ *ap = v; - struct vnode *vp, *dvp; - struct componentname *cnp; - struct inode *ip; - struct direct *newdir; - int error; + struct vnode *dvp = ap->a_dvp; + struct vnode *vp = ap->a_vp; + struct componentname *cnp = ap->a_cnp; + struct inode *ip; + struct direct *newdir; + int error; - dvp = ap->a_dvp; - vp = ap->a_vp; - cnp = ap->a_cnp; + KASSERT(dvp != vp); + KASSERT(vp->v_type != VDIR); + KASSERT(dvp->v_mount == vp->v_mount); fstrans_start(dvp->v_mount, FSTRANS_SHARED); - if (vp->v_type == VDIR) { - VOP_ABORTOP(dvp, cnp); - error = EPERM; - goto out2; - } - if (dvp->v_mount != vp->v_mount) { - VOP_ABORTOP(dvp, cnp); - error = EXDEV; - goto out2; - } - if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { + error = vn_lock(vp, LK_EXCLUSIVE); + if (error) { VOP_ABORTOP(dvp, cnp); goto out2; } @@ -855,8 +847,7 @@ } UFS_WAPBL_END(vp->v_mount); out1: - if (dvp != vp) - VOP_UNLOCK(vp); + VOP_UNLOCK(vp); out2: VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(dvp, NOTE_WRITE);