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 #include "ipc_object_stub.h"
16 #include <string>
17 #include "ipc_types.h"
18 #include "ipc_debug.h"
19 #include "ipc_process_skeleton.h"
20 #include "ipc_thread_skeleton.h"
21 #include "log_tags.h"
22 #include "ipc_skeleton.h"
23 #include "app_log_wrapper.h"
24
25 #ifdef CONFIG_IPC_RPC
26 #include "dbinder_databus_invoker.h"
27 #include "dbinder_error_code.h"
28 #include "ISessionService.h"
29 #endif
30
31 namespace OHOS {
32 using namespace OHOS::AppExecFwk;
33 using namespace OHOS::HiviewDFX;
34 #ifdef CONFIG_IPC_RPC
35 static constexpr HiLogLabel LABEL = {LOG_CORE, LOG_ID_IPC, "IPCObjectStub"};
36 // Authentication information can be added only for processes with system permission.
37 static constexpr pid_t ALLOWED_UID = 10000;
38 // Only the samgr can obtain the UID and PID.
39 static constexpr pid_t SYSTEM_SERVER_UID = 1000;
40 #endif
IPCObjectStub(std::u16string descriptor)41 IPCObjectStub::IPCObjectStub(std::u16string descriptor) : IRemoteObject(descriptor)
42 {}
43
~IPCObjectStub()44 IPCObjectStub::~IPCObjectStub()
45 {
46 APP_LOGI("IPCObjectStub destroyed");
47 }
48
IsDeviceIdIllegal(const std::string & deviceID)49 bool IPCObjectStub::IsDeviceIdIllegal(const std::string &deviceID)
50 {
51 if (deviceID.empty() || deviceID.length() > DEVICEID_LENGTH) {
52 return true;
53 }
54 return false;
55 }
56
GetObjectRefCount()57 int32_t IPCObjectStub::GetObjectRefCount()
58 {
59 int kRefCount = 0;
60 int refCount = GetSptrRefCount();
61 IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
62
63 if (invoker != nullptr) {
64 kRefCount = invoker->GetObjectRefCount(this);
65 }
66
67 /* the kernel has already acquire the reference
68 * on this object, so we need to decrement by 1.
69 */
70 if (kRefCount > 0) {
71 refCount += kRefCount - 1;
72 }
73
74 return refCount;
75 }
76
Dump(int fd,const std::vector<std::u16string> & args)77 int IPCObjectStub::Dump(int fd, const std::vector<std::u16string> &args)
78 {
79 const size_t numArgs = args.size();
80 APP_LOGI("Invalid call on Stub:fd:%{public}d, args:%{public}zu", fd, numArgs);
81 return ERR_NONE;
82 }
83
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)84 int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
85 {
86 int result = ERR_NONE;
87 switch (code) {
88 #ifdef CONFIG_IPC_RPC
89 case DBINDER_OBITUARY_TRANSACTION: {
90 if (IPCSkeleton::GetCallingUid() != SYSTEM_SERVER_UID) {
91 APP_LOGI(LABEL, "%s: DBINDER_OBITUARY_TRANSACTION unauthenticated user ", __func__);
92 result = IPC_STUB_INVALID_DATA_ERR;
93 break;
94 }
95 if (data.ReadInt32() == IRemoteObject::DeathRecipient::NOTICE_DEATH_RECIPIENT) {
96 result = NoticeServiceDie(data, reply, option);
97 } else {
98 result = IPC_STUB_INVALID_DATA_ERR;
99 }
100 break;
101 }
102 #endif
103 default:
104 result = IPC_STUB_UNKNOW_TRANS_ERR;
105 APP_LOGI("unknown OnRemoteRequest code = %{public}u", code);
106 break;
107 }
108
109 return result;
110 }
111
OnRemoteDump(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)112 int IPCObjectStub::OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
113 {
114 int result = ERR_NONE;
115 int fd = data.ReadFileDescriptor();
116 std::vector<std::u16string> args;
117 if (fd != INVALID_FD) {
118 if (data.ReadString16Vector(&args)) {
119 result = Dump(fd, args);
120 }
121 ::close(fd);
122 } else {
123 result = IPC_STUB_INVALID_DATA_ERR;
124 }
125 return result;
126 }
127
SendRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)128 int IPCObjectStub::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
129 {
130 int result = ERR_NONE;
131 switch (code) {
132 case PING_TRANSACTION: {
133 if (!reply.WriteInt32(ERR_NONE)) {
134 result = IPC_STUB_WRITE_PARCEL_ERR;
135 }
136 break;
137 }
138 case INTERFACE_TRANSACTION: {
139 std::u16string descriptor = GetObjectDescriptor();
140 if (!reply.WriteString16(descriptor)) {
141 APP_LOGI("write to parcel fail");
142 result = IPC_STUB_WRITE_PARCEL_ERR;
143 }
144 break;
145 }
146 case SYNCHRONIZE_REFERENCE: {
147 int refCount = GetObjectRefCount();
148 // when handle transaction the invoker would try to acquire
149 // the object's reference to defense the object being released
150 // so the actual we should decrement the temporary reference.
151 --refCount;
152 reply.WriteInt32(refCount);
153 break;
154 }
155 case DUMP_TRANSACTION: {
156 if (!IPCSkeleton::IsLocalCalling()) {
157 APP_LOGI("do not allow dump");
158 break;
159 }
160 result = OnRemoteDump(code, data, reply, option);
161 break;
162 }
163 #ifdef CONFIG_IPC_RPC
164 case INVOKE_LISTEN_THREAD: {
165 if (!IPCSkeleton::IsLocalCalling() || IPCSkeleton::GetCallingUid() >= ALLOWED_UID) {
166 APP_LOGI("%s: INVOKE_LISTEN_THREAD unauthenticated user ", __func__);
167 result = IPC_STUB_INVALID_DATA_ERR;
168 break;
169 }
170 result = InvokerThread(code, data, reply, option);
171 break;
172 }
173 case GET_PROTO_INFO: {
174 result = ProcessProto(code, data, reply, option);
175 break;
176 }
177 case DBINDER_INCREFS_TRANSACTION: {
178 if (IPCSkeleton::IsLocalCalling()) {
179 APP_LOGI("%s: cannot be called in same device", __func__);
180 result = IPC_STUB_INVALID_DATA_ERR;
181 break;
182 }
183 result = IncStubRefs(data, reply);
184 break;
185 }
186 case DBINDER_DECREFS_TRANSACTION: {
187 if (IPCSkeleton::IsLocalCalling()) {
188 APP_LOGI("%s: cannot be called in same device", __func__);
189 result = IPC_STUB_INVALID_DATA_ERR;
190 break;
191 }
192 result = DecStubRefs(data, reply);
193 break;
194 }
195 case DBINDER_ADD_COMMAUTH: {
196 if (IPCSkeleton::IsLocalCalling() || IPCSkeleton::GetCallingUid() >= ALLOWED_UID) {
197 APP_LOGI("%s: DBINDER_ADD_COMMAUTH unauthenticated user ", __func__);
198 result = IPC_STUB_INVALID_DATA_ERR;
199 break;
200 }
201 result = AddAuthInfo(data, reply);
202 break;
203 }
204 case GET_UIDPID_INFO: {
205 if (!IPCSkeleton::IsLocalCalling()) {
206 APP_LOGI("GET_UIDPID_INFO message is not from sa manager");
207 result = IPC_STUB_INVALID_DATA_ERR;
208 break;
209 }
210 std::string sessionName = GetDataBusName();
211 if (sessionName.empty()) {
212 APP_LOGI("sessionName is empty");
213 result = IPC_STUB_CREATE_BUS_SERVER_ERR;
214 break;
215 }
216 if (!reply.WriteString(sessionName)) {
217 APP_LOGI("write to parcel fail");
218 result = IPC_STUB_INVALID_DATA_ERR;
219 break;
220 }
221 break;
222 }
223 case GRANT_DATABUS_NAME: {
224 if (!IPCSkeleton::IsLocalCalling() || getuid() != SYSTEM_SERVER_UID) {
225 APP_LOGI("GRANT_DATABUS_NAME message is excluded in sa manager");
226 result = IPC_STUB_INVALID_DATA_ERR;
227 break;
228 }
229 result = GrantDataBusName(code, data, reply, option);
230 break;
231 }
232 #endif
233 default:
234 result = OnRemoteRequest(code, data, reply, option);
235 break;
236 }
237
238 return result;
239 }
240
OnFirstStrongRef(const void * objectId)241 void IPCObjectStub::OnFirstStrongRef(const void *objectId)
242 {
243 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
244
245 if (current != nullptr) {
246 current->AttachObject(this);
247 }
248 }
249
OnLastStrongRef(const void * objectId)250 void IPCObjectStub::OnLastStrongRef(const void *objectId)
251 {
252 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
253
254 if (current != nullptr) {
255 current->DetachObject(this);
256 #ifdef CONFIG_IPC_RPC
257 current->DetachStubRecvRefInfo(this);
258 current->DetachStubSendRefInfo(this);
259 (void)current->DetachStubRefTimes(this);
260 current->DetachCommAuthInfoByStub(this);
261 uint64_t stubIndex = current->EraseStubIndex(reinterpret_cast<IRemoteObject *>(this));
262 current->DetachAppInfoToStubIndex(stubIndex);
263 #endif
264 }
265 }
266
AddDeathRecipient(const sptr<DeathRecipient> & recipient)267 bool IPCObjectStub::AddDeathRecipient(const sptr<DeathRecipient> &recipient)
268 {
269 return true;
270 }
271
RemoveDeathRecipient(const sptr<DeathRecipient> & recipient)272 bool IPCObjectStub::RemoveDeathRecipient(const sptr<DeathRecipient> &recipient)
273 {
274 return false;
275 }
276
GetCallingPid()277 pid_t IPCObjectStub::GetCallingPid()
278 {
279 return IPCSkeleton::GetCallingPid();
280 }
281
GetCallingUid()282 pid_t IPCObjectStub::GetCallingUid()
283 {
284 return IPCSkeleton::GetCallingUid();
285 }
286
ProcessProto(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)287 int32_t IPCObjectStub::ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
288 {
289 int result = ERR_NONE;
290 APP_LOGI("IPCObjectStub::ProcessProto called, type = 0, normal stub object");
291 if (!reply.WriteUint32(IRemoteObject::IF_PROT_BINDER)) {
292 APP_LOGI("write to parcel fail");
293 result = IPC_STUB_WRITE_PARCEL_ERR;
294 }
295 return result;
296 }
297
298 #ifdef CONFIG_IPC_RPC
InvokerThread(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)299 int32_t IPCObjectStub::InvokerThread(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
300 {
301 switch (data.ReadUint32()) {
302 case IRemoteObject::DATABUS_TYPE: {
303 if (InvokerDataBusThread(data, reply) != ERR_NONE) {
304 APP_LOGI("Invoker databus thread fail");
305 return IPC_STUB_INVOKE_THREAD_ERR;
306 }
307 break;
308 }
309 default: {
310 APP_LOGI("InvokerThread Invalid Type");
311 return IPC_STUB_INVALID_DATA_ERR;
312 }
313 }
314
315 return ERR_NONE;
316 }
317
InvokerDataBusThread(MessageParcel & data,MessageParcel & reply)318 int32_t IPCObjectStub::InvokerDataBusThread(MessageParcel &data, MessageParcel &reply)
319 {
320 std::string deviceId = data.ReadString();
321 uint32_t remotePid = data.ReadUint32();
322 uint32_t remoteUid = data.ReadUint32();
323 std::string remoteDeviceId = data.ReadString();
324 std::string sessionName = data.ReadString();
325 if (IsDeviceIdIllegal(deviceId) || IsDeviceIdIllegal(remoteDeviceId) || sessionName.empty()) {
326 APP_LOGI("%s: device ID is invalid or session name nil", __func__);
327 return IPC_STUB_INVALID_DATA_ERR;
328 }
329
330 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
331 if (current == nullptr) {
332 APP_LOGI("IPCProcessSkeleton is nullptr");
333 return IPC_STUB_CURRENT_NULL_ERR;
334 }
335 if (!current->CreateSoftbusServer(sessionName)) {
336 APP_LOGI("%s: fail to create databus server", __func__);
337 return IPC_STUB_CREATE_BUS_SERVER_ERR;
338 }
339
340 uint64_t stubIndex = current->AddStubByIndex(this);
341 if (stubIndex == 0) {
342 APP_LOGI("%s: add stub fail", __func__);
343 return IPC_STUB_INVALID_DATA_ERR;
344 }
345 if (!reply.WriteUint64(stubIndex) || !reply.WriteString(sessionName) || !reply.WriteString(deviceId)) {
346 APP_LOGI("%s: write to parcel fail", __func__);
347 return IPC_STUB_INVALID_DATA_ERR;
348 }
349 if (!current->AttachAppInfoToStubIndex(remotePid, remoteUid, remoteDeviceId, stubIndex)) {
350 APP_LOGI("fail to attach appinfo to stubIndex, maybe attach already");
351 }
352 if (!current->AttachCommAuthInfo(this, remotePid, remoteUid, remoteDeviceId)) {
353 APP_LOGI("fail to attach comm auth info");
354 }
355
356 return ERR_NONE;
357 }
358
NoticeServiceDie(MessageParcel & data,MessageParcel & reply,MessageOption & option)359 int32_t IPCObjectStub::NoticeServiceDie(MessageParcel &data, MessageParcel &reply, MessageOption &option)
360 {
361 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
362 if (current == nullptr) {
363 APP_LOGI("%s: current is null", __func__);
364 return IPC_STUB_CURRENT_NULL_ERR;
365 }
366
367 IPCObjectProxy *ipcProxy = current->QueryCallbackProxy(this);
368 if (ipcProxy == nullptr) {
369 APP_LOGI("%s: ipc proxy is null", __func__);
370 return IPC_STUB_INVALID_DATA_ERR;
371 }
372
373 ipcProxy->SendObituary();
374
375 if (!current->DetachCallbackStub(this)) {
376 APP_LOGI("%s: fail to detach callback stub", __func__);
377 // do nothing, RemoveDeathRecipient can delete this too
378 }
379
380 return ERR_NONE;
381 }
382
IncStubRefs(MessageParcel & data,MessageParcel & reply)383 int32_t IPCObjectStub::IncStubRefs(MessageParcel &data, MessageParcel &reply)
384 {
385 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
386 if (current == nullptr) {
387 APP_LOGI("%s: current is null", __func__);
388 return IPC_STUB_CURRENT_NULL_ERR;
389 }
390
391 std::string deviceId = IPCSkeleton::GetCallingDeviceID();
392 if (deviceId.empty()) {
393 APP_LOGI("%s: calling error", __func__);
394 return IPC_STUB_INVALID_DATA_ERR;
395 }
396 if (!current->AttachStubRecvRefInfo(this, IPCSkeleton::GetCallingPid(), deviceId)) {
397 APP_LOGI("%s: attach stub ref info err, already in", __func__);
398 return ERR_NONE;
399 }
400
401 if (!current->DecStubRefTimes(this)) {
402 this->IncStrongRef(this);
403 }
404
405 return ERR_NONE;
406 }
407
DecStubRefs(MessageParcel & data,MessageParcel & reply)408 int32_t IPCObjectStub::DecStubRefs(MessageParcel &data, MessageParcel &reply)
409 {
410 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
411 if (current == nullptr) {
412 APP_LOGI("%s: current is null", __func__);
413 return IPC_STUB_CURRENT_NULL_ERR;
414 }
415
416 std::string deviceId = IPCSkeleton::GetCallingDeviceID();
417 current->DetachStubRefInfo(this, IPCSkeleton::GetCallingPid(), deviceId);
418 return ERR_NONE;
419 }
420
AddAuthInfo(MessageParcel & data,MessageParcel & reply)421 int32_t IPCObjectStub::AddAuthInfo(MessageParcel &data, MessageParcel &reply)
422 {
423 uint32_t remotePid = data.ReadUint32();
424 uint32_t remoteUid = data.ReadUint32();
425 std::string remoteDeviceId = data.ReadString();
426 if (IsDeviceIdIllegal(remoteDeviceId)) {
427 APP_LOGI("%s: remote deviceId is null", __func__);
428 return IPC_STUB_INVALID_DATA_ERR;
429 }
430
431 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
432 if (current == nullptr) {
433 APP_LOGI("%s: current is null", __func__);
434 return IPC_STUB_CURRENT_NULL_ERR;
435 }
436
437 if (!current->AttachCommAuthInfo(this, remotePid, remoteUid, remoteDeviceId)) {
438 APP_LOGI("fail to attach comm auth info fail");
439 return IPC_STUB_INVALID_DATA_ERR;
440 }
441 return ERR_NONE;
442 }
443
GetDataBusName()444 std::string IPCObjectStub::GetDataBusName()
445 {
446 sptr<IRemoteObject> object = IPCProcessSkeleton::GetCurrent()->GetSAMgrObject();
447 if (object == nullptr) {
448 APP_LOGI("get object is null");
449 return std::string("");
450 }
451
452 IPCObjectProxy *samgr = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
453 return samgr->GetDataBusName();
454 }
455
GrantDataBusName(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)456 int32_t IPCObjectStub::GrantDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
457 {
458 int pid = IPCSkeleton::GetCallingPid();
459 int uid = IPCSkeleton::GetCallingUid();
460 std::string sessionName = CreateDatabusName(uid, pid);
461 if (sessionName.empty()) {
462 APP_LOGI("pid/uid is invalid, pid = {public}%d, uid = {public}%d", pid, uid);
463 return IPC_STUB_INVALID_DATA_ERR;
464 }
465 if (!reply.WriteUint32(IRemoteObject::IF_PROT_DATABUS) || !reply.WriteString(sessionName)) {
466 APP_LOGI("write to parcel fail");
467 return IPC_STUB_INVALID_DATA_ERR;
468 }
469
470 return ERR_NONE;
471 }
472
CreateDatabusName(int uid,int pid)473 std::string IPCObjectStub::CreateDatabusName(int uid, int pid)
474 {
475 std::shared_ptr<ISessionService> softbusManager = ISessionService::GetInstance();
476 if (softbusManager == nullptr) {
477 APP_LOGI("fail to get softbus service");
478 return "";
479 }
480
481 std::string sessionName = "DBinder" + std::to_string(uid) + std::string("_") + std::to_string(pid);
482 if (softbusManager->GrantPermission(uid, pid, sessionName) != ERR_NONE) {
483 APP_LOGI("fail to Grant Permission softbus name");
484 return "";
485 }
486
487 return sessionName;
488 }
489 #endif
490 } // namespace OHOS
491