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;
 }
 

Reply via email to