Page MenuHomeFreeBSD

D49654.id153667.diff
No OneTemporary

D49654.id153667.diff

diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h.xattr b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h
--- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h.xattr
+++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h
@@ -227,6 +227,7 @@
#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */
#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */
#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
+#define LOOKUP_NAMED_ATTR 0x10 /* Lookup a named attribute */
/*
* Public vnode manipulation functions.
diff --git a/sys/contrib/openzfs/include/sys/xvattr.h.xattr b/sys/contrib/openzfs/include/sys/xvattr.h
--- a/sys/contrib/openzfs/include/sys/xvattr.h.xattr
+++ b/sys/contrib/openzfs/include/sys/xvattr.h
@@ -311,6 +311,7 @@
*/
#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
#define V_APPEND 0x2 /* want to do append only check */
+#define V_NAMEDATTR 0x4 /* is a named attribute check */
/*
* Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
@@ -2357,10 +2357,42 @@
* In FreeBSD, we don't care about permissions of individual ADS.
* Note that not checking them is not just an optimization - without
* this shortcut, EA operations may bogusly fail with EACCES.
+ *
+ * If this is a named attribute lookup, do the checks.
*/
- if (zp->z_pflags & ZFS_XATTR)
+ if ((zp->z_pflags & ZFS_XATTR)
+#ifdef VIRF_NAMEDATTR
+ && (flags & V_NAMEDATTR) == 0
+#endif
+ )
return (0);
+
+ /*
+ * If a named attribute directory then validate against base file
+ */
+ if (is_attr) {
+ if ((error = zfs_zget(ZTOZSB(zp),
+ zp->z_xattr_parent, &xzp)) != 0) {
+ return (error);
+ }
+
+ check_zp = xzp;
+
+ /*
+ * fixup mode to map to xattr perms
+ */
+
+ if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
+ mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
+ mode |= ACE_WRITE_NAMED_ATTRS;
+ }
+ if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
+ mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
+ mode |= ACE_READ_NAMED_ATTRS;
+ }
+ }
+
owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
/*
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
@@ -1174,6 +1174,8 @@
zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
}
+
+extern int zfs_xattr_compat;
static int
zfs_domount(vfs_t *vfsp, char *osname)
@@ -1255,6 +1257,16 @@
goto out;
}
+#ifdef VIRF_NAMEDATTR
+ /*
+ * Named attributes can only work if the xattr property is set to
+ * on/dir and not sa. Also, zfs_xattr_compat must be set.
+ */
+ if ((zfsvfs->z_flags & ZSB_XATTR) != 0 && !zfsvfs->z_xattr_sa &&
+ zfs_xattr_compat)
+ vfsp->mnt_flag |= MNT_NAMEDATTR;
+#endif
+
vfs_mountedfrom(vfsp, osname);
if (!zfsvfs->z_issnap)
@@ -1778,6 +1790,14 @@
err = vn_lock(*vpp, flags);
if (err != 0)
vrele(*vpp);
+#ifdef VIRF_NAMEDATTR
+ else if ((zp->z_pflags & ZFS_XATTR) != 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+#endif
}
if (err != 0)
*vpp = NULL;
@@ -1930,9 +1950,17 @@
*vpp = ZTOV(zp);
zfs_exit(zfsvfs, FTAG);
err = vn_lock(*vpp, flags);
- if (err == 0)
+ if (err == 0) {
vnode_create_vobject(*vpp, zp->z_size, curthread);
- else
+#ifdef VIRF_NAMEDATTR
+ if ((zp->z_pflags & ZFS_XATTR) != 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+#endif
+ } else
*vpp = NULL;
return (err);
}
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -717,7 +717,12 @@
/*
* Do we have permission to get into attribute directory?
*/
- error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr, NULL);
+ if (flags & LOOKUP_NAMED_ATTR)
+ error = zfs_zaccess(zp, ACE_EXECUTE, V_NAMEDATTR,
+ B_FALSE, cr, NULL);
+ else
+ error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr,
+ NULL);
if (error) {
vrele(ZTOV(zp));
}
@@ -4480,8 +4485,16 @@
* ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
*/
accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
- if (accmode != 0)
- error = zfs_access(zp, accmode, 0, ap->a_cred);
+ if (accmode != 0) {
+#ifdef VIRF_NAMEDATTR
+ /* For named attributes, do the checks. */
+ if ((vn_irflag_read(vp) & VIRF_NAMEDATTR) != 0)
+ error = zfs_access(zp, accmode, V_NAMEDATTR,
+ ap->a_cred);
+ else
+#endif
+ error = zfs_access(zp, accmode, 0, ap->a_cred);
+ }
/*
* VADMIN has to be handled by vaccess().
@@ -4513,7 +4526,89 @@
struct componentname *a_cnp;
};
#endif
+
+#ifdef VIRF_NAMEDATTR
+static int
+zfs_freebsd_lookup(struct vop_lookup_args *ap, boolean_t cached)
+{
+ struct componentname *cnp = ap->a_cnp;
+ char nm[NAME_MAX + 1];
+ int error;
+ struct vnode **vpp = ap->a_vpp, *dvp = ap->a_dvp;
+ struct vnode *xvp;
+ bool is_nameddir, needs_nameddir, opennamed = false;
+
+ /*
+ * These variables are used to handle the named attribute cases:
+ * opennamed - Is true when this is a call from open with O_NAMEDATTR
+ * specified and it is the last component.
+ * is_nameddir - Is true when the directory is a named attribute dir.
+ * needs_nameddir - Is set when the lookup needs to look for/create
+ * a named attribute directory. It is only set when is_nameddir
+ * is_nameddir is false and opennamed is true.
+ * xvp - Is the directory that the lookup needs to be done in.
+ * Usually dvp, unless needs_nameddir is true where it is the
+ * result of the first non-named directory lookup.
+ * Note that name caching must be disabled for named attribute
+ * handling.
+ */
+ needs_nameddir = false;
+ xvp = dvp;
+ opennamed = (cnp->cn_flags & (OPENNAMED | ISLASTCN)) ==
+ (OPENNAMED | ISLASTCN);
+ is_nameddir = (vn_irflag_read(dvp) & VIRF_NAMEDDIR) != 0;
+ if (is_nameddir && (cnp->cn_flags & ISLASTCN) == 0)
+ return (ENOATTR);
+ if (opennamed || is_nameddir)
+ cnp->cn_flags &= ~MAKEENTRY;
+ if (opennamed && !is_nameddir) {
+ vpp = &xvp;
+ needs_nameddir = true;
+ }
+ ASSERT3U(cnp->cn_namelen, <, sizeof (nm));
+ error = 0;
+ if (!needs_nameddir || cnp->cn_namelen != 1 ||
+ *cnp->cn_nameptr != '.') {
+ strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1,
+ sizeof (nm)));
+ error = zfs_lookup(dvp, nm, vpp, cnp, cnp->cn_nameiop,
+ cnp->cn_cred, 0, cached);
+ if (is_nameddir && error == 0 && (cnp->cn_namelen != 1 ||
+ *cnp->cn_nameptr != '.') &&
+ (cnp->cn_flags & ISDOTDOT) == 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+ } else {
+ /* Lookup of "." when a named attribute dir is needed. */
+ xvp = dvp;
+ }
+ if (needs_nameddir && error == 0) {
+ int flags;
+ flags = LOOKUP_XATTR | LOOKUP_NAMED_ATTR;
+ if ((cnp->cn_flags & CREATENAMED) != 0)
+ flags |= CREATE_XATTR_DIR;
+ error = zfs_lookup(xvp, NULL, ap->a_vpp, NULL, 0,
+ cnp->cn_cred, flags, B_FALSE);
+ if (error == 0) {
+ if ((cnp->cn_flags & LOCKLEAF) != 0)
+ error = vn_lock(*ap->a_vpp, cnp->cn_lkflags);
+ if (error == 0) {
+ vn_irflag_set_cond(*ap->a_vpp, VIRF_NAMEDDIR);
+ } else {
+ vrele(*ap->a_vpp);
+ *ap->a_vpp = NULL;
+ }
+ }
+ if (xvp != dvp)
+ vput(xvp);
+ }
+ return (error);
+}
+#else
static int
zfs_freebsd_lookup(struct vop_lookup_args *ap, boolean_t cached)
{
@@ -4526,6 +4621,7 @@
return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
cnp->cn_cred, 0, cached));
}
+#endif
static int
zfs_freebsd_cachedlookup(struct vop_cachedlookup_args *ap)
@@ -4548,12 +4644,28 @@
zfsvfs_t *zfsvfs;
zfsvfs = ap->a_dvp->v_mount->mnt_data;
- if (zfsvfs->z_use_namecache)
+ if (zfsvfs->z_use_namecache
+#ifdef VIRF_NAMEDATTR
+ && (ap->a_cnp->cn_flags & OPENNAMED) == 0
+#endif
+ )
return (vfs_cache_lookup(ap));
else
return (zfs_freebsd_lookup(ap, B_FALSE));
}
+static int
+zfs_check_attrname(const char *name)
+{
+ /* We don't allow '/' character in attribute name. */
+ if (strchr(name, '/') != NULL)
+ return (SET_ERROR(EINVAL));
+ /* We don't allow attribute names that start with a namespace prefix. */
+ if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
+ return (SET_ERROR(EINVAL));
+ return (0);
+}
+
#ifndef _SYS_SYSPROTO_H_
struct vop_create_args {
struct vnode *a_dvp;
@@ -4571,6 +4683,9 @@
vattr_t *vap = ap->a_vap;
znode_t *zp = NULL;
int rc, mode;
+#ifdef VIRF_NAMEDATTR
+ bool is_nameddir;
+#endif
#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
@@ -4581,10 +4696,23 @@
zfsvfs = ap->a_dvp->v_mount->mnt_data;
*ap->a_vpp = NULL;
- rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode,
- &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL);
+ rc = 0;
+#ifdef VIRF_NAMEDATTR
+ is_nameddir = (vn_irflag_read(ap->a_dvp) & VIRF_NAMEDDIR) != 0;
+ if (is_nameddir)
+ rc = zfs_check_attrname(cnp->cn_nameptr);
+#endif
+
if (rc == 0)
+ rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode,
+ &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL);
+ if (rc == 0) {
*ap->a_vpp = ZTOV(zp);
+#ifdef VIRF_NAMEDATTR
+ if (is_nameddir)
+ vn_irflag_set_cond(*ap->a_vpp, VIRF_NAMEDATTR);
+#endif
+ }
if (zfsvfs->z_use_namecache &&
rc == 0 && (cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
@@ -4603,13 +4731,21 @@
static int
zfs_freebsd_remove(struct vop_remove_args *ap)
{
+ int error = 0;
#if __FreeBSD_version < 1400068
ASSERT(ap->a_cnp->cn_flags & SAVENAME);
#endif
- return (zfs_remove_(ap->a_dvp, ap->a_vp, ap->a_cnp->cn_nameptr,
- ap->a_cnp->cn_cred));
+#ifdef VIRF_NAMEDATTR
+ if ((vn_irflag_read(ap->a_dvp) & VIRF_NAMEDDIR) != 0)
+ error = zfs_check_attrname(ap->a_cnp->cn_nameptr);
+#endif
+
+ if (error == 0)
+ error = zfs_remove_(ap->a_dvp, ap->a_vp, ap->a_cnp->cn_nameptr,
+ ap->a_cnp->cn_cred);
+ return (error);
}
#ifndef _SYS_SYSPROTO_H_
@@ -4767,6 +4903,11 @@
#undef FLAG_CHECK
*vap = xvap.xva_vattr;
vap->va_flags = fflags;
+
+#ifdef VIRF_NAMEDATTR
+ if ((vn_irflag_read(ap->a_vp) & (VIRF_NAMEDDIR | VIRF_NAMEDATTR)) != 0)
+ vap->va_bsdflags |= SFBSD_NAMEDATTR;
+#endif
return (0);
}
@@ -4909,15 +5050,24 @@
vnode_t *fvp = ap->a_fvp;
vnode_t *tdvp = ap->a_tdvp;
vnode_t *tvp = ap->a_tvp;
- int error;
+ int error = 0;
#if __FreeBSD_version < 1400068
ASSERT(ap->a_fcnp->cn_flags & (SAVENAME|SAVESTART));
ASSERT(ap->a_tcnp->cn_flags & (SAVENAME|SAVESTART));
#endif
- error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
- ap->a_tcnp, ap->a_fcnp->cn_cred);
+#ifdef VIRF_NAMEDATTR
+ if ((vn_irflag_read(fdvp) & VIRF_NAMEDDIR) != 0) {
+ error = zfs_check_attrname(ap->a_fcnp->cn_nameptr);
+ if (error == 0)
+ error = zfs_check_attrname(ap->a_tcnp->cn_nameptr);
+ }
+#endif
+
+ if (error == 0)
+ error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
+ ap->a_tcnp, ap->a_fcnp->cn_cred);
vrele(fdvp);
vrele(fvp);
@@ -5171,24 +5321,22 @@
return (0);
}
return (EINVAL);
+#ifdef VIRF_NAMEDATTR
+ case _PC_NAMEDATTR_ENABLED:
+ MNT_ILOCK(ap->a_vp->v_mount);
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NAMEDATTR) != 0)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ MNT_IUNLOCK(ap->a_vp->v_mount);
+ return (0);
+#endif
default:
return (vop_stdpathconf(ap));
}
}
-
-static int zfs_xattr_compat = 1;
-static int
-zfs_check_attrname(const char *name)
-{
- /* We don't allow '/' character in attribute name. */
- if (strchr(name, '/') != NULL)
- return (SET_ERROR(EINVAL));
- /* We don't allow attribute names that start with a namespace prefix. */
- if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
- return (SET_ERROR(EINVAL));
- return (0);
-}
+int zfs_xattr_compat = 1;
/*
* FreeBSD's extended attributes namespace defines file name prefix for ZFS'

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 16, 7:15 AM (21 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27659254
Default Alt Text
D49654.id153667.diff (12 KB)

Event Timeline