b0c698df创建于 1月16日历史提交
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dslm_ipc_process.h"

#include <map>
#include <utility>

#include "ipc_skeleton.h"
#include "iremote_broker.h"
#include "securec.h"

#include "dslm_callback_proxy.h"
#include "dslm_core_process.h"
#include "dslm_device_list.h"
#include "utils_log.h"

namespace {
constexpr uint32_t DFT_TIMEOUT = 45;
constexpr uint32_t MAX_TIMEOUT = 60;
constexpr uint32_t MIN_TIMEOUT = 1;
constexpr uint32_t WARNING_GATE = 64;
constexpr uint32_t COOKIE_SHIFT = 32;
} // namespace

namespace OHOS {
namespace Security {
namespace DeviceSecurityLevel {

static void ProcessCallback(uint32_t owner, uint32_t cookie, uint32_t result, const DslmCallbackInfo *info)
{
    if ((cookie == 0) || (info == nullptr)) {
        return;
    }
    auto object = Singleton<DslmIpcProcess::RemoteHolder>::GetInstance().Pop(owner, cookie);
    if (object == nullptr) {
        SECURITY_LOG_ERROR("Pop failed");
        return;
    }

    auto proxy = iface_cast<IDeviceSecurityLevelCallback>(object);
    if (proxy == nullptr) {
        SECURITY_LOG_ERROR("iface_cast failed");
        return;
    }
    DslmCallbackProxy::ResponseInfo resInfo = {result, info->level, info->extraBuff, info->extraLen};
    proxy->ResponseDeviceSecurityLevel(cookie, resInfo);
}

int32_t DslmIpcProcess::DslmGetRequestFromParcel(MessageParcel &data, DeviceIdentify &identify, RequestOption &option,
    sptr<IRemoteObject> &object, uint32_t &cookie)
{
    uint32_t expected = sizeof(DeviceIdentify) + sizeof(RequestOption) + sizeof(uint32_t);
    uint32_t actual = data.GetReadableBytes();
    if (expected >= actual) {
        SECURITY_LOG_ERROR("unexpected input, length error");
        return ERR_INVALID_PARA;
    }

    identify.length = data.ReadUint32();

    const uint8_t *dataRead = data.ReadBuffer(DEVICE_ID_MAX_LEN);
    if (dataRead == nullptr) {
        SECURITY_LOG_ERROR("unexpected input, buffer error");
        return ERR_INVALID_PARA;
    }
    if (memcpy_s(identify.identity, DEVICE_ID_MAX_LEN, dataRead, DEVICE_ID_MAX_LEN) != EOK) {
        SECURITY_LOG_ERROR("unexpected input, buffer copy error");
        return ERR_INVALID_PARA;
    }

    option.challenge = data.ReadUint64();
    option.timeout = data.ReadUint32();
    if (option.timeout < MIN_TIMEOUT || option.timeout > MAX_TIMEOUT) {
        option.timeout = DFT_TIMEOUT;
    }

    option.extra = data.ReadUint32();

    object = data.ReadRemoteObject();
    if (object == nullptr) {
        SECURITY_LOG_ERROR("unexpected input, callback ipc error");
        return ERR_INVALID_PARA;
    }
    cookie = data.ReadUint32();
    if (cookie == 0) {
        SECURITY_LOG_ERROR("unexpected input, cookie error");
        return ERR_INVALID_PARA;
    }

    return SUCCESS;
}

int32_t DslmIpcProcess::DslmSetResponseToParcel(MessageParcel &reply, uint32_t status)
{
    auto owner = IPCSkeleton::GetCallingPid();
    auto success = reply.WriteUint32(status);
    if (!success) {
        Singleton<RemoteHolder>::GetInstance().Pop(owner, status);
        return ERR_IPC_RET_PARCEL_ERR;
    }
    return SUCCESS;
}

int32_t DslmIpcProcess::DslmProcessGetDeviceSecurityLevel(const DeviceIdentify *identify, const RequestOption *option,
    uint32_t cookie, const sptr<IRemoteObject> &callback)
{
    auto owner = IPCSkeleton::GetCallingPid();
    Singleton<RemoteHolder>::GetInstance().Push(owner, cookie, callback);

    int32_t ret = OnRequestDeviceSecLevelInfo(identify, option, owner, cookie, ProcessCallback);
    if (ret != SUCCESS) {
        Singleton<RemoteHolder>::GetInstance().Pop(owner, cookie);
        SECURITY_LOG_ERROR("OnRequestDeviceSecLevelInfo failed, ret = %{public}d", ret);
        return ret;
    }

    return SUCCESS;
}

bool DslmIpcProcess::RemoteHolder::Push(uint32_t owner, uint32_t cookie, const sptr<IRemoteObject> &object)
{
    std::lock_guard<std::mutex> lock(mutex_);
    uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
    map_[key] = object;
    if (map_.size() > WARNING_GATE) {
        SECURITY_LOG_WARN("remote objects max warning");
    }
    return true;
}

sptr<IRemoteObject> DslmIpcProcess::RemoteHolder::Pop(uint32_t owner, uint32_t cookie)
{
    std::lock_guard<std::mutex> lock(mutex_);
    uint64_t key = (static_cast<uint64_t>(owner) << COOKIE_SHIFT) | cookie;
    auto iter = map_.find(key);
    if (iter == map_.end()) {
        return nullptr;
    }
    auto obj = iter->second;
    map_.erase(iter);
    return obj;
}
} // namespace DeviceSecurityLevel
} // namespace Security
} // namespace OHOS