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