@@ -1530,12 +1530,23 @@ xfs_attr_node_get(
return error;
}
+/* Enforce that there is at most one namespace bit per attr. */
+inline bool xfs_attr_check_namespace(unsigned int attr_flags)
+{
+ return hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) < 2;
+}
+
/* Returns true if the attribute entry name is valid. */
bool
xfs_attr_namecheck(
+ unsigned int attr_flags,
const void *name,
size_t length)
{
+ /* Only one namespace bit allowed. */
+ if (!xfs_attr_check_namespace(attr_flags))
+ return false;
+
/*
* MAXNAMELEN includes the trailing null, but (name/length) leave it
* out, so use >= for the length check.
@@ -560,7 +560,9 @@ enum xfs_attr_update {
int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op);
int xfs_attr_set_iter(struct xfs_attr_intent *attr);
int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
-bool xfs_attr_namecheck(const void *name, size_t length);
+bool xfs_attr_check_namespace(unsigned int attr_flags);
+bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
+ size_t length);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
unsigned int *total);
@@ -947,6 +947,11 @@ xfs_attr_shortform_to_leaf(
nargs.hashval = xfs_da_hashname(sfe->nameval,
sfe->namelen);
nargs.attr_filter = sfe->flags & XFS_ATTR_NSP_ONDISK_MASK;
+ if (!xfs_attr_check_namespace(sfe->flags)) {
+ xfs_da_mark_sick(args);
+ error = -EFSCORRUPTED;
+ goto out;
+ }
error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */
ASSERT(error == -ENOATTR);
error = xfs_attr3_leaf_add(bp, &nargs);
@@ -1060,7 +1065,7 @@ xfs_attr_shortform_verify(
* one namespace flag per xattr, so we can just count the
* bits (i.e. hweight) here.
*/
- if (hweight8(sfep->flags & XFS_ATTR_NSP_ONDISK_MASK) > 1)
+ if (!xfs_attr_check_namespace(sfep->flags))
return __this_address;
sfep = next_sfep;
@@ -292,7 +292,8 @@ process_shortform_attr(
}
/* namecheck checks for null chars in attr names. */
- if (!libxfs_attr_namecheck(currententry->nameval,
+ if (!libxfs_attr_namecheck(currententry->flags,
+ currententry->nameval,
currententry->namelen)) {
do_warn(
_("entry contains illegal character in shortform attribute name\n"));
@@ -473,7 +474,7 @@ process_leaf_attr_local(
local = xfs_attr3_leaf_name_local(leaf, i);
if (local->namelen == 0 ||
- !libxfs_attr_namecheck(local->nameval,
+ !libxfs_attr_namecheck(entry->flags, local->nameval,
local->namelen)) {
do_warn(
_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
@@ -529,7 +530,7 @@ process_leaf_attr_remote(
remotep = xfs_attr3_leaf_name_remote(leaf, i);
if (remotep->namelen == 0 ||
- !libxfs_attr_namecheck(remotep->name,
+ !libxfs_attr_namecheck(entry->flags, remotep->name,
remotep->namelen) ||
be32_to_cpu(entry->hashval) !=
libxfs_da_hashname((unsigned char *)&remotep->name[0],