@@ -450,7 +450,9 @@ ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
450450 struct ntfs_inode * ni = NTFS_I (inode );
451451 const struct ea_attr * p_ea ;
452452 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 ;
454456 u32 ea_info_qsize ;
455457 char * ea_buf = NULL ;
456458 ssize_t ret = 0 ;
@@ -471,43 +473,45 @@ ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
471473 if (!ea_buf )
472474 goto out ;
473475
474- if (ea_info_qsize > ea_buf_size )
476+ if (ea_info_qsize > ea_buf_size || ea_info_qsize == 0 )
475477 goto out ;
476478
477- if (ea_buf_size < sizeof (struct ea_attr ))
479+ if (ea_info_qsize < sizeof (struct ea_attr )) {
480+ err = - EIO ;
478481 goto out ;
482+ }
479483
480484 offset = 0 ;
481485 do {
482486 p_ea = (const struct ea_attr * )& ea_buf [offset ];
483487 next = le32_to_cpu (p_ea -> next_entry_offset );
484- if (next )
485- ea_size = next ;
486- else
487- ea_size = ALIGN (struct_size (p_ea , ea_name ,
488- 1 + p_ea -> ea_name_length +
489- le16_to_cpu (p_ea -> ea_value_length )),
490- 4 );
491- if (buffer ) {
492- if (offset + ea_size > ea_info_qsize )
493- break ;
488+ ea_size = next ? next : (ea_info_qsize - offset );
489+
490+ if (ea_size < sizeof (struct ea_attr ) ||
491+ offset + ea_size > ea_info_qsize ) {
492+ err = - EIO ;
493+ goto out ;
494+ }
494495
496+ if ((int )p_ea -> ea_name_length + 1 >
497+ ea_size - offsetof(struct ea_attr , ea_name )) {
498+ err = - EIO ;
499+ goto out ;
500+ }
501+
502+ if (buffer ) {
495503 if (ret + p_ea -> ea_name_length + 1 > size ) {
496504 err = - ERANGE ;
497505 goto out ;
498506 }
499507
500- if (p_ea -> ea_name_length + 1 > (ea_info_qsize - offset ))
501- break ;
502-
503508 memcpy (buffer + ret , p_ea -> ea_name , p_ea -> ea_name_length );
504509 buffer [ret + p_ea -> ea_name_length ] = 0 ;
505510 }
506511
507512 ret += p_ea -> ea_name_length + 1 ;
508513 offset += ea_size ;
509- } while (next > 0 && offset < ea_info_qsize &&
510- sizeof (struct ea_attr ) < (ea_info_qsize - offset ));
514+ } while (next > 0 && offset < ea_info_qsize );
511515
512516out :
513517 mutex_unlock (& NTFS_I (inode )-> mrec_lock );
0 commit comments