1 /*
2 * Copyright (c) 2021 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 <unistd.h>
17 #include <sys/mman.h>
18 #include "message_parcel.h"
19
20 #include "ipc_debug.h"
21 #include "iremote_object.h"
22 #include "ipc_file_descriptor.h"
23 #include "sys_binder.h"
24 #include "ashmem.h"
25 #include "securec.h"
26 #include "ans_manager_stub.h"
27
28 namespace OHOS {
MessageParcel()29 MessageParcel::MessageParcel()
30 : Parcel(),
31 writeRawDataFd_(-1),
32 readRawDataFd_(-1),
33 kernelMappedWrite_(nullptr),
34 kernelMappedRead_(nullptr),
35 rawData_(nullptr),
36 rawDataSize_(0)
37 {}
38
MessageParcel(Allocator * allocator)39 MessageParcel::MessageParcel(Allocator *allocator)
40 : Parcel(allocator),
41 writeRawDataFd_(-1),
42 readRawDataFd_(-1),
43 kernelMappedWrite_(nullptr),
44 kernelMappedRead_(nullptr),
45 rawData_(nullptr),
46 rawDataSize_(0)
47 {}
48
~MessageParcel()49 MessageParcel::~MessageParcel()
50 {
51 if (kernelMappedWrite_ != nullptr) {
52 ::munmap(kernelMappedWrite_, rawDataSize_);
53 kernelMappedWrite_ = nullptr;
54 }
55 if (kernelMappedRead_ != nullptr) {
56 ::munmap(kernelMappedRead_, rawDataSize_);
57 kernelMappedRead_ = nullptr;
58 }
59
60 if (readRawDataFd_ > 0) {
61 ::close(readRawDataFd_);
62 readRawDataFd_ = -1;
63 }
64 if (writeRawDataFd_ > 0) {
65 ::close(writeRawDataFd_);
66 writeRawDataFd_ = -1;
67 }
68
69 ClearFileDescriptor();
70
71 rawData_ = nullptr;
72 rawDataSize_ = 0;
73 }
74
WriteRemoteObject(const sptr<IRemoteObject> & object)75 bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject> &object)
76 {
77 holders_.push_back(object);
78 return WriteObject<IRemoteObject>(object);
79 }
80
ReadRemoteObject()81 sptr<IRemoteObject> MessageParcel::ReadRemoteObject()
82 {
83 return ReadObject<IRemoteObject>();
84 }
85
WriteFileDescriptor(int fd)86 bool MessageParcel::WriteFileDescriptor(int fd)
87 {
88 if (fd < 0) {
89 return false;
90 }
91 int dupFd = dup(fd);
92 if (dupFd < 0) {
93 return false;
94 }
95 sptr<IPCFileDescriptor> descriptor = new IPCFileDescriptor(dupFd);
96 return WriteObject<IPCFileDescriptor>(descriptor);
97 }
98
ReadFileDescriptor()99 int MessageParcel::ReadFileDescriptor()
100 {
101 sptr<IPCFileDescriptor> descriptor = ReadObject<IPCFileDescriptor>();
102 if (descriptor == nullptr) {
103 return -1;
104 }
105 int fd = descriptor->GetFd();
106 if (fd < 0) {
107 return -1;
108 }
109 holders_.push_back(descriptor);
110 return dup(fd);
111 }
112
ClearFileDescriptor()113 void MessageParcel::ClearFileDescriptor()
114 {
115 binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
116 size_t objectNum = GetOffsetsSize();
117 uintptr_t data = GetData();
118 for (size_t i = 0; i < objectNum; i++) {
119 const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
120 if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
121 ::close(flat->handle);
122 }
123 }
124 }
125
ContainFileDescriptors() const126 bool MessageParcel::ContainFileDescriptors() const
127 {
128 binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
129 size_t objectNum = GetOffsetsSize();
130 uintptr_t data = GetData();
131 for (size_t i = 0; i < objectNum; i++) {
132 const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
133 if (flat->hdr.type == BINDER_TYPE_FD) {
134 return true;
135 }
136 }
137
138 return false;
139 }
140
WriteInterfaceToken(std::u16string name)141 bool MessageParcel::WriteInterfaceToken(std::u16string name)
142 {
143 constexpr int strictModePolicy = 0x100;
144 constexpr int workSource = 0;
145 size_t rewindPos = GetWritePosition();
146 if (!WriteInt32(strictModePolicy)) {
147 return false;
148 }
149
150 if (!WriteInt32(workSource)) {
151 if (!RewindWrite(rewindPos)) {
152 FlushBuffer();
153 }
154 return false;
155 }
156
157 return WriteString16(name);
158 }
159
ReadInterfaceToken()160 std::u16string MessageParcel::ReadInterfaceToken()
161 {
162 [[maybe_unused]] int strictModePolicy = ReadInt32();
163 [[maybe_unused]] int workSource = ReadInt32();
164 return ReadString16();
165 }
166
WriteRawData(const void * data,size_t size)167 bool MessageParcel::WriteRawData(const void *data, size_t size)
168 {
169 if (data == nullptr || size > MAX_RAWDATA_SIZE) {
170 return false;
171 }
172 if (kernelMappedWrite_ != nullptr) {
173 return false;
174 }
175 if (!WriteInt32(size)) {
176 return false;
177 }
178 if (size <= MIN_RAWDATA_SIZE) {
179 return WriteUnpadBuffer(data, size);
180 }
181 int fd = AshmemCreate("Parcel RawData", size);
182 if (fd < 0) {
183 return false;
184 }
185 writeRawDataFd_ = fd;
186
187 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
188 if (result < 0) {
189 return false;
190 }
191 void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
192 if (ptr == MAP_FAILED) {
193 return false;
194 }
195 if (!WriteFileDescriptor(fd)) {
196 ::munmap(ptr, size);
197 return false;
198 }
199 if (memcpy_s(ptr, size, data, size) != EOK) {
200 ::munmap(ptr, size);
201 return false;
202 }
203 kernelMappedWrite_ = ptr;
204 rawDataSize_ = size;
205 return true;
206 }
207
RestoreRawData(std::shared_ptr<char> rawData,size_t size)208 bool MessageParcel::RestoreRawData(std::shared_ptr<char> rawData, size_t size)
209 {
210 if (rawData_ != nullptr || rawData == nullptr) {
211 return false;
212 }
213 rawData_ = rawData;
214 rawDataSize_ = size;
215 writeRawDataFd_ = 0;
216 return true;
217 }
218
ReadRawData(size_t size)219 const void *MessageParcel::ReadRawData(size_t size)
220 {
221 int32_t bufferSize = ReadInt32();
222 if (static_cast<unsigned int>(bufferSize) != size) {
223 return nullptr;
224 }
225
226 if (static_cast<unsigned int>(bufferSize) <= MIN_RAWDATA_SIZE) {
227 return ReadUnpadBuffer(size);
228 }
229
230 /* if rawDataFd_ == 0 means rawData is received from remote
231 */
232 if (rawData_ != nullptr && writeRawDataFd_ == 0) {
233 /* should read fd for move readCursor of parcel */
234 if (ReadFileDescriptor()) {
235 // do nothing
236 }
237 if (rawDataSize_ != size) {
238 return nullptr;
239 }
240 return rawData_.get();
241 }
242 int fd = ReadFileDescriptor();
243 if (fd < 0) {
244 return nullptr;
245 }
246 readRawDataFd_ = fd;
247
248 int ashmemSize = AshmemGetSize(fd);
249 if (ashmemSize < 0 || size_t(ashmemSize) < size) {
250 // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
251 return nullptr;
252 }
253 void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
254 if (ptr == MAP_FAILED) {
255 // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
256 return nullptr;
257 }
258 kernelMappedRead_ = ptr;
259 rawDataSize_ = size;
260 return ptr;
261 }
262
GetRawData() const263 const void *MessageParcel::GetRawData() const
264 {
265 if (rawData_ != nullptr) {
266 return rawData_.get();
267 }
268 if (kernelMappedWrite_ != nullptr) {
269 return kernelMappedWrite_;
270 }
271 if (kernelMappedRead_ != nullptr) {
272 return kernelMappedRead_;
273 }
274 return nullptr;
275 }
276
GetRawDataSize() const277 size_t MessageParcel::GetRawDataSize() const
278 {
279 return rawDataSize_;
280 }
281
GetRawDataCapacity() const282 size_t MessageParcel::GetRawDataCapacity() const
283 {
284 return MAX_RAWDATA_SIZE;
285 }
286
WriteNoException()287 void MessageParcel::WriteNoException()
288 {
289 WriteInt32(0);
290 }
291
ReadException()292 int32_t MessageParcel::ReadException()
293 {
294 int32_t errorCode = ReadInt32();
295 if (errorCode != 0) {
296 ReadString16();
297 }
298 return errorCode;
299 }
300
WriteAshmem(sptr<Ashmem> ashmem)301 bool MessageParcel::WriteAshmem(sptr<Ashmem> ashmem)
302 {
303 int fd = ashmem->GetAshmemFd();
304 int32_t size = ashmem->GetAshmemSize();
305 if (fd < 0 || size <= 0) {
306 return false;
307 }
308 if (!WriteFileDescriptor(fd) || !WriteInt32(size)) {
309 return false;
310 }
311 return true;
312 }
313
ReadAshmem()314 sptr<Ashmem> MessageParcel::ReadAshmem()
315 {
316 int fd = ReadFileDescriptor();
317 if (fd < 0) {
318 return nullptr;
319 }
320
321 int32_t size = ReadInt32();
322 if (size <= 0) {
323 ::close(fd);
324 return nullptr;
325 }
326 return new Ashmem(fd, size);
327 }
328 } // namespace OHOS
329