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