worker pac

Signed-off-by: zhuhan <2281542033@qq.com>
Change-Id: I4ddda436113697924ab164d2241da7147ee4b9e8
This commit is contained in:
zhuhan
2024-07-13 14:23:44 +08:00
parent d62a80eeee
commit 563b01699a
10 changed files with 382 additions and 21 deletions
+6 -3
View File
@@ -1464,15 +1464,18 @@ void JsRuntime::InitWorkerModule(const Options& options)
{
CHECK_POINTER(jsEnv_);
std::shared_ptr<JsEnv::WorkerInfo> workerInfo = std::make_shared<JsEnv::WorkerInfo>();
workerInfo->codePath = options.codePath;
// workerInfo->codePath = options.codePath;
workerInfo->codePath = JsEnv::StringPacProtect(options.codePath);
workerInfo->isDebugVersion = options.isDebugVersion;
workerInfo->isBundle = options.isBundle;
workerInfo->packagePathStr = options.packagePathStr;
workerInfo->assetBasePathStr = options.assetBasePathStr;
workerInfo->hapPath = options.hapPath;
// workerInfo->hapPath = options.hapPath;
workerInfo->hapPath = JsEnv::StringPacProtect(options.hapPath);
workerInfo->isStageModel = options.isStageModel;
workerInfo->moduleName = options.moduleName;
workerInfo->apiTargetVersion = options.apiTargetVersion;
// workerInfo->apiTargetVersion = options.apiTargetVersion;
workerInfo->apiTargetVersion = JsEnv::DataProtect(static_cast<uintptr_t>(options.apiTargetVersion));
if (options.isJsFramework) {
SetJsFramework();
}
+13 -10
View File
@@ -211,7 +211,7 @@ void AssetHelper::operator()(const std::string& uri, uint8_t** buff, size_t* buf
if (!workerInfo_->isStageModel) {
GetAmi(ami, filePath);
} else {
ami = workerInfo_->codePath + filePath;
ami = (workerInfo_->codePath).GetOriginString() + filePath;
}
TAG_LOGD(AAFwkTag::JSRUNTIME, "Get asset, ami: %{private}s", ami.c_str());
@@ -252,10 +252,11 @@ void AssetHelper::operator()(const std::string& uri, uint8_t** buff, size_t* buf
filePath = NormalizedFileName(realPath);
// for safe reason, filePath must starts with 'abcs/' in restricted env
if (isRestricted && filePath.find(RESTRICTED_PREFIX_PATH) && workerInfo_->apiTargetVersion >= API12) {
if (isRestricted && filePath.find(RESTRICTED_PREFIX_PATH)
&& (static_cast<int32_t>(workerInfo_->apiTargetVersion.GetOriginPointer())) >= API12) {
filePath = RESTRICTED_PREFIX_PATH + filePath;
}
ami = workerInfo_->codePath + filePath;
ami = (workerInfo_->codePath).GetOriginString() + filePath;
TAG_LOGD(AAFwkTag::JSRUNTIME, "Get asset, ami: %{private}s", ami.c_str());
if (ami.find(CACHE_DIRECTORY) != std::string::npos) {
if (!ReadAmiData(ami, buff, buffSize, content, useSecureMem, isRestricted)) {
@@ -316,9 +317,10 @@ bool AssetHelper::ReadAmiData(const std::string& ami, uint8_t** buff, size_t* bu
bool& useSecureMem, bool isRestricted)
{
// Current function is a private, validity of workerInfo_ has been checked by caller.
bool apiSatisfy = workerInfo_->apiTargetVersion == 0 || workerInfo_->apiTargetVersion > API8;
int32_t apiTargetVersion = static_cast<int32_t>(workerInfo_->apiTargetVersion.GetOriginPointer());
bool apiSatisfy = apiTargetVersion == 0 || apiTargetVersion > API8;
if (workerInfo_->isStageModel && !isRestricted && apiSatisfy) {
if (workerInfo_->apiTargetVersion >= API12) {
if (apiTargetVersion >= API12) {
useSecureMem = true;
return GetSafeData(ami, buff, buffSize);
} else if (GetSafeData(ami, buff, buffSize)) {
@@ -383,7 +385,7 @@ bool AssetHelper::ReadFilePathData(const std::string& filePath, uint8_t** buff,
std::string newHapPath;
size_t pos = filePath.find('/');
if (!workerInfo_->isStageModel) {
newHapPath = workerInfo_->hapPath;
newHapPath = (workerInfo_->hapPath).GetOriginString();
} else {
for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
if (hapModuleInfo.moduleName == filePath.substr(0, pos)) {
@@ -420,11 +422,12 @@ bool AssetHelper::ReadFilePathData(const std::string& filePath, uint8_t** buff,
} else {
realfilePath = filePath.substr(pos + 1);
TAG_LOGD(AAFwkTag::JSRUNTIME, "realfilePath: %{private}s", realfilePath.c_str());
bool apiSatisfy = workerInfo_->apiTargetVersion == 0 || workerInfo_->apiTargetVersion > API8;
int32_t apiTargetVersion = static_cast<int32_t>(workerInfo_->apiTargetVersion.GetOriginPointer());
bool apiSatisfy = apiTargetVersion == 0 || apiTargetVersion > API8;
if (workerInfo_->isStageModel && !isRestricted && apiSatisfy && !extractor->IsHapCompress(realfilePath)) {
TAG_LOGD(AAFwkTag::JSRUNTIME, "Use secure mem.");
auto safeData = extractor->GetSafeData(realfilePath);
if (workerInfo_->apiTargetVersion >= API12) {
if (apiTargetVersion >= API12) {
useSecureMem = true;
if (safeData == nullptr) {
TAG_LOGE(AAFwkTag::JSRUNTIME, "Get secure mem failed, file %{private}s.", filePath.c_str());
@@ -464,7 +467,7 @@ void AssetHelper::GetAmi(std::string& ami, const std::string& filePath)
std::string fileName = filePath.substr(slashPos + 1);
std::string path = filePath.substr(0, slashPos + 1);
std::string loadPath = ExtractorUtil::GetLoadFilePath(workerInfo_->hapPath);
std::string loadPath = ExtractorUtil::GetLoadFilePath((workerInfo_->hapPath).GetOriginString());
bool newCreate = false;
std::shared_ptr<Extractor> extractor = ExtractorUtil::GetExtractor(loadPath, newCreate);
if (extractor == nullptr) {
@@ -509,7 +512,7 @@ void AssetHelper::GetAmi(std::string& ami, const std::string& filePath)
std::string filePathName = basePath + targetFilePath;
bool hasFile = extractor->HasEntry(filePathName);
if (hasFile) {
ami = workerInfo_->hapPath + "/" + filePathName;
ami = (workerInfo_->hapPath).GetOriginString() + "/" + filePathName;
return;
}
}
+5 -2
View File
@@ -35,8 +35,11 @@ class AssetHelper final {
public:
explicit AssetHelper(std::shared_ptr<JsEnv::WorkerInfo> workerInfo) : workerInfo_(workerInfo)
{
if (!(workerInfo_->codePath).empty() && (workerInfo->codePath).back() != '/') {
(workerInfo_->codePath).append("/");
JsEnv::StringPacProtect codePath = JsEnv::StringPacProtect(workerInfo_->codePath);
if (!(codePath.GetOriginString()).empty() && (codePath.GetOriginString()).back() != '/') {
// (workerInfo_->codePath).append("/");
// workerInfo_->codePath = StringPacProtect(codePath.append("/"));
(workerInfo_->codePath).Append("/");
}
}
@@ -315,12 +315,14 @@ void NativeRuntimeImpl::InitWorkerModule(const Options& options, const std::shar
}
std::shared_ptr<JsEnv::WorkerInfo> workerInfo = std::make_shared<JsEnv::WorkerInfo>();
workerInfo->codePath = options.codePath;
// workerInfo->codePath = options.codePath;
workerInfo->codePath = JsEnv::StringPacProtect(options.codePath);
workerInfo->isDebugVersion = options.isDebugVersion;
workerInfo->isBundle = options.isBundle;
workerInfo->packagePathStr = options.packagePathStr;
workerInfo->assetBasePathStr = options.assetBasePathStr;
workerInfo->hapPath = options.hapPath;
// workerInfo->hapPath = options.hapPath;
workerInfo->hapPath = JsEnv::StringPacProtect(options.hapPath);
workerInfo->isStageModel = options.isStageModel;
workerInfo->moduleName = options.moduleName;
if (options.isJsFramework) {
@@ -172,7 +172,7 @@ void OHOSJsEnvironmentImpl::InitWorkerModule(NativeEngine* engine, std::shared_p
engine->SetInitWorkerFunc(InitWorkerFunc);
engine->SetOffWorkerFunc(OffWorkerFunc);
engine->SetGetAssetFunc(AssetHelper(workerInfo));
engine->SetApiVersion(workerInfo->apiTargetVersion);
engine->SetApiVersion(static_cast<int32_t>(workerInfo->apiTargetVersion.GetOriginPointer()));
engine->SetGetContainerScopeIdFunc(GetContainerId);
engine->SetInitContainerScopeFunc(UpdateContainerScope);
+2
View File
@@ -33,6 +33,8 @@ config("runtime_config") {
}
include_dirs = []
cflags_cc = [ "-march=armv8.3a" ]
}
config("runtime_public_config") {
@@ -17,6 +17,7 @@ import("../../js_environment.gni")
config("js_environment_config") {
include_dirs = [ "${inner_api_path}" ]
cflags_cc = [ "-march=armv8.3a" ]
}
config("public_js_environment_config") {
@@ -29,6 +30,7 @@ config("public_js_environment_config") {
ohos_shared_library("js_environment") {
sources = [
"${utils_path}/src/data_protect.cpp",
"${utils_path}/src/js_env_logger.cpp",
"src/js_environment.cpp",
"src/source_map.cpp",
@@ -0,0 +1,305 @@
/**
* Copyright (c) 2024 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.
*/
#ifndef LIBPANDAFILE_DATA_PROTECT_H
#define LIBPANDAFILE_DATA_PROTECT_H
#include <cstdint>
#include <vector>
#include <string>
#include <string_view>
#include <algorithm>
namespace OHOS {
namespace JsEnv {
class DataProtect {
public:
DataProtect() : protect_pointer_(0) {}
explicit DataProtect(const uintptr_t pointer)
{
if (pointer == 0) {
protect_pointer_ = 0;
return;
}
protect_pointer_ = DataProtectPac(pointer, reinterpret_cast<uintptr_t>(&protect_pointer_));
}
~DataProtect() = default;
static bool CheckPacSupport();
static inline uintptr_t DataProtectAut(const uintptr_t pointer,
[[maybe_unused]]const uintptr_t address)
{
#if defined(PANDA_TARGET_ARM64)
// todo: print t1, t2
if (!isSupportPacA_) {
return pointer;
}
void *t1 = reinterpret_cast<void*>(pointer);
void *t2 = reinterpret_cast<void*>(address);
#ifdef PAC_DFI_PTR_BKEY
__asm__ __volatile__("autdb %0, %1":"+r"(t1):"r"(t2):);
#else
__asm__ __volatile__("autda %0, %1":"+r"(t1):"r"(t2):);
#endif
return reinterpret_cast<uintptr_t>(t1);
#else
return pointer;
#endif
}
static inline uintptr_t DataProtectPac(const uintptr_t pointer,
[[maybe_unused]]const uintptr_t address)
{
#if defined(PANDA_TARGET_ARM64)
if (!isSupportPacA_) {
return pointer;
}
void *t1 = reinterpret_cast<void*>(pointer);
void *t2 = reinterpret_cast<void*>(address);
#ifdef PAC_DFI_PTR_BKEY
__asm__ __volatile__("pacdb %0, %1":"+r"(t1):"r"(t2):);
#else
__asm__ __volatile__("pacda %0, %1":"+r"(t1):"r"(t2):);
#endif
return reinterpret_cast<uintptr_t>(t1);
#else
return pointer;
#endif
}
static bool isSupportPacA_;
private:
void Update(const uintptr_t pointer)
{
if (pointer == 0) {
protect_pointer_ = 0;
return;
}
protect_pointer_ = DataProtectPac(pointer, reinterpret_cast<uintptr_t>(&protect_pointer_));
}
uintptr_t GetOriginPointer() const
{
if (protect_pointer_ == 0) {
return protect_pointer_;
}
return DataProtectAut(protect_pointer_, reinterpret_cast<uintptr_t>(&protect_pointer_));
}
uintptr_t protect_pointer_;
};
class StringPacProtect : public DataProtect {
public:
enum Shift : uint8_t {
SHIFT8 = 8,
SHIFT16 = 16,
SHIFT24 = 24
};
StringPacProtect() : data(std::vector<uintptr_t>()), originLength(0) {}
explicit StringPacProtect(std::string_view strData)
{
Update(strData);
}
~StringPacProtect()
{
Clear();
}
// replace data by pac(strData)
void Update(std::string_view strData)
{
Clear();
AppendWithoutCheckBack(strData);
}
void Append(char ch)
{
constexpr uint32_t step = 4;
if (originLength % step > 0) {
// Filling back empty
uint32_t emptyCount = step - (originLength % step);
auto lastData = DataProtectAut(data.back(), reinterpret_cast<uintptr_t>(&data));
data.pop_back();
uint8_t shift = (SHIFT8 * (emptyCount - 1));
lastData |= ch << shift;
data.push_back(DataProtectPac(lastData, reinterpret_cast<uintptr_t>(&data)));
} else {
uintptr_t tempData = uintptr_t(ch);
tempData <<= SHIFT24;
data.push_back(DataProtectPac(tempData, reinterpret_cast<uintptr_t>(&data)));
}
originLength ++;
}
// data += pac(strData)
void Append(std::string_view strData)
{
if (strData.empty()) {
return;
}
constexpr uint32_t step = 4;
auto str = reinterpret_cast<const uint8_t *>(strData.data());
auto len = strData.length();
if (originLength % step != 0) {
// Filling back empty
uint32_t iter = 0;
uint32_t emptyCount = step - (originLength % step);
auto lastData = DataProtectAut(data.back(), reinterpret_cast<uintptr_t>(&data));
data.pop_back();
lastData >>= SHIFT8 * emptyCount;
while (iter < emptyCount) {
lastData <<= SHIFT8;
lastData += (iter < len ? str[iter] : 0);
iter++;
}
data.push_back(DataProtectPac(lastData, reinterpret_cast<uintptr_t>(&data)));
originLength += (emptyCount < len ? emptyCount : len);
if (emptyCount < len) {
AppendWithoutCheckBack(strData.substr(emptyCount));
}
} else {
AppendWithoutCheckBack(strData);
}
}
// return string(aut(data))
std::string GetOriginString() const
{
if (data.empty()) {
return "";
}
std::string res = "";
constexpr uintptr_t mask = (1 << SHIFT8) - 1;
int32_t iter = data.size() - 1;
uint32_t dataCount = originLength % 4;
// need to delete back empty
if (dataCount != 0) {
uintptr_t tempData = DataProtectAut(data[iter], reinterpret_cast<uintptr_t>(&data));
constexpr uint32_t step = 4;
uint32_t emptyCount = step - dataCount;
tempData >>= SHIFT8 * emptyCount;
while (dataCount > 0) {
res.push_back(char(tempData & mask));
tempData >>= SHIFT8;
--dataCount;
}
--iter;
}
for (; iter >= 0; --iter) {
uintptr_t tempData = DataProtectAut(data[iter], reinterpret_cast<uintptr_t>(&data));
res.push_back(char(tempData & mask));
tempData >>= SHIFT8;
res.push_back(char(tempData & mask));
tempData >>= SHIFT8;
res.push_back(char(tempData & mask));
tempData >>= SHIFT8;
res.push_back(char(tempData & mask));
tempData >>= SHIFT8;
}
std::reverse(res.begin(), res.end());
return res;
}
// Compare strData with Paced data, return true if equal
bool CompareStringWithPacedString(std::string_view strData)
{
auto len = strData.length();
constexpr uint32_t step = 4;
if (len != originLength) {
return false;
}
auto str = reinterpret_cast<const uint8_t *>(strData.data());
auto dataPtr = data.begin();
for (uint32_t left = 0; left < len; left += step) {
uint32_t right = (len > left + step ? left + step : len);
uintptr_t tempData = 0;
for (uint32_t iter = left; iter < right; ++iter) {
tempData += str[iter];
tempData <<= SHIFT8;
}
auto res = DataProtectPac(tempData, reinterpret_cast<uintptr_t>(&data));
if (res != *dataPtr) {
return false;
}
++dataPtr;
}
return true;
}
void Clear()
{
std::vector<uintptr_t>().swap(data);
originLength = 0;
}
// PacDataSize = ceil(StrLength / 4)
uint32_t PacDataSize()
{
return data.size();
}
// Original String Length Before Pac
uint32_t StrLength()
{
return originLength;
}
private:
void AppendWithoutCheckBack(std::string_view strData)
{
if (strData.empty()) {
return;
}
auto str = reinterpret_cast<const uint8_t *>(strData.data());
auto len = strData.length();
constexpr uint32_t step = 4;
// uint32 = char << 24 | char << 16 | char << 8 | char
// compress 4 char => 1 uint32 => PAC(uint32) => uintptr_t
for (uint32_t left = 0; left < len; left += step) {
uint32_t right = left + step;
uintptr_t tempData = 0;
for (uint32_t iter = left; iter < right; ++iter) {
tempData <<= SHIFT8;
tempData += (iter < len ? str[iter] : 0);
}
data.push_back(DataProtectPac(tempData, reinterpret_cast<uintptr_t>(&data)));
}
originLength += strData.length();
}
std::vector<uintptr_t>data;
uint32_t originLength;
};
}
}
#endif // LIBPANDAFILE_DATA_PROTECT_H
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2024 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 "data_protect.h"
#if defined(PANDA_TARGET_ARM64)
#include <sys/auxv.h>
#include <asm/hwcap.h>
#endif
namespace OHOS {
namespace JsEnv {
bool DataProtect::isSupportPacA_ = CheckPacSupport();
bool DataProtect::CheckPacSupport()
{
#if defined(PANDA_TARGET_ARM64) && defined(HWCAP_PACA)
uint64_t hwcaps = getauxval(AT_HWCAP);
return hwcaps & HWCAP_PACA;
#else
return false;
#endif
}
}
}
@@ -22,18 +22,23 @@
#include "native_engine/native_engine.h"
#include "data_protect.h"
namespace OHOS {
namespace JsEnv {
struct WorkerInfo {
std::string codePath;
// std::string codePath;
StringPacProtect codePath;
bool isDebugVersion = false;
bool isBundle = true;
std::string packagePathStr;
std::vector<std::string> assetBasePathStr;
std::string hapPath;
// std::string hapPath;
StringPacProtect hapPath;
bool isStageModel = true;
std::string moduleName;
int32_t apiTargetVersion = 0;
// int32_t apiTargetVersion = 0;
DataProtect apiTargetVersion = DataProtect();
};
class JsEnvironmentImpl {