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