@@ -1096,6 +1096,40 @@ static int smb_append_inherited_ace(struct smb_ace **ace, int *nt_size,
10961096 return 0 ;
10971097}
10981098
1099+ static int smb_validate_ntsd_sid (struct smb_ntsd * pntsd , size_t pntsd_size ,
1100+ unsigned int sid_offset , struct smb_sid * * sid ,
1101+ size_t * sid_size )
1102+ {
1103+ size_t sid_end ;
1104+
1105+ * sid = NULL ;
1106+ * sid_size = 0 ;
1107+
1108+ if (!sid_offset )
1109+ return 0 ;
1110+
1111+ if (sid_offset < sizeof (struct smb_ntsd ) ||
1112+ check_add_overflow (sid_offset , (size_t )CIFS_SID_BASE_SIZE ,
1113+ & sid_end ) ||
1114+ sid_end > pntsd_size )
1115+ return - EINVAL ;
1116+
1117+ * sid = (struct smb_sid * )((char * )pntsd + sid_offset );
1118+ if ((* sid )-> num_subauth > SID_MAX_SUB_AUTHORITIES )
1119+ return - EINVAL ;
1120+
1121+ if (check_add_overflow ((size_t )CIFS_SID_BASE_SIZE ,
1122+ sizeof (__le32 ) * (size_t )(* sid )-> num_subauth ,
1123+ & sid_end ))
1124+ return - EINVAL ;
1125+
1126+ if (sid_offset > pntsd_size || sid_end > pntsd_size - sid_offset )
1127+ return - EINVAL ;
1128+
1129+ * sid_size = sid_end ;
1130+ return 0 ;
1131+ }
1132+
10991133int smb_inherit_dacl (struct ksmbd_conn * conn ,
11001134 const struct path * path ,
11011135 unsigned int uid , unsigned int gid )
@@ -1108,28 +1142,28 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
11081142 struct dentry * parent = path -> dentry -> d_parent ;
11091143 struct mnt_idmap * idmap = mnt_idmap (path -> mnt );
11101144 int inherited_flags = 0 , flags = 0 , i , nt_size = 0 , pdacl_size ;
1111- int rc = 0 , pntsd_type , pntsd_size , acl_len , aces_size ;
1145+ int rc = 0 , pntsd_type , ppntsd_size , acl_len , aces_size ;
11121146 unsigned int dacloffset ;
11131147 size_t dacl_struct_end ;
11141148 u16 num_aces , ace_cnt = 0 ;
11151149 char * aces_base ;
11161150 bool is_dir = S_ISDIR (d_inode (path -> dentry )-> i_mode );
11171151
1118- pntsd_size = ksmbd_vfs_get_sd_xattr (conn , idmap ,
1152+ ppntsd_size = ksmbd_vfs_get_sd_xattr (conn , idmap ,
11191153 parent , & parent_pntsd );
1120- if (pntsd_size <= 0 )
1154+ if (ppntsd_size <= 0 )
11211155 return - ENOENT ;
11221156
11231157 dacloffset = le32_to_cpu (parent_pntsd -> dacloffset );
11241158 if (!dacloffset ||
11251159 check_add_overflow (dacloffset , sizeof (struct smb_acl ), & dacl_struct_end ) ||
1126- dacl_struct_end > (size_t )pntsd_size ) {
1160+ dacl_struct_end > (size_t )ppntsd_size ) {
11271161 rc = - EINVAL ;
11281162 goto free_parent_pntsd ;
11291163 }
11301164
11311165 parent_pdacl = (struct smb_acl * )((char * )parent_pntsd + dacloffset );
1132- acl_len = pntsd_size - dacloffset ;
1166+ acl_len = ppntsd_size - dacloffset ;
11331167 num_aces = le16_to_cpu (parent_pdacl -> num_aces );
11341168 pntsd_type = le16_to_cpu (parent_pntsd -> type );
11351169 pdacl_size = le16_to_cpu (parent_pdacl -> size );
@@ -1243,19 +1277,19 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
12431277 struct smb_ntsd * pntsd ;
12441278 struct smb_acl * pdacl ;
12451279 struct smb_sid * powner_sid = NULL , * pgroup_sid = NULL ;
1246- int powner_sid_size = 0 , pgroup_sid_size = 0 , pntsd_size ;
1280+ size_t powner_sid_size = 0 , pgroup_sid_size = 0 , pntsd_size ;
12471281 size_t pntsd_alloc_size ;
12481282
1249- if (parent_pntsd -> osidoffset ) {
1250- powner_sid = ( struct smb_sid * )(( char * ) parent_pntsd +
1251- le32_to_cpu ( parent_pntsd -> osidoffset ) );
1252- powner_sid_size = 1 + 1 + 6 + ( powner_sid -> num_subauth * 4 );
1253- }
1254- if (parent_pntsd -> gsidoffset ) {
1255- pgroup_sid = ( struct smb_sid * )(( char * ) parent_pntsd +
1256- le32_to_cpu ( parent_pntsd -> gsidoffset ) );
1257- pgroup_sid_size = 1 + 1 + 6 + ( pgroup_sid -> num_subauth * 4 );
1258- }
1283+ rc = smb_validate_ntsd_sid (parent_pntsd , ppntsd_size ,
1284+ le32_to_cpu ( parent_pntsd -> osidoffset ),
1285+ & powner_sid , & powner_sid_size );
1286+ if ( rc )
1287+ goto free_aces_base ;
1288+ rc = smb_validate_ntsd_sid (parent_pntsd , ppntsd_size ,
1289+ le32_to_cpu ( parent_pntsd -> gsidoffset ),
1290+ & pgroup_sid , & pgroup_sid_size );
1291+ if ( rc )
1292+ goto free_aces_base ;
12591293
12601294 if (check_add_overflow (sizeof (struct smb_ntsd ),
12611295 (size_t )powner_sid_size ,
0 commit comments