sepolicy : Recommend fuzzers for new services

Adding soong module and tool to check if there is fuzzer present
for every service in private/service_contexts. Whenever a service is
added, its is recommended to update
$ANDROID_BUILD_TOP/system/sepolicy/soong/build/service_fuzzer_bindings.go
with service name and its corresponding fuzzer.

Test: m
Bug: 242104782
Change-Id: Id9bc45f50bebf464de7c91c7469d4bb6ff153ebd
This commit is contained in:
Pawan 2022-09-12 23:20:53 +00:00
parent 6b09c56a6a
commit 0ecf99def5
8 changed files with 632 additions and 0 deletions

View file

@ -324,6 +324,7 @@ LOCAL_REQUIRED_MODULES += \
plat_service_contexts_test \
plat_hwservice_contexts \
plat_hwservice_contexts_test \
fuzzer_bindings_test \
plat_bug_map \
searchpolicy \

View file

@ -43,6 +43,8 @@ bootstrap_go_package {
"sepolicy_neverallow.go",
"sepolicy_vers.go",
"versioned_policy.go",
"service_fuzzer_bindings.go",
"validate_bindings.go",
],
pluginFor: ["soong_build"],
}

View file

@ -0,0 +1,406 @@
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package selinux
var (
ServiceFuzzerBindings = map[string][]string{
"android.hardware.audio.core.IConfig/default": []string{},
"android.hardware.audio.core.IModule/default": []string{},
"android.hardware.audio.effect.IFactory/default": []string{},
"android.hardware.authsecret.IAuthSecret/default": []string{},
"android.hardware.automotive.evs.IEvsEnumerator/hw/0": []string{},
"android.hardware.boot.IBootControl/default": []string{},
"android.hardware.automotive.evs.IEvsEnumerator/hw/1": []string{},
"android.hardware.automotive.vehicle.IVehicle/default": []string{},
"android.hardware.automotive.audiocontrol.IAudioControl/default": []string{},
"android.hardware.biometrics.face.IFace/default": []string{},
"android.hardware.biometrics.fingerprint.IFingerprint/default": []string{},
"android.hardware.biometrics.fingerprint.IFingerprint/virtual": []string{},
"android.hardware.bluetooth.audio.IBluetoothAudioProviderFactory/default": []string{},
"android.hardware.camera.provider.ICameraProvider/internal/0": []string{},
"android.hardware.contexthub.IContextHub/default": []string{},
"android.hardware.drm.IDrmFactory/clearkey": []string{},
"android.hardware.drm.ICryptoFactory/clearkey": []string{},
"android.hardware.dumpstate.IDumpstateDevice/default": []string{},
"android.hardware.gnss.IGnss/default": []string{},
"android.hardware.graphics.allocator.IAllocator/default": []string{},
"android.hardware.graphics.composer3.IComposer/default": []string{},
"android.hardware.health.storage.IStorage/default": []string{},
"android.hardware.health.IHealth/default": []string{},
"android.hardware.identity.IIdentityCredentialStore/default": []string{},
"android.hardware.input.processor.IInputProcessor/default": []string{},
"android.hardware.ir.IConsumerIr/default": []string{},
"android.hardware.light.ILights/default": []string{},
"android.hardware.memtrack.IMemtrack/default": []string{},
"android.hardware.net.nlinterceptor.IInterceptor/default": []string{},
"android.hardware.nfc.INfc/default": []string{},
"android.hardware.oemlock.IOemLock/default": []string{},
"android.hardware.power.IPower/default": []string{},
"android.hardware.power.stats.IPowerStats/default": []string{},
"android.hardware.radio.config.IRadioConfig/default": []string{},
"android.hardware.radio.data.IRadioData/slot1": []string{},
"android.hardware.radio.data.IRadioData/slot2": []string{},
"android.hardware.radio.data.IRadioData/slot3": []string{},
"android.hardware.radio.messaging.IRadioMessaging/slot1": []string{},
"android.hardware.radio.messaging.IRadioMessaging/slot2": []string{},
"android.hardware.radio.messaging.IRadioMessaging/slot3": []string{},
"android.hardware.radio.modem.IRadioModem/slot1": []string{},
"android.hardware.radio.modem.IRadioModem/slot2": []string{},
"android.hardware.radio.modem.IRadioModem/slot3": []string{},
"android.hardware.radio.network.IRadioNetwork/slot1": []string{},
"android.hardware.radio.network.IRadioNetwork/slot2": []string{},
"android.hardware.radio.network.IRadioNetwork/slot3": []string{},
"android.hardware.radio.sim.IRadioSim/slot1": []string{},
"android.hardware.radio.sim.IRadioSim/slot2": []string{},
"android.hardware.radio.sim.IRadioSim/slot3": []string{},
"android.hardware.radio.voice.IRadioVoice/slot1": []string{},
"android.hardware.radio.voice.IRadioVoice/slot2": []string{},
"android.hardware.radio.voice.IRadioVoice/slot3": []string{},
"android.hardware.rebootescrow.IRebootEscrow/default": []string{},
"android.hardware.security.dice.IDiceDevice/default": []string{},
"android.hardware.security.keymint.IKeyMintDevice/default": []string{},
"android.hardware.security.keymint.IRemotelyProvisionedComponent/default": []string{},
"android.hardware.security.secureclock.ISecureClock/default": []string{},
"android.hardware.security.sharedsecret.ISharedSecret/default": []string{},
"android.hardware.sensors.ISensors/default": []string{},
"android.hardware.soundtrigger3.ISoundTriggerHw/default": []string{},
"android.hardware.tv.input.ITvInput/default": []string{},
"android.hardware.tv.tuner.ITuner/default": []string{},
"android.hardware.usb.IUsb/default": []string{},
"android.hardware.uwb.IUwb/default": []string{},
"android.hardware.vibrator.IVibrator/default": []string{},
"android.hardware.vibrator.IVibratorManager/default": []string{},
"android.hardware.weaver.IWeaver/default": []string{},
"android.hardware.wifi.hostapd.IHostapd/default": []string{},
"android.hardware.wifi.supplicant.ISupplicant/default": []string{},
"android.frameworks.stats.IStats/default": []string{},
"android.se.omapi.ISecureElementService/default": []string{},
"android.system.keystore2.IKeystoreService/default": []string{},
"android.system.net.netd.INetd/default": []string{},
"android.system.suspend.ISystemSuspend/default": []string{},
"accessibility": []string{},
"account": []string{},
"activity": []string{},
"activity_task": []string{},
"adb": []string{},
"adservices_manager": []string{},
"aidl_lazy_test_1": []string{},
"aidl_lazy_test_2": []string{},
"aidl_lazy_cb_test": []string{},
"alarm": []string{},
"android.hardware.automotive.evs.IEvsEnumerator/default": []string{},
"android.os.UpdateEngineService": []string{},
"android.os.UpdateEngineStableService": []string{},
"android.frameworks.automotive.display.ICarDisplayProxy/default": []string{},
"android.security.apc": []string{},
"android.security.authorization": []string{},
"android.security.compat": []string{},
"android.security.dice.IDiceMaintenance": []string{},
"android.security.dice.IDiceNode": []string{},
"android.security.identity": []string{},
"android.security.keystore": []string{},
"android.security.legacykeystore": []string{},
"android.security.maintenance": []string{},
"android.security.metrics": []string{},
"android.security.remoteprovisioning": []string{},
"android.security.remoteprovisioning.IRemotelyProvisionedKeyPool": []string{},
"android.service.gatekeeper.IGateKeeperService": []string{},
"android.system.composd": []string{},
"android.system.virtualizationservice": []string{},
"ambient_context": []string{},
"app_binding": []string{},
"app_hibernation": []string{},
"app_integrity": []string{},
"app_prediction": []string{},
"app_search": []string{},
"apexservice": []string{},
"attestation_verification": []string{},
"blob_store": []string{},
"gsiservice": []string{},
"appops": []string{},
"appwidget": []string{},
"artd": []string{},
"assetatlas": []string{},
"attention": []string{},
"audio": []string{},
"auth": []string{},
"autofill": []string{},
"backup": []string{},
"batteryproperties": []string{},
"batterystats": []string{},
"battery": []string{},
"binder_calls_stats": []string{},
"biometric": []string{},
"bluetooth_manager": []string{},
"bluetooth": []string{},
"broadcastradio": []string{},
"bugreport": []string{},
"cacheinfo": []string{},
"carrier_config": []string{},
"clipboard": []string{},
"cloudsearch": []string{},
"cloudsearch_service": []string{},
"com.android.net.IProxyService": []string{},
"companiondevice": []string{},
"communal": []string{},
"platform_compat": []string{},
"platform_compat_native": []string{},
"connectivity": []string{},
"connectivity_native": []string{},
"connmetrics": []string{},
"consumer_ir": []string{},
"content": []string{},
"content_capture": []string{},
"content_suggestions": []string{},
"contexthub": []string{},
"country_detector": []string{},
"coverage": []string{},
"cpuinfo": []string{},
"crossprofileapps": []string{},
"dataloader_manager": []string{},
"dbinfo": []string{},
"device_config": []string{},
"device_policy": []string{},
"device_identifiers": []string{},
"deviceidle": []string{},
"device_state": []string{},
"devicestoragemonitor": []string{},
"diskstats": []string{},
"display": []string{},
"dnsresolver": []string{},
"domain_verification": []string{},
"color_display": []string{},
"netd_listener": []string{},
"network_watchlist": []string{},
"DockObserver": []string{},
"dreams": []string{},
"drm.drmManager": []string{},
"dropbox": []string{},
"dumpstate": []string{},
"dynamic_system": []string{},
"econtroller": []string{},
"emergency_affordance": []string{},
"euicc_card_controller": []string{},
"external_vibrator_service": []string{},
"ethernet": []string{},
"face": []string{},
"file_integrity": []string{},
"fingerprint": []string{},
"font": []string{},
"android.hardware.fingerprint.IFingerprintDaemon": []string{},
"game": []string{},
"gfxinfo": []string{},
"gnss_time_update_service": []string{},
"graphicsstats": []string{},
"gpu": []string{},
"hardware": []string{},
"hardware_properties": []string{},
"hdmi_control": []string{},
"ions": []string{},
"idmap": []string{},
"incident": []string{},
"incidentcompanion": []string{},
"inputflinger": []string{},
"input_method": []string{},
"input": []string{},
"installd": []string{},
"iphonesubinfo_msim": []string{},
"iphonesubinfo2": []string{},
"iphonesubinfo": []string{},
"ims": []string{},
"imms": []string{},
"incremental": []string{},
"ipsec": []string{},
"ircsmessage": []string{},
"iris": []string{},
"isms_msim": []string{},
"isms2": []string{},
"isms": []string{},
"isub": []string{},
"jobscheduler": []string{},
"launcherapps": []string{},
"legacy_permission": []string{},
"lights": []string{},
"locale": []string{},
"location": []string{},
"location_time_zone_manager": []string{},
"lock_settings": []string{},
"logcat": []string{},
"logd": []string{},
"looper_stats": []string{},
"lpdump_service": []string{},
"mdns": []string{},
"media.aaudio": []string{},
"media.audio_flinger": []string{},
"media.audio_policy": []string{},
"media.camera": []string{},
"media.camera.proxy": []string{},
"media.log": []string{},
"media.player": []string{},
"media.metrics": []string{},
"media.extractor": []string{},
"media.transcoding": []string{},
"media.resource_manager": []string{},
"media.resource_observer": []string{},
"media.sound_trigger_hw": []string{},
"media.drm": []string{},
"media.tuner": []string{},
"media_communication": []string{},
"media_metrics": []string{},
"media_projection": []string{},
"media_resource_monitor": []string{},
"media_router": []string{},
"media_session": []string{},
"meminfo": []string{},
"memtrack.proxy": []string{},
"midi": []string{},
"mount": []string{},
"music_recognition": []string{},
"nearby": []string{},
"netd": []string{},
"netpolicy": []string{},
"netstats": []string{},
"network_stack": []string{},
"network_management": []string{},
"network_score": []string{},
"network_time_update_service": []string{},
"nfc": []string{},
"notification": []string{},
"oem_lock": []string{},
"otadexopt": []string{},
"overlay": []string{},
"pac_proxy": []string{},
"package": []string{},
"package_native": []string{},
"people": []string{},
"performance_hint": []string{},
"permission": []string{},
"permissionmgr": []string{},
"permission_checker": []string{},
"persistent_data_block": []string{},
"phone_msim": []string{},
"phone1": []string{},
"phone2": []string{},
"phone": []string{},
"pinner": []string{},
"powerstats": []string{},
"power": []string{},
"print": []string{},
"processinfo": []string{},
"procstats": []string{},
"profcollectd": []string{},
"radio.phonesubinfo": []string{},
"radio.phone": []string{},
"radio.sms": []string{},
"rcs": []string{},
"reboot_readiness": []string{},
"recovery": []string{},
"resolver": []string{},
"resources": []string{},
"restrictions": []string{},
"role": []string{},
"rollback": []string{},
"rttmanager": []string{},
"runtime": []string{},
"safety_center": []string{},
"samplingprofiler": []string{},
"scheduling_policy": []string{},
"search": []string{},
"search_ui": []string{},
"secure_element": []string{},
"sec_key_att_app_id_provider": []string{},
"selection_toolbar": []string{},
"sensorservice": []string{},
"sensor_privacy": []string{},
"serial": []string{},
"servicediscovery": []string{},
"manager": []string{},
"settings": []string{},
"shortcut": []string{},
"simphonebook_msim": []string{},
"simphonebook2": []string{},
"simphonebook": []string{},
"sip": []string{},
"slice": []string{},
"smartspace": []string{},
"speech_recognition": []string{},
"stats": []string{},
"statsbootstrap": []string{},
"statscompanion": []string{},
"statsmanager": []string{},
"soundtrigger": []string{},
"soundtrigger_middleware": []string{},
"statusbar": []string{},
"storaged": []string{},
"storaged_pri": []string{},
"storagestats": []string{},
"sdk_sandbox": []string{},
"SurfaceFlinger": []string{},
"SurfaceFlingerAIDL": []string{},
"suspend_control": []string{},
"suspend_control_internal": []string{},
"system_config": []string{},
"system_server_dumper": []string{},
"system_update": []string{},
"tare": []string{},
"task": []string{},
"telecom": []string{},
"telephony.registry": []string{},
"telephony_ims": []string{},
"testharness": []string{},
"tethering": []string{},
"textclassification": []string{},
"textservices": []string{},
"texttospeech": []string{},
"time_detector": []string{},
"time_zone_detector": []string{},
"thermalservice": []string{},
"tracing.proxy": []string{},
"translation": []string{},
"transparency": []string{},
"trust": []string{},
"tv_interactive_app": []string{},
"tv_input": []string{},
"tv_tuner_resource_mgr": []string{},
"uce": []string{},
"uimode": []string{},
"updatelock": []string{},
"uri_grants": []string{},
"usagestats": []string{},
"usb": []string{},
"user": []string{},
"uwb": []string{},
"vcn_management": []string{},
"vibrator": []string{},
"vibrator_manager": []string{},
"virtualdevice": []string{},
"virtual_touchpad": []string{},
"voiceinteraction": []string{},
"vold": []string{},
"vpn_management": []string{},
"vrmanager": []string{},
"wallpaper": []string{},
"wallpaper_effects_generation": []string{},
"webviewupdate": []string{},
"wifip2p": []string{},
"wifiscanner": []string{},
"wifi": []string{},
"wifinl80211": []string{},
"wifiaware": []string{},
"wifirtt": []string{},
"window": []string{},
"*": []string{},
}
)

