• 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_service_stub.h"
17 
18 #include <cinttypes>
19 #include "sys_binder.h"
20 #include "string_ex.h"
21 #include "dbinder_log.h"
22 #include "dbinder_service.h"
23 #include "dbinder_death_recipient.h"
24 #include "ipc_skeleton.h"
25 
26 namespace OHOS {
27 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "DbinderServiceStub" };
28 
DBinderServiceStub(const std::string & service,const std::string & device,binder_uintptr_t object)29 DBinderServiceStub::DBinderServiceStub(const std::string &service, const std::string &device, binder_uintptr_t object)
30     : IPCObjectStub(Str8ToStr16(device + service)), serviceName_(service), deviceID_(device), binderObject_(object)
31 {
32     DBINDER_LOGI(LOG_LABEL, "new DBinderServiceStub created");
33 }
34 
~DBinderServiceStub()35 DBinderServiceStub::~DBinderServiceStub()
36 {
37     DBINDER_LOGI(LOG_LABEL, "DBinderServiceStub delete");
38 }
39 
GetServiceName()40 const std::string &DBinderServiceStub::GetServiceName()
41 {
42     return serviceName_;
43 }
44 
GetDeviceID()45 const std::string &DBinderServiceStub::GetDeviceID()
46 {
47     return deviceID_;
48 }
49 
GetBinderObject() const50 binder_uintptr_t DBinderServiceStub::GetBinderObject() const
51 {
52     return binderObject_;
53 }
54 
ProcessProto(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)55 int32_t DBinderServiceStub::ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply,
56     MessageOption &option)
57 {
58     int result = ERR_NONE;
59     sptr<DBinderService> dBinderService = DBinderService::GetInstance();
60     if (dBinderService == nullptr) {
61         DBINDER_LOGE(LOG_LABEL, "DBinderService is nullptr");
62         return DBINDER_SERVICE_PROCESS_PROTO_ERR;
63     }
64     auto session = dBinderService->QuerySessionObject(reinterpret_cast<binder_uintptr_t>(this));
65     if (session == nullptr) {
66         DBINDER_LOGE(LOG_LABEL, "client find session is null");
67         return DBINDER_SERVICE_PROCESS_PROTO_ERR;
68     }
69 
70     DBINDER_LOGI(LOG_LABEL, "serviceName = %s", session->serviceName.c_str());
71 
72     int uid = IPCSkeleton::GetCallingUid();
73     int pid = IPCSkeleton::GetCallingPid();
74     if (uid < 0 || pid < 0) {
75         DBINDER_LOGE(LOG_LABEL, "uid or pid err");
76         return DBINDER_SERVICE_PROCESS_PROTO_ERR;
77     }
78 
79     std::string localBusName = dBinderService->CreateDatabusName(uid, pid);
80     if (localBusName.empty()) {
81         DBINDER_LOGE(LOG_LABEL, "local busname nil");
82         return DBINDER_SERVICE_PROCESS_PROTO_ERR;
83     }
84 
85     switch (session->type) {
86         case IRemoteObject::DATABUS_TYPE: {
87             if (!reply.WriteUint32(IRemoteObject::IF_PROT_DATABUS) || !reply.WriteUint64(session->stubIndex) ||
88                 !reply.WriteString(session->serviceName) || !reply.WriteString(session->deviceIdInfo.toDeviceId) ||
89                 !reply.WriteString(session->deviceIdInfo.fromDeviceId) || !reply.WriteString(localBusName) ||
90                 !reply.WriteUint32(session->rpcFeatureSet)) {
91                 DBINDER_LOGE(LOG_LABEL, "write to parcel fail");
92                 return DBINDER_SERVICE_PROCESS_PROTO_ERR;
93             }
94             break;
95         }
96         default: {
97             DBINDER_LOGE(LOG_LABEL, "Invalid Type");
98             return DBINDER_SERVICE_PROCESS_PROTO_ERR;
99         }
100     }
101 
102     return result;
103 }
104 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)105 int32_t DBinderServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
106     MessageOption &option)
107 {
108     int32_t result = ERR_NONE;
109     switch (code) {
110         case GET_PROTO_INFO: {
111             result = ProcessProto(code, data, reply, option);
112             break;
113         }
114         case DBINDER_OBITUARY_TRANSACTION: {
115             DBINDER_LOGE(LOG_LABEL, "%{public}s: recv DBINDER_OBITUARY_TRANSACTION", __func__);
116             result = ProcessDeathRecipient(data, reply);
117             break;
118         }
119         default: {
120             DBINDER_LOGI(LOG_LABEL, "unknown code = %{public}u", code);
121             result = DBINDER_SERVICE_UNKNOW_TRANS_ERR;
122             break;
123         }
124     }
125 
126     return result;
127 }
128 
ProcessDeathRecipient(MessageParcel & data,MessageParcel & reply)129 int32_t DBinderServiceStub::ProcessDeathRecipient(MessageParcel &data, MessageParcel &reply)
130 {
131     int32_t processType = data.ReadInt32();
132     DBINDER_LOGE(LOG_LABEL, "%{public}s: enter, processType:%{public}d", __func__, processType);
133     if (processType == IRemoteObject::DeathRecipient::ADD_DEATH_RECIPIENT) {
134         return AddDbinderDeathRecipient(data, reply);
135     }
136 
137     if (processType == IRemoteObject::DeathRecipient::REMOVE_DEATH_RECIPIENT) {
138         return RemoveDbinderDeathRecipient(data, reply);
139     }
140 
141     return DBINDER_SERVICE_UNKNOW_TRANS_ERR;
142 }
143 
AddDbinderDeathRecipient(MessageParcel & data,MessageParcel & reply)144 int32_t DBinderServiceStub::AddDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply)
145 {
146     sptr<IRemoteObject> object = data.ReadRemoteObject();
147     if (object == nullptr) {
148         DBINDER_LOGE(LOG_LABEL, "received proxy is null");
149         return DBINDER_SERVICE_INVALID_DATA_ERR;
150     }
151 
152     std::string sessionName = data.ReadString();
153     if (sessionName.empty()) {
154         DBINDER_LOGE(LOG_LABEL, "received sessionName is null");
155         return DBINDER_SERVICE_INVALID_DATA_ERR;
156     }
157 
158     IPCObjectProxy *callbackProxy = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
159     sptr<IRemoteObject::DeathRecipient> death(new DbinderDeathRecipient());
160     DBINDER_LOGI(LOG_LABEL, "%{public}s: stub desc:%{public}s",
161         __func__, DBinderService::ConvertToSecureDeviceID(Str16ToStr8(descriptor_)).c_str());
162     // If the client dies, notify DBS to delete information of callbackProxy
163     if (!callbackProxy->AddDeathRecipient(death)) {
164         DBINDER_LOGE(LOG_LABEL, "fail to add death recipient");
165         return DBINDER_SERVICE_ADD_DEATH_ERR;
166     }
167 
168     sptr<DBinderService> dBinderService = DBinderService::GetInstance();
169     if (dBinderService == nullptr) {
170         DBINDER_LOGE(LOG_LABEL, "dBinder service is null");
171         return DBINDER_SERVICE_ADD_DEATH_ERR;
172     }
173 
174     if (!dBinderService->AttachDeathRecipient(object, death)) {
175         DBINDER_LOGE(LOG_LABEL, "fail to attach death recipient");
176         return DBINDER_SERVICE_ADD_DEATH_ERR;
177     }
178 
179     if (!dBinderService->AttachCallbackProxy(object, this)) {
180         DBINDER_LOGE(LOG_LABEL, "fail to attach callback proxy");
181         return DBINDER_SERVICE_ADD_DEATH_ERR;
182     }
183 
184     if (!dBinderService->AttachBusNameObject(callbackProxy, sessionName)) {
185         DBINDER_LOGE(LOG_LABEL, "fail to attach sessionName for callback proxy");
186         return DBINDER_SERVICE_ADD_DEATH_ERR;
187     }
188 
189     return ERR_NONE;
190 }
191 
RemoveDbinderDeathRecipient(MessageParcel & data,MessageParcel & reply)192 int32_t DBinderServiceStub::RemoveDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply)
193 {
194     sptr<IRemoteObject> object = data.ReadRemoteObject();
195     if (object == nullptr) {
196         DBINDER_LOGE(LOG_LABEL, "received proxy is null");
197         return DBINDER_SERVICE_REMOVE_DEATH_ERR;
198     }
199 
200     IPCObjectProxy *callbackProxy = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
201 
202     DBINDER_LOGI(LOG_LABEL, "%{public}s: stub desc:%{public}s",
203         __func__, DBinderService::ConvertToSecureDeviceID(Str16ToStr8(descriptor_)).c_str());
204     sptr<DBinderService> dBinderService = DBinderService::GetInstance();
205     if (dBinderService == nullptr) {
206         DBINDER_LOGE(LOG_LABEL, "dBinder service is null");
207         return DBINDER_SERVICE_REMOVE_DEATH_ERR;
208     }
209     sptr<IRemoteObject::DeathRecipient> death = dBinderService->QueryDeathRecipient(object);
210     if (death != nullptr) {
211         // Continue to clear subsequent data
212         callbackProxy->RemoveDeathRecipient(death);
213     }
214 
215     if (!dBinderService->DetachDeathRecipient(object)) {
216         DBINDER_LOGE(LOG_LABEL, "fail to detach death recipient");
217         return DBINDER_SERVICE_REMOVE_DEATH_ERR;
218     }
219 
220     if (!dBinderService->DetachCallbackProxy(object)) {
221         DBINDER_LOGE(LOG_LABEL, "fail to detach callback proxy");
222         return DBINDER_SERVICE_REMOVE_DEATH_ERR;
223     }
224 
225     if (!dBinderService->DetachBusNameObject(callbackProxy)) {
226         DBINDER_LOGE(LOG_LABEL, "fail to deatch sessionName for callback proxy");
227         return DBINDER_SERVICE_ADD_DEATH_ERR;
228     }
229 
230     return ERR_NONE;
231 }
232 } // namespace OHOS
233