.. | .. |
---|
433 | 433 | } |
---|
434 | 434 | #endif /* 0 */ |
---|
435 | 435 | |
---|
436 | | -static void ses_process_descriptor(struct enclosure_component *ecomp, |
---|
437 | | - unsigned char *desc) |
---|
| 436 | +static int ses_process_descriptor(struct enclosure_component *ecomp, |
---|
| 437 | + unsigned char *desc, int max_desc_len) |
---|
438 | 438 | { |
---|
439 | 439 | int eip = desc[0] & 0x10; |
---|
440 | 440 | int invalid = desc[0] & 0x80; |
---|
.. | .. |
---|
445 | 445 | unsigned char *d; |
---|
446 | 446 | |
---|
447 | 447 | if (invalid) |
---|
448 | | - return; |
---|
| 448 | + return 0; |
---|
449 | 449 | |
---|
450 | 450 | switch (proto) { |
---|
451 | 451 | case SCSI_PROTOCOL_FCP: |
---|
452 | 452 | if (eip) { |
---|
| 453 | + if (max_desc_len <= 7) |
---|
| 454 | + return 1; |
---|
453 | 455 | d = desc + 4; |
---|
454 | 456 | slot = d[3]; |
---|
455 | 457 | } |
---|
456 | 458 | break; |
---|
457 | 459 | case SCSI_PROTOCOL_SAS: |
---|
| 460 | + |
---|
458 | 461 | if (eip) { |
---|
| 462 | + if (max_desc_len <= 27) |
---|
| 463 | + return 1; |
---|
459 | 464 | d = desc + 4; |
---|
460 | 465 | slot = d[3]; |
---|
461 | 466 | d = desc + 8; |
---|
462 | | - } else |
---|
| 467 | + } else { |
---|
| 468 | + if (max_desc_len <= 23) |
---|
| 469 | + return 1; |
---|
463 | 470 | d = desc + 4; |
---|
| 471 | + } |
---|
| 472 | + |
---|
| 473 | + |
---|
464 | 474 | /* only take the phy0 addr */ |
---|
465 | 475 | addr = (u64)d[12] << 56 | |
---|
466 | 476 | (u64)d[13] << 48 | |
---|
.. | .. |
---|
477 | 487 | } |
---|
478 | 488 | ecomp->slot = slot; |
---|
479 | 489 | scomp->addr = addr; |
---|
| 490 | + |
---|
| 491 | + return 0; |
---|
480 | 492 | } |
---|
481 | 493 | |
---|
482 | 494 | struct efd { |
---|
.. | .. |
---|
490 | 502 | struct efd *efd = data; |
---|
491 | 503 | int i; |
---|
492 | 504 | struct ses_component *scomp; |
---|
493 | | - |
---|
494 | | - if (!edev->component[0].scratch) |
---|
495 | | - return 0; |
---|
496 | 505 | |
---|
497 | 506 | for (i = 0; i < edev->components; i++) { |
---|
498 | 507 | scomp = edev->component[i].scratch; |
---|
.. | .. |
---|
549 | 558 | /* skip past overall descriptor */ |
---|
550 | 559 | desc_ptr += len + 4; |
---|
551 | 560 | } |
---|
552 | | - if (ses_dev->page10) |
---|
| 561 | + if (ses_dev->page10 && ses_dev->page10_len > 9) |
---|
553 | 562 | addl_desc_ptr = ses_dev->page10 + 8; |
---|
554 | 563 | type_ptr = ses_dev->page1_types; |
---|
555 | 564 | components = 0; |
---|
.. | .. |
---|
557 | 566 | for (j = 0; j < type_ptr[1]; j++) { |
---|
558 | 567 | char *name = NULL; |
---|
559 | 568 | struct enclosure_component *ecomp; |
---|
| 569 | + int max_desc_len; |
---|
560 | 570 | |
---|
561 | 571 | if (desc_ptr) { |
---|
562 | | - if (desc_ptr >= buf + page7_len) { |
---|
| 572 | + if (desc_ptr + 3 >= buf + page7_len) { |
---|
563 | 573 | desc_ptr = NULL; |
---|
564 | 574 | } else { |
---|
565 | 575 | len = (desc_ptr[2] << 8) + desc_ptr[3]; |
---|
566 | 576 | desc_ptr += 4; |
---|
567 | | - /* Add trailing zero - pushes into |
---|
568 | | - * reserved space */ |
---|
569 | | - desc_ptr[len] = '\0'; |
---|
570 | | - name = desc_ptr; |
---|
| 577 | + if (desc_ptr + len > buf + page7_len) |
---|
| 578 | + desc_ptr = NULL; |
---|
| 579 | + else { |
---|
| 580 | + /* Add trailing zero - pushes into |
---|
| 581 | + * reserved space */ |
---|
| 582 | + desc_ptr[len] = '\0'; |
---|
| 583 | + name = desc_ptr; |
---|
| 584 | + } |
---|
571 | 585 | } |
---|
572 | 586 | } |
---|
573 | 587 | if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || |
---|
.. | .. |
---|
579 | 593 | components++, |
---|
580 | 594 | type_ptr[0], |
---|
581 | 595 | name); |
---|
582 | | - else |
---|
| 596 | + else if (components < edev->components) |
---|
583 | 597 | ecomp = &edev->component[components++]; |
---|
| 598 | + else |
---|
| 599 | + ecomp = ERR_PTR(-EINVAL); |
---|
584 | 600 | |
---|
585 | 601 | if (!IS_ERR(ecomp)) { |
---|
586 | | - if (addl_desc_ptr) |
---|
587 | | - ses_process_descriptor( |
---|
588 | | - ecomp, |
---|
589 | | - addl_desc_ptr); |
---|
| 602 | + if (addl_desc_ptr) { |
---|
| 603 | + max_desc_len = ses_dev->page10_len - |
---|
| 604 | + (addl_desc_ptr - ses_dev->page10); |
---|
| 605 | + if (ses_process_descriptor(ecomp, |
---|
| 606 | + addl_desc_ptr, |
---|
| 607 | + max_desc_len)) |
---|
| 608 | + addl_desc_ptr = NULL; |
---|
| 609 | + } |
---|
590 | 610 | if (create) |
---|
591 | 611 | enclosure_component_register( |
---|
592 | 612 | ecomp); |
---|
.. | .. |
---|
603 | 623 | /* these elements are optional */ |
---|
604 | 624 | type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT || |
---|
605 | 625 | type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT || |
---|
606 | | - type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) |
---|
| 626 | + type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) { |
---|
607 | 627 | addl_desc_ptr += addl_desc_ptr[1] + 2; |
---|
608 | | - |
---|
| 628 | + if (addl_desc_ptr + 1 >= ses_dev->page10 + ses_dev->page10_len) |
---|
| 629 | + addl_desc_ptr = NULL; |
---|
| 630 | + } |
---|
609 | 631 | } |
---|
610 | 632 | } |
---|
611 | 633 | kfree(buf); |
---|
.. | .. |
---|
704 | 726 | type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) |
---|
705 | 727 | components += type_ptr[1]; |
---|
706 | 728 | } |
---|
| 729 | + |
---|
707 | 730 | ses_dev->page1 = buf; |
---|
708 | 731 | ses_dev->page1_len = len; |
---|
709 | 732 | buf = NULL; |
---|
.. | .. |
---|
745 | 768 | buf = NULL; |
---|
746 | 769 | } |
---|
747 | 770 | page2_not_supported: |
---|
748 | | - scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); |
---|
749 | | - if (!scomp) |
---|
750 | | - goto err_free; |
---|
| 771 | + if (components > 0) { |
---|
| 772 | + scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); |
---|
| 773 | + if (!scomp) |
---|
| 774 | + goto err_free; |
---|
| 775 | + } |
---|
751 | 776 | |
---|
752 | 777 | edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev), |
---|
753 | 778 | components, &ses_enclosure_callbacks); |
---|
.. | .. |
---|
827 | 852 | kfree(ses_dev->page2); |
---|
828 | 853 | kfree(ses_dev); |
---|
829 | 854 | |
---|
830 | | - kfree(edev->component[0].scratch); |
---|
| 855 | + if (edev->components) |
---|
| 856 | + kfree(edev->component[0].scratch); |
---|
831 | 857 | |
---|
832 | 858 | put_device(&edev->edev); |
---|
833 | 859 | enclosure_unregister(edev); |
---|