KERNEL SECURITY FLAWS (0day for nexus4)

About a month ago, when I was looking at the android kernle source code, I found a strange logic, it could trigger the device crash by bypassing the detection logic. I test it in Nexus 4 and the security patch level is 20161005.

The last_kmsg:

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
[  510.188720] Unable to handle kernel paging request at virtual address 40404040
[ 510.188873] pgd = e453c000
[ 510.188934] [40404040] *pgd=00000000
[ 510.189422] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
[ 510.189575] CPU: 0 Not tainted (3.4.0-cyanogenmod-g756c08a #1)
[ 510.189636] PC is at memcmp+0x14/0x34
[ 510.189727] LR is at iw_set_band_config+0x2c/0x58
[ 510.189849] pc : [<c037573c>] lr : [<c0615260>] psr: 80000013
[ 510.189849] sp : e6567e44 ip : 00000000 fp : c09864e8
[ 510.190032] r10: c0615234 r9 : 00000001 r8 : c09c94e8
[ 510.190124] r7 : 0000004b r6 : 00000000 r5 : 40404040 r4 : 40404040
[ 510.190246] r3 : 00000000 r2 : 00000008 r1 : c0b7ef56 r0 : 40404040
[ 510.190368] Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 510.190429] Control: 10c5787d Table: a633c06a DAC: 00000015
[ 510.190551]
[ 510.190582] PC: 0xc03756bc:
[ 510.190704] 56bc e3520000 1afffff3 e3a00001 e8bd8010 e5d03000 e353004e 0a00000e
...
[ 510.232727] [<c037573c>] (memcmp+0x14/0x34) from [<c0615260>] (iw_set_band_config+0x2c/0x58)
[ 510.232788] [<c0615260>] (iw_set_band_config+0x2c/0x58) from [<c08bcdf8>] (ioctl_private_call+0xdc/0x278)
[ 510.232940] [<c08bcdf8>] (ioctl_private_call+0xdc/0x278) from [<c08bc788>] (wext_handle_ioctl+0x1cc/0x1e4)
[ 510.233062] [<c08bc788>] (wext_handle_ioctl+0x1cc/0x1e4) from [<c078cb6c>] (dev_ioctl+0x65c/0x6a0)
[ 510.233215] [<c078cb6c>] (dev_ioctl+0x65c/0x6a0) from [<c0232288>] (vfs_ioctl+0x28/0x3c)
[ 510.233337] [<c0232288>] (vfs_ioctl+0x28/0x3c) from [<c0232ccc>] (do_vfs_ioctl+0x484/0x574)
[ 510.233428] [<c0232ccc>] (do_vfs_ioctl+0x484/0x574) from [<c0232e04>] (sys_ioctl+0x48/0x74)
[ 510.233551] [<c0232e04>] (sys_ioctl+0x48/0x74) from [<c0105a00>] (ret_fast_syscall+0x0/0x30)
[ 510.233673] Code: e3a03000 e1a05000 e1530002 0a000005 (e7d54003)
[ 510.245880] ---[ end trace 8731deb30c10132d ]---
[ 510.246643] Kernel panic - not syncing: Fatal exception
[ 511.518859] wcnss_8960: crash shutdown : 0
[ 515.030487] Rebooting in 5 seconds..
[ 520.046020] Going down for restart now
[ 520.046325] in panic

No errors detected
Boot info:
Last boot reason: kernel_panic

so I write a POC and report this security issue to google.

Soon, I received a reply.

1
2
3
4
5
6
7
Hey,

The Nexus 4 is no longer being supported and this vulnerability does not affect any other Nexus devices. Closing issue.

Thanks,

Android Security Team

I think they are not going to look at the root cause of the problem.

As we knows, the socket func could be called by ioctl, the ioctl last call func is ioctl_private_iw_point.

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
static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd,
const struct iw_priv_args *descr,
iw_handler handler, struct net_device *dev,
struct iw_request_info *info, int extra_size)

{

char *extra;
int err;
if (IW_IS_SET(cmd)) { // is set op
if (!iwp->pointer && iwp->length != 0) // set iwp->pointer = 0x40404040 && iwp->length = 0, pass this check
return -EFAULT;
if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK))
return -E2BIG;
} else if (!iwp->pointer)
return -EFAULT;
extra = kmalloc(extra_size, GFP_KERNEL);
if (!extra)
return -ENOMEM;

// If it is a SET, get all the extra data in here
if (IW_IS_SET(cmd) && (iwp->length != 0)) { // pass this check because of iwp->length = 0
if (copy_from_user(extra, iwp->pointer, extra_size)) {
err = -EFAULT;
goto out;
}
}

// Call the handler
// pass all check but iwp->pointer is not valid, will casue a security issue.
err = handler(dev, info, (union iwreq_data *) iwp, extra);
}

when i set iwp->pointer = 0x40404040 && iwp->length = 0 but not map 0x40404040,
it will pass all check like comment.
Once func uses this pointer(not map)and does not detect whether it is valid, it will casue a security issue. and this issue code logic (ioctl_private_iw_point) appeared in all kernel.

by chance, I found the proof in wlan_hdd_wext.c of nexus4.
all func listed below in wlan_hdd_wext.c module (nuxus4) will cause kernel panic.

1
2
3
4
5
6
7
8
9
10
iw_set_priv,
iw_qcom_set_wapi_mode,
iw_set_keepalive_params,
iw_set_packet_filter_params,
iw_set_band_config,
iw_set_dynamic_mcbc_filter,
iw_setchar_getnone,
iw_qcom_set_wapi_bkid,
iw_set_host_offload
...

I gave them the root cause of the above problem. and I say, you can say is a security flaws and the next level func should check this pointer. I only give you a proof by wlan_hdd_wext.c module in nexus4, maybe other modules will appear later. After all, there are still a lot of careless programmers in the world. If you still believe that is not a security issue, i will public it in my blog or other social platform.

Soon, I received a reply.

1
2
3
4
5
Hey,

We reviewed your latest comments and the code you reference is different in all our other Nexus devices. In those devices, there are adequate checks in place to prevent this issue. We still believe this is not a security issue.

Thanks,

so, it is really a sad story?