From ed1e03ab5263c504543a4f1c4cfcb14cb63790c0 Mon Sep 17 00:00:00 2001 From: yangbinfa Date: Tue, 15 Oct 2024 10:44:05 +0800 Subject: [PATCH 1/2] [Build] Add binary permission check script Issue:https://gitee.com/openharmony/third_party_llvm-project/issues/IAX53S?from=project-issue Description:Add the binary permission verification script so_permission_check.py to verify the permissions of all SO files in the clang and ndk libraries. Provide the script usage description document so_permission_check-readme.md (https://gitee.com/yang-ming4249/third_party_llvm-project/blob/master/llvm-build/so_permission_check_readme.md) . The default verification list (https://mirrors.huaweicloud.com/harmonyos/compiler/clang/15.0.4-6fe50d/linux/) is generated based on the 15.0.4-6fe50d version on the image website. Signed-off-by: yangbinfa --- .../default_clang_lib_so_permission.checklist | 98 ++++++++++++++ .../default_ndk_lib_so_permission.checklist | 14 ++ llvm-build/so_permission_check_readme.md | 71 ++++++++++ llvm-build/so_permissions_check.py | 124 ++++++++++++++++++ 4 files changed, 307 insertions(+) create mode 100644 llvm-build/default_clang_lib_so_permission.checklist create mode 100644 llvm-build/default_ndk_lib_so_permission.checklist create mode 100644 llvm-build/so_permission_check_readme.md create mode 100644 llvm-build/so_permissions_check.py diff --git a/llvm-build/default_clang_lib_so_permission.checklist b/llvm-build/default_clang_lib_so_permission.checklist new file mode 100644 index 000000000000..4e3ab067c37f --- /dev/null +++ b/llvm-build/default_clang_lib_so_permission.checklist @@ -0,0 +1,98 @@ +lib/liblzma.so,-rwxr-xr-x +lib/libLLVM-15.so,-rw-r--r-- +lib/libarcher.so,-rw-r--r-- +lib/libclang-cpp.so,-rw-r--r-- +lib/LLVMgold.so,-rw-r--r-- +lib/libompd.so,-rw-r--r-- +lib/libRemarks.so,-rw-r--r-- +lib/libLTO.so,-rw-r--r-- +lib/liblldb.so,-rw-r--r-- +lib/libomptarget.rtl.amdgpu.so,-rw-r--r-- +lib/libomptarget.rtl.cuda.so,-rw-r--r-- +lib/libLLVM-15.0.4.so,-rw-r--r-- +lib/liblldbIntelFeatures.so,-rw-r--r-- +lib/libomptarget.so,-rw-r--r-- +lib/libLLVM.so,-rw-r--r-- +lib/libomptarget.rtl.x86_64.so,-rw-r--r-- +lib/libclang.so,-rw-r--r-- +lib/mipsel-linux-ohos/libc++.so,-rw-r--r-- +lib/mipsel-linux-ohos/nanlegacy/libc++.so,-rw-r--r-- +lib/arm-linux-ohos/libc++.so,-rw-r--r-- +lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libc++.so,-rw-r--r-- +lib/arm-linux-ohos/a7_soft/libc++.so,-rw-r--r-- +lib/arm-linux-ohos/a7_hard_neon-vfpv4/libc++.so,-rw-r--r-- +lib/aarch64-linux-ohos/libc++.so,-rw-r--r-- +lib/riscv64-linux-ohos/libc++.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/mipsel-linux-ohos/nanlegacy/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_soft/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/arm-linux-ohos/a7_hard_neon-vfpv4/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.tsan.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.hwasan.so,-rw-r--r-- +lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/riscv64-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/riscv64-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/riscv64-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.tsan.so,-rw-r--r-- +lib/clang/15.0.4/lib/loongarch64-linux-ohos/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.ubsan_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.ubsan_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.scudo.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.asan.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.scudo_minimal.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.tsan.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.hwasan.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.scudo_standalone.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.dyndd.so,-rw-r--r-- +lib/clang/15.0.4/lib/x86_64-linux-ohos/libclang_rt.hwasan_aliases.so,-rw-r--r-- +lib/loongarch64-linux-ohos/libc++.so,-rw-r--r-- +lib/x86_64-unknown-linux-gnu/libunwind.so,-rw-r--r-- +lib/x86_64-unknown-linux-gnu/libc++.so,-rw-r--r-- +lib/x86_64-unknown-linux-gnu/libc++abi.so,-rw-r--r-- +lib/arm-liteos-ohos/libc++.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libc++.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_soft/libc++.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libc++.so,-rw-r--r-- +lib/x86_64-linux-ohos/libc++.so,-rw-r--r-- diff --git a/llvm-build/default_ndk_lib_so_permission.checklist b/llvm-build/default_ndk_lib_so_permission.checklist new file mode 100644 index 000000000000..56168fb1761d --- /dev/null +++ b/llvm-build/default_ndk_lib_so_permission.checklist @@ -0,0 +1,14 @@ +lib/mipsel-linux-ohos/libc++_shared.so,-rw-r--r-- +lib/mipsel-linux-ohos/nanlegacy/libc++_shared.so,-rw-r--r-- +lib/arm-linux-ohos/libc++_shared.so,-rw-r--r-- +lib/arm-linux-ohos/a7_softfp_neon-vfpv4/libc++_shared.so,-rw-r--r-- +lib/arm-linux-ohos/a7_soft/libc++_shared.so,-rw-r--r-- +lib/arm-linux-ohos/a7_hard_neon-vfpv4/libc++_shared.so,-rw-r--r-- +lib/aarch64-linux-ohos/libc++_shared.so,-rw-r--r-- +lib/riscv64-linux-ohos/libc++_shared.so,-rw-r--r-- +lib/loongarch64-linux-ohos/libc++_shared.so,-rw-r--r-- +lib/arm-liteos-ohos/libc++_shared.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libc++_shared.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_soft/libc++_shared.so,-rw-r--r-- +lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libc++_shared.so,-rw-r--r-- +lib/x86_64-linux-ohos/libc++_shared.so,-rw-r--r-- diff --git a/llvm-build/so_permission_check_readme.md b/llvm-build/so_permission_check_readme.md new file mode 100644 index 000000000000..44b2382aa449 --- /dev/null +++ b/llvm-build/so_permission_check_readme.md @@ -0,0 +1,71 @@ +# llvm工具链编译产物中so文件权限校验脚本 +## 用途 +校验llvm编译产物clang和ndk中lib文件夹下所有的so文件权限是否符合要求 +## 版本说明 +当前提交中包含的权限检查列表基于镜像网站中15.0.4-6fe50d版本生成(https://mirrors.huaweicloud.com/harmonyos/compiler/clang/15.0.4-6fe50d/linux/) +## 使用方法 +针对clang和ndk中lib文件夹分别进行校验,`{lib_path}`为clang或ndk下第一层lib对应绝对路径或相较于py脚本所在位置的相对路径,且以lib结尾 +### so文件权限列表生成 +搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中 +```shell +python so_permission_check.py -g {lib_path} {filename} +``` +### 默认so文件权限列表生成 +搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中,默认检查列表为default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist +```shell +# clang lib默认权限列表生成 +python so_permission_check.py -cdg {lib_path} +# ndk lib默认权限列表生成 +python so_permission_check.py -ndg {lib_path} +``` +### 校验自定义列表 +根据给定的权限校验列表,校验输入lib文件夹内.so文件的权限是否正确 +```shell +python so_permission_check.py -v {lib_path} {filename} +``` +### 校验默认列表 +根据基准版本的.so权限列表,校验输入lib文件夹内.so文件的权限是否正确(运行该指令之前,确保目录中包含default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist) +```shell +# clang lib校验 +python so_permission_check.py -cdv {lib_path} +# ndk lib校验 +python so_permission_check.py -ndv {lib_path} +``` + +# LLVM Toolchain Compiled Product SO File Permission Check Script +## Purpose +To verify whether the permissions of all .so files in the lib folders of LLVM compiled products, Clang, and NDK meet the requirements. + +## Version Description +The permission check list included in the current submission is based on the version 15.0.4-6fe50d generated from the mirror site (https://mirrors.huaweicloud.com/harmonyos/compiler/clang/15.0.4-6fe50d/linux/). + +## Usage +Checks are performed separately on the lib folders of Clang and NDK. The {lib_path} should be the absolute path or relative path (relative to the location of the Python script) corresponding to the first-level lib directory, and it should end with lib. + +### Generate SO File Permission List +Search and check each .so file in the lib folder, and record the permission list to the output file. + +```shell +python so_permission_check.py -g {lib_path} {filename} +``` +### Generate Default SO File Permission List +Search and check each .so file in the lib folder, and record the permission list to the output file. The default check lists are default_clang_lib_so_permission.checklist and default_ndk_lib_so_permission.checklist. +```shell +# Generate default permission list for Clang lib +python so_permission_check.py -cdg {lib_path} +# Generate default permission list for NDK lib +python so_permission_check.py -ndg {lib_path} +``` +### Check Custom List +Check the permissions of the .so files in the input lib folder based on the provided permission check list. +```shell +python so_permission_check.py -v {lib_path} {filename} +``` +### Check Default List +Verify the permissions of the .so files in the input lib folder against the permission list of the baseline version (before running this command, ensure that the directory contains default_clang_lib_so_permission.checklist and default_ndk_lib_so_permission.checklist). +```shell +# Check Clang lib +python so_permission_check.py -cdv {lib_path} +# Check NDK lib +python so_permission_check.py -ndv {lib_path} +``` \ No newline at end of file diff --git a/llvm-build/so_permissions_check.py b/llvm-build/so_permissions_check.py new file mode 100644 index 000000000000..924d9954f166 --- /dev/null +++ b/llvm-build/so_permissions_check.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# 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. + +import os +import stat +import sys +from datetime import datetime + +DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_clang_lib_so_permission.checklist" +DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_ndk_lib_so_permission.checklist" + +def main(): + args = sys.argv + if len(args) < 3: + print("Missing arguments. Correct eg: python so_permission_check.py -g clang/lib") + return + if args[1] == '-g': + so_permissions_list_generate(args[2], args[3]) + elif args[1] == '-cdg': + so_permissions_list_generate(args[2], DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) + elif args[1] == '-ndg': + so_permissions_list_generate(args[2], DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) + elif args[1] == '-v': + so_files_permissions_check(args[2], args[3]) + elif args[1] == '-cdv': + so_files_permissions_check(args[2], DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) + elif args[1] == '-ndv': + so_files_permissions_check(args[2], DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) + else: + print("The input parameter is incorrect. Check the input parameter by reading the README document.") + +# Read all .so files in the lib folder and generate a verification file (typically used for generating new verification files after a version update). +def so_permissions_list_generate(directory, output_file): + + with open(output_file, 'w') as ff: + pass + total = 0 + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith('.so'): + total += 1 + file_path = os.path.join(root, file) + file_stat = os.stat(file_path) + file_mode = stat.filemode(file_stat.st_mode) + with open(output_file, 'a') as f: + f.write('lib' + file_path.replace(directory, '').replace('\\', '/') + ',' + file_mode+ '\n') + print(f"Total {total} .so files in {directory}") + +# Check if the permissions of the binary files match those in the verification file. +def so_files_permissions_check(directory, standard_file): + lack = 0 + total = 0 + fail = 0 + success = 0 + + timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") + log_file_path = "so_permissions_check_log" + timestamp + ".txt" + + success_log = "" + error_log = "" + lack_log = "" + with open(standard_file, 'r') as ff: + for line in ff: + lib_file_path = os.path.join(directory, line.split(',')[0].split('lib/', 1)[1]).replace('\\', '/') + so_file_stat_expected = line.split(',')[1].replace('\n', '') + so_file_stat_real = get_file_permissions(lib_file_path) + if so_file_stat_real == None: + lack += 1 + total += 1 + lack_log += lib_file_path + ' check failed, the file is missed.\n' + elif so_file_stat_expected == stat.filemode(os.stat(lib_file_path).st_mode): + success += 1 + total += 1 + success_log += lib_file_path + ' check succeeded.\n' + else: + fail += 1 + total += 1 + error_log += lib_file_path + ' check failed, expected:' + so_file_stat_expected + ', real: ' + stat.filemode(os.stat(lib_file_path).st_mode) + '\n' + if success == total: + print("So Permissions check passed.") + else: + print("So Permissions check failed.") + print(str(fail) + '/' + str(total) + ' checks failed.\n') + print(error_log) + print(str(lack) + '/' + str(total) + ' file missed.\n') + print(lack_log) + print(str(fail + lack) + '/' + str(total) + ' checks failed, check logs are in ' + os.path.join(os.getcwd(), log_file_path)) + with open(log_file_path, 'w') as f: + f.write('llvm so permissions check complete, ' + 'Success:' + str(success) + '/' + str(total) + ', ' + 'Failed:' + str(fail) + '/' + str(total) + ', Lack:' + str(lack) + '/' + str(total)) + f.write('\n\n' + str(fail) + '/' + str(total) + ' checks failed.\n') + f.write(error_log) + f.write('\n\n' + str(lack) + '/' + str(total) + ' file missed.\n') + f.write(lack_log) + f.write('\n\n' + str(success) + '/' + str(total) + ' checks succeed.\n') + f.write(success_log) + print('Success:' + str(success) + '/' + str(total) + ', ' + 'Failed:' + str(fail) + '/' + str(total) + ', Lack:' + str(lack) + '/' + str(total)) + +def get_file_permissions(file_path): + try: + file_stat = os.stat(file_path) + permissions = stat.filemode(file_stat.st_mode) + return permissions + except FileNotFoundError: + print(f"error: file '{file_path}' not found.") + except PermissionError: + print(f"error: no read permission for '{file_path}'.") + except Exception as e: + print(f"error: unknow error - {e}") + return None + +if __name__ == '__main__': + main() \ No newline at end of file -- Gitee From 65db5bd08e6d3e1352341d373ecaf9cc2ef5fb38 Mon Sep 17 00:00:00 2001 From: yangbinfa Date: Fri, 1 Nov 2024 12:06:52 +0800 Subject: [PATCH 2/2] [Build] Modify so_permission_check.py according to the review. Description: Add calling interface for the main build script; use logging for message output; encapsulate functions using classes. Signed-off-by: yangbinfa --- ...me.md => so_permission_check_readme_en.md} | 34 --- llvm-build/so_permission_check_readme_zh.md | 33 +++ llvm-build/so_permissions_check.py | 238 +++++++++++------- 3 files changed, 175 insertions(+), 130 deletions(-) rename llvm-build/{so_permission_check_readme.md => so_permission_check_readme_en.md} (53%) create mode 100644 llvm-build/so_permission_check_readme_zh.md diff --git a/llvm-build/so_permission_check_readme.md b/llvm-build/so_permission_check_readme_en.md similarity index 53% rename from llvm-build/so_permission_check_readme.md rename to llvm-build/so_permission_check_readme_en.md index 44b2382aa449..02d34f3e5b90 100644 --- a/llvm-build/so_permission_check_readme.md +++ b/llvm-build/so_permission_check_readme_en.md @@ -1,37 +1,3 @@ -# llvm工具链编译产物中so文件权限校验脚本 -## 用途 -校验llvm编译产物clang和ndk中lib文件夹下所有的so文件权限是否符合要求 -## 版本说明 -当前提交中包含的权限检查列表基于镜像网站中15.0.4-6fe50d版本生成(https://mirrors.huaweicloud.com/harmonyos/compiler/clang/15.0.4-6fe50d/linux/) -## 使用方法 -针对clang和ndk中lib文件夹分别进行校验,`{lib_path}`为clang或ndk下第一层lib对应绝对路径或相较于py脚本所在位置的相对路径,且以lib结尾 -### so文件权限列表生成 -搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中 -```shell -python so_permission_check.py -g {lib_path} {filename} -``` -### 默认so文件权限列表生成 -搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中,默认检查列表为default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist -```shell -# clang lib默认权限列表生成 -python so_permission_check.py -cdg {lib_path} -# ndk lib默认权限列表生成 -python so_permission_check.py -ndg {lib_path} -``` -### 校验自定义列表 -根据给定的权限校验列表,校验输入lib文件夹内.so文件的权限是否正确 -```shell -python so_permission_check.py -v {lib_path} {filename} -``` -### 校验默认列表 -根据基准版本的.so权限列表,校验输入lib文件夹内.so文件的权限是否正确(运行该指令之前,确保目录中包含default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist) -```shell -# clang lib校验 -python so_permission_check.py -cdv {lib_path} -# ndk lib校验 -python so_permission_check.py -ndv {lib_path} -``` - # LLVM Toolchain Compiled Product SO File Permission Check Script ## Purpose To verify whether the permissions of all .so files in the lib folders of LLVM compiled products, Clang, and NDK meet the requirements. diff --git a/llvm-build/so_permission_check_readme_zh.md b/llvm-build/so_permission_check_readme_zh.md new file mode 100644 index 000000000000..7e6a0912ec70 --- /dev/null +++ b/llvm-build/so_permission_check_readme_zh.md @@ -0,0 +1,33 @@ +# llvm工具链编译产物中so文件权限校验脚本 +## 用途 +校验llvm编译产物clang和ndk中lib文件夹下所有的so文件权限是否符合要求 +## 版本说明 +当前提交中包含的权限检查列表基于镜像网站中15.0.4-6fe50d版本生成(https://mirrors.huaweicloud.com/harmonyos/compiler/clang/15.0.4-6fe50d/linux/) +## 使用方法 +针对clang和ndk中lib文件夹分别进行校验,`{lib_path}`为clang或ndk下第一层lib对应绝对路径或相较于py脚本所在位置的相对路径,且以lib结尾 +### so文件权限列表生成 +搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中 +```shell +python so_permission_check.py -g {lib_path} {filename} +``` +### 默认so文件权限列表生成 +搜索并检查lib文件夹内的每个.so文件,记录权限列表到输出文件中,默认检查列表为default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist +```shell +# clang lib默认权限列表生成 +python so_permission_check.py -cdg {lib_path} +# ndk lib默认权限列表生成 +python so_permission_check.py -ndg {lib_path} +``` +### 校验自定义列表 +根据给定的权限校验列表,校验输入lib文件夹内.so文件的权限是否正确 +```shell +python so_permission_check.py -v {lib_path} {filename} +``` +### 校验默认列表 +根据基准版本的.so权限列表,校验输入lib文件夹内.so文件的权限是否正确(运行该指令之前,确保目录中包含default_clang_lib_so_permission.checklist和default_ndk_lib_so_permission.checklist) +```shell +# clang lib校验 +python so_permission_check.py -cdv {lib_path} +# ndk lib校验 +python so_permission_check.py -ndv {lib_path} +``` \ No newline at end of file diff --git a/llvm-build/so_permissions_check.py b/llvm-build/so_permissions_check.py index 924d9954f166..1301ca239a95 100644 --- a/llvm-build/so_permissions_check.py +++ b/llvm-build/so_permissions_check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python3 # Copyright (C) 2024 Huawei Device Co., Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,108 +17,154 @@ import os import stat import sys from datetime import datetime +import logging -DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_clang_lib_so_permission.checklist" -DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_ndk_lib_so_permission.checklist" +class SoPermissionCheck: + SO_PERMISSION_CHECK_MIN_ARGS_NUMBER = 3 + DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_clang_lib_so_permission.checklist" + DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH = "default_ndk_lib_so_permission.checklist" + logger = None -def main(): - args = sys.argv - if len(args) < 3: - print("Missing arguments. Correct eg: python so_permission_check.py -g clang/lib") - return - if args[1] == '-g': - so_permissions_list_generate(args[2], args[3]) - elif args[1] == '-cdg': - so_permissions_list_generate(args[2], DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) - elif args[1] == '-ndg': - so_permissions_list_generate(args[2], DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) - elif args[1] == '-v': - so_files_permissions_check(args[2], args[3]) - elif args[1] == '-cdv': - so_files_permissions_check(args[2], DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) - elif args[1] == '-ndv': - so_files_permissions_check(args[2], DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) - else: - print("The input parameter is incorrect. Check the input parameter by reading the README document.") + def __init__(self) -> None: + self.logger = logging.getLogger("so permission check") + self.logger.setLevel(logging.INFO) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s: %(levelname)s: %(name)s: %(message)s') + ch.setFormatter(formatter) + self.logger.addHandler(ch) + + def so_permissions_list_generate(self, directory: str, output_file: str): + ''' + Read all .so files in the lib folder and generate a verification file. + Typically used for generating new verification files after a version update. + + Args: + directory(str): the clang lib path or the ndk lib path + output_file(str): path and filename of the output file to save the permission check list + Return: + No return value but a checklist file will be generated. + ''' + with open(output_file, 'w') as ff: + pass + total = 0 + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith('.so'): + total += 1 + file_path = os.path.join(root, file) + file_stat = os.stat(file_path) + file_mode = stat.filemode(file_stat.st_mode) + with open(output_file, 'a') as f: + f.write('lib' + file_path.replace(directory, '').replace('\\', '/') + ',' + file_mode+ '\n') + self.logger.info(f"Total {total} .so files in {directory}") -# Read all .so files in the lib folder and generate a verification file (typically used for generating new verification files after a version update). -def so_permissions_list_generate(directory, output_file): + def so_files_permissions_check(self, directory: str, checklist_file: str) -> bool: + ''' + Check if the permissions of the binary files match those in the checklist file. - with open(output_file, 'w') as ff: - pass - total = 0 - for root, dirs, files in os.walk(directory): - for file in files: - if file.endswith('.so'): - total += 1 - file_path = os.path.join(root, file) - file_stat = os.stat(file_path) - file_mode = stat.filemode(file_stat.st_mode) - with open(output_file, 'a') as f: - f.write('lib' + file_path.replace(directory, '').replace('\\', '/') + ',' + file_mode+ '\n') - print(f"Total {total} .so files in {directory}") + Args: + directory(str): the clang lib path or the ndk lib path + checklist_file(str): path and filename of the checklist file saved the permission check list + Return: + True(all permission check succeeded) or False(one or more check failed). + ''' + lack = 0 + total = 0 + fail = 0 + success = 0 -# Check if the permissions of the binary files match those in the verification file. -def so_files_permissions_check(directory, standard_file): - lack = 0 - total = 0 - fail = 0 - success = 0 + timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") + log_file_path = "so_permissions_check_log" + timestamp + ".txt" - timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") - log_file_path = "so_permissions_check_log" + timestamp + ".txt" + success_log = "" + error_log = "" + lack_log = "" + with open(checklist_file, 'r') as ff: + for line in ff: + lib_file_path = os.path.join(directory, line.split(',')[0].split('lib/', 1)[1]).replace('\\', '/') + so_file_stat_expected = line.split(',')[1].replace('\n', '') + so_file_stat_real = self.get_file_permissions(lib_file_path) + if so_file_stat_real is None: + lack += 1 + total += 1 + lack_log += f"{lib_file_path} check failed, the file is missed.\n" + elif so_file_stat_expected == stat.filemode(os.stat(lib_file_path).st_mode): + success += 1 + total += 1 + success_log += f"{lib_file_path} check succeeded.\n" + else: + fail += 1 + total += 1 + error_log += f"{lib_file_path} check failed, expected: {so_file_stat_expected}, real: {stat.filemode(os.stat(lib_file_path).st_mode)}\n" - success_log = "" - error_log = "" - lack_log = "" - with open(standard_file, 'r') as ff: - for line in ff: - lib_file_path = os.path.join(directory, line.split(',')[0].split('lib/', 1)[1]).replace('\\', '/') - so_file_stat_expected = line.split(',')[1].replace('\n', '') - so_file_stat_real = get_file_permissions(lib_file_path) - if so_file_stat_real == None: - lack += 1 - total += 1 - lack_log += lib_file_path + ' check failed, the file is missed.\n' - elif so_file_stat_expected == stat.filemode(os.stat(lib_file_path).st_mode): - success += 1 - total += 1 - success_log += lib_file_path + ' check succeeded.\n' - else: - fail += 1 - total += 1 - error_log += lib_file_path + ' check failed, expected:' + so_file_stat_expected + ', real: ' + stat.filemode(os.stat(lib_file_path).st_mode) + '\n' - if success == total: - print("So Permissions check passed.") - else: - print("So Permissions check failed.") - print(str(fail) + '/' + str(total) + ' checks failed.\n') - print(error_log) - print(str(lack) + '/' + str(total) + ' file missed.\n') - print(lack_log) - print(str(fail + lack) + '/' + str(total) + ' checks failed, check logs are in ' + os.path.join(os.getcwd(), log_file_path)) - with open(log_file_path, 'w') as f: - f.write('llvm so permissions check complete, ' + 'Success:' + str(success) + '/' + str(total) + ', ' + 'Failed:' + str(fail) + '/' + str(total) + ', Lack:' + str(lack) + '/' + str(total)) - f.write('\n\n' + str(fail) + '/' + str(total) + ' checks failed.\n') - f.write(error_log) - f.write('\n\n' + str(lack) + '/' + str(total) + ' file missed.\n') - f.write(lack_log) - f.write('\n\n' + str(success) + '/' + str(total) + ' checks succeed.\n') - f.write(success_log) - print('Success:' + str(success) + '/' + str(total) + ', ' + 'Failed:' + str(fail) + '/' + str(total) + ', Lack:' + str(lack) + '/' + str(total)) + with open(log_file_path, 'w') as f: + f.write(f'llvm so permissions check complete, Success: {success}/{total}, Failed: {fail}/{total}, Lack: {lack}/{total}\n') + f.write(f'\n{fail}/{total} checks failed.\n') + f.write(error_log) + f.write(f'\n{lack}/{total} file missed.\n') + f.write(lack_log) + f.write(f'\n{success}/{total} checks succeed.\n') + f.write(success_log) + + if success == total: + self.logger.info(f"{directory} so permissions check passed.") + return True + else: + self.logger.error(f"{directory} so permissions check failed.") + self.logger.error(f"{fail}/{total} checks failed.\n") + self.logger.error(error_log) + self.logger.error(f"{lack}/{total} file missed.\n") + self.logger.error(lack_log) + self.logger.error(f"{fail + lack}/{total} checks failed, check logs are in {os.path.join(os.getcwd(), log_file_path)}") + return False -def get_file_permissions(file_path): - try: - file_stat = os.stat(file_path) - permissions = stat.filemode(file_stat.st_mode) - return permissions - except FileNotFoundError: - print(f"error: file '{file_path}' not found.") - except PermissionError: - print(f"error: no read permission for '{file_path}'.") - except Exception as e: - print(f"error: unknow error - {e}") - return None + def get_file_permissions(self, file_path: str) -> str: + '''Get file permissions and throw possible exceptions.''' + try: + file_stat = os.stat(file_path) + permissions = stat.filemode(file_stat.st_mode) + return permissions + except FileNotFoundError: + self.logger.error(f"file '{file_path}' not found.") + except PermissionError: + self.logger.error(f"no read permission for '{file_path}'.") + except Exception as e: + self.logger.error(f"unknown error - {e}") + return None + def check(self, clang_lib_path: str, ndk_lib_path: str) -> bool: + ''' + Main build script calling interface. + Check the so file permissions in clang and ndk lib directories based on the default check list. + ''' + return self.so_files_permissions_check(clang_lib_path, self.DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) \ + & self.so_files_permissions_check(ndk_lib_path, self.DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) + + def cmd_handler(self) -> None: + '''Perform parameter recognition and execute corresponding tasks.''' + args = sys.argv + if len(args) < self.SO_PERMISSION_CHECK_MIN_ARGS_NUMBER: + self.logger.info("Missing arguments. Correct eg: python so_permission_check.py -g clang/lib") + return + + match args[1]: + case '-g': + self.so_permissions_list_generate(args[2], args[3]) + case '-cdg': + self.so_permissions_list_generate(args[2], self.DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) + case '-ndg': + self.so_permissions_list_generate(args[2], self.DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) + case '-v': + self.so_files_permissions_check(args[2], args[3]) + case '-cdv': + self.so_files_permissions_check(args[2], self.DEFAULT_CLANG_LIB_SO_PERMISSION_CHECKLIST_PATH) + case '-ndv': + self.so_files_permissions_check(args[2], self.DEFAULT_NDK_LIB_SO_PERMISSION_CHECKLIST_PATH) + case _: + self.logger.info("The input arguments are incorrect. Check the input arguments by reading the README document.") +def main(): + so_permission_check = SoPermissionCheck() + so_permission_check.cmd_handler() if __name__ == '__main__': - main() \ No newline at end of file + main() -- Gitee