@@ -80,18 +80,21 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
8080};
8181
8282/*
83- * Returns the pointer to the beginning of the data area. Length of the data
84- * area and the offset to it (from the beginning of the smb are also returned .
83+ * Set length of the data area and the offset to arguments.
84+ * if they are invalid, return error .
8585 */
86- static char * smb2_get_data_area_len (int * off , int * len , struct smb2_hdr * hdr )
86+ static int smb2_get_data_area_len (unsigned int * off , unsigned int * len ,
87+ struct smb2_hdr * hdr )
8788{
89+ int ret = 0 ;
90+
8891 * off = 0 ;
8992 * len = 0 ;
9093
9194 /* error reqeusts do not have data area */
9295 if (hdr -> Status && hdr -> Status != STATUS_MORE_PROCESSING_REQUIRED &&
9396 (((struct smb2_err_rsp * )hdr )-> StructureSize ) == SMB2_ERROR_STRUCTURE_SIZE2_LE )
94- return NULL ;
97+ return ret ;
9598
9699 /*
97100 * Following commands have data areas so we have to get the location
@@ -165,69 +168,60 @@ static char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
165168 case SMB2_IOCTL :
166169 * off = le32_to_cpu (((struct smb2_ioctl_req * )hdr )-> InputOffset );
167170 * len = le32_to_cpu (((struct smb2_ioctl_req * )hdr )-> InputCount );
168-
169171 break ;
170172 default :
171173 ksmbd_debug (SMB , "no length check for command\n" );
172174 break ;
173175 }
174176
175- /*
176- * Invalid length or offset probably means data area is invalid, but
177- * we have little choice but to ignore the data area in this case.
178- */
179177 if (* off > 4096 ) {
180- ksmbd_debug (SMB , "offset %d too large, data area ignored\n" ,
181- * off );
182- * len = 0 ;
183- * off = 0 ;
184- } else if (* off < 0 ) {
185- ksmbd_debug (SMB ,
186- "negative offset %d to data invalid ignore data area\n" ,
187- * off );
188- * off = 0 ;
189- * len = 0 ;
190- } else if (* len < 0 ) {
191- ksmbd_debug (SMB ,
192- "negative data length %d invalid, data area ignored\n" ,
193- * len );
194- * len = 0 ;
195- } else if (* len > 128 * 1024 ) {
196- ksmbd_debug (SMB , "data area larger than 128K: %d\n" , * len );
197- * len = 0 ;
178+ ksmbd_debug (SMB , "offset %d too large\n" , * off );
179+ ret = - EINVAL ;
180+ } else if ((u64 )* off + * len > MAX_STREAM_PROT_LEN ) {
181+ ksmbd_debug (SMB , "Request is larger than maximum stream protocol length(%u): %llu\n" ,
182+ MAX_STREAM_PROT_LEN , (u64 )* off + * len );
183+ ret = - EINVAL ;
198184 }
199185
200- /* return pointer to beginning of data area, ie offset from SMB start */
201- if ((* off != 0 ) && (* len != 0 ))
202- return (char * )hdr + * off ;
203- else
204- return NULL ;
186+ return ret ;
205187}
206188
207189/*
208190 * Calculate the size of the SMB message based on the fixed header
209191 * portion, the number of word parameters and the data portion of the message.
210192 */
211- static unsigned int smb2_calc_size (void * buf )
193+ static int smb2_calc_size (void * buf , unsigned int * len )
212194{
213195 struct smb2_pdu * pdu = (struct smb2_pdu * )buf ;
214196 struct smb2_hdr * hdr = & pdu -> hdr ;
215- int offset ; /* the offset from the beginning of SMB to data area */
216- int data_length ; /* the length of the variable length data area */
197+ unsigned int offset ; /* the offset from the beginning of SMB to data area */
198+ unsigned int data_length ; /* the length of the variable length data area */
199+ int ret ;
200+
217201 /* Structure Size has already been checked to make sure it is 64 */
218- int len = le16_to_cpu (hdr -> StructureSize );
202+ * len = le16_to_cpu (hdr -> StructureSize );
219203
220204 /*
221205 * StructureSize2, ie length of fixed parameter area has already
222206 * been checked to make sure it is the correct length.
223207 */
224- len += le16_to_cpu (pdu -> StructureSize2 );
208+ * len += le16_to_cpu (pdu -> StructureSize2 );
209+ /*
210+ * StructureSize2 of smb2_lock pdu is set to 48, indicating
211+ * the size of smb2 lock request with single smb2_lock_element
212+ * regardless of number of locks. Subtract single
213+ * smb2_lock_element for correct buffer size check.
214+ */
215+ if (hdr -> Command == SMB2_LOCK )
216+ * len -= sizeof (struct smb2_lock_element );
225217
226218 if (has_smb2_data_area [le16_to_cpu (hdr -> Command )] == false)
227219 goto calc_size_exit ;
228220
229- smb2_get_data_area_len (& offset , & data_length , hdr );
230- ksmbd_debug (SMB , "SMB2 data length %d offset %d\n" , data_length ,
221+ ret = smb2_get_data_area_len (& offset , & data_length , hdr );
222+ if (ret )
223+ return ret ;
224+ ksmbd_debug (SMB , "SMB2 data length %u offset %u\n" , data_length ,
231225 offset );
232226
233227 if (data_length > 0 ) {
@@ -237,16 +231,19 @@ static unsigned int smb2_calc_size(void *buf)
237231 * for some commands, typically those with odd StructureSize,
238232 * so we must add one to the calculation.
239233 */
240- if (offset + 1 < len )
234+ if (offset + 1 < * len ) {
241235 ksmbd_debug (SMB ,
242- "data area offset %d overlaps SMB2 header %d\n" ,
243- offset + 1 , len );
244- else
245- len = offset + data_length ;
236+ "data area offset %d overlaps SMB2 header %u\n" ,
237+ offset + 1 , * len );
238+ return - EINVAL ;
239+ }
240+
241+ * len = offset + data_length ;
246242 }
243+
247244calc_size_exit :
248- ksmbd_debug (SMB , "SMB2 len %d \n" , len );
249- return len ;
245+ ksmbd_debug (SMB , "SMB2 len %u \n" , * len );
246+ return 0 ;
250247}
251248
252249static inline int smb2_query_info_req_len (struct smb2_query_info_req * h )
@@ -391,9 +388,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
391388 return 1 ;
392389 }
393390
394- clc_len = smb2_calc_size (hdr );
391+ if (smb2_calc_size (hdr , & clc_len ))
392+ return 1 ;
393+
395394 if (len != clc_len ) {
396- /* server can return one byte more due to implied bcc[0] */
395+ /* client can return one byte more due to implied bcc[0] */
397396 if (clc_len == len + 1 )
398397 return 0 ;
399398
@@ -418,9 +417,6 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
418417 return 0 ;
419418 }
420419
421- if (command == SMB2_LOCK_HE && len == 88 )
422- return 0 ;
423-
424420 ksmbd_debug (SMB ,
425421 "cli req too short, len %d not %d. cmd:%d mid:%llu\n" ,
426422 len , clc_len , command ,
0 commit comments