• 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 "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