1*e4a36f41SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*e4a36f41SAndroid Build Coastguard Worker# 3*e4a36f41SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project 4*e4a36f41SAndroid Build Coastguard Worker# 5*e4a36f41SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*e4a36f41SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*e4a36f41SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*e4a36f41SAndroid Build Coastguard Worker# 9*e4a36f41SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*e4a36f41SAndroid Build Coastguard Worker# 11*e4a36f41SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*e4a36f41SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*e4a36f41SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*e4a36f41SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*e4a36f41SAndroid Build Coastguard Worker# limitations under the License. 16*e4a36f41SAndroid Build Coastguard Worker 17*e4a36f41SAndroid Build Coastguard Worker"""Command-line tool to build SEPolicy files.""" 18*e4a36f41SAndroid Build Coastguard Worker 19*e4a36f41SAndroid Build Coastguard Workerimport argparse 20*e4a36f41SAndroid Build Coastguard Workerimport os 21*e4a36f41SAndroid Build Coastguard Workerimport subprocess 22*e4a36f41SAndroid Build Coastguard Workerimport sys 23*e4a36f41SAndroid Build Coastguard Worker 24*e4a36f41SAndroid Build Coastguard Workerimport file_utils 25*e4a36f41SAndroid Build Coastguard Worker 26*e4a36f41SAndroid Build Coastguard Worker 27*e4a36f41SAndroid Build Coastguard Worker# All supported commands in this module. 28*e4a36f41SAndroid Build Coastguard Worker# For each command, need to add two functions. Take 'build_cil' for example: 29*e4a36f41SAndroid Build Coastguard Worker# - setup_build_cil() 30*e4a36f41SAndroid Build Coastguard Worker# - Sets up command parsers and sets default function to do_build_cil(). 31*e4a36f41SAndroid Build Coastguard Worker# - do_build_cil() 32*e4a36f41SAndroid Build Coastguard Worker_SUPPORTED_COMMANDS = ('build_cil', 'filter_out') 33*e4a36f41SAndroid Build Coastguard Worker 34*e4a36f41SAndroid Build Coastguard Worker 35*e4a36f41SAndroid Build Coastguard Workerdef run_host_command(args, **kwargs): 36*e4a36f41SAndroid Build Coastguard Worker """Runs a host command and prints output.""" 37*e4a36f41SAndroid Build Coastguard Worker if kwargs.get('shell'): 38*e4a36f41SAndroid Build Coastguard Worker command_log = args 39*e4a36f41SAndroid Build Coastguard Worker else: 40*e4a36f41SAndroid Build Coastguard Worker command_log = ' '.join(args) # For args as a sequence. 41*e4a36f41SAndroid Build Coastguard Worker 42*e4a36f41SAndroid Build Coastguard Worker try: 43*e4a36f41SAndroid Build Coastguard Worker subprocess.check_call(args, **kwargs) 44*e4a36f41SAndroid Build Coastguard Worker except subprocess.CalledProcessError as err: 45*e4a36f41SAndroid Build Coastguard Worker sys.stderr.write( 46*e4a36f41SAndroid Build Coastguard Worker 'build_sepolicy - failed to run command: {!r} (ret:{})\n'.format( 47*e4a36f41SAndroid Build Coastguard Worker command_log, err.returncode)) 48*e4a36f41SAndroid Build Coastguard Worker sys.exit(err.returncode) 49*e4a36f41SAndroid Build Coastguard Worker 50*e4a36f41SAndroid Build Coastguard Worker 51*e4a36f41SAndroid Build Coastguard Workerdef do_build_cil(args): 52*e4a36f41SAndroid Build Coastguard Worker """Builds a sepolicy CIL (Common Intermediate Language) file. 53*e4a36f41SAndroid Build Coastguard Worker 54*e4a36f41SAndroid Build Coastguard Worker This functions invokes some host utils (e.g., secilc, checkpolicy, 55*e4a36f41SAndroid Build Coastguard Worker version_sepolicy) to generate a .cil file. 56*e4a36f41SAndroid Build Coastguard Worker 57*e4a36f41SAndroid Build Coastguard Worker Args: 58*e4a36f41SAndroid Build Coastguard Worker args: the parsed command arguments. 59*e4a36f41SAndroid Build Coastguard Worker """ 60*e4a36f41SAndroid Build Coastguard Worker # Determines the raw CIL file name. 61*e4a36f41SAndroid Build Coastguard Worker input_file_name = os.path.splitext(args.input_policy_conf)[0] 62*e4a36f41SAndroid Build Coastguard Worker raw_cil_file = input_file_name + '_raw.cil' 63*e4a36f41SAndroid Build Coastguard Worker # Builds the raw CIL. 64*e4a36f41SAndroid Build Coastguard Worker file_utils.make_parent_dirs(raw_cil_file) 65*e4a36f41SAndroid Build Coastguard Worker checkpolicy_cmd = [args.checkpolicy_env] 66*e4a36f41SAndroid Build Coastguard Worker checkpolicy_cmd += [os.path.join(args.android_host_path, 'checkpolicy'), 67*e4a36f41SAndroid Build Coastguard Worker '-C', '-M', '-c', args.policy_vers, 68*e4a36f41SAndroid Build Coastguard Worker '-o', raw_cil_file, args.input_policy_conf] 69*e4a36f41SAndroid Build Coastguard Worker # Using shell=True to setup args.checkpolicy_env variables. 70*e4a36f41SAndroid Build Coastguard Worker run_host_command(' '.join(checkpolicy_cmd), shell=True) 71*e4a36f41SAndroid Build Coastguard Worker file_utils.filter_out([args.reqd_mask], raw_cil_file) 72*e4a36f41SAndroid Build Coastguard Worker 73*e4a36f41SAndroid Build Coastguard Worker # Builds the output CIL by versioning the above raw CIL. 74*e4a36f41SAndroid Build Coastguard Worker output_file = args.output_cil 75*e4a36f41SAndroid Build Coastguard Worker if output_file is None: 76*e4a36f41SAndroid Build Coastguard Worker output_file = input_file_name + '.cil' 77*e4a36f41SAndroid Build Coastguard Worker file_utils.make_parent_dirs(output_file) 78*e4a36f41SAndroid Build Coastguard Worker 79*e4a36f41SAndroid Build Coastguard Worker run_host_command([os.path.join(args.android_host_path, 'version_policy'), 80*e4a36f41SAndroid Build Coastguard Worker '-b', args.base_policy, '-t', raw_cil_file, 81*e4a36f41SAndroid Build Coastguard Worker '-n', args.treble_sepolicy_vers, '-o', output_file]) 82*e4a36f41SAndroid Build Coastguard Worker if args.filter_out_files: 83*e4a36f41SAndroid Build Coastguard Worker file_utils.filter_out(args.filter_out_files, output_file) 84*e4a36f41SAndroid Build Coastguard Worker 85*e4a36f41SAndroid Build Coastguard Worker # Tests that the output file can be merged with the given CILs. 86*e4a36f41SAndroid Build Coastguard Worker if args.dependent_cils: 87*e4a36f41SAndroid Build Coastguard Worker merge_cmd = [os.path.join(args.android_host_path, 'secilc'), 88*e4a36f41SAndroid Build Coastguard Worker '-m', '-M', 'true', '-G', '-N', '-c', args.policy_vers] 89*e4a36f41SAndroid Build Coastguard Worker merge_cmd += args.dependent_cils # the give CILs to merge 90*e4a36f41SAndroid Build Coastguard Worker merge_cmd += [output_file, '-o', '/dev/null', '-f', '/dev/null'] 91*e4a36f41SAndroid Build Coastguard Worker run_host_command(merge_cmd) 92*e4a36f41SAndroid Build Coastguard Worker 93*e4a36f41SAndroid Build Coastguard Worker 94*e4a36f41SAndroid Build Coastguard Workerdef setup_build_cil(subparsers): 95*e4a36f41SAndroid Build Coastguard Worker """Sets up command args for 'build_cil' command.""" 96*e4a36f41SAndroid Build Coastguard Worker 97*e4a36f41SAndroid Build Coastguard Worker # Required arguments. 98*e4a36f41SAndroid Build Coastguard Worker parser = subparsers.add_parser('build_cil', help='build CIL files') 99*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-i', '--input_policy_conf', required=True, 100*e4a36f41SAndroid Build Coastguard Worker help='source policy.conf') 101*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-m', '--reqd_mask', required=True, 102*e4a36f41SAndroid Build Coastguard Worker help='the bare minimum policy.conf to use checkpolicy') 103*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-b', '--base_policy', required=True, 104*e4a36f41SAndroid Build Coastguard Worker help='base policy for versioning') 105*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-t', '--treble_sepolicy_vers', required=True, 106*e4a36f41SAndroid Build Coastguard Worker help='the version number to use for Treble-OTA') 107*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-p', '--policy_vers', required=True, 108*e4a36f41SAndroid Build Coastguard Worker help='SELinux policy version') 109*e4a36f41SAndroid Build Coastguard Worker 110*e4a36f41SAndroid Build Coastguard Worker # Optional arguments. 111*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-c', '--checkpolicy_env', 112*e4a36f41SAndroid Build Coastguard Worker help='environment variables passed to checkpolicy') 113*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-f', '--filter_out_files', nargs='+', 114*e4a36f41SAndroid Build Coastguard Worker help='the pattern files to filter out the output cil') 115*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-d', '--dependent_cils', nargs='+', 116*e4a36f41SAndroid Build Coastguard Worker help=('check the output file can be merged with ' 117*e4a36f41SAndroid Build Coastguard Worker 'the dependent cil files')) 118*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-o', '--output_cil', help='the output cil file') 119*e4a36f41SAndroid Build Coastguard Worker 120*e4a36f41SAndroid Build Coastguard Worker # The function that performs the actual works. 121*e4a36f41SAndroid Build Coastguard Worker parser.set_defaults(func=do_build_cil) 122*e4a36f41SAndroid Build Coastguard Worker 123*e4a36f41SAndroid Build Coastguard Worker 124*e4a36f41SAndroid Build Coastguard Workerdef do_filter_out(args): 125*e4a36f41SAndroid Build Coastguard Worker """Removes all lines in one file that match any line in another file. 126*e4a36f41SAndroid Build Coastguard Worker 127*e4a36f41SAndroid Build Coastguard Worker Args: 128*e4a36f41SAndroid Build Coastguard Worker args: the parsed command arguments. 129*e4a36f41SAndroid Build Coastguard Worker """ 130*e4a36f41SAndroid Build Coastguard Worker file_utils.filter_out(args.filter_out_files, args.target_file) 131*e4a36f41SAndroid Build Coastguard Worker 132*e4a36f41SAndroid Build Coastguard Workerdef setup_filter_out(subparsers): 133*e4a36f41SAndroid Build Coastguard Worker """Sets up command args for 'filter_out' command.""" 134*e4a36f41SAndroid Build Coastguard Worker parser = subparsers.add_parser('filter_out', help='filter CIL files') 135*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-f', '--filter_out_files', required=True, nargs='+', 136*e4a36f41SAndroid Build Coastguard Worker help='the pattern files to filter out the output cil') 137*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-t', '--target_file', required=True, 138*e4a36f41SAndroid Build Coastguard Worker help='target file to filter') 139*e4a36f41SAndroid Build Coastguard Worker parser.set_defaults(func=do_filter_out) 140*e4a36f41SAndroid Build Coastguard Worker 141*e4a36f41SAndroid Build Coastguard Worker 142*e4a36f41SAndroid Build Coastguard Workerdef run(argv): 143*e4a36f41SAndroid Build Coastguard Worker """Sets up command parser and execuates sub-command.""" 144*e4a36f41SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 145*e4a36f41SAndroid Build Coastguard Worker 146*e4a36f41SAndroid Build Coastguard Worker # Adds top-level arguments. 147*e4a36f41SAndroid Build Coastguard Worker parser.add_argument('-a', '--android_host_path', default='', 148*e4a36f41SAndroid Build Coastguard Worker help='a path to host out executables') 149*e4a36f41SAndroid Build Coastguard Worker 150*e4a36f41SAndroid Build Coastguard Worker # Adds subparsers for each COMMAND. 151*e4a36f41SAndroid Build Coastguard Worker subparsers = parser.add_subparsers(title='COMMAND') 152*e4a36f41SAndroid Build Coastguard Worker for command in _SUPPORTED_COMMANDS: 153*e4a36f41SAndroid Build Coastguard Worker globals()['setup_' + command](subparsers) 154*e4a36f41SAndroid Build Coastguard Worker 155*e4a36f41SAndroid Build Coastguard Worker args = parser.parse_args(argv[1:]) 156*e4a36f41SAndroid Build Coastguard Worker args.func(args) 157*e4a36f41SAndroid Build Coastguard Worker 158*e4a36f41SAndroid Build Coastguard Worker 159*e4a36f41SAndroid Build Coastguard Workerif __name__ == '__main__': 160*e4a36f41SAndroid Build Coastguard Worker run(sys.argv) 161