• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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