1#!/usr/bin/env python3 2# 3# Copyright 2022 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import logging 18import json 19import sys 20import os 21import argparse 22 23def check_file_exists(file_name): 24 if not os.path.exists(file_name): 25 sys.exit("File doesn't exist : {0}".format(file_name)) 26 27def read_bindings(binding_file): 28 check_file_exists(binding_file) 29 with open(binding_file) as jsonFile: 30 bindings = json.loads(jsonFile.read()) 31 return bindings 32 33def check_fuzzer_exists(context_file, bindings): 34 with open(context_file) as file: 35 for line in file: 36 # Ignore empty lines and comments 37 line = line.strip() 38 if line.startswith("#"): 39 logging.debug("Found a comment..skipping") 40 continue 41 42 tokens = line.split() 43 if len(tokens) == 0: 44 logging.debug("Skipping empty lines in service_contexts") 45 continue 46 47 # For a valid service_context file, there will be only two tokens 48 # First will be service name and second will be its label. 49 service_name = tokens[0] 50 if service_name not in bindings: 51 sys.exit("\nerror: Service '{0}' is being added, but we have no fuzzer on file for it. " 52 "Fuzzers are listed at $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go \n\n" 53 "NOTE: automatic service fuzzers are currently not supported in Java (b/232439254) " 54 "and Rust (b/164122727). In this case, please ignore this for now and add an entry for your" 55 "new service in service_fuzzer_bindings.go \n\n" 56 "If you are writing a new service, it may be subject to attack from other " 57 "potentially malicious processes. A fuzzer can be written automatically " 58 "by adding these things: \n" 59 "- a cc_fuzz Android.bp entry \n" 60 "- a main file that constructs your service and calls 'fuzzService' \n\n" 61 "An examples can be found here: \n" 62 "- $ANDROID_BUILD_TOP/hardware/interfaces/vibrator/aidl/default/fuzzer.cpp \n" 63 "- https://source.android.com/docs/core/architecture/aidl/aidl-fuzzing \n\n" 64 "This is only ~30 lines of configuration. It requires dependency injection " 65 "for your service which is a good practice, and (in AOSP) you will get bugs " 66 "automatically filed on you. You will find out about issues without needing " 67 "to backport changes years later, and the system will automatically find ways " 68 "to reproduce difficult to solve issues for you. \n\n" 69 "This error can be bypassed by adding entry " 70 "for new service in $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go \n\n" 71 "- Android Fuzzing and Security teams".format(service_name)) 72 return 73 74def validate_bindings(args): 75 bindings = read_bindings(args.bindings) 76 for file in args.srcs: 77 check_file_exists(file) 78 check_fuzzer_exists(file, bindings) 79 return 80 81def get_args(): 82 parser = argparse.ArgumentParser(description="Tool to check if fuzzer is " 83 "added for new services") 84 parser.add_argument('-b', help='Path to json file containing ' 85 '"service":[fuzzers...] bindings.', 86 required=True, dest='bindings') 87 parser.add_argument('-s', '--list', nargs='+', 88 help='list of service_contexts files. Tool will check if ' 89 'there is fuzzer for every service in the context ' 90 'file.', required=True, dest='srcs') 91 parsed_args = parser.parse_args() 92 return parsed_args 93 94if __name__ == "__main__": 95 args = get_args() 96 validate_bindings(args) 97