diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2017-01-03 01:59:53 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-01-06 12:13:58 -0500 |
commit | 0b9a4411aaed0939f4886e7e2641b8a60bfb34bd (patch) | |
tree | e4fbd954d0f6513d8dab8911f6ac1cfa01bb21d1 /drivers/gpu/nvgpu | |
parent | 67fc4629892ab60d6335752b93d883ef690f1ea4 (diff) |
gpu: nvgpu: fix out-of-bound access on gr->map_tiles
Fix slab-out-of-bounds issue reported by KASAN
[ 28.464077] BUG: KASAN: slab-out-of-bounds in
gr_gk20a_init_map_tiles+0x624/0x708 at addr ffffffc1a098ee01
...
[ 28.503241] INFO: Allocated in gr_gk20a_init_map_tiles+0x2dc/0x708
age=11 cpu=5 pid=1
out-of-bound access from below 3 stacks :
[1]
[ 28.782886] [<ffffffc0007d5f64>] gr_gk20a_init_map_tiles+0x624/0x708
[ 28.789228] [<ffffffc0007eadf0>] gk20a_init_gr_support+0x2d0/0xeb0
[ 28.795397] [<ffffffc00079d9c8>]
gk20a_pm_finalize_poweron+0x738/0xd10
[2]
[ 29.268070] [<ffffffc0007d618c>] gr_gk20a_zcull_init_hw+0x144/0x730
[ 29.274329] [<ffffffc0007d6a00>] gk20a_init_gr_setup_hw+0x288/0x1530
[ 29.280677] [<ffffffc0007eac6c>] gk20a_init_gr_support+0x14c/0xeb0
[ 29.286938] [<ffffffc00079d9c8>]
gk20a_pm_finalize_poweron+0x738/0xd10
[3]
[ 50.076223] [<ffffffc000d1df14>]
gr_gk20a_setup_rop_mapping+0x5e4/0x2018
[ 50.082913] [<ffffffc000d2559c>] gr_gk20a_init_fs_state+0x80c/0x1028
[ 50.089259] [<ffffffc000ddcbc8>] gr_gm20b_init_fs_state+0xc8/0x960
[ 50.095430] [<ffffffc000e413f8>] gr_gp10b_init_fs_state+0x5c0/0x5d8
[ 50.101687] [<ffffffc000d2ed30>] gk20a_init_gr_setup_hw+0x1b48/0x2418
[ 50.108115] [<ffffffc000d50bc0>] gk20a_init_gr_support+0x19e0/0x1ab0
[ 50.114457] [<ffffffc000cc7af8>]
gk20a_pm_finalize_poweron+0xd20/0x1558
Fix this by adding below
- allocate gr->map_tiles[] with size of (num_gpc * num_tpc_per_gpc)
intead of num_gpc
- add new static API gr_gk20a_get_map_tile_count() which returns
tile count for given index, and returns 0 for out-of-bounds access
Bug 200257557
Change-Id: If572837ffb661f92a21be5ce855d0146b2609cb0
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1279411
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 104 |
1 files changed, 60 insertions, 44 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index ceb3cb18..39562ec1 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A Graphics | 2 | * GK20A Graphics |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -1028,6 +1028,18 @@ int gr_gk20a_commit_global_timeslice(struct gk20a *g, struct channel_gk20a *c, | |||
1028 | return 0; | 1028 | return 0; |
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | /* | ||
1032 | * Return map tiles count for given index | ||
1033 | * Return 0 if index is out-of-bounds | ||
1034 | */ | ||
1035 | static u32 gr_gk20a_get_map_tile_count(struct gr_gk20a *gr, u32 index) | ||
1036 | { | ||
1037 | if (index >= gr->map_tile_count) | ||
1038 | return 0; | ||
1039 | |||
1040 | return gr->map_tiles[index]; | ||
1041 | } | ||
1042 | |||
1031 | int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr) | 1043 | int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr) |
1032 | { | 1044 | { |
1033 | u32 norm_entries, norm_shift; | 1045 | u32 norm_entries, norm_shift; |
@@ -1043,43 +1055,43 @@ int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr) | |||
1043 | gr_crstr_map_table_cfg_row_offset_f(gr->map_row_offset) | | 1055 | gr_crstr_map_table_cfg_row_offset_f(gr->map_row_offset) | |
1044 | gr_crstr_map_table_cfg_num_entries_f(gr->tpc_count)); | 1056 | gr_crstr_map_table_cfg_num_entries_f(gr->tpc_count)); |
1045 | 1057 | ||
1046 | map0 = gr_crstr_gpc_map0_tile0_f(gr->map_tiles[0]) | | 1058 | map0 = gr_crstr_gpc_map0_tile0_f(gr_gk20a_get_map_tile_count(gr, 0)) | |
1047 | gr_crstr_gpc_map0_tile1_f(gr->map_tiles[1]) | | 1059 | gr_crstr_gpc_map0_tile1_f(gr_gk20a_get_map_tile_count(gr, 1)) | |
1048 | gr_crstr_gpc_map0_tile2_f(gr->map_tiles[2]) | | 1060 | gr_crstr_gpc_map0_tile2_f(gr_gk20a_get_map_tile_count(gr, 2)) | |
1049 | gr_crstr_gpc_map0_tile3_f(gr->map_tiles[3]) | | 1061 | gr_crstr_gpc_map0_tile3_f(gr_gk20a_get_map_tile_count(gr, 3)) | |
1050 | gr_crstr_gpc_map0_tile4_f(gr->map_tiles[4]) | | 1062 | gr_crstr_gpc_map0_tile4_f(gr_gk20a_get_map_tile_count(gr, 4)) | |
1051 | gr_crstr_gpc_map0_tile5_f(gr->map_tiles[5]); | 1063 | gr_crstr_gpc_map0_tile5_f(gr_gk20a_get_map_tile_count(gr, 5)); |
1052 | 1064 | ||
1053 | map1 = gr_crstr_gpc_map1_tile6_f(gr->map_tiles[6]) | | 1065 | map1 = gr_crstr_gpc_map1_tile6_f(gr_gk20a_get_map_tile_count(gr, 6)) | |
1054 | gr_crstr_gpc_map1_tile7_f(gr->map_tiles[7]) | | 1066 | gr_crstr_gpc_map1_tile7_f(gr_gk20a_get_map_tile_count(gr, 7)) | |
1055 | gr_crstr_gpc_map1_tile8_f(gr->map_tiles[8]) | | 1067 | gr_crstr_gpc_map1_tile8_f(gr_gk20a_get_map_tile_count(gr, 8)) | |
1056 | gr_crstr_gpc_map1_tile9_f(gr->map_tiles[9]) | | 1068 | gr_crstr_gpc_map1_tile9_f(gr_gk20a_get_map_tile_count(gr, 9)) | |
1057 | gr_crstr_gpc_map1_tile10_f(gr->map_tiles[10]) | | 1069 | gr_crstr_gpc_map1_tile10_f(gr_gk20a_get_map_tile_count(gr, 10)) | |
1058 | gr_crstr_gpc_map1_tile11_f(gr->map_tiles[11]); | 1070 | gr_crstr_gpc_map1_tile11_f(gr_gk20a_get_map_tile_count(gr, 11)); |
1059 | 1071 | ||
1060 | map2 = gr_crstr_gpc_map2_tile12_f(gr->map_tiles[12]) | | 1072 | map2 = gr_crstr_gpc_map2_tile12_f(gr_gk20a_get_map_tile_count(gr, 12)) | |
1061 | gr_crstr_gpc_map2_tile13_f(gr->map_tiles[13]) | | 1073 | gr_crstr_gpc_map2_tile13_f(gr_gk20a_get_map_tile_count(gr, 13)) | |
1062 | gr_crstr_gpc_map2_tile14_f(gr->map_tiles[14]) | | 1074 | gr_crstr_gpc_map2_tile14_f(gr_gk20a_get_map_tile_count(gr, 14)) | |
1063 | gr_crstr_gpc_map2_tile15_f(gr->map_tiles[15]) | | 1075 | gr_crstr_gpc_map2_tile15_f(gr_gk20a_get_map_tile_count(gr, 15)) | |
1064 | gr_crstr_gpc_map2_tile16_f(gr->map_tiles[16]) | | 1076 | gr_crstr_gpc_map2_tile16_f(gr_gk20a_get_map_tile_count(gr, 16)) | |
1065 | gr_crstr_gpc_map2_tile17_f(gr->map_tiles[17]); | 1077 | gr_crstr_gpc_map2_tile17_f(gr_gk20a_get_map_tile_count(gr, 17)); |
1066 | 1078 | ||
1067 | map3 = gr_crstr_gpc_map3_tile18_f(gr->map_tiles[18]) | | 1079 | map3 = gr_crstr_gpc_map3_tile18_f(gr_gk20a_get_map_tile_count(gr, 18)) | |
1068 | gr_crstr_gpc_map3_tile19_f(gr->map_tiles[19]) | | 1080 | gr_crstr_gpc_map3_tile19_f(gr_gk20a_get_map_tile_count(gr, 19)) | |
1069 | gr_crstr_gpc_map3_tile20_f(gr->map_tiles[20]) | | 1081 | gr_crstr_gpc_map3_tile20_f(gr_gk20a_get_map_tile_count(gr, 20)) | |
1070 | gr_crstr_gpc_map3_tile21_f(gr->map_tiles[21]) | | 1082 | gr_crstr_gpc_map3_tile21_f(gr_gk20a_get_map_tile_count(gr, 21)) | |
1071 | gr_crstr_gpc_map3_tile22_f(gr->map_tiles[22]) | | 1083 | gr_crstr_gpc_map3_tile22_f(gr_gk20a_get_map_tile_count(gr, 22)) | |
1072 | gr_crstr_gpc_map3_tile23_f(gr->map_tiles[23]); | 1084 | gr_crstr_gpc_map3_tile23_f(gr_gk20a_get_map_tile_count(gr, 23)); |
1073 | 1085 | ||
1074 | map4 = gr_crstr_gpc_map4_tile24_f(gr->map_tiles[24]) | | 1086 | map4 = gr_crstr_gpc_map4_tile24_f(gr_gk20a_get_map_tile_count(gr, 24)) | |
1075 | gr_crstr_gpc_map4_tile25_f(gr->map_tiles[25]) | | 1087 | gr_crstr_gpc_map4_tile25_f(gr_gk20a_get_map_tile_count(gr, 25)) | |
1076 | gr_crstr_gpc_map4_tile26_f(gr->map_tiles[26]) | | 1088 | gr_crstr_gpc_map4_tile26_f(gr_gk20a_get_map_tile_count(gr, 26)) | |
1077 | gr_crstr_gpc_map4_tile27_f(gr->map_tiles[27]) | | 1089 | gr_crstr_gpc_map4_tile27_f(gr_gk20a_get_map_tile_count(gr, 27)) | |
1078 | gr_crstr_gpc_map4_tile28_f(gr->map_tiles[28]) | | 1090 | gr_crstr_gpc_map4_tile28_f(gr_gk20a_get_map_tile_count(gr, 28)) | |
1079 | gr_crstr_gpc_map4_tile29_f(gr->map_tiles[29]); | 1091 | gr_crstr_gpc_map4_tile29_f(gr_gk20a_get_map_tile_count(gr, 29)); |
1080 | 1092 | ||
1081 | map5 = gr_crstr_gpc_map5_tile30_f(gr->map_tiles[30]) | | 1093 | map5 = gr_crstr_gpc_map5_tile30_f(gr_gk20a_get_map_tile_count(gr, 30)) | |
1082 | gr_crstr_gpc_map5_tile31_f(gr->map_tiles[31]) | | 1094 | gr_crstr_gpc_map5_tile31_f(gr_gk20a_get_map_tile_count(gr, 31)) | |
1083 | gr_crstr_gpc_map5_tile32_f(0) | | 1095 | gr_crstr_gpc_map5_tile32_f(0) | |
1084 | gr_crstr_gpc_map5_tile33_f(0) | | 1096 | gr_crstr_gpc_map5_tile33_f(0) | |
1085 | gr_crstr_gpc_map5_tile34_f(0) | | 1097 | gr_crstr_gpc_map5_tile34_f(0) | |
@@ -3658,6 +3670,7 @@ static int gr_gk20a_init_map_tiles(struct gk20a *g, struct gr_gk20a *gr) | |||
3658 | int ret = 0; | 3670 | int ret = 0; |
3659 | int num_gpcs = nvgpu_get_litter_value(g, GPU_LIT_NUM_GPCS); | 3671 | int num_gpcs = nvgpu_get_litter_value(g, GPU_LIT_NUM_GPCS); |
3660 | int num_tpc_per_gpc = nvgpu_get_litter_value(g, GPU_LIT_NUM_TPC_PER_GPC); | 3672 | int num_tpc_per_gpc = nvgpu_get_litter_value(g, GPU_LIT_NUM_TPC_PER_GPC); |
3673 | int map_tile_count = num_gpcs * num_tpc_per_gpc; | ||
3661 | 3674 | ||
3662 | init_frac = kzalloc(num_gpcs * sizeof(s32), GFP_KERNEL); | 3675 | init_frac = kzalloc(num_gpcs * sizeof(s32), GFP_KERNEL); |
3663 | init_err = kzalloc(num_gpcs * sizeof(s32), GFP_KERNEL); | 3676 | init_err = kzalloc(num_gpcs * sizeof(s32), GFP_KERNEL); |
@@ -3721,7 +3734,8 @@ static int gr_gk20a_init_map_tiles(struct gk20a *g, struct gr_gk20a *gr) | |||
3721 | delete_map = true; | 3734 | delete_map = true; |
3722 | 3735 | ||
3723 | for (tile_count = 0; tile_count < gr->map_tile_count; tile_count++) { | 3736 | for (tile_count = 0; tile_count < gr->map_tile_count; tile_count++) { |
3724 | if ((u32)gr->map_tiles[tile_count] >= gr->tpc_count) | 3737 | if (gr_gk20a_get_map_tile_count(gr, tile_count) |
3738 | >= gr->tpc_count) | ||
3725 | delete_map = true; | 3739 | delete_map = true; |
3726 | } | 3740 | } |
3727 | 3741 | ||
@@ -3733,13 +3747,13 @@ static int gr_gk20a_init_map_tiles(struct gk20a *g, struct gr_gk20a *gr) | |||
3733 | } | 3747 | } |
3734 | 3748 | ||
3735 | if (gr->map_tiles == NULL) { | 3749 | if (gr->map_tiles == NULL) { |
3736 | gr->map_tile_count = num_gpcs; | 3750 | gr->map_tiles = kzalloc(map_tile_count * sizeof(u8), |
3737 | 3751 | GFP_KERNEL); | |
3738 | gr->map_tiles = kzalloc(num_gpcs * sizeof(u8), GFP_KERNEL); | ||
3739 | if (gr->map_tiles == NULL) { | 3752 | if (gr->map_tiles == NULL) { |
3740 | ret = -ENOMEM; | 3753 | ret = -ENOMEM; |
3741 | goto clean_up; | 3754 | goto clean_up; |
3742 | } | 3755 | } |
3756 | gr->map_tile_count = map_tile_count; | ||
3743 | 3757 | ||
3744 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { | 3758 | for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { |
3745 | sorted_num_tpcs[gpc_index] = gr->gpc_tpc_count[gpc_index]; | 3759 | sorted_num_tpcs[gpc_index] = gr->gpc_tpc_count[gpc_index]; |
@@ -4508,6 +4522,7 @@ static int gr_gk20a_zcull_init_hw(struct gk20a *g, struct gr_gk20a *gr) | |||
4508 | u32 num_tpc_per_gpc = nvgpu_get_litter_value(g, | 4522 | u32 num_tpc_per_gpc = nvgpu_get_litter_value(g, |
4509 | GPU_LIT_NUM_TPC_PER_GPC); | 4523 | GPU_LIT_NUM_TPC_PER_GPC); |
4510 | u32 zcull_alloc_num = num_gpcs * num_tpc_per_gpc; | 4524 | u32 zcull_alloc_num = num_gpcs * num_tpc_per_gpc; |
4525 | u32 map_tile_count; | ||
4511 | 4526 | ||
4512 | if (!gr->map_tiles) | 4527 | if (!gr->map_tiles) |
4513 | return -1; | 4528 | return -1; |
@@ -4534,9 +4549,10 @@ static int gr_gk20a_zcull_init_hw(struct gk20a *g, struct gr_gk20a *gr) | |||
4534 | } | 4549 | } |
4535 | 4550 | ||
4536 | for (map_counter = 0; map_counter < gr->tpc_count; map_counter++) { | 4551 | for (map_counter = 0; map_counter < gr->tpc_count; map_counter++) { |
4552 | map_tile_count = gr_gk20a_get_map_tile_count(gr, map_counter); | ||
4537 | zcull_map_tiles[map_counter] = | 4553 | zcull_map_tiles[map_counter] = |
4538 | zcull_bank_counters[gr->map_tiles[map_counter]]; | 4554 | zcull_bank_counters[map_tile_count]; |
4539 | zcull_bank_counters[gr->map_tiles[map_counter]]++; | 4555 | zcull_bank_counters[map_tile_count]++; |
4540 | } | 4556 | } |
4541 | 4557 | ||
4542 | if (g->ops.gr.program_zcull_mapping) | 4558 | if (g->ops.gr.program_zcull_mapping) |