diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 102ba18e561f..673622c47804 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -135,18 +135,30 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si secno a; struct extended_attribute *ea; struct extended_attribute *ea_end = fnode_end_ea(fnode); - for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) - if (!strcmp(ea->name, key)) { - if (ea_indirect(ea)) - return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); - if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { - pr_err("out of memory for EA\n"); - return NULL; + for (ea = fnode_ea(fnode); + (void *)ea + sizeof(*ea) <= (void *)fnode + fnode->ea_off + fnode->ea_size; + ea = (void *)ea + ((sizeof(*ea) + ea->name_len + 3) & ~3)) { + + /* Add this extra safety check inside the loop before using ea->name_len */ + if ((void *)ea + sizeof(*ea) > (void *)fnode + fnode->ea_off + fnode->ea_size) + break; + + int len = ea->name_len; + int entry_size = sizeof(*ea) + ((len + 3) & ~3); + + if ((void *)ea + entry_size > (void *)fnode + fnode->ea_off + fnode->ea_size) + break; + + if (ea->name_len == aname->len && !memcmp(ea->name, aname->name, len)) { + if (ea->type & 0x80) { + *buffer = kmalloc(ea->size, GFP_KERNEL); + if (!*buffer) + return -ENOMEM; + memcpy(*buffer, (char *)ea + entry_size, ea->size); } - memcpy(ret, ea_data(ea), ea_valuelen(ea)); - ret[ea_valuelen(ea)] = 0; - return ret; + return ea->size; } + } a = le32_to_cpu(fnode->ea_secno); len = le32_to_cpu(fnode->ea_size_l); ano = fnode_in_anode(fnode);