@@ -333,7 +333,7 @@ void posix_state_to_acl(struct posix_acl_state *state,
333333 pace -> e_perm = state -> other .allow ;
334334}
335335
336- int init_acl_state (struct posix_acl_state * state , int cnt )
336+ int init_acl_state (struct posix_acl_state * state , u16 cnt )
337337{
338338 int alloc ;
339339
@@ -368,7 +368,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
368368 struct smb_fattr * fattr )
369369{
370370 int i , ret ;
371- int num_aces = 0 ;
371+ u16 num_aces = 0 ;
372372 unsigned int acl_size ;
373373 char * acl_base ;
374374 struct smb_ace * * ppace ;
@@ -389,16 +389,18 @@ static void parse_dacl(struct mnt_idmap *idmap,
389389
390390 ksmbd_debug (SMB , "DACL revision %d size %d num aces %d\n" ,
391391 le16_to_cpu (pdacl -> revision ), le16_to_cpu (pdacl -> size ),
392- le32_to_cpu (pdacl -> num_aces ));
392+ le16_to_cpu (pdacl -> num_aces ));
393393
394394 acl_base = (char * )pdacl ;
395395 acl_size = sizeof (struct smb_acl );
396396
397- num_aces = le32_to_cpu (pdacl -> num_aces );
397+ num_aces = le16_to_cpu (pdacl -> num_aces );
398398 if (num_aces <= 0 )
399399 return ;
400400
401- if (num_aces > ULONG_MAX / sizeof (struct smb_ace * ))
401+ if (num_aces > (le16_to_cpu (pdacl -> size ) - sizeof (struct smb_acl )) /
402+ (offsetof(struct smb_ace , sid ) +
403+ offsetof(struct smb_sid , sub_auth ) + sizeof (__le16 )))
402404 return ;
403405
404406 ret = init_acl_state (& acl_state , num_aces );
@@ -432,6 +434,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
432434 offsetof(struct smb_sid , sub_auth );
433435
434436 if (end_of_acl - acl_base < acl_size ||
437+ ppace [i ]-> sid .num_subauth == 0 ||
435438 ppace [i ]-> sid .num_subauth > SID_MAX_SUB_AUTHORITIES ||
436439 (end_of_acl - acl_base <
437440 acl_size + sizeof (__le32 ) * ppace [i ]-> sid .num_subauth ) ||
@@ -580,7 +583,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
580583
581584static void set_posix_acl_entries_dacl (struct mnt_idmap * idmap ,
582585 struct smb_ace * pndace ,
583- struct smb_fattr * fattr , u32 * num_aces ,
586+ struct smb_fattr * fattr , u16 * num_aces ,
584587 u16 * size , u32 nt_aces_num )
585588{
586589 struct posix_acl_entry * pace ;
@@ -701,7 +704,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
701704 struct smb_fattr * fattr )
702705{
703706 struct smb_ace * ntace , * pndace ;
704- int nt_num_aces = le32_to_cpu (nt_dacl -> num_aces ), num_aces = 0 ;
707+ u16 nt_num_aces = le16_to_cpu (nt_dacl -> num_aces ), num_aces = 0 ;
705708 unsigned short size = 0 ;
706709 int i ;
707710
@@ -728,15 +731,15 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
728731
729732 set_posix_acl_entries_dacl (idmap , pndace , fattr ,
730733 & num_aces , & size , nt_num_aces );
731- pndacl -> num_aces = cpu_to_le32 (num_aces );
734+ pndacl -> num_aces = cpu_to_le16 (num_aces );
732735 pndacl -> size = cpu_to_le16 (le16_to_cpu (pndacl -> size ) + size );
733736}
734737
735738static void set_mode_dacl (struct mnt_idmap * idmap ,
736739 struct smb_acl * pndacl , struct smb_fattr * fattr )
737740{
738741 struct smb_ace * pace , * pndace ;
739- u32 num_aces = 0 ;
742+ u16 num_aces = 0 ;
740743 u16 size = 0 , ace_size = 0 ;
741744 uid_t uid ;
742745 const struct smb_sid * sid ;
@@ -792,7 +795,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap,
792795 fattr -> cf_mode , 0007 );
793796
794797out :
795- pndacl -> num_aces = cpu_to_le32 (num_aces );
798+ pndacl -> num_aces = cpu_to_le16 (num_aces );
796799 pndacl -> size = cpu_to_le16 (le16_to_cpu (pndacl -> size ) + size );
797800}
798801
@@ -807,6 +810,13 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl)
807810 return - EINVAL ;
808811 }
809812
813+ if (!psid -> num_subauth )
814+ return 0 ;
815+
816+ if (psid -> num_subauth > SID_MAX_SUB_AUTHORITIES ||
817+ end_of_acl < (char * )psid + 8 + sizeof (__le32 ) * psid -> num_subauth )
818+ return - EINVAL ;
819+
810820 return 0 ;
811821}
812822
@@ -848,6 +858,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
848858 pntsd -> type = cpu_to_le16 (DACL_PRESENT );
849859
850860 if (pntsd -> osidoffset ) {
861+ if (le32_to_cpu (pntsd -> osidoffset ) < sizeof (struct smb_ntsd ))
862+ return - EINVAL ;
863+
851864 rc = parse_sid (owner_sid_ptr , end_of_acl );
852865 if (rc ) {
853866 pr_err ("%s: Error %d parsing Owner SID\n" , __func__ , rc );
@@ -863,6 +876,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
863876 }
864877
865878 if (pntsd -> gsidoffset ) {
879+ if (le32_to_cpu (pntsd -> gsidoffset ) < sizeof (struct smb_ntsd ))
880+ return - EINVAL ;
881+
866882 rc = parse_sid (group_sid_ptr , end_of_acl );
867883 if (rc ) {
868884 pr_err ("%s: Error %d mapping Owner SID to gid\n" ,
@@ -884,6 +900,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
884900 pntsd -> type |= cpu_to_le16 (DACL_PROTECTED );
885901
886902 if (dacloffset ) {
903+ if (dacloffset < sizeof (struct smb_ntsd ))
904+ return - EINVAL ;
905+
887906 parse_dacl (idmap , dacl_ptr , end_of_acl ,
888907 owner_sid_ptr , group_sid_ptr , fattr );
889908 }
@@ -1006,8 +1025,9 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
10061025 struct smb_sid owner_sid , group_sid ;
10071026 struct dentry * parent = path -> dentry -> d_parent ;
10081027 struct mnt_idmap * idmap = mnt_idmap (path -> mnt );
1009- int inherited_flags = 0 , flags = 0 , i , ace_cnt = 0 , nt_size = 0 , pdacl_size ;
1010- int rc = 0 , num_aces , dacloffset , pntsd_type , pntsd_size , acl_len , aces_size ;
1028+ int inherited_flags = 0 , flags = 0 , i , nt_size = 0 , pdacl_size ;
1029+ int rc = 0 , dacloffset , pntsd_type , pntsd_size , acl_len , aces_size ;
1030+ u16 num_aces , ace_cnt = 0 ;
10111031 char * aces_base ;
10121032 bool is_dir = S_ISDIR (d_inode (path -> dentry )-> i_mode );
10131033
@@ -1023,7 +1043,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
10231043
10241044 parent_pdacl = (struct smb_acl * )((char * )parent_pntsd + dacloffset );
10251045 acl_len = pntsd_size - dacloffset ;
1026- num_aces = le32_to_cpu (parent_pdacl -> num_aces );
1046+ num_aces = le16_to_cpu (parent_pdacl -> num_aces );
10271047 pntsd_type = le16_to_cpu (parent_pntsd -> type );
10281048 pdacl_size = le16_to_cpu (parent_pdacl -> size );
10291049
@@ -1183,7 +1203,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
11831203 pdacl = (struct smb_acl * )((char * )pntsd + le32_to_cpu (pntsd -> dacloffset ));
11841204 pdacl -> revision = cpu_to_le16 (2 );
11851205 pdacl -> size = cpu_to_le16 (sizeof (struct smb_acl ) + nt_size );
1186- pdacl -> num_aces = cpu_to_le32 (ace_cnt );
1206+ pdacl -> num_aces = cpu_to_le16 (ace_cnt );
11871207 pace = (struct smb_ace * )((char * )pdacl + sizeof (struct smb_acl ));
11881208 memcpy (pace , aces_base , nt_size );
11891209 pntsd_size += sizeof (struct smb_acl ) + nt_size ;
@@ -1264,7 +1284,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
12641284
12651285 ace = (struct smb_ace * )((char * )pdacl + sizeof (struct smb_acl ));
12661286 aces_size = acl_size - sizeof (struct smb_acl );
1267- for (i = 0 ; i < le32_to_cpu (pdacl -> num_aces ); i ++ ) {
1287+ for (i = 0 ; i < le16_to_cpu (pdacl -> num_aces ); i ++ ) {
12681288 if (offsetof(struct smb_ace , access_req ) > aces_size )
12691289 break ;
12701290 ace_size = le16_to_cpu (ace -> size );
@@ -1285,7 +1305,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
12851305
12861306 ace = (struct smb_ace * )((char * )pdacl + sizeof (struct smb_acl ));
12871307 aces_size = acl_size - sizeof (struct smb_acl );
1288- for (i = 0 ; i < le32_to_cpu (pdacl -> num_aces ); i ++ ) {
1308+ for (i = 0 ; i < le16_to_cpu (pdacl -> num_aces ); i ++ ) {
12891309 if (offsetof(struct smb_ace , access_req ) > aces_size )
12901310 break ;
12911311 ace_size = le16_to_cpu (ace -> size );
0 commit comments