Skip to content

Commit abde491

Browse files
srishanmalexdeucher
authored andcommitted
drm/amd/display: Fix out-of-bounds stream encoder index v3
eng_id can be negative and that stream_enc_regs[] can be indexed out of bounds. eng_id is used directly as an index into stream_enc_regs[], which has only 5 entries. When eng_id is 5 (ENGINE_ID_DIGF) or negative, this can access memory past the end of the array. Add a bounds check using ARRAY_SIZE() before using eng_id as an index. The unsigned cast also rejects negative values. This avoids out-of-bounds access. Fixes the below smatch error: dcn*_resource.c: stream_encoder_create() may index stream_enc_regs[eng_id] out of bounds (size 5). drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn351/dcn351_resource.c 1246 static struct stream_encoder *dcn35_stream_encoder_create( 1247 enum engine_id eng_id, 1248 struct dc_context *ctx) 1249 { ... 1255 1256 /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ 1257 if (eng_id <= ENGINE_ID_DIGF) { ENGINE_ID_DIGF is 5. should <= be <? Unrelated but, ugh, why is Smatch saying that "eng_id" can be negative? end_id is type signed long, but there are checks in the caller which prevent it from being negative. 1258 vpg_inst = eng_id; 1259 afmt_inst = eng_id; 1260 } else 1261 return NULL; 1262 ... 1281 1282 dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, 1283 eng_id, vpg, afmt, --> 1284 &stream_enc_regs[eng_id], ^^^^^^^^^^^^^^^^^^^^^^^ This stream_enc_regs[] array has 5 elements so we are one element beyond the end of the array. ... 1287 return &enc1->base; 1288 } v2: use explicit bounds check as suggested by Roman/Dan; avoid unsigned int cast v3: The compiler already knows how to compare the two values, so the cast (int) is not needed. (Roman) Fixes: 2728e9c ("drm/amd/display: add DC changes for DCN351") Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Mario Limonciello <superm1@kernel.org> Cc: Alex Hung <alex.hung@amd.com> Cc: Aurabindo Pillai <aurabindo.pillai@amd.com> Cc: ChiaHsuan Chung <chiahsuan.chung@amd.com> Cc: Roman Li <roman.li@amd.com> Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> Reviewed-by: Roman Li <roman.li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 8446c74 commit abde491

6 files changed

Lines changed: 24 additions & 24 deletions

File tree

drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,12 +1230,12 @@ static struct stream_encoder *dcn315_stream_encoder_create(
12301230
/*PHYB is wired off in HW, allow front end to remapping, otherwise needs more changes*/
12311231

12321232
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1233-
if (eng_id <= ENGINE_ID_DIGF) {
1234-
vpg_inst = eng_id;
1235-
afmt_inst = eng_id;
1236-
} else
1233+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
12371234
return NULL;
12381235

1236+
vpg_inst = eng_id;
1237+
afmt_inst = eng_id;
1238+
12391239
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12401240
vpg = dcn31_vpg_create(ctx, vpg_inst);
12411241
afmt = dcn31_afmt_create(ctx, afmt_inst);

drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,12 +1223,12 @@ static struct stream_encoder *dcn316_stream_encoder_create(
12231223
int afmt_inst;
12241224

12251225
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1226-
if (eng_id <= ENGINE_ID_DIGF) {
1227-
vpg_inst = eng_id;
1228-
afmt_inst = eng_id;
1229-
} else
1226+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
12301227
return NULL;
12311228

1229+
vpg_inst = eng_id;
1230+
afmt_inst = eng_id;
1231+
12321232
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12331233
vpg = dcn31_vpg_create(ctx, vpg_inst);
12341234
afmt = dcn31_afmt_create(ctx, afmt_inst);

drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,12 +1211,12 @@ static struct stream_encoder *dcn32_stream_encoder_create(
12111211
int afmt_inst;
12121212

12131213
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1214-
if (eng_id <= ENGINE_ID_DIGF) {
1215-
vpg_inst = eng_id;
1216-
afmt_inst = eng_id;
1217-
} else
1214+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
12181215
return NULL;
12191216

1217+
vpg_inst = eng_id;
1218+
afmt_inst = eng_id;
1219+
12201220
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12211221
vpg = dcn32_vpg_create(ctx, vpg_inst);
12221222
afmt = dcn32_afmt_create(ctx, afmt_inst);

drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,12 +1192,12 @@ static struct stream_encoder *dcn321_stream_encoder_create(
11921192
int afmt_inst;
11931193

11941194
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1195-
if (eng_id <= ENGINE_ID_DIGF) {
1196-
vpg_inst = eng_id;
1197-
afmt_inst = eng_id;
1198-
} else
1195+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
11991196
return NULL;
12001197

1198+
vpg_inst = eng_id;
1199+
afmt_inst = eng_id;
1200+
12011201
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12021202
vpg = dcn321_vpg_create(ctx, vpg_inst);
12031203
afmt = dcn321_afmt_create(ctx, afmt_inst);

drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,12 +1274,12 @@ static struct stream_encoder *dcn35_stream_encoder_create(
12741274
int afmt_inst;
12751275

12761276
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1277-
if (eng_id <= ENGINE_ID_DIGF) {
1278-
vpg_inst = eng_id;
1279-
afmt_inst = eng_id;
1280-
} else
1277+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
12811278
return NULL;
12821279

1280+
vpg_inst = eng_id;
1281+
afmt_inst = eng_id;
1282+
12831283
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12841284
vpg = dcn31_vpg_create(ctx, vpg_inst);
12851285
afmt = dcn31_afmt_create(ctx, afmt_inst);

drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,12 +1254,12 @@ static struct stream_encoder *dcn35_stream_encoder_create(
12541254
int afmt_inst;
12551255

12561256
/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1257-
if (eng_id <= ENGINE_ID_DIGF) {
1258-
vpg_inst = eng_id;
1259-
afmt_inst = eng_id;
1260-
} else
1257+
if (eng_id < 0 || eng_id >= ARRAY_SIZE(stream_enc_regs))
12611258
return NULL;
12621259

1260+
vpg_inst = eng_id;
1261+
afmt_inst = eng_id;
1262+
12631263
enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12641264
vpg = dcn31_vpg_create(ctx, vpg_inst);
12651265
afmt = dcn31_afmt_create(ctx, afmt_inst);

0 commit comments

Comments
 (0)