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