View file

@ -0,0 +1,109 @@
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package selinux
import (
"encoding/json"
"fmt"
"android/soong/android"
)
func init() {
android.RegisterModuleType("fuzzer_bindings_test", fuzzerBindingsTestFactory)
android.PreArchMutators(registerFuzzerMutators)
}
func registerFuzzerMutators(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("addFuzzerConfigDeps", addFuzzerConfigDeps).Parallel()
}
func addFuzzerConfigDeps(ctx android.BottomUpMutatorContext) {
if _, ok := ctx.Module().(*fuzzerBindingsTestModule); ok {
for _, fuzzers := range ServiceFuzzerBindings {
for _, fuzzer := range fuzzers {
if !ctx.OtherModuleExists(fuzzer) {
panic(fmt.Errorf("Fuzzer doesn't exist : %s", fuzzer))
}
}
}
}
}
type bindingsTestProperties struct {
// Contexts files to be tested.
Srcs []string `android:"path"`
}
type fuzzerBindingsTestModule struct {
android.ModuleBase
tool string
properties bindingsTestProperties
testTimestamp android.ModuleOutPath
}
// fuzzer_bindings_test checks if a fuzzer is implemented for every service in service_contexts
func fuzzerBindingsTestFactory() android.Module {
m := &fuzzerBindingsTestModule{tool: "fuzzer_bindings_check"}
m.AddProperties(&m.properties)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
func (m *fuzzerBindingsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
tool := m.tool
if tool != "fuzzer_bindings_check" {
panic(fmt.Errorf("%q: unknown tool name: %q", ctx.ModuleName(), tool))
}
if len(m.properties.Srcs) == 0 {
ctx.PropertyErrorf("srcs", "can't be empty")
return
}
// Generate a json file which contains existing bindings
rootPath := android.PathForIntermediates(ctx, "bindings.json")
jsonString, parseError := json.Marshal(ServiceFuzzerBindings)
if parseError != nil {
panic(fmt.Errorf("Error while marshalling ServiceFuzzerBindings dict. Check Format"))
}
android.WriteFileRule(ctx, rootPath, string(jsonString))
//input module json, service context and binding files here
srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().BuiltTool(tool).Flag("-s").Inputs(srcs).Flag("-b").Input(rootPath)
// Every Soong module needs to generate an output even if it doesn't require it
m.testTimestamp = android.PathForModuleOut(ctx, "timestamp")
rule.Command().Text("touch").Output(m.testTimestamp)
rule.Build("fuzzer_bindings_test", "running service:fuzzer bindings test: "+ctx.ModuleName())
}
func (m *fuzzerBindingsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "FAKE",
// OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
// Without OutputFile this module won't be exported to Makefile.
OutputFile: android.OptionalPathForPath(m.testTimestamp),
Include: "$(BUILD_PHONY_PACKAGE)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
},
},
}}
}

