|
@@ -364,22 +364,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
|
|
|
/*
|
|
|
* Check if the attribute is in a supported namespace.
|
|
|
*
|
|
|
- * This applied after the check for the synthetic attributes in the system
|
|
|
+ * This is applied after the check for the synthetic attributes in the system
|
|
|
* namespace.
|
|
|
*/
|
|
|
-static bool btrfs_is_valid_xattr(const char *name)
|
|
|
+static int btrfs_is_valid_xattr(const char *name)
|
|
|
{
|
|
|
- return !strncmp(name, XATTR_SECURITY_PREFIX,
|
|
|
- XATTR_SECURITY_PREFIX_LEN) ||
|
|
|
- !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
|
|
|
- !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
|
|
|
- !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
|
|
|
- !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
|
|
|
+ int len = strlen(name);
|
|
|
+ int prefixlen = 0;
|
|
|
+
|
|
|
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
|
|
+ XATTR_SECURITY_PREFIX_LEN))
|
|
|
+ prefixlen = XATTR_SECURITY_PREFIX_LEN;
|
|
|
+ else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
|
+ prefixlen = XATTR_SYSTEM_PREFIX_LEN;
|
|
|
+ else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
|
|
|
+ prefixlen = XATTR_TRUSTED_PREFIX_LEN;
|
|
|
+ else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
|
|
|
+ prefixlen = XATTR_USER_PREFIX_LEN;
|
|
|
+ else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
|
+ prefixlen = XATTR_BTRFS_PREFIX_LEN;
|
|
|
+ else
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The name cannot consist of just prefix
|
|
|
+ */
|
|
|
+ if (len <= prefixlen)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
|
|
void *buffer, size_t size)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
/*
|
|
|
* If this is a request for a synthetic attribute in the system.*
|
|
|
* namespace use the generic infrastructure to resolve a handler
|
|
@@ -388,8 +408,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
|
|
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
|
return generic_getxattr(dentry, name, buffer, size);
|
|
|
|
|
|
- if (!btrfs_is_valid_xattr(name))
|
|
|
- return -EOPNOTSUPP;
|
|
|
+ ret = btrfs_is_valid_xattr(name);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
|
|
|
}
|
|
|
|
|
@@ -397,6 +418,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
|
|
size_t size, int flags)
|
|
|
{
|
|
|
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
|
|
|
+ int ret;
|
|
|
|
|
|
/*
|
|
|
* The permission on security.* and system.* is not checked
|
|
@@ -413,8 +435,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
|
|
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
|
return generic_setxattr(dentry, name, value, size, flags);
|
|
|
|
|
|
- if (!btrfs_is_valid_xattr(name))
|
|
|
- return -EOPNOTSUPP;
|
|
|
+ ret = btrfs_is_valid_xattr(name);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
|
return btrfs_set_prop(dentry->d_inode, name,
|
|
@@ -430,6 +453,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
|
|
int btrfs_removexattr(struct dentry *dentry, const char *name)
|
|
|
{
|
|
|
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
|
|
|
+ int ret;
|
|
|
|
|
|
/*
|
|
|
* The permission on security.* and system.* is not checked
|
|
@@ -446,8 +470,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
|
|
|
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
|
|
return generic_removexattr(dentry, name);
|
|
|
|
|
|
- if (!btrfs_is_valid_xattr(name))
|
|
|
- return -EOPNOTSUPP;
|
|
|
+ ret = btrfs_is_valid_xattr(name);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
|
|
return btrfs_set_prop(dentry->d_inode, name,
|