Skip to content

Commit

Permalink
Check for forbidden xattr namespace prefixes
Browse files Browse the repository at this point in the history
FreeBSD has a "freebsd:" namespace prefix. Linux has "security.",
"system.", "trusted.", and "user." namespaces in ZFS.  We are trying
to get away from the user namespace prefix for compatibility with
other platforms.  If a user xattr is created with a name prefixed
with one of the namespace prefixes, it will end up in that namespace
instead of the user namespace.

Do not allow setting or getting xattrs with a name that is prefixed
with one of the namespace names used by ZFS on supported platforms.

Signed-off-by: Ryan Moeller <[email protected]>
  • Loading branch information
Ryan Moeller authored and Ryan Moeller committed Apr 14, 2021
1 parent d39ca5b commit 5069856
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
28 changes: 28 additions & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,34 @@ typedef enum {
#define ZFS_EV_HIST_DSID "history_dsid"
#define ZFS_EV_RESILVER_TYPE "resilver_type"

/*
* xattr namespace prefixes. These are forbidden in xattr names.
*
* For cross-platform compatibility, xattrs in the user namespace should not be
* prefixed with the namespace name, but for backwards compatibility with older
* ZFS on Linux versions we do prefix the namespace.
*/
#define ZFS_XA_NS_FREEBSD_PREFIX "freebsd:"
#define ZFS_XA_NS_FREEBSD_PREFIX_LEN strlen("freebsd:")
#define ZFS_XA_NS_LINUX_SECURITY_PREFIX "security."
#define ZFS_XA_NS_LINUX_SECURITY_PREFIX_LEN strlen("security.")
#define ZFS_XA_NS_LINUX_SYSTEM_PREFIX "system."
#define ZFS_XA_NS_LINUX_SYSTEM_PREFIX_LEN strlen("system.")
#define ZFS_XA_NS_LINUX_TRUSTED_PREFIX "trusted."
#define ZFS_XA_NS_LINUX_TRUSTED_PREFIX_LEN strlen("trusted.")
#define ZFS_XA_NS_LINUX_USER_PREFIX "user."
#define ZFS_XA_NS_LINUX_USER_PREFIX_LEN strlen("user.")

#define ZFS_XA_NS_PREFIX_MATCH(ns, name) \
(strncmp(name, ZFS_XA_NS_##ns##_PREFIX, ZFS_XA_NS_##ns##_PREFIX_LEN) == 0)

#define ZFS_XA_NS_PREFIX_FORBIDDEN(name) \
(ZFS_XA_NS_PREFIX_MATCH(FREEBSD, name) || \
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))

#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 3 additions & 3 deletions module/os/freebsd/zfs/zfs_vnops_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -5163,8 +5163,8 @@ zfs_create_attrname(int attrnamespace, const char *name, char *attrname,
/* We don't allow '/' character in attribute name. */
if (strchr(name, '/') != NULL)
return (EINVAL);
/* We don't allow attribute names that start with "freebsd:" string. */
if (strncmp(name, "freebsd:", 8) == 0)
/* We don't allow attribute names that start with a namespace prefix. */
if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
return (EINVAL);

bzero(attrname, size);
Expand Down Expand Up @@ -5531,7 +5531,7 @@ zfs_listextattr(struct vop_listextattr_args *ap)
if (dp->d_type != DT_REG && dp->d_type != DT_UNKNOWN)
continue;
if (plen == 0 &&
strncmp(dp->d_name, "freebsd:", 8) == 0)
ZFS_XA_NS_PREFIX_FORBIDDEN(dp->d_name))
continue;
else if (strncmp(dp->d_name, attrprefix, plen) != 0)
continue;
Expand Down
6 changes: 5 additions & 1 deletion module/os/linux/zfs/zpl_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,8 @@ __zpl_xattr_user_get(struct inode *ip, const char *name,
if (strcmp(name, "") == 0)
return (-EINVAL);
#endif
if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
return (-EINVAL);
if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
return (-EOPNOTSUPP);

Expand Down Expand Up @@ -767,6 +769,8 @@ __zpl_xattr_user_set(struct inode *ip, const char *name,
if (strcmp(name, "") == 0)
return (-EINVAL);
#endif
if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
return (-EINVAL);
if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
return (-EOPNOTSUPP);

Expand Down Expand Up @@ -1431,7 +1435,7 @@ zpl_xattr_handler(const char *name, boolean_t *compat)
#endif /* CONFIG_FS_POSIX_ACL */

/* Do not expose FreeBSD system namespace xattrs. */
if (strncmp(name, "freebsd:system:", sizeof ("freebsd:system")) == 0)
if (ZFS_XA_NS_PREFIX_MATCH(FREEBSD, name))
return (NULL);

/*
Expand Down

0 comments on commit 5069856

Please sign in to comment.