xref: /aosp_15_r20/system/sepolicy/build/build_sepolicy.py (revision e4a36f4174b17bbab9dc043f4a65dc8d87377290)
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