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