Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ntfs: harden ntfs_ea_lookup against malformed EA entries

Validate p_ea->ea_name_length tightly, and the used entry size
for every EA.

Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

authored by

Hyunchul Lee and committed by
Namjae Jeon
c451d34a 10993e52

+17 -19
+17 -19
fs/ntfs/ea.c
··· 46 46 } 47 47 48 48 static int ntfs_ea_lookup(char *ea_buf, s64 ea_buf_size, const char *name, 49 - int name_len, s64 *ea_offset, s64 *ea_size) 49 + int name_len, s64 *ea_offset, s64 *ea_size) 50 50 { 51 51 const struct ea_attr *p_ea; 52 - s64 offset; 52 + size_t actual_size; 53 + loff_t offset, p_ea_size; 53 54 unsigned int next; 54 55 55 56 if (ea_buf_size < sizeof(struct ea_attr)) ··· 60 59 do { 61 60 p_ea = (const struct ea_attr *)&ea_buf[offset]; 62 61 next = le32_to_cpu(p_ea->next_entry_offset); 62 + p_ea_size = next ? next : (ea_buf_size - offset); 63 63 64 - if (offset + next > ea_buf_size || 65 - ((1 + p_ea->ea_name_length) > (ea_buf_size - offset))) 64 + if (p_ea_size < sizeof(struct ea_attr) || 65 + offset + p_ea_size > ea_buf_size) 66 + break; 67 + 68 + if ((s64)p_ea->ea_name_length + 1 > 69 + p_ea_size - offsetof(struct ea_attr, ea_name)) 70 + break; 71 + 72 + actual_size = ALIGN(struct_size(p_ea, ea_name, 1 + p_ea->ea_name_length + 73 + le16_to_cpu(p_ea->ea_value_length)), 4); 74 + if (actual_size > p_ea_size) 66 75 break; 67 76 68 77 if (p_ea->ea_name_length == name_len && 69 78 !memcmp(p_ea->ea_name, name, name_len)) { 70 79 *ea_offset = offset; 71 - if (next) 72 - *ea_size = next; 73 - else { 74 - unsigned int ea_len = 1 + p_ea->ea_name_length + 75 - le16_to_cpu(p_ea->ea_value_length); 76 - 77 - if ((ea_buf_size - offset) < ea_len) 78 - goto out; 79 - 80 - *ea_size = ALIGN(struct_size(p_ea, ea_name, 81 - 1 + p_ea->ea_name_length + 82 - le16_to_cpu(p_ea->ea_value_length)), 4); 83 - } 80 + *ea_size = next ? next : actual_size; 84 81 85 82 if (ea_buf_size < *ea_offset + *ea_size) 86 83 goto out; ··· 86 87 return 0; 87 88 } 88 89 offset += next; 89 - } while (next > 0 && offset < ea_buf_size && 90 - sizeof(struct ea_attr) < (ea_buf_size - offset)); 90 + } while (next > 0 && offset < ea_buf_size); 91 91 92 92 out: 93 93 return -ENOENT;