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 <map>
19 #include <utility>
20
21 #include "ipc_skeleton.h"
22 #include "iremote_broker.h"
23 #include "securec.h"
24
25 #include "dslm_callback_info.h"
26 #include "dslm_callback_proxy.h"
27 #include "dslm_core_process.h"
28 #include "dslm_device_list.h"
29 #include "utils_log.h"
30
31 namespace {
32 constexpr uint32_t DFT_TIMEOUT = 45;
33 constexpr uint32_t MAX_TIMEOUT = 60;
34 constexpr uint32_t MIN_TIMEOUT = 1;
35 constexpr uint32_t WARNING_GATE = 64;
36 constexpr uint32_t COOKIE_SHIFT = 32;
37 constexpr uint32_t UNLOAD_TIMEOUT = 10000;
38 } // namespace
39
40 namespace OHOS {
41 namespace Security {
42 namespace DeviceSecurityLevel {
ProcessCallback(uint32_t owner,uint32_t cookie,uint32_t result,const DslmCallbackInfo * info)43 static void ProcessCallback(uint32_t owner, uint32_t cookie, uint32_t result, const DslmCallbackInfo *info)
44 {
45 if ((cookie == 0) || (info == nullptr)) {
46 return;
47 }
48 auto object = Singleton<DslmIpcProcess::RemoteHolder>::GetInstance().Pop(owner, cookie);
49 if (object == nullptr) {
50 SECURITY_LOG_ERROR("Pop failed");
51 return;
52 }
53
54 auto proxy = iface_cast<DslmCallbackProxy>(object);
55 if (proxy == nullptr) {
56 SECURITY_LOG_ERROR("iface_cast failed");
57 return;
58 }
59 DslmCallbackProxy::ResponseInfo resInfo = {result, info->level, info->extraBuff, info->extraLen};
60 proxy->ResponseDeviceSecurityLevel(cookie, resInfo);
61 }
62
DslmGetRequestFromParcel(MessageParcel & data,DeviceIdentify & identify,RequestOption & option,sptr<IRemoteObject> & object,uint32_t & cookie)63 int32_t DslmIpcProcess::DslmGetRequestFromParcel(MessageParcel &data, DeviceIdentify &identify, RequestOption &option,
64 sptr<IRemoteObject> &object, uint32_t &cookie)
65 {
66 uint32_t expected = sizeof(DeviceIdentify) + sizeof(RequestOption) + sizeof(uint32_t);
67 uint32_t actual = data.GetReadableBytes();
68 if (expected >= actual) {
69 SECURITY_LOG_ERROR("unexpected input, length error");
70 return ERR_INVALID_PARA;
71 }
72
73 identify.length = data.ReadUint32();
74
75 const uint8_t *dataRead = data.ReadBuffer(DEVICE_ID_MAX_LEN);
76 if (dataRead == nullptr) {
77 SECURITY_LOG_ERROR("unexpected input, buffer error");
78 return ERR_INVALID_PARA;
79 }
80 if (memcpy_s(identify.identity, DEVICE_ID_MAX_LEN, dataRead, DEVICE_ID_MAX_LEN) != EOK) {
81 SECURITY_LOG_ERROR("unexpected input, buffer copy error");
82 return ERR_INVALID_PARA;
83 }
84
85 option.challenge = data.ReadUint64();
86 option.timeout = data.ReadUint32();
87 if (option.timeout < MIN_TIMEOUT || option.timeout > MAX_TIMEOUT) {
88 option.timeout = DFT_TIMEOUT;
89 }
90
91 option.extra = data.ReadUint32();
92
93 object = data.ReadRemoteObject();
94 if (object == nullptr) {
95 SECURITY_LOG_ERROR("unexpected input, callback ipc error");
96 return ERR_INVALID_PARA;
97 }
98 cookie = data.ReadUint32();
99 if (cookie == 0) {
100 SECURITY_LOG_ERROR("unexpected input, cookie error");
101 return ERR_INVALID_PARA;
102 }
103
104 return SUCCESS;
105 }
106
DslmSetResponseToParcel(MessageParcel & reply,uint32_t status)107 int32_t DslmIpcProcess::DslmSetResponseToParcel(MessageParcel &reply, uint32_t status)
108 {
109 auto success = reply.WriteUint32(status);
110 if (!success) {
111 return ERR_IPC_RET_PARCEL_ERR;
112 }
113 return SUCCESS;
114 }
115
TimerProcessUnloadSystemAbility(const void * context)116 static void TimerProcessUnloadSystemAbility(const void *context)
117 {
118 (void)context;
119
120 if (!JudgeListDeviceType()) {
121 return;
122 }
123
124 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
125 if (samgrProxy == nullptr) {
126 SECURITY_LOG_ERROR("get samgr failed");
127 return;
128 }
129
130 int32_t ret = samgrProxy->UnloadSystemAbility(DEVICE_SECURITY_LEVEL_MANAGER_SA_ID);
131 if (ret != ERR_OK) {
132 SECURITY_LOG_ERROR("unload system ability failed");
133 return;
134 }
135 SECURITY_LOG_INFO("unload system ability succeed");
136 }
137
SetSystemAbilityUnloadSchedule(TimerHandle & handle)138 static void SetSystemAbilityUnloadSchedule(TimerHandle &handle)
139 {
140 if (!JudgeListDeviceType()) {
141 return;
142 }
143
144 if (handle != 0) {
145 DslmUtilsStopTimerTask(handle);
146 }
147
148 handle = DslmUtilsStartOnceTimerTask(UNLOAD_TIMEOUT, TimerProcessUnloadSystemAbility, nullptr);
149 }
150
DslmProcessGetDeviceSecurityLevel(MessageParcel & data,MessageParcel & reply)151 int32_t DslmIpcProcess::DslmProcessGetDeviceSecurityLevel(MessageParcel &data, MessageParcel &reply)
152 {
153 DeviceIdentify identity;
154 RequestOption option;
155 sptr<IRemoteObject> callback;
156 uint32_t cookie;
157
158 SetSystemAbilityUnloadSchedule(unloadTimerHandle_);
159
160 int32_t ret = DslmGetRequestFromParcel(data, identity, option, callback, cookie);
161 if (ret != SUCCESS) {
162 SECURITY_LOG_ERROR("DslmGetRequestFromParcel failed, ret = %{public}d", ret);
163 return ret;
164 }
165
166 auto owner = IPCSkeleton::GetCallingPid();
167 Singleton<RemoteHolder>::GetInstance().Push(owner, cookie, callback);
168
169 ret = OnRequestDeviceSecLevelInfo(&identity, &option, owner, cookie, ProcessCallback);
170 if (ret != SUCCESS) {
171 Singleton<RemoteHolder>::GetInstance().Pop(owner, cookie);
172 SECURITY_LOG_ERROR("OnRequestDeviceSecLevelInfo failed, ret = %{public}d", ret);
173 return ret;
174 }
175
176 ret = DslmSetResponseToParcel(reply, cookie);
177 if (ret != SUCCESS) {
178 Singleton<RemoteHolder>::GetInstance().Pop(owner, cookie);
179 SECURITY_LOG_ERROR("DslmSetResponseToParcel failed, ret = %{public}d", ret);
180 return ret;
181 }
182 return SUCCESS;
183 }
184
Push(uint32_t owner,uint32_t cookie,const sptr<IRemoteObject> & object)185 bool DslmIpcProcess::RemoteHolder::Push(uint32_t owner, uint32_t cookie, const sptr<IRemoteObject> &object)
186 {
187 std::lock_guard<std::mutex> lock(mutex_);
188 uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
189 map_[key] = object;
190 if (map_.size() > WARNING_GATE) {
191 SECURITY_LOG_WARN("remote objects max warning");
192 }
193 return true;
194 }
195
Pop(uint32_t owner,uint32_t cookie)196 sptr<IRemoteObject> DslmIpcProcess::RemoteHolder::Pop(uint32_t owner, uint32_t cookie)
197 {
198 std::lock_guard<std::mutex> lock(mutex_);
199 uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
200 auto iter = map_.find(key);
201 if (iter == map_.end()) {
202 return nullptr;
203 }
204 auto obj = iter->second;
205 map_.erase(iter);
206 return obj;
207 }
208 } // namespace DeviceSecurityLevel
209 } // namespace Security
210 } // namespace OHOS
211