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

drm/amd/display: Fix UBSAN: shift-out-of-bounds warning

[Why]
On NAVI14 CONFIG_UBSAN reported shift-out-of-bounds at
display_rq_dlg_calc_20v2.c:304:38

rq_param->misc.rq_c.blk256_height is 0 when chroma(*_c) is invalid.
dml_log2 returns -1023 for log2(0), although log2(0) is undefined.

Which ended up as:
rq_param->dlg.rq_c.swath_height = 1 << -1023

[How]
Fix applied on all dml versions.
1. Ensure dml_log2 is only called if the argument is greater than 0.
2. Subtract req128_l/req128_c from log2_swath_height_l/log2_swath_height_c
only when it is greater than 0.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Anson Jacob <Anson.Jacob@amd.com>
Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Solomon Chiu <solomon.chiu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Anson Jacob and committed by
Alex Deucher
54718747 3d223c55

+115 -25
+23 -5
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
··· 293 293 if (surf_linear) { 294 294 log2_swath_height_l = 0; 295 295 log2_swath_height_c = 0; 296 - } else if (!surf_vert) { 297 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; 298 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; 299 296 } else { 300 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; 301 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; 297 + unsigned int swath_height_l; 298 + unsigned int swath_height_c; 299 + 300 + if (!surf_vert) { 301 + swath_height_l = rq_param->misc.rq_l.blk256_height; 302 + swath_height_c = rq_param->misc.rq_c.blk256_height; 303 + } else { 304 + swath_height_l = rq_param->misc.rq_l.blk256_width; 305 + swath_height_c = rq_param->misc.rq_c.blk256_width; 306 + } 307 + 308 + if (swath_height_l > 0) 309 + log2_swath_height_l = dml_log2(swath_height_l); 310 + 311 + if (req128_l && log2_swath_height_l > 0) 312 + log2_swath_height_l -= 1; 313 + 314 + if (swath_height_c > 0) 315 + log2_swath_height_c = dml_log2(swath_height_c); 316 + 317 + if (req128_c && log2_swath_height_c > 0) 318 + log2_swath_height_c -= 1; 302 319 } 320 + 303 321 rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; 304 322 rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; 305 323
+23 -5
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
··· 293 293 if (surf_linear) { 294 294 log2_swath_height_l = 0; 295 295 log2_swath_height_c = 0; 296 - } else if (!surf_vert) { 297 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; 298 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; 299 296 } else { 300 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; 301 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; 297 + unsigned int swath_height_l; 298 + unsigned int swath_height_c; 299 + 300 + if (!surf_vert) { 301 + swath_height_l = rq_param->misc.rq_l.blk256_height; 302 + swath_height_c = rq_param->misc.rq_c.blk256_height; 303 + } else { 304 + swath_height_l = rq_param->misc.rq_l.blk256_width; 305 + swath_height_c = rq_param->misc.rq_c.blk256_width; 306 + } 307 + 308 + if (swath_height_l > 0) 309 + log2_swath_height_l = dml_log2(swath_height_l); 310 + 311 + if (req128_l && log2_swath_height_l > 0) 312 + log2_swath_height_l -= 1; 313 + 314 + if (swath_height_c > 0) 315 + log2_swath_height_c = dml_log2(swath_height_c); 316 + 317 + if (req128_c && log2_swath_height_c > 0) 318 + log2_swath_height_c -= 1; 302 319 } 320 + 303 321 rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; 304 322 rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; 305 323
+23 -5
drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
··· 277 277 if (surf_linear) { 278 278 log2_swath_height_l = 0; 279 279 log2_swath_height_c = 0; 280 - } else if (!surf_vert) { 281 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; 282 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; 283 280 } else { 284 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; 285 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; 281 + unsigned int swath_height_l; 282 + unsigned int swath_height_c; 283 + 284 + if (!surf_vert) { 285 + swath_height_l = rq_param->misc.rq_l.blk256_height; 286 + swath_height_c = rq_param->misc.rq_c.blk256_height; 287 + } else { 288 + swath_height_l = rq_param->misc.rq_l.blk256_width; 289 + swath_height_c = rq_param->misc.rq_c.blk256_width; 290 + } 291 + 292 + if (swath_height_l > 0) 293 + log2_swath_height_l = dml_log2(swath_height_l); 294 + 295 + if (req128_l && log2_swath_height_l > 0) 296 + log2_swath_height_l -= 1; 297 + 298 + if (swath_height_c > 0) 299 + log2_swath_height_c = dml_log2(swath_height_c); 300 + 301 + if (req128_c && log2_swath_height_c > 0) 302 + log2_swath_height_c -= 1; 286 303 } 304 + 287 305 rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; 288 306 rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; 289 307
+23 -5
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
··· 237 237 if (surf_linear) { 238 238 log2_swath_height_l = 0; 239 239 log2_swath_height_c = 0; 240 - } else if (!surf_vert) { 241 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; 242 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; 243 240 } else { 244 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; 245 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; 241 + unsigned int swath_height_l; 242 + unsigned int swath_height_c; 243 + 244 + if (!surf_vert) { 245 + swath_height_l = rq_param->misc.rq_l.blk256_height; 246 + swath_height_c = rq_param->misc.rq_c.blk256_height; 247 + } else { 248 + swath_height_l = rq_param->misc.rq_l.blk256_width; 249 + swath_height_c = rq_param->misc.rq_c.blk256_width; 250 + } 251 + 252 + if (swath_height_l > 0) 253 + log2_swath_height_l = dml_log2(swath_height_l); 254 + 255 + if (req128_l && log2_swath_height_l > 0) 256 + log2_swath_height_l -= 1; 257 + 258 + if (swath_height_c > 0) 259 + log2_swath_height_c = dml_log2(swath_height_c); 260 + 261 + if (req128_c && log2_swath_height_c > 0) 262 + log2_swath_height_c -= 1; 246 263 } 264 + 247 265 rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; 248 266 rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; 249 267
+23 -5
drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
··· 344 344 if (surf_linear) { 345 345 log2_swath_height_l = 0; 346 346 log2_swath_height_c = 0; 347 - } else if (!surf_vert) { 348 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; 349 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; 350 347 } else { 351 - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; 352 - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; 348 + unsigned int swath_height_l; 349 + unsigned int swath_height_c; 350 + 351 + if (!surf_vert) { 352 + swath_height_l = rq_param->misc.rq_l.blk256_height; 353 + swath_height_c = rq_param->misc.rq_c.blk256_height; 354 + } else { 355 + swath_height_l = rq_param->misc.rq_l.blk256_width; 356 + swath_height_c = rq_param->misc.rq_c.blk256_width; 357 + } 358 + 359 + if (swath_height_l > 0) 360 + log2_swath_height_l = dml_log2(swath_height_l); 361 + 362 + if (req128_l && log2_swath_height_l > 0) 363 + log2_swath_height_l -= 1; 364 + 365 + if (swath_height_c > 0) 366 + log2_swath_height_c = dml_log2(swath_height_c); 367 + 368 + if (req128_c && log2_swath_height_c > 0) 369 + log2_swath_height_c -= 1; 353 370 } 371 + 354 372 rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; 355 373 rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; 356 374