1#!/usr/bin/env python 2# coding=utf-8 3 4# 5# Copyright (c) 2024 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20import sys 21import subprocess 22import json 23from collections import OrderedDict 24 25sys.path.append( 26 os.path.dirname(os.path.dirname(os.path.dirname( 27 os.path.abspath(__file__))))) 28from scripts.util.file_utils import read_json_file 29 30 31class KernelPermission(): 32 33 34 @staticmethod 35 def run(out_path, root_path): 36 target_out_path = os.path.join(root_path, out_path.lstrip("//")) 37 print("target_out_path", target_out_path) 38 KernelPermission.execute_kernel_permission_cmd(target_out_path, root_path) 39 40 41 @staticmethod 42 def scan_file(out_path): 43 """scan path uild_configs/kernel_permission/ 44 return file_list include kernel_permission.json 45 """ 46 file_list = [] 47 file_path = file_path = os.path.join(out_path, "build_configs/kernel_permission/") 48 for root, subdirs, files in os.walk(file_path): 49 for _filename in files: 50 content = read_json_file(os.path.join(root, _filename)) 51 file_list.append(content[0]) 52 return file_list 53 54 55 @staticmethod 56 def execute_kernel_permission_cmd(out_path, root_path): 57 """execute cmd 58 llvm-object --add-section .kernelpermission=json_file xx/xx.so 59 """ 60 print("begin run kernel permission cmd") 61 62 try: 63 llvm_tool = KernelPermission.regist_llvm_objcopy_path(root_path) 64 except FileNotFoundError as e: 65 print("regist_llvm_objcopy_path failed:{}".format(e)) 66 file_list = KernelPermission.scan_file(out_path) 67 68 cmds = KernelPermission.gen_cmds(file_list, out_path, llvm_tool) 69 if cmds: 70 for cmd in cmds: 71 print("llvm cmd: {}".format(cmd)) 72 KernelPermission.exec_command(cmd) 73 else: 74 print("There is no kernel permission json file,no need to run llvm-object cmd.") 75 76 77 @staticmethod 78 def regist_llvm_objcopy_path(root_path): 79 """find llvm_objcopy_path executable 80 :raise FileNotFoundError: when can't find the llvm_objcopy_path excutable 81 """ 82 llvm_objcopy_path = os.path.join(root_path, "prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-objcopy") 83 if os.path.exists(llvm_objcopy_path): 84 return llvm_objcopy_path 85 else: 86 raise FileNotFoundError( 87 'There is no llvm-object executable file at {}'.format(llvm_objcopy_path), '0001') 88 89 90 @staticmethod 91 def gen_cmds(file_list, out_path, llvm_path): 92 """generate cmd 93 llvm-object --add-section .kernelpermission=json_file xx/xx.so 94 """ 95 cmds = [] 96 cmd = [] 97 for info in file_list: 98 kernel_permission_file = os.path.join(out_path, info.get("kernel_permission_path")) 99 if not KernelPermission.check_json_file(kernel_permission_file): 100 raise FileExistsError( 101 'kernel_permission json file {} invalid!'.format(kernel_permission_file), '0001') 102 target_name = info.get("target_name") 103 output_extension = info.get("gn_output_extension") 104 output_name = info.get("gn_output_name") 105 part_name = info.get("part_name") 106 subsystem_name = info.get("subsystem_name") 107 target_type = info.get("type") 108 module_name = target_name 109 if output_name == "" and output_extension == "": 110 if target_type == "lib" and target_name.startswith("lib"): 111 module_name = "{}.z.so".format(target_name) 112 elif target_type == "lib" and not target_name.startswith("lib"): 113 module_name = "lib{}.z.so".format(target_name) 114 print("module_name:{}".format(module_name)) 115 module_path = os.path.join(subsystem_name, part_name) 116 module_path = os.path.join(module_path, module_name) 117 print("module_path:{}".format(module_path)) 118 target_source = os.path.join(out_path, module_path) 119 if os.path.exists(target_source): 120 cmd = [llvm_path, 121 "--add-section", 122 ".kernelpermission=" + kernel_permission_file, 123 target_source 124 ] 125 cmds.append(cmd) 126 return cmds 127 128 129 @staticmethod 130 def check_json_file(file_path): 131 try: 132 with os.fdopen(os.open(file_path, os.O_RDWR, 0o640), 'r') as file: 133 json_data = json.load(file) 134 if KernelPermission.check_json_content(json_data): 135 return True 136 else: 137 print("encaps.json is invalid") 138 return False 139 except FileNotFoundError: 140 print("encaps.json is not found") 141 return False 142 except json.JSONDecodeError: 143 print("encaps.json doesn't conform to json format") 144 return False 145 except Exception: 146 print("encaps.json error") 147 return False 148 149 150 @staticmethod 151 def check_json_content(json_data): 152 if len(json_data) == 1 and "encaps" in json_data: 153 return KernelPermission.check_json_value(json_data) 154 else: 155 return False 156 157 158 @staticmethod 159 def check_json_value(json_data): 160 encaps_data = json_data["encaps"] 161 for key, value in encaps_data.items(): 162 if not isinstance(value, (bool, int)): 163 return False 164 return True 165 166 167 @staticmethod 168 def exec_command(cmd: list, exec_env=None, **kwargs): 169 process = subprocess.Popen(cmd, 170 stdout=subprocess.PIPE, 171 stderr=subprocess.STDOUT, 172 encoding='utf-8', 173 errors='ignore', 174 env=exec_env, 175 **kwargs) 176 for line in iter(process.stdout.readline, ''): 177 print(line) 178 179 process.wait() 180 ret_code = process.returncode 181 182 if ret_code != 0: 183 raise Exception( 184 'Please check llvm cmd: {}'.format(cmd)) 185 186if __name__ == "__main__": 187 pass