Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu/pptable: Fix UBSAN array-index-out-of-bounds

Flexible arrays used [1] instead of []. Replace the former with the latter
to resolve multiple UBSAN warnings observed on boot with a BONAIRE card.

In addition, use the __counted_by attribute where possible to hint the
length of the arrays to the compiler and any sanitizers.

Signed-off-by: Tasos Sahanidis <tasos@tasossah.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Tasos Sahanidis and committed by
Alex Deucher
98f9e5ea 34a6aa4e

+49 -42
+49 -42
drivers/gpu/drm/amd/include/pptable.h
··· 477 477 } ATOM_PPLIB_STATE_V2; 478 478 479 479 typedef struct _StateArray{ 480 - //how many states we have 481 - UCHAR ucNumEntries; 482 - 483 - ATOM_PPLIB_STATE_V2 states[1]; 480 + //how many states we have 481 + UCHAR ucNumEntries; 482 + 483 + ATOM_PPLIB_STATE_V2 states[] /* __counted_by(ucNumEntries) */; 484 484 }StateArray; 485 485 486 486 487 487 typedef struct _ClockInfoArray{ 488 - //how many clock levels we have 489 - UCHAR ucNumEntries; 490 - 491 - //sizeof(ATOM_PPLIB_CLOCK_INFO) 492 - UCHAR ucEntrySize; 493 - 494 - UCHAR clockInfo[]; 488 + //how many clock levels we have 489 + UCHAR ucNumEntries; 490 + 491 + //sizeof(ATOM_PPLIB_CLOCK_INFO) 492 + UCHAR ucEntrySize; 493 + 494 + UCHAR clockInfo[]; 495 495 }ClockInfoArray; 496 496 497 497 typedef struct _NonClockInfoArray{ 498 + //how many non-clock levels we have. normally should be same as number of states 499 + UCHAR ucNumEntries; 500 + //sizeof(ATOM_PPLIB_NONCLOCK_INFO) 501 + UCHAR ucEntrySize; 498 502 499 - //how many non-clock levels we have. normally should be same as number of states 500 - UCHAR ucNumEntries; 501 - //sizeof(ATOM_PPLIB_NONCLOCK_INFO) 502 - UCHAR ucEntrySize; 503 - 504 - ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[]; 503 + ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries); 505 504 }NonClockInfoArray; 506 505 507 506 typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record ··· 512 513 513 514 typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table 514 515 { 515 - UCHAR ucNumEntries; // Number of entries. 516 - ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1]; // Dynamically allocate entries. 516 + // Number of entries. 517 + UCHAR ucNumEntries; 518 + // Dynamically allocate entries. 519 + ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[] __counted_by(ucNumEntries); 517 520 }ATOM_PPLIB_Clock_Voltage_Dependency_Table; 518 521 519 522 typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record ··· 530 529 531 530 typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table 532 531 { 533 - UCHAR ucNumEntries; // Number of entries. 534 - ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. 532 + // Number of entries. 533 + UCHAR ucNumEntries; 534 + // Dynamically allocate entries. 535 + ATOM_PPLIB_Clock_Voltage_Limit_Record entries[] __counted_by(ucNumEntries); 535 536 }ATOM_PPLIB_Clock_Voltage_Limit_Table; 536 537 537 538 union _ATOM_PPLIB_CAC_Leakage_Record ··· 556 553 557 554 typedef struct _ATOM_PPLIB_CAC_Leakage_Table 558 555 { 559 - UCHAR ucNumEntries; // Number of entries. 560 - ATOM_PPLIB_CAC_Leakage_Record entries[1]; // Dynamically allocate entries. 556 + // Number of entries. 557 + UCHAR ucNumEntries; 558 + // Dynamically allocate entries. 559 + ATOM_PPLIB_CAC_Leakage_Record entries[] __counted_by(ucNumEntries); 561 560 }ATOM_PPLIB_CAC_Leakage_Table; 562 561 563 562 typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Record ··· 573 568 574 569 typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Table 575 570 { 576 - UCHAR ucNumEntries; // Number of entries. 577 - ATOM_PPLIB_PhaseSheddingLimits_Record entries[1]; // Dynamically allocate entries. 571 + // Number of entries. 572 + UCHAR ucNumEntries; 573 + // Dynamically allocate entries. 574 + ATOM_PPLIB_PhaseSheddingLimits_Record entries[] __counted_by(ucNumEntries); 578 575 }ATOM_PPLIB_PhaseSheddingLimits_Table; 579 576 580 577 typedef struct _VCEClockInfo{ ··· 587 580 }VCEClockInfo; 588 581 589 582 typedef struct _VCEClockInfoArray{ 590 - UCHAR ucNumEntries; 591 - VCEClockInfo entries[1]; 583 + UCHAR ucNumEntries; 584 + VCEClockInfo entries[] __counted_by(ucNumEntries); 592 585 }VCEClockInfoArray; 593 586 594 587 typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record ··· 599 592 600 593 typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table 601 594 { 602 - UCHAR numEntries; 603 - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[1]; 595 + UCHAR numEntries; 596 + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[] __counted_by(numEntries); 604 597 }ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table; 605 598 606 599 typedef struct _ATOM_PPLIB_VCE_State_Record ··· 611 604 612 605 typedef struct _ATOM_PPLIB_VCE_State_Table 613 606 { 614 - UCHAR numEntries; 615 - ATOM_PPLIB_VCE_State_Record entries[1]; 607 + UCHAR numEntries; 608 + ATOM_PPLIB_VCE_State_Record entries[] __counted_by(numEntries); 616 609 }ATOM_PPLIB_VCE_State_Table; 617 610 618 611 ··· 633 626 }UVDClockInfo; 634 627 635 628 typedef struct _UVDClockInfoArray{ 636 - UCHAR ucNumEntries; 637 - UVDClockInfo entries[1]; 629 + UCHAR ucNumEntries; 630 + UVDClockInfo entries[] __counted_by(ucNumEntries); 638 631 }UVDClockInfoArray; 639 632 640 633 typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record ··· 645 638 646 639 typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table 647 640 { 648 - UCHAR numEntries; 649 - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[1]; 641 + UCHAR numEntries; 642 + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[] __counted_by(numEntries); 650 643 }ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table; 651 644 652 645 typedef struct _ATOM_PPLIB_UVD_Table ··· 664 657 }ATOM_PPLIB_SAMClk_Voltage_Limit_Record; 665 658 666 659 typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Table{ 667 - UCHAR numEntries; 668 - ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[]; 660 + UCHAR numEntries; 661 + ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[] __counted_by(numEntries); 669 662 }ATOM_PPLIB_SAMClk_Voltage_Limit_Table; 670 663 671 664 typedef struct _ATOM_PPLIB_SAMU_Table ··· 682 675 }ATOM_PPLIB_ACPClk_Voltage_Limit_Record; 683 676 684 677 typedef struct _ATOM_PPLIB_ACPClk_Voltage_Limit_Table{ 685 - UCHAR numEntries; 686 - ATOM_PPLIB_ACPClk_Voltage_Limit_Record entries[1]; 678 + UCHAR numEntries; 679 + ATOM_PPLIB_ACPClk_Voltage_Limit_Record entries[] __counted_by(numEntries); 687 680 }ATOM_PPLIB_ACPClk_Voltage_Limit_Table; 688 681 689 682 typedef struct _ATOM_PPLIB_ACP_Table ··· 750 743 } ATOM_PPLIB_VQ_Budgeting_Record; 751 744 752 745 typedef struct ATOM_PPLIB_VQ_Budgeting_Table { 753 - UCHAR revid; 754 - UCHAR numEntries; 755 - ATOM_PPLIB_VQ_Budgeting_Record entries[1]; 746 + UCHAR revid; 747 + UCHAR numEntries; 748 + ATOM_PPLIB_VQ_Budgeting_Record entries[] __counted_by(numEntries); 756 749 } ATOM_PPLIB_VQ_Budgeting_Table; 757 750 758 751 #pragma pack()