1 /*
2 * Copyright (c) 2022 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 "dslm_ipc_process.h"
17
18 #include "dslm_callback_info.h"
19 #include "dslm_core_process.h"
20 #include "ipc_skeleton.h"
21 #include "securec.h"
22 #include "utils_list.h"
23 #include "utils_log.h"
24 #include "utils_mem.h"
25 #include "utils_mutex.h"
26
27 #define DFT_TIMEOUT 45
28 const uint32_t MAX_TIMEOUT = 60;
29 const uint32_t MIN_TIMEOUT = 1;
30 const uint32_t WARNING_GATE = 64;
31 const uint32_t COOKIE_SHIFT = 32;
32
GetRemoteStubList(void)33 static DslmRemoteStubList *GetRemoteStubList(void)
34 {
35 static DslmRemoteStubListNode head = {
36 .node = INIT_LIST(head.node),
37 .key = 0,
38 .reply = NULL
39 };
40 static Mutex mutex = INITED_MUTEX;
41 static DslmRemoteStubList stubList = { .head = &head, .size = 0, .mutex = &mutex};
42 return &stubList;
43 }
44
SetRemoteStubStatus(IpcIo * reply,int32_t status)45 static inline void SetRemoteStubStatus(IpcIo *reply, int32_t status)
46 {
47 WriteInt32(reply, status);
48 }
49
DslmGetRequestFromParcel(IpcIo * req,DeviceIdentify * identity,RequestOption * option,uint32_t * cookie)50 static int32_t DslmGetRequestFromParcel(IpcIo *req, DeviceIdentify *identity,
51 RequestOption *option, uint32_t *cookie)
52 {
53 ReadUint32(req, &identity->length);
54 uint32_t *dataRead = ReadBuffer(req, DEVICE_ID_MAX_LEN);
55 if (dataRead == NULL) {
56 SECURITY_LOG_ERROR("unexpected input, buffer error");
57 return ERR_INVALID_PARA;
58 }
59 if (memcpy_s(identity->identity, DEVICE_ID_MAX_LEN, dataRead, DEVICE_ID_MAX_LEN) != EOK) {
60 SECURITY_LOG_ERROR("unexpected input, buffer copy error");
61 return ERR_INVALID_PARA;
62 }
63 FREE(dataRead);
64 dataRead = NULL;
65
66 ReadUint64(req, &option->challenge);
67 ReadUint32(req, &option->timeout);
68 if (option->timeout < MIN_TIMEOUT || option->timeout > MAX_TIMEOUT) {
69 option->timeout = DFT_TIMEOUT;
70 }
71 ReadUint32(req, &option->extra);
72 ReadUint32(req, cookie);
73 if (cookie == 0) {
74 SECURITY_LOG_ERROR("unexpected input, cookie error");
75 return ERR_INVALID_PARA;
76 }
77
78 return SUCCESS;
79 }
80
DslmPushRemoteStub(uint32_t owner,uint32_t cookie,IpcIo * reply)81 static BOOL DslmPushRemoteStub(uint32_t owner, uint32_t cookie, IpcIo *reply)
82 {
83 if (GetRemoteStubList()->size > WARNING_GATE) {
84 SECURITY_LOG_WARN("remote objects max warning");
85 }
86 uint64_t key = ((uint64_t)owner << COOKIE_SHIFT) | cookie;
87 DslmRemoteStubListNode *item = (DslmRemoteStubListNode *)MALLOC(sizeof(DslmRemoteStubListNode));
88 if (item == NULL) {
89 SECURITY_LOG_ERROR("malloc failed, node is null");
90 return false;
91 }
92 memset_s(item, sizeof(DslmRemoteStubListNode), 0, sizeof(DslmRemoteStubListNode));
93
94 item->key = key;
95 item->reply = reply;
96 LockMutex(GetRemoteStubList()->mutex);
97 AddListNode(&item->node, &GetRemoteStubList()->head->node);
98 GetRemoteStubList()->size++;
99 UnlockMutex(GetRemoteStubList()->mutex);
100 return true;
101 }
102
DslmPopRemoteStub(uint32_t owner,uint32_t cookie)103 static IpcIo *DslmPopRemoteStub(uint32_t owner, uint32_t cookie)
104 {
105 IpcIo *reply = NULL;
106 ListNode *node = NULL;
107 ListNode *temp = NULL;
108
109 LockMutex(GetRemoteStubList()->mutex);
110 uint64_t key = ((uint64_t)owner << COOKIE_SHIFT) | cookie;
111 FOREACH_LIST_NODE_SAFE (node, &GetRemoteStubList()->head->node, temp) {
112 DslmRemoteStubListNode *item = LIST_ENTRY(node, DslmRemoteStubListNode, node);
113 if (item->key == key) {
114 SECURITY_LOG_INFO("pop remote stub");
115 reply = item->reply;
116 RemoveListNode(node);
117 if (GetRemoteStubList()->size > 0) {
118 GetRemoteStubList()->size--;
119 } else {
120 SECURITY_LOG_ERROR("list size is abnormal, size = %u", GetRemoteStubList()->size);
121 }
122 FREE(item);
123 break;
124 }
125 }
126 UnlockMutex(GetRemoteStubList()->mutex);
127 return reply;
128 }
129
ProcessCallback(uint32_t owner,uint32_t cookie,uint32_t result,const DslmCallbackInfo * info)130 static void ProcessCallback(uint32_t owner, uint32_t cookie, uint32_t result, const DslmCallbackInfo *info)
131 {
132 IpcIo *reply = NULL;
133 if ((cookie == 0) || (info == NULL)) {
134 return;
135 }
136
137 reply = DslmPopRemoteStub(owner, cookie);
138 if (reply == NULL) {
139 SECURITY_LOG_ERROR("no such remote stub");
140 return;
141 }
142
143 WriteUint32(reply, result);
144 WriteUint32(reply, info->level);
145 if (info->extraBuff != NULL && info->extraLen != 0) {
146 WriteUint32(reply, info->extraLen);
147 WriteBuffer(reply, info->extraBuff, info->extraLen);
148 }
149 SECURITY_LOG_INFO("process callback succ");
150 }
151
DslmProcessGetDeviceSecurityLevel(IUnknown * iUnknown,IpcIo * req,IpcIo * reply)152 int32_t DslmProcessGetDeviceSecurityLevel(IUnknown *iUnknown, IpcIo *req, IpcIo *reply)
153 {
154 DeviceIdentify identity;
155 RequestOption option;
156 uint32_t cookie;
157
158 int32_t ret = DslmGetRequestFromParcel(req, &identity, &option, &cookie);
159 if (ret != SUCCESS) {
160 SECURITY_LOG_ERROR("DslmGetRequestFromParcel failed, ret = %d", ret);
161 return ret;
162 }
163
164 uint64_t owner = GetCallingPid();
165 DslmPushRemoteStub(owner, cookie, reply);
166 ret = OnRequestDeviceSecLevelInfo(&identity, &option, owner, cookie, ProcessCallback);
167 if (ret != SUCCESS) {
168 SECURITY_LOG_ERROR("OnRequestDeviceSecLevelInfo failed, ret = %d", ret);
169 SetRemoteStubStatus(reply, ret);
170 DslmPopRemoteStub(owner, cookie);
171 return ret;
172 }
173 return SUCCESS;
174 }