aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-02-10 16:18:26 -0500
committerSteve French <sfrench@us.ibm.com>2010-02-23 15:47:11 -0500
commit0cd126b504cede8a74acf7583a44eba32f9a1da1 (patch)
treec62a5835dbc50a2d5958a29ef511b349dff2842d /fs/cifs
parente529614ad0c2bf1f3a6fcf1402aa77430ecfaa2c (diff)
cifs: verify lengths of QueryAllEAs reply
Make sure the lengths in a QUERY_ALL_EAS reply don't make the parser walk off the end of the SMB. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifssmb.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 4f24f83ce623..e197e1647d5d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -5285,6 +5285,7 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5285 struct fealist *ea_response_data; 5285 struct fealist *ea_response_data;
5286 struct fea *temp_fea; 5286 struct fea *temp_fea;
5287 char *temp_ptr; 5287 char *temp_ptr;
5288 char *end_of_smb;
5288 __u16 params, byte_count, data_offset; 5289 __u16 params, byte_count, data_offset;
5289 5290
5290 cFYI(1, ("In Query All EAs path %s", searchName)); 5291 cFYI(1, ("In Query All EAs path %s", searchName));
@@ -5368,22 +5369,47 @@ QAllEAsRetry:
5368 goto QAllEAsOut; 5369 goto QAllEAsOut;
5369 } 5370 }
5370 5371
5372 /* make sure list_len doesn't go past end of SMB */
5373 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5374 if ((char *)ea_response_data + list_len > end_of_smb) {
5375 cFYI(1, ("EA list appears to go beyond SMB"));
5376 rc = -EIO;
5377 goto QAllEAsOut;
5378 }
5379
5371 /* account for ea list len */ 5380 /* account for ea list len */
5372 list_len -= 4; 5381 list_len -= 4;
5373 temp_fea = ea_response_data->list; 5382 temp_fea = ea_response_data->list;
5374 temp_ptr = (char *)temp_fea; 5383 temp_ptr = (char *)temp_fea;
5375 while (list_len > 0) { 5384 while (list_len > 0) {
5385 __u8 name_len;
5376 __u16 value_len; 5386 __u16 value_len;
5387
5377 list_len -= 4; 5388 list_len -= 4;
5378 temp_ptr += 4; 5389 temp_ptr += 4;
5379 rc += temp_fea->name_len; 5390 /* make sure we can read name_len and value_len */
5391 if (list_len < 0) {
5392 cFYI(1, ("EA entry goes beyond length of list"));
5393 rc = -EIO;
5394 goto QAllEAsOut;
5395 }
5396
5397 name_len = temp_fea->name_len;
5398 value_len = le16_to_cpu(temp_fea->value_len);
5399 list_len -= name_len + 1 + value_len;
5400 if (list_len < 0) {
5401 cFYI(1, ("EA entry goes beyond length of list"));
5402 rc = -EIO;
5403 goto QAllEAsOut;
5404 }
5405
5380 /* account for prefix user. and trailing null */ 5406 /* account for prefix user. and trailing null */
5381 rc = rc + 5 + 1; 5407 rc += (5 + 1 + name_len);
5382 if (rc < (int) buf_size) { 5408 if (rc < (int) buf_size) {
5383 memcpy(EAData, "user.", 5); 5409 memcpy(EAData, "user.", 5);
5384 EAData += 5; 5410 EAData += 5;
5385 memcpy(EAData, temp_ptr, temp_fea->name_len); 5411 memcpy(EAData, temp_ptr, name_len);
5386 EAData += temp_fea->name_len; 5412 EAData += name_len;
5387 /* null terminate name */ 5413 /* null terminate name */
5388 *EAData = 0; 5414 *EAData = 0;
5389 ++EAData; 5415 ++EAData;
@@ -5394,20 +5420,7 @@ QAllEAsRetry:
5394 rc = -ERANGE; 5420 rc = -ERANGE;
5395 break; 5421 break;
5396 } 5422 }
5397 list_len -= temp_fea->name_len; 5423 temp_ptr += name_len + 1 + value_len;
5398 temp_ptr += temp_fea->name_len;
5399 /* account for trailing null */
5400 list_len--;
5401 temp_ptr++;
5402 value_len = le16_to_cpu(temp_fea->value_len);
5403 list_len -= value_len;
5404 temp_ptr += value_len;
5405 /* BB check that temp_ptr is still
5406 within the SMB BB*/
5407
5408 /* no trailing null to account for
5409 in value len */
5410 /* go on to next EA */
5411 temp_fea = (struct fea *)temp_ptr; 5424 temp_fea = (struct fea *)temp_ptr;
5412 } 5425 }
5413 5426