1 /*
2  * Copyright (c) 2024 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 "ipc_cremote_object.h"
17 #include "ipc_inner_object.h"
18 #include "ipc_internal_utils.h"
19 #include "ipc_remote_object_internal.h"
20 #include "log_tags.h"
21 #include "ipc_debug.h"
22 #include "ipc_error_code.h"
23 #include "ipc_types.h"
24 #include "sys_binder.h"
25 
26 #include <securec.h>
27 
28 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, OHOS::LOG_ID_IPC_CAPI, "IPCRemoteObject" };
29 
30 static constexpr uint32_t MIN_SEND_REQUEST_CODE = 0x01;
31 static constexpr uint32_t MAX_SEND_REQUEST_CODE = 0x00ffffff;
32 
OH_IPCRemoteStub_Create(const char * descriptor,OH_OnRemoteRequestCallback requestCallback,OH_OnRemoteDestroyCallback destroyCallback,void * userData)33 OHIPCRemoteStub* OH_IPCRemoteStub_Create(const char *descriptor, OH_OnRemoteRequestCallback requestCallback,
34     OH_OnRemoteDestroyCallback destroyCallback, void *userData)
35 {
36     if (descriptor == nullptr || requestCallback == nullptr) {
37         ZLOGE(LOG_LABEL, "check param error!");
38         return nullptr;
39     }
40     int len = strlen(descriptor);
41     if (len == 0 || len > MAX_PARCEL_LEN) {
42         ZLOGE(LOG_LABEL, "descriptor len:%{public}d is invalid!", len);
43         return nullptr;
44     }
45     std::u16string desc = OHOS::Str8ToStr16(std::string(descriptor));
46     if (desc.length() == 0 && len != 0) {
47         ZLOGE(LOG_LABEL, "convert descriptor to u16string failed: %{public}d", len);
48         return nullptr;
49     }
50     OHOS::sptr<OHIPCRemoteServiceStub> serviceStub(new (std::nothrow) OHIPCRemoteServiceStub(desc,
51         requestCallback, destroyCallback, userData));
52     if (serviceStub == nullptr) {
53         ZLOGE(LOG_LABEL, "new OHIPCRemoteServiceStub failed");
54         return nullptr;
55     }
56     OHIPCRemoteStub *stub = new (std::nothrow) OHIPCRemoteStub();
57     if (stub == nullptr) {
58         ZLOGE(LOG_LABEL, "new OHIPCRemoteStub failed");
59         return nullptr;
60     }
61     stub->remote = serviceStub;
62     return stub;
63 }
64 
OH_IPCRemoteStub_Destroy(OHIPCRemoteStub * stub)65 void OH_IPCRemoteStub_Destroy(OHIPCRemoteStub *stub)
66 {
67     if (stub != nullptr) {
68         stub->remote = nullptr;
69         delete stub;
70     }
71 }
72 
OH_IPCRemoteProxy_Destroy(OHIPCRemoteProxy * proxy)73 void OH_IPCRemoteProxy_Destroy(OHIPCRemoteProxy *proxy)
74 {
75     if (proxy != nullptr) {
76         proxy->remote = nullptr;
77         delete proxy;
78     }
79 }
80 
GetMessageFlag(OH_IPC_RequestMode mode)81 static int GetMessageFlag(OH_IPC_RequestMode mode)
82 {
83     return (mode == OH_IPC_REQUEST_MODE_ASYNC) ?
84         OHOS::MessageOption::TF_ASYNC : OHOS::MessageOption::TF_SYNC;
85 }
86 
87 static constexpr struct {
88     int innerErrorCode;
89     int error;
90 } ERROR_MAP[] = {
91     {OHOS::IPC_PROXY_DEAD_OBJECT_ERR, OH_IPC_DEAD_REMOTE_OBJECT},
92     {OHOS::IPC_INVOKER_CONNECT_ERR, OH_IPC_INNER_ERROR},
93     {OHOS::IPC_PROXY_INVALID_CODE_ERR, OH_IPC_CODE_OUT_OF_RANGE},
94     {OHOS::IPC_STUB_WRITE_PARCEL_ERR, OH_IPC_PARCEL_WRITE_ERROR},
95     {OH_IPC_INVALID_USER_ERROR_CODE, OH_IPC_INVALID_USER_ERROR_CODE},
96     {BR_DEAD_REPLY, OH_IPC_DEAD_REMOTE_OBJECT},
97     {BR_FAILED_REPLY, OH_IPC_INNER_ERROR},
98 };
99 
ConvertSendRequestError(int error)100 static int ConvertSendRequestError(int error)
101 {
102     if (error == OHOS::ERR_NONE) {
103         return OH_IPC_SUCCESS;
104     }
105     if (IsUserDefinedError(error) || IsIpcErrorCode(error)) {
106         return error;
107     }
108 
109     static size_t arraySize = sizeof(ERROR_MAP) / sizeof(ERROR_MAP[0]);
110     for (size_t i = 0; i < arraySize; ++i) {
111         if (ERROR_MAP[i].innerErrorCode == error) {
112             return ERROR_MAP[i].error;
113         }
114     }
115 
116     return OH_IPC_INNER_ERROR;
117 }
118 
IsCodeValid(uint32_t code)119 static bool IsCodeValid(uint32_t code)
120 {
121     return (code >= MIN_SEND_REQUEST_CODE) && (code <= MAX_SEND_REQUEST_CODE);
122 }
123 
OH_IPCRemoteProxy_SendRequest(const OHIPCRemoteProxy * proxy,uint32_t code,const OHIPCParcel * data,OHIPCParcel * reply,const OH_IPC_MessageOption * option)124 int OH_IPCRemoteProxy_SendRequest(const OHIPCRemoteProxy *proxy, uint32_t code, const OHIPCParcel *data,
125     OHIPCParcel *reply, const OH_IPC_MessageOption *option)
126 {
127     if (!IsIPCRemoteProxyValid(proxy, __func__)
128         || !IsIPCParcelValid(data, __func__)
129         || (option != nullptr && option->reserved != nullptr)) {
130         return OH_IPC_CHECK_PARAM_ERROR;
131     }
132     if (!IsCodeValid(code)) {
133         ZLOGE(LOG_LABEL, "send request code:%{public}d out of range[%{public}d, %{public}d]",
134             code, MIN_SEND_REQUEST_CODE, MAX_SEND_REQUEST_CODE);
135         return OH_IPC_CODE_OUT_OF_RANGE;
136     }
137 
138     OH_IPC_RequestMode mode = (option != nullptr) ? option->mode : OH_IPC_REQUEST_MODE_SYNC;
139     int ret = OH_IPC_SUCCESS;
140     OHOS::MessageOption msgOption(GetMessageFlag(mode));
141     if (IsIPCParcelValid(reply, __func__)) {
142         ret = proxy->remote->SendRequest(code, *data->msgParcel, *reply->msgParcel, msgOption);
143     } else if (mode == OH_IPC_REQUEST_MODE_SYNC) {
144         return OH_IPC_CHECK_PARAM_ERROR;
145     } else {
146         OHOS::MessageParcel msgReply;
147         ret = proxy->remote->SendRequest(code, *data->msgParcel, msgReply, msgOption);
148     }
149     return ConvertSendRequestError(ret);
150 }
151 
OH_IPCRemoteProxy_GetInterfaceDescriptor(OHIPCRemoteProxy * proxy,char ** descriptor,int32_t * len,OH_IPC_MemAllocator allocator)152 int OH_IPCRemoteProxy_GetInterfaceDescriptor(OHIPCRemoteProxy *proxy, char **descriptor, int32_t *len,
153     OH_IPC_MemAllocator allocator)
154 {
155     if (!IsIPCRemoteProxyValid(proxy, __func__)
156         || !IsMemoryParamsValid(descriptor, len, allocator, __func__)) {
157         return OH_IPC_CHECK_PARAM_ERROR;
158     }
159 
160     std::u16string u16string(proxy->remote->GetInterfaceDescriptor());
161     std::string value = OHOS::Str16ToStr8(u16string);
162     if (u16string.length() != 0 && value.length() == 0) {
163         ZLOGE(LOG_LABEL, "Str16ToStr8 failed! u16string len: %{public}u, string len: %{public}u",
164             static_cast<uint32_t>(u16string.length()), static_cast<uint32_t>(value.length()));
165         return OH_IPC_PARCEL_READ_ERROR;
166     }
167 
168     int memLength = static_cast<int>(value.length()) + 1;
169     *descriptor = static_cast<char*>(allocator(memLength));
170     if (*descriptor == nullptr) {
171         ZLOGE(LOG_LABEL, "memory allocator failed!");
172         return OH_IPC_MEM_ALLOCATOR_ERROR;
173     }
174     if (memcpy_s(*descriptor, memLength, value.c_str(), memLength) != EOK) {
175         ZLOGE(LOG_LABEL, "memcpy string failed");
176         return OH_IPC_PARCEL_READ_ERROR;
177     }
178     *len = memLength;
179     return OH_IPC_SUCCESS;
180 }
181 
OH_IPCDeathRecipient_Create(OH_OnDeathRecipientCallback deathRecipientCallback,OH_OnDeathRecipientDestroyCallback destroyCallback,void * userData)182 OHIPCDeathRecipient* OH_IPCDeathRecipient_Create(OH_OnDeathRecipientCallback deathRecipientCallback,
183     OH_OnDeathRecipientDestroyCallback destroyCallback, void *userData)
184 {
185     if (deathRecipientCallback == nullptr) {
186         ZLOGE(LOG_LABEL, "args must not be null");
187         return nullptr;
188     }
189     OHOS::sptr<IPCDeathRecipient> recipient(new (std::nothrow) IPCDeathRecipient(
190         deathRecipientCallback, destroyCallback, userData));
191     if (recipient == nullptr) {
192         ZLOGE(LOG_LABEL, "create IPCDeathRecipient object failed");
193         return nullptr;
194     }
195     OHIPCDeathRecipient *deathRecipient = new (std::nothrow) OHIPCDeathRecipient();
196     if (deathRecipient == nullptr) {
197         ZLOGE(LOG_LABEL, "create OHIPCDeathRecipient failed");
198         return nullptr;
199     }
200     deathRecipient->recipient = recipient;
201     return deathRecipient;
202 }
203 
OH_IPCDeathRecipient_Destroy(OHIPCDeathRecipient * recipient)204 void OH_IPCDeathRecipient_Destroy(OHIPCDeathRecipient *recipient)
205 {
206     if (recipient != nullptr) {
207         recipient->recipient = nullptr;
208         delete recipient;
209     }
210 }
211 
OH_IPCRemoteProxy_AddDeathRecipient(OHIPCRemoteProxy * proxy,OHIPCDeathRecipient * recipient)212 int OH_IPCRemoteProxy_AddDeathRecipient(OHIPCRemoteProxy *proxy, OHIPCDeathRecipient *recipient)
213 {
214     if (!IsIPCRemoteProxyValid(proxy, __func__)
215         || recipient == nullptr
216         || recipient->recipient == nullptr) {
217         return OH_IPC_CHECK_PARAM_ERROR;
218     }
219 
220     return proxy->remote->AddDeathRecipient(recipient->recipient) ? OH_IPC_SUCCESS : OH_IPC_INNER_ERROR;
221 }
222 
OH_IPCRemoteProxy_RemoveDeathRecipient(OHIPCRemoteProxy * proxy,OHIPCDeathRecipient * recipient)223 int OH_IPCRemoteProxy_RemoveDeathRecipient(OHIPCRemoteProxy *proxy, OHIPCDeathRecipient *recipient)
224 {
225     if (!IsIPCRemoteProxyValid(proxy, __func__)
226         || recipient == nullptr
227         || recipient->recipient == nullptr) {
228         return OH_IPC_CHECK_PARAM_ERROR;
229     }
230 
231     return proxy->remote->RemoveDeathRecipient(recipient->recipient) ? OH_IPC_SUCCESS : OH_IPC_INNER_ERROR;
232 }
233 
OH_IPCRemoteProxy_IsRemoteDead(const OHIPCRemoteProxy * proxy)234 int OH_IPCRemoteProxy_IsRemoteDead(const OHIPCRemoteProxy *proxy)
235 {
236     if (!IsIPCRemoteProxyValid(proxy, __func__)) {
237         return 1;
238     }
239 
240     return proxy->remote->IsObjectDead() ? 1 : 0;
241 }
242