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 "utils_log.h"
29
30 namespace {
31 constexpr uint32_t DFT_TIMEOUT = 45;
32 constexpr uint32_t MAX_TIMEOUT = 60;
33 constexpr uint32_t MIN_TIMEOUT = 1;
34 constexpr uint32_t WARNING_GATE = 64;
35 constexpr uint32_t COOKIE_SHIFT = 32;
36 } // namespace
37
38 namespace OHOS {
39 namespace Security {
40 namespace DeviceSecurityLevel {
ProcessCallback(uint32_t owner,uint32_t cookie,uint32_t result,const DslmCallbackInfo * info)41 static void ProcessCallback(uint32_t owner, uint32_t cookie, uint32_t result, const DslmCallbackInfo *info)
42 {
43 if ((cookie == 0) || (info == nullptr)) {
44 return;
45 }
46 auto object = Singleton<DslmIpcProcess::RemoteHolder>::GetInstance().Pop(owner, cookie);
47 if (object == nullptr) {
48 SECURITY_LOG_ERROR("Pop failed");
49 return;
50 }
51
52 auto proxy = iface_cast<DslmCallbackProxy>(object);
53 if (proxy == nullptr) {
54 SECURITY_LOG_ERROR("iface_cast failed");
55 return;
56 }
57 DslmCallbackProxy::ResponseInfo resInfo = {result, info->level, info->extraBuff, info->extraLen};
58 proxy->ResponseDeviceSecurityLevel(cookie, resInfo);
59 }
60
DslmGetRequestFromParcel(MessageParcel & data,DeviceIdentify & identify,RequestOption & option,sptr<IRemoteObject> & object,uint32_t & cookie)61 int32_t DslmIpcProcess::DslmGetRequestFromParcel(MessageParcel &data, DeviceIdentify &identify, RequestOption &option,
62 sptr<IRemoteObject> &object, uint32_t &cookie)
63 {
64 uint32_t expected = sizeof(DeviceIdentify) + sizeof(RequestOption) + sizeof(uint32_t);
65 uint32_t actual = data.GetReadableBytes();
66 if (expected >= actual) {
67 SECURITY_LOG_ERROR("unexpected input, length error");
68 return ERR_INVALID_PARA;
69 }
70
71 identify.length = data.ReadUint32();
72
73 const uint8_t *dataRead = data.ReadBuffer(DEVICE_ID_MAX_LEN);
74 if (dataRead == nullptr) {
75 SECURITY_LOG_ERROR("unexpected input, buffer error");
76 return ERR_INVALID_PARA;
77 }
78 if (memcpy_s(identify.identity, DEVICE_ID_MAX_LEN, dataRead, DEVICE_ID_MAX_LEN) != EOK) {
79 SECURITY_LOG_ERROR("unexpected input, buffer copy error");
80 return ERR_INVALID_PARA;
81 }
82
83 option.challenge = data.ReadUint64();
84 option.timeout = data.ReadUint32();
85 if (option.timeout < MIN_TIMEOUT || option.timeout > MAX_TIMEOUT) {
86 option.timeout = DFT_TIMEOUT;
87 }
88
89 option.extra = data.ReadUint32();
90
91 object = data.ReadRemoteObject();
92 if (object == nullptr) {
93 SECURITY_LOG_ERROR("unexpected input, callback ipc error");
94 return ERR_INVALID_PARA;
95 }
96 cookie = data.ReadUint32();
97 if (cookie == 0) {
98 SECURITY_LOG_ERROR("unexpected input, cookie error");
99 return ERR_INVALID_PARA;
100 }
101
102 return SUCCESS;
103 }
104
DslmSetResponseToParcel(MessageParcel & reply,uint32_t status)105 int32_t DslmIpcProcess::DslmSetResponseToParcel(MessageParcel &reply, uint32_t status)
106 {
107 auto success = reply.WriteUint32(status);
108 if (!success) {
109 return ERR_IPC_RET_PARCEL_ERR;
110 }
111 return SUCCESS;
112 }
113
DslmProcessGetDeviceSecurityLevel(MessageParcel & data,MessageParcel & reply)114 int32_t DslmIpcProcess::DslmProcessGetDeviceSecurityLevel(MessageParcel &data, MessageParcel &reply)
115 {
116 DeviceIdentify identity;
117 RequestOption option;
118 sptr<IRemoteObject> callback;
119 uint32_t cookie;
120
121 int32_t ret = DslmGetRequestFromParcel(data, identity, option, callback, cookie);
122 if (ret != SUCCESS) {
123 SECURITY_LOG_ERROR("DslmGetRequestFromParcel failed, ret = %{public}d", ret);
124 return ret;
125 }
126
127 auto owner = IPCSkeleton::GetCallingPid();
128 Singleton<RemoteHolder>::GetInstance().Push(owner, cookie, callback);
129
130 ret = OnRequestDeviceSecLevelInfo(&identity, &option, owner, cookie, ProcessCallback);
131 if (ret != SUCCESS) {
132 Singleton<RemoteHolder>::GetInstance().Pop(owner, cookie);
133 SECURITY_LOG_ERROR("OnRequestDeviceSecLevelInfo failed, ret = %{public}d", ret);
134 return ret;
135 }
136
137 ret = DslmSetResponseToParcel(reply, cookie);
138 if (ret != SUCCESS) {
139 Singleton<RemoteHolder>::GetInstance().Pop(owner, cookie);
140 SECURITY_LOG_ERROR("DslmSetResponseToParcel failed, ret = %{public}d", ret);
141 return ret;
142 }
143 return SUCCESS;
144 }
145
Push(uint32_t owner,uint32_t cookie,const sptr<IRemoteObject> & object)146 bool DslmIpcProcess::RemoteHolder::Push(uint32_t owner, uint32_t cookie, const sptr<IRemoteObject> &object)
147 {
148 std::lock_guard<std::mutex> lock(mutex_);
149 uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
150 map_[key] = object;
151 if (map_.size() > WARNING_GATE) {
152 SECURITY_LOG_WARN("remote objects max warning");
153 }
154 return true;
155 }
156
Pop(uint32_t owner,uint32_t cookie)157 sptr<IRemoteObject> DslmIpcProcess::RemoteHolder::Pop(uint32_t owner, uint32_t cookie)
158 {
159 std::lock_guard<std::mutex> lock(mutex_);
160 uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
161 auto iter = map_.find(key);
162 if (iter == map_.end()) {
163 return nullptr;
164 }
165 auto obj = iter->second;
166 map_.erase(iter);
167 return obj;
168 }
169 } // namespace DeviceSecurityLevel
170 } // namespace Security
171 } // namespace OHOS
172