@@ -1510,9 +1510,33 @@ xfs_attr_node_get(
return error;
}
-/* Returns true if the attribute entry name is valid. */
-bool
-xfs_attr_namecheck(
+/*
+ * Verify parent pointer attribute is valid.
+ * Return true on success or false on failure
+ */
+STATIC bool
+xfs_verify_pptr(
+ struct xfs_mount *mp,
+ const struct xfs_parent_name_rec *rec)
+{
+ xfs_ino_t p_ino;
+ xfs_dir2_dataptr_t p_diroffset;
+
+ p_ino = be64_to_cpu(rec->p_ino);
+ p_diroffset = be32_to_cpu(rec->p_diroffset);
+
+ if (!xfs_verify_ino(mp, p_ino))
+ return false;
+
+ if (p_diroffset > XFS_DIR2_MAX_DATAPTR)
+ return false;
+
+ return true;
+}
+
+/* Returns true if the string attribute entry name is valid. */
+static bool
+xfs_str_attr_namecheck(
const void *name,
size_t length)
{
@@ -1527,6 +1551,23 @@ xfs_attr_namecheck(
return !memchr(name, 0, length);
}
+/* Returns true if the attribute entry name is valid. */
+bool
+xfs_attr_namecheck(
+ struct xfs_mount *mp,
+ const void *name,
+ size_t length,
+ int flags)
+{
+ if (flags & XFS_ATTR_PARENT) {
+ if (length != sizeof(struct xfs_parent_name_rec))
+ return false;
+ return xfs_verify_pptr(mp, (struct xfs_parent_name_rec *)name);
+ }
+
+ return xfs_str_attr_namecheck(name, length);
+}
+
int __init
xfs_attr_intent_init_cache(void)
{
@@ -547,7 +547,8 @@ int xfs_attr_get(struct xfs_da_args *args);
int xfs_attr_set(struct xfs_da_args *args);
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_namecheck(struct xfs_mount *mp, const void *name, size_t length,
+ int flags);
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);
@@ -757,6 +757,14 @@ xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
}
+static inline int
+xfs_attr3_leaf_flags(xfs_attr_leafblock_t *leafp, int idx)
+{
+ struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
+
+ return entries[idx].flags;
+}
+
static inline xfs_attr_leaf_name_remote_t *
xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
{
@@ -292,8 +292,9 @@ process_shortform_attr(
}
/* namecheck checks for null chars in attr names. */
- if (!libxfs_attr_namecheck(currententry->nameval,
- currententry->namelen)) {
+ if (!libxfs_attr_namecheck(mp, currententry->nameval,
+ currententry->namelen,
+ currententry->flags)) {
do_warn(
_("entry contains illegal character in shortform attribute name\n"));
junkit = 1;
@@ -469,12 +470,14 @@ process_leaf_attr_local(
xfs_dablk_t da_bno,
xfs_ino_t ino)
{
- xfs_attr_leaf_name_local_t *local;
+ xfs_attr_leaf_name_local_t *local;
+ int flags;
local = xfs_attr3_leaf_name_local(leaf, i);
+ flags = xfs_attr3_leaf_flags(leaf, i);
if (local->namelen == 0 ||
- !libxfs_attr_namecheck(local->nameval,
- local->namelen)) {
+ !libxfs_attr_namecheck(mp, local->nameval,
+ local->namelen, flags)) {
do_warn(
_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
i, da_bno, ino, local->namelen);
@@ -525,12 +528,14 @@ process_leaf_attr_remote(
{
xfs_attr_leaf_name_remote_t *remotep;
char* value;
+ int flags;
remotep = xfs_attr3_leaf_name_remote(leaf, i);
+ flags = xfs_attr3_leaf_flags(leaf, i);
if (remotep->namelen == 0 ||
- !libxfs_attr_namecheck(remotep->name,
- remotep->namelen) ||
+ !libxfs_attr_namecheck(mp, remotep->name,
+ remotep->namelen, flags) ||
be32_to_cpu(entry->hashval) !=
libxfs_da_hashname((unsigned char *)&remotep->name[0],
remotep->namelen) ||