Module Name: src Committed By: christos Date: Wed Mar 30 13:24:00 UTC 2022
Modified Files: src/sys/fs/udf: udf_vnops.c Log Message: Fix locking in udf_link(). XXX: udf_symlink is prolly similarly broken. To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/fs/udf/udf_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/udf/udf_vnops.c diff -u src/sys/fs/udf/udf_vnops.c:1.120 src/sys/fs/udf/udf_vnops.c:1.121 --- src/sys/fs/udf/udf_vnops.c:1.120 Sun Mar 27 12:24:58 2022 +++ src/sys/fs/udf/udf_vnops.c Wed Mar 30 09:23:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: udf_vnops.c,v 1.120 2022/03/27 16:24:58 christos Exp $ */ +/* $NetBSD: udf_vnops.c,v 1.121 2022/03/30 13:23:59 christos 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.120 2022/03/27 16:24:58 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.121 2022/03/30 13:23:59 christos Exp $"); #endif /* not lint */ @@ -1542,12 +1542,20 @@ udf_mkdir(void *v) /* --------------------------------------------------------------------- */ -static int -udf_do_link(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) +int +udf_link(void *v) { + struct vop_link_v2_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 udf_node *udf_node, *dir_node; struct vattr vap; - int error; + int error, abrt = 1; DPRINTF(CALL, ("udf_link called\n")); KASSERT(dvp != vp); @@ -1558,44 +1566,31 @@ udf_do_link(struct vnode *dvp, struct vn dir_node = VTOI(dvp); udf_node = VTOI(vp); + if ((error = vn_lock(vp, LK_EXCLUSIVE))) { + DPRINTF("lock failed. %p\n", vp); + goto out; + } + error = VOP_GETATTR(vp, &vap, FSCRED); if (error) - goto out; + goto out1; /* check link count overflow */ if (vap.va_nlink >= (1<<16)-1) { /* uint16_t */ error = EMLINK; - goto out; + goto out1; } error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_ADD_LINK, vp, dvp, 0); if (error) - goto out; - + goto out1; + abrt = 0; error = udf_dir_attach(dir_node->ump, dir_node, udf_node, &vap, cnp); +out1: + VOP_UNLOCK(vp); out: - if (error) - VOP_UNLOCK(vp); - return error; -} - -int -udf_link(void *v) -{ - struct vop_link_v2_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; - int error; - - error = udf_do_link(dvp, vp, cnp); - if (error) + if (abrt) VOP_ABORTOP(dvp, cnp); - return error; }