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_listxattr against EA entries

Validate every EA entry only if the buffer length is required to prevent
large memory allocation.

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
e6a95c5a c451d34a

+22 -18
+22 -18
fs/ntfs/ea.c
··· 450 450 struct ntfs_inode *ni = NTFS_I(inode); 451 451 const struct ea_attr *p_ea; 452 452 s64 offset, ea_buf_size, ea_info_size; 453 - int next, err = 0, ea_size; 453 + s64 ea_size; 454 + u32 next; 455 + int err = 0; 454 456 u32 ea_info_qsize; 455 457 char *ea_buf = NULL; 456 458 ssize_t ret = 0; ··· 473 471 if (!ea_buf) 474 472 goto out; 475 473 476 - if (ea_info_qsize > ea_buf_size) 474 + if (ea_info_qsize > ea_buf_size || ea_info_qsize == 0) 477 475 goto out; 478 476 479 - if (ea_buf_size < sizeof(struct ea_attr)) 477 + if (ea_info_qsize < sizeof(struct ea_attr)) { 478 + err = -EIO; 480 479 goto out; 480 + } 481 481 482 482 offset = 0; 483 483 do { 484 484 p_ea = (const struct ea_attr *)&ea_buf[offset]; 485 485 next = le32_to_cpu(p_ea->next_entry_offset); 486 - if (next) 487 - ea_size = next; 488 - else 489 - ea_size = ALIGN(struct_size(p_ea, ea_name, 490 - 1 + p_ea->ea_name_length + 491 - le16_to_cpu(p_ea->ea_value_length)), 492 - 4); 493 - if (buffer) { 494 - if (offset + ea_size > ea_info_qsize) 495 - break; 486 + ea_size = next ? next : (ea_info_qsize - offset); 496 487 488 + if (ea_size < sizeof(struct ea_attr) || 489 + offset + ea_size > ea_info_qsize) { 490 + err = -EIO; 491 + goto out; 492 + } 493 + 494 + if ((int)p_ea->ea_name_length + 1 > 495 + ea_size - offsetof(struct ea_attr, ea_name)) { 496 + err = -EIO; 497 + goto out; 498 + } 499 + 500 + if (buffer) { 497 501 if (ret + p_ea->ea_name_length + 1 > size) { 498 502 err = -ERANGE; 499 503 goto out; 500 504 } 501 - 502 - if (p_ea->ea_name_length + 1 > (ea_info_qsize - offset)) 503 - break; 504 505 505 506 memcpy(buffer + ret, p_ea->ea_name, p_ea->ea_name_length); 506 507 buffer[ret + p_ea->ea_name_length] = 0; ··· 511 506 512 507 ret += p_ea->ea_name_length + 1; 513 508 offset += ea_size; 514 - } while (next > 0 && offset < ea_info_qsize && 515 - sizeof(struct ea_attr) < (ea_info_qsize - offset)); 509 + } while (next > 0 && offset < ea_info_qsize); 516 510 517 511 out: 518 512 mutex_unlock(&NTFS_I(inode)->mrec_lock);