View file

@ -520,3 +520,8 @@ vndservice_contexts_test {
srcs: [":vndservice_contexts"],
sepolicy: ":precompiled_sepolicy",
}
fuzzer_bindings_test {
name: "fuzzer_bindings_test",
srcs: [":plat_service_contexts"],
}

View file

@ -77,3 +77,8 @@ python_binary_host {
libs: ["mini_cil_parser", "pysepolwrap"],
data: [":libsepolwrap"],
}
python_binary_host {
name: "fuzzer_bindings_check",
srcs: ["fuzzer_bindings_check.py"],
}

View file

@ -70,3 +70,15 @@ sepolicy-check
sepolicy-analyze
A tool for performing various kinds of analysis on a sepolicy
file.
fuzzer_bindings_check
Tool to check if fuzzer is added for new services. it is used by fuzzer_bindings_test soong module internally.
Error will be generated if there is no fuzzer binding present for service added in service_contexts in
system/sepolicy/soong/build/service_fuzzer_bindings.go
Usage:
fuzzer_bindings_check.py -s [SRCs...] -b /path/to/binding.json
-s [SRCs...] list of service_contexts files. Tool will check if there is fuzzer for every service
in the context file.
-b /path/to/binding.json Path to json file containing "service":[fuzzers...] bindings.

