• Gustavo A. R. Silva's avatar
    drm/amd/pm: Fix out-of-bounds bug · 939baec9
    Gustavo A. R. Silva authored
    Create new structure SISLANDS_SMC_SWSTATE_SINGLE, as initialState.levels
    and ACPIState.levels are never actually used as flexible arrays. Those
    arrays can be used as simple objects of type
    SISLANDS_SMC_HW_PERFORMANCE_LEVEL, instead.
    
    Currently, the code fails because flexible array _levels_ in
    struct SISLANDS_SMC_SWSTATE doesn't allow for code that accesses
    the first element of initialState.levels and ACPIState.levels
    arrays:
    
    drivers/gpu/drm/amd/pm/powerplay/si_dpm.c:
    4820: table->initialState.levels[0].mclk.vDLL_CNTL =
    4821:         cpu_to_be32(si_pi->clock_registers.dll_cntl);
    ...
    5021: table->ACPIState.levels[0].mclk.vDLL_CNTL =
    5022:         cpu_to_be32(dll_cntl);
    
    because such element cannot be accessed without previously allocating
    enough dynamic memory for it to exist (which never actually happens).
    So, there is an out-of-bounds bug in this case.
    
    That's why struct SISLANDS_SMC_SWSTATE should only be used as type
    for object driverState and new struct SISLANDS_SMC_SWSTATE_SINGLE is
    created as type for objects initialState, ACPIState and ULVState.
    
    Also, with the change from one-element array to flexible-array member
    in commit 0e1aa13c ("drm/amd/pm: Replace one-element array with
    flexible-array in struct SISLANDS_SMC_SWSTATE"), the size of
    dpmLevels in struct SISLANDS_SMC_STATETABLE should be fixed to be
    SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE instead of
    SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1.
    
    Fixes: 0e1aa13c ("drm/amd/pm: Replace one-element array with flexible-array in struct SISLANDS_SMC_SWSTATE")
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarGustavo A. R. Silva <gustavoars@kernel.org>
    Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
    939baec9
si_dpm.c 254 KB