@@ -763,7 +763,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
763763 struct cifs_fattr * fattr , bool mode_from_special_sid )
764764{
765765 int i ;
766- int num_aces = 0 ;
766+ u16 num_aces = 0 ;
767767 int acl_size ;
768768 char * acl_base ;
769769 struct smb_ace * * ppace ;
@@ -778,14 +778,15 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
778778 }
779779
780780 /* validate that we do not go past end of acl */
781- if (end_of_acl < (char * )pdacl + le16_to_cpu (pdacl -> size )) {
781+ if (end_of_acl < (char * )pdacl + sizeof (struct smb_acl ) ||
782+ end_of_acl < (char * )pdacl + le16_to_cpu (pdacl -> size )) {
782783 cifs_dbg (VFS , "ACL too small to parse DACL\n" );
783784 return ;
784785 }
785786
786787 cifs_dbg (NOISY , "DACL revision %d size %d num aces %d\n" ,
787788 le16_to_cpu (pdacl -> revision ), le16_to_cpu (pdacl -> size ),
788- le32_to_cpu (pdacl -> num_aces ));
789+ le16_to_cpu (pdacl -> num_aces ));
789790
790791 /* reset rwx permissions for user/group/other.
791792 Also, if num_aces is 0 i.e. DACL has no ACEs,
@@ -795,19 +796,38 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
795796 acl_base = (char * )pdacl ;
796797 acl_size = sizeof (struct smb_acl );
797798
798- num_aces = le32_to_cpu (pdacl -> num_aces );
799+ num_aces = le16_to_cpu (pdacl -> num_aces );
799800 if (num_aces > 0 ) {
800801 umode_t denied_mode = 0 ;
801802
802- if (num_aces > ULONG_MAX / sizeof (struct smb_ace * ))
803+ if (num_aces > (le16_to_cpu (pdacl -> size ) - sizeof (struct smb_acl )) /
804+ (offsetof(struct smb_ace , sid ) +
805+ offsetof(struct smb_sid , sub_auth ) + sizeof (__le16 )))
803806 return ;
807+
804808 ppace = kmalloc_array (num_aces , sizeof (struct smb_ace * ),
805809 GFP_KERNEL );
806810 if (!ppace )
807811 return ;
808812
809813 for (i = 0 ; i < num_aces ; ++ i ) {
814+ if (end_of_acl - acl_base < acl_size )
815+ break ;
816+
810817 ppace [i ] = (struct smb_ace * ) (acl_base + acl_size );
818+ acl_base = (char * )ppace [i ];
819+ acl_size = offsetof(struct smb_ace , sid ) +
820+ offsetof(struct smb_sid , sub_auth );
821+
822+ if (end_of_acl - acl_base < acl_size ||
823+ ppace [i ]-> sid .num_subauth == 0 ||
824+ ppace [i ]-> sid .num_subauth > SID_MAX_SUB_AUTHORITIES ||
825+ (end_of_acl - acl_base <
826+ acl_size + sizeof (__le32 ) * ppace [i ]-> sid .num_subauth ) ||
827+ (le16_to_cpu (ppace [i ]-> size ) <
828+ acl_size + sizeof (__le32 ) * ppace [i ]-> sid .num_subauth ))
829+ break ;
830+
811831#ifdef CONFIG_CIFS_DEBUG2
812832 dump_ace (ppace [i ], end_of_acl );
813833#endif
@@ -851,7 +871,6 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
851871 (void *)ppace[i],
852872 sizeof(struct smb_ace)); */
853873
854- acl_base = (char * )ppace [i ];
855874 acl_size = le16_to_cpu (ppace [i ]-> size );
856875 }
857876
@@ -937,12 +956,12 @@ unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace)
937956static void populate_new_aces (char * nacl_base ,
938957 struct smb_sid * pownersid ,
939958 struct smb_sid * pgrpsid ,
940- __u64 * pnmode , u32 * pnum_aces , u16 * pnsize ,
959+ __u64 * pnmode , u16 * pnum_aces , u16 * pnsize ,
941960 bool modefromsid ,
942961 bool posix )
943962{
944963 __u64 nmode ;
945- u32 num_aces = 0 ;
964+ u16 num_aces = 0 ;
946965 u16 nsize = 0 ;
947966 __u64 user_mode ;
948967 __u64 group_mode ;
@@ -1050,15 +1069,15 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p
10501069 u16 size = 0 ;
10511070 struct smb_ace * pntace = NULL ;
10521071 char * acl_base = NULL ;
1053- u32 src_num_aces = 0 ;
1072+ u16 src_num_aces = 0 ;
10541073 u16 nsize = 0 ;
10551074 struct smb_ace * pnntace = NULL ;
10561075 char * nacl_base = NULL ;
10571076 u16 ace_size = 0 ;
10581077
10591078 acl_base = (char * )pdacl ;
10601079 size = sizeof (struct smb_acl );
1061- src_num_aces = le32_to_cpu (pdacl -> num_aces );
1080+ src_num_aces = le16_to_cpu (pdacl -> num_aces );
10621081
10631082 nacl_base = (char * )pndacl ;
10641083 nsize = sizeof (struct smb_acl );
@@ -1090,11 +1109,11 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
10901109 u16 size = 0 ;
10911110 struct smb_ace * pntace = NULL ;
10921111 char * acl_base = NULL ;
1093- u32 src_num_aces = 0 ;
1112+ u16 src_num_aces = 0 ;
10941113 u16 nsize = 0 ;
10951114 struct smb_ace * pnntace = NULL ;
10961115 char * nacl_base = NULL ;
1097- u32 num_aces = 0 ;
1116+ u16 num_aces = 0 ;
10981117 bool new_aces_set = false;
10991118
11001119 /* Assuming that pndacl and pnmode are never NULL */
@@ -1112,7 +1131,7 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
11121131
11131132 acl_base = (char * )pdacl ;
11141133 size = sizeof (struct smb_acl );
1115- src_num_aces = le32_to_cpu (pdacl -> num_aces );
1134+ src_num_aces = le16_to_cpu (pdacl -> num_aces );
11161135
11171136 /* Retain old ACEs which we can retain */
11181137 for (i = 0 ; i < src_num_aces ; ++ i ) {
@@ -1158,7 +1177,7 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
11581177 }
11591178
11601179finalize_dacl :
1161- pndacl -> num_aces = cpu_to_le32 (num_aces );
1180+ pndacl -> num_aces = cpu_to_le16 (num_aces );
11621181 pndacl -> size = cpu_to_le16 (nsize );
11631182
11641183 return 0 ;
@@ -1293,7 +1312,7 @@ static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
12931312 dacloffset ? dacl_ptr -> revision : cpu_to_le16 (ACL_REVISION );
12941313
12951314 ndacl_ptr -> size = cpu_to_le16 (0 );
1296- ndacl_ptr -> num_aces = cpu_to_le32 (0 );
1315+ ndacl_ptr -> num_aces = cpu_to_le16 (0 );
12971316
12981317 rc = set_chmod_dacl (dacl_ptr , ndacl_ptr , owner_sid_ptr , group_sid_ptr ,
12991318 pnmode , mode_from_sid , posix );
@@ -1546,7 +1565,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
15461565 int rc = 0 ;
15471566 struct tcon_link * tlink = cifs_sb_tlink (cifs_sb );
15481567 struct smb_version_operations * ops ;
1549- const u32 info = 0 ;
1568+ const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO ;
15501569
15511570 cifs_dbg (NOISY , "converting ACL to mode for %s\n" , path );
15521571
@@ -1600,7 +1619,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
16001619 struct tcon_link * tlink ;
16011620 struct smb_version_operations * ops ;
16021621 bool mode_from_sid , id_from_sid ;
1603- const u32 info = 0 ;
1622+ const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO ;
16041623 bool posix ;
16051624
16061625 tlink = cifs_sb_tlink (cifs_sb );
@@ -1653,7 +1672,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
16531672 dacl_ptr = (struct smb_acl * )((char * )pntsd + dacloffset );
16541673 if (mode_from_sid )
16551674 nsecdesclen +=
1656- le32_to_cpu (dacl_ptr -> num_aces ) * sizeof (struct smb_ace );
1675+ le16_to_cpu (dacl_ptr -> num_aces ) * sizeof (struct smb_ace );
16571676 else /* cifsacl */
16581677 nsecdesclen += le16_to_cpu (dacl_ptr -> size );
16591678 }
0 commit comments