1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2023 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 argparse 20import sys 21import os 22import audit_log_analysis as audit_policy 23import generate_code_from_policy as gen_policy 24 25 26 27def parse_line(fp): 28 func_name_set = set() 29 for line in fp: 30 line = line.strip() 31 func_name = line[:line.find('(')] 32 if ' ' in func_name: 33 func_name = func_name.split(' ')[-1].strip() 34 func_name_set.add(func_name) 35 36 return func_name_set 37 38 39def get_item_content(arch, func_name_set, name_nr_table): 40 func_name_to_nr = dict() 41 for func_name in func_name_set: 42 if func_name.startswith('arm_'): 43 func_name = func_name[len('arm_'):] 44 if func_name in name_nr_table.get(arch).keys(): 45 func_name_to_nr.update({func_name: name_nr_table.get(arch).get(func_name)}) 46 47 func_name_to_nr_list = sorted(func_name_to_nr.items(), key=lambda x : x[1]) 48 content = '@allowList\n' 49 func_name_list = [func_name for func_name, _ in func_name_to_nr_list] 50 51 content = '{}{};{}\n'.format(content, ';{}\n'.format(arch).join(func_name_list), arch) 52 53 return content 54 55 56def parse_file(file_name): 57 with open(file_name) as f: 58 return parse_line(f) 59 60 61def parse_strace_log_to_policy(args): 62 file_list = extract_file_from_path(args.src_path) 63 function_name_nr_table_dict = {} 64 for file_name in file_list: 65 file_name_tmp = file_name.split('/')[-1] 66 if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): 67 continue 68 gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) 69 70 func_name_set = set() 71 for file_name in file_list: 72 if '.strace.log' in file_name.lower(): 73 func_name_set |= parse_file(file_name) 74 75 content = get_item_content(args.target_cpu, func_name_set, function_name_nr_table_dict) 76 audit_policy.gen_output_file(args.filter_name, content) 77 78 79def extract_file_from_path(dir_path): 80 file_list = [] 81 for path in dir_path: 82 if path[-1] == '/': 83 print('input dir path can not end with /') 84 return [] 85 86 if os.path.isdir(path): 87 # get file list 88 file_list_tmp = os.listdir(path) 89 file_list += ['{}/{}'.format(path, item) for item in file_list_tmp] 90 91 return file_list 92 93 94def main(): 95 parser = argparse.ArgumentParser( 96 description='Generates a seccomp-bpf policy') 97 parser.add_argument('--src-path', action='append', 98 help='the path of directory which includes strace log and libsyscall_to_nr files') 99 parser.add_argument('--target-cpu', type=str, 100 help='input arm or arm64 or riscv64') 101 parser.add_argument('--filter-name', type=str, 102 help=('consist of output file name\n')) 103 104 args = parser.parse_args() 105 if args.target_cpu not in gen_policy.supported_architecture: 106 raise ValueError("target_cpu must int {}".format(gen_policy.supported_architecture)) 107 parse_strace_log_to_policy(args) 108 109 110if __name__ == '__main__': 111 sys.exit(main()) 112