1 /*
2  * Copyright (C) 2014-2017 ARM Limited. All rights reserved.
3  *
4  * Copyright (C) 2008 The Android Open Source Project
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <cutils/ashmem.h>
20 #include <log/log.h>
21 #include <sys/mman.h>
22 
23 #if GRALLOC_USE_GRALLOC1_API == 1
24 #include <hardware/gralloc1.h>
25 #else
26 #include <hardware/gralloc.h>
27 #endif
28 
29 #include "mali_gralloc_module.h"
30 #include "mali_gralloc_private_interface_types.h"
31 #include "mali_gralloc_buffer.h"
32 #include "gralloc_buffer_priv.h"
33 
34 /*
35  * Allocate shared memory for attribute storage. Only to be
36  * used by gralloc internally.
37  *
38  * Return 0 on success.
39  */
gralloc_buffer_attr_allocate(private_handle_t * hnd)40 int gralloc_buffer_attr_allocate(private_handle_t *hnd)
41 {
42 	int rval = -1;
43 	const size_t page_size = getpagesize();
44 
45 	if (!hnd)
46 	{
47 		goto out;
48 	}
49 
50 	if (hnd->share_attr_fd >= 0)
51 	{
52 		ALOGW("Warning share attribute fd already exists during create. Closing.");
53 		close(hnd->share_attr_fd);
54 	}
55 
56 	hnd->share_attr_fd = ashmem_create_region("gralloc_shared_attr", page_size);
57 
58 	if (hnd->share_attr_fd < 0)
59 	{
60 		ALOGE("Failed to allocate page for shared attribute region");
61 		goto err_ashmem;
62 	}
63 
64 	/*
65 	 * Default protection on the shm region is PROT_EXEC | PROT_READ | PROT_WRITE.
66 	 *
67 	 * Personality flag READ_IMPLIES_EXEC which is used by some processes, namely gdbserver,
68 	 * causes a mmap with PROT_READ to be translated to PROT_READ | PROT_EXEC.
69 	 *
70 	 * If we were to drop PROT_EXEC here with a call to ashmem_set_prot_region()
71 	 * this can potentially cause clients to fail importing this gralloc attribute buffer
72 	 * with EPERM error since PROT_EXEC is not allowed.
73 	 *
74 	 * Because of this we keep the PROT_EXEC flag.
75 	 */
76 
77 	hnd->attr_base = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, hnd->share_attr_fd, 0);
78 
79 	if (hnd->attr_base != MAP_FAILED)
80 	{
81 		/* The attribute region contains signed integers only.
82 		 * The reason for this is because we can set a value less than 0 for
83 		 * not-initialized values.
84 		 */
85 		attr_region *region = (attr_region *)hnd->attr_base;
86 
87 		memset(hnd->attr_base, 0xff, page_size);
88 		munmap(hnd->attr_base, page_size);
89 		hnd->attr_base = MAP_FAILED;
90 	}
91 	else
92 	{
93 		ALOGE("Failed to mmap shared attribute region");
94 		goto err_ashmem;
95 	}
96 
97 	rval = 0;
98 	goto out;
99 
100 err_ashmem:
101 
102 	if (hnd->share_attr_fd >= 0)
103 	{
104 		close(hnd->share_attr_fd);
105 		hnd->share_attr_fd = -1;
106 	}
107 
108 out:
109 	return rval;
110 }
111 
112 /*
113  * Frees the shared memory allocated for attribute storage.
114  * Only to be used by gralloc internally.
115 
116  * Return 0 on success.
117  */
gralloc_buffer_attr_free(private_handle_t * hnd)118 int gralloc_buffer_attr_free(private_handle_t *hnd)
119 {
120 	int rval = -1;
121 
122 	if (!hnd)
123 	{
124 		goto out;
125 	}
126 
127 	if (hnd->share_attr_fd < 0)
128 	{
129 		ALOGE("Shared attribute region not avail to free");
130 		goto out;
131 	}
132 
133 	if (hnd->attr_base != MAP_FAILED)
134 	{
135 		ALOGW("Warning shared attribute region mapped at free. Unmapping");
136 		munmap(hnd->attr_base, getpagesize());
137 		hnd->attr_base = MAP_FAILED;
138 	}
139 
140 	close(hnd->share_attr_fd);
141 	hnd->share_attr_fd = -1;
142 	rval = 0;
143 
144 out:
145 	return rval;
146 }
147