• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dslm_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     if (reply == NULL) {
48         SECURITY_LOG_ERROR("unexpected input, reply is NULL");
49         return;
50     }
51     WriteInt32(reply, status);
52 }
53 
DslmGetRequestFromParcel(IpcIo * req,DeviceIdentify * identity,RequestOption * option,uint32_t * cookie)54 static int32_t DslmGetRequestFromParcel(IpcIo *req, DeviceIdentify *identity,
55     RequestOption *option, uint32_t *cookie)
56 {
57     ReadUint32(req, &identity->length);
58     uint32_t *dataRead = ReadBuffer(req, DEVICE_ID_MAX_LEN);
59     if (dataRead == NULL) {
60         SECURITY_LOG_ERROR("unexpected input, buffer error");
61         return ERR_INVALID_PARA;
62     }
63     if (memcpy_s(identity->identity, DEVICE_ID_MAX_LEN, dataRead, DEVICE_ID_MAX_LEN) != EOK) {
64         SECURITY_LOG_ERROR("unexpected input, buffer copy error");
65         return ERR_INVALID_PARA;
66     }
67     FREE(dataRead);
68     dataRead = NULL;
69 
70     ReadUint64(req, &option->challenge);
71     ReadUint32(req, &option->timeout);
72     if (option->timeout < MIN_TIMEOUT || option->timeout > MAX_TIMEOUT) {
73         option->timeout = DFT_TIMEOUT;
74     }
75     ReadUint32(req, &option->extra);
76     ReadUint32(req, cookie);
77     if (cookie == 0) {
78         SECURITY_LOG_ERROR("unexpected input, cookie error");
79         return ERR_INVALID_PARA;
80     }
81 
82     return SUCCESS;
83 }
84 
DslmPushRemoteStub(uint32_t owner,uint32_t cookie,IpcIo * reply)85 static BOOL DslmPushRemoteStub(uint32_t owner, uint32_t cookie, IpcIo *reply)
86 {
87     if (GetRemoteStubList()->size > WARNING_GATE) {
88         SECURITY_LOG_WARN("remote objects max warning");
89     }
90     uint64_t key = ((uint64_t)owner << COOKIE_SHIFT) | cookie;
91     DslmRemoteStubListNode *item = (DslmRemoteStubListNode *)MALLOC(sizeof(DslmRemoteStubListNode));
92     if (item == NULL) {
93         SECURITY_LOG_ERROR("malloc failed, node is null");
94         return false;
95     }
96     memset_s(item, sizeof(DslmRemoteStubListNode), 0, sizeof(DslmRemoteStubListNode));
97 
98     item->key = key;
99     item->reply = reply;
100     LockMutex(GetRemoteStubList()->mutex);
101     AddListNode(&item->node, &GetRemoteStubList()->head->node);
102     GetRemoteStubList()->size++;
103     UnlockMutex(GetRemoteStubList()->mutex);
104     return true;
105 }
106 
DslmPopRemoteStub(uint32_t owner,uint32_t cookie)107 static IpcIo *DslmPopRemoteStub(uint32_t owner, uint32_t cookie)
108 {
109     IpcIo *reply = NULL;
110     ListNode *node = NULL;
111     ListNode *temp = NULL;
112 
113     LockMutex(GetRemoteStubList()->mutex);
114     uint64_t key = ((uint64_t)owner << COOKIE_SHIFT) | cookie;
115     FOREACH_LIST_NODE_SAFE (node, &GetRemoteStubList()->head->node, temp) {
116         DslmRemoteStubListNode *item = LIST_ENTRY(node, DslmRemoteStubListNode, node);
117         if (item->key == key) {
118             SECURITY_LOG_INFO("pop remote stub");
119             reply = item->reply;
120             RemoveListNode(node);
121             if (GetRemoteStubList()->size > 0) {
122                 GetRemoteStubList()->size--;
123             } else {
124                 SECURITY_LOG_ERROR("list size is abnormal, size = %u", GetRemoteStubList()->size);
125             }
126             FREE(item);
127             break;
128         }
129     }
130     UnlockMutex(GetRemoteStubList()->mutex);
131     return reply;
132 }
133 
ProcessCallback(uint32_t owner,uint32_t cookie,uint32_t result,const DslmCallbackInfo * info)134 static void ProcessCallback(uint32_t owner, uint32_t cookie, uint32_t result, const DslmCallbackInfo *info)
135 {
136     IpcIo *reply = NULL;
137     if ((cookie == 0) || (info == NULL)) {
138         return;
139     }
140 
141     reply = DslmPopRemoteStub(owner, cookie);
142     if (reply == NULL) {
143         SECURITY_LOG_ERROR("no such remote stub");
144         return;
145     }
146 
147     WriteUint32(reply, result);
148     WriteUint32(reply, info->level);
149     if (info->extraBuff != NULL && info->extraLen != 0) {
150         WriteUint32(reply, info->extraLen);
151         WriteBuffer(reply, info->extraBuff, info->extraLen);
152     }
153     SECURITY_LOG_INFO("process callback succ");
154 }
155 
DslmProcessGetDeviceSecurityLevel(IUnknown * iUnknown,IpcIo * req,IpcIo * reply)156 int32_t DslmProcessGetDeviceSecurityLevel(IUnknown *iUnknown, IpcIo *req, IpcIo *reply)
157 {
158     DeviceIdentify identity;
159     RequestOption option;
160     uint32_t cookie;
161 
162     int32_t ret = DslmGetRequestFromParcel(req, &identity, &option, &cookie);
163     if (ret != SUCCESS) {
164         SECURITY_LOG_ERROR("DslmGetRequestFromParcel failed, ret = %d", ret);
165         return ret;
166     }
167 
168     uint64_t owner = GetCallingPid();
169     DslmPushRemoteStub(owner, cookie, reply);
170     ret = OnRequestDeviceSecLevelInfo(&identity, &option, owner, cookie, ProcessCallback);
171     if (ret != SUCCESS) {
172         SECURITY_LOG_ERROR("OnRequestDeviceSecLevelInfo failed, ret = %d", ret);
173         SetRemoteStubStatus(reply, ret);
174         DslmPopRemoteStub(owner, cookie);
175         return ret;
176     }
177     return SUCCESS;
178 }