diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 151 |
1 files changed, 75 insertions, 76 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 941441d3e386..30709589e0c9 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -5282,9 +5282,10 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | |||
5282 | int rc = 0; | 5282 | int rc = 0; |
5283 | int bytes_returned; | 5283 | int bytes_returned; |
5284 | int name_len; | 5284 | int name_len; |
5285 | struct fealist *ea_response_data; | ||
5285 | struct fea *temp_fea; | 5286 | struct fea *temp_fea; |
5286 | char *temp_ptr; | 5287 | char *temp_ptr; |
5287 | __u16 params, byte_count; | 5288 | __u16 params, byte_count, data_offset; |
5288 | 5289 | ||
5289 | cFYI(1, ("In Query All EAs path %s", searchName)); | 5290 | cFYI(1, ("In Query All EAs path %s", searchName)); |
5290 | QAllEAsRetry: | 5291 | QAllEAsRetry: |
@@ -5334,85 +5335,83 @@ QAllEAsRetry: | |||
5334 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5335 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
5335 | if (rc) { | 5336 | if (rc) { |
5336 | cFYI(1, ("Send error in QueryAllEAs = %d", rc)); | 5337 | cFYI(1, ("Send error in QueryAllEAs = %d", rc)); |
5337 | } else { /* decode response */ | 5338 | goto QAllEAsOut; |
5338 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5339 | } |
5339 | 5340 | ||
5340 | /* BB also check enough total bytes returned */ | ||
5341 | /* BB we need to improve the validity checking | ||
5342 | of these trans2 responses */ | ||
5343 | if (rc || (pSMBr->ByteCount < 4)) | ||
5344 | rc = -EIO; /* bad smb */ | ||
5345 | /* else if (pFindData){ | ||
5346 | memcpy((char *) pFindData, | ||
5347 | (char *) &pSMBr->hdr.Protocol + | ||
5348 | data_offset, kl); | ||
5349 | }*/ else { | ||
5350 | /* check that length of list is not more than bcc */ | ||
5351 | /* check that each entry does not go beyond length | ||
5352 | of list */ | ||
5353 | /* check that each element of each entry does not | ||
5354 | go beyond end of list */ | ||
5355 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
5356 | struct fealist *ea_response_data; | ||
5357 | rc = 0; | ||
5358 | /* validate_trans2_offsets() */ | ||
5359 | /* BB check if start of smb + data_offset > &bcc+ bcc */ | ||
5360 | ea_response_data = (struct fealist *) | ||
5361 | (((char *) &pSMBr->hdr.Protocol) + | ||
5362 | data_offset); | ||
5363 | name_len = le32_to_cpu(ea_response_data->list_len); | ||
5364 | cFYI(1, ("ea length %d", name_len)); | ||
5365 | if (name_len <= 8) { | ||
5366 | /* returned EA size zeroed at top of function */ | ||
5367 | cFYI(1, ("empty EA list returned from server")); | ||
5368 | } else { | ||
5369 | /* account for ea list len */ | ||
5370 | name_len -= 4; | ||
5371 | temp_fea = ea_response_data->list; | ||
5372 | temp_ptr = (char *)temp_fea; | ||
5373 | while (name_len > 0) { | ||
5374 | __u16 value_len; | ||
5375 | name_len -= 4; | ||
5376 | temp_ptr += 4; | ||
5377 | rc += temp_fea->name_len; | ||
5378 | /* account for prefix user. and trailing null */ | ||
5379 | rc = rc + 5 + 1; | ||
5380 | if (rc < (int)buf_size) { | ||
5381 | memcpy(EAData, "user.", 5); | ||
5382 | EAData += 5; | ||
5383 | memcpy(EAData, temp_ptr, | ||
5384 | temp_fea->name_len); | ||
5385 | EAData += temp_fea->name_len; | ||
5386 | /* null terminate name */ | ||
5387 | *EAData = 0; | ||
5388 | EAData = EAData + 1; | ||
5389 | } else if (buf_size == 0) { | ||
5390 | /* skip copy - calc size only */ | ||
5391 | } else { | ||
5392 | /* stop before overrun buffer */ | ||
5393 | rc = -ERANGE; | ||
5394 | break; | ||
5395 | } | ||
5396 | name_len -= temp_fea->name_len; | ||
5397 | temp_ptr += temp_fea->name_len; | ||
5398 | /* account for trailing null */ | ||
5399 | name_len--; | ||
5400 | temp_ptr++; | ||
5401 | value_len = | ||
5402 | le16_to_cpu(temp_fea->value_len); | ||
5403 | name_len -= value_len; | ||
5404 | temp_ptr += value_len; | ||
5405 | /* BB check that temp_ptr is still | ||
5406 | within the SMB BB*/ | ||
5407 | 5341 | ||
5408 | /* no trailing null to account for | 5342 | /* BB also check enough total bytes returned */ |
5409 | in value len */ | 5343 | /* BB we need to improve the validity checking |
5410 | /* go on to next EA */ | 5344 | of these trans2 responses */ |
5411 | temp_fea = (struct fea *)temp_ptr; | 5345 | |
5412 | } | 5346 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
5413 | } | 5347 | if (rc || (pSMBr->ByteCount < 4)) { |
5348 | rc = -EIO; /* bad smb */ | ||
5349 | goto QAllEAsOut; | ||
5350 | } | ||
5351 | |||
5352 | /* check that length of list is not more than bcc */ | ||
5353 | /* check that each entry does not go beyond length | ||
5354 | of list */ | ||
5355 | /* check that each element of each entry does not | ||
5356 | go beyond end of list */ | ||
5357 | /* validate_trans2_offsets() */ | ||
5358 | /* BB check if start of smb + data_offset > &bcc+ bcc */ | ||
5359 | |||
5360 | data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
5361 | ea_response_data = (struct fealist *) | ||
5362 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | ||
5363 | |||
5364 | name_len = le32_to_cpu(ea_response_data->list_len); | ||
5365 | cFYI(1, ("ea length %d", name_len)); | ||
5366 | if (name_len <= 8) { | ||
5367 | cFYI(1, ("empty EA list returned from server")); | ||
5368 | goto QAllEAsOut; | ||
5369 | } | ||
5370 | |||
5371 | /* account for ea list len */ | ||
5372 | name_len -= 4; | ||
5373 | temp_fea = ea_response_data->list; | ||
5374 | temp_ptr = (char *)temp_fea; | ||
5375 | while (name_len > 0) { | ||
5376 | __u16 value_len; | ||
5377 | name_len -= 4; | ||
5378 | temp_ptr += 4; | ||
5379 | rc += temp_fea->name_len; | ||
5380 | /* account for prefix user. and trailing null */ | ||
5381 | rc = rc + 5 + 1; | ||
5382 | if (rc < (int) buf_size) { | ||
5383 | memcpy(EAData, "user.", 5); | ||
5384 | EAData += 5; | ||
5385 | memcpy(EAData, temp_ptr, temp_fea->name_len); | ||
5386 | EAData += temp_fea->name_len; | ||
5387 | /* null terminate name */ | ||
5388 | *EAData = 0; | ||
5389 | EAData = EAData + 1; | ||
5390 | } else if (buf_size == 0) { | ||
5391 | /* skip copy - calc size only */ | ||
5392 | } else { | ||
5393 | /* stop before overrun buffer */ | ||
5394 | rc = -ERANGE; | ||
5395 | break; | ||
5414 | } | 5396 | } |
5397 | name_len -= temp_fea->name_len; | ||
5398 | temp_ptr += temp_fea->name_len; | ||
5399 | /* account for trailing null */ | ||
5400 | name_len--; | ||
5401 | temp_ptr++; | ||
5402 | value_len = le16_to_cpu(temp_fea->value_len); | ||
5403 | name_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; | ||
5415 | } | 5412 | } |
5413 | |||
5414 | QAllEAsOut: | ||
5416 | cifs_buf_release(pSMB); | 5415 | cifs_buf_release(pSMB); |
5417 | if (rc == -EAGAIN) | 5416 | if (rc == -EAGAIN) |
5418 | goto QAllEAsRetry; | 5417 | goto QAllEAsRetry; |