xref: /aosp_15_r20/cts/hostsidetests/securitybulletin/securityPatch/CVE-2023-4272/poc.c (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <mali_gpu_utils.h>
18 
19 #include "../includes/common.h"
20 
21 struct base_mem_import_user_buffer {
22     __u64 ptr;
23     __u64 length;
24 };
25 
26 union kbase_ioctl_mem_import {
27     struct {
28         __u64 flags;
29         __u64 phandle;
30         __u32 type;
31         __u32 padding;
32     } in;
33     struct {
34         __u64 flags;
35         __u64 gpu_va;
36         __u64 va_pages;
37     } out;
38 };
39 
40 #define KBASE_IOCTL_MEM_IMPORT _IOWR(KBASE_IOCTL_TYPE, 22, union kbase_ioctl_mem_import)
41 
main(void)42 int main(void) {
43     const size_t page_size = getpagesize();
44     int mali_fd = open("/dev/mali0", O_RDWR);
45     if (mali_fd < 0) {
46         printf("Failed to open /dev/mali0!");
47         return EXIT_FAILURE;
48     }
49 
50     mali_gpu_info gpu_info = {
51             .is_csf = false,
52             .version = 0,
53             .tracking_page = NULL,
54     };
55 
56     // This bug affects both CSF and non-CSF versions. Hence, version check is not needed
57     if (initialize_mali_gpu(mali_fd, &gpu_info) == EXIT_FAILURE) {
58         return EXIT_FAILURE;
59     }
60 
61     // make a single-page anonymous mapping
62     void *anon_mapping =
63             mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
64     if (anon_mapping == MAP_FAILED) {
65         printf("mmap failed!");
66         teardown(&gpu_info);
67         return EXIT_FAILURE;
68     }
69 
70     // Create a KBASE_MEM_TYPE_IMPORTED_USER_BUF that refers to the anonymous
71     // mapping's address range.
72     struct base_mem_import_user_buffer ubuf = {.ptr = (unsigned long)anon_mapping, .length = 128};
73     union kbase_ioctl_mem_import mi = {.in = {
74                                                .flags = 0xf /* CPU+GPU R+W */,
75                                                .phandle = (unsigned long)&ubuf,
76                                                .type = 3 /* BASE_MEM_IMPORT_TYPE_USER_BUFFER */
77                                        }};
78 
79     // USER_BUFFER must be CPU cached. Without fix, the user buffer mapping is created.
80     // With fix, the ioctl call fails and returns an error value
81     int result = ioctl(mali_fd, KBASE_IOCTL_MEM_IMPORT, &mi);
82 
83     // free the allocated memory
84     munmap(anon_mapping, page_size);
85     teardown(&gpu_info);
86 
87     if (result == 0) {
88         printf("Driver vulnerable to b/296910715!");
89         return EXIT_VULNERABLE;
90     }
91     return EXIT_SUCCESS;
92 }
93