git: ee95e4d02dbd - main - vfs_vnops.c: Fix the named attribute check for open

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Sun, 20 Apr 2025 23:20:09 UTC
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=ee95e4d02dbdd59daed46bbf2170897c1c2a8894

commit ee95e4d02dbdd59daed46bbf2170897c1c2a8894
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2025-04-20 23:19:05 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2025-04-20 23:19:05 +0000

    vfs_vnops.c: Fix the named attribute check for open
    
    In vn_open_cred(), the correct check for O_NAMEDATTR
    was done when O_CREAT was specified, but the file already
    exists. (Added by commit 2ec2ba7e232d, which will be listed
    as a Fixes: in the commit log message.)
    
    This correct check was not copied to the case where O_CREAT
    has not been specified.
    
    This patch fixes this.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D49898
    Fixes:  2ec2ba7e232d ("vfs: Add VFS/syscall support for Solaris style extended attributes")
---
 sys/kern/vfs_vnops.c | 39 ++++++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 4a369559111e..6ad9c75564c3 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -222,6 +222,25 @@ open2nameif(int fmode, u_int vn_open_flags)
 	return (res);
 }
 
+/*
+ * For the O_NAMEDATTR case, check for a valid use of it.
+ */
+static int
+vfs_check_namedattr(struct vnode *vp)
+{
+	int error;
+	short irflag;
+
+	error = 0;
+	irflag = vn_irflag_read(vp);
+	if ((vp->v_mount->mnt_flag & MNT_NAMEDATTR) == 0 ||
+	    ((irflag & VIRF_NAMEDATTR) != 0 && vp->v_type != VREG))
+		error = EINVAL;
+	else if ((irflag & (VIRF_NAMEDDIR | VIRF_NAMEDATTR)) == 0)
+		error = ENOATTR;
+	return (error);
+}
+
 /*
  * Common code for vnode open operations via a name lookup.
  * Lookup the vnode and invoke VOP_CREATE if needed.
@@ -334,17 +353,7 @@ restart:
 				goto bad;
 			}
 			if ((fmode & O_NAMEDATTR) != 0) {
-				short irflag;
-
-				irflag = vn_irflag_read(vp);
-				if ((vp->v_mount->mnt_flag &
-				     MNT_NAMEDATTR) == 0 ||
-				    ((irflag & VIRF_NAMEDATTR) != 0 &&
-				    vp->v_type != VREG))
-					error = EINVAL;
-				else if ((irflag & (VIRF_NAMEDDIR |
-				    VIRF_NAMEDATTR)) == 0)
-					error = ENOATTR;
+				error = vfs_check_namedattr(vp);
 				if (error != 0)
 					goto bad;
 			} else if (vp->v_type == VDIR) {
@@ -363,10 +372,10 @@ restart:
 		if ((error = namei(ndp)) != 0)
 			return (error);
 		vp = ndp->ni_vp;
-		if ((fmode & O_NAMEDATTR) != 0 && (vp->v_mount->mnt_flag &
-		     MNT_NAMEDATTR) == 0) {
-			error = EINVAL;
-			goto bad;
+		if ((fmode & O_NAMEDATTR) != 0) {
+			error = vfs_check_namedattr(vp);
+			if (error != 0)
+				goto bad;
 		}
 	}
 	error = vn_open_vnode(vp, fmode, cred, curthread, fp);