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 "dbinder_callback_stub.h"
17
18 #include <cinttypes>
19
20 #include "dbinder_error_code.h"
21 #include "log_tags.h"
22 #include "ipc_debug.h"
23 #include "ipc_process_skeleton.h"
24 #include "ipc_skeleton.h"
25 #include "ipc_thread_skeleton.h"
26 #include "ipc_types.h"
27 #include "securec.h"
28 #include "string_ex.h"
29 #include "sys_binder.h"
30
31 namespace OHOS {
32 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC_DBINDER_CB_STUB,
33 "DBinderCallbackStub" };
34
DBinderCallbackStub(const std::string & service,const std::string & device,const std::string & localDevice,uint64_t stubIndex,uint32_t handle,uint32_t tokenId)35 DBinderCallbackStub::DBinderCallbackStub(const std::string &service, const std::string &device,
36 const std::string &localDevice, uint64_t stubIndex, uint32_t handle, uint32_t tokenId)
37 : IPCObjectStub(Str8ToStr16("DBinderCallback" + IPCProcessSkeleton::ConvertToSecureString(device) + service)),
38 serviceName_(service),
39 deviceID_(device),
40 localDeviceID_(localDevice),
41 stubIndex_(stubIndex),
42 handle_(handle),
43 tokenId_(tokenId)
44 {
45 ZLOGD(LOG_LABEL, "created, service:%{public}s deviceId:%{public}s handle:%{public}u stubIndex:%{public}" PRIu64,
46 serviceName_.c_str(), IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(), handle_, stubIndex_);
47 dbinderData_ = std::make_unique<uint8_t[]>(sizeof(dbinder_negotiation_data));
48 if (dbinderData_ == nullptr) {
49 ZLOGE(LOG_LABEL, "malloc dbinderData_ fail");
50 return;
51 }
52 memset_s(dbinderData_.get(), sizeof(dbinder_negotiation_data), 0, sizeof(dbinder_negotiation_data));
53 }
54
~DBinderCallbackStub()55 DBinderCallbackStub::~DBinderCallbackStub()
56 {
57 ZLOGD(LOG_LABEL, "destroyed, service:%{public}s deviceId:%{public}s handle:%{public}u stubIndex:%{public}" PRIu64,
58 serviceName_.c_str(), IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(), handle_, stubIndex_);
59 IPCProcessSkeleton::GetCurrent()->DetachDBinderCallbackStub(this);
60 dbinderData_ = nullptr;
61 }
62
GetServiceName()63 const std::string &DBinderCallbackStub::GetServiceName()
64 {
65 return serviceName_;
66 }
67
GetDeviceID()68 const std::string &DBinderCallbackStub::GetDeviceID()
69 {
70 return deviceID_;
71 }
72
GetStubIndex() const73 uint64_t DBinderCallbackStub::GetStubIndex() const
74 {
75 return stubIndex_;
76 }
77
GetTokenId() const78 uint32_t DBinderCallbackStub::GetTokenId() const
79 {
80 return tokenId_;
81 }
82
ProcessProto(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)83 int32_t DBinderCallbackStub::ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply,
84 MessageOption &option)
85 {
86 int uid = IPCSkeleton::GetCallingUid();
87 int pid = IPCSkeleton::GetCallingPid();
88 if (uid < 0 || pid < 0) {
89 ZLOGE(LOG_LABEL, "uid or pid err");
90 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_UID_OR_PID_FAIL, __FUNCTION__);
91 return DBINDER_SERVICE_PROCESS_PROTO_ERR;
92 }
93 sptr<IRemoteObject> object = IPCProcessSkeleton::GetCurrent()->GetSAMgrObject();
94 if (object == nullptr) {
95 ZLOGE(LOG_LABEL, "get sa object is null");
96 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SA_OBJECT_NULL, __FUNCTION__);
97 return DBINDER_CALLBACK_READ_OBJECT_ERR;
98 }
99 IPCObjectProxy *samgr = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
100 std::string sessionName = samgr->GetSessionNameForPidUid(uid, pid);
101 if (sessionName.empty()) {
102 ZLOGE(LOG_LABEL, "grans session name failed");
103 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SESSION_NAME_FAIL, __FUNCTION__);
104 return DBINDER_SERVICE_WRONG_SESSION;
105 }
106 return ProcessData(uid, pid, sessionName, data, reply);
107 }
108
ProcessData(int uid,int pid,const std::string & sessionName,MessageParcel & data,MessageParcel & reply)109 int32_t DBinderCallbackStub::ProcessData(int uid, int pid, const std::string &sessionName, MessageParcel &data,
110 MessageParcel &reply)
111 {
112 MessageParcel authData;
113 MessageParcel authReply;
114 MessageOption authOption;
115 if (!authData.WriteUint32(pid) || !authData.WriteUint32(uid) || !authData.WriteString(localDeviceID_) ||
116 !authData.WriteUint64(stubIndex_) || !authData.WriteUint32(tokenId_)) {
117 ZLOGE(LOG_LABEL, "write to MessageParcel fail");
118 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_INVALID_DATA, __FUNCTION__);
119 return ERR_INVALID_DATA;
120 }
121 IRemoteInvoker *dbinderInvoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS);
122 if (dbinderInvoker == nullptr) {
123 ZLOGE(LOG_LABEL, "no databus thread and invoker");
124 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_RPC_DATABUS_INVOKER_ERR, __FUNCTION__);
125 return RPC_DATABUS_INVOKER_ERR;
126 }
127 int err = dbinderInvoker->SendRequest(handle_, DBINDER_ADD_COMMAUTH, authData, authReply, authOption);
128 if (err != ERR_NONE) {
129 ZLOGE(LOG_LABEL, "send auth info to remote fail");
130 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_BINDER_CALLBACK_AUTHCOMM_ERR, __FUNCTION__);
131 return BINDER_CALLBACK_AUTHCOMM_ERR;
132 }
133 ZLOGI(LOG_LABEL, "send to stub ok! stubIndex:%{public}" PRIu64 " peerDevice:%{public}s "
134 "localDeviceID:%{public}s serviceName:%{public}s uid:%{public}d pid:%{public}d "
135 "tokenId:%{public}u sessionName:%{public}s",
136 stubIndex_, IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(),
137 IPCProcessSkeleton::ConvertToSecureString(localDeviceID_).c_str(), serviceName_.c_str(), uid, pid, tokenId_,
138 sessionName.c_str());
139 if (!reply.WriteUint32(IRemoteObject::IF_PROT_DATABUS) || !reply.WriteUint64(stubIndex_) ||
140 !reply.WriteString(serviceName_) || !reply.WriteString(deviceID_) || !reply.WriteString(localDeviceID_) ||
141 !reply.WriteString(sessionName) || !reply.WriteUint32(tokenId_)) {
142 ZLOGE(LOG_LABEL, "write to parcel fail");
143 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_INVALID_DATA, __FUNCTION__);
144 return ERR_INVALID_DATA;
145 }
146 return 0;
147 }
148
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)149 int32_t DBinderCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
150 MessageOption &option)
151 {
152 int32_t result = ERR_NONE;
153 ZLOGI(LOG_LABEL, "code:%{public}u", code);
154 switch (code) {
155 case GET_PROTO_INFO: {
156 result = ProcessProto(code, data, reply, option);
157 break;
158 }
159 default: {
160 ZLOGI(LOG_LABEL, "unknown code:%{public}u", code);
161 result = DBINDER_CALLBACK_ERR;
162 break;
163 }
164 }
165
166 return result;
167 }
168
Marshalling(Parcel & parcel) const169 bool DBinderCallbackStub::Marshalling(Parcel &parcel) const
170 {
171 ZLOGD(LOG_LABEL, "enter");
172 if (dbinderData_ == nullptr) {
173 ZLOGE(LOG_LABEL, "dbinderData_ is nullptr");
174 return false;
175 }
176
177 auto *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
178 if (invoker == nullptr) {
179 ZLOGE(LOG_LABEL, "GetRemoteInvoker fail");
180 return false;
181 }
182
183 size_t offset = parcel.GetWritePosition();
184 auto dbinderData = reinterpret_cast<const dbinder_negotiation_data *>(dbinderData_.get());
185 if (!ProcessSkeleton::FlattenDBinderData(parcel, dbinderData)) {
186 return false;
187 }
188
189 if (!invoker->FlattenObject(parcel, this)) {
190 ZLOGE(LOG_LABEL, "FlattenObject fail");
191 parcel.RewindWrite(offset);
192 return false;
193 }
194 return true;
195 }
196
Marshalling(Parcel & parcel,const sptr<IRemoteObject> & object)197 bool DBinderCallbackStub::Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object)
198 {
199 ZLOGD(LOG_LABEL, "enter");
200 auto callback = reinterpret_cast<DBinderCallbackStub *>(object.GetRefPtr());
201 if (callback == nullptr) {
202 return false;
203 }
204 return callback->Marshalling(parcel);
205 }
206
AddDBinderCommAuth(pid_t pid,uid_t uid,const std::string & sessionName)207 int DBinderCallbackStub::AddDBinderCommAuth(pid_t pid, uid_t uid, const std::string &sessionName)
208 {
209 MessageParcel authData, authReply;
210 MessageOption authOption;
211 if (!authData.WriteUint32(pid) || !authData.WriteUint32(uid) || !authData.WriteString(localDeviceID_) ||
212 !authData.WriteUint64(stubIndex_) || !authData.WriteUint32(tokenId_)) {
213 ZLOGE(LOG_LABEL, "write to MessageParcel fail");
214 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_WRITE_TO_PARCEL_FAIL, __FUNCTION__);
215 return IPC_STUB_WRITE_PARCEL_ERR;
216 }
217 IRemoteInvoker *dbinderInvoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS);
218 if (dbinderInvoker == nullptr) {
219 ZLOGE(LOG_LABEL, "no databus thread and invoker");
220 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_RPC_DATABUS_INVOKER_ERR, __FUNCTION__);
221 return RPC_DATABUS_INVOKER_ERR;
222 }
223 int err = dbinderInvoker->SendRequest(handle_, DBINDER_ADD_COMMAUTH, authData, authReply, authOption);
224 if (err != ERR_NONE) {
225 ZLOGE(LOG_LABEL, "send auth info to remote fail");
226 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_BINDER_CALLBACK_AUTHCOMM_ERR, __FUNCTION__);
227 return BINDER_CALLBACK_AUTHCOMM_ERR;
228 }
229
230 ZLOGI(LOG_LABEL, "send to stub ok! stubIndex:%{public}" PRIu64 " peerDevice:%{public}s "
231 "localDeviceID:%{public}s serviceName:%{public}s uid:%{public}d pid:%{public}d "
232 "tokenId:%{public}u sessionName:%{public}s",
233 stubIndex_, IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(),
234 IPCProcessSkeleton::ConvertToSecureString(localDeviceID_).c_str(), serviceName_.c_str(), uid, pid, tokenId_,
235 sessionName.c_str());
236 return ERR_NONE;
237 }
238
SaveDBinderData(const std::string & sessionName)239 int DBinderCallbackStub::SaveDBinderData(const std::string &sessionName)
240 {
241 if (dbinderData_ == nullptr) {
242 ZLOGE(LOG_LABEL, "dbinderData_ is nullptr");
243 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
244 return DBINDER_CALLBACK_MALLOC_ERR;
245 }
246
247 dbinder_negotiation_data *dbinderData = reinterpret_cast<dbinder_negotiation_data *>(dbinderData_.get());
248 (void)memset_s(dbinderData, sizeof(dbinder_negotiation_data), 0, sizeof(dbinder_negotiation_data));
249 dbinderData->proto = IRemoteObject::IF_PROT_DATABUS;
250 dbinderData->stub_index = stubIndex_;
251 dbinderData->tokenid = tokenId_;
252 auto ret = memcpy_s(dbinderData->target_name, SESSION_NAME_LENGTH, serviceName_.c_str(),
253 serviceName_.length());
254 ret += memcpy_s(dbinderData->target_device, DEVICEID_LENGTH, deviceID_.c_str(),
255 deviceID_.length());
256 ret += memcpy_s(dbinderData->local_device, DEVICEID_LENGTH, localDeviceID_.c_str(),
257 localDeviceID_.length());
258 ret += memcpy_s(dbinderData->local_name, SESSION_NAME_LENGTH, sessionName.c_str(), sessionName.length());
259 ret += memcpy_s(dbinderData->desc, DBINDER_DESC_LENGTH, descriptor_.c_str(), descriptor_.length());
260 if (ret != EOK) {
261 ZLOGE(LOG_LABEL, "memcpy_s fail, ret:%{public}d", ret);
262 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
263 return DBINDER_CALLBACK_MEMCPY_ERR;
264 }
265 ZLOGI(LOG_LABEL, "proto:%{public}u stubIndex:%{public}llu tokenId:%{public}u "
266 "targetName:%{public}s localName:%{public}s",
267 dbinderData->proto, dbinderData->stub_index, dbinderData->tokenid, dbinderData->target_name,
268 dbinderData->local_name);
269 return ERR_NONE;
270 }
271
GetAndSaveDBinderData(pid_t pid,uid_t uid)272 int DBinderCallbackStub::GetAndSaveDBinderData(pid_t pid, uid_t uid)
273 {
274 if (uid < 0 || pid < 0) {
275 ZLOGE(LOG_LABEL, "uid(%{public}d) or pid(%{public}d) is invalid", uid, pid);
276 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_UID_OR_PID_FAIL, __FUNCTION__);
277 return DBINDER_CALLBACK_FILL_DATA_ERR;
278 }
279
280 sptr<IRemoteObject> object = IPCProcessSkeleton::GetCurrent()->GetSAMgrObject();
281 if (object == nullptr) {
282 ZLOGE(LOG_LABEL, "GetSAMgrObject failed");
283 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SA_OBJECT_NULL, __FUNCTION__);
284 return DBINDER_CALLBACK_FILL_DATA_ERR;
285 }
286 IPCObjectProxy *samgr = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
287 std::string sessionName = samgr->GetSessionNameForPidUid(uid, pid);
288 if (sessionName.empty()) {
289 ZLOGE(LOG_LABEL, "GetSessionNameForPidUid failed");
290 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SESSION_NAME_FAIL, __FUNCTION__);
291 return DBINDER_CALLBACK_FILL_DATA_ERR;
292 }
293
294 int ret = AddDBinderCommAuth(pid, uid, sessionName);
295 if (ret != ERR_NONE) {
296 ZLOGE(LOG_LABEL, "AddDBinderCommAuth failed");
297 return ret;
298 }
299
300 ret = SaveDBinderData(sessionName);
301 if (ret != ERR_NONE) {
302 ZLOGE(LOG_LABEL, "SaveDBinderData failed");
303 return ret;
304 }
305 return ERR_NONE;
306 }
307 } // namespace OHOS
308