diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 1676020d04d3..c88774239946 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -1954,7 +1954,8 @@ enum zio_encrypt { ZFS_XA_NS_PREFIX_MATCH(LINUX_SECURITY, name) || \ ZFS_XA_NS_PREFIX_MATCH(LINUX_SYSTEM, name) || \ ZFS_XA_NS_PREFIX_MATCH(LINUX_TRUSTED, name) || \ - ZFS_XA_NS_PREFIX_MATCH(LINUX_USER, name)) + (ZFS_XA_NS_PREFIX_MATCH(LINUX_USER, name) && \ + zfs_xattr_compat)) #ifdef __cplusplus } diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c index d5547c0a9392..ac530bf37315 100644 --- a/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/module/os/freebsd/zfs/zfs_vnops_os.c @@ -5189,6 +5189,27 @@ zfs_check_attrname(const char *name) return (0); } +static char * +zfs_attrname_maybe_rename(char *name) +{ + char *ret; + + if (zfs_xattr_compat) + return (name); + + if (ZFS_XA_NS_PREFIX_FORBIDDEN(name)) { + ret = kmem_alloc(strlen(name) + 6, KM_SLEEP); + snprintf(ret, strlen(name), "user.%s", name); + } +} + +static void +zfs_attrname_maybe_free(char *name, char *orig) +{ + if (name != orig) + kmem_free(name, strlen(name)); +} + /* * FreeBSD's extended attributes namespace defines file name prefix for ZFS' * extended attribute name: @@ -5373,6 +5394,7 @@ zfs_getextattr_impl(struct vop_getextattr_args *ap, boolean_t compat) static int zfs_getextattr(struct vop_getextattr_args *ap) { + char *origname = ap->a_name; znode_t *zp = VTOZ(ap->a_vp); zfsvfs_t *zfsvfs = ZTOZSB(zp); int error; @@ -5388,12 +5410,17 @@ zfs_getextattr(struct vop_getextattr_args *ap) if (error != 0) return (SET_ERROR(error)); + ap->a_name = zfs_attrname_maybe_rename(origname); error = zfs_check_attrname(ap->a_name); - if (error != 0) + if (error != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); + } - if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) + if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); + } error = ENOENT; rw_enter(&zp->z_xattr_lock, RW_READER); @@ -5411,6 +5438,7 @@ zfs_getextattr(struct vop_getextattr_args *ap) zfs_exit(zfsvfs, FTAG); if (error == ENOENT) error = SET_ERROR(ENOATTR); + zfs_attrname_maybe_free(ap->a_name, origname); return (error); } @@ -5514,6 +5542,7 @@ zfs_deleteextattr_impl(struct vop_deleteextattr_args *ap, boolean_t compat) static int zfs_deleteextattr(struct vop_deleteextattr_args *ap) { + char *origname = ap->a_name; znode_t *zp = VTOZ(ap->a_vp); zfsvfs_t *zfsvfs = ZTOZSB(zp); int error; @@ -5529,12 +5558,16 @@ zfs_deleteextattr(struct vop_deleteextattr_args *ap) if (error != 0) return (SET_ERROR(error)); + ap->a_name = zfs_attrname_maybe_rename(origname); error = zfs_check_attrname(ap->a_name); - if (error != 0) + if (error != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); - - if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) + } + if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); + } rw_enter(&zp->z_xattr_lock, RW_WRITER); error = zfs_deleteextattr_impl(ap, zfs_xattr_compat); @@ -5551,6 +5584,7 @@ zfs_deleteextattr(struct vop_deleteextattr_args *ap) zfs_exit(zfsvfs, FTAG); if (error == ENOENT) error = SET_ERROR(ENOATTR); + zfs_attrname_maybe_free(ap->a_name, origname); return (error); } @@ -5702,6 +5736,7 @@ zfs_setextattr_impl(struct vop_setextattr_args *ap, boolean_t compat) static int zfs_setextattr(struct vop_setextattr_args *ap) { + char *origname = ap->a_name; znode_t *zp = VTOZ(ap->a_vp); zfsvfs_t *zfsvfs = ZTOZSB(zp); int error; @@ -5717,18 +5752,24 @@ zfs_setextattr(struct vop_setextattr_args *ap) if (error != 0) return (SET_ERROR(error)); + ap->a_name = zfs_attrname_maybe_rename(origname); error = zfs_check_attrname(ap->a_name); - if (error != 0) + if (error != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); + } - if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) + if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) { + zfs_attrname_maybe_free(ap->a_name, origname); return (error); + } rw_enter(&zp->z_xattr_lock, RW_WRITER); error = zfs_setextattr_impl(ap, zfs_xattr_compat); rw_exit(&zp->z_xattr_lock); zfs_exit(zfsvfs, FTAG); + zfs_attrname_maybe_free(ap->a_name, origname); return (error); }