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 "message_parcel.h"
17
18 #include <sys/mman.h>
19 #include <unistd.h>
20
21 #include "ashmem.h"
22 #ifndef CONFIG_IPC_SINGLE
23 #include "dbinder_callback_stub.h"
24 #include "dbinder_session_object.h"
25 #endif
26 #include "ipc_debug.h"
27 #include "ipc_file_descriptor.h"
28 #include "ipc_process_skeleton.h"
29 #include "iremote_object.h"
30 #include "log_tags.h"
31 #include "securec.h"
32 #include "sys_binder.h"
33
34 namespace OHOS {
35 #ifndef TITLE
36 #define TITLE __PRETTY_FUNCTION__
37 #endif
38
39 #ifndef CONFIG_IPC_SINGLE
40 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "MessageParcel" };
41 #define DBINDER_LOGE(fmt, args...) \
42 (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
43 #define DBINDER_LOGI(fmt, args...) \
44 (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
45 #endif
46
47
MessageParcel()48 MessageParcel::MessageParcel()
49 : Parcel(),
50 writeRawDataFd_(-1),
51 readRawDataFd_(-1),
52 kernelMappedWrite_(nullptr),
53 kernelMappedRead_(nullptr),
54 rawData_(nullptr),
55 rawDataSize_(0)
56 {}
57
MessageParcel(Allocator * allocator)58 MessageParcel::MessageParcel(Allocator *allocator)
59 : Parcel(allocator),
60 writeRawDataFd_(-1),
61 readRawDataFd_(-1),
62 kernelMappedWrite_(nullptr),
63 kernelMappedRead_(nullptr),
64 rawData_(nullptr),
65 rawDataSize_(0)
66 {}
67
~MessageParcel()68 MessageParcel::~MessageParcel()
69 {
70 if (kernelMappedWrite_ != nullptr) {
71 ::munmap(kernelMappedWrite_, rawDataSize_);
72 kernelMappedWrite_ = nullptr;
73 }
74 if (kernelMappedRead_ != nullptr) {
75 ::munmap(kernelMappedRead_, rawDataSize_);
76 kernelMappedRead_ = nullptr;
77 }
78
79 if (readRawDataFd_ > 0) {
80 ::close(readRawDataFd_);
81 readRawDataFd_ = -1;
82 }
83 if (writeRawDataFd_ > 0) {
84 ::close(writeRawDataFd_);
85 writeRawDataFd_ = -1;
86 }
87
88 ClearFileDescriptor();
89
90 rawData_ = nullptr;
91 rawDataSize_ = 0;
92 }
93
94
95 #ifndef CONFIG_IPC_SINGLE
WriteDBinderProxy(const sptr<IRemoteObject> & object,uint32_t handle,uint64_t stubIndex)96 bool MessageParcel::WriteDBinderProxy(const sptr<IRemoteObject> &object, uint32_t handle, uint64_t stubIndex)
97 {
98 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
99 if (current == nullptr) {
100 DBINDER_LOGE("current is nullptr");
101 return false;
102 }
103 std::shared_ptr<DBinderSessionObject> sessionOfPeer = current->ProxyQueryDBinderSession(handle);
104 if (sessionOfPeer == nullptr) {
105 DBINDER_LOGE("sessionOfPeer is nullptr");
106 return false;
107 }
108 std::string peerName = sessionOfPeer->GetServiceName();
109 std::string peerId = sessionOfPeer->GetDeviceId();
110 std::string localId = current->GetLocalDeviceID();
111 sptr<DBinderCallbackStub> fakeStub = current->QueryDBinderCallbackStub(object);
112 if (fakeStub == nullptr) {
113 // note that cannot use this proxy's descriptor
114 fakeStub = new DBinderCallbackStub(peerName, peerId, localId, stubIndex, handle);
115 if (!current->AttachDBinderCallbackStub(object, fakeStub)) {
116 DBINDER_LOGE("save callback of fake stub failed");
117 return false;
118 }
119 }
120 return WriteRemoteObject(fakeStub);
121 }
122 #endif
123
WriteRemoteObject(const sptr<IRemoteObject> & object)124 bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject> &object)
125 {
126 if (object == nullptr) {
127 return false;
128 }
129 holders_.push_back(object);
130 #ifndef CONFIG_IPC_SINGLE
131 if (object->IsProxyObject()) {
132 const IPCObjectProxy *proxy = reinterpret_cast<const IPCObjectProxy *>(object.GetRefPtr());
133 const uint32_t handle = proxy ? proxy->GetHandle() : 0;
134 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
135 if (IPCProcessSkeleton::IsHandleMadeByUser(handle) && current != nullptr) {
136 DBINDER_LOGI("send dbinder object to local devices");
137 /* this is a fake proxy which handle get by MakeRemoteHandle(), Not binder driver of kernel */
138 uint64_t stubIndex = current->QueryHandleToIndex(handle);
139 if (stubIndex > 0) {
140 DBINDER_LOGI("this is dbinder proxy want to send anthor process in this device");
141 return WriteDBinderProxy(object, handle, stubIndex);
142 }
143 }
144 }
145 #endif
146 auto result = WriteObject<IRemoteObject>(object);
147 if (result == false) {
148 return result;
149 }
150 return result;
151 }
152
ReadRemoteObject()153 sptr<IRemoteObject> MessageParcel::ReadRemoteObject()
154 {
155 sptr<IRemoteObject> temp = ReadObject<IRemoteObject>();
156 #ifndef CONFIG_IPC_SINGLE
157 if (temp != nullptr && !temp->IsProxyObject()) {
158 // if this stub is a DBinderCallbackStub, return corresponding proxy
159 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
160 if (current != nullptr) {
161 sptr<IRemoteObject> proxy = current->QueryDBinderCallbackProxy(temp);
162 if (proxy != nullptr) {
163 temp = proxy;
164 }
165 }
166 }
167 #endif
168 return temp;
169 }
170
WriteFileDescriptor(int fd)171 bool MessageParcel::WriteFileDescriptor(int fd)
172 {
173 if (fd < 0) {
174 return false;
175 }
176 int dupFd = dup(fd);
177 if (dupFd < 0) {
178 return false;
179 }
180 sptr<IPCFileDescriptor> descriptor = new IPCFileDescriptor(dupFd);
181 return WriteObject<IPCFileDescriptor>(descriptor);
182 }
183
ReadFileDescriptor()184 int MessageParcel::ReadFileDescriptor()
185 {
186 sptr<IPCFileDescriptor> descriptor = ReadObject<IPCFileDescriptor>();
187 if (descriptor == nullptr) {
188 return -1;
189 }
190 int fd = descriptor->GetFd();
191 if (fd < 0) {
192 return -1;
193 }
194 holders_.push_back(descriptor);
195 return dup(fd);
196 }
197
ClearFileDescriptor()198 void MessageParcel::ClearFileDescriptor()
199 {
200 binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
201 size_t objectNum = GetOffsetsSize();
202 uintptr_t data = GetData();
203 for (size_t i = 0; i < objectNum; i++) {
204 const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
205 if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
206 ::close(flat->handle);
207 }
208 }
209 }
210
ContainFileDescriptors() const211 bool MessageParcel::ContainFileDescriptors() const
212 {
213 binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
214 size_t objectNum = GetOffsetsSize();
215 uintptr_t data = GetData();
216 for (size_t i = 0; i < objectNum; i++) {
217 const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
218 if (flat->hdr.type == BINDER_TYPE_FD) {
219 return true;
220 }
221 }
222
223 return false;
224 }
225
WriteInterfaceToken(std::u16string name)226 bool MessageParcel::WriteInterfaceToken(std::u16string name)
227 {
228 constexpr int strictModePolicy = 0x100;
229 constexpr int workSource = 0;
230 size_t rewindPos = GetWritePosition();
231 if (!WriteInt32(strictModePolicy)) {
232 return false;
233 }
234
235 if (!WriteInt32(workSource)) {
236 if (!RewindWrite(rewindPos)) {
237 FlushBuffer();
238 }
239 return false;
240 }
241
242 return WriteString16(name);
243 }
244
ReadInterfaceToken()245 std::u16string MessageParcel::ReadInterfaceToken()
246 {
247 [[maybe_unused]] int strictModePolicy = ReadInt32();
248 [[maybe_unused]] int workSource = ReadInt32();
249 return ReadString16();
250 }
251
WriteRawData(const void * data,size_t size)252 bool MessageParcel::WriteRawData(const void *data, size_t size)
253 {
254 if (data == nullptr || size > MAX_RAWDATA_SIZE) {
255 return false;
256 }
257 if (kernelMappedWrite_ != nullptr) {
258 return false;
259 }
260 if (!WriteInt32(size)) {
261 return false;
262 }
263 if (size <= MIN_RAWDATA_SIZE) {
264 return WriteUnpadBuffer(data, size);
265 }
266 int fd = AshmemCreate("Parcel RawData", size);
267 if (fd < 0) {
268 return false;
269 }
270 writeRawDataFd_ = fd;
271
272 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
273 if (result < 0) {
274 return false;
275 }
276 void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
277 if (ptr == MAP_FAILED) {
278 return false;
279 }
280 if (!WriteFileDescriptor(fd)) {
281 ::munmap(ptr, size);
282 return false;
283 }
284 if (memcpy_s(ptr, size, data, size) != EOK) {
285 ::munmap(ptr, size);
286 return false;
287 }
288 kernelMappedWrite_ = ptr;
289 rawDataSize_ = size;
290 return true;
291 }
292
RestoreRawData(std::shared_ptr<char> rawData,size_t size)293 bool MessageParcel::RestoreRawData(std::shared_ptr<char> rawData, size_t size)
294 {
295 if (rawData_ != nullptr || rawData == nullptr) {
296 return false;
297 }
298 rawData_ = rawData;
299 rawDataSize_ = size;
300 writeRawDataFd_ = 0;
301 return true;
302 }
303
ReadRawData(size_t size)304 const void *MessageParcel::ReadRawData(size_t size)
305 {
306 int32_t bufferSize = ReadInt32();
307 if (static_cast<unsigned int>(bufferSize) != size) {
308 return nullptr;
309 }
310
311 if (static_cast<unsigned int>(bufferSize) <= MIN_RAWDATA_SIZE) {
312 return ReadUnpadBuffer(size);
313 }
314
315 /* if rawDataFd_ == 0 means rawData is received from remote
316 */
317 if (rawData_ != nullptr && writeRawDataFd_ == 0) {
318 /* should read fd for move readCursor of parcel */
319 if (ReadFileDescriptor()) {
320 // do nothing
321 }
322 if (rawDataSize_ != size) {
323 return nullptr;
324 }
325 return rawData_.get();
326 }
327 int fd = ReadFileDescriptor();
328 if (fd < 0) {
329 return nullptr;
330 }
331 readRawDataFd_ = fd;
332
333 int ashmemSize = AshmemGetSize(fd);
334 if (ashmemSize < 0 || size_t(ashmemSize) < size) {
335 // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
336 return nullptr;
337 }
338 void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
339 if (ptr == MAP_FAILED) {
340 // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
341 return nullptr;
342 }
343 kernelMappedRead_ = ptr;
344 rawDataSize_ = size;
345 return ptr;
346 }
347
GetRawData() const348 const void *MessageParcel::GetRawData() const
349 {
350 if (rawData_ != nullptr) {
351 return rawData_.get();
352 }
353 if (kernelMappedWrite_ != nullptr) {
354 return kernelMappedWrite_;
355 }
356 if (kernelMappedRead_ != nullptr) {
357 return kernelMappedRead_;
358 }
359 return nullptr;
360 }
361
GetRawDataSize() const362 size_t MessageParcel::GetRawDataSize() const
363 {
364 return rawDataSize_;
365 }
366
GetRawDataCapacity() const367 size_t MessageParcel::GetRawDataCapacity() const
368 {
369 return MAX_RAWDATA_SIZE;
370 }
371
WriteNoException()372 void MessageParcel::WriteNoException()
373 {
374 WriteInt32(0);
375 }
376
ReadException()377 int32_t MessageParcel::ReadException()
378 {
379 int32_t errorCode = ReadInt32();
380 if (errorCode != 0) {
381 ReadString16();
382 }
383 return errorCode;
384 }
385
WriteAshmem(sptr<Ashmem> ashmem)386 bool MessageParcel::WriteAshmem(sptr<Ashmem> ashmem)
387 {
388 int fd = ashmem->GetAshmemFd();
389 int32_t size = ashmem->GetAshmemSize();
390 if (fd < 0 || size <= 0) {
391 return false;
392 }
393 if (!WriteFileDescriptor(fd) || !WriteInt32(size)) {
394 return false;
395 }
396 return true;
397 }
398
ReadAshmem()399 sptr<Ashmem> MessageParcel::ReadAshmem()
400 {
401 int fd = ReadFileDescriptor();
402 if (fd < 0) {
403 return nullptr;
404 }
405
406 int32_t size = ReadInt32();
407 if (size <= 0) {
408 ::close(fd);
409 return nullptr;
410 }
411 return new Ashmem(fd, size);
412 }
413 } // namespace OHOS
414