1d9f0492fSopenharmony_ci#!/usr/bin/env python3 2d9f0492fSopenharmony_ci# -*- coding: utf-8 -*- 3d9f0492fSopenharmony_ci 4d9f0492fSopenharmony_ci# 5d9f0492fSopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd. 6d9f0492fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 7d9f0492fSopenharmony_ci# you may not use this file except in compliance with the License. 8d9f0492fSopenharmony_ci# You may obtain a copy of the License at 9d9f0492fSopenharmony_ci# 10d9f0492fSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 11d9f0492fSopenharmony_ci# 12d9f0492fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 13d9f0492fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 14d9f0492fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15d9f0492fSopenharmony_ci# See the License for the specific language governing permissions and 16d9f0492fSopenharmony_ci# limitations under the License. 17d9f0492fSopenharmony_ci# 18d9f0492fSopenharmony_ci 19d9f0492fSopenharmony_ciimport sys 20d9f0492fSopenharmony_ciimport argparse 21d9f0492fSopenharmony_ciimport audit_log_analysis as audit_policy 22d9f0492fSopenharmony_ciimport generate_code_from_policy as gen_policy 23d9f0492fSopenharmony_ci 24d9f0492fSopenharmony_ci 25d9f0492fSopenharmony_ciclass MergePolicy: 26d9f0492fSopenharmony_ci def __init__(self): 27d9f0492fSopenharmony_ci self.cur_parse_item = '' 28d9f0492fSopenharmony_ci self.arches = set() 29d9f0492fSopenharmony_ci self.seccomp_policy_param = dict() 30d9f0492fSopenharmony_ci 31d9f0492fSopenharmony_ci @staticmethod 32d9f0492fSopenharmony_ci def get_item_content(name_nr_table, item_str, itme_dict): 33d9f0492fSopenharmony_ci syscall_name_dict = {} 34d9f0492fSopenharmony_ci flag = False 35d9f0492fSopenharmony_ci for arch in gen_policy.supported_architecture: 36d9f0492fSopenharmony_ci func_name_to_nr = dict() 37d9f0492fSopenharmony_ci for item in itme_dict.get(arch): 38d9f0492fSopenharmony_ci if ':' in item: 39d9f0492fSopenharmony_ci func_name = item[:item.find(':')].strip() 40d9f0492fSopenharmony_ci else: 41d9f0492fSopenharmony_ci func_name = item 42d9f0492fSopenharmony_ci func_name_to_nr.update({item: name_nr_table.get(arch).get(func_name)}) 43d9f0492fSopenharmony_ci func_name_to_nr_list = sorted(func_name_to_nr.items(), key=lambda x : x[1]) 44d9f0492fSopenharmony_ci 45d9f0492fSopenharmony_ci syscall_name_dict.update({arch: func_name_to_nr_list}) 46d9f0492fSopenharmony_ci for arch in gen_policy.supported_architecture: 47d9f0492fSopenharmony_ci if syscall_name_dict.get(arch): 48d9f0492fSopenharmony_ci flag = True 49d9f0492fSopenharmony_ci if not flag: 50d9f0492fSopenharmony_ci return '' 51d9f0492fSopenharmony_ci content = '{}\n'.format(item_str) 52d9f0492fSopenharmony_ci 53d9f0492fSopenharmony_ci for func_name, _ in syscall_name_dict.get('arm64'): 54d9f0492fSopenharmony_ci flag = False 55d9f0492fSopenharmony_ci for func_name_arm, nr_arm in syscall_name_dict.get('arm'): 56d9f0492fSopenharmony_ci if func_name == func_name_arm: 57d9f0492fSopenharmony_ci content = '{}{};all\n'.format(content, func_name) 58d9f0492fSopenharmony_ci syscall_name_dict.get('arm').remove((func_name, nr_arm)) 59d9f0492fSopenharmony_ci flag = True 60d9f0492fSopenharmony_ci break 61d9f0492fSopenharmony_ci if not flag: 62d9f0492fSopenharmony_ci content = '{}{};arm64\n'.format(content, func_name) 63d9f0492fSopenharmony_ci if (syscall_name_dict.get('arm')): 64d9f0492fSopenharmony_ci content = '{}{};arm\n'.format(content, ';arm\n'.join( 65d9f0492fSopenharmony_ci [func_name for func_name, _ in syscall_name_dict.get('arm')])) 66d9f0492fSopenharmony_ci if (syscall_name_dict.get('riscv64')): 67d9f0492fSopenharmony_ci content = '{}{};riscv64\n'.format(content, ';riscv64\n'.join( 68d9f0492fSopenharmony_ci [func_name for func_name, _ in syscall_name_dict.get('riscv64')])) 69d9f0492fSopenharmony_ci return content 70d9f0492fSopenharmony_ci 71d9f0492fSopenharmony_ci def update_parse_item(self, line): 72d9f0492fSopenharmony_ci item = line[1:] 73d9f0492fSopenharmony_ci if item in gen_policy.supported_parse_item: 74d9f0492fSopenharmony_ci self.cur_parse_item = item 75d9f0492fSopenharmony_ci print('start deal with {}'.format(self.cur_parse_item)) 76d9f0492fSopenharmony_ci 77d9f0492fSopenharmony_ci def parse_line(self, line): 78d9f0492fSopenharmony_ci if not self.cur_parse_item : 79d9f0492fSopenharmony_ci return 80d9f0492fSopenharmony_ci line = line.replace(' ', '') 81d9f0492fSopenharmony_ci pos = line.rfind(';') 82d9f0492fSopenharmony_ci if pos < 0: 83d9f0492fSopenharmony_ci for arch in self.arches: 84d9f0492fSopenharmony_ci self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line) 85d9f0492fSopenharmony_ci else: 86d9f0492fSopenharmony_ci arches = line[pos + 1:].split(',') 87d9f0492fSopenharmony_ci if arches[0] == 'all': 88d9f0492fSopenharmony_ci arches = gen_policy.supported_architecture 89d9f0492fSopenharmony_ci for arch in arches: 90d9f0492fSopenharmony_ci self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line[:pos]) 91d9f0492fSopenharmony_ci 92d9f0492fSopenharmony_ci 93d9f0492fSopenharmony_ci def parse_open_file(self, fp): 94d9f0492fSopenharmony_ci for line in fp: 95d9f0492fSopenharmony_ci line = line.strip() 96d9f0492fSopenharmony_ci if not line: 97d9f0492fSopenharmony_ci continue 98d9f0492fSopenharmony_ci if line[0] == '#': 99d9f0492fSopenharmony_ci continue 100d9f0492fSopenharmony_ci if line[0] == '@': 101d9f0492fSopenharmony_ci self.update_parse_item(line) 102d9f0492fSopenharmony_ci continue 103d9f0492fSopenharmony_ci if line[0] != '@' and self.cur_parse_item == '': 104d9f0492fSopenharmony_ci continue 105d9f0492fSopenharmony_ci self.parse_line(line) 106d9f0492fSopenharmony_ci 107d9f0492fSopenharmony_ci def parse_file(self, file_path): 108d9f0492fSopenharmony_ci with open(file_path) as fp: 109d9f0492fSopenharmony_ci self.parse_open_file(fp) 110d9f0492fSopenharmony_ci 111d9f0492fSopenharmony_ci def merge_policy(self, args): 112d9f0492fSopenharmony_ci function_name_nr_table_dict = {} 113d9f0492fSopenharmony_ci for file_name in args.src_files: 114d9f0492fSopenharmony_ci file_name_tmp = file_name.split('/')[-1] 115d9f0492fSopenharmony_ci if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): 116d9f0492fSopenharmony_ci continue 117d9f0492fSopenharmony_ci gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) 118d9f0492fSopenharmony_ci 119d9f0492fSopenharmony_ci for arch in gen_policy.supported_architecture: 120d9f0492fSopenharmony_ci self.seccomp_policy_param.update(\ 121d9f0492fSopenharmony_ci {arch: gen_policy.SeccompPolicyParam(arch, function_name_nr_table_dict.get(arch))}) 122d9f0492fSopenharmony_ci 123d9f0492fSopenharmony_ci for file_name in args.src_files: 124d9f0492fSopenharmony_ci if file_name.lower().endswith('.policy'): 125d9f0492fSopenharmony_ci self.parse_file(file_name) 126d9f0492fSopenharmony_ci 127d9f0492fSopenharmony_ci dict_priority = dict() 128d9f0492fSopenharmony_ci dict_allow_list = dict() 129d9f0492fSopenharmony_ci dict_priority_with_args = dict() 130d9f0492fSopenharmony_ci dict_allow_list_with_args = dict() 131d9f0492fSopenharmony_ci dict_blocklist = dict() 132d9f0492fSopenharmony_ci 133d9f0492fSopenharmony_ci for arch in gen_policy.supported_architecture: 134d9f0492fSopenharmony_ci dict_priority.update({arch: self.seccomp_policy_param.get(arch).priority}) 135d9f0492fSopenharmony_ci dict_allow_list.update({arch: self.seccomp_policy_param.get(arch).allow_list}) 136d9f0492fSopenharmony_ci dict_priority_with_args.update({arch: self.seccomp_policy_param.get(arch).priority_with_args}) 137d9f0492fSopenharmony_ci dict_allow_list_with_args.update({arch: self.seccomp_policy_param.get(arch).allow_list_with_args}) 138d9f0492fSopenharmony_ci dict_blocklist.update({arch: self.seccomp_policy_param.get(arch).blocklist}) 139d9f0492fSopenharmony_ci 140d9f0492fSopenharmony_ci content = self.get_item_content(function_name_nr_table_dict, "@priority", dict_priority) 141d9f0492fSopenharmony_ci content += self.get_item_content(function_name_nr_table_dict, "@allowList", dict_allow_list) 142d9f0492fSopenharmony_ci content += self.get_item_content(function_name_nr_table_dict, "@priorityWithArgs", dict_priority_with_args) 143d9f0492fSopenharmony_ci content += self.get_item_content(function_name_nr_table_dict, "@allowListWithArgs", dict_allow_list_with_args) 144d9f0492fSopenharmony_ci content += self.get_item_content(function_name_nr_table_dict, "@blockList", dict_blocklist) 145d9f0492fSopenharmony_ci audit_policy.gen_output_file(args.filter_name, content) 146d9f0492fSopenharmony_ci 147d9f0492fSopenharmony_ci 148d9f0492fSopenharmony_cidef main(): 149d9f0492fSopenharmony_ci parser = argparse.ArgumentParser( 150d9f0492fSopenharmony_ci description='Generates a seccomp-bpf policy') 151d9f0492fSopenharmony_ci parser.add_argument('--src-files', type=str, action='append', 152d9f0492fSopenharmony_ci help=('input libsyscall_to_nr files and policy filse\n')) 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_ci parser.add_argument('--filter-name', type=str, 155d9f0492fSopenharmony_ci help='Name of seccomp bpf array generated by this script') 156d9f0492fSopenharmony_ci 157d9f0492fSopenharmony_ci args = parser.parse_args() 158d9f0492fSopenharmony_ci 159d9f0492fSopenharmony_ci generator = MergePolicy() 160d9f0492fSopenharmony_ci generator.merge_policy(args) 161d9f0492fSopenharmony_ci 162d9f0492fSopenharmony_ci 163d9f0492fSopenharmony_ciif __name__ == '__main__': 164d9f0492fSopenharmony_ci sys.exit(main()) 165