1 /* 2 * Copyright (c) 2024 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 #ifndef ECMASCRIPT_OHOS_OHOS_PKG_VERIFIER_H 17 #define ECMASCRIPT_OHOS_OHOS_PKG_VERIFIER_H 18 19 #include <fcntl.h> 20 21 #include "ecmascript/compiler/aot_compiler_preprocessor.h" 22 #include "ecmascript/ohos/ohos_pkg_args.h" 23 #include "ecmascript/platform/file.h" 24 25 namespace panda::ecmascript::ohos { 26 using AotCompilerPreprocessor = kungfu::AotCompilerPreprocessor; 27 using CompilationOptions = kungfu::CompilationOptions; 28 using OhosPkgArgs = kungfu::OhosPkgArgs; 29 using ParseBundleNameAndAppIdentifierFunc = int32_t (*)(const int32_t, std::string&, std::string&); 30 31 class OhosPkgVerifier { 32 public: 33 constexpr static const char *const LIB_HAPVERIFY_SO_NAME = "libhapverify.z.so"; 34 VerifyPkgInfo(AotCompilerPreprocessor & cPreprocessor,CompilationOptions & cOptions)35 static bool VerifyPkgInfo(AotCompilerPreprocessor &cPreprocessor, CompilationOptions &cOptions) 36 { 37 // Processing only for application packages 38 if (!cPreprocessor.GetMainPkgArgs()) { 39 return true; 40 } 41 if (CheckBundleNameAndAppIdentifier(cPreprocessor) && 42 CheckArkProfile(cPreprocessor) && 43 CheckAOTOutputFilePath(cPreprocessor, cOptions)) { 44 return true; 45 } 46 return false; 47 } 48 CheckArkProfile(AotCompilerPreprocessor & cPreprocessor)49 static bool CheckArkProfile(AotCompilerPreprocessor &cPreprocessor) 50 { 51 std::regex pattern("/data/app/el1/\\d+/aot_compiler/ark_profile.*"); 52 std::string pgoDir = cPreprocessor.GetMainPkgArgs()->GetPgoDir(); 53 std::string bundleName = cPreprocessor.GetMainPkgArgs()->GetBundleName(); 54 if (!std::regex_search(pgoDir, pattern) || 55 pgoDir.find(bundleName) == std::string::npos) { 56 LOG_COMPILER(ERROR) << "verify ark-profile path wrong"; 57 return false; 58 } 59 return true; 60 } 61 CheckAOTOutputFilePath(AotCompilerPreprocessor & cPreprocessor,CompilationOptions & cOptions)62 static bool CheckAOTOutputFilePath(AotCompilerPreprocessor &cPreprocessor, CompilationOptions &cOptions) 63 { 64 std::string arkCachePath = "/data/app/el1/public/aot_compiler/ark_cache/"; 65 if (cOptions.outputFileName_.length() < arkCachePath.length()) { 66 LOG_COMPILER(ERROR) << "outputFileName_ is too short"; 67 return false; 68 } 69 if (cOptions.outputFileName_.substr(0, arkCachePath.length()) != arkCachePath) { 70 LOG_COMPILER(ERROR) << "aot file name wrong"; 71 return false; 72 } 73 std::shared_ptr<OhosPkgArgs> mainPkgArgs = cPreprocessor.GetMainPkgArgs(); 74 if (!mainPkgArgs) { 75 LOG_COMPILER(ERROR) << "mainPkgArgs is nullptr"; 76 return false; 77 } 78 const std::string bundleName = mainPkgArgs->GetBundleName(); 79 if (bundleName.empty()) { 80 LOG_COMPILER(ERROR) << "bundleName is empty"; 81 return false; 82 } 83 if (cOptions.outputFileName_.find(bundleName) == std::string::npos) { 84 LOG_COMPILER(ERROR) << "verify main pkg bundleName wrong"; 85 return false; 86 } 87 return true; 88 } 89 CheckBundleNameAndAppIdentifier(AotCompilerPreprocessor & cPreprocessor)90 static bool CheckBundleNameAndAppIdentifier([[maybe_unused]] AotCompilerPreprocessor &cPreprocessor) 91 { 92 #if defined(PANDA_TARGET_OHOS) 93 void* handle = dlopen(LIB_HAPVERIFY_SO_NAME, RTLD_NOW); 94 if (handle == nullptr) { 95 LOG_COMPILER(ERROR) << "dlopen hapverify so fail"; 96 return false; 97 } 98 ParseBundleNameAndAppIdentifierFunc parseBundleNameAndAppIdentifierFunc = 99 reinterpret_cast<ParseBundleNameAndAppIdentifierFunc>(dlsym(handle, "ParseBundleNameAndAppIdentifier")); 100 if (parseBundleNameAndAppIdentifierFunc == nullptr) { 101 LOG_COMPILER(ERROR) << "dlsym ParseBundleNameAndAppIdentifier fail"; 102 dlclose(handle); 103 return false; 104 } 105 for (const auto& pkg : cPreprocessor.GetPkgsArgs()) { 106 std::string realPath; 107 if (!RealPath(pkg.second->GetPath().c_str(), realPath, true)) { 108 LOG_ECMA(ERROR) << "Fail to get realPath: " << pkg.second->GetPath().c_str(); 109 dlclose(handle); 110 return false; 111 } 112 fd_t fd = open(realPath.c_str(), FILE_RDONLY); 113 if (fd == INVALID_FD) { 114 LOG_ECMA(ERROR) << realPath.c_str() << " file open failed"; 115 dlclose(handle); 116 return false; 117 } 118 FdsanExchangeOwnerTag(fd); 119 pkg.second->SetPkgFd(fd); 120 std::string bundleName; 121 std::string appIdentifier; 122 int32_t res = parseBundleNameAndAppIdentifierFunc(fd, bundleName, appIdentifier); 123 if (res != 0 || bundleName != pkg.second->GetBundleName()) { 124 dlclose(handle); 125 LOG_COMPILER(ERROR) << "parse bundleName: " << bundleName.c_str() << " fail, res: " << res; 126 return false; 127 } 128 // Only mainpkg carries appindetifier 129 if (IsMainPkg(cPreprocessor, pkg) && appIdentifier != pkg.second->GetAppSignature()) { 130 dlclose(handle); 131 LOG_COMPILER(ERROR) << "parse mainPkgName: " << cPreprocessor.GetMainPkgName().c_str() << 132 " appIdentifier fail"; 133 return false; 134 } 135 } 136 dlclose(handle); 137 return true; 138 #endif 139 return false; 140 } 141 IsMainPkg(AotCompilerPreprocessor & cPreprocessor,std::pair<const std::string,std::shared_ptr<OhosPkgArgs>> pkg)142 static bool IsMainPkg(AotCompilerPreprocessor &cPreprocessor, std::pair<const std::string, 143 std::shared_ptr<OhosPkgArgs>> pkg) 144 { 145 if (cPreprocessor.GetMainPkgName() == pkg.first) { 146 return true; 147 } 148 return false; 149 } 150 }; 151 } // namespace panda::ecmascript::ohos 152 #endif 153