xref: /aosp_15_r20/system/sepolicy/tools/fuzzer_bindings_check.py (revision e4a36f4174b17bbab9dc043f4a65dc8d87377290)
1*e4a36f41SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*e4a36f41SAndroid Build Coastguard Worker#
3*e4a36f41SAndroid Build Coastguard Worker# Copyright 2022 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 Workerimport logging
18*e4a36f41SAndroid Build Coastguard Workerimport json
19*e4a36f41SAndroid Build Coastguard Workerimport sys
20*e4a36f41SAndroid Build Coastguard Workerimport os
21*e4a36f41SAndroid Build Coastguard Workerimport argparse
22*e4a36f41SAndroid Build Coastguard Worker
23*e4a36f41SAndroid Build Coastguard Workerdef check_file_exists(file_name):
24*e4a36f41SAndroid Build Coastguard Worker  if not os.path.exists(file_name):
25*e4a36f41SAndroid Build Coastguard Worker    sys.exit("File doesn't exist : {0}".format(file_name))
26*e4a36f41SAndroid Build Coastguard Worker
27*e4a36f41SAndroid Build Coastguard Workerdef read_bindings(binding_file):
28*e4a36f41SAndroid Build Coastguard Worker  check_file_exists(binding_file)
29*e4a36f41SAndroid Build Coastguard Worker  with open(binding_file) as jsonFile:
30*e4a36f41SAndroid Build Coastguard Worker   bindings = json.loads(jsonFile.read())
31*e4a36f41SAndroid Build Coastguard Worker  return bindings
32*e4a36f41SAndroid Build Coastguard Worker
33*e4a36f41SAndroid Build Coastguard Workerdef check_fuzzer_exists(context_file, bindings):
34*e4a36f41SAndroid Build Coastguard Worker  with open(context_file) as file:
35*e4a36f41SAndroid Build Coastguard Worker    for line in file:
36*e4a36f41SAndroid Build Coastguard Worker       # Ignore empty lines and comments
37*e4a36f41SAndroid Build Coastguard Worker       line = line.strip()
38*e4a36f41SAndroid Build Coastguard Worker       if line.startswith("#"):
39*e4a36f41SAndroid Build Coastguard Worker         logging.debug("Found a comment..skipping")
40*e4a36f41SAndroid Build Coastguard Worker         continue
41*e4a36f41SAndroid Build Coastguard Worker
42*e4a36f41SAndroid Build Coastguard Worker       tokens = line.split()
43*e4a36f41SAndroid Build Coastguard Worker       if len(tokens) == 0:
44*e4a36f41SAndroid Build Coastguard Worker         logging.debug("Skipping empty lines in service_contexts")
45*e4a36f41SAndroid Build Coastguard Worker         continue
46*e4a36f41SAndroid Build Coastguard Worker
47*e4a36f41SAndroid Build Coastguard Worker       # For a valid service_context file, there will be only two tokens
48*e4a36f41SAndroid Build Coastguard Worker       # First will be service name and second will be its label.
49*e4a36f41SAndroid Build Coastguard Worker       service_name = tokens[0]
50*e4a36f41SAndroid Build Coastguard Worker       if service_name not in bindings:
51*e4a36f41SAndroid Build Coastguard Worker         sys.exit("\nerror: Service '{0}' is being added, but we have no fuzzer on file for it. "
52*e4a36f41SAndroid Build Coastguard Worker                  "Fuzzers are listed at $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go \n\n"
53*e4a36f41SAndroid Build Coastguard Worker                  "NOTE: automatic service fuzzers are currently not supported in Java (b/287102710.)"
54*e4a36f41SAndroid Build Coastguard Worker                  "In this case, please ignore this for now and add an entry for your"
55*e4a36f41SAndroid Build Coastguard Worker                  "new service in service_fuzzer_bindings.go \n\n"
56*e4a36f41SAndroid Build Coastguard Worker                  "If you are writing a new service, it may be subject to attack from other "
57*e4a36f41SAndroid Build Coastguard Worker                  "potentially malicious processes. A fuzzer can be written automatically "
58*e4a36f41SAndroid Build Coastguard Worker                  "by adding these things: \n"
59*e4a36f41SAndroid Build Coastguard Worker                  "- a cc_fuzz Android.bp entry \n"
60*e4a36f41SAndroid Build Coastguard Worker                  "- a main file that constructs your service and calls 'fuzzService' \n\n"
61*e4a36f41SAndroid Build Coastguard Worker                  "An examples can be found here: \n"
62*e4a36f41SAndroid Build Coastguard Worker                  "- $ANDROID_BUILD_TOP/hardware/interfaces/vibrator/aidl/default/fuzzer.cpp \n"
63*e4a36f41SAndroid Build Coastguard Worker                  "- https://source.android.com/docs/core/architecture/aidl/aidl-fuzzing \n\n"
64*e4a36f41SAndroid Build Coastguard Worker                  "This is only ~30 lines of configuration. It requires dependency injection "
65*e4a36f41SAndroid Build Coastguard Worker                  "for your service which is a good practice, and (in AOSP) you will get bugs "
66*e4a36f41SAndroid Build Coastguard Worker                  "automatically filed on you. You will find out about issues without needing "
67*e4a36f41SAndroid Build Coastguard Worker                  "to backport changes years later, and the system will automatically find ways "
68*e4a36f41SAndroid Build Coastguard Worker                  "to reproduce difficult to solve issues for you. \n\n"
69*e4a36f41SAndroid Build Coastguard Worker                  "This error can be bypassed by adding entry "
70*e4a36f41SAndroid Build Coastguard Worker                  "for new service in $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go \n\n"
71*e4a36f41SAndroid Build Coastguard Worker                  "- Android Fuzzing and Security teams".format(service_name))
72*e4a36f41SAndroid Build Coastguard Worker  return
73*e4a36f41SAndroid Build Coastguard Worker
74*e4a36f41SAndroid Build Coastguard Workerdef validate_bindings(args):
75*e4a36f41SAndroid Build Coastguard Worker  bindings = read_bindings(args.bindings)
76*e4a36f41SAndroid Build Coastguard Worker  for file in args.srcs:
77*e4a36f41SAndroid Build Coastguard Worker    check_file_exists(file)
78*e4a36f41SAndroid Build Coastguard Worker    check_fuzzer_exists(file, bindings)
79*e4a36f41SAndroid Build Coastguard Worker  return
80*e4a36f41SAndroid Build Coastguard Worker
81*e4a36f41SAndroid Build Coastguard Workerdef get_args():
82*e4a36f41SAndroid Build Coastguard Worker  parser =  argparse.ArgumentParser(description="Tool to check if fuzzer is "
83*e4a36f41SAndroid Build Coastguard Worker                                                "added for new services")
84*e4a36f41SAndroid Build Coastguard Worker  parser.add_argument('-b', help='Path to json file containing '
85*e4a36f41SAndroid Build Coastguard Worker                                 '"service":[fuzzers...] bindings.',
86*e4a36f41SAndroid Build Coastguard Worker                      required=True, dest='bindings')
87*e4a36f41SAndroid Build Coastguard Worker  parser.add_argument('-s', '--list', nargs='+',
88*e4a36f41SAndroid Build Coastguard Worker                      help='list of service_contexts files. Tool will check if '
89*e4a36f41SAndroid Build Coastguard Worker                           'there is fuzzer for every service in the context '
90*e4a36f41SAndroid Build Coastguard Worker                           'file.', required=True, dest='srcs')
91*e4a36f41SAndroid Build Coastguard Worker  parsed_args = parser.parse_args()
92*e4a36f41SAndroid Build Coastguard Worker  return parsed_args
93*e4a36f41SAndroid Build Coastguard Worker
94*e4a36f41SAndroid Build Coastguard Workerif __name__ == "__main__":
95*e4a36f41SAndroid Build Coastguard Worker  args = get_args()
96*e4a36f41SAndroid Build Coastguard Worker  validate_bindings(args)
97