1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ashmem_impl.h"
17
18 #include <cinttypes>
19 #include <limits>
20 #include <unistd.h>
21
22 namespace OHOS {
23 static constexpr int MMAP_PROT_MAX = AshmemImpl::PROT_EXEC | AshmemImpl::PROT_READ | AshmemImpl::PROT_WRITE;
24
AshmemImpl(sptr<Ashmem> ashmem)25 AshmemImpl::AshmemImpl(sptr<Ashmem> ashmem) : ashmem_(ashmem)
26 {
27 if (ashmem == nullptr) {
28 ZLOGE(LOG_LABEL, "ashmem is null");
29 }
30 }
31
CloseAshmem()32 void AshmemImpl::CloseAshmem()
33 {
34 if (ashmem_ == nullptr) {
35 ZLOGE(LOG_LABEL, "ashmem is null");
36 return;
37 }
38 ashmem_->CloseAshmem();
39 }
40
GetAshmemSize(int32_t * errCode)41 int32_t AshmemImpl::GetAshmemSize(int32_t* errCode)
42 {
43 if (ashmem_ == nullptr) {
44 ZLOGE(LOG_LABEL, "ashmem is null");
45 *errCode = errorDesc::CHECK_PARAM_ERROR;
46 return 0;
47 }
48 return ashmem_->GetAshmemSize();
49 }
50
MapTypedAshmem(uint32_t mapType)51 int32_t AshmemImpl::MapTypedAshmem(uint32_t mapType)
52 {
53 if (mapType > MMAP_PROT_MAX) {
54 ZLOGE(LOG_LABEL, "ashmem mapType error");
55 return errorDesc::CHECK_PARAM_ERROR;
56 }
57
58 if (ashmem_ == nullptr) {
59 ZLOGE(LOG_LABEL, "ashmem is null");
60 return errorDesc::OS_MMAP_ERROR;
61 }
62 ashmem_->MapAshmem(mapType);
63 return 0;
64 }
65
MapReadWriteAshmem()66 int32_t AshmemImpl::MapReadWriteAshmem()
67 {
68 if (ashmem_ == nullptr) {
69 ZLOGE(LOG_LABEL, "ashmem is null");
70 return errorDesc::OS_MMAP_ERROR;
71 }
72 ashmem_->MapReadAndWriteAshmem();
73 return 0;
74 }
75
MapReadonlyAshmem()76 int32_t AshmemImpl::MapReadonlyAshmem()
77 {
78 if (ashmem_ == nullptr) {
79 ZLOGE(LOG_LABEL, "ashmem is null");
80 return errorDesc::OS_MMAP_ERROR;
81 }
82 ashmem_->MapReadOnlyAshmem();
83 return 0;
84 }
85
SetProtectionType(uint32_t protectionType)86 int32_t AshmemImpl::SetProtectionType(uint32_t protectionType)
87 {
88 if (ashmem_ == nullptr) {
89 ZLOGE(LOG_LABEL, "ashmem is null");
90 return errorDesc::OS_IOCTL_ERROR;
91 }
92 ashmem_->SetProtection(protectionType);
93 return 0;
94 }
95
UnmapAshmem()96 void AshmemImpl::UnmapAshmem()
97 {
98 if (ashmem_ == nullptr) {
99 ZLOGE(LOG_LABEL, "ashmem is null");
100 return;
101 }
102 ashmem_->UnmapAshmem();
103 }
104
WriteDataToAshmem(uint8_t * data,int64_t size,int64_t offset)105 int32_t AshmemImpl::WriteDataToAshmem(uint8_t* data, int64_t size, int64_t offset)
106 {
107 if (ashmem_ == nullptr) {
108 ZLOGE(LOG_LABEL, "ashmem is null");
109 return errorDesc::WRITE_TO_ASHMEM_ERROR;
110 }
111 if (data == nullptr) {
112 return errorDesc::CHECK_PARAM_ERROR;
113 }
114 int64_t ashmemSize = static_cast<int64_t>(ashmem_->GetAshmemSize());
115 if (size <= 0 || size > std::numeric_limits<int32_t>::max() || offset < 0 ||
116 offset > std::numeric_limits<int32_t>::max() || (size + offset) > ashmemSize) {
117 ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}" PRId64 " offset:%{public}" PRId64, size, offset);
118 return errorDesc::WRITE_TO_ASHMEM_ERROR;
119 }
120 if (!ashmem_->WriteToAshmem(data, size, offset)) {
121 ZLOGE(LOG_LABEL, "WriteToAshmem fail");
122 return errorDesc::WRITE_TO_ASHMEM_ERROR;
123 }
124 return 0;
125 }
126
ReadDataFromAshmem(int64_t size,int64_t offset,int32_t * errCode)127 uint8_t* AshmemImpl::ReadDataFromAshmem(int64_t size, int64_t offset, int32_t* errCode)
128 {
129 if (ashmem_ == nullptr) {
130 ZLOGE(LOG_LABEL, "ashmem is null");
131 *errCode = errorDesc::READ_FROM_ASHMEM_ERROR;
132 return nullptr;
133 }
134 uint32_t ashmemSize = (uint32_t)ashmem_->GetAshmemSize();
135 if (size <= 0 || size > std::numeric_limits<int32_t>::max() || offset < 0 ||
136 offset > std::numeric_limits<int32_t>::max() || (size + offset) > ashmemSize) {
137 ZLOGE(LOG_LABEL, "invalid parameter, size:%{public}" PRId64 " offset:%{public}" PRId64, size, offset);
138 *errCode = errorDesc::READ_FROM_ASHMEM_ERROR;
139 return nullptr;
140 }
141 const void* result = ashmem_->ReadFromAshmem(size, offset);
142 if (result == nullptr) {
143 ZLOGE(LOG_LABEL, "ashmem->ReadFromAshmem returns null");
144 *errCode = errorDesc::READ_FROM_ASHMEM_ERROR;
145 return nullptr;
146 }
147 uint8_t* data = static_cast<uint8_t*>(malloc(size));
148 if (data == nullptr) {
149 *errCode = errorDesc::READ_FROM_ASHMEM_ERROR;
150 return nullptr;
151 }
152 errno_t status = memcpy_s(data, size, result, size);
153 if (status != EOK) {
154 free(data);
155 *errCode = errorDesc::READ_FROM_ASHMEM_ERROR;
156 return nullptr;
157 }
158 return data;
159 }
160 } // namespace OHOS