View file

@ -0,0 +1,92 @@
#!/usr/bin/env python3
#
# Copyright 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import json
import sys
import os
import argparse
def check_file_exists(file_name):
if not os.path.exists(file_name):
sys.exit("File doesn't exist : {0}".format(file_name))
def read_bindings(binding_file):
check_file_exists(binding_file)
with open(binding_file) as jsonFile:
bindings = json.loads(jsonFile.read())
return bindings
def check_fuzzer_exists(context_file, bindings):
with open(context_file) as file:
for line in file:
# Ignore empty lines and comments
line = line.strip()
if line.startswith("#"):
logging.debug("Found a comment..skipping")
continue
tokens = line.split()
if len(tokens) == 0:
logging.debug("Skipping empty lines in service_contexts")
continue
# For a valid service_context file, there will be only two tokens
# First will be service name and second will be its label.
service_name = tokens[0]
if service_name not in bindings:
sys.exit("\nerror: Service {0} is being added, but we have no fuzzer on file for it. "
"Fuzzers are listed at $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go \n\n"
"NOTE: automatic service fuzzers are currently not supported in Java (b/232439254) "
"and Rust (b/164122727). In this case, please ignore this for now. \n\n"
"If you are writing a new service, it may be subject to attack from other "
"potentially malicious processes. A fuzzer can be written automatically "
"by adding these things: \n"
"- a cc_fuzz Android.bp entry \n"
"- a main file that constructs your service and calls 'fuzzService' \n\n"
"An example can be found here: \n "
"$ANDROID_BUILD_TOP/hardware/interfaces/vibrator/aidl/default/fuzzer.cpp \n\n"
"This is only ~30 lines of configuration. It requires dependency injection "
"for your service which is a good practice, and (in AOSP) you will get bugs "
"automatically filed on you. You will find out about issues without needing "
"to backport changes years later, and the system will automatically find ways "
"to reproduce difficult to solve issues for you. \n\n"
"- Android Fuzzing and Security teams".format(service_name))
return
def validate_bindings(args):
bindings = read_bindings(args.bindings)
for file in args.srcs:
check_file_exists(file)
check_fuzzer_exists(file, bindings)
return
def get_args():
parser = argparse.ArgumentParser(description="Tool to check if fuzzer is "
"added for new services")
parser.add_argument('-b', help='Path to json file containing '
'"service":[fuzzers...] bindings.',
required=True, dest='bindings')
parser.add_argument('-s', '--list', nargs='+',
help='list of service_contexts files. Tool will check if '
'there is fuzzer for every service in the context '
'file.', required=True, dest='srcs')
parsed_args = parser.parse_args()
return parsed_args
if __name__ == "__main__":
args = get_args()
validate_bindings(args)