Project import
diff --git a/sepolicy/Android.mk b/sepolicy/Android.mk new file mode 100644 index 0000000..5cc4a24 --- /dev/null +++ b/sepolicy/Android.mk
@@ -0,0 +1,507 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +# SELinux policy version. +# Must be <= /sys/fs/selinux/policyvers reported by the Android kernel. +# Must be within the compatibility range reported by checkpolicy -V. +POLICYVERS ?= 29 + +MLS_SENS=1 +MLS_CATS=1024 + +ifdef BOARD_SEPOLICY_REPLACE +$(error BOARD_SEPOLICY_REPLACE is no longer supported; please remove from your BoardConfig.mk or other .mk file.) +endif + +ifdef BOARD_SEPOLICY_IGNORE +$(error BOARD_SEPOLICY_IGNORE is no longer supported; please remove from your BoardConfig.mk or other .mk file.) +endif + +ifdef BOARD_SEPOLICY_UNION +$(warning BOARD_SEPOLICY_UNION is no longer required - all files found in BOARD_SEPOLICY_DIRS are implicitly unioned; please remove from your BoardConfig.mk or other .mk file.) +endif + +ifdef BOARD_SEPOLICY_M4DEFS +LOCAL_ADDITIONAL_M4DEFS := $(addprefix -D, $(BOARD_SEPOLICY_M4DEFS)) +endif + +# Builds paths for all policy files found in BOARD_SEPOLICY_DIRS and the LOCAL_PATH. +# $(1): the set of policy name paths to build +build_policy = $(foreach type, $(1), $(foreach file, $(addsuffix /$(type), $(LOCAL_PATH) $(BOARD_SEPOLICY_DIRS)), $(sort $(wildcard $(file))))) + +# Builds paths for all policy files found in BOARD_SEPOLICY_DIRS. +# $(1): the set of policy name paths to build +build_device_policy = $(foreach type, $(1), $(foreach file, $(addsuffix /$(type), $(BOARD_SEPOLICY_DIRS)), $(sort $(wildcard $(file))))) + +# Add a file containing only a newline in-between each policy configuration +# 'contexts' file. This will allow OEM policy configuration files without a +# final newline (0x0A) to be built correctly by the m4(1) macro processor. +# $(1): the set of contexts file names. +# $(2): the file containing only 0x0A. +add_nl = $(foreach entry, $(1), $(subst $(entry), $(entry) $(2), $(entry))) + +sepolicy_build_files := security_classes \ + initial_sids \ + access_vectors \ + global_macros \ + neverallow_macros \ + mls_macros \ + mls \ + policy_capabilities \ + te_macros \ + attributes \ + ioctl_macros \ + *.te \ + roles \ + users \ + initial_sid_contexts \ + fs_use \ + genfs_contexts \ + port_contexts + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := sectxfile_nl +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional + +# Create a file containing newline only to add between context config files +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): + @mkdir -p $(dir $@) + $(hide) echo > $@ + +built_nl := $(LOCAL_BUILT_MODULE) + +################################# +include $(CLEAR_VARS) + +LOCAL_MODULE := sepolicy +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk + +sepolicy_policy.conf := $(intermediates)/policy.conf +$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS) +$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS) +$(sepolicy_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(sepolicy_policy.conf): $(call build_policy, $(sepolicy_build_files)) + @mkdir -p $(dir $@) + $(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \ + -D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \ + -D target_build_variant=$(TARGET_BUILD_VARIANT) \ + -s $^ > $@ + $(hide) sed '/dontaudit/d' $@ > $@.dontaudit + +$(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy $(HOST_OUT_EXECUTABLES)/sepolicy-analyze + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@.tmp $< > /dev/null + $(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $(dir $<)/$(notdir $@).dontaudit $<.dontaudit > /dev/null + $(hide) $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $@.tmp permissive > $@.permissivedomains + $(hide) if [ "$(TARGET_BUILD_VARIANT)" = "user" -a -s $@.permissivedomains ]; then \ + echo "==========" 1>&2; \ + echo "ERROR: permissive domains not allowed in user builds" 1>&2; \ + echo "List of invalid domains:" 1>&2; \ + cat $@.permissivedomains 1>&2; \ + exit 1; \ + fi + $(hide) mv $@.tmp $@ + +built_sepolicy := $(LOCAL_BUILT_MODULE) +sepolicy_policy.conf := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := sepolicy.recovery +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := eng + +include $(BUILD_SYSTEM)/base_rules.mk + +sepolicy_policy_recovery.conf := $(intermediates)/policy_recovery.conf +$(sepolicy_policy_recovery.conf): PRIVATE_MLS_SENS := $(MLS_SENS) +$(sepolicy_policy_recovery.conf): PRIVATE_MLS_CATS := $(MLS_CATS) +$(sepolicy_policy_recovery.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(sepolicy_policy_recovery.conf): $(call build_policy, $(sepolicy_build_files)) + @mkdir -p $(dir $@) + $(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \ + -D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \ + -D target_build_variant=$(TARGET_BUILD_VARIANT) \ + -D target_recovery=true \ + -s $^ > $@ + +$(LOCAL_BUILT_MODULE): $(sepolicy_policy_recovery.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy $(HOST_OUT_EXECUTABLES)/sepolicy-analyze + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@.tmp $< > /dev/null + $(hide) $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $@.tmp permissive > $@.permissivedomains + $(hide) if [ "$(TARGET_BUILD_VARIANT)" = "user" -a -s $@.permissivedomains ]; then \ + echo "==========" 1>&2; \ + echo "ERROR: permissive domains not allowed in user builds" 1>&2; \ + echo "List of invalid domains:" 1>&2; \ + cat $@.permissivedomains 1>&2; \ + exit 1; \ + fi + $(hide) mv $@.tmp $@ + +built_sepolicy_recovery := $(LOCAL_BUILT_MODULE) +sepolicy_policy_recovery.conf := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := general_sepolicy.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +exp_sepolicy_build_files :=\ + $(foreach file, $(addprefix $(LOCAL_PATH)/, $(sepolicy_build_files)), $(sort $(wildcard $(file)))) + +$(LOCAL_BUILT_MODULE): PRIVATE_MLS_SENS := $(MLS_SENS) +$(LOCAL_BUILT_MODULE): PRIVATE_MLS_CATS := $(MLS_CATS) +$(LOCAL_BUILT_MODULE): $(exp_sepolicy_build_files) + mkdir -p $(dir $@) + $(hide) m4 -D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \ + -D target_build_variant=user \ + -s $^ > $@ + $(hide) sed '/dontaudit/d' $@ > $@.dontaudit + +built_general_sepolicy.conf := $(LOCAL_BUILT_MODULE) +exp_sepolicy_build_files := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := sepolicy.general +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): PRIVATE_BUILT_SEPOLICY.CONF := $(built_general_sepolicy.conf) +$(LOCAL_BUILT_MODULE): $(built_general_sepolicy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@ $(PRIVATE_BUILT_SEPOLICY.CONF) > /dev/null + +built_general_sepolicy := $(LOCAL_BUILT_MODULE) +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := file_contexts.bin +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk + +# The file_contexts.bin is built in the following way: +# 1. Collect all file_contexts files in THIS repository and process them with +# m4 into a tmp file called file_contexts.local.tmp. +# 2. Collect all device specific file_contexts files and process them with m4 +# into a tmp file called file_contexts.device.tmp. +# 3. Run checkfc -e (allow no device fc entries ie empty) and fc_sort on +# file_contexts.device.tmp and output to file_contexts.device.sorted.tmp. +# 4. Concatenate file_contexts.local.tmp and file_contexts.device.tmp into +# file_contexts.concat.tmp. +# 5. Run checkfc and sefcontext_compile on file_contexts.concat.tmp to produce +# file_contexts.bin. +# +# Note: That a newline file is placed between each file_context file found to +# ensure a proper build when an fc file is missing an ending newline. + +local_fc_files := $(LOCAL_PATH)/file_contexts +ifneq ($(filter address,$(SANITIZE_TARGET)),) + local_fc_files := $(local_fc_files) $(LOCAL_PATH)/file_contexts_asan +endif +local_fcfiles_with_nl := $(call add_nl, $(local_fc_files), $(built_nl)) + +file_contexts.local.tmp := $(intermediates)/file_contexts.local.tmp +$(file_contexts.local.tmp): $(local_fcfiles_with_nl) + @mkdir -p $(dir $@) + $(hide) m4 -s $^ > $@ + +device_fc_files := $(call build_device_policy, file_contexts) +device_fcfiles_with_nl := $(call add_nl, $(device_fc_files), $(built_nl)) + +file_contexts.device.tmp := $(intermediates)/file_contexts.device.tmp +$(file_contexts.device.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(file_contexts.device.tmp): $(device_fcfiles_with_nl) + @mkdir -p $(dir $@) + $(hide) m4 -s $(PRIVATE_ADDITIONAL_M4DEFS) $^ > $@ + +file_contexts.device.sorted.tmp := $(intermediates)/file_contexts.device.sorted.tmp +$(file_contexts.device.sorted.tmp): PRIVATE_SEPOLICY := $(built_sepolicy) +$(file_contexts.device.sorted.tmp): $(file_contexts.device.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/fc_sort $(HOST_OUT_EXECUTABLES)/checkfc + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -e $(PRIVATE_SEPOLICY) $< + $(hide) $(HOST_OUT_EXECUTABLES)/fc_sort $< $@ + +file_contexts.concat.tmp := $(intermediates)/file_contexts.concat.tmp +$(file_contexts.concat.tmp): $(file_contexts.local.tmp) $(file_contexts.device.sorted.tmp) + @mkdir -p $(dir $@) + $(hide) m4 -s $^ > $@ + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy) +$(LOCAL_BUILT_MODULE): $(file_contexts.concat.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $< + $(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $< + +built_fc := $(LOCAL_BUILT_MODULE) +local_fc_files := +local_fcfiles_with_nl := +device_fc_files := +device_fcfiles_with_nl := +file_contexts.concat.tmp := +file_contexts.device.sorted.tmp := +file_contexts.device.tmp := +file_contexts.local.tmp := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := general_file_contexts.bin +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +general_file_contexts.tmp := $(intermediates)/general_file_contexts.tmp +$(general_file_contexts.tmp): $(addprefix $(LOCAL_PATH)/, file_contexts) + @mkdir -p $(dir $@) + $(hide) m4 -s $< > $@ + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy) +$(LOCAL_BUILT_MODULE): $(general_file_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $< + $(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $< + +general_file_contexts.tmp := + +################################## +include $(CLEAR_VARS) +LOCAL_MODULE := seapp_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk + +all_sc_files := $(call build_policy, seapp_contexts) + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy) +$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(all_sc_files) +$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(all_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILES) + +built_sc := $(LOCAL_BUILT_MODULE) +all_sc_files := + +################################## +include $(CLEAR_VARS) +LOCAL_MODULE := general_seapp_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +all_sc_files := $(addprefix $(LOCAL_PATH)/, seapp_contexts) + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy) +$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILE := $(all_sc_files) +$(LOCAL_BUILT_MODULE): $(built_general_sepolicy) $(all_sc_files) $(HOST_OUT_EXECUTABLES)/checkseapp + @mkdir -p $(dir $@) + $(hide) $(HOST_OUT_EXECUTABLES)/checkseapp -p $(PRIVATE_SEPOLICY) -o $@ $(PRIVATE_SC_FILE) + +all_sc_files := + +################################## +include $(CLEAR_VARS) +LOCAL_MODULE := general_seapp_neverallows +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): $(addprefix $(LOCAL_PATH)/, seapp_contexts) + @mkdir -p $(dir $@) + - $(hide) grep -ie '^neverallow' $< > $@ + + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := property_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk + +all_pc_files := $(call build_policy, property_contexts) +all_pcfiles_with_nl := $(call add_nl, $(all_pc_files), $(built_nl)) + +property_contexts.tmp := $(intermediates)/property_contexts.tmp +$(property_contexts.tmp): PRIVATE_PC_FILES := $(all_pcfiles_with_nl) +$(property_contexts.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(property_contexts.tmp): $(all_pcfiles_with_nl) + @mkdir -p $(dir $@) + $(hide) m4 -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_PC_FILES) > $@ + + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy) +$(LOCAL_BUILT_MODULE): $(property_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc + @mkdir -p $(dir $@) + $(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@ + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@ + +built_pc := $(LOCAL_BUILT_MODULE) +all_pc_files := +all_pcfiles_with_nl := +property_contexts.tmp := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := general_property_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +general_property_contexts.tmp := $(intermediates)/general_property_contexts.tmp +$(general_property_contexts.tmp): $(addprefix $(LOCAL_PATH)/, property_contexts) + @mkdir -p $(dir $@) + $(hide) m4 -s $< > $@ + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy) +$(LOCAL_BUILT_MODULE): $(general_property_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP) + @mkdir -p $(dir $@) + $(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@ + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@ + +general_property_contexts.tmp := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := service_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk + +all_svc_files := $(call build_policy, service_contexts) +all_svcfiles_with_nl := $(call add_nl, $(all_svc_files), $(built_nl)) + +service_contexts.tmp := $(intermediates)/service_contexts.tmp +$(service_contexts.tmp): PRIVATE_SVC_FILES := $(all_svcfiles_with_nl) +$(service_contexts.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(service_contexts.tmp): $(all_svcfiles_with_nl) + @mkdir -p $(dir $@) + $(hide) m4 -s $(PRIVATE_ADDITIONAL_M4DEFS) $(PRIVATE_SVC_FILES) > $@ + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy) +$(LOCAL_BUILT_MODULE): $(service_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP) + @mkdir -p $(dir $@) + sed -e 's/#.*$$//' -e '/^$$/d' $< > $@ + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@ + +built_svc := $(LOCAL_BUILT_MODULE) +all_svc_files := +all_svcfiles_with_nl := +service_contexts.tmp := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := general_service_contexts +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := tests + +include $(BUILD_SYSTEM)/base_rules.mk + +general_service_contexts.tmp := $(intermediates)/general_service_contexts.tmp +$(general_service_contexts.tmp): $(addprefix $(LOCAL_PATH)/, service_contexts) + @mkdir -p $(dir $@) + $(hide) m4 -s $< > $@ + +$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy) +$(LOCAL_BUILT_MODULE): $(general_service_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP) + @mkdir -p $(dir $@) + sed -e 's/#.*$$//' -e '/^$$/d' $< > $@ + $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@ + +general_service_contexts.tmp := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := mac_permissions.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/security + +include $(BUILD_SYSTEM)/base_rules.mk + +# Build keys.conf +mac_perms_keys.tmp := $(intermediates)/keys.tmp +$(mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS) +$(mac_perms_keys.tmp): $(call build_policy, keys.conf) + @mkdir -p $(dir $@) + $(hide) m4 -s $(PRIVATE_ADDITIONAL_M4DEFS) $^ > $@ + +all_mac_perms_files := $(call build_policy, $(LOCAL_MODULE)) + +# Should be synced with keys.conf. +all_keys := platform media shared testkey +all_keys := $(all_keys:%=$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))/%.x509.pem) + +$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_mac_perms_files) +$(LOCAL_BUILT_MODULE): $(mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys.py $(all_mac_perms_files) $(all_keys) + @mkdir -p $(dir $@) + $(hide) DEFAULT_SYSTEM_DEV_CERTIFICATE="$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))" \ + $(HOST_OUT_EXECUTABLES)/insertkeys.py -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES) + +mac_perms_keys.tmp := +all_mac_perms_files := + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := selinux_version +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): $(built_sepolicy) $(built_pc) $(built_fc) $(built_sc) $(built_svc) + @mkdir -p $(dir $@) + $(hide) echo -n $(BUILD_FINGERPRINT_FROM_FILE) > $@ + +################################## + +build_policy := +build_device_policy := +sepolicy_build_files := +built_sepolicy := +built_sepolicy_recovery := +built_sc := +built_fc := +built_pc := +built_svc := +built_general_sepolicy := +built_general_sepolicy.conf := +built_nl := +add_nl := + +include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/sepolicy/CleanSpec.mk b/sepolicy/CleanSpec.mk new file mode 100644 index 0000000..f141e34 --- /dev/null +++ b/sepolicy/CleanSpec.mk
@@ -0,0 +1,52 @@ +# Copyright (C) 2015 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/file_contexts) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/file_contexts)
diff --git a/sepolicy/MODULE_LICENSE_PUBLIC_DOMAIN b/sepolicy/MODULE_LICENSE_PUBLIC_DOMAIN new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sepolicy/MODULE_LICENSE_PUBLIC_DOMAIN
diff --git a/sepolicy/NOTICE b/sepolicy/NOTICE new file mode 100644 index 0000000..e4ebf52 --- /dev/null +++ b/sepolicy/NOTICE
@@ -0,0 +1,21 @@ +This configuration (sepolicy) is public domain, i.e. not copyrighted. + +Warranty Exclusion +------------------ +You agree that this software is a +non-commercially developed program that may contain "bugs" (as that +term is used in the industry) and that it may not function as intended. +The software is licensed "as is". NSA makes no, and hereby expressly +disclaims all, warranties, express, implied, statutory, or otherwise +with respect to the software, including noninfringement and the implied +warranties of merchantability and fitness for a particular purpose. + +Limitation of Liability +----------------------- +In no event will NSA be liable for any damages, including loss of data, +lost profits, cost of cover, or other special, incidental, +consequential, direct or indirect damages arising from the software or +the use thereof, however caused and on any theory of liability. This +limitation will apply even if NSA has been advised of the possibility +of such damage. You acknowledge that this is a reasonable allocation of +risk.
diff --git a/sepolicy/README b/sepolicy/README new file mode 100644 index 0000000..a3c75b8 --- /dev/null +++ b/sepolicy/README
@@ -0,0 +1,103 @@ +This directory contains the core Android SELinux policy configuration. +It defines the domains and types for the AOSP services and apps common to +all devices. Device-specific policy should be placed under a +separate device/<vendor>/<board>/sepolicy subdirectory and linked +into the policy build as described below. + +Policy Generation: + +Additional, per device, policy files can be added into the +policy build. These files should have each line including the +final line terminated by a newline character (0x0A). This +will allow files to be concatenated and processed whenever +the m4(1) macro processor is called by the build process. +Adding the newline will also make the intermediate text files +easier to read when debugging build failures. The sets of file, +service and property contexts files will automatically have a +newline inserted between each file as these are common failure +points. + +These device policy files can be configured through the use of +the BOARD_SEPOLICY_DIRS variable. This variable should be set +in the BoardConfig.mk file in the device or vendor directories. + +BOARD_SEPOLICY_DIRS contains a list of directories to search +for additional policy files. Order matters in this list. +For example, if you have 2 instances of widget.te files in the +BOARD_SEPOLICY_DIRS search path, then the first one found (at the +first search dir containing the file) will be concatenated first. +Reviewing out/target/product/<device>/etc/sepolicy_intermediates/policy.conf +will help sort out ordering issues. + +Example BoardConfig.mk Usage: +From the Tuna device BoardConfig.mk, device/samsung/tuna/BoardConfig.mk + +BOARD_SEPOLICY_DIRS += device/samsung/tuna/sepolicy + +Additionally, OEMs can specify BOARD_SEPOLICY_M4DEFS to pass arbitrary m4 +definitions during the build. A definition consists of a string in the form +of macro-name=value. Spaces must NOT be present. This is useful for building modular +policies, policy generation, conditional file paths, etc. It is supported in +the following file types: + * All *.te and SE Linux policy files as passed to checkpolicy + * file_contexts + * service_contexts + * property_contexts + * keys.conf + +Example BoardConfig.mk Usage: +BOARD_SEPOLICY_M4DEFS += btmodule=foomatic \ + btdevice=/dev/gps + +SPECIFIC POLICY FILE INFORMATION + +mac_permissions.xml: + ABOUT: + The mac_permissions.xml file is used for controlling the mmac solutions + as well as mapping a public base16 signing key with an arbitrary seinfo + string. Details of the files contents can be found in a comment at the + top of that file. The seinfo string, previously mentioned, is the same string + that is referenced in seapp_contexts. + + It is important to note the final processed version of this file + is stripped of comments and whitespace. This is to preserve space on the + system.img. If one wishes to view it in a more human friendly format, + the "tidy" or "xmllint" command will assist you. + + TOOLING: + insertkeys.py + Is a helper script for mapping arbitrary tags in the signature stanzas of + mac_permissions.xml to public keys found in pem files. This script takes + a mac_permissions.xml file(s) and configuration file in order to operate. + Details of the configuration file (keys.conf) can be found in the subsection + keys.conf. This tool is also responsible for stripping the comments and + whitespace during processing. + + keys.conf + The keys.conf file is used for controlling the mapping of "tags" found in + the mac_permissions.xml signature stanzas with actual public keys found in + pem files. The configuration file is processed via m4. + + The script allows for mapping any string contained in TARGET_BUILD_VARIANT + with specific path to a pem file. Typically TARGET_BUILD_VARIANT is either + user, eng or userdebug. Additionally, one can specify "ALL" to map a path to + any string specified in TARGET_BUILD_VARIANT. All tags are matched verbatim + and all options are matched lowercase. The options are "tolowered" automatically + for the user, it is convention to specify tags and options in all uppercase + and tags start with @. The option arguments can also use environment variables + via the familiar $VARIABLE syntax. This is often useful for setting a location + to ones release keys. + + Often times, one will need to integrate an application that was signed by a separate + organization and may need to extract the pem file for the insertkeys/keys.conf tools. + Extraction of the public key in the pem format is possible via openssl. First you need + to unzip the apk, once it is unzipped, cd into the META_INF directory and then execute + openssl pkcs7 -inform DER -in CERT.RSA -out CERT.pem -outform PEM -print_certs + On some occasions CERT.RSA has a different name, and you will need to adjust for that. + After extracting the pem, you can rename it, and configure keys.conf and + mac_permissions.xml to pick up the change. You MUST open the generated pem file in a text + editor and strip out anything outside the opening and closing scissor lines. Failure to do + so WILL cause a compile time issue thrown by insertkeys.py + + NOTE: The pem files are base64 encoded and PackageManagerService, mac_permissions.xml + and setool all use base16 encodings.
diff --git a/sepolicy/access_vectors b/sepolicy/access_vectors new file mode 100644 index 0000000..26286b2 --- /dev/null +++ b/sepolicy/access_vectors
@@ -0,0 +1,621 @@ +# +# Define common prefixes for access vectors +# +# common common_name { permission_name ... } + + +# +# Define a common prefix for file access vectors. +# + +common file +{ + ioctl + read + write + create + getattr + setattr + lock + relabelfrom + relabelto + append + unlink + link + rename + execute + swapon + quotaon + mounton +} + + +# +# Define a common prefix for socket access vectors. +# + +common socket +{ +# inherited from file + ioctl + read + write + create + getattr + setattr + lock + relabelfrom + relabelto + append +# socket-specific + bind + connect + listen + accept + getopt + setopt + shutdown + recvfrom + sendto + recv_msg + send_msg + name_bind +} + +# +# Define a common prefix for ipc access vectors. +# + +common ipc +{ + create + destroy + getattr + setattr + read + write + associate + unix_read + unix_write +} + +# +# Define the access vectors. +# +# class class_name [ inherits common_name ] { permission_name ... } + + +# +# Define the access vector interpretation for file-related objects. +# + +class filesystem +{ + mount + remount + unmount + getattr + relabelfrom + relabelto + transition + associate + quotamod + quotaget +} + +class dir +inherits file +{ + add_name + remove_name + reparent + search + rmdir + open + audit_access + execmod +} + +class file +inherits file +{ + execute_no_trans + entrypoint + execmod + open + audit_access +} + +class lnk_file +inherits file +{ + open + audit_access + execmod +} + +class chr_file +inherits file +{ + execute_no_trans + entrypoint + execmod + open + audit_access +} + +class blk_file +inherits file +{ + open + audit_access + execmod +} + +class sock_file +inherits file +{ + open + audit_access + execmod +} + +class fifo_file +inherits file +{ + open + audit_access + execmod +} + +class fd +{ + use +} + + +# +# Define the access vector interpretation for network-related objects. +# + +class socket +inherits socket + +class tcp_socket +inherits socket +{ + connectto + newconn + acceptfrom + node_bind + name_connect +} + +class udp_socket +inherits socket +{ + node_bind +} + +class rawip_socket +inherits socket +{ + node_bind +} + +class node +{ + tcp_recv + tcp_send + udp_recv + udp_send + rawip_recv + rawip_send + enforce_dest + dccp_recv + dccp_send + recvfrom + sendto +} + +class netif +{ + tcp_recv + tcp_send + udp_recv + udp_send + rawip_recv + rawip_send + dccp_recv + dccp_send + ingress + egress +} + +class netlink_socket +inherits socket + +class packet_socket +inherits socket + +class key_socket +inherits socket + +class unix_stream_socket +inherits socket +{ + connectto + newconn + acceptfrom +} + +class unix_dgram_socket +inherits socket + +# +# Define the access vector interpretation for process-related objects +# + +class process +{ + fork + transition + sigchld # commonly granted from child to parent + sigkill # cannot be caught or ignored + sigstop # cannot be caught or ignored + signull # for kill(pid, 0) + signal # all other signals + ptrace + getsched + setsched + getsession + getpgid + setpgid + getcap + setcap + share + getattr + setexec + setfscreate + noatsecure + siginh + setrlimit + rlimitinh + dyntransition + setcurrent + execmem + execstack + execheap + setkeycreate + setsockcreate +} + + +# +# Define the access vector interpretation for ipc-related objects +# + +class ipc +inherits ipc + +class sem +inherits ipc + +class msgq +inherits ipc +{ + enqueue +} + +class msg +{ + send + receive +} + +class shm +inherits ipc +{ + lock +} + + +# +# Define the access vector interpretation for the security server. +# + +class security +{ + compute_av + compute_create + compute_member + check_context + load_policy + compute_relabel + compute_user + setenforce # was avc_toggle in system class + setbool + setsecparam + setcheckreqprot + read_policy +} + + +# +# Define the access vector interpretation for system operations. +# + +class system +{ + ipc_info + syslog_read + syslog_mod + syslog_console + module_request + module_load +} + +# +# Define the access vector interpretation for controling capabilies +# + +class capability +{ + # The capabilities are defined in include/linux/capability.h + # Capabilities >= 32 are defined in the capability2 class. + # Care should be taken to ensure that these are consistent with + # those definitions. (Order matters) + + chown + dac_override + dac_read_search + fowner + fsetid + kill + setgid + setuid + setpcap + linux_immutable + net_bind_service + net_broadcast + net_admin + net_raw + ipc_lock + ipc_owner + sys_module + sys_rawio + sys_chroot + sys_ptrace + sys_pacct + sys_admin + sys_boot + sys_nice + sys_resource + sys_time + sys_tty_config + mknod + lease + audit_write + audit_control + setfcap +} + +class capability2 +{ + mac_override # unused by SELinux + mac_admin # unused by SELinux + syslog + wake_alarm + block_suspend + audit_read +} + +# +# Extended Netlink classes +# +class netlink_route_socket +inherits socket +{ + nlmsg_read + nlmsg_write +} + +class netlink_firewall_socket +inherits socket +{ + nlmsg_read + nlmsg_write +} + +class netlink_tcpdiag_socket +inherits socket +{ + nlmsg_read + nlmsg_write +} + +class netlink_nflog_socket +inherits socket + +class netlink_xfrm_socket +inherits socket +{ + nlmsg_read + nlmsg_write +} + +class netlink_selinux_socket +inherits socket + +class netlink_audit_socket +inherits socket +{ + nlmsg_read + nlmsg_write + nlmsg_relay + nlmsg_readpriv + nlmsg_tty_audit +} + +class netlink_ip6fw_socket +inherits socket +{ + nlmsg_read + nlmsg_write +} + +class netlink_dnrt_socket +inherits socket + +# Define the access vector interpretation for controlling +# access to IPSec network data by association +# +class association +{ + sendto + recvfrom + setcontext + polmatch +} + +# Updated Netlink class for KOBJECT_UEVENT family. +class netlink_kobject_uevent_socket +inherits socket + +class appletalk_socket +inherits socket + +class packet +{ + send + recv + relabelto + flow_in # deprecated + flow_out # deprecated + forward_in + forward_out +} + +class key +{ + view + read + write + search + link + setattr + create +} + +class dccp_socket +inherits socket +{ + node_bind + name_connect +} + +class memprotect +{ + mmap_zero +} + +# network peer labels +class peer +{ + recv +} + +class kernel_service +{ + use_as_override + create_files_as +} + +class tun_socket +inherits socket +{ + attach_queue +} + +class binder +{ + impersonate + call + set_context_mgr + transfer +} + +class netlink_iscsi_socket +inherits socket + +class netlink_fib_lookup_socket +inherits socket + +class netlink_connector_socket +inherits socket + +class netlink_netfilter_socket +inherits socket + +class netlink_generic_socket +inherits socket + +class netlink_scsitransport_socket +inherits socket + +class netlink_rdma_socket +inherits socket + +class netlink_crypto_socket +inherits socket + +class property_service +{ + set +} + +class service_manager +{ + add + find + list +} + +class keystore_key +{ + get_state + get + insert + delete + exist + list + reset + password + lock + unlock + is_empty + sign + verify + grant + duplicate + clear_uid + add_auth + user_changed +} + +class debuggerd +{ + dump_tombstone + dump_backtrace +} + +class drmservice { + consumeRights + setPlaybackStatus + openDecryptSession + closeDecryptSession + initializeDecryptUnit + decrypt + finalizeDecryptUnit + pread +}
diff --git a/sepolicy/adbd.te b/sepolicy/adbd.te new file mode 100644 index 0000000..217a284 --- /dev/null +++ b/sepolicy/adbd.te
@@ -0,0 +1,116 @@ +# adbd seclabel is specified in init.rc since +# it lives in the rootfs and has no unique file type. +type adbd, domain, mlstrustedsubject; + +userdebug_or_eng(` + allow adbd self:process setcurrent; + allow adbd su:process dyntransition; +') + +domain_auto_trans(adbd, shell_exec, shell) + +# Do not sanitize the environment or open fds of the shell. Allow signaling +# created processes. +allow adbd shell:process { noatsecure signal }; + +# Set UID and GID to shell. Set supplementary groups. +allow adbd self:capability { setuid setgid }; + +# Drop capabilities from bounding set on user builds. +allow adbd self:capability setpcap; + +# Create and use network sockets. +net_domain(adbd) + +# Access /dev/android_adb or /dev/usb-ffs/adb/ep0 +allow adbd adb_device:chr_file rw_file_perms; +allow adbd functionfs:dir search; +allow adbd functionfs:file rw_file_perms; + +# Use a pseudo tty. +allow adbd devpts:chr_file rw_file_perms; + +# adb push/pull /data/local/tmp. +allow adbd shell_data_file:dir create_dir_perms; +allow adbd shell_data_file:file create_file_perms; + +# adb push/pull sdcard. +allow adbd tmpfs:dir search; +allow adbd rootfs:lnk_file r_file_perms; +allow adbd sdcard_type:dir create_dir_perms; +allow adbd sdcard_type:file create_file_perms; + +# adb pull /data/anr/traces.txt +allow adbd anr_data_file:dir r_dir_perms; +allow adbd anr_data_file:file r_file_perms; + +# Set service.adb.*, sys.powerctl, and sys.usb.ffs.ready properties. +set_prop(adbd, shell_prop) +set_prop(adbd, powerctl_prop) +set_prop(adbd, ffs_prop) + +# Access device logging gating property +get_prop(adbd, device_logging_prop) + +# Run /system/bin/bu +allow adbd system_file:file rx_file_perms; + +# Perform binder IPC to surfaceflinger (screencap) +# XXX Run screencap in a separate domain? +binder_use(adbd) +binder_call(adbd, surfaceflinger) +# b/13188914 +allow adbd gpu_device:chr_file rw_file_perms; +allow adbd ion_device:chr_file rw_file_perms; +r_dir_file(adbd, system_file) + +# Read /data/misc/adb/adb_keys. +allow adbd adb_keys_file:dir search; +allow adbd adb_keys_file:file r_file_perms; + +userdebug_or_eng(` + # Write debugging information to /data/adb + # when persist.adb.trace_mask is set + # https://code.google.com/p/android/issues/detail?id=72895 + allow adbd adb_data_file:dir rw_dir_perms; + allow adbd adb_data_file:file create_file_perms; +') + +# ndk-gdb invokes adb forward to forward the gdbserver socket. +allow adbd app_data_file:dir search; +allow adbd app_data_file:sock_file write; +allow adbd appdomain:unix_stream_socket connectto; + +# ndk-gdb invokes adb pull of app_process, linker, and libc.so. +allow adbd zygote_exec:file r_file_perms; +allow adbd system_file:file r_file_perms; + +# Allow pulling the SELinux policy for CTS purposes +allow adbd selinuxfs:dir r_dir_perms; +allow adbd selinuxfs:file r_file_perms; +allow adbd kernel:security read_policy; + +allow adbd surfaceflinger_service:service_manager find; +allow adbd bootchart_data_file:dir search; +allow adbd bootchart_data_file:file r_file_perms; + +# Allow access to external storage; we have several visible mount points under /storage +# and symlinks to primary storage at places like /storage/sdcard0 and /mnt/user/0/primary +allow adbd storage_file:dir r_dir_perms; +allow adbd storage_file:lnk_file r_file_perms; +allow adbd mnt_user_file:dir r_dir_perms; +allow adbd mnt_user_file:lnk_file r_file_perms; + +r_dir_file(adbd, apk_data_file) + +allow adbd rootfs:dir r_dir_perms; + +### +### Neverallow rules +### + +# No transitions from adbd to non-shell domains. adbd only ever +# transitions to the shell domain. In particular, we never want +# to see a transition from adbd to su (aka "adb root") +neverallow adbd { domain -shell }:process transition; +neverallow adbd { domain -su }:process dyntransition;
diff --git a/sepolicy/app.te b/sepolicy/app.te new file mode 100644 index 0000000..34c4bdb --- /dev/null +++ b/sepolicy/app.te
@@ -0,0 +1,413 @@ +### +### Domain for all zygote spawned apps +### +### This file is the base policy for all zygote spawned apps. +### Other policy files, such as isolated_app.te, untrusted_app.te, etc +### extend from this policy. Only policies which should apply to ALL +### zygote spawned apps should be added here. +### + +# WebView and other application-specific JIT compilers +allow appdomain self:process execmem; + +allow appdomain ashmem_device:chr_file execute; + +# Receive and use open file descriptors inherited from zygote. +allow appdomain zygote:fd use; + +# gdbserver for ndk-gdb reads the zygote. +# valgrind needs mmap exec for zygote +allow appdomain zygote_exec:file rx_file_perms; + +# Read system properties managed by zygote. +allow appdomain zygote_tmpfs:file read; + +# Notify zygote of death; +allow appdomain zygote:process sigchld; + +# Place process into foreground / background +allow appdomain cgroup:dir { search write }; +allow appdomain cgroup:file w_file_perms; + +# Read /data/dalvik-cache. +allow appdomain dalvikcache_data_file:dir { search getattr }; +allow appdomain dalvikcache_data_file:file r_file_perms; + +# Read the /sdcard symlink +allow appdomain rootfs:lnk_file r_file_perms; + +# Search /storage/emulated tmpfs mount. +allow appdomain tmpfs:dir r_dir_perms; + +userdebug_or_eng(` + # Notify zygote of the wrapped process PID when using --invoke-with. + allow appdomain zygote:fifo_file write; + + # Allow apps to create and write method traces in /data/misc/trace. + allow appdomain method_trace_data_file:dir w_dir_perms; + allow appdomain method_trace_data_file:file { create w_file_perms }; +') + +# Notify shell and adbd of death when spawned via runas for ndk-gdb. +allow appdomain shell:process sigchld; +allow appdomain adbd:process sigchld; + +# child shell or gdbserver pty access for runas. +allow appdomain devpts:chr_file { getattr read write ioctl }; + +# Use pipes and sockets provided by system_server via binder or local socket. +allow appdomain system_server:fifo_file rw_file_perms; +allow appdomain system_server:unix_stream_socket { read write setopt getattr getopt shutdown }; +allow appdomain system_server:tcp_socket { read write getattr getopt shutdown }; + +# Communication with other apps via fifos +allow appdomain appdomain:fifo_file rw_file_perms; + +# Communicate with surfaceflinger. +allow appdomain surfaceflinger:unix_stream_socket { read write setopt getattr getopt shutdown }; + +# App sandbox file accesses. +allow { appdomain -isolated_app } app_data_file:dir create_dir_perms; +allow { appdomain -isolated_app } app_data_file:notdevfile_class_set create_file_perms; + +# Traverse into expanded storage +allow appdomain mnt_expand_file:dir r_dir_perms; + +# Keychain and user-trusted credentials +allow appdomain keychain_data_file:dir r_dir_perms; +allow appdomain keychain_data_file:file r_file_perms; +allow appdomain misc_user_data_file:dir r_dir_perms; +allow appdomain misc_user_data_file:file r_file_perms; + +# Access to OEM provided data and apps +allow appdomain oemfs:dir r_dir_perms; +allow appdomain oemfs:file rx_file_perms; + +# Execute the shell or other system executables. +allow appdomain shell_exec:file rx_file_perms; +allow appdomain system_file:file rx_file_perms; +allow appdomain toolbox_exec:file rx_file_perms; + +# Renderscript needs the ability to read directories on /system +r_dir_file(appdomain, system_file) + +# Execute dex2oat when apps call dexclassloader +allow appdomain dex2oat_exec:file rx_file_perms; + +# Read/write wallpaper file (opened by system). +allow appdomain wallpaper_file:file { getattr read write }; + +# Write to /data/anr/traces.txt. +allow appdomain anr_data_file:dir search; +allow appdomain anr_data_file:file { open append }; + +# Allow apps to send dump information to dumpstate +allow appdomain dumpstate:fd use; +allow appdomain dumpstate:unix_stream_socket { read write getopt getattr shutdown }; +allow appdomain shell_data_file:file { write getattr }; + +# Send heap dumps to system_server via an already open file descriptor +# % adb shell am set-watch-heap com.android.systemui 1048576 +# % adb shell dumpsys procstats --start-testing +# debuggable builds only. +userdebug_or_eng(` + allow appdomain heapdump_data_file:file append; +') + +# Write to /proc/net/xt_qtaguid/ctrl file. +allow appdomain qtaguid_proc:file rw_file_perms; +# Everybody can read the xt_qtaguid resource tracking misc dev. +# So allow all apps to read from /dev/xt_qtaguid. +allow appdomain qtaguid_device:chr_file r_file_perms; + +# Grant GPU access to all processes started by Zygote. +# They need that to render the standard UI. +allow { appdomain -isolated_app } gpu_device:chr_file rw_file_perms; + +# Use the Binder. +binder_use(appdomain) +# Perform binder IPC to binder services. +binder_call(appdomain, binderservicedomain) +# Perform binder IPC to other apps. +binder_call(appdomain, appdomain) + +# Already connected, unnamed sockets being passed over some other IPC +# hence no sock_file or connectto permission. This appears to be how +# Chrome works, may need to be updated as more apps using isolated services +# are examined. +allow appdomain appdomain:unix_stream_socket { getopt getattr read write shutdown }; + +# Backup ability for every app. BMS opens and passes the fd +# to any app that has backup ability. Hence, no open permissions here. +allow appdomain backup_data_file:file { read write getattr }; +allow appdomain cache_backup_file:file { read write getattr }; +allow appdomain cache_backup_file:dir getattr; +# Backup ability using 'adb backup' +allow appdomain system_data_file:lnk_file getattr; + +# Allow read/stat of /data/media files passed by Binder or local socket IPC. +allow appdomain media_rw_data_file:file { read getattr }; + +# Read and write /data/data/com.android.providers.telephony files passed over Binder. +allow appdomain radio_data_file:file { read write getattr }; + +# Allow access to external storage; we have several visible mount points under /storage +# and symlinks to primary storage at places like /storage/sdcard0 and /mnt/user/0/primary +allow appdomain storage_file:dir r_dir_perms; +allow appdomain storage_file:lnk_file r_file_perms; +allow appdomain mnt_user_file:dir r_dir_perms; +allow appdomain mnt_user_file:lnk_file r_file_perms; + +# Read/write visible storage +allow appdomain fuse:dir create_dir_perms; +allow appdomain fuse:file create_file_perms; +allow appdomain sdcardfs:dir create_dir_perms; +allow appdomain sdcardfs:file create_file_perms; + +# Access OBBs (vfat images) mounted by vold (b/17633509) +# File write access allowed for FDs returned through Storage Access Framework +allow appdomain vfat:dir r_dir_perms; +allow appdomain vfat:file rw_file_perms; + +# Allow apps to use the USB Accessory interface. +# http://developer.android.com/guide/topics/connectivity/usb/accessory.html +# +# USB devices are first opened by the system server (USBDeviceManagerService) +# and the file descriptor is passed to the right Activity via binder. +allow appdomain usb_device:chr_file { read write getattr ioctl }; +allow appdomain usbaccessory_device:chr_file { read write getattr }; + +# For art. +allow appdomain dalvikcache_data_file:file execute; +allow appdomain dalvikcache_data_file:lnk_file r_file_perms; + +# Allow any app to read shared RELRO files. +allow appdomain shared_relro_file:dir search; +allow appdomain shared_relro_file:file r_file_perms; + +# Allow apps to read/execute installed binaries +allow appdomain apk_data_file:dir r_dir_perms; +allow appdomain apk_data_file:file { rx_file_perms execmod }; + +# /data/resource-cache +allow appdomain resourcecache_data_file:file r_file_perms; +allow appdomain resourcecache_data_file:dir r_dir_perms; + +# logd access +read_logd(appdomain) +control_logd(appdomain) +# application inherit logd write socket (urge is to deprecate this long term) +allow appdomain zygote:unix_dgram_socket write; + +allow { appdomain -isolated_app } keystore:keystore_key { get_state get insert delete exist list sign verify }; + +use_keystore({ appdomain -isolated_app }) + +allow appdomain console_device:chr_file { read write }; + +allow { appdomain -isolated_app } ion_device:chr_file rw_file_perms; + +# TODO: switch to meminfo service +allow appdomain proc_meminfo:file r_file_perms; + +# For app fuse. +allow appdomain app_fuse_file:file { getattr read append write }; + +### +### CTS-specific rules +### + +# For cts/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java. +# testRunAsHasCorrectCapabilities +allow appdomain runas_exec:file getattr; +# Others are either allowed elsewhere or not desired. + +# For cts/tests/tests/security/src/android/security/cts/SELinuxTest.java +# Check SELinux policy and contexts. +selinux_check_access(appdomain) +selinux_check_context(appdomain) + +# Apps receive an open tun fd from the framework for +# device traffic. Do not allow untrusted app to directly open tun_device +allow { appdomain -isolated_app } tun_device:chr_file { read write getattr ioctl append }; + +# Connect to adbd and use a socket transferred from it. +# This is used for e.g. adb backup/restore. +allow appdomain adbd:unix_stream_socket connectto; +allow appdomain adbd:fd use; +allow appdomain adbd:unix_stream_socket { getattr getopt ioctl read write shutdown }; + +allow appdomain cache_file:dir getattr; + +### +### Neverallow rules +### +### These are things that Android apps should NEVER be able to do +### + +# Superuser capabilities. +# bluetooth requires net_admin and wake_alarm. +neverallow { appdomain -bluetooth -su } self:capability *; +neverallow { appdomain -bluetooth } self:capability2 *; + +# Block device access. +neverallow appdomain dev_type:blk_file { read write }; + +# Access to any of the following character devices. +neverallow appdomain { + audio_device + camera_device + dm_device + radio_device + rpmsg_device + video_device +}:chr_file { read write }; + +# Note: Try expanding list of app domains in the future. +neverallow { untrusted_app isolated_app shell } graphics_device:chr_file { read write }; + +neverallow { appdomain -nfc } nfc_device:chr_file + { read write }; +neverallow { appdomain -bluetooth } hci_attach_dev:chr_file + { read write }; +neverallow appdomain tee_device:chr_file { read write }; + +# Privileged netlink socket interfaces. +neverallow appdomain + domain:{ + netlink_firewall_socket + netlink_tcpdiag_socket + netlink_nflog_socket + netlink_xfrm_socket + netlink_audit_socket + netlink_ip6fw_socket + netlink_dnrt_socket + } *; + +# These messages are broadcast messages from the kernel to userspace. +# Do not allow the writing of netlink messages, which has been a source +# of rooting vulns in the past. +neverallow appdomain domain:netlink_kobject_uevent_socket { write append }; + +# Sockets under /dev/socket that are not specifically typed. +neverallow appdomain socket_device:sock_file write; + +# Unix domain sockets. +neverallow appdomain adbd_socket:sock_file write; +neverallow appdomain installd_socket:sock_file write; +neverallow { appdomain -radio } rild_socket:sock_file write; +neverallow appdomain vold_socket:sock_file write; +neverallow appdomain zygote_socket:sock_file write; + +# ptrace access to non-app domains. +neverallow appdomain { domain -appdomain }:process ptrace; + +# Write access to /proc/pid entries for any non-app domain. +neverallow appdomain { domain -appdomain }:file write; + +# signal access to non-app domains. +# sigchld allowed for parent death notification. +# signull allowed for kill(pid, 0) existence test. +# All others prohibited. +neverallow appdomain { domain -appdomain }:process + { sigkill sigstop signal }; + +# Transition to a non-app domain. +# Exception for the shell domain and the su domain, can transition to runas, +# etc. +neverallow { appdomain -shell userdebug_or_eng(`-su') } { domain -appdomain }:process + { transition dyntransition }; + +# Write to rootfs. +neverallow appdomain rootfs:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; + +# Write to /system. +neverallow appdomain system_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; + +# Write to entrypoint executables. +neverallow appdomain exec_type:file + { create write setattr relabelfrom relabelto append unlink link rename }; + +# Write to system-owned parts of /data. +# This is the default type for anything under /data not otherwise +# specified in file_contexts. Define a different type for portions +# that should be writable by apps. +neverallow appdomain system_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; + +# Write to various other parts of /data. +neverallow appdomain drm_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -platform_app } + apk_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -platform_app } + apk_tmp_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -platform_app } + apk_private_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -platform_app } + apk_private_tmp_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -shell -su } + shell_data_file:dir_file_class_set + { create setattr relabelfrom relabelto append unlink link rename }; +neverallow { appdomain -bluetooth -su } + bluetooth_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow appdomain + keystore_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow appdomain + systemkeys_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow appdomain + wifi_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; +neverallow appdomain + dhcp_data_file:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; + +# access tmp apk files +neverallow { appdomain -platform_app -priv_app } + { apk_tmp_file apk_private_tmp_file }:dir_file_class_set *; + +# Access to factory files. +neverallow appdomain efs_file:dir_file_class_set write; +neverallow { appdomain -shell } efs_file:dir_file_class_set read; + +# Write to various pseudo file systems. +neverallow { appdomain -bluetooth -nfc } + sysfs:dir_file_class_set write; +neverallow appdomain + proc:dir_file_class_set write; + +# Access to syslog(2) or /proc/kmsg. +neverallow { appdomain -system_app } + kernel:system { syslog_mod syslog_console }; +neverallow { appdomain -system_app -shell -su } + kernel:system syslog_read; + +# Ability to perform any filesystem operation other than statfs(2). +# i.e. no mount(2), unmount(2), etc. +neverallow appdomain fs_type:filesystem ~getattr; + +# prevent creation/manipulation of globally readable symlinks +neverallow appdomain { + apk_data_file + cache_file + cache_recovery_file + dev_type + rootfs + system_file + tmpfs +}:lnk_file no_w_file_perms; + +# Applications should use the activity model for receiving events +neverallow { + appdomain + -shell # bugreport +} input_device:chr_file ~getattr;
diff --git a/sepolicy/atrace.te b/sepolicy/atrace.te new file mode 100644 index 0000000..31cf9e7 --- /dev/null +++ b/sepolicy/atrace.te
@@ -0,0 +1,24 @@ +# Domain for atrace process spawned by boottrace service. +type atrace_exec, exec_type, file_type; + +userdebug_or_eng(` + + type atrace, domain, domain_deprecated; + init_daemon_domain(atrace) + + # boottrace services uses /data/misc/boottrace/categories + allow atrace boottrace_data_file:dir search; + allow atrace boottrace_data_file:file r_file_perms; + + # atrace reads the files in /sys/kernel/debug/tracing/ + allow atrace debugfs_tracing:file r_file_perms; + + # atrace sets debug.atrace.* properties + set_prop(atrace, debug_prop) + + # atrace pokes all the binder-enabled processes at startup. + binder_use(atrace) + allow atrace healthd:binder call; + allow atrace surfaceflinger:binder call; + +')
diff --git a/sepolicy/attributes b/sepolicy/attributes new file mode 100644 index 0000000..052f0dd --- /dev/null +++ b/sepolicy/attributes
@@ -0,0 +1,112 @@ +###################################### +# Attribute declarations +# + +# All types used for devices. +# On change, update CHECK_FC_ASSERT_ATTRS +# in tools/checkfc.c +attribute dev_type; + +# All types used for processes. +attribute domain; + +# Temporary attribute used for migrating permissions out of domain. +# Motivation: Domain is overly permissive. Start removing permissions +# from domain and assign them to the domain_deprecated attribute. +# Domain_deprecated and domain can initially be assigned to all +# domains. The goal is to not assign domain_deprecated to new domains +# and to start removing domain_deprecated where it's not required or +# reassigning the appropriate permissions to the inheriting domain +# when necessary. +attribute domain_deprecated; + +# All types used for filesystems. +# On change, update CHECK_FC_ASSERT_ATTRS +# definition in tools/checkfc.c. +attribute fs_type; + +# All types used for context= mounts. +attribute contextmount_type; + +# All types used for files that can exist on a labeled fs. +# Do not use for pseudo file types. +# On change, update CHECK_FC_ASSERT_ATTRS +# definition in tools/checkfc.c. +attribute file_type; + +# All types used for domain entry points. +attribute exec_type; + +# All types used for /data files. +attribute data_file_type; + +# All types use for sysfs files. +attribute sysfs_type; + +# All types use for debugfs files. +attribute debugfs_type; + +# Attribute used for all sdcards +attribute sdcard_type; + +# All types used for nodes/hosts. +attribute node_type; + +# All types used for network interfaces. +attribute netif_type; + +# All types used for network ports. +attribute port_type; + +# All types used for property service +# On change, update CHECK_PC_ASSERT_ATTRS +# definition in tools/checkfc.c. +attribute property_type; + +# All properties defined in core SELinux policy. Should not be +# used by device specific properties +attribute core_property_type; + +# All service_manager types created by system_server +attribute system_server_service; + +# services which should be available to all but isolated apps +attribute app_api_service; + +# services which export only system_api +attribute system_api_service; + +# All types used for services managed by service_manager. +# On change, update CHECK_SC_ASSERT_ATTRS +# definition in tools/checkfc.c. +attribute service_manager_type; + +# All domains that can override MLS restrictions. +# i.e. processes that can read up and write down. +attribute mlstrustedsubject; + +# All types that can override MLS restrictions. +# i.e. files that can be read by lower and written by higher +attribute mlstrustedobject; + +# All domains used for apps. +attribute appdomain; + +# All domains used for apps with network access. +attribute netdomain; + +# All domains used for apps with bluetooth access. +attribute bluetoothdomain; + +# All domains used for binder service domains. +attribute binderservicedomain; + +# All domains that access the boot_control HAL. The permissions the HAL +# requires are specific to the implementation provided in each device, but +# common daemons need to be aware of those when calling into the HAL. +attribute boot_control_hal; + +# update_engine related domains that need to apply an update and run +# postinstall. This includes the background daemon and the sideload tool from +# recovery for A/B devices. +attribute update_engine_common;
diff --git a/sepolicy/binderservicedomain.te b/sepolicy/binderservicedomain.te new file mode 100644 index 0000000..36993eb --- /dev/null +++ b/sepolicy/binderservicedomain.te
@@ -0,0 +1,21 @@ +# Rules common to all binder service domains + +# Allow dumpstate to collect information from binder services +allow binderservicedomain dumpstate:fd use; +allow binderservicedomain dumpstate:unix_stream_socket { read write getopt getattr }; +allow binderservicedomain shell_data_file:file { getattr write }; + +# Allow dumpsys to work from adb shell or the serial console +allow binderservicedomain devpts:chr_file rw_file_perms; +allow binderservicedomain console_device:chr_file rw_file_perms; + +# Receive and write to a pipe received over Binder from an app. +allow binderservicedomain appdomain:fd use; +allow binderservicedomain appdomain:fifo_file write; + +# allow all services to run permission checks +allow binderservicedomain permission_service:service_manager find; + +allow binderservicedomain keystore:keystore_key { get_state get insert delete exist list sign verify }; + +use_keystore(binderservicedomain)
diff --git a/sepolicy/blkid.te b/sepolicy/blkid.te new file mode 100644 index 0000000..43bc944 --- /dev/null +++ b/sepolicy/blkid.te
@@ -0,0 +1,20 @@ +# blkid called from vold +type blkid, domain, domain_deprecated; +type blkid_exec, exec_type, file_type; + +# Allowed read-only access to encrypted devices to extract UUID/label +allow blkid block_device:dir search; +allow blkid userdata_block_device:blk_file r_file_perms; +allow blkid dm_device:blk_file r_file_perms; + +# Allow stdin/out back to vold +allow blkid vold:fd use; +allow blkid vold:fifo_file { read write getattr }; + +# For blkid launched through popen() +allow blkid blkid_exec:file rx_file_perms; + +# Only allow entry from vold +neverallow { domain -vold } blkid:process transition; +neverallow * blkid:process dyntransition; +neverallow blkid { file_type fs_type -blkid_exec -shell_exec }:file entrypoint;
diff --git a/sepolicy/blkid_untrusted.te b/sepolicy/blkid_untrusted.te new file mode 100644 index 0000000..da3bdac --- /dev/null +++ b/sepolicy/blkid_untrusted.te
@@ -0,0 +1,36 @@ +# blkid for untrusted block devices +type blkid_untrusted, domain, domain_deprecated; + +# Allowed read-only access to vold block devices to extract UUID/label +allow blkid_untrusted block_device:dir search; +allow blkid_untrusted vold_device:blk_file r_file_perms; + +# Allow stdin/out back to vold +allow blkid_untrusted vold:fd use; +allow blkid_untrusted vold:fifo_file { read write getattr }; + +# For blkid launched through popen() +allow blkid_untrusted blkid_exec:file rx_file_perms; + +### +### neverallow rules +### + +# Untrusted blkid should never be run on block devices holding sensitive data +neverallow blkid_untrusted { + boot_block_device + frp_block_device + metadata_block_device + recovery_block_device + root_block_device + swap_block_device + system_block_device + userdata_block_device + cache_block_device + dm_device +}:blk_file no_rw_file_perms; + +# Only allow entry from vold via blkid binary +neverallow { domain -vold } blkid_untrusted:process transition; +neverallow * blkid_untrusted:process dyntransition; +neverallow blkid_untrusted { file_type fs_type -blkid_exec -shell_exec }:file entrypoint;
diff --git a/sepolicy/bluetooth.te b/sepolicy/bluetooth.te new file mode 100644 index 0000000..f249e9b --- /dev/null +++ b/sepolicy/bluetooth.te
@@ -0,0 +1,64 @@ +# bluetooth subsystem +type bluetooth, domain, domain_deprecated; +app_domain(bluetooth) +net_domain(bluetooth) + +wakelock_use(bluetooth); + +# Data file accesses. +allow bluetooth bluetooth_data_file:dir create_dir_perms; +allow bluetooth bluetooth_data_file:notdevfile_class_set create_file_perms; + +# Socket creation under /data/misc/bluedroid. +type_transition bluetooth bluetooth_data_file:sock_file bluetooth_socket; +allow bluetooth bluetooth_socket:sock_file create_file_perms; + +# bluetooth factory file accesses. +r_dir_file(bluetooth, bluetooth_efs_file) + +allow bluetooth { uhid_device hci_attach_dev }:chr_file rw_file_perms; + +# sysfs access. +allow bluetooth sysfs_bluetooth_writable:file rw_file_perms; +allow bluetooth self:capability net_admin; +allow bluetooth self:capability2 wake_alarm; + +# tethering +allow bluetooth self:tun_socket create_socket_perms; +allow bluetooth tun_device:chr_file rw_file_perms; +allow bluetooth efs_file:dir search; + +# proc access. +allow bluetooth proc_bluetooth_writable:file rw_file_perms; + +# Allow write access to bluetooth specific properties +set_prop(bluetooth, bluetooth_prop) +set_prop(bluetooth, pan_result_prop) +set_prop(bluetooth, ctl_dhcp_pan_prop) + +allow bluetooth bluetooth_service:service_manager find; +allow bluetooth drmserver_service:service_manager find; +allow bluetooth mediaserver_service:service_manager find; +allow bluetooth radio_service:service_manager find; +allow bluetooth surfaceflinger_service:service_manager find; +allow bluetooth app_api_service:service_manager find; +allow bluetooth system_api_service:service_manager find; + +# Bluetooth Sim Access Profile Socket to the RIL +unix_socket_connect(bluetooth, sap_uim, rild) + +# already open bugreport file descriptors may be shared with +# the bluetooth process, from a file in +# /data/data/com.android.shell/files/bugreports/bugreport-*. +allow bluetooth shell_data_file:file read; + +### +### Neverallow rules +### +### These are things that the bluetooth app should NEVER be able to do +### + +# Superuser capabilities. +# bluetooth requires net_admin, wake_alarm and block_suspend +neverallow bluetooth self:capability ~net_admin; +neverallow bluetooth self:capability2 ~{ wake_alarm block_suspend };
diff --git a/sepolicy/bluetoothdomain.te b/sepolicy/bluetoothdomain.te new file mode 100644 index 0000000..fe4f0e6 --- /dev/null +++ b/sepolicy/bluetoothdomain.te
@@ -0,0 +1,2 @@ +# Allow clients to use a socket provided by the bluetooth app. +allow bluetoothdomain bluetooth:unix_stream_socket { getopt setopt getattr read write ioctl shutdown };
diff --git a/sepolicy/boot_control_hal.te b/sepolicy/boot_control_hal.te new file mode 100644 index 0000000..2a670b3 --- /dev/null +++ b/sepolicy/boot_control_hal.te
@@ -0,0 +1,2 @@ +# Allow read/write bootctrl block device, if one is defined. +allow boot_control_hal bootctrl_block_device:blk_file rw_file_perms;
diff --git a/sepolicy/bootanim.te b/sepolicy/bootanim.te new file mode 100644 index 0000000..fa0e4dc --- /dev/null +++ b/sepolicy/bootanim.te
@@ -0,0 +1,30 @@ +# bootanimation oneshot service +type bootanim, domain; +type bootanim_exec, exec_type, file_type; + +init_daemon_domain(bootanim) + +binder_use(bootanim) +binder_call(bootanim, surfaceflinger) + +allow bootanim gpu_device:chr_file rw_file_perms; + +# /oem access +allow bootanim oemfs:dir search; +allow bootanim oemfs:file r_file_perms; + +allow bootanim audio_device:dir r_dir_perms; +allow bootanim audio_device:chr_file rw_file_perms; + +allow bootanim surfaceflinger_service:service_manager find; + +# Allow access to ion memory allocation device +allow bootanim ion_device:chr_file rw_file_perms; + +# Read access to pseudo filesystems. +r_dir_file(bootanim, proc) +r_dir_file(bootanim, sysfs) +r_dir_file(bootanim, cgroup) + +# System file accesses. +allow bootanim system_file:dir r_dir_perms;
diff --git a/sepolicy/bootstat.te b/sepolicy/bootstat.te new file mode 100644 index 0000000..44a8c91 --- /dev/null +++ b/sepolicy/bootstat.te
@@ -0,0 +1,12 @@ +# bootstat command +type bootstat, domain; +type bootstat_exec, exec_type, file_type; + +init_daemon_domain(bootstat) + +# Allow persistent storage in /data/misc/bootstat. +allow bootstat bootstat_data_file:dir rw_dir_perms; +allow bootstat bootstat_data_file:file create_file_perms; + +# Read access to pseudo filesystems (for /proc/uptime). +r_dir_file(bootstat, proc) \ No newline at end of file
diff --git a/sepolicy/clatd.te b/sepolicy/clatd.te new file mode 100644 index 0000000..3cda6a2 --- /dev/null +++ b/sepolicy/clatd.te
@@ -0,0 +1,31 @@ +# 464xlat daemon +type clatd, domain, domain_deprecated; +type clatd_exec, exec_type, file_type; + +net_domain(clatd) + +# Access objects inherited from netd. +allow clatd netd:fd use; +allow clatd netd:fifo_file { read write }; +# TODO: Check whether some or all of these sockets should be close-on-exec. +allow clatd netd:netlink_kobject_uevent_socket { read write }; +allow clatd netd:netlink_nflog_socket { read write }; +allow clatd netd:netlink_route_socket { read write }; +allow clatd netd:udp_socket { read write }; +allow clatd netd:unix_stream_socket { read write }; +allow clatd netd:unix_dgram_socket { read write }; + +allow clatd self:capability { net_admin net_raw setuid setgid }; + +# clatd calls mmap(MAP_LOCKED) with a 1M buffer. MAP_LOCKED first checks +# capable(CAP_IPC_LOCK), and then checks to see the requested amount is +# under RLIMIT_MEMLOCK. If the latter check succeeds clatd won't have +# needed CAP_IPC_LOCK. But this is not guaranteed to succeed on all devices +# so we permit any requests we see from clatd asking for this capability. +# See https://android-review.googlesource.com/127940 and +# https://b.corp.google.com/issues/21736319 +allow clatd self:capability ipc_lock; + +allow clatd self:netlink_route_socket nlmsg_write; +allow clatd self:{ packet_socket rawip_socket tun_socket } create_socket_perms; +allow clatd tun_device:chr_file rw_file_perms;
diff --git a/sepolicy/debuggerd.te b/sepolicy/debuggerd.te new file mode 100644 index 0000000..04dcb79 --- /dev/null +++ b/sepolicy/debuggerd.te
@@ -0,0 +1,38 @@ +# debugger interface +type debuggerd, domain, domain_deprecated; +type debuggerd_exec, exec_type, file_type; + +init_daemon_domain(debuggerd) +typeattribute debuggerd mlstrustedsubject; +allow debuggerd self:capability { dac_override sys_ptrace chown kill fowner setuid setgid }; +allow debuggerd self:capability2 { syslog }; +allow debuggerd domain:dir r_dir_perms; +allow debuggerd domain:file r_file_perms; +allow debuggerd domain:lnk_file read; +allow debuggerd { domain -init -ueventd -watchdogd -healthd -adbd -keystore }:process { ptrace getattr }; +allow debuggerd tombstone_data_file:dir rw_dir_perms; +allow debuggerd tombstone_data_file:file create_file_perms; +allow debuggerd shared_relro_file:dir r_dir_perms; +allow debuggerd shared_relro_file:file r_file_perms; +allow debuggerd domain:process { sigstop sigkill signal }; +allow debuggerd exec_type:file r_file_perms; +# Access app library +allow debuggerd system_data_file:file open; +# Allow debuggerd to redirect a dump_backtrace request to itself. +# This only happens on 64 bit systems, where all requests go to the 64 bit +# debuggerd and get redirected to the 32 bit debuggerd if the process is 32 bit. +allow debuggerd { drmserver mediaserver sdcardd surfaceflinger inputflinger }:debuggerd dump_backtrace; + +# Connect to system_server via /data/system/ndebugsocket. +unix_socket_connect(debuggerd, system_ndebug, system_server) + +userdebug_or_eng(` + allow debuggerd input_device:dir r_dir_perms; + allow debuggerd input_device:chr_file rw_file_perms; +') + +# logd access +read_logd(debuggerd) + +# Check SELinux permissions. +selinux_check_access(debuggerd)
diff --git a/sepolicy/device.te b/sepolicy/device.te new file mode 100644 index 0000000..e4a792e --- /dev/null +++ b/sepolicy/device.te
@@ -0,0 +1,101 @@ +# Device types +type device, dev_type, fs_type; +type alarm_device, dev_type, mlstrustedobject; +type adb_device, dev_type; +type ashmem_device, dev_type, mlstrustedobject; +type audio_device, dev_type; +type binder_device, dev_type, mlstrustedobject; +type block_device, dev_type; +type camera_device, dev_type; +type dm_device, dev_type; +type loop_device, dev_type; +type pmsg_device, dev_type, mlstrustedobject; +type radio_device, dev_type; +type ram_device, dev_type; +type rtc_device, dev_type; +type vold_device, dev_type; +type console_device, dev_type; +type cpuctl_device, dev_type; +type fscklogs, dev_type; +type full_device, dev_type; +# GPU (used by most UI apps) +type gpu_device, dev_type, mlstrustedobject; +type graphics_device, dev_type; +type hw_random_device, dev_type; +type input_device, dev_type; +type kmem_device, dev_type; +type log_device, dev_type, mlstrustedobject; +type mtd_device, dev_type; +type mtp_device, dev_type, mlstrustedobject; +type nfc_device, dev_type; +type ptmx_device, dev_type, mlstrustedobject; +type kmsg_device, dev_type; +type null_device, dev_type, mlstrustedobject; +type random_device, dev_type, mlstrustedobject; +type sensors_device, dev_type; +type serial_device, dev_type; +type socket_device, dev_type; +type owntty_device, dev_type, mlstrustedobject; +type tty_device, dev_type; +type urandom_device, dev_type, mlstrustedobject; +type video_device, dev_type; +type vcs_device, dev_type; +type zero_device, dev_type, mlstrustedobject; +type fuse_device, dev_type, mlstrustedobject; +type iio_device, dev_type; +type ion_device, dev_type, mlstrustedobject; +type qtaguid_device, dev_type; +type watchdog_device, dev_type; +type uhid_device, dev_type; +type uio_device, dev_type; +type tun_device, dev_type, mlstrustedobject; +type usbaccessory_device, dev_type, mlstrustedobject; +type usb_device, dev_type, mlstrustedobject; +type properties_device, dev_type; +type properties_serial, dev_type; +type i2c_device, dev_type; + +# All devices have a uart for the hci +# attach service. The uart dev node +# varies per device. This type +# is used in per device policy +type hci_attach_dev, dev_type; + +# All devices have a rpmsg device for +# achieving remoteproc and rpmsg modules +type rpmsg_device, dev_type; + +# Partition layout block device +type root_block_device, dev_type; + +# factory reset protection block device +type frp_block_device, dev_type; + +# System block device mounted on /system. +type system_block_device, dev_type; + +# Recovery block device. +type recovery_block_device, dev_type; + +# boot block device. +type boot_block_device, dev_type; + +# Userdata block device mounted on /data. +type userdata_block_device, dev_type; + +# Cache block device mounted on /cache. +type cache_block_device, dev_type; + +# Block device for any swap partition. +type swap_block_device, dev_type; + +# Metadata block device used for encryption metadata. +# Assign this type to the partition specified by the encryptable= +# mount option in your fstab file in the entry for userdata. +type metadata_block_device, dev_type; + +# The 'misc' partition used by recovery and A/B. +type misc_block_device, dev_type; + +# Bootctrl block device used by A/B update (update_engine, update_verifier). +type bootctrl_block_device, dev_type;
diff --git a/sepolicy/dex2oat.te b/sepolicy/dex2oat.te new file mode 100644 index 0000000..83a7c8a --- /dev/null +++ b/sepolicy/dex2oat.te
@@ -0,0 +1,16 @@ +# dex2oat +type dex2oat, domain, domain_deprecated; +type dex2oat_exec, exec_type, file_type; + +allow dex2oat dalvikcache_data_file:file write; +# Read symlinks in /data/dalvik-cache +allow dex2oat dalvikcache_data_file:lnk_file read; +allow dex2oat installd:fd use; + +# Read already open asec_apk_file file descriptors passed by installd. +# Also allow reading unlabeled files, to allow for upgrading forward +# locked APKs. +allow dex2oat asec_apk_file:file read; +allow dex2oat unlabeled:file read; +allow dex2oat oemfs:file read; +allow dex2oat apk_tmp_file:file read;
diff --git a/sepolicy/dhcp.te b/sepolicy/dhcp.te new file mode 100644 index 0000000..a858e08 --- /dev/null +++ b/sepolicy/dhcp.te
@@ -0,0 +1,32 @@ +type dhcp, domain, domain_deprecated; +type dhcp_exec, exec_type, file_type; +type dhcp_data_file, file_type, data_file_type; + +init_daemon_domain(dhcp) +net_domain(dhcp) + +allow dhcp cgroup:dir { create write add_name }; +allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service }; +allow dhcp self:packet_socket create_socket_perms; +allow dhcp self:netlink_route_socket nlmsg_write; +allow dhcp shell_exec:file rx_file_perms; +allow dhcp system_file:file rx_file_perms; + +# dhcpcd runs dhcpcd-hooks/*, which runs getprop / setprop (toolbox_exec) +allow dhcp toolbox_exec:file rx_file_perms; + +# For /proc/sys/net/ipv4/conf/*/promote_secondaries +allow dhcp proc_net:file write; + +set_prop(dhcp, dhcp_prop) +set_prop(dhcp, pan_result_prop) + +type_transition dhcp system_data_file:{ dir file } dhcp_data_file; +allow dhcp dhcp_data_file:dir create_dir_perms; +allow dhcp dhcp_data_file:file create_file_perms; + +# PAN connections +allow dhcp netd:fd use; +allow dhcp netd:fifo_file rw_file_perms; +allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write }; +allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket netlink_nflog_socket } { read write };
diff --git a/sepolicy/dnsmasq.te b/sepolicy/dnsmasq.te new file mode 100644 index 0000000..e5e4198 --- /dev/null +++ b/sepolicy/dnsmasq.te
@@ -0,0 +1,24 @@ +# DNS, DHCP services +type dnsmasq, domain, domain_deprecated; +type dnsmasq_exec, exec_type, file_type; + +net_domain(dnsmasq) + +# TODO: Run with dhcp group to avoid need for dac_override. +allow dnsmasq self:capability dac_override; + +allow dnsmasq self:capability { net_admin net_raw net_bind_service setgid setuid }; + +allow dnsmasq dhcp_data_file:dir w_dir_perms; +allow dnsmasq dhcp_data_file:file create_file_perms; + +# Inherit and use open files from netd. +allow dnsmasq netd:fd use; +allow dnsmasq netd:fifo_file { read write }; +# TODO: Investigate whether these inherited sockets should be closed on exec. +allow dnsmasq netd:netlink_kobject_uevent_socket { read write }; +allow dnsmasq netd:netlink_nflog_socket { read write }; +allow dnsmasq netd:netlink_route_socket { read write }; +allow dnsmasq netd:unix_stream_socket { read write }; +allow dnsmasq netd:unix_dgram_socket { read write }; +allow dnsmasq netd:udp_socket { read write };
diff --git a/sepolicy/domain.te b/sepolicy/domain.te new file mode 100644 index 0000000..3917f8b --- /dev/null +++ b/sepolicy/domain.te
@@ -0,0 +1,593 @@ +# Rules for all domains. + +# Allow reaping by init. +allow domain init:process sigchld; + +# Intra-domain accesses. +allow domain self:process { + fork + sigchld + sigkill + sigstop + signull + signal + getsched + setsched + getsession + getpgid + setpgid + getcap + setcap + getattr + setrlimit +}; +allow domain self:fd use; +allow domain proc:dir r_dir_perms; +allow domain proc_net:dir search; +r_dir_file(domain, self) +allow domain self:{ fifo_file file } rw_file_perms; +allow domain self:unix_dgram_socket { create_socket_perms sendto }; +allow domain self:unix_stream_socket { create_stream_socket_perms connectto }; + +# Inherit or receive open files from others. +allow domain init:fd use; + +userdebug_or_eng(` + # Same as adbd rules above, except allow su to do the same thing + allow domain su:unix_stream_socket connectto; + allow domain su:fd use; + allow domain su:unix_stream_socket { getattr getopt read write shutdown }; + + binder_call({ domain -init }, su) + + # Running something like "pm dump com.android.bluetooth" requires + # fifo writes + allow domain su:fifo_file { write getattr }; + + # allow "gdbserver --attach" to work for su. + allow domain su:process sigchld; + + # Allow writing coredumps to /cores/* + allow domain coredump_file:file create_file_perms; + allow domain coredump_file:dir ra_dir_perms; +') + +### +### Talk to debuggerd. +### +allow domain debuggerd:process sigchld; +allow domain debuggerd:unix_stream_socket connectto; + +# Root fs. +allow domain rootfs:dir search; +allow domain rootfs:lnk_file read; + +# Device accesses. +allow domain device:dir search; +allow domain dev_type:lnk_file r_file_perms; +allow domain devpts:dir search; +allow domain socket_device:dir r_dir_perms; +allow domain owntty_device:chr_file rw_file_perms; +allow domain null_device:chr_file rw_file_perms; +allow domain zero_device:chr_file rw_file_perms; +allow domain ashmem_device:chr_file rw_file_perms; +allow domain binder_device:chr_file rw_file_perms; +allow domain ptmx_device:chr_file rw_file_perms; +allow domain alarm_device:chr_file r_file_perms; +allow domain urandom_device:chr_file rw_file_perms; +allow domain random_device:chr_file rw_file_perms; +allow domain properties_device:dir r_dir_perms; +allow domain properties_serial:file r_file_perms; + +# For now, everyone can access core property files +# Device specific properties are not granted by default +get_prop(domain, core_property_type) +dontaudit domain property_type:file audit_access; +allow domain property_contexts:file r_file_perms; + +allow domain init:key search; +allow domain vold:key search; + +# logd access +write_logd(domain) + +# System file accesses. +allow domain system_file:dir { search getattr }; +allow domain system_file:file { execute read open getattr }; +allow domain system_file:lnk_file read; + +# read any sysfs symlinks +allow domain sysfs:lnk_file read; + +# libc references /data/misc/zoneinfo for timezone related information +r_dir_file(domain, zoneinfo_data_file) + +# Lots of processes access current CPU information +r_dir_file(domain, sysfs_devices_system_cpu) + +# files under /data. +allow domain system_data_file:dir { search getattr }; +allow domain system_data_file:lnk_file read; + +# required by the dynamic linker +allow domain proc:lnk_file { getattr read }; + +# /proc/cpuinfo +allow domain proc_cpuinfo:file r_file_perms; + +# jemalloc needs to read /proc/sys/vm/overcommit_memory +allow domain proc_overcommit_memory:file r_file_perms; + +# toybox loads libselinux which stats /sys/fs/selinux/ +allow domain selinuxfs:dir search; +allow domain selinuxfs:file getattr; +allow domain sysfs:dir search; +allow domain selinuxfs:filesystem getattr; + +# For /acct/uid/*/tasks. +allow domain cgroup:dir { search write }; +allow domain cgroup:file w_file_perms; + +# Almost all processes log tracing information to +# /sys/kernel/debug/tracing/trace_marker +# The reason behind this is documented in b/6513400 +allow domain debugfs:dir search; +allow domain debugfs_tracing:dir search; +allow domain debugfs_trace_marker:file w_file_perms; + +# Filesystem access. +allow domain fs_type:filesystem getattr; +allow domain fs_type:dir getattr; + +### +### neverallow rules +### + +# Do not allow any domain other than init or recovery to create unlabeled files. +neverallow { domain -init -recovery } unlabeled:dir_file_class_set create; + +# Limit ability to ptrace or read sensitive /proc/pid files of processes +# with other UIDs to these whitelisted domains. +neverallow { + domain + -debuggerd + -vold + -dumpstate + -system_server + userdebug_or_eng(`-perfprofd') +} self:capability sys_ptrace; + +# Limit device node creation to these whitelisted domains. +neverallow { + domain + -kernel + -init + -ueventd + -vold + -recovery +} self:capability mknod; + +# Limit raw I/O to these whitelisted domains. +neverallow { domain -kernel -init -recovery -ueventd -watchdogd -healthd -uncrypt -tee } self:capability sys_rawio; + +# No process can map low memory (< CONFIG_LSM_MMAP_MIN_ADDR). +neverallow * self:memprotect mmap_zero; + +# No domain needs mac_override as it is unused by SELinux. +neverallow * self:capability2 mac_override; + +# Only recovery needs mac_admin to set contexts not defined in current policy. +neverallow { domain -recovery } self:capability2 mac_admin; + +# Once the policy has been loaded there shall be none to modify the policy. +# It is sealed. +neverallow * kernel:security load_policy; + +# Only init and the system_server shall use the property_service. +neverallow { domain -init -system_server } security_prop:property_service set; + +# Only init prior to switching context should be able to set enforcing mode. +# init starts in kernel domain and switches to init domain via setcon in +# the init.rc, so the setenforce occurs while still in kernel. After +# switching domains, there is never any need to setenforce again by init. +neverallow * kernel:security setenforce; +neverallow { domain -kernel } kernel:security setcheckreqprot; + +# No booleans in AOSP policy, so no need to ever set them. +neverallow * kernel:security setbool; + +# Adjusting the AVC cache threshold. +# Not presently allowed to anything in policy, but possibly something +# that could be set from init.rc. +neverallow { domain -init } kernel:security setsecparam; + +# Only init, ueventd, shell and system_server should be able to access HW RNG +neverallow { + domain + -init + -shell # For CTS and is restricted to getattr in shell.te + -system_server + -ueventd +} hw_random_device:chr_file *; + +# Ensure that all entrypoint executables are in exec_type or postinstall_file. +neverallow * { file_type -exec_type -postinstall_file }:file entrypoint; + +# Ensure that nothing in userspace can access /dev/mem or /dev/kmem +neverallow { + domain + -init + -kernel + -shell # For CTS and is restricted to getattr in shell.te + -ueventd # Further restricted in ueventd.te +} kmem_device:chr_file *; +neverallow * kmem_device:chr_file ~{ create relabelto unlink setattr getattr }; + +# Only init should be able to configure kernel usermodehelpers or +# security-sensitive proc settings. +neverallow { domain -init } usermodehelper:file { append write }; +neverallow { domain -init } proc_security:file { append write }; + +# No domain should be allowed to ptrace init. +neverallow * init:process ptrace; + +# Init can't do anything with binder calls. If this neverallow rule is being +# triggered, it's probably due to a service with no SELinux domain. +neverallow * init:binder *; + +# Don't allow raw read/write/open access to block_device +# Rather force a relabel to a more specific type +neverallow { domain -kernel -init -recovery } block_device:blk_file { open read write }; + +# Don't allow raw read/write/open access to generic devices. +# Rather force a relabel to a more specific type. +# init is exempt from this as there are character devices that only it uses. +# ueventd is exempt from this, as it is managing these devices. +neverallow { domain -init -ueventd } device:chr_file { open read write }; + +# Limit what domains can mount filesystems or change their mount flags. +# sdcard_type / vfat is exempt as a larger set of domains need +# this capability, including device-specific domains. +neverallow { domain -kernel -init -recovery -vold -zygote -update_engine } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto }; + +# +# Assert that, to the extent possible, we're not loading executable content from +# outside the rootfs or /system partition except for a few whitelisted domains. +# +neverallow { + domain + -appdomain + -dumpstate + -shell + -su + -system_server + -zygote +} { file_type -system_file -exec_type -postinstall_file }:file execute; +neverallow { + domain + -appdomain # for oemfs + -recovery # for /tmp/update_binary in tmpfs +} { fs_type -rootfs }:file execute; +# Files from cache should never be executed +neverallow domain { cache_file cache_backup_file cache_recovery_file }:file execute; + +# Protect most domains from executing arbitrary content from /data. +neverallow { + domain + -untrusted_app + -priv_app + -shell +} { + data_file_type + -dalvikcache_data_file + -system_data_file # shared libs in apks + -apk_data_file +}:file no_x_file_perms; + +neverallow { domain userdebug_or_eng(`-shell') } nativetest_data_file:file no_x_file_perms; + +# Only the init property service should write to /data/property and /dev/__properties__ +neverallow { domain -init } property_data_file:dir no_w_dir_perms; +neverallow { domain -init } property_data_file:file { no_w_file_perms no_x_file_perms }; +neverallow { domain -init -su } property_type:file { no_w_file_perms no_x_file_perms }; +neverallow { domain -init } properties_device:file { no_w_file_perms no_x_file_perms }; +neverallow { domain -init } properties_serial:file { no_w_file_perms no_x_file_perms }; + +# Only recovery should be doing writes to /system +neverallow { domain -recovery } { system_file exec_type }:dir_file_class_set + { create write setattr relabelfrom append unlink link rename }; +neverallow { domain -recovery -kernel } { system_file exec_type }:dir_file_class_set relabelto; + +# Don't allow mounting on top of /system files or directories +neverallow * exec_type:dir_file_class_set mounton; +neverallow { domain -init } system_file:dir_file_class_set mounton; + +# Nothing should be writing to files in the rootfs. +neverallow * rootfs:file { create write setattr relabelto append unlink link rename }; + +# Restrict context mounts to specific types marked with +# the contextmount_type attribute. +neverallow * {fs_type -contextmount_type}:filesystem relabelto; + +# Ensure that context mount types are not writable, to ensure that +# the write to /system restriction above is not bypassed via context= +# mount to another type. +neverallow { domain -recovery } contextmount_type:dir_file_class_set + { create write setattr relabelfrom relabelto append unlink link rename }; + +# Do not allow service_manager add for default_android_service. +# Instead domains should use a more specific type such as +# system_app_service rather than the generic type. +# New service_types are defined in service.te and new mappings +# from service name to service_type are defined in service_contexts. +neverallow * default_android_service:service_manager add; + +# Require that domains explicitly label unknown properties, and do not allow +# anyone but init to modify unknown properties. +neverallow { domain -init } default_prop:property_service set; +neverallow { domain -init } mmc_prop:property_service set; + +neverallow { + domain + -init + -recovery + -system_server + -shell # Shell is further restricted in shell.te + -ueventd # Further restricted in ueventd.te +} frp_block_device:blk_file rw_file_perms; + +# No domain other than recovery and update_engine can write to system partition(s). +neverallow { domain -recovery -update_engine } system_block_device:blk_file write; + +# No domains other than install_recovery or recovery can write to recovery. +neverallow { domain -install_recovery -recovery } recovery_block_device:blk_file write; + +# No domains other than a select few can access the misc_block_device. This +# block device is reserved for OTA use. +# Do not assert this rule on userdebug/eng builds, due to some devices using +# this partition for testing purposes. +neverallow { + domain + userdebug_or_eng(`-domain') # exclude debuggable builds + -init + -uncrypt + -update_engine + -vold + -recovery + -ueventd +} misc_block_device:blk_file { append link relabelfrom rename write open read ioctl lock }; + +# Only servicemanager should be able to register with binder as the context manager +neverallow { domain -servicemanager } *:binder set_context_mgr; + +# Only authorized processes should be writing to files in /data/dalvik-cache +neverallow { + domain + -init # TODO: limit init to relabelfrom for files + -zygote + -installd + -dex2oat +} dalvikcache_data_file:file no_w_file_perms; + +neverallow { + domain + -init + -installd + -dex2oat + -zygote +} dalvikcache_data_file:dir no_w_dir_perms; + +# Only system_server should be able to send commands via the zygote socket +neverallow { domain -zygote -system_server } zygote:unix_stream_socket connectto; +neverallow { domain -system_server } zygote_socket:sock_file write; + +# Android does not support System V IPCs. +# +# The reason for this is due to the fact that, by design, they lead to global +# kernel resource leakage. +# +# For example, there is no way to automatically release a SysV semaphore +# allocated in the kernel when: +# +# - a buggy or malicious process exits +# - a non-buggy and non-malicious process crashes or is explicitly killed. +# +# Killing processes automatically to make room for new ones is an +# important part of Android's application lifecycle implementation. This means +# that, even assuming only non-buggy and non-malicious code, it is very likely +# that over time, the kernel global tables used to implement SysV IPCs will fill +# up. +neverallow * *:{ shm sem msg msgq } *; + +# Do not mount on top of symlinks, fifos, or sockets. +# Feature parity with Chromium LSM. +neverallow * { file_type fs_type dev_type }:{ lnk_file fifo_file sock_file } mounton; + +# Nobody should be able to execute su on user builds. +# On userdebug/eng builds, only dumpstate, shell, and +# su itself execute su. +neverallow { domain userdebug_or_eng(`-dumpstate -shell') -su } su_exec:file no_x_file_perms; + +# Do not allow the introduction of new execmod rules. Text relocations +# and modification of executable pages are unsafe. +# The only exceptions are for NDK text relocations associated with +# https://code.google.com/p/android/issues/detail?id=23203 +# which, long term, need to go away. +neverallow * { + file_type + -apk_data_file + -app_data_file + -asec_public_file +}:file execmod; + +# Do not allow making the stack or heap executable. +# We would also like to minimize execmem but it seems to be +# required by some device-specific service domains. +neverallow * self:process { execstack execheap }; + +# prohibit non-zygote spawned processes from using shared libraries +# with text relocations. b/20013628 . +neverallow { domain -appdomain } file_type:file execmod; + +neverallow { domain -init } proc:{ file dir } mounton; + +# Ensure that all types assigned to processes are included +# in the domain attribute, so that all allow and neverallow rules +# written on domain are applied to all processes. +# This is achieved by ensuring that it is impossible to transition +# from a domain to a non-domain type and vice versa. +neverallow domain ~domain:process { transition dyntransition }; +neverallow ~domain domain:process { transition dyntransition }; + +# +# Only system_app and system_server should be creating or writing +# their files. The proper way to share files is to setup +# type transitions to a more specific type or assigning a type +# to its parent directory via a file_contexts entry. +# Example type transition: +# mydomain.te:file_type_auto_trans(mydomain, system_data_file, new_file_type) +# +neverallow { + domain + -system_server + -system_app + -init + -installd # for relabelfrom and unlink, check for this in explicit neverallow +} system_data_file:file no_w_file_perms; +# do not grant anything greater than r_file_perms and relabelfrom unlink +# to installd +neverallow installd system_data_file:file ~{ r_file_perms relabelfrom unlink }; + +# respect system_app sandboxes +neverallow { + domain + -system_app # its own sandbox + -system_server #populate com.android.providers.settings/databases/settings.db. + -installd # creation of app sandbox +} system_app_data_file:dir_file_class_set { create unlink open }; + +# Services should respect app sandboxes +neverallow { + domain + -appdomain + -installd # creation of sandbox +} app_data_file:dir_file_class_set { create unlink }; + +# +# Only these domains should transition to shell domain. This domain is +# permissible for the "shell user". If you need a process to exec a shell +# script with differing privilege, define a domain and set up a transition. +# +neverallow { + domain + -adbd + -init + -runas + -zygote +} shell:process { transition dyntransition }; + +# Minimize read access to shell- or app-writable symlinks. +# This is to prevent malicious symlink attacks. +neverallow { + domain + -appdomain + -installd + -uncrypt # TODO: see if we can remove +} app_data_file:lnk_file read; + +neverallow { + domain + -shell + userdebug_or_eng(`-uncrypt') + -installd +} shell_data_file:lnk_file read; + +# In addition to the symlink reading restrictions above, restrict +# write access to shell owned directories. The /data/local/tmp +# directory is untrustworthy, and non-whitelisted domains should +# not be trusting any content in those directories. +neverallow { + domain + -adbd + -dumpstate + -installd + -init + -shell + -vold + -su +} shell_data_file:dir no_w_dir_perms; + +neverallow { + domain + -adbd + -appdomain + -dumpstate + -init + -installd + -system_server # why? + userdebug_or_eng(`-uncrypt') +} shell_data_file:dir { open search }; + +# Same as above for /data/local/tmp files. We allow shell files +# to be passed around by file descriptor, but not directly opened. +neverallow { + domain + -adbd + -appdomain + -dumpstate + -installd + userdebug_or_eng(`-uncrypt') +} shell_data_file:file open; + +# servicemanager is the only process which handles list request +neverallow * ~servicemanager:service_manager list; + +# only service_manager_types can be added to service_manager +neverallow * ~service_manager_type:service_manager { add find }; + +# Prevent assigning non property types to properties +neverallow * ~property_type:property_service set; + +# Domain types should never be assigned to any files other +# than the /proc/pid files associated with a process. The +# executable file used to enter a domain should be labeled +# with its own _exec type, not with the domain type. +# Conventionally, this looks something like: +# $ cat mydaemon.te +# type mydaemon, domain; +# type mydaemon_exec, exec_type, file_type; +# init_daemon_domain(mydaemon) +# $ grep mydaemon file_contexts +# /system/bin/mydaemon -- u:object_r:mydaemon_exec:s0 +neverallow * domain:file { execute execute_no_trans entrypoint }; + +# Do not allow access to the generic debugfs label. This is too broad. +# Instead, if access to part of debugfs is desired, it should have a +# more specific label. +# TODO: fix system_server and dumpstate +neverallow { domain -init -system_server -dumpstate } debugfs:file no_rw_file_perms; + +neverallow { + domain + -init + -recovery + -sdcardd + -vold +} fuse_device:chr_file open; +neverallow { + domain + -dumpstate + -init + -priv_app + -recovery + -sdcardd + -shell # Restricted by shell.te to only getattr + -system_server + -ueventd + -vold +} fuse_device:chr_file *; + +# Enforce restrictions on kernel module origin. +# Do not allow kernel module loading except from system, +# vendor, and boot partitions. +neverallow * ~{ system_file rootfs }:system module_load;
diff --git a/sepolicy/domain_deprecated.te b/sepolicy/domain_deprecated.te new file mode 100644 index 0000000..2a35bcf --- /dev/null +++ b/sepolicy/domain_deprecated.te
@@ -0,0 +1,68 @@ +# rules removed from the domain attribute + +# Read access to properties mapping. +allow domain_deprecated kernel:fd use; +allow domain_deprecated tmpfs:file { read getattr }; +allow domain_deprecated tmpfs:lnk_file { read getattr }; + +# Search /storage/emulated tmpfs mount. +allow domain_deprecated tmpfs:dir r_dir_perms; + +# Inherit or receive open files from others. +allow domain_deprecated system_server:fd use; + +# Connect to adbd and use a socket transferred from it. +# This is used for e.g. adb backup/restore. +allow domain_deprecated adbd:unix_stream_socket connectto; +allow domain_deprecated adbd:fd use; +allow domain_deprecated adbd:unix_stream_socket { getattr getopt ioctl read write shutdown }; + +# Root fs. +allow domain_deprecated rootfs:dir r_dir_perms; +allow domain_deprecated rootfs:file r_file_perms; +allow domain_deprecated rootfs:lnk_file r_file_perms; + +# Device accesses. +allow domain_deprecated device:file read; + +# System file accesses. +allow domain_deprecated system_file:dir r_dir_perms; +allow domain_deprecated system_file:file r_file_perms; +allow domain_deprecated system_file:lnk_file r_file_perms; + +# Read files already opened under /data. +allow domain_deprecated system_data_file:file { getattr read }; +allow domain_deprecated system_data_file:lnk_file r_file_perms; + +# Read apk files under /data/app. +allow domain_deprecated apk_data_file:dir { getattr search }; +allow domain_deprecated apk_data_file:file r_file_perms; +allow domain_deprecated apk_data_file:lnk_file r_file_perms; + +# Read /data/dalvik-cache. +allow domain_deprecated dalvikcache_data_file:dir { search getattr }; +allow domain_deprecated dalvikcache_data_file:file r_file_perms; + +# Read already opened /cache files. +allow domain_deprecated cache_file:dir r_dir_perms; +allow domain_deprecated cache_file:file { getattr read }; +allow domain_deprecated cache_file:lnk_file r_file_perms; + +#Allow access to ion memory allocation device +allow domain_deprecated ion_device:chr_file rw_file_perms; + +# Read access to pseudo filesystems. +r_dir_file(domain_deprecated, proc) +r_dir_file(domain_deprecated, sysfs) +r_dir_file(domain_deprecated, inotify) +r_dir_file(domain_deprecated, cgroup) +r_dir_file(domain_deprecated, proc_meminfo) +r_dir_file(domain_deprecated, proc_net) + +# Get SELinux enforcing status. +allow domain_deprecated selinuxfs:dir r_dir_perms; +allow domain_deprecated selinuxfs:file r_file_perms; + +# World readable asec image contents +allow domain_deprecated asec_public_file:file r_file_perms; +allow domain_deprecated { asec_public_file asec_apk_file }:dir r_dir_perms;
diff --git a/sepolicy/drmserver.te b/sepolicy/drmserver.te new file mode 100644 index 0000000..3b654cc --- /dev/null +++ b/sepolicy/drmserver.te
@@ -0,0 +1,55 @@ +# drmserver - DRM service +type drmserver, domain, domain_deprecated; +type drmserver_exec, exec_type, file_type; + +init_daemon_domain(drmserver) +typeattribute drmserver mlstrustedsubject; + +net_domain(drmserver) + +# Perform Binder IPC to system server. +binder_use(drmserver) +binder_call(drmserver, system_server) +binder_call(drmserver, appdomain) +binder_service(drmserver) + +# Perform Binder IPC to mediaserver +binder_call(drmserver, mediaserver) + +allow drmserver sdcard_type:dir search; +allow drmserver drm_data_file:dir create_dir_perms; +allow drmserver drm_data_file:file create_file_perms; +allow drmserver tee_device:chr_file rw_file_perms; +allow drmserver app_data_file:file { read write getattr }; +allow drmserver sdcard_type:file { read write getattr }; +r_dir_file(drmserver, efs_file) + +type drmserver_socket, file_type; + +# /data/app/tlcd_sock socket file. +# Clearly, /data/app is the most logical place to create a socket. Not. +allow drmserver apk_data_file:dir rw_dir_perms; +type_transition drmserver apk_data_file:sock_file drmserver_socket; +allow drmserver drmserver_socket:sock_file create_file_perms; +allow drmserver tee:unix_stream_socket connectto; +# Delete old socket file if present. +allow drmserver apk_data_file:sock_file unlink; + +# After taking a video, drmserver looks at the video file. +r_dir_file(drmserver, media_rw_data_file) + +# Read resources from open apk files passed over Binder. +allow drmserver apk_data_file:file { read getattr }; +allow drmserver asec_apk_file:file { read getattr }; + +# Read /data/data/com.android.providers.telephony files passed over Binder. +allow drmserver radio_data_file:file { read getattr }; + +# /oem access +allow drmserver oemfs:dir search; +allow drmserver oemfs:file r_file_perms; + +allow drmserver drmserver_service:service_manager { add find }; +allow drmserver permission_service:service_manager find; + +selinux_check_access(drmserver)
diff --git a/sepolicy/dumpstate.te b/sepolicy/dumpstate.te new file mode 100644 index 0000000..4bb12c3 --- /dev/null +++ b/sepolicy/dumpstate.te
@@ -0,0 +1,147 @@ +# dumpstate +type dumpstate, domain, domain_deprecated, mlstrustedsubject; +type dumpstate_exec, exec_type, file_type; + +init_daemon_domain(dumpstate) +net_domain(dumpstate) +binder_use(dumpstate) + +# Allow setting process priority, protect from OOM killer, and dropping +# privileges by switching UID / GID +allow dumpstate self:capability { setuid setgid sys_resource }; + +# Allow dumpstate to scan through /proc/pid for all processes +r_dir_file(dumpstate, domain) + +allow dumpstate self:capability { + # Send signals to processes + kill + # Run iptables + net_raw + net_admin +}; + +# Allow executing files on system, such as: +# /system/bin/toolbox +# /system/bin/logcat +# /system/bin/dumpsys +allow dumpstate system_file:file execute_no_trans; +allow dumpstate toolbox_exec:file rx_file_perms; + +# Create and write into /data/anr/ +allow dumpstate self:capability { dac_override chown fowner fsetid }; +allow dumpstate anr_data_file:dir rw_dir_perms; +allow dumpstate anr_data_file:file create_file_perms; + +# Allow reading /data/system/uiderrors.txt +# TODO: scope this down. +allow dumpstate system_data_file:file r_file_perms; + +# Read dmesg +allow dumpstate self:capability2 syslog; +allow dumpstate kernel:system syslog_read; + +# Read /sys/fs/pstore/console-ramoops +allow dumpstate pstorefs:dir r_dir_perms; +allow dumpstate pstorefs:file r_file_perms; + +# Get process attributes +allow dumpstate domain:process getattr; + +# Signal java processes to dump their stack +allow dumpstate { appdomain system_server }:process signal; + +# Signal native processes to dump their stack. +# This list comes from native_processes_to_dump in dumpstate/utils.c +allow dumpstate { drmserver mediaserver sdcardd surfaceflinger }:process signal; +# Ask debuggerd for the backtraces of these processes. +allow dumpstate { drmserver mediaserver sdcardd surfaceflinger }:debuggerd dump_backtrace; + +# Execute and transition to the vdc domain +domain_auto_trans(dumpstate, vdc_exec, vdc) + +# Vibrate the device after we're done collecting the bugreport +# /sys/class/timed_output/vibrator/enable +# TODO: create a new file class, instead of allowing write access to all of /sys +allow dumpstate sysfs:file w_file_perms; + +# Other random bits of data we want to collect +allow dumpstate qtaguid_proc:file r_file_perms; +allow dumpstate debugfs:file r_file_perms; +# df for /storage/emulated needs search +allow dumpstate { storage_file block_device }:dir { search getattr }; +allow dumpstate fuse_device:chr_file getattr; +allow dumpstate { dm_device cache_block_device }:blk_file getattr; + +# Allow dumpstate to make binder calls to any binder service +binder_call(dumpstate, binderservicedomain) +binder_call(dumpstate, appdomain) + +# Reading /proc/PID/maps of other processes +allow dumpstate self:capability sys_ptrace; + +# Allow the bugreport service to create a file in +# /data/data/com.android.shell/files/bugreports/bugreport +allow dumpstate shell_data_file:dir create_dir_perms; +allow dumpstate shell_data_file:file create_file_perms; + +# Run a shell. +allow dumpstate shell_exec:file rx_file_perms; + +# For running am and similar framework commands. +# Run /system/bin/app_process. +allow dumpstate zygote_exec:file rx_file_perms; +# Dalvik Compiler JIT. +allow dumpstate ashmem_device:chr_file execute; +allow dumpstate dumpstate_tmpfs:file execute; +allow dumpstate self:process execmem; +# For art. +allow dumpstate dalvikcache_data_file:file execute; +allow dumpstate dalvikcache_data_file:lnk_file r_file_perms; + +# Dumpstate calls screencap, which grabs a screenshot. Needs gpu access +allow dumpstate gpu_device:chr_file rw_file_perms; + +# logd access +read_logd(dumpstate) +control_logd(dumpstate) + +# Read network state info files. +allow dumpstate net_data_file:dir search; +allow dumpstate net_data_file:file r_file_perms; + +# Access /data/tombstones. +allow dumpstate tombstone_data_file:dir r_dir_perms; +allow dumpstate tombstone_data_file:file r_file_perms; + +# Access /cache/recovery +allow dumpstate cache_recovery_file:dir r_dir_perms; +allow dumpstate cache_recovery_file:file r_file_perms; + +# Access /data/misc/recovery +allow dumpstate recovery_data_file:dir r_dir_perms; +allow dumpstate recovery_data_file:file r_file_perms; + +# Access /data/misc/logd +userdebug_or_eng(` + allow dumpstate misc_logd_file:dir r_dir_perms; + allow dumpstate misc_logd_file:file r_file_perms; +') + +allow dumpstate { service_manager_type -gatekeeper_service }:service_manager find; +allow dumpstate servicemanager:service_manager list; + +allow dumpstate devpts:chr_file rw_file_perms; + +# Set properties. +# dumpstate_prop is used to share state with the Shell app. +set_prop(dumpstate, dumpstate_prop) + +# systrace support - allow atrace to run +allow dumpstate debugfs_tracing:dir r_dir_perms; +allow dumpstate debugfs_tracing:file rw_file_perms; +allow dumpstate debugfs_trace_marker:file getattr; +allow dumpstate atrace_exec:file rx_file_perms; + +allow dumpstate proc_interrupts:file r_file_perms; +allow dumpstate proc_zoneinfo:file r_file_perms;
diff --git a/sepolicy/file.te b/sepolicy/file.te new file mode 100644 index 0000000..02112ef --- /dev/null +++ b/sepolicy/file.te
@@ -0,0 +1,239 @@ +# Filesystem types +type labeledfs, fs_type; +type pipefs, fs_type; +type sockfs, fs_type; +type rootfs, fs_type; +type proc, fs_type; +# Security-sensitive proc nodes that should not be writable to most. +type proc_security, fs_type; +type proc_drop_caches, fs_type; +type proc_overcommit_memory, fs_type; +# proc, sysfs, or other nodes that permit configuration of kernel usermodehelpers. +type usermodehelper, fs_type, sysfs_type; +type qtaguid_proc, fs_type, mlstrustedobject; +type proc_bluetooth_writable, fs_type; +type proc_cpuinfo, fs_type; +type proc_interrupts, fs_type; +type proc_iomem, fs_type; +type proc_meminfo, fs_type; +type proc_net, fs_type; +type proc_stat, fs_type; +type proc_sysrq, fs_type; +type proc_timer, fs_type; +type proc_uid_cputime_showstat, fs_type; +type proc_uid_cputime_removeuid, fs_type; +type proc_zoneinfo, fs_type; +type selinuxfs, fs_type, mlstrustedobject; +type cgroup, fs_type, mlstrustedobject; +type sysfs, fs_type, sysfs_type, mlstrustedobject; +type sysfs_uio, sysfs_type, fs_type; +type sysfs_batteryinfo, fs_type, sysfs_type; +type sysfs_bluetooth_writable, fs_type, sysfs_type, mlstrustedobject; +type sysfs_hwrandom, fs_type, sysfs_type; +type sysfs_nfc_power_writable, fs_type, sysfs_type, mlstrustedobject; +type sysfs_wake_lock, fs_type, sysfs_type; +type sysfs_mac_address, fs_type, sysfs_type; +type configfs, fs_type; +# /sys/devices/system/cpu +type sysfs_devices_system_cpu, fs_type, sysfs_type; +# /sys/module/lowmemorykiller +type sysfs_lowmemorykiller, fs_type, sysfs_type; + +type sysfs_thermal, sysfs_type, fs_type; + +type sysfs_zram, fs_type, sysfs_type; +type sysfs_zram_uevent, fs_type, sysfs_type; +type inotify, fs_type, mlstrustedobject; +type devpts, fs_type, mlstrustedobject; +type tmpfs, fs_type; +type shm, fs_type; +type mqueue, fs_type; +type fuse, sdcard_type, fs_type, mlstrustedobject; +type sdcardfs, sdcard_type, fs_type, mlstrustedobject; +type vfat, sdcard_type, fs_type, mlstrustedobject; +typealias fuse alias sdcard_internal; +typealias vfat alias sdcard_external; +type debugfs, fs_type; +type debugfs_trace_marker, fs_type, debugfs_type, mlstrustedobject; +type debugfs_tracing, fs_type, debugfs_type; +type pstorefs, fs_type; +type functionfs, fs_type; +type oemfs, fs_type, contextmount_type; +type usbfs, fs_type; +type binfmt_miscfs, fs_type; +type app_fusefs, fs_type, contextmount_type; + +# File types +type unlabeled, file_type; +# Default type for anything under /system. +type system_file, file_type; +# Type for /system/bin/logcat. +type logcat_exec, exec_type, file_type; +# /cores for coredumps on userdebug / eng builds +type coredump_file, file_type; +# Default type for anything under /data. +type system_data_file, file_type, data_file_type; +# Unencrypted data +type unencrypted_data_file, file_type, data_file_type; +# /data/.layout_version or other installd-created files that +# are created in a system_data_file directory. +type install_data_file, file_type, data_file_type; +# /data/drm - DRM plugin data +type drm_data_file, file_type, data_file_type; +# /data/adb - adb debugging files +type adb_data_file, file_type, data_file_type; +# /data/anr - ANR traces +type anr_data_file, file_type, data_file_type, mlstrustedobject; +# /data/tombstones - core dumps +type tombstone_data_file, file_type, data_file_type; +# /data/app - user-installed apps +type apk_data_file, file_type, data_file_type; +type apk_tmp_file, file_type, data_file_type, mlstrustedobject; +# /data/app-private - forward-locked apps +type apk_private_data_file, file_type, data_file_type; +type apk_private_tmp_file, file_type, data_file_type, mlstrustedobject; +# /data/dalvik-cache +type dalvikcache_data_file, file_type, data_file_type; +# /data/resource-cache +type resourcecache_data_file, file_type, data_file_type; +# /data/local - writable by shell +type shell_data_file, file_type, data_file_type, mlstrustedobject; +# /data/property +type property_data_file, file_type, data_file_type; +# /data/bootchart +type bootchart_data_file, file_type, data_file_type; +# /data/system/heapdump +type heapdump_data_file, file_type, data_file_type, mlstrustedobject; +# /data/nativetest +type nativetest_data_file, file_type, data_file_type; + +# Mount locations managed by vold +type mnt_media_rw_file, file_type; +type mnt_user_file, file_type; +type mnt_expand_file, file_type; +type storage_file, file_type; + +# Label for storage dirs which are just mount stubs +type mnt_media_rw_stub_file, file_type; +type storage_stub_file, file_type; + +# /postinstall: Mount point used by update_engine to run postinstall. +type postinstall_mnt_dir, file_type; +# Files inside the /postinstall mountpoint are all labeled as postinstall_file. +type postinstall_file, file_type; + +# /data/misc subdirectories +type adb_keys_file, file_type, data_file_type; +type audio_data_file, file_type, data_file_type; +type bluetooth_data_file, file_type, data_file_type; +type bootstat_data_file, file_type, data_file_type; +type boottrace_data_file, file_type, data_file_type; +type camera_data_file, file_type, data_file_type; +type gatekeeper_data_file, file_type, data_file_type; +type keychain_data_file, file_type, data_file_type; +type keystore_data_file, file_type, data_file_type; +type media_data_file, file_type, data_file_type; +type media_rw_data_file, file_type, data_file_type, mlstrustedobject; +type misc_user_data_file, file_type, data_file_type; +type net_data_file, file_type, data_file_type; +type nfc_data_file, file_type, data_file_type; +type radio_data_file, file_type, data_file_type, mlstrustedobject; +type recovery_data_file, file_type, data_file_type; +type shared_relro_file, file_type, data_file_type; +type systemkeys_data_file, file_type, data_file_type; +type vpn_data_file, file_type, data_file_type; +type wifi_data_file, file_type, data_file_type; +type zoneinfo_data_file, file_type, data_file_type; +type vold_data_file, file_type, data_file_type; +type perfprofd_data_file, file_type, data_file_type, mlstrustedobject; +# /data/misc/trace for method traces on userdebug / eng builds +type method_trace_data_file, file_type, data_file_type, mlstrustedobject; + +# Compatibility with type names used in vanilla Android 4.3 and 4.4. +typealias audio_data_file alias audio_firmware_file; +# /data/data subdirectories - app sandboxes +type app_data_file, file_type, data_file_type; +# /data/data subdirectory for system UID apps. +type system_app_data_file, file_type, data_file_type, mlstrustedobject; +# Compatibility with type name used in Android 4.3 and 4.4. +typealias app_data_file alias platform_app_data_file; +typealias app_data_file alias download_file; +# Default type for anything under /cache +type cache_file, file_type, mlstrustedobject; +# Type for /cache/.*\.{data|restore} and default +# type for anything under /cache/backup +type cache_backup_file, file_type, mlstrustedobject; +# Type for anything under /cache/recovery +type cache_recovery_file, file_type, mlstrustedobject; +# Default type for anything under /efs +type efs_file, file_type; +# Type for wallpaper file. +type wallpaper_file, file_type, mlstrustedobject; +# /mnt/asec +type asec_apk_file, file_type, data_file_type, mlstrustedobject; +# Elements of asec files (/mnt/asec) that are world readable +type asec_public_file, file_type, data_file_type; +# /data/app-asec +type asec_image_file, file_type, data_file_type; +# /data/backup and /data/secure/backup +type backup_data_file, file_type, data_file_type, mlstrustedobject; +# All devices have bluetooth efs files. But they +# vary per device, so this type is used in per +# device policy +type bluetooth_efs_file, file_type; +# Type for fingerprint template file. +type fingerprintd_data_file, file_type, data_file_type; +# Type for appfuse file. +type app_fuse_file, file_type, data_file_type, mlstrustedobject; + +# Socket types +type adbd_socket, file_type; +type bluetooth_socket, file_type; +type dnsproxyd_socket, file_type, mlstrustedobject; +type dumpstate_socket, file_type; +type fwmarkd_socket, file_type, mlstrustedobject; +type installd_socket, file_type; +type lmkd_socket, file_type; +type logd_socket, file_type, mlstrustedobject; +type logdr_socket, file_type, mlstrustedobject; +type logdw_socket, file_type, mlstrustedobject; +type mdns_socket, file_type; +type mdnsd_socket, file_type, mlstrustedobject; +type misc_logd_file, file_type; +type mtpd_socket, file_type; +type netd_socket, file_type; +type property_socket, file_type, mlstrustedobject; +type racoon_socket, file_type; +type rild_socket, file_type; +type rild_debug_socket, file_type; +type system_wpa_socket, file_type; +type system_ndebug_socket, file_type; +type vold_socket, file_type; +type wpa_socket, file_type; +type zygote_socket, file_type; +type sap_uim_socket, file_type; +# UART (for GPS) control proc file +type gps_control, file_type; + +# property_contexts file +type property_contexts, file_type; + +# Allow files to be created in their appropriate filesystems. +allow fs_type self:filesystem associate; +allow sysfs_type sysfs:filesystem associate; +allow debugfs_type { debugfs debugfs_tracing }:filesystem associate; +allow file_type labeledfs:filesystem associate; +allow file_type tmpfs:filesystem associate; +allow file_type rootfs:filesystem associate; +allow dev_type tmpfs:filesystem associate; +allow app_fuse_file app_fusefs:filesystem associate; +allow postinstall_file self:filesystem associate; + +# It's a bug to assign the file_type attribute and fs_type attribute +# to any type. Do not allow it. +# +# For example, the following is a bug: +# type apk_data_file, file_type, data_file_type, fs_type; +# Should be: +# type apk_data_file, file_type, data_file_type; +neverallow fs_type file_type:filesystem associate;
diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts new file mode 100644 index 0000000..39c006d --- /dev/null +++ b/sepolicy/file_contexts
@@ -0,0 +1,350 @@ +########################################### +# Root +/ u:object_r:rootfs:s0 + +# Data files +/adb_keys u:object_r:adb_keys_file:s0 +/build\.prop u:object_r:rootfs:s0 +/default\.prop u:object_r:rootfs:s0 +/fstab\..* u:object_r:rootfs:s0 +/init\..* u:object_r:rootfs:s0 +/res(/.*)? u:object_r:rootfs:s0 +/selinux_version u:object_r:rootfs:s0 +/ueventd\..* u:object_r:rootfs:s0 +/verity_key u:object_r:rootfs:s0 + +# Executables +/charger u:object_r:rootfs:s0 +/init u:object_r:init_exec:s0 +/sbin(/.*)? u:object_r:rootfs:s0 + +# Empty directories +/lost\+found u:object_r:rootfs:s0 +/acct u:object_r:cgroup:s0 +/config u:object_r:rootfs:s0 +/mnt u:object_r:tmpfs:s0 +/postinstall u:object_r:postinstall_mnt_dir:s0 +/proc u:object_r:rootfs:s0 +/root u:object_r:rootfs:s0 +/sys u:object_r:sysfs:s0 + +# Symlinks +/d u:object_r:rootfs:s0 +/etc u:object_r:rootfs:s0 +/sdcard u:object_r:rootfs:s0 + +# SELinux policy files +/file_contexts\.bin u:object_r:rootfs:s0 +/property_contexts u:object_r:property_contexts:s0 +/seapp_contexts u:object_r:rootfs:s0 +/sepolicy u:object_r:rootfs:s0 +/service_contexts u:object_r:rootfs:s0 + +########################## +# Devices +# +/dev(/.*)? u:object_r:device:s0 +/dev/akm8973.* u:object_r:sensors_device:s0 +/dev/accelerometer u:object_r:sensors_device:s0 +/dev/adf[0-9]* u:object_r:graphics_device:s0 +/dev/adf-interface[0-9]*\.[0-9]* u:object_r:graphics_device:s0 +/dev/adf-overlay-engine[0-9]*\.[0-9]* u:object_r:graphics_device:s0 +/dev/alarm u:object_r:alarm_device:s0 +/dev/android_adb.* u:object_r:adb_device:s0 +/dev/ashmem u:object_r:ashmem_device:s0 +/dev/audio.* u:object_r:audio_device:s0 +/dev/binder u:object_r:binder_device:s0 +/dev/block(/.*)? u:object_r:block_device:s0 +/dev/block/dm-[0-9]+ u:object_r:dm_device:s0 +/dev/block/loop[0-9]* u:object_r:loop_device:s0 +/dev/block/vold/.+ u:object_r:vold_device:s0 +/dev/block/ram[0-9]* u:object_r:ram_device:s0 +/dev/block/zram[0-9]* u:object_r:ram_device:s0 +/dev/bus/usb(.*)? u:object_r:usb_device:s0 +/dev/cam u:object_r:video_device:s0 +/dev/console u:object_r:console_device:s0 +/dev/cpuctl(/.*)? u:object_r:cpuctl_device:s0 +/dev/device-mapper u:object_r:dm_device:s0 +/dev/eac u:object_r:audio_device:s0 +/dev/fscklogs(/.*)? u:object_r:fscklogs:s0 +/dev/full u:object_r:full_device:s0 +/dev/fuse u:object_r:fuse_device:s0 +/dev/graphics(/.*)? u:object_r:graphics_device:s0 +/dev/hw_random u:object_r:hw_random_device:s0 +/dev/i2c-[0-9]+ u:object_r:i2c_device:s0 +/dev/input(/.*) u:object_r:input_device:s0 +/dev/iio:device[0-9]+ u:object_r:iio_device:s0 +/dev/ion u:object_r:ion_device:s0 +/dev/kmem u:object_r:kmem_device:s0 +/dev/log(/.*)? u:object_r:log_device:s0 +/dev/mem u:object_r:kmem_device:s0 +/dev/modem.* u:object_r:radio_device:s0 +/dev/mtd(/.*)? u:object_r:mtd_device:s0 +/dev/mtp_usb u:object_r:mtp_device:s0 +/dev/pmsg0 u:object_r:pmsg_device:s0 +/dev/pn544 u:object_r:nfc_device:s0 +/dev/ppp u:object_r:ppp_device:s0 +/dev/ptmx u:object_r:ptmx_device:s0 +/dev/pvrsrvkm u:object_r:gpu_device:s0 +/dev/kmsg u:object_r:kmsg_device:s0 +/dev/null u:object_r:null_device:s0 +/dev/nvhdcp1 u:object_r:video_device:s0 +/dev/random u:object_r:random_device:s0 +/dev/rpmsg-omx[0-9] u:object_r:rpmsg_device:s0 +/dev/rproc_user u:object_r:rpmsg_device:s0 +/dev/rtc[0-9] u:object_r:rtc_device:s0 +/dev/snd(/.*)? u:object_r:audio_device:s0 +/dev/socket(/.*)? u:object_r:socket_device:s0 +/dev/socket/adbd u:object_r:adbd_socket:s0 +/dev/socket/sap_uim_socket[0-9] u:object_r:sap_uim_socket:s0 +/dev/socket/cryptd u:object_r:vold_socket:s0 +/dev/socket/dnsproxyd u:object_r:dnsproxyd_socket:s0 +/dev/socket/dumpstate u:object_r:dumpstate_socket:s0 +/dev/socket/fwmarkd u:object_r:fwmarkd_socket:s0 +/dev/socket/installd u:object_r:installd_socket:s0 +/dev/socket/lmkd u:object_r:lmkd_socket:s0 +/dev/socket/logd u:object_r:logd_socket:s0 +/dev/socket/logdr u:object_r:logdr_socket:s0 +/dev/socket/logdw u:object_r:logdw_socket:s0 +/dev/socket/mdns u:object_r:mdns_socket:s0 +/dev/socket/mdnsd u:object_r:mdnsd_socket:s0 +/dev/socket/mtpd u:object_r:mtpd_socket:s0 +/dev/socket/netd u:object_r:netd_socket:s0 +/dev/socket/property_service u:object_r:property_socket:s0 +/dev/socket/racoon u:object_r:racoon_socket:s0 +/dev/socket/rild u:object_r:rild_socket:s0 +/dev/socket/rild-debug u:object_r:rild_debug_socket:s0 +/dev/socket/vold u:object_r:vold_socket:s0 +/dev/socket/wpa_eth[0-9] u:object_r:wpa_socket:s0 +/dev/socket/wpa_wlan[0-9] u:object_r:wpa_socket:s0 +/dev/socket/zygote u:object_r:zygote_socket:s0 +/dev/socket/zygote_secondary u:object_r:zygote_socket:s0 +/dev/spdif_out.* u:object_r:audio_device:s0 +/dev/tegra.* u:object_r:video_device:s0 +/dev/tf_driver u:object_r:tee_device:s0 +/dev/tty u:object_r:owntty_device:s0 +/dev/tty[0-9]* u:object_r:tty_device:s0 +/dev/ttyS[0-9]* u:object_r:serial_device:s0 +/dev/tun u:object_r:tun_device:s0 +/dev/uhid u:object_r:uhid_device:s0 +/dev/uinput u:object_r:uhid_device:s0 +/dev/uio[0-9]* u:object_r:uio_device:s0 +/dev/urandom u:object_r:urandom_device:s0 +/dev/usb_accessory u:object_r:usbaccessory_device:s0 +/dev/vcs[0-9a-z]* u:object_r:vcs_device:s0 +/dev/video[0-9]* u:object_r:video_device:s0 +/dev/watchdog u:object_r:watchdog_device:s0 +/dev/xt_qtaguid u:object_r:qtaguid_device:s0 +/dev/zero u:object_r:zero_device:s0 +/dev/__properties__ u:object_r:properties_device:s0 +############################# +# System files +# +/system(/.*)? u:object_r:system_file:s0 +/system/bin/atrace u:object_r:atrace_exec:s0 +/system/bin/e2fsck -- u:object_r:fsck_exec:s0 +/system/bin/fsck\.f2fs -- u:object_r:fsck_exec:s0 +/system/bin/fsck_msdos -- u:object_r:fsck_exec:s0 +/system/bin/toolbox -- u:object_r:toolbox_exec:s0 +/system/bin/toybox -- u:object_r:toolbox_exec:s0 +/system/bin/logcat -- u:object_r:logcat_exec:s0 +/system/bin/sh -- u:object_r:shell_exec:s0 +/system/bin/run-as -- u:object_r:runas_exec:s0 +/system/bin/bootanimation u:object_r:bootanim_exec:s0 +/system/bin/bootstat u:object_r:bootstat_exec:s0 +/system/bin/app_process32 u:object_r:zygote_exec:s0 +/system/bin/app_process64 u:object_r:zygote_exec:s0 +/system/bin/servicemanager u:object_r:servicemanager_exec:s0 +/system/bin/surfaceflinger u:object_r:surfaceflinger_exec:s0 +/system/bin/drmserver u:object_r:drmserver_exec:s0 +/system/bin/dumpstate u:object_r:dumpstate_exec:s0 +/system/bin/vold u:object_r:vold_exec:s0 +/system/bin/netd u:object_r:netd_exec:s0 +/system/bin/rild u:object_r:rild_exec:s0 +/system/bin/mediaserver u:object_r:mediaserver_exec:s0 +/system/bin/mdnsd u:object_r:mdnsd_exec:s0 +/system/bin/installd u:object_r:installd_exec:s0 +/system/bin/keystore u:object_r:keystore_exec:s0 +/system/bin/fingerprintd u:object_r:fingerprintd_exec:s0 +/system/bin/gatekeeperd u:object_r:gatekeeperd_exec:s0 +/system/bin/debuggerd u:object_r:debuggerd_exec:s0 +/system/bin/debuggerd64 u:object_r:debuggerd_exec:s0 +/system/bin/wpa_supplicant u:object_r:wpa_exec:s0 +/system/bin/recovery-persist u:object_r:recovery_persist_exec:s0 +/system/bin/recovery-refresh u:object_r:recovery_refresh_exec:s0 +/system/bin/sdcard u:object_r:sdcardd_exec:s0 +/system/bin/dhcpcd u:object_r:dhcp_exec:s0 +/system/bin/dhcpcd-6.8.2 u:object_r:dhcp_exec:s0 +/system/bin/mtpd u:object_r:mtp_exec:s0 +/system/bin/pppd u:object_r:ppp_exec:s0 +/system/bin/tf_daemon u:object_r:tee_exec:s0 +/system/bin/racoon u:object_r:racoon_exec:s0 +/system/xbin/su u:object_r:su_exec:s0 +/system/xbin/perfprofd u:object_r:perfprofd_exec:s0 +/system/bin/dnsmasq u:object_r:dnsmasq_exec:s0 +/system/bin/hostapd u:object_r:hostapd_exec:s0 +/system/bin/clatd u:object_r:clatd_exec:s0 +/system/bin/lmkd u:object_r:lmkd_exec:s0 +/system/bin/inputflinger u:object_r:inputflinger_exec:s0 +/system/bin/logd u:object_r:logd_exec:s0 +/system/bin/uncrypt u:object_r:uncrypt_exec:s0 +/system/bin/update_verifier u:object_r:update_verifier_exec:s0 +/system/bin/logwrapper u:object_r:system_file:s0 +/system/bin/vdc u:object_r:vdc_exec:s0 +/system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0 +/system/bin/dex2oat u:object_r:dex2oat_exec:s0 +# patchoat executable has (essentially) the same requirements as dex2oat. +/system/bin/patchoat u:object_r:dex2oat_exec:s0 +/system/bin/sgdisk u:object_r:sgdisk_exec:s0 +/system/bin/blkid u:object_r:blkid_exec:s0 +/system/bin/tzdatacheck u:object_r:tzdatacheck_exec:s0 +/system/bin/idmap u:object_r:idmap_exec:s0 +/system/bin/update_engine u:object_r:update_engine_exec:s0 +/system/bin/bspatch u:object_r:update_engine_exec:s0 + +############################# +# Vendor files +# +/vendor(/.*)? u:object_r:system_file:s0 + +############################# +# OEM and ODM files +# +/odm(/.*)? u:object_r:system_file:s0 +/oem(/.*)? u:object_r:oemfs:s0 + + +############################# +# Data files +# +# NOTE: When modifying existing label rules, changes may also need to +# propagate to the "Expanded data files" section. +# +/data(/.*)? u:object_r:system_data_file:s0 +/data/.layout_version u:object_r:install_data_file:s0 +/data/unencrypted(/.*)? u:object_r:unencrypted_data_file:s0 +/data/backup(/.*)? u:object_r:backup_data_file:s0 +/data/secure/backup(/.*)? u:object_r:backup_data_file:s0 +/data/system/ndebugsocket u:object_r:system_ndebug_socket:s0 +/data/drm(/.*)? u:object_r:drm_data_file:s0 +/data/resource-cache(/.*)? u:object_r:resourcecache_data_file:s0 +/data/dalvik-cache(/.*)? u:object_r:dalvikcache_data_file:s0 +/data/adb(/.*)? u:object_r:adb_data_file:s0 +/data/anr(/.*)? u:object_r:anr_data_file:s0 +/data/app(/.*)? u:object_r:apk_data_file:s0 +/data/app/[^/]+/oat(/.*)? u:object_r:dalvikcache_data_file:s0 +/data/app/vmdl[^/]+\.tmp(/.*)? u:object_r:apk_tmp_file:s0 +/data/app/vmdl[^/]+\.tmp/oat(/.*)? u:object_r:dalvikcache_data_file:s0 +/data/app-private(/.*)? u:object_r:apk_private_data_file:s0 +/data/app-private/vmdl.*\.tmp(/.*)? u:object_r:apk_private_tmp_file:s0 +/data/tombstones(/.*)? u:object_r:tombstone_data_file:s0 +/data/local/tmp(/.*)? u:object_r:shell_data_file:s0 +/data/media(/.*)? u:object_r:media_rw_data_file:s0 +/data/mediadrm(/.*)? u:object_r:media_data_file:s0 +/data/nativetest(/.*)? u:object_r:nativetest_data_file:s0 +/data/property(/.*)? u:object_r:property_data_file:s0 + +# Misc data +/data/misc/adb(/.*)? u:object_r:adb_keys_file:s0 +/data/misc/audio(/.*)? u:object_r:audio_data_file:s0 +/data/misc/bootstat(/.*)? u:object_r:bootstat_data_file:s0 +/data/misc/boottrace(/.*)? u:object_r:boottrace_data_file:s0 +/data/misc/bluetooth(/.*)? u:object_r:bluetooth_data_file:s0 +/data/misc/bluedroid(/.*)? u:object_r:bluetooth_data_file:s0 +/data/misc/bluedroid/\.a2dp_ctrl u:object_r:bluetooth_socket:s0 +/data/misc/bluedroid/\.a2dp_data u:object_r:bluetooth_socket:s0 +/data/misc/camera(/.*)? u:object_r:camera_data_file:s0 +/data/misc/dhcp(/.*)? u:object_r:dhcp_data_file:s0 +/data/misc/dhcp-6.8.2(/.*)? u:object_r:dhcp_data_file:s0 +/data/misc/gatekeeper(/.*)? u:object_r:gatekeeper_data_file:s0 +/data/misc/keychain(/.*)? u:object_r:keychain_data_file:s0 +/data/misc/keystore(/.*)? u:object_r:keystore_data_file:s0 +/data/misc/logd(/.*)? u:object_r:misc_logd_file:s0 +/data/misc/media(/.*)? u:object_r:media_data_file:s0 +/data/misc/net(/.*)? u:object_r:net_data_file:s0 +/data/misc/recovery(/.*)? u:object_r:recovery_data_file:s0 +/data/misc/shared_relro(/.*)? u:object_r:shared_relro_file:s0 +/data/misc/sms(/.*)? u:object_r:radio_data_file:s0 +/data/misc/systemkeys(/.*)? u:object_r:systemkeys_data_file:s0 +/data/misc/user(/.*)? u:object_r:misc_user_data_file:s0 +/data/misc/vpn(/.*)? u:object_r:vpn_data_file:s0 +/data/misc/wifi(/.*)? u:object_r:wifi_data_file:s0 +/data/misc/wifi/sockets(/.*)? u:object_r:wpa_socket:s0 +/data/misc/wifi/sockets/wpa_ctrl.* u:object_r:system_wpa_socket:s0 +/data/misc/wifi/hostapd(/.*)? u:object_r:wpa_socket:s0 +/data/misc/zoneinfo(/.*)? u:object_r:zoneinfo_data_file:s0 +/data/misc/vold(/.*)? u:object_r:vold_data_file:s0 +/data/misc/perfprofd(/.*)? u:object_r:perfprofd_data_file:s0 +/data/misc/update_engine(/.*)? u:object_r:update_engine_data_file:s0 +/data/system/heapdump(/.*)? u:object_r:heapdump_data_file:s0 +/data/misc/trace(/.*)? u:object_r:method_trace_data_file:s0 + +# Fingerprint data +/data/system/users/[0-9]+/fpdata(/.*)? u:object_r:fingerprintd_data_file:s0 + +# Bootchart data +/data/bootchart(/.*)? u:object_r:bootchart_data_file:s0 + +############################# +# Expanded data files +# +/mnt/expand(/.*)? u:object_r:mnt_expand_file:s0 +/mnt/expand/[^/]+(/.*)? u:object_r:system_data_file:s0 +/mnt/expand/[^/]+/app(/.*)? u:object_r:apk_data_file:s0 +/mnt/expand/[^/]+/app/[^/]+/oat(/.*)? u:object_r:dalvikcache_data_file:s0 +/mnt/expand/[^/]+/app/vmdl[^/]+\.tmp(/.*)? u:object_r:apk_tmp_file:s0 +/mnt/expand/[^/]+/app/vmdl[^/]+\.tmp/oat(/.*)? u:object_r:dalvikcache_data_file:s0 +/mnt/expand/[^/]+/local/tmp(/.*)? u:object_r:shell_data_file:s0 +/mnt/expand/[^/]+/media(/.*)? u:object_r:media_rw_data_file:s0 +/mnt/expand/[^/]+/misc/vold(/.*)? u:object_r:vold_data_file:s0 + +# coredump directory for userdebug/eng devices +/cores(/.*)? u:object_r:coredump_file:s0 + +# Wallpaper file for other users +/data/system/users/[0-9]+/wallpaper u:object_r:wallpaper_file:s0 +############################# +# efs files +# +/efs(/.*)? u:object_r:efs_file:s0 +############################# +# Cache files +# +/cache(/.*)? u:object_r:cache_file:s0 +/cache/.*\.data u:object_r:cache_backup_file:s0 +/cache/.*\.restore u:object_r:cache_backup_file:s0 +# LocalTransport (backup) uses this directory +/cache/backup(/.*)? u:object_r:cache_backup_file:s0 +/cache/recovery(/.*)? u:object_r:cache_recovery_file:s0 +############################# +# sysfs files +# +/sys/devices/platform/nfc-power/nfc_power -- u:object_r:sysfs_nfc_power_writable:s0 +/sys/devices/system/cpu(/.*)? u:object_r:sysfs_devices_system_cpu:s0 +/sys/devices/virtual/block/zram\d+(/.*)? u:object_r:sysfs_zram:s0 +/sys/devices/virtual/block/zram\d+/uevent u:object_r:sysfs_zram_uevent:s0 +/sys/devices/virtual/misc/hw_random(/.*)? u:object_r:sysfs_hwrandom:s0 +/sys/power/wake_lock -- u:object_r:sysfs_wake_lock:s0 +/sys/power/wake_unlock -- u:object_r:sysfs_wake_lock:s0 +/sys/kernel/uevent_helper -- u:object_r:usermodehelper:s0 +/sys/module/lowmemorykiller(/.*)? -- u:object_r:sysfs_lowmemorykiller:s0 + +############################# +# debugfs files +# +/sys/kernel/debug/tracing(/.*)? u:object_r:debugfs_tracing:s0 +/sys/kernel/debug/tracing/trace_marker u:object_r:debugfs_trace_marker:s0 + +############################# +# asec containers +/mnt/asec(/.*)? u:object_r:asec_apk_file:s0 +/mnt/asec/[^/]+/[^/]+\.zip u:object_r:asec_public_file:s0 +/mnt/asec/[^/]+/lib(/.*)? u:object_r:asec_public_file:s0 +/data/app-asec(/.*)? u:object_r:asec_image_file:s0 + +############################# +# external storage +/mnt/media_rw(/.*)? u:object_r:mnt_media_rw_file:s0 +/mnt/user(/.*)? u:object_r:mnt_user_file:s0 +/mnt/runtime(/.*)? u:object_r:storage_file:s0 +/storage(/.*)? u:object_r:storage_file:s0
diff --git a/sepolicy/file_contexts_asan b/sepolicy/file_contexts_asan new file mode 100644 index 0000000..5813d32 --- /dev/null +++ b/sepolicy/file_contexts_asan
@@ -0,0 +1,4 @@ +/data/lib(/.*)? u:object_r:system_file:s0 +/data/lib64(/.*)? u:object_r:system_file:s0 +/data/vendor/lib(/.*)? u:object_r:system_file:s0 +/data/vendor/lib64(/.*)? u:object_r:system_file:s0
diff --git a/sepolicy/fingerprintd.te b/sepolicy/fingerprintd.te new file mode 100644 index 0000000..1c0ab1c --- /dev/null +++ b/sepolicy/fingerprintd.te
@@ -0,0 +1,23 @@ +type fingerprintd, domain, domain_deprecated; +type fingerprintd_exec, exec_type, file_type; + +# fingerprintd +init_daemon_domain(fingerprintd) +binder_use(fingerprintd) + +# need to find KeyStore and add self +allow fingerprintd fingerprintd_service:service_manager { add find }; + +# allow HAL module to read dir contents +allow fingerprintd fingerprintd_data_file:file { create_file_perms }; + +# allow HAL module to read/write/unlink contents of this dir +allow fingerprintd fingerprintd_data_file:dir rw_dir_perms; + +# Need to add auth tokens to KeyStore +use_keystore(fingerprintd) +allow fingerprintd keystore:keystore_key { add_auth }; + +# For permissions checking +binder_call(fingerprintd, system_server); +allow fingerprintd permission_service:service_manager find;
diff --git a/sepolicy/fs_use b/sepolicy/fs_use new file mode 100644 index 0000000..4bd1112 --- /dev/null +++ b/sepolicy/fs_use
@@ -0,0 +1,23 @@ +# Label inodes via getxattr. +fs_use_xattr yaffs2 u:object_r:labeledfs:s0; +fs_use_xattr jffs2 u:object_r:labeledfs:s0; +fs_use_xattr ext2 u:object_r:labeledfs:s0; +fs_use_xattr ext3 u:object_r:labeledfs:s0; +fs_use_xattr ext4 u:object_r:labeledfs:s0; +fs_use_xattr xfs u:object_r:labeledfs:s0; +fs_use_xattr btrfs u:object_r:labeledfs:s0; +fs_use_xattr f2fs u:object_r:labeledfs:s0; +fs_use_xattr squashfs u:object_r:labeledfs:s0; + +# Label inodes from task label. +fs_use_task pipefs u:object_r:pipefs:s0; +fs_use_task sockfs u:object_r:sockfs:s0; + +# Label inodes from combination of task label and fs label. +# Define type_transition rules if you want per-domain types. +fs_use_trans devpts u:object_r:devpts:s0; +fs_use_trans tmpfs u:object_r:tmpfs:s0; +fs_use_trans devtmpfs u:object_r:device:s0; +fs_use_trans shm u:object_r:shm:s0; +fs_use_trans mqueue u:object_r:mqueue:s0; +
diff --git a/sepolicy/fsck.te b/sepolicy/fsck.te new file mode 100644 index 0000000..d5a6db1 --- /dev/null +++ b/sepolicy/fsck.te
@@ -0,0 +1,47 @@ +# Any fsck program run by init +type fsck, domain, domain_deprecated; +type fsck_exec, exec_type, file_type; + +init_daemon_domain(fsck) + +# /dev/__null__ created by init prior to policy load, +# open fd inherited by fsck. +allow fsck tmpfs:chr_file { read write ioctl }; + +# Inherit and use pty created by android_fork_execvp_ext(). +allow fsck devpts:chr_file { read write ioctl getattr }; + +# Allow stdin/out back to vold +allow fsck vold:fd use; +allow fsck vold:fifo_file { read write getattr }; + +# Run fsck on certain block devices +allow fsck block_device:dir search; +allow fsck userdata_block_device:blk_file rw_file_perms; +allow fsck cache_block_device:blk_file rw_file_perms; +allow fsck dm_device:blk_file rw_file_perms; + +# fsck performs a stat() on swap to verify that it is a valid +# swap device before setting the EXT2_MF_SWAP mount flag. +allow fsck swap_block_device:blk_file getattr; + +### +### neverallow rules +### + +# fsck should never be run on these block devices +neverallow fsck { + boot_block_device + frp_block_device + metadata_block_device + recovery_block_device + root_block_device + swap_block_device + system_block_device + vold_device +}:blk_file no_rw_file_perms; + +# Only allow entry from init or vold via fsck binaries +neverallow { domain -init -vold } fsck:process transition; +neverallow * fsck:process dyntransition; +neverallow fsck { file_type fs_type -fsck_exec }:file entrypoint;
diff --git a/sepolicy/fsck_untrusted.te b/sepolicy/fsck_untrusted.te new file mode 100644 index 0000000..00faa20 --- /dev/null +++ b/sepolicy/fsck_untrusted.te
@@ -0,0 +1,36 @@ +# Any fsck program run on untrusted block devices +type fsck_untrusted, domain, domain_deprecated; + +# Inherit and use pty created by android_fork_execvp_ext(). +allow fsck_untrusted devpts:chr_file { read write ioctl getattr }; + +# Allow stdin/out back to vold +allow fsck_untrusted vold:fd use; +allow fsck_untrusted vold:fifo_file { read write getattr }; + +# Run fsck on vold block devices +allow fsck_untrusted block_device:dir search; +allow fsck_untrusted vold_device:blk_file rw_file_perms; + +### +### neverallow rules +### + +# Untrusted fsck should never be run on block devices holding sensitive data +neverallow fsck_untrusted { + boot_block_device + frp_block_device + metadata_block_device + recovery_block_device + root_block_device + swap_block_device + system_block_device + userdata_block_device + cache_block_device + dm_device +}:blk_file no_rw_file_perms; + +# Only allow entry from vold via fsck binaries +neverallow { domain -vold } fsck_untrusted:process transition; +neverallow * fsck_untrusted:process dyntransition; +neverallow fsck_untrusted { file_type fs_type -fsck_exec }:file entrypoint;
diff --git a/sepolicy/gatekeeperd.te b/sepolicy/gatekeeperd.te new file mode 100644 index 0000000..81d7fdf --- /dev/null +++ b/sepolicy/gatekeeperd.te
@@ -0,0 +1,27 @@ +type gatekeeperd, domain, domain_deprecated; +type gatekeeperd_exec, exec_type, file_type; + +# gatekeeperd +init_daemon_domain(gatekeeperd) +binder_service(gatekeeperd) +binder_use(gatekeeperd) +allow gatekeeperd tee_device:chr_file rw_file_perms; + +# need to find KeyStore and add self +allow gatekeeperd gatekeeper_service:service_manager { add find }; + +# Need to add auth tokens to KeyStore +use_keystore(gatekeeperd) +allow gatekeeperd keystore:keystore_key { add_auth }; + +# For permissions checking +allow gatekeeperd system_server:binder call; +allow gatekeeperd permission_service:service_manager find; +# For parent user ID lookup +allow gatekeeperd user_service:service_manager find; + +# for SID file access +allow gatekeeperd gatekeeper_data_file:dir rw_dir_perms; +allow gatekeeperd gatekeeper_data_file:file create_file_perms; + +neverallow { domain -gatekeeperd } gatekeeper_service:service_manager add;
diff --git a/sepolicy/genfs_contexts b/sepolicy/genfs_contexts new file mode 100644 index 0000000..bb2fea9 --- /dev/null +++ b/sepolicy/genfs_contexts
@@ -0,0 +1,51 @@ +# Label inodes with the fs label. +genfscon rootfs / u:object_r:rootfs:s0 +# proc labeling can be further refined (longest matching prefix). +genfscon proc / u:object_r:proc:s0 +genfscon proc /interrupts u:object_r:proc_interrupts:s0 +genfscon proc /iomem u:object_r:proc_iomem:s0 +genfscon proc /meminfo u:object_r:proc_meminfo:s0 +genfscon proc /net u:object_r:proc_net:s0 +genfscon proc /net/xt_qtaguid/ctrl u:object_r:qtaguid_proc:s0 +genfscon proc /cpuinfo u:object_r:proc_cpuinfo:s0 +genfscon proc /softirqs u:object_r:proc_timer:s0 +genfscon proc /stat u:object_r:proc_stat:s0 +genfscon proc /sysrq-trigger u:object_r:proc_sysrq:s0 +genfscon proc /sys/fs/protected_hardlinks u:object_r:proc_security:s0 +genfscon proc /sys/fs/protected_symlinks u:object_r:proc_security:s0 +genfscon proc /sys/fs/suid_dumpable u:object_r:proc_security:s0 +genfscon proc /sys/kernel/core_pattern u:object_r:usermodehelper:s0 +genfscon proc /sys/kernel/dmesg_restrict u:object_r:proc_security:s0 +genfscon proc /sys/kernel/hotplug u:object_r:usermodehelper:s0 +genfscon proc /sys/kernel/kptr_restrict u:object_r:proc_security:s0 +genfscon proc /sys/kernel/modprobe u:object_r:usermodehelper:s0 +genfscon proc /sys/kernel/modules_disabled u:object_r:proc_security:s0 +genfscon proc /sys/kernel/poweroff_cmd u:object_r:usermodehelper:s0 +genfscon proc /sys/kernel/randomize_va_space u:object_r:proc_security:s0 +genfscon proc /sys/kernel/usermodehelper u:object_r:usermodehelper:s0 +genfscon proc /sys/net u:object_r:proc_net:s0 +genfscon proc /sys/vm/mmap_min_addr u:object_r:proc_security:s0 +genfscon proc /sys/vm/drop_caches u:object_r:proc_drop_caches:s0 +genfscon proc /sys/vm/overcommit_memory u:object_r:proc_overcommit_memory:s0 +genfscon proc /timer_list u:object_r:proc_timer:s0 +genfscon proc /timer_stats u:object_r:proc_timer:s0 +genfscon proc /uid_cputime/show_uid_stat u:object_r:proc_uid_cputime_showstat:s0 +genfscon proc /uid_cputime/remove_uid_range u:object_r:proc_uid_cputime_removeuid:s0 +genfscon proc /zoneinfo u:object_r:proc_zoneinfo:s0 + +# selinuxfs booleans can be individually labeled. +genfscon selinuxfs / u:object_r:selinuxfs:s0 +genfscon cgroup / u:object_r:cgroup:s0 +# sysfs labels can be set by userspace. +genfscon sysfs / u:object_r:sysfs:s0 +genfscon inotifyfs / u:object_r:inotify:s0 +genfscon vfat / u:object_r:vfat:s0 +genfscon debugfs / u:object_r:debugfs:s0 +genfscon tracefs / u:object_r:debugfs_tracing:s0 +genfscon fuse / u:object_r:fuse:s0 +genfscon configfs / u:object_r:configfs:s0 +genfscon sdcardfs / u:object_r:sdcardfs:s0 +genfscon pstore / u:object_r:pstorefs:s0 +genfscon functionfs / u:object_r:functionfs:s0 +genfscon usbfs / u:object_r:usbfs:s0 +genfscon binfmt_misc / u:object_r:binfmt_miscfs:s0
diff --git a/sepolicy/global_macros b/sepolicy/global_macros new file mode 100644 index 0000000..0534e46 --- /dev/null +++ b/sepolicy/global_macros
@@ -0,0 +1,46 @@ +##################################### +# Common groupings of object classes. +# +define(`capability_class_set', `{ capability capability2 }') + +define(`devfile_class_set', `{ chr_file blk_file }') +define(`notdevfile_class_set', `{ file lnk_file sock_file fifo_file }') +define(`file_class_set', `{ devfile_class_set notdevfile_class_set }') +define(`dir_file_class_set', `{ dir file_class_set }') + +define(`socket_class_set', `{ socket tcp_socket udp_socket rawip_socket netlink_socket packet_socket key_socket unix_stream_socket unix_dgram_socket appletalk_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket netlink_iscsi_socket netlink_fib_lookup_socket netlink_connector_socket netlink_netfilter_socket netlink_generic_socket netlink_scsitransport_socket netlink_rdma_socket netlink_crypto_socket }') +define(`dgram_socket_class_set', `{ udp_socket unix_dgram_socket }') +define(`stream_socket_class_set', `{ tcp_socket unix_stream_socket }') +define(`unpriv_socket_class_set', `{ tcp_socket udp_socket unix_stream_socket unix_dgram_socket }') + +define(`ipc_class_set', `{ sem msgq shm ipc }') + +##################################### +# Common groupings of permissions. +# +define(`x_file_perms', `{ getattr execute execute_no_trans }') +define(`r_file_perms', `{ getattr open read ioctl lock }') +define(`w_file_perms', `{ open append write lock }') +define(`rx_file_perms', `{ r_file_perms x_file_perms }') +define(`ra_file_perms', `{ r_file_perms append }') +define(`rw_file_perms', `{ r_file_perms w_file_perms }') +define(`rwx_file_perms', `{ rw_file_perms x_file_perms }') +define(`create_file_perms', `{ create rename setattr unlink rw_file_perms }') + +define(`r_dir_perms', `{ open getattr read search ioctl lock }') +define(`w_dir_perms', `{ open search write add_name remove_name lock }') +define(`ra_dir_perms', `{ r_dir_perms add_name write }') +define(`rw_dir_perms', `{ r_dir_perms w_dir_perms }') +define(`create_dir_perms', `{ create reparent rename rmdir setattr rw_dir_perms }') + +define(`r_ipc_perms', `{ getattr read associate unix_read }') +define(`w_ipc_perms', `{ write unix_write }') +define(`rw_ipc_perms', `{ r_ipc_perms w_ipc_perms }') +define(`create_ipc_perms', `{ create setattr destroy rw_ipc_perms }') + +##################################### +# Common socket permission sets. +define(`rw_socket_perms', `{ ioctl read getattr write setattr lock append bind connect getopt setopt shutdown }') +define(`create_socket_perms', `{ create rw_socket_perms }') +define(`rw_stream_socket_perms', `{ rw_socket_perms listen accept }') +define(`create_stream_socket_perms', `{ create rw_stream_socket_perms }')
diff --git a/sepolicy/hci_attach.te b/sepolicy/hci_attach.te new file mode 100644 index 0000000..543cae1 --- /dev/null +++ b/sepolicy/hci_attach.te
@@ -0,0 +1,9 @@ +type hci_attach, domain, domain_deprecated; +type hci_attach_exec, exec_type, file_type; + +init_daemon_domain(hci_attach) + +allow hci_attach kernel:system module_request; +allow hci_attach hci_attach_dev:chr_file rw_file_perms; +allow hci_attach bluetooth_efs_file:dir r_dir_perms; +allow hci_attach bluetooth_efs_file:file r_file_perms;
diff --git a/sepolicy/healthd.te b/sepolicy/healthd.te new file mode 100644 index 0000000..f54d716 --- /dev/null +++ b/sepolicy/healthd.te
@@ -0,0 +1,48 @@ +# healthd seclabel is specified in init.rc since +# it lives in the rootfs and has no unique file type. +type healthd, domain, domain_deprecated; + +# Write to /dev/kmsg +allow healthd kmsg_device:chr_file rw_file_perms; + +# Read access to pseudo filesystems. +r_dir_file(healthd, sysfs) + +allow healthd self:capability { net_admin sys_tty_config }; +wakelock_use(healthd) +allow healthd self:netlink_kobject_uevent_socket create_socket_perms; +binder_use(healthd) +binder_service(healthd) +binder_call(healthd, system_server) + +# Write to state file. +# TODO: Split into a separate type? +allow healthd sysfs:file write; + +allow healthd sysfs_batteryinfo:file r_file_perms; + +### +### healthd: charger mode +### + +# Read /sys/fs/pstore/console-ramoops +# Don't worry about overly broad permissions for now, as there's +# only one file in /sys/fs/pstore +allow healthd pstorefs:dir r_dir_perms; +allow healthd pstorefs:file r_file_perms; + +allow healthd graphics_device:dir r_dir_perms; +allow healthd graphics_device:chr_file rw_file_perms; +allow healthd input_device:dir r_dir_perms; +allow healthd input_device:chr_file r_file_perms; +allow healthd tty_device:chr_file rw_file_perms; +allow healthd ashmem_device:chr_file execute; +allow healthd self:process execmem; +allow healthd proc_sysrq:file rw_file_perms; +allow healthd self:capability sys_boot; + +allow healthd batteryproperties_service:service_manager { add find }; + +# Healthd needs to tell init to continue the boot +# process when running in charger mode. +set_prop(healthd, system_prop)
diff --git a/sepolicy/hostapd.te b/sepolicy/hostapd.te new file mode 100644 index 0000000..204a0d9 --- /dev/null +++ b/sepolicy/hostapd.te
@@ -0,0 +1,27 @@ +# userspace wifi access points +type hostapd, domain, domain_deprecated; +type hostapd_exec, exec_type, file_type; + +net_domain(hostapd) + +allow hostapd self:capability { net_admin net_raw setuid setgid }; +allow hostapd self:netlink_socket create_socket_perms; +allow hostapd self:netlink_generic_socket create_socket_perms; +allow hostapd self:packet_socket create_socket_perms; +allow hostapd self:netlink_route_socket nlmsg_write; + +allow hostapd wifi_data_file:file rw_file_perms; +allow hostapd wifi_data_file:dir create_dir_perms; +type_transition hostapd wifi_data_file:dir wpa_socket "sockets"; +type_transition hostapd wifi_data_file:dir wpa_socket "hostapd"; +allow hostapd wpa_socket:dir create_dir_perms; +allow hostapd wpa_socket:sock_file create_file_perms; +allow hostapd netd:fd use; +allow hostapd netd:udp_socket { read write }; +allow hostapd netd:fifo_file { read write }; +# TODO: Investigate whether these inherited sockets should be closed on exec. +allow hostapd netd:netlink_kobject_uevent_socket { read write }; +allow hostapd netd:netlink_nflog_socket { read write }; +allow hostapd netd:netlink_route_socket { read write }; +allow hostapd netd:unix_stream_socket { read write }; +allow hostapd netd:unix_dgram_socket { read write };
diff --git a/sepolicy/idmap.te b/sepolicy/idmap.te new file mode 100644 index 0000000..c1b4d0f --- /dev/null +++ b/sepolicy/idmap.te
@@ -0,0 +1,10 @@ +# idmap, when executed by installd +type idmap, domain, domain_deprecated; +type idmap_exec, exec_type, file_type; + +# Use open file to /data/resource-cache file inherited from installd. +allow idmap installd:fd use; +allow idmap resourcecache_data_file:file { getattr read write }; + +# Open and read from target and overlay apk files passed by argument. +allow idmap apk_data_file:file r_file_perms;
diff --git a/sepolicy/init.te b/sepolicy/init.te new file mode 100644 index 0000000..2b64953 --- /dev/null +++ b/sepolicy/init.te
@@ -0,0 +1,369 @@ +# init is its own domain. +type init, domain, domain_deprecated, mlstrustedsubject; +tmpfs_domain(init) + +# The init domain is entered by execing init. +type init_exec, exec_type, file_type; + +# /dev/__null__ node created by init. +allow init tmpfs:chr_file create_file_perms; + +# +# init direct restorecon calls. +# +# /dev/kmsg +allow init tmpfs:chr_file relabelfrom; +allow init kmsg_device:chr_file { write relabelto }; +# /dev/__properties__ +allow init properties_device:dir relabelto; +allow init properties_serial:file { write relabelto }; +allow init property_type:file { create_file_perms relabelto }; +# /dev/socket +allow init { device socket_device }:dir relabelto; +# /dev/device-mapper, /dev/block(/.*)? +allow init tmpfs:{ chr_file blk_file } relabelfrom; +allow init tmpfs:blk_file getattr; +allow init block_device:{ dir blk_file } relabelto; +allow init dm_device:{ chr_file blk_file } relabelto; + +# setrlimit +allow init self:capability sys_resource; + +# Remove /dev/.booting, created before initial policy load or restorecon /dev. +allow init tmpfs:file unlink; + +# Access pty created for fsck. +allow init devpts:chr_file { read write open }; + +# Create /dev/fscklogs files. +allow init fscklogs:file create_file_perms; + +# Access /dev/__null__ node created prior to initial policy load. +allow init tmpfs:chr_file write; + +# Access /dev/console. +allow init console_device:chr_file rw_file_perms; + +# Access /dev/tty0. +allow init tty_device:chr_file rw_file_perms; + +# Call mount(2). +allow init self:capability sys_admin; + +# Create and mount on directories in /. +allow init rootfs:dir create_dir_perms; +allow init { rootfs cache_file cgroup storage_file system_data_file system_file }:dir mounton; + +# Mount on /dev/usb-ffs/adb. +allow init device:dir mounton; + +# Create and remove symlinks in /. +allow init rootfs:lnk_file { create unlink }; + +# Mount debugfs on /sys/kernel/debug. +allow init sysfs:dir mounton; + +# Create cgroups mount points in tmpfs and mount cgroups on them. +allow init tmpfs:dir create_dir_perms; +allow init tmpfs:dir mounton; +allow init cgroup:dir create_dir_perms; +allow init cpuctl_device:dir { create mounton }; + +# /config +allow init configfs:dir mounton; +allow init configfs:dir create_dir_perms; + +# Use tmpfs as /data, used for booting when /data is encrypted +allow init tmpfs:dir relabelfrom; + +# Create directories under /dev/cpuctl after chowning it to system. +allow init self:capability dac_override; + +# Set system clock. +allow init self:capability sys_time; + +allow init self:capability { sys_rawio mknod }; + +# Mounting filesystems from block devices. +allow init dev_type:blk_file r_file_perms; + +# Mounting filesystems. +# Only allow relabelto for types used in context= mount options, +# which should all be assigned the contextmount_type attribute. +# This can be done in device-specific policy via type or typeattribute +# declarations. +allow init fs_type:filesystem ~relabelto; +allow init unlabeled:filesystem ~relabelto; +allow init contextmount_type:filesystem relabelto; + +# Allow read-only access to context= mounted filesystems. +allow init contextmount_type:dir r_dir_perms; +allow init contextmount_type:notdevfile_class_set r_file_perms; + +# restorecon /adb_keys or any other rootfs files and directories to a more +# specific type. +allow init rootfs:{ dir file } relabelfrom; + +# mkdir, symlink, write, rm/rmdir, chown/chmod, restorecon/restorecon_recursive from init.rc files. +# chown/chmod require open+read+setattr required for open()+fchown/fchmod(). +# system/core/init.rc requires at least cache_file and data_file_type. +# init.<board>.rc files often include device-specific types, so +# we just allow all file types except /system files here. +allow init self:capability { chown fowner fsetid }; + +allow init { + file_type + -system_file + -exec_type + -app_data_file + -system_app_data_file +}:dir { create search getattr open read setattr ioctl }; + +allow init { + file_type + -system_file + -exec_type + -keystore_data_file + -app_data_file + -system_app_data_file + -shell_data_file + -vold_data_file + -misc_logd_file +}:dir { write add_name remove_name rmdir relabelfrom }; + +allow init { + file_type + -system_file + -exec_type + -keystore_data_file + -app_data_file + -system_app_data_file + -shell_data_file + -vold_data_file + -misc_logd_file +}:file { create getattr open read write setattr relabelfrom unlink }; + +allow init { + file_type + -system_file + -exec_type + -keystore_data_file + -app_data_file + -system_app_data_file + -shell_data_file + -vold_data_file + -misc_logd_file +}:{ sock_file fifo_file } { create getattr open read setattr relabelfrom unlink }; + +allow init { + file_type + -system_file + -exec_type + -keystore_data_file + -app_data_file + -system_app_data_file + -shell_data_file + -vold_data_file + -misc_logd_file +}:lnk_file { create getattr setattr relabelfrom unlink }; + +allow init {file_type -system_file -exec_type}:dir_file_class_set relabelto; +allow init { sysfs debugfs debugfs_tracing }:{ dir file lnk_file } { getattr relabelfrom }; +allow init { sysfs_type debugfs_type }:{ dir file lnk_file } relabelto; +allow init dev_type:dir create_dir_perms; +allow init dev_type:lnk_file create; + +# Disable tracing by writing to /sys/kernel/debug/tracing/tracing_on +allow init debugfs_tracing:file w_file_perms; + +# chown/chmod on pseudo files. +allow init { fs_type -contextmount_type -sdcard_type -rootfs }:file { open read setattr }; +allow init { fs_type -contextmount_type -sdcard_type -rootfs }:dir { open read setattr search }; + +# chown/chmod on devices. +allow init { dev_type -kmem_device }:chr_file { read open setattr }; + +# Unlabeled file access for upgrades from 4.2. +allow init unlabeled:dir { create_dir_perms relabelfrom }; +allow init unlabeled:notdevfile_class_set { create_file_perms relabelfrom }; + +# Any operation that can modify the kernel ring buffer, e.g. clear +# or a read that consumes the messages that were read. +allow init kernel:system syslog_mod; +allow init self:capability2 syslog; + +# Set usermodehelpers and /proc security settings. +allow init usermodehelper:file rw_file_perms; +allow init proc_security:file rw_file_perms; + +# Write to /proc/sys/kernel/panic_on_oops. +allow init proc:file w_file_perms; + +# Write to /proc/sys/net/ping_group_range and other /proc/sys/net files. +allow init proc_net:file w_file_perms; +allow init self:capability net_admin; + +# Write to /proc/sysrq-trigger. +allow init proc_sysrq:file w_file_perms; + +# Read /proc/stat for bootchart. +allow init proc_stat:file r_file_perms; + +# Reboot. +allow init self:capability sys_boot; + +# Write to sysfs nodes. +allow init sysfs_type:dir r_dir_perms; +allow init sysfs_type:lnk_file read; +allow init sysfs_type:file w_file_perms; + +# disksize +allow init sysfs_zram:file getattr; + +# Transitions to seclabel processes in init.rc +domain_trans(init, rootfs, adbd) +domain_trans(init, rootfs, healthd) +domain_trans(init, rootfs, slideshow) +recovery_only(` + domain_trans(init, rootfs, recovery) +') +domain_trans(init, shell_exec, shell) +domain_trans(init, init_exec, ueventd) +domain_trans(init, init_exec, watchdogd) +# case where logpersistd is actually logcat -f in logd context (nee: logcatd) +userdebug_or_eng(` + domain_auto_trans(init, logcat_exec, logd) +') + +# Init will create /data/misc/logd when the property persist.logd.logpersistd is "logcatd". +# Init will also walk through the directory as part of a recursive restorecon. +allow init misc_logd_file:dir { open create read getattr setattr search }; +allow init misc_logd_file:file { getattr }; + +# Support "adb shell stop" +allow init self:capability kill; +allow init domain:process { sigkill signal }; + +# Init creates keystore's directory on boot, and walks through +# the directory as part of a recursive restorecon. +allow init keystore_data_file:dir { open create read getattr setattr search }; +allow init keystore_data_file:file { getattr }; + +# Init creates vold's directory on boot, and walks through +# the directory as part of a recursive restorecon. +allow init vold_data_file:dir { open create read getattr setattr search }; +allow init vold_data_file:file { getattr }; + +# Init creates /data/local/tmp at boot +allow init shell_data_file:dir { open create read getattr setattr search }; +allow init shell_data_file:file { getattr }; + +# Set UID and GID for services. +allow init self:capability { setuid setgid }; + +# For bootchart to read the /proc/$pid/cmdline file of each process, +# we need to have following line to allow init to have access +# to different domains. +r_dir_file(init, domain) + +# Use setexeccon(), setfscreatecon(), and setsockcreatecon(). +# setexec is for services with seclabel options. +# setfscreate is for labeling directories and socket files. +# setsockcreate is for labeling local/unix domain sockets. +allow init self:process { setexec setfscreate setsockcreate }; + +# Perform SELinux access checks on setting properties. +selinux_check_access(init) + +# Ask the kernel for the new context on services to label their sockets. +allow init kernel:security compute_create; + +# Create sockets for the services. +allow init domain:unix_stream_socket { create bind }; +allow init domain:unix_dgram_socket { create bind }; + +# Create /data/property and files within it. +allow init property_data_file:dir create_dir_perms; +allow init property_data_file:file create_file_perms; + +# Set any property. +allow init property_type:property_service set; + +# Run "ifup lo" to bring up the localhost interface +allow init self:udp_socket { create ioctl }; +allow init self:capability net_raw; + +# This line seems suspect, as it should not really need to +# set scheduling parameters for a kernel domain task. +allow init kernel:process setsched; + +# swapon() needs write access to swap device +# system/core/fs_mgr/fs_mgr.c - fs_mgr_swapon_all +allow init swap_block_device:blk_file rw_file_perms; + +# Read from /dev/hw_random if present. +# system/core/init/init.c - mix_hwrng_into_linux_rng_action +allow init hw_random_device:chr_file r_file_perms; + +# Create and access /dev files without a specific type, +# e.g. /dev/.coldboot_done, /dev/.booting +# TODO: Move these files into their own type unless they are +# only ever accessed by init. +allow init device:file create_file_perms; + +# Access character devices without a specific type, +# e.g. /dev/keychord. +# TODO: Move these devices into their own type unless they +# are only ever accessed by init. +allow init device:chr_file { rw_file_perms setattr }; + +# keychord configuration +allow init self:capability sys_tty_config; + +# Access device mapper for setting up dm-verity +allow init dm_device:chr_file rw_file_perms; +allow init dm_device:blk_file rw_file_perms; + +# Access metadata block device for storing dm-verity state +allow init metadata_block_device:blk_file rw_file_perms; + +# Read /sys/fs/pstore/console-ramoops to detect restarts caused +# by dm-verity detecting corrupted blocks +allow init pstorefs:dir search; +allow init pstorefs:file r_file_perms; +allow init kernel:system syslog_read; + +# linux keyring configuration +allow init init:key { write search setattr }; + +# Allow init to create /data/unencrypted +allow init unencrypted_data_file:dir create_dir_perms; + +# Allow init to write to /proc/sys/vm/overcommit_memory +allow init proc_overcommit_memory:file { write }; + +unix_socket_connect(init, vold, vold) + +### +### neverallow rules +### + +# The init domain is only entered via setcon from the kernel domain, +# never via an exec-based transition. +neverallow domain init:process dyntransition; +neverallow { domain -kernel} init:process transition; +neverallow init { file_type fs_type -init_exec }:file entrypoint; + +# Never read/follow symlinks created by shell or untrusted apps. +neverallow init shell_data_file:lnk_file read; +neverallow init app_data_file:lnk_file read; + +# init should never execute a program without changing to another domain. +neverallow init { file_type fs_type }:file execute_no_trans; + +# Init never adds or uses services via service_manager. +neverallow init service_manager_type:service_manager { add find }; +neverallow init servicemanager:service_manager list; + +# Init should not be creating subdirectories in /data/local/tmp +neverallow init shell_data_file:dir { write add_name remove_name };
diff --git a/sepolicy/initial_sid_contexts b/sepolicy/initial_sid_contexts new file mode 100644 index 0000000..9819051 --- /dev/null +++ b/sepolicy/initial_sid_contexts
@@ -0,0 +1,27 @@ +sid kernel u:r:kernel:s0 +sid security u:object_r:kernel:s0 +sid unlabeled u:object_r:unlabeled:s0 +sid fs u:object_r:labeledfs:s0 +sid file u:object_r:unlabeled:s0 +sid file_labels u:object_r:unlabeled:s0 +sid init u:object_r:unlabeled:s0 +sid any_socket u:object_r:unlabeled:s0 +sid port u:object_r:port:s0 +sid netif u:object_r:netif:s0 +sid netmsg u:object_r:unlabeled:s0 +sid node u:object_r:node:s0 +sid igmp_packet u:object_r:unlabeled:s0 +sid icmp_socket u:object_r:unlabeled:s0 +sid tcp_socket u:object_r:unlabeled:s0 +sid sysctl_modprobe u:object_r:unlabeled:s0 +sid sysctl u:object_r:proc:s0 +sid sysctl_fs u:object_r:unlabeled:s0 +sid sysctl_kernel u:object_r:unlabeled:s0 +sid sysctl_net u:object_r:unlabeled:s0 +sid sysctl_net_unix u:object_r:unlabeled:s0 +sid sysctl_vm u:object_r:unlabeled:s0 +sid sysctl_dev u:object_r:unlabeled:s0 +sid kmod u:object_r:unlabeled:s0 +sid policy u:object_r:unlabeled:s0 +sid scmp_packet u:object_r:unlabeled:s0 +sid devnull u:object_r:null_device:s0
diff --git a/sepolicy/initial_sids b/sepolicy/initial_sids new file mode 100644 index 0000000..91ac816 --- /dev/null +++ b/sepolicy/initial_sids
@@ -0,0 +1,35 @@ +# FLASK + +# +# Define initial security identifiers +# + +sid kernel +sid security +sid unlabeled +sid fs +sid file +sid file_labels +sid init +sid any_socket +sid port +sid netif +sid netmsg +sid node +sid igmp_packet +sid icmp_socket +sid tcp_socket +sid sysctl_modprobe +sid sysctl +sid sysctl_fs +sid sysctl_kernel +sid sysctl_net +sid sysctl_net_unix +sid sysctl_vm +sid sysctl_dev +sid kmod +sid policy +sid scmp_packet +sid devnull + +# FLASK
diff --git a/sepolicy/inputflinger.te b/sepolicy/inputflinger.te new file mode 100644 index 0000000..324f3f6 --- /dev/null +++ b/sepolicy/inputflinger.te
@@ -0,0 +1,15 @@ +# inputflinger +type inputflinger, domain, domain_deprecated; +type inputflinger_exec, exec_type, file_type; + +init_daemon_domain(inputflinger) +binder_use(inputflinger) +binder_service(inputflinger) + +binder_call(inputflinger, system_server) + +wakelock_use(inputflinger) + +allow inputflinger inputflinger_service:service_manager { add find }; +allow inputflinger input_device:dir r_dir_perms; +allow inputflinger input_device:chr_file rw_file_perms;
diff --git a/sepolicy/install_recovery.te b/sepolicy/install_recovery.te new file mode 100644 index 0000000..b11ff74 --- /dev/null +++ b/sepolicy/install_recovery.te
@@ -0,0 +1,28 @@ +# service flash_recovery in init.rc +type install_recovery, domain, domain_deprecated; +type install_recovery_exec, exec_type, file_type; + +init_daemon_domain(install_recovery) + +allow install_recovery self:capability dac_override; + +# /system/bin/install-recovery.sh is a shell script. +# Needs to execute /system/bin/sh +allow install_recovery shell_exec:file rx_file_perms; + +# Execute /system/bin/applypatch +allow install_recovery system_file:file rx_file_perms; + +allow install_recovery toolbox_exec:file rx_file_perms; + +# Update the recovery block device based off a diff of the boot block device +allow install_recovery block_device:dir search; +allow install_recovery boot_block_device:blk_file r_file_perms; +allow install_recovery recovery_block_device:blk_file rw_file_perms; + +# Create and delete /cache/saved.file +allow install_recovery cache_file:dir rw_dir_perms; +allow install_recovery cache_file:file create_file_perms; + +# Write to /proc/sys/vm/drop_caches +allow install_recovery proc_drop_caches:file w_file_perms;
diff --git a/sepolicy/installd.te b/sepolicy/installd.te new file mode 100644 index 0000000..1f83501 --- /dev/null +++ b/sepolicy/installd.te
@@ -0,0 +1,94 @@ +# installer daemon +type installd, domain, domain_deprecated; +type installd_exec, exec_type, file_type; + +init_daemon_domain(installd) +typeattribute installd mlstrustedsubject; +allow installd self:capability { chown dac_override fowner fsetid setgid setuid }; + +# Allow labeling of files under /data/app/com.example/oat/ +allow installd dalvikcache_data_file:dir relabelto; +allow installd dalvikcache_data_file:file { relabelto link }; + +# Allow movement of APK files between volumes +allow installd apk_data_file:dir { create_dir_perms relabelfrom }; +allow installd apk_data_file:file { create_file_perms relabelfrom link }; +allow installd apk_data_file:lnk_file { create read unlink }; + +allow installd asec_apk_file:file r_file_perms; +allow installd apk_tmp_file:file { r_file_perms unlink }; +allow installd apk_tmp_file:dir { relabelfrom create_dir_perms }; +allow installd oemfs:dir r_dir_perms; +allow installd oemfs:file r_file_perms; +allow installd cgroup:dir create_dir_perms; +allow installd mnt_expand_file:dir { search getattr }; +# Check validity of SELinux context before use. +selinux_check_context(installd) + +# Search /data/app-asec and stat files in it. +allow installd asec_image_file:dir search; +allow installd asec_image_file:file getattr; + +# Create /data/user and /data/user/0 if necessary. +# Also required to initially create /data/data subdirectories +# and lib symlinks before the setfilecon call. May want to +# move symlink creation after setfilecon in installd. +allow installd system_data_file:dir create_dir_perms; +allow installd system_data_file:lnk_file { create setattr unlink }; + +# Upgrade /data/media for multi-user if necessary. +allow installd media_rw_data_file:dir create_dir_perms; +allow installd media_rw_data_file:file { getattr unlink }; +# restorecon new /data/media directory. +allow installd system_data_file:dir relabelfrom; +allow installd media_rw_data_file:dir relabelto; + +# Upgrade /data/misc/keychain for multi-user if necessary. +allow installd misc_user_data_file:dir create_dir_perms; +allow installd misc_user_data_file:file create_file_perms; +allow installd keychain_data_file:dir create_dir_perms; +allow installd keychain_data_file:file {r_file_perms unlink}; + +# Create /data/.layout_version.* file +type_transition installd system_data_file:file install_data_file; +allow installd install_data_file:file create_file_perms; + +# Create files under /data/dalvik-cache. +allow installd dalvikcache_data_file:dir create_dir_perms; +allow installd dalvikcache_data_file:file create_file_perms; + +# Create files under /data/resource-cache. +allow installd resourcecache_data_file:dir rw_dir_perms; +allow installd resourcecache_data_file:file create_file_perms; + +# Run dex2oat in its own sandbox. +domain_auto_trans(installd, dex2oat_exec, dex2oat) + +# Run idmap in its own sandbox. +domain_auto_trans(installd, idmap_exec, idmap) + +# Upgrade from unlabeled userdata. +# Just need enough to remove and/or relabel it. +allow installd unlabeled:dir { getattr search relabelfrom rw_dir_perms rmdir }; +allow installd unlabeled:notdevfile_class_set { getattr relabelfrom rename unlink setattr }; +# Read pkg.apk file for input during dexopt. +allow installd unlabeled:file r_file_perms; + +# Upgrade from before system_app_data_file was used for system UID apps. +# Just need enough to relabel it and to unlink removed package files. +# Directory access covered by earlier rule above. +allow installd system_data_file:notdevfile_class_set { getattr relabelfrom unlink }; + +# Manage /data/data subdirectories, including initially labeling them +# upon creation via setfilecon or running restorecon_recursive, +# setting owner/mode, creating symlinks within them, and deleting them +# upon package uninstall. +# Types extracted from seapp_contexts type= fields. +allow installd { system_app_data_file bluetooth_data_file nfc_data_file radio_data_file shell_data_file app_data_file }:dir { create_dir_perms relabelfrom relabelto }; +allow installd { system_app_data_file bluetooth_data_file nfc_data_file radio_data_file shell_data_file app_data_file }:notdevfile_class_set { create_file_perms relabelfrom relabelto }; + +# Create and use pty created by android_fork_execvp(). +allow installd devpts:chr_file rw_file_perms; + +# execute toybox for app relocation +allow installd toolbox_exec:file rx_file_perms;
diff --git a/sepolicy/ioctl_macros b/sepolicy/ioctl_macros new file mode 100644 index 0000000..e71e0ce --- /dev/null +++ b/sepolicy/ioctl_macros
@@ -0,0 +1,11 @@ +# socket ioctls allowed to unprivileged apps +define(`unpriv_sock_ioctls', ` +{ +# all socket ioctls except the Mac address SIOCGIFHWADDR 0x8927 +0x8900-0x8926 0x8928-0x89ff +# all wireless extensions ioctls except get/set essid +# IOCSIWESSID 0x8B1A SIOCGIWESSID 0x8B1B +0x8B00-0x8B09 0x8B1C-0x8BFF +# commonly used TTY ioctls +0x5411 0x5451 +}')
diff --git a/sepolicy/isolated_app.te b/sepolicy/isolated_app.te new file mode 100644 index 0000000..124fde9 --- /dev/null +++ b/sepolicy/isolated_app.te
@@ -0,0 +1,62 @@ +### +### Services with isolatedProcess=true in their manifest. +### +### This file defines the rules for isolated apps. An "isolated +### app" is an APP with UID between AID_ISOLATED_START (99000) +### and AID_ISOLATED_END (99999). +### +### isolated_app includes all the appdomain rules, plus the +### additional following rules: +### + +type isolated_app, domain; +app_domain(isolated_app) + +# Access already open app data files received over Binder or local socket IPC. +allow isolated_app app_data_file:file { read write getattr lock }; + +allow isolated_app activity_service:service_manager find; +allow isolated_app display_service:service_manager find; + +# Google Breakpad (crash reporter for Chrome) relies on ptrace +# functionality. Without the ability to ptrace, the crash reporter +# tool is broken. +# b/20150694 +# https://code.google.com/p/chromium/issues/detail?id=475270 +allow isolated_app self:process ptrace; + +##### +##### Neverallow +##### + +# Do not allow isolated_app to directly open tun_device +neverallow isolated_app tun_device:chr_file open; + +# Do not allow isolated_app to set system properties. +neverallow isolated_app property_socket:sock_file write; +neverallow isolated_app property_type:property_service set; + +# Isolated apps should not directly open app data files themselves. +neverallow isolated_app app_data_file:file open; + +# Only allow appending to /data/anr/traces.txt (b/27853304, b/18340553) +# TODO: are there situations where isolated_apps write to this file? +# TODO: should we tighten these restrictions further? +neverallow isolated_app anr_data_file:file ~{ open append }; +neverallow isolated_app anr_data_file:dir ~search; + +# b/17487348 +# Isolated apps can only access two services, +# activity_service and display_service +neverallow isolated_app { + service_manager_type + -activity_service + -display_service +}:service_manager find; + +# Isolated apps shouldn't be able to access the driver directly. +neverallow isolated_app gpu_device:chr_file { rw_file_perms execute }; + +# Do not allow isolated_app access to /cache +neverallow isolated_app cache_file:dir ~{ r_dir_perms }; +neverallow isolated_app cache_file:file ~{ read getattr };
diff --git a/sepolicy/kernel.te b/sepolicy/kernel.te new file mode 100644 index 0000000..adab085 --- /dev/null +++ b/sepolicy/kernel.te
@@ -0,0 +1,92 @@ +# Life begins with the kernel. +type kernel, domain, domain_deprecated, mlstrustedsubject; + +allow kernel self:capability sys_nice; + +# Root fs. +allow kernel rootfs:dir r_dir_perms; +allow kernel rootfs:file r_file_perms; +allow kernel rootfs:lnk_file r_file_perms; + +# Get SELinux enforcing status. +allow kernel selinuxfs:dir r_dir_perms; +allow kernel selinuxfs:file r_file_perms; + +# Allow init relabel itself. +allow kernel rootfs:file relabelfrom; +allow kernel init_exec:file relabelto; +# TODO: investigate why we need this. +allow kernel init:process share; + +# cgroup filesystem initialization prior to setting the cgroup root directory label. +allow kernel unlabeled:dir search; + +# Mount usbfs. +allow kernel usbfs:filesystem mount; +allow kernel usbfs:dir search; + +# Initial setenforce by init prior to switching to init domain. +# We use dontaudit instead of allow to prevent a kernel spawned userspace +# process from turning off SELinux once enabled. +dontaudit kernel self:security setenforce; + +# Write to /proc/1/oom_adj prior to switching to init domain. +allow kernel self:capability sys_resource; + +# Init reboot before switching selinux domains under certain error +# conditions. Allow it. +# As part of rebooting, init writes "u" to /proc/sysrq-trigger to +# remount filesystems read-only. /data is not mounted at this point, +# so we could ignore this. For now, we allow it. +allow kernel self:capability sys_boot; +allow kernel proc_sysrq:file w_file_perms; + +# Allow writing to /dev/kmsg which was created prior to loading policy. +allow kernel tmpfs:chr_file write; + +# Set checkreqprot by init.rc prior to switching to init domain. +allow kernel selinuxfs:file write; +allow kernel self:security setcheckreqprot; + +# MTP sync (b/15835289) +# kernel thread "loop0", used by the loop block device, for ASECs (b/17158723) +allow kernel priv_app:fd use; +allow kernel sdcard_type:file { read write }; + +# Allow the kernel to read OBB files from app directories. (b/17428116) +# Kernel thread "loop0" reads a vold supplied file descriptor. +# Fixes CTS tests: +# * android.os.storage.cts.StorageManagerTest#testMountAndUnmountObbNormal +# * android.os.storage.cts.StorageManagerTest#testMountAndUnmountTwoObbs +allow kernel vold:fd use; +allow kernel app_data_file:file read; +allow kernel asec_image_file:file read; + +# Allow reading loop device in update_engine_unittests. (b/28319454) +userdebug_or_eng(` + allow kernel update_engine_data_file:file read; + allow kernel nativetest_data_file:file read; +') + +domain_auto_trans(kernel, init_exec, init) + +### +### neverallow rules +### + +# The initial task starts in the kernel domain (assigned via +# initial_sid_contexts), but nothing ever transitions to it. +neverallow * kernel:process { transition dyntransition }; + +# The kernel domain is never entered via an exec, nor should it +# ever execute a program outside the rootfs without changing to another domain. +# If you encounter an execute_no_trans denial on the kernel domain, then +# possible causes include: +# - The program is a kernel usermodehelper. In this case, define a domain +# for the program and domain_auto_trans() to it. +# - You failed to setcon u:r:init:s0 in your init.rc and thus your init +# program was left in the kernel domain and is now trying to execute +# some other program. Fix your init.rc file. +# - You are running an exploit which switched to the init task credentials +# and is then trying to exec a shell or other program. You lose! +neverallow kernel { file_type fs_type -rootfs }:file { entrypoint execute_no_trans };
diff --git a/sepolicy/keys.conf b/sepolicy/keys.conf new file mode 100644 index 0000000..7a307b5 --- /dev/null +++ b/sepolicy/keys.conf
@@ -0,0 +1,25 @@ +# +# Maps an arbitrary tag [TAGNAME] with the string contents found in +# TARGET_BUILD_VARIANT. Common convention is to start TAGNAME with an @ and +# name it after the base file name of the pem file. +# +# Each tag (section) then allows one to specify any string found in +# TARGET_BUILD_VARIANT. Typcially this is user, eng, and userdebug. Another +# option is to use ALL which will match ANY TARGET_BUILD_VARIANT string. +# + +[@PLATFORM] +ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/platform.x509.pem + +[@MEDIA] +ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/media.x509.pem + +[@SHARED] +ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/shared.x509.pem + +# Example of ALL TARGET_BUILD_VARIANTS +[@RELEASE] +ENG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem +USER : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem +USERDEBUG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem +
diff --git a/sepolicy/keystore.te b/sepolicy/keystore.te new file mode 100644 index 0000000..9dca43c --- /dev/null +++ b/sepolicy/keystore.te
@@ -0,0 +1,32 @@ +type keystore, domain, domain_deprecated; +type keystore_exec, exec_type, file_type; + +# keystore daemon +init_daemon_domain(keystore) +typeattribute keystore mlstrustedsubject; +binder_use(keystore) +binder_service(keystore) +allow keystore keystore_data_file:dir create_dir_perms; +allow keystore keystore_data_file:notdevfile_class_set create_file_perms; +allow keystore keystore_exec:file { getattr }; +allow keystore tee_device:chr_file rw_file_perms; +allow keystore tee:unix_stream_socket connectto; + +allow keystore keystore_service:service_manager { add find }; + +# Check SELinux permissions. +selinux_check_access(keystore) + +### +### Neverallow rules +### +### Protect ourself from others +### + +neverallow { domain -keystore } keystore_data_file:dir ~{ open create read getattr setattr search relabelto ioctl }; +neverallow { domain -keystore } keystore_data_file:notdevfile_class_set ~{ relabelto getattr }; + +neverallow { domain -keystore -init } keystore_data_file:dir *; +neverallow { domain -keystore -init } keystore_data_file:notdevfile_class_set *; + +neverallow * keystore:process ptrace;
diff --git a/sepolicy/lmkd.te b/sepolicy/lmkd.te new file mode 100644 index 0000000..ee731c5 --- /dev/null +++ b/sepolicy/lmkd.te
@@ -0,0 +1,40 @@ +# lmkd low memory killer daemon +type lmkd, domain, domain_deprecated, mlstrustedsubject; +type lmkd_exec, exec_type, file_type; + +init_daemon_domain(lmkd) + +allow lmkd self:capability { dac_override sys_resource kill }; + +# lmkd locks itself in memory, to prevent it from being +# swapped out and unable to kill other memory hogs. +# system/core commit b28ff9131363f7b4a698990da5748b2a88c3ed35 +# b/16236289 +allow lmkd self:capability ipc_lock; + +## Open and write to /proc/PID/oom_score_adj +## TODO: maybe scope this down? +r_dir_file(lmkd, appdomain) +allow lmkd appdomain:file write; +r_dir_file(lmkd, system_server) +allow lmkd system_server:file write; + +## Writes to /sys/module/lowmemorykiller/parameters/minfree +r_dir_file(lmkd, sysfs_type) +allow lmkd sysfs_lowmemorykiller:file w_file_perms; + +# Send kill signals +allow lmkd appdomain:process sigkill; + +# Clean up old cgroups +allow lmkd cgroup:dir { remove_name rmdir }; + +# Set self to SCHED_FIFO +allow lmkd self:capability sys_nice; + +allow lmkd proc_zoneinfo:file r_file_perms; + +### neverallow rules + +# never honor LD_PRELOAD +neverallow * lmkd:process noatsecure;
diff --git a/sepolicy/logd.te b/sepolicy/logd.te new file mode 100644 index 0000000..8c68ae7 --- /dev/null +++ b/sepolicy/logd.te
@@ -0,0 +1,66 @@ +# android user-space log manager +type logd, domain, domain_deprecated, mlstrustedsubject; +type logd_exec, exec_type, file_type; + +init_daemon_domain(logd) + +# Read access to pseudo filesystems. +r_dir_file(logd, proc) +r_dir_file(logd, proc_net) + +allow logd self:capability { setuid setgid setpcap sys_nice audit_control }; +allow logd self:capability2 syslog; +allow logd self:netlink_audit_socket { create_socket_perms nlmsg_write }; +allow logd kernel:system syslog_read; +allow logd kmsg_device:chr_file w_file_perms; +allow logd system_data_file:file r_file_perms; +# logpersist is only allowed on userdebug and eng builds +userdebug_or_eng(` + allow logd misc_logd_file:file create_file_perms; + allow logd misc_logd_file:dir rw_dir_perms; +') +allow logd pstorefs:dir search; +allow logd pstorefs:file r_file_perms; + +# Set persist.sys. and sys.powerctl +set_prop(logd, safemode_prop) +set_prop(logd, powerctl_prop) + +# Access device logging gating property +get_prop(logd, device_logging_prop) +userdebug_or_eng(`get_prop(logd, logpersistd_logging_prop)') + +r_dir_file(logd, domain) + +allow logd kernel:system syslog_mod; + +control_logd(logd) + +# case where logpersistd is actually logcat -f in logd context (nee: logcatd) +userdebug_or_eng(` + unix_socket_connect(logd, logdr, logd) +') + +### +### Neverallow rules +### +### logd should NEVER do any of this + +# Block device access. +neverallow logd dev_type:blk_file { read write }; + +# ptrace any other app +neverallow logd domain:process ptrace; + +# Write to /system. +neverallow logd system_file:dir_file_class_set write; + +# Write to files in /data/data or system files on /data +neverallow logd { app_data_file system_data_file }:dir_file_class_set write; + +# logd is not allowed to write anywhere other than /data/misc/logd +neverallow logd { file_type -logd_tmpfs -misc_logd_file -coredump_file }:file { create write append }; + +neverallow { domain -shell -dumpstate -logd -logrotate -su } misc_logd_file:file no_rw_file_perms; +neverallow { domain -logd -logrotate -su } misc_logd_file:dir { add_name link relabelfrom remove_name rename reparent rmdir write }; +neverallow { domain -init } misc_logd_file:dir create;
diff --git a/sepolicy/mac_permissions.xml b/sepolicy/mac_permissions.xml new file mode 100644 index 0000000..87efe0e --- /dev/null +++ b/sepolicy/mac_permissions.xml
@@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<policy> + +<!-- + + * A signature is a hex encoded X.509 certificate or a tag defined in + keys.conf and is required for each signer tag. The signature can + either appear as a set of attached cert child tags or as an attribute. + * A signer tag must contain a seinfo tag XOR multiple package stanzas. + * Each signer/package tag is allowed to contain one seinfo tag. This tag + represents additional info that each app can use in setting a SELinux security + context on the eventual process as well as the apps data directory. + * seinfo assignments are made according to the following rules: + - Stanzas with package name refinements will be checked first. + - Stanzas w/o package name refinements will be checked second. + - The "default" seinfo label is automatically applied. + + * valid stanzas can take one of the following forms: + + // single cert protecting seinfo + <signer signature="@PLATFORM" > + <seinfo value="platform" /> + </signer> + + // multiple certs protecting seinfo (all contained certs must match) + <signer> + <cert signature="@PLATFORM1"/> + <cert signature="@PLATFORM2"/> + <seinfo value="platform" /> + </signer> + + // single cert protecting explicitly named app + <signer signature="@PLATFORM" > + <package name="com.android.foo"> + <seinfo value="bar" /> + </package> + </signer> + + // multiple certs protecting explicitly named app (all certs must match) + <signer> + <cert signature="@PLATFORM1"/> + <cert signature="@PLATFORM2"/> + <package name="com.android.foo"> + <seinfo value="bar" /> + </package> + </signer> +--> + + <!-- Platform dev key in AOSP --> + <signer signature="@PLATFORM" > + <seinfo value="platform" /> + </signer> + +</policy>
diff --git a/sepolicy/mdnsd.te b/sepolicy/mdnsd.te new file mode 100644 index 0000000..a9dc7c5 --- /dev/null +++ b/sepolicy/mdnsd.te
@@ -0,0 +1,9 @@ +# mdns daemon +type mdnsd, domain, mlstrustedsubject; +type mdnsd_exec, exec_type, file_type; + +init_daemon_domain(mdnsd) +net_domain(mdnsd) + +# Read from /proc/net +r_dir_file(mdnsd, proc_net)
diff --git a/sepolicy/mediaserver.te b/sepolicy/mediaserver.te new file mode 100644 index 0000000..7e20002 --- /dev/null +++ b/sepolicy/mediaserver.te
@@ -0,0 +1,124 @@ +# mediaserver - multimedia daemon +type mediaserver, domain, domain_deprecated; +type mediaserver_exec, exec_type, file_type; + +typeattribute mediaserver mlstrustedsubject; + +net_domain(mediaserver) +init_daemon_domain(mediaserver) + +r_dir_file(mediaserver, sdcard_type) + +# stat /proc/self +allow mediaserver proc:lnk_file getattr; + +# open /vendor/lib/mediadrm +allow mediaserver system_file:dir r_dir_perms; + +binder_use(mediaserver) +binder_call(mediaserver, binderservicedomain) +binder_call(mediaserver, appdomain) +binder_service(mediaserver) + +# Required by Widevine DRM (b/22990512) +allow mediaserver self:process execmem; + +allow mediaserver kernel:system module_request; +allow mediaserver media_data_file:dir create_dir_perms; +allow mediaserver media_data_file:file create_file_perms; +allow mediaserver app_data_file:dir search; +allow mediaserver app_data_file:file rw_file_perms; +allow mediaserver sdcard_type:file write; +allow mediaserver gpu_device:chr_file rw_file_perms; +allow mediaserver video_device:dir r_dir_perms; +allow mediaserver video_device:chr_file rw_file_perms; +allow mediaserver audio_device:dir r_dir_perms; +allow mediaserver tee_device:chr_file rw_file_perms; + +set_prop(mediaserver, audio_prop) + +# Access audio devices at all. +allow mediaserver audio_device:chr_file rw_file_perms; + +# XXX Label with a specific type? +allow mediaserver sysfs:file r_file_perms; + +# Read resources from open apk files passed over Binder. +allow mediaserver apk_data_file:file { read getattr }; +allow mediaserver asec_apk_file:file { read getattr }; + +# Read /data/data/com.android.providers.telephony files passed over Binder. +allow mediaserver radio_data_file:file { read getattr }; + +# Use pipes passed over Binder from app domains. +allow mediaserver appdomain:fifo_file { getattr read write }; + +allow mediaserver rpmsg_device:chr_file rw_file_perms; + +# Inter System processes communicate over named pipe (FIFO) +allow mediaserver system_server:fifo_file r_file_perms; + +# Camera data +r_dir_file(mediaserver, camera_data_file) +r_dir_file(mediaserver, media_rw_data_file) + +# Grant access to audio files to mediaserver +allow mediaserver audio_data_file:dir ra_dir_perms; +allow mediaserver audio_data_file:file create_file_perms; + +# Grant access to read files on appfuse. +allow mediaserver app_fuse_file:file { read getattr }; + +# Read/[write] to /proc/net/xt_qtaguid/ctrl and /dev/xt_qtaguid +allow mediaserver qtaguid_proc:file rw_file_perms; +allow mediaserver qtaguid_device:chr_file r_file_perms; + +# Allow abstract socket connection +allow mediaserver rild:unix_stream_socket { connectto read write setopt }; + +# Needed on some devices for playing DRM protected content, +# but seems expected and appropriate for all devices. +unix_socket_connect(mediaserver, drmserver, drmserver) + +# Needed on some devices for playing audio on paired BT device, +# but seems appropriate for all devices. +unix_socket_connect(mediaserver, bluetooth, bluetooth) + +# Connect to tee service. +allow mediaserver tee:unix_stream_socket connectto; + +allow mediaserver activity_service:service_manager find; +allow mediaserver appops_service:service_manager find; +allow mediaserver cameraproxy_service:service_manager find; +allow mediaserver batterystats_service:service_manager find; +allow mediaserver drmserver_service:service_manager find; +allow mediaserver mediaserver_service:service_manager { add find }; +allow mediaserver permission_service:service_manager find; +allow mediaserver power_service:service_manager find; +allow mediaserver processinfo_service:service_manager find; +allow mediaserver scheduling_policy_service:service_manager find; +allow mediaserver surfaceflinger_service:service_manager find; + +# /oem access +allow mediaserver oemfs:dir search; +allow mediaserver oemfs:file r_file_perms; + +use_drmservice(mediaserver) +allow mediaserver drmserver:drmservice { + consumeRights + setPlaybackStatus + openDecryptSession + closeDecryptSession + initializeDecryptUnit + decrypt + finalizeDecryptUnit + pread +}; + +### +### neverallow rules +### + +# mediaserver should never execute any executable without a +# domain transition +neverallow mediaserver { file_type fs_type }:file execute_no_trans;
diff --git a/sepolicy/mls b/sepolicy/mls new file mode 100644 index 0000000..5589b4b --- /dev/null +++ b/sepolicy/mls
@@ -0,0 +1,112 @@ +######################################### +# MLS declarations +# + +# Generate the desired number of sensitivities and categories. +gen_sens(mls_num_sens) +gen_cats(mls_num_cats) + +# Generate level definitions for each sensitivity and category. +gen_levels(mls_num_sens,mls_num_cats) + + +################################################# +# MLS policy constraints +# + +# +# Process constraints +# + +# Process transition: Require equivalence unless the subject is trusted. +mlsconstrain process { transition dyntransition } + ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject); + +# Process read operations: No read up unless trusted. +mlsconstrain process { getsched getsession getpgid getcap getattr ptrace share } + (l1 dom l2 or t1 == mlstrustedsubject); + +# Process write operations: Require equivalence unless trusted. +mlsconstrain process { sigkill sigstop signal setsched setpgid setcap setrlimit ptrace share } + (l1 eq l2 or t1 == mlstrustedsubject); + +# +# Socket constraints +# + +# Create/relabel operations: Subject must be equivalent to object unless +# the subject is trusted. Sockets inherit the range of their creator. +mlsconstrain socket_class_set { create relabelfrom relabelto } + ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject); + +# Datagram send: Sender must be equivalent to the receiver unless one of them +# is trusted. +mlsconstrain unix_dgram_socket { sendto } + (l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject); + +# Stream connect: Client must be equivalent to server unless one of them +# is trusted. +mlsconstrain unix_stream_socket { connectto } + (l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject); + +# +# Directory/file constraints +# + +# Create/relabel operations: Subject must be equivalent to object unless +# the subject is trusted. Also, files should always be single-level. +# Do NOT exempt mlstrustedobject types from this constraint. +mlsconstrain dir_file_class_set { create relabelfrom relabelto } + (l2 eq h2 and (l1 eq l2 or t1 == mlstrustedsubject)); + +# +# Constraints for app data files only. +# + +# Only constrain open, not read/write. +# Also constrain other forms of manipulation, e.g. chmod/chown, unlink, rename, etc. +# Subject must be equivalent to object unless the subject is trusted. +mlsconstrain dir { open search setattr rename add_name remove_name reparent rmdir } + (t2 != app_data_file or l1 eq l2 or t1 == mlstrustedsubject); +mlsconstrain { file lnk_file sock_file } { open setattr unlink link rename } + (t2 != app_data_file or l1 eq l2 or t1 == mlstrustedsubject); + +# +# Constraints for file types other than app data files. +# + +# Read operations: Subject must dominate object unless the subject +# or the object is trusted. +mlsconstrain dir { read getattr search } + (t2 == app_data_file or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject); + +mlsconstrain { file lnk_file sock_file chr_file blk_file } { read getattr execute } + (t2 == app_data_file or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject); + +# Write operations: Subject must be equivalent to the object unless the +# subject or the object is trusted. +mlsconstrain dir { write setattr rename add_name remove_name reparent rmdir } + (t2 == app_data_file or l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject); + +mlsconstrain { file lnk_file sock_file chr_file blk_file } { write setattr append unlink link rename } + (t2 == app_data_file or l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject); + +# Special case for FIFOs. +# These can be unnamed pipes, in which case they will be labeled with the +# creating process' label. Thus we also have an exemption when the "object" +# is a domain type, so that processes can communicate via unnamed pipes +# passed by binder or local socket IPC. +mlsconstrain fifo_file { read getattr } + (l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject or t2 == domain); + +mlsconstrain fifo_file { write setattr append unlink link rename } + (l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject or t2 == domain); + +# +# Binder IPC constraints +# +# Presently commented out, as apps are expected to call one another. +# This would only make sense if apps were assigned categories +# based on allowable communications rather than per-app categories. +#mlsconstrain binder call +# (l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject);
diff --git a/sepolicy/mls_macros b/sepolicy/mls_macros new file mode 100644 index 0000000..83e0542 --- /dev/null +++ b/sepolicy/mls_macros
@@ -0,0 +1,54 @@ +######################################## +# +# gen_cats(N) +# +# declares categores c0 to c(N-1) +# +define(`decl_cats',`dnl +category c$1; +ifelse(`$1',`$2',,`decl_cats(incr($1),$2)')dnl +') + +define(`gen_cats',`decl_cats(0,decr($1))') + +######################################## +# +# gen_sens(N) +# +# declares sensitivites s0 to s(N-1) with dominance +# in increasing numeric order with s0 lowest, s(N-1) highest +# +define(`decl_sens',`dnl +sensitivity s$1; +ifelse(`$1',`$2',,`decl_sens(incr($1),$2)')dnl +') + +define(`gen_dominance',`s$1 ifelse(`$1',`$2',,`gen_dominance(incr($1),$2)')') + +define(`gen_sens',` +# Each sensitivity has a name and zero or more aliases. +decl_sens(0,decr($1)) + +# Define the ordering of the sensitivity levels (least to greatest) +dominance { gen_dominance(0,decr($1)) } +') + +######################################## +# +# gen_levels(N,M) +# +# levels from s0 to (N-1) with categories c0 to (M-1) +# +define(`decl_levels',`dnl +level s$1:c0.c$3; +ifelse(`$1',`$2',,`decl_levels(incr($1),$2,$3)')dnl +') + +define(`gen_levels',`decl_levels(0,decr($1),decr($2))') + +######################################## +# +# Basic level names for system low and high +# +define(`mls_systemlow',`s0') +define(`mls_systemhigh',`s`'decr(mls_num_sens):c0.c`'decr(mls_num_cats)')
diff --git a/sepolicy/mtp.te b/sepolicy/mtp.te new file mode 100644 index 0000000..9677abd --- /dev/null +++ b/sepolicy/mtp.te
@@ -0,0 +1,12 @@ +# vpn tunneling protocol manager +type mtp, domain, domain_deprecated; +type mtp_exec, exec_type, file_type; + +init_daemon_domain(mtp) +net_domain(mtp) + +# pptp policy +allow mtp self:socket create_socket_perms; +allow mtp self:capability net_raw; +allow mtp ppp:process signal; +allow mtp vpn_data_file:dir search;
diff --git a/sepolicy/net.te b/sepolicy/net.te new file mode 100644 index 0000000..6aa12f2 --- /dev/null +++ b/sepolicy/net.te
@@ -0,0 +1,25 @@ +# Network types +type node, node_type; +type netif, netif_type; +type port, port_type; + +# Use network sockets. +allow netdomain self:tcp_socket create_stream_socket_perms; +allow netdomain self:{ udp_socket rawip_socket } create_socket_perms; +# Connect to ports. +allow netdomain port_type:tcp_socket name_connect; +# Bind to ports. +allow netdomain node_type:{ tcp_socket udp_socket } node_bind; +allow netdomain port_type:udp_socket name_bind; +allow netdomain port_type:tcp_socket name_bind; +# See changes to the routing table. +allow netdomain self:netlink_route_socket { create_socket_perms nlmsg_read }; + +# Talks to netd via dnsproxyd socket. +unix_socket_connect(netdomain, dnsproxyd, netd) + +# Talks to netd via fwmarkd socket. +unix_socket_connect(netdomain, fwmarkd, netd) + +# Connect to mdnsd via mdnsd socket. +unix_socket_connect(netdomain, mdnsd, mdnsd)
diff --git a/sepolicy/netd.te b/sepolicy/netd.te new file mode 100644 index 0000000..d6c715c --- /dev/null +++ b/sepolicy/netd.te
@@ -0,0 +1,88 @@ +# network manager +type netd, domain, domain_deprecated, mlstrustedsubject; +type netd_exec, exec_type, file_type; + +init_daemon_domain(netd) +net_domain(netd) + +allow netd self:capability { net_admin net_raw kill }; +# Note: fsetid is deliberately not included above. fsetid checks are +# triggered by chmod on a directory or file owned by a group other +# than one of the groups assigned to the current process to see if +# the setgid bit should be cleared, regardless of whether the setgid +# bit was even set. We do not appear to truly need this capability +# for netd to operate. +dontaudit netd self:capability fsetid; + +allow netd self:netlink_kobject_uevent_socket create_socket_perms; +allow netd self:netlink_route_socket nlmsg_write; +allow netd self:netlink_nflog_socket create_socket_perms; +allow netd self:netlink_socket create_socket_perms; +allow netd self:netlink_tcpdiag_socket { create_socket_perms nlmsg_read nlmsg_write }; +allow netd self:netlink_generic_socket create_socket_perms; +allow netd self:netlink_netfilter_socket create_socket_perms; +allow netd shell_exec:file rx_file_perms; +allow netd system_file:file x_file_perms; +allow netd devpts:chr_file rw_file_perms; + +# For /proc/sys/net/ipv[46]/route/flush. +allow netd proc_net:file write; + +# For /sys/modules/bcmdhd/parameters/firmware_path +# XXX Split into its own type. +allow netd sysfs:file write; + +# Set dhcp lease for PAN connection +set_prop(netd, dhcp_prop) +set_prop(netd, system_prop) +auditallow netd system_prop:property_service set; + +# Connect to PAN +domain_auto_trans(netd, dhcp_exec, dhcp) +allow netd dhcp:process signal; + +# Needed to update /data/misc/wifi/hostapd.conf +# TODO: See what we can do to reduce the need for +# these capabilities +allow netd self:capability { dac_override chown fowner }; +allow netd wifi_data_file:file create_file_perms; +allow netd wifi_data_file:dir rw_dir_perms; + +# Needed to update /data/misc/net/rt_tables +allow netd net_data_file:file create_file_perms; +allow netd net_data_file:dir rw_dir_perms; + +# Allow netd to spawn hostapd in it's own domain +domain_auto_trans(netd, hostapd_exec, hostapd) +allow netd hostapd:process signal; + +# Allow netd to spawn dnsmasq in it's own domain +domain_auto_trans(netd, dnsmasq_exec, dnsmasq) +allow netd dnsmasq:process signal; + +# Allow netd to start clatd in its own domain +domain_auto_trans(netd, clatd_exec, clatd) +allow netd clatd:process signal; + +set_prop(netd, ctl_mdnsd_prop) + +# Allow netd to operate on sockets that are passed to it. +allow netd netdomain:{tcp_socket udp_socket rawip_socket dccp_socket tun_socket} {read write getattr setattr getopt setopt}; +allow netd netdomain:fd use; + +### +### Neverallow rules +### +### netd should NEVER do any of this + +# Block device access. +neverallow netd dev_type:blk_file { read write }; + +# ptrace any other app +neverallow netd { domain }:process ptrace; + +# Write to /system. +neverallow netd system_file:dir_file_class_set write; + +# Write to files in /data/data or system files on /data +neverallow netd { app_data_file system_data_file }:dir_file_class_set write;
diff --git a/sepolicy/neverallow_macros b/sepolicy/neverallow_macros new file mode 100644 index 0000000..b36cceb --- /dev/null +++ b/sepolicy/neverallow_macros
@@ -0,0 +1,6 @@ +# +# Common neverallow permissions +define(`no_w_file_perms', `{ append create link unlink relabelfrom rename setattr write }') +define(`no_rw_file_perms', `{ no_w_file_perms open read ioctl lock }') +define(`no_x_file_perms', `{ execute execute_no_trans }') +define(`no_w_dir_perms', `{ add_name create link relabelfrom remove_name rename reparent rmdir setattr write }')
diff --git a/sepolicy/nfc.te b/sepolicy/nfc.te new file mode 100644 index 0000000..85572e2 --- /dev/null +++ b/sepolicy/nfc.te
@@ -0,0 +1,31 @@ +# nfc subsystem +type nfc, domain, domain_deprecated; +app_domain(nfc) +net_domain(nfc) +binder_service(nfc) + +# Set NFC properties +set_prop(nfc, nfc_prop) + +# NFC device access. +allow nfc nfc_device:chr_file rw_file_perms; + +# Data file accesses. +allow nfc nfc_data_file:dir create_dir_perms; +allow nfc nfc_data_file:notdevfile_class_set create_file_perms; + +allow nfc sysfs_nfc_power_writable:file rw_file_perms; +allow nfc sysfs:file write; + +allow nfc drmserver_service:service_manager find; +allow nfc mediaserver_service:service_manager find; +allow nfc nfc_service:service_manager { add find }; +allow nfc radio_service:service_manager find; +allow nfc surfaceflinger_service:service_manager find; +allow nfc app_api_service:service_manager find; +allow nfc system_api_service:service_manager find; + +# already open bugreport file descriptors may be shared with +# the nfc process, from a file in +# /data/data/com.android.shell/files/bugreports/bugreport-*. +allow nfc shell_data_file:file read;
diff --git a/sepolicy/perfprofd.te b/sepolicy/perfprofd.te new file mode 100644 index 0000000..0122c55 --- /dev/null +++ b/sepolicy/perfprofd.te
@@ -0,0 +1,59 @@ +# perfprofd - perf profile collection daemon +type perfprofd_exec, exec_type, file_type; + +userdebug_or_eng(` + + type perfprofd, domain, domain_deprecated, mlstrustedsubject; + + init_daemon_domain(perfprofd) + + # perfprofd needs to control CPU hot-plug in order to avoid kernel + # perfevents problems in cases where CPU goes on/off during measurement; + # this means read access to /sys/devices/system/cpu/possible + # and read/write access to /sys/devices/system/cpu/cpu*/online + allow perfprofd sysfs_devices_system_cpu:file rw_file_perms; + + # perfprofd checks for the existence of and then invokes simpleperf; + # simpleperf retains perfprofd domain after exec + allow perfprofd system_file:file rx_file_perms; + + # perfprofd reads a config file from /data/data/com.google.android.gms/files + allow perfprofd app_data_file:file r_file_perms; + allow perfprofd app_data_file:dir search; + allow perfprofd self:capability { dac_override }; + + # perfprofd opens a file for writing in /data/misc/perfprofd + allow perfprofd perfprofd_data_file:file create_file_perms; + allow perfprofd perfprofd_data_file:dir rw_dir_perms; + + # perfprofd uses the system log + read_logd(perfprofd); + write_logd(perfprofd); + + # perfprofd inspects /sys/power/wake_unlock + wakelock_use(perfprofd); + + # simpleperf uses ioctl() to turn on kernel perf events measurements + allow perfprofd self:capability sys_admin; + + # simpleperf needs to examine /proc to collect task/thread info + r_dir_file(perfprofd, domain) + + # simpleperf needs to access /proc/<pid>/exec + allow perfprofd self:capability { sys_resource sys_ptrace }; + neverallow perfprofd domain:process ptrace; + + # simpleperf needs open/read any file that turns up in a profile + # to see whether it has a build ID + allow perfprofd exec_type:file r_file_perms; + + # simpleperf examines debugfs on startup to collect tracepoint event types + allow perfprofd debugfs_tracing:file r_file_perms; + + # simpleperf is going to execute "sleep" + allow perfprofd toolbox_exec:file rx_file_perms; + + # needed for simpleperf on some kernels + allow perfprofd self:capability ipc_lock; + +')
diff --git a/sepolicy/platform_app.te b/sepolicy/platform_app.te new file mode 100644 index 0000000..0381288 --- /dev/null +++ b/sepolicy/platform_app.te
@@ -0,0 +1,47 @@ +### +### Apps signed with the platform key. +### + +type platform_app, domain, domain_deprecated; +app_domain(platform_app) +# Access the network. +net_domain(platform_app) +# Access bluetooth. +bluetooth_domain(platform_app) +# Read from /data/local/tmp or /data/data/com.android.shell. +allow platform_app shell_data_file:dir search; +allow platform_app shell_data_file:file { open getattr read }; +# Populate /data/app/vmdl*.tmp, /data/app-private/vmdl*.tmp files +# created by system server. +allow platform_app { apk_tmp_file apk_private_tmp_file }:dir rw_dir_perms; +allow platform_app { apk_tmp_file apk_private_tmp_file }:file rw_file_perms; +allow platform_app apk_private_data_file:dir search; +# ASEC +allow platform_app asec_apk_file:dir create_dir_perms; +allow platform_app asec_apk_file:file create_file_perms; + +# Access to /data/media. +allow platform_app media_rw_data_file:dir create_dir_perms; +allow platform_app media_rw_data_file:file create_file_perms; + +# Write to /cache. +allow platform_app { cache_file cache_recovery_file }:dir create_dir_perms; +allow platform_app { cache_file cache_recovery_file }:file create_file_perms; + +# Likely not needed +auditallow platform_app cache_recovery_file:dir create_dir_perms; +auditallow platform_app cache_recovery_file:file create_file_perms; + +# Direct access to vold-mounted storage under /mnt/media_rw +# This is a performance optimization that allows platform apps to bypass the FUSE layer +allow platform_app mnt_media_rw_file:dir r_dir_perms; +allow platform_app vfat:dir create_dir_perms; +allow platform_app vfat:file create_file_perms; + +allow platform_app drmserver_service:service_manager find; +allow platform_app mediaserver_service:service_manager find; +allow platform_app persistent_data_block_service:service_manager find; +allow platform_app radio_service:service_manager find; +allow platform_app surfaceflinger_service:service_manager find; +allow platform_app app_api_service:service_manager find; +allow platform_app system_api_service:service_manager find;
diff --git a/sepolicy/policy_capabilities b/sepolicy/policy_capabilities new file mode 100644 index 0000000..c7b9d9c --- /dev/null +++ b/sepolicy/policy_capabilities
@@ -0,0 +1,5 @@ +# Enable new networking controls. +policycap network_peer_controls; + +# Enable open permission check. +policycap open_perms;
diff --git a/sepolicy/port_contexts b/sepolicy/port_contexts new file mode 100644 index 0000000..b473c0c --- /dev/null +++ b/sepolicy/port_contexts
@@ -0,0 +1,3 @@ +# portcon statements go here, e.g. +# portcon tcp 80 u:object_r:http_port:s0 +
diff --git a/sepolicy/postinstall.te b/sepolicy/postinstall.te new file mode 100644 index 0000000..dd89886 --- /dev/null +++ b/sepolicy/postinstall.te
@@ -0,0 +1,25 @@ +# Domain where the postinstall program runs during the update. +# Extend the permissions in this domain to allow this program to access other +# files needed by the specific device on your device's sepolicy directory. +type postinstall, domain; + +# Allow postinstall to write to its stdout/stderr when redirected via pipes to +# update_engine. +allow postinstall update_engine_common:fd use; +allow postinstall update_engine_common:fifo_file rw_file_perms; + +# Allow postinstall to read and execute directories and files in the same +# mounted location. +allow postinstall postinstall_file:file rx_file_perms; +allow postinstall postinstall_file:lnk_file r_file_perms; +allow postinstall postinstall_file:dir r_dir_perms; + +# Allow postinstall to execute the shell or other system executables. +allow postinstall shell_exec:file rx_file_perms; +allow postinstall system_file:file rx_file_perms; +allow postinstall toolbox_exec:file rx_file_perms; + +# No domain other than update_engine and recovery (via update_engine_sideload) +# should transition to postinstall, as it is only meant to run during the +# update. +neverallow { domain -update_engine -recovery } postinstall:process { transition dyntransition };
diff --git a/sepolicy/ppp.te b/sepolicy/ppp.te new file mode 100644 index 0000000..d7ed70d --- /dev/null +++ b/sepolicy/ppp.te
@@ -0,0 +1,16 @@ +# Point to Point Protocol daemon +type ppp, domain, domain_deprecated; +type ppp_device, dev_type; +type ppp_exec, exec_type, file_type; +domain_auto_trans(mtp, ppp_exec, ppp) + +net_domain(ppp) + +allow ppp mtp:socket rw_socket_perms; +allow ppp mtp:unix_dgram_socket rw_socket_perms; +allow ppp ppp_device:chr_file rw_file_perms; +allow ppp self:capability net_admin; +allow ppp system_file:file rx_file_perms; +allow ppp vpn_data_file:dir w_dir_perms; +allow ppp vpn_data_file:file create_file_perms; +allow ppp mtp:fd use;
diff --git a/sepolicy/priv_app.te b/sepolicy/priv_app.te new file mode 100644 index 0000000..9146263 --- /dev/null +++ b/sepolicy/priv_app.te
@@ -0,0 +1,123 @@ +### +### A domain for further sandboxing privileged apps. +### +type priv_app, domain, domain_deprecated; +app_domain(priv_app) +# Access the network. +net_domain(priv_app) +# Access bluetooth. +bluetooth_domain(priv_app) + +# Some apps ship with shared libraries and binaries that they write out +# to their sandbox directory and then execute. +allow priv_app app_data_file:file rx_file_perms; + +# android.process.media uses /dev/mtp_usb +allow priv_app mtp_device:chr_file rw_file_perms; + +# Allow the allocation and use of ptys +# Used by: https://play.privileged.com/store/apps/details?id=jackpal.androidterm +create_pty(priv_app) + +allow priv_app drmserver_service:service_manager find; +allow priv_app mediaserver_service:service_manager find; +allow priv_app nfc_service:service_manager find; +allow priv_app radio_service:service_manager find; +allow priv_app surfaceflinger_service:service_manager find; +allow priv_app app_api_service:service_manager find; +allow priv_app system_api_service:service_manager find; +allow priv_app persistent_data_block_service:service_manager find; +allow priv_app recovery_service:service_manager find; + +# Traverse into /mnt/media_rw for bypassing FUSE daemon +# TODO: narrow this to just MediaProvider +allow priv_app mnt_media_rw_file:dir search; + +# Write to /cache. +allow priv_app { cache_file cache_recovery_file }:dir create_dir_perms; +allow priv_app { cache_file cache_recovery_file }:file create_file_perms; + +# Access to /data/media. +allow priv_app media_rw_data_file:dir create_dir_perms; +allow priv_app media_rw_data_file:file create_file_perms; + +# Used by Finsky / Android "Verify Apps" functionality when +# running "adb install foo.apk". +allow priv_app shell_data_file:file r_file_perms; +allow priv_app shell_data_file:dir r_dir_perms; + +# Allow verifier to access staged apks. +allow priv_app { apk_tmp_file apk_private_tmp_file }:dir r_dir_perms; +allow priv_app { apk_tmp_file apk_private_tmp_file }:file r_file_perms; + +# b/18504118: Allow reads from /data/anr/traces.txt +allow priv_app anr_data_file:file r_file_perms; + +# Allow GMS core to access perfprofd output, which is stored +# in /data/misc/perfprofd/. GMS core will need to list all +# data stored in that directory to process them one by one. +userdebug_or_eng(` + allow priv_app perfprofd_data_file:file r_file_perms; + allow priv_app perfprofd_data_file:dir r_dir_perms; +') + +# Allow GMS core to stat files and executables on +# the system partition +allow priv_app exec_type:file getattr; + +# For AppFuse. +allow priv_app vold:fd use; +allow priv_app fuse_device:chr_file { read write }; +allow priv_app app_fuse_file:dir rw_dir_perms; +allow priv_app app_fuse_file:file rw_file_perms; + +# /sys access +allow priv_app sysfs_zram:dir search; +allow priv_app sysfs_zram:file r_file_perms; + +# Allow GMS core to communicate with update_engine for A/B update. +binder_call(priv_app, update_engine) +allow priv_app update_engine_service:service_manager find; + +### +### neverallow rules +### + +# Receive or send uevent messages. +neverallow priv_app domain:netlink_kobject_uevent_socket *; + +# Receive or send generic netlink messages +neverallow priv_app domain:netlink_socket *; + +# Too much leaky information in debugfs. It's a security +# best practice to ensure these files aren't readable. +neverallow priv_app debugfs:file read; + +# Do not allow privileged apps to register services. +# Only trusted components of Android should be registering +# services. +neverallow priv_app service_manager_type:service_manager add; + +# Do not allow privileged apps to connect to the property service +# or set properties. b/10243159 +neverallow priv_app property_socket:sock_file write; +neverallow priv_app init:unix_stream_socket connectto; +neverallow priv_app property_type:property_service set; + +# Do not allow priv_app to be assigned mlstrustedsubject. +# This would undermine the per-user isolation model being +# enforced via levelFrom=user in seapp_contexts and the mls +# constraints. As there is no direct way to specify a neverallow +# on attribute assignment, this relies on the fact that fork +# permission only makes sense within a domain (hence should +# never be granted to any other domain within mlstrustedsubject) +# and priv_app is allowed fork permission to itself. +neverallow priv_app mlstrustedsubject:process fork; + +# Do not allow priv_app to hard link to any files. +# In particular, if priv_app links to other app data +# files, installd will not be able to guarantee the deletion +# of the linked to file. Hard links also contribute to security +# bugs, so we want to ensure priv_app never has this +# capability. +neverallow priv_app file_type:file link;
diff --git a/sepolicy/property.te b/sepolicy/property.te new file mode 100644 index 0000000..6d3ba4f --- /dev/null +++ b/sepolicy/property.te
@@ -0,0 +1,39 @@ +type default_prop, property_type, core_property_type; +type shell_prop, property_type, core_property_type; +type debug_prop, property_type, core_property_type; +type dumpstate_prop, property_type, core_property_type; +type persist_debug_prop, property_type, core_property_type; +type debuggerd_prop, property_type, core_property_type; +type dhcp_prop, property_type, core_property_type; +type fingerprint_prop, property_type, core_property_type; +type ffs_prop, property_type, core_property_type; +type radio_prop, property_type, core_property_type; +type net_radio_prop, property_type, core_property_type; +type system_radio_prop, property_type, core_property_type; +type system_prop, property_type, core_property_type; +type vold_prop, property_type, core_property_type; +type ctl_bootanim_prop, property_type; +type ctl_default_prop, property_type; +type ctl_dhcp_pan_prop, property_type; +type ctl_dumpstate_prop, property_type; +type ctl_fuse_prop, property_type; +type ctl_mdnsd_prop, property_type; +type ctl_rildaemon_prop, property_type; +type ctl_bugreport_prop, property_type; +type ctl_console_prop, property_type; +type audio_prop, property_type, core_property_type; +type logd_prop, property_type, core_property_type; +type logpersistd_logging_prop, property_type; +type mmc_prop, property_type; +type restorecon_prop, property_type, core_property_type; +type security_prop, property_type, core_property_type; +type bluetooth_prop, property_type, core_property_type; +type pan_result_prop, property_type, core_property_type; +type powerctl_prop, property_type, core_property_type; +type nfc_prop, property_type, core_property_type; +type dalvik_prop, property_type, core_property_type; +type config_prop, property_type, core_property_type; +type device_logging_prop, property_type; +type safemode_prop, property_type; + +allow property_type tmpfs:filesystem associate;
diff --git a/sepolicy/property_contexts b/sepolicy/property_contexts new file mode 100644 index 0000000..bbfea8a --- /dev/null +++ b/sepolicy/property_contexts
@@ -0,0 +1,95 @@ +########################## +# property service keys +# +# +net.rmnet u:object_r:net_radio_prop:s0 +net.gprs u:object_r:net_radio_prop:s0 +net.ppp u:object_r:net_radio_prop:s0 +net.qmi u:object_r:net_radio_prop:s0 +net.lte u:object_r:net_radio_prop:s0 +net.cdma u:object_r:net_radio_prop:s0 +net.dns u:object_r:net_radio_prop:s0 +sys.usb.config u:object_r:system_radio_prop:s0 +ril. u:object_r:radio_prop:s0 +ro.ril. u:object_r:radio_prop:s0 +gsm. u:object_r:radio_prop:s0 +persist.radio u:object_r:radio_prop:s0 + +net. u:object_r:system_prop:s0 +dev. u:object_r:system_prop:s0 +ro.runtime. u:object_r:system_prop:s0 +hw. u:object_r:system_prop:s0 +ro.hw. u:object_r:system_prop:s0 +sys. u:object_r:system_prop:s0 +sys.powerctl u:object_r:powerctl_prop:s0 +sys.usb.ffs. u:object_r:ffs_prop:s0 +service. u:object_r:system_prop:s0 +wlan. u:object_r:system_prop:s0 +dhcp. u:object_r:dhcp_prop:s0 +dhcp.bt-pan.result u:object_r:pan_result_prop:s0 +bluetooth. u:object_r:bluetooth_prop:s0 + +debug. u:object_r:debug_prop:s0 +debug.db. u:object_r:debuggerd_prop:s0 +dumpstate. u:object_r:dumpstate_prop:s0 +log. u:object_r:shell_prop:s0 +security.perf_harden u:object_r:shell_prop:s0 +service.adb.root u:object_r:shell_prop:s0 +service.adb.tcp.port u:object_r:shell_prop:s0 + +persist.audio. u:object_r:audio_prop:s0 +persist.bluetooth. u:object_r:bluetooth_prop:s0 +persist.debug. u:object_r:persist_debug_prop:s0 +persist.logd. u:object_r:logd_prop:s0 +persist.logd.security u:object_r:device_logging_prop:s0 +persist.logd.logpersistd u:object_r:logpersistd_logging_prop:s0 +logd.logpersistd u:object_r:logpersistd_logging_prop:s0 +persist.log.tag u:object_r:logd_prop:s0 +persist.mmc. u:object_r:mmc_prop:s0 +persist.sys. u:object_r:system_prop:s0 +persist.sys.safemode u:object_r:safemode_prop:s0 +persist.sys.audit_safemode u:object_r:safemode_prop:s0 +persist.service. u:object_r:system_prop:s0 +persist.service.bdroid. u:object_r:bluetooth_prop:s0 +persist.security. u:object_r:system_prop:s0 + +# Boolean property set by system server upon boot indicating +# if device owner is provisioned. +ro.device_owner u:object_r:device_logging_prop:s0 + +# selinux non-persistent properties +selinux.restorecon_recursive u:object_r:restorecon_prop:s0 +selinux. u:object_r:security_prop:s0 + +# default property context +* u:object_r:default_prop:s0 + +# data partition encryption properties +vold. u:object_r:vold_prop:s0 +ro.crypto. u:object_r:vold_prop:s0 + +# ro.build.fingerprint is either set in /system/build.prop, or is +# set at runtime by system_server. +ro.build.fingerprint u:object_r:fingerprint_prop:s0 + +# ctl properties +ctl.bootanim u:object_r:ctl_bootanim_prop:s0 +ctl.dumpstate u:object_r:ctl_dumpstate_prop:s0 +ctl.fuse_ u:object_r:ctl_fuse_prop:s0 +ctl.mdnsd u:object_r:ctl_mdnsd_prop:s0 +ctl.ril-daemon u:object_r:ctl_rildaemon_prop:s0 +ctl.bugreport u:object_r:ctl_bugreport_prop:s0 +ctl.dhcpcd_bt-pan u:object_r:ctl_dhcp_pan_prop:s0 +ctl.console u:object_r:ctl_console_prop:s0 +ctl. u:object_r:ctl_default_prop:s0 + +# NFC properties +nfc. u:object_r:nfc_prop:s0 + +# These properties are not normally set by processes other than init. +# They are only distinguished here for setting by qemu-props on the +# emulator/goldfish. +config. u:object_r:config_prop:s0 +ro.config. u:object_r:config_prop:s0 +dalvik. u:object_r:dalvik_prop:s0 +ro.dalvik. u:object_r:dalvik_prop:s0
diff --git a/sepolicy/racoon.te b/sepolicy/racoon.te new file mode 100644 index 0000000..bf272d1 --- /dev/null +++ b/sepolicy/racoon.te
@@ -0,0 +1,32 @@ +# IKE key management daemon +type racoon, domain, domain_deprecated; +type racoon_exec, exec_type, file_type; + +init_daemon_domain(racoon) +typeattribute racoon mlstrustedsubject; + +net_domain(racoon) + +binder_use(racoon) + +allow racoon tun_device:chr_file r_file_perms; +allow racoon cgroup:dir { add_name create }; +allow racoon kernel:system module_request; + +allow racoon self:key_socket create_socket_perms; +allow racoon self:tun_socket create_socket_perms; +allow racoon self:capability { net_admin net_bind_service net_raw setuid }; + +# XXX: should we give ip-up-vpn its own label (currently racoon domain) +allow racoon system_file:file rx_file_perms; +allow racoon vpn_data_file:file create_file_perms; +allow racoon vpn_data_file:dir w_dir_perms; + +use_keystore(racoon) + +# Racoon (VPN) has a restricted set of permissions from the default. +allow racoon keystore:keystore_key { + get + sign + verify +};
diff --git a/sepolicy/radio.te b/sepolicy/radio.te new file mode 100644 index 0000000..448fdb5 --- /dev/null +++ b/sepolicy/radio.te
@@ -0,0 +1,35 @@ +# phone subsystem +type radio, domain, domain_deprecated, mlstrustedsubject; +app_domain(radio) +net_domain(radio) +bluetooth_domain(radio) +binder_service(radio) + +# Talks to rild via the rild socket. +unix_socket_connect(radio, rild, rild) + +# Data file accesses. +allow radio radio_data_file:dir create_dir_perms; +allow radio radio_data_file:notdevfile_class_set create_file_perms; + +allow radio alarm_device:chr_file rw_file_perms; + +allow radio net_data_file:dir search; +allow radio net_data_file:file r_file_perms; + +# Property service +set_prop(radio, radio_prop) +set_prop(radio, system_radio_prop) +set_prop(radio, net_radio_prop) +auditallow radio net_radio_prop:property_service set; +auditallow radio system_radio_prop:property_service set; + +# ctl interface +set_prop(radio, ctl_rildaemon_prop) + +allow radio drmserver_service:service_manager find; +allow radio mediaserver_service:service_manager find; +allow radio radio_service:service_manager { add find }; +allow radio surfaceflinger_service:service_manager find; +allow radio app_api_service:service_manager find; +allow radio system_api_service:service_manager find;
diff --git a/sepolicy/recovery.te b/sepolicy/recovery.te new file mode 100644 index 0000000..209a276 --- /dev/null +++ b/sepolicy/recovery.te
@@ -0,0 +1,124 @@ +# recovery console (used in recovery init.rc for /sbin/recovery) + +# Declare the domain unconditionally so we can always reference it +# in neverallow rules. +type recovery, domain, domain_deprecated; + +# But the allow rules are only included in the recovery policy. +# Otherwise recovery is only allowed the domain rules. +recovery_only(` + # Allow recovery to perform an update as update_engine would do. + typeattribute recovery update_engine_common, boot_control_hal; + + allow recovery self:capability { chown dac_override fowner fsetid setfcap setuid setgid sys_admin sys_tty_config }; + + # Set security contexts on files that are not known to the loaded policy. + allow recovery self:capability2 mac_admin; + + # Run helpers from / or /system without changing domain. + allow recovery rootfs:file execute_no_trans; + allow recovery system_file:file execute_no_trans; + allow recovery toolbox_exec:file rx_file_perms; + + # Mount filesystems. + allow recovery rootfs:dir mounton; + allow recovery fs_type:filesystem ~relabelto; + allow recovery unlabeled:filesystem ~relabelto; + allow recovery contextmount_type:filesystem relabelto; + + # Create and relabel files and directories under /system. + allow recovery exec_type:{ file lnk_file } { create_file_perms relabelfrom relabelto }; + allow recovery system_file:{ file lnk_file } { create_file_perms relabelfrom relabelto }; + allow recovery system_file:dir { create_dir_perms relabelfrom relabelto }; + + # We may be asked to set an SELinux label for a type not known to the + # currently loaded policy. Allow it. + allow recovery unlabeled:{ file lnk_file } { create_file_perms relabelfrom relabelto }; + allow recovery unlabeled:dir { create_dir_perms relabelfrom relabelto }; + + # 0eb17d944704b3eb140bb9dded299d3be3aed77e in build/ added SELinux + # support to OTAs. However, that code has a bug. When an update occurs, + # some directories are inappropriately labeled as exec_type. This is + # only transient, and subsequent steps in the OTA script correct this + # mistake. New devices are moving to block based OTAs, so this is not + # worth fixing. b/15575013 + allow recovery exec_type:dir { create_dir_perms relabelfrom relabelto }; + + # Write to /proc/sys/vm/drop_caches + allow recovery proc_drop_caches:file w_file_perms; + + # Write to /sys/class/android_usb/android0/enable. + # TODO: create more specific label? + allow recovery sysfs:file w_file_perms; + + allow recovery sysfs_batteryinfo:file r_file_perms; + + allow recovery kernel:system syslog_read; + + # Access /dev/android_adb or /dev/usb-ffs/adb/ep0 + allow recovery adb_device:chr_file rw_file_perms; + allow recovery functionfs:dir search; + allow recovery functionfs:file rw_file_perms; + + # Required to e.g. wipe userdata/cache. + allow recovery device:dir r_dir_perms; + allow recovery block_device:dir r_dir_perms; + allow recovery dev_type:blk_file rw_file_perms; + + # GUI + allow recovery self:process execmem; + allow recovery ashmem_device:chr_file execute; + allow recovery graphics_device:chr_file rw_file_perms; + allow recovery graphics_device:dir r_dir_perms; + allow recovery input_device:dir r_dir_perms; + allow recovery input_device:chr_file r_file_perms; + allow recovery tty_device:chr_file rw_file_perms; + + # Create /tmp/recovery.log and execute /tmp/update_binary. + allow recovery tmpfs:file { create_file_perms x_file_perms }; + allow recovery tmpfs:dir create_dir_perms; + + # Manage files on /cache and /cache/recovery + allow recovery { cache_file cache_recovery_file }:dir create_dir_perms; + allow recovery { cache_file cache_recovery_file }:file create_file_perms; + + # Read files on /oem. + r_dir_file(recovery, oemfs); + + # Reboot the device + set_prop(recovery, powerctl_prop) + + # Start/stop adbd via ctl.start adbd + set_prop(recovery, ctl_default_prop) + + # Use setfscreatecon() to label files for OTA updates. + allow recovery self:process setfscreate; + + # Allow recovery to create a fuse filesystem, and read files from it. + allow recovery fuse_device:chr_file rw_file_perms; + allow recovery fuse:dir r_dir_perms; + allow recovery fuse:file r_file_perms; + + wakelock_use(recovery) + + # This line seems suspect, as it should not really need to + # set scheduling parameters for a kernel domain task. + allow recovery kernel:process setsched; +') + +### +### neverallow rules +### + +# Recovery should never touch /data. +# +# In particular, if /data is encrypted, it is not accessible +# to recovery anyway. +# +# For now, we only enforce write/execute restrictions, as domain.te +# contains a number of read-only rules that apply to all +# domains, including recovery. +# +# TODO: tighten this up further. +neverallow recovery data_file_type:file { no_w_file_perms no_x_file_perms }; +neverallow recovery data_file_type:dir no_w_dir_perms;
diff --git a/sepolicy/recovery_persist.te b/sepolicy/recovery_persist.te new file mode 100644 index 0000000..162ebb1 --- /dev/null +++ b/sepolicy/recovery_persist.te
@@ -0,0 +1,31 @@ +# android recovery persistent log manager +type recovery_persist, domain; +type recovery_persist_exec, exec_type, file_type; + +init_daemon_domain(recovery_persist) + +allow recovery_persist pstorefs:dir search; +allow recovery_persist pstorefs:file r_file_perms; + +allow recovery_persist recovery_data_file:file create_file_perms; +allow recovery_persist recovery_data_file:dir create_dir_perms; + +### +### Neverallow rules +### +### recovery_persist should NEVER do any of this + +# Block device access. +neverallow recovery_persist dev_type:blk_file { read write }; + +# ptrace any other app +neverallow recovery_persist domain:process ptrace; + +# Write to /system. +neverallow recovery_persist system_file:dir_file_class_set write; + +# Write to files in /data/data +neverallow recovery_persist { app_data_file system_data_file }:dir_file_class_set write; + +# recovery_persist is not allowed to write anywhere other than recovery_data_file +neverallow recovery_persist { file_type -recovery_data_file -recovery_persist_tmpfs -coredump_file }:file write;
diff --git a/sepolicy/recovery_refresh.te b/sepolicy/recovery_refresh.te new file mode 100644 index 0000000..907086e --- /dev/null +++ b/sepolicy/recovery_refresh.te
@@ -0,0 +1,29 @@ +# android recovery refresh log manager +type recovery_refresh, domain; +type recovery_refresh_exec, exec_type, file_type; + +init_daemon_domain(recovery_refresh) + +allow recovery_refresh pstorefs:dir search; +allow recovery_refresh pstorefs:file r_file_perms; +# NB: domain inherits write_logd which hands us write to pmsg_device + +### +### Neverallow rules +### +### recovery_refresh should NEVER do any of this + +# Block device access. +neverallow recovery_refresh dev_type:blk_file { read write }; + +# ptrace any other app +neverallow recovery_refresh domain:process ptrace; + +# Write to /system. +neverallow recovery_refresh system_file:dir_file_class_set write; + +# Write to files in /data/data or system files on /data +neverallow recovery_refresh { app_data_file system_data_file }:dir_file_class_set write; + +# recovery_refresh is not allowed to write anywhere +neverallow recovery_refresh { file_type -recovery_refresh_tmpfs -coredump_file }:file write;
diff --git a/sepolicy/rild.te b/sepolicy/rild.te new file mode 100644 index 0000000..c63f2e7 --- /dev/null +++ b/sepolicy/rild.te
@@ -0,0 +1,44 @@ +# rild - radio interface layer daemon +type rild, domain, domain_deprecated; +type rild_exec, exec_type, file_type; + +init_daemon_domain(rild) +net_domain(rild) +allow rild self:netlink_route_socket nlmsg_write; +allow rild kernel:system module_request; +allow rild self:capability { setpcap setgid setuid net_admin net_raw }; +allow rild alarm_device:chr_file rw_file_perms; +allow rild cgroup:dir create_dir_perms; +allow rild radio_device:chr_file rw_file_perms; +allow rild radio_device:blk_file r_file_perms; +allow rild mtd_device:dir search; +allow rild efs_file:dir create_dir_perms; +allow rild efs_file:file create_file_perms; +allow rild shell_exec:file rx_file_perms; +allow rild bluetooth_efs_file:file r_file_perms; +allow rild bluetooth_efs_file:dir r_dir_perms; +allow rild radio_data_file:dir rw_dir_perms; +allow rild radio_data_file:file create_file_perms; +allow rild sdcard_type:dir r_dir_perms; +allow rild system_data_file:dir r_dir_perms; +allow rild system_data_file:file r_file_perms; +allow rild system_file:file x_file_perms; + +# property service +set_prop(rild, radio_prop) +set_prop(rild, net_radio_prop) +set_prop(rild, system_radio_prop) +auditallow rild net_radio_prop:property_service set; +auditallow rild system_radio_prop:property_service set; + +allow rild tty_device:chr_file rw_file_perms; + +# Allow rild to create and use netlink sockets. +allow rild self:netlink_socket create_socket_perms; +allow rild self:netlink_generic_socket create_socket_perms; +allow rild self:netlink_kobject_uevent_socket create_socket_perms; + +# Access to wake locks +wakelock_use(rild) + +allow rild self:socket create_socket_perms;
diff --git a/sepolicy/roles b/sepolicy/roles new file mode 100644 index 0000000..af5fe8b --- /dev/null +++ b/sepolicy/roles
@@ -0,0 +1,2 @@ +role r; +role r types domain;
diff --git a/sepolicy/runas.te b/sepolicy/runas.te new file mode 100644 index 0000000..58a1bdc --- /dev/null +++ b/sepolicy/runas.te
@@ -0,0 +1,33 @@ +type runas, domain, domain_deprecated, mlstrustedsubject; +type runas_exec, exec_type, file_type; + +# ndk-gdb invokes adb shell run-as. +domain_auto_trans(shell, runas_exec, runas) +allow runas adbd:process sigchld; +allow runas shell:fd use; +allow runas shell:fifo_file { read write }; +allow runas devpts:chr_file { read write ioctl }; +allow runas shell_data_file:file { read write }; + +# run-as reads package information. +allow runas system_data_file:file r_file_perms; + +# run-as checks and changes to the app data dir. +dontaudit runas self:capability dac_override; +allow runas app_data_file:dir { getattr search }; + +# run-as switches to the app UID/GID. +allow runas self:capability { setuid setgid }; + +# run-as switches to the app security context. +selinux_check_context(runas) # validate context +allow runas self:process setcurrent; +allow runas non_system_app_set:process dyntransition; # setcon + +### +### neverallow rules +### + +# run-as cannot have capabilities other than CAP_SETUID and CAP_SETGID +neverallow runas self:capability ~{ setuid setgid }; +neverallow runas self:capability2 *;
diff --git a/sepolicy/sdcardd.te b/sepolicy/sdcardd.te new file mode 100644 index 0000000..846c59b --- /dev/null +++ b/sepolicy/sdcardd.te
@@ -0,0 +1,40 @@ +type sdcardd, domain, domain_deprecated; +type sdcardd_exec, exec_type, file_type; + +allow sdcardd cgroup:dir create_dir_perms; +allow sdcardd fuse_device:chr_file rw_file_perms; +allow sdcardd rootfs:dir mounton; # TODO: deprecated in M +allow sdcardd tmpfs:dir r_dir_perms; +allow sdcardd mnt_media_rw_file:dir r_dir_perms; +allow sdcardd storage_file:dir search; +allow sdcardd storage_stub_file:dir { search mounton }; +allow sdcardd sdcard_type:filesystem { mount unmount }; +allow sdcardd self:capability { setuid setgid dac_override sys_admin sys_resource }; + +allow sdcardd sdcard_type:dir create_dir_perms; +allow sdcardd sdcard_type:file create_file_perms; + +type_transition sdcardd system_data_file:{ dir file } media_rw_data_file; +allow sdcardd media_rw_data_file:dir create_dir_perms; +allow sdcardd media_rw_data_file:file create_file_perms; + +# Read /data/system/packages.list. +allow sdcardd system_data_file:file r_file_perms; + +# Read /data/.layout_version +allow sdcardd install_data_file:file r_file_perms; + +# Allow stdin/out back to vold +allow sdcardd vold:fd use; +allow sdcardd vold:fifo_file { read write getattr }; + +# Allow running on top of expanded storage +allow sdcardd mnt_expand_file:dir search; + +### +### neverallow rules +### + +# The sdcard daemon should no longer be started from init +neverallow init sdcardd_exec:file execute; +neverallow init sdcardd:process { transition dyntransition };
diff --git a/sepolicy/seapp_contexts b/sepolicy/seapp_contexts new file mode 100644 index 0000000..d8d2240 --- /dev/null +++ b/sepolicy/seapp_contexts
@@ -0,0 +1,92 @@ +# Input selectors: +# isSystemServer (boolean) +# isOwner (boolean) +# user (string) +# seinfo (string) +# name (string) +# path (string) +# isPrivApp (boolean) +# isSystemServer=true can only be used once. +# An unspecified isSystemServer defaults to false. +# isOwner=true will only match for the owner/primary user. +# isOwner=false will only match for secondary users. +# If unspecified, the entry can match either case. +# An unspecified string selector will match any value. +# A user string selector that ends in * will perform a prefix match. +# user=_app will match any regular app UID. +# user=_isolated will match any isolated service UID. +# isPrivApp=true will only match for applications preinstalled in +# /system/priv-app. +# All specified input selectors in an entry must match (i.e. logical AND). +# Matching is case-insensitive. +# +# Precedence rules: +# (1) isSystemServer=true before isSystemServer=false. +# (2) Specified isOwner= before unspecified isOwner= boolean. +# (3) Specified user= string before unspecified user= string. +# (4) Fixed user= string before user= prefix (i.e. ending in *). +# (5) Longer user= prefix before shorter user= prefix. +# (6) Specified seinfo= string before unspecified seinfo= string. +# ':' character is reserved and may not be used. +# (7) Specified name= string before unspecified name= string. +# (8) Specified path= string before unspecified path= string. +# (9) Specified isPrivApp= before unspecified isPrivApp= boolean. +# +# Outputs: +# domain (string) +# type (string) +# levelFrom (string; one of none, all, app, or user) +# level (string) +# Only entries that specify domain= will be used for app process labeling. +# Only entries that specify type= will be used for app directory labeling. +# levelFrom=user is only supported for _app or _isolated UIDs. +# levelFrom=app or levelFrom=all is only supported for _app UIDs. +# level may be used to specify a fixed level for any UID. +# +# +# Neverallow Assertions +# Additional compile time assertion checks can be added as well. The assertion +# rules are lines beginning with the keyword neverallow. Full support for PCRE +# regular expressions exists on all input and output selectors. Neverallow +# rules are never output to the built seapp_contexts file. Like all keywords, +# neverallows are case-insensitive. A neverallow is asserted when all key value +# inputs are matched on a key value rule line. +# + +# only the system server can be in system_server domain +neverallow isSystemServer=false domain=system_server +neverallow isSystemServer="" domain=system_server + +# system domains should never be assigned outside of system uid +neverallow user=((?!system).)* domain=system_app +neverallow user=((?!system).)* type=system_app_data_file + +# anything with a non-known uid with a specified name should have a specified seinfo +neverallow user=_app name=.* seinfo="" +neverallow user=_app name=.* seinfo=default + +# neverallow shared relro to any other domain +# and neverallow any other uid into shared_relro +neverallow user=shared_relro domain=((?!shared_relro).)* +neverallow user=((?!shared_relro).)* domain=shared_relro + +# neverallow non-isolated uids into isolated_app domain +# and vice versa +neverallow user=_isolated domain=((?!isolated_app).)* +neverallow user=((?!_isolated).)* domain=isolated_app + +# uid shell should always be in shell domain, however non-shell +# uid's can be in shell domain +neverallow user=shell domain=((?!shell).)* + +isSystemServer=true domain=system_server +user=system seinfo=platform domain=system_app type=system_app_data_file +user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file +user=nfc seinfo=platform domain=nfc type=nfc_data_file +user=radio seinfo=platform domain=radio type=radio_data_file +user=shared_relro domain=shared_relro +user=shell seinfo=platform domain=shell type=shell_data_file +user=_isolated domain=isolated_app levelFrom=user +user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user +user=_app isPrivApp=true domain=priv_app type=app_data_file levelFrom=user +user=_app domain=untrusted_app type=app_data_file levelFrom=user
diff --git a/sepolicy/security_classes b/sepolicy/security_classes new file mode 100644 index 0000000..680d3dd --- /dev/null +++ b/sepolicy/security_classes
@@ -0,0 +1,110 @@ +# FLASK + +# +# Define the security object classes +# + +# Classes marked as userspace are classes +# for userspace object managers + +class security +class process +class system +class capability + +# file-related classes +class filesystem +class file +class dir +class fd +class lnk_file +class chr_file +class blk_file +class sock_file +class fifo_file + +# network-related classes +class socket +class tcp_socket +class udp_socket +class rawip_socket +class node +class netif +class netlink_socket +class packet_socket +class key_socket +class unix_stream_socket +class unix_dgram_socket + +# sysv-ipc-related classes +class sem +class msg +class msgq +class shm +class ipc + +# extended netlink sockets +class netlink_route_socket +class netlink_firewall_socket +class netlink_tcpdiag_socket +class netlink_nflog_socket +class netlink_xfrm_socket +class netlink_selinux_socket +class netlink_audit_socket +class netlink_ip6fw_socket +class netlink_dnrt_socket + +# IPSec association +class association + +# Updated Netlink class for KOBJECT_UEVENT family. +class netlink_kobject_uevent_socket + +class appletalk_socket + +class packet + +# Kernel access key retention +class key + +class dccp_socket + +class memprotect + +# network peer labels +class peer + +# Capabilities >= 32 +class capability2 + +# kernel services that need to override task security, e.g. cachefiles +class kernel_service + +class tun_socket + +class binder + +# Updated netlink classes for more recent netlink protocols. +class netlink_iscsi_socket +class netlink_fib_lookup_socket +class netlink_connector_socket +class netlink_netfilter_socket +class netlink_generic_socket +class netlink_scsitransport_socket +class netlink_rdma_socket +class netlink_crypto_socket + +# Property service +class property_service # userspace + +# Service manager +class service_manager # userspace + +# Keystore Key +class keystore_key # userspace + +# debuggerd service +class debuggerd # userspace + +class drmservice # userspace +# FLASK
diff --git a/sepolicy/service.te b/sepolicy/service.te new file mode 100644 index 0000000..fb5b9f4 --- /dev/null +++ b/sepolicy/service.te
@@ -0,0 +1,106 @@ +type bluetooth_service, service_manager_type; +type default_android_service, service_manager_type; +type drmserver_service, service_manager_type; +type gatekeeper_service, app_api_service, service_manager_type; +type fingerprintd_service, service_manager_type; +type batteryproperties_service, app_api_service, service_manager_type; +type inputflinger_service, service_manager_type; +type keystore_service, service_manager_type; +type mediaserver_service, service_manager_type; +type nfc_service, service_manager_type; +type radio_service, service_manager_type; +type surfaceflinger_service, service_manager_type; +type system_app_service, service_manager_type; +type update_engine_service, service_manager_type; + +# system_server_services broken down +type accessibility_service, app_api_service, system_server_service, service_manager_type; +type account_service, app_api_service, system_server_service, service_manager_type; +type activity_service, app_api_service, system_server_service, service_manager_type; +type alarm_service, app_api_service, system_server_service, service_manager_type; +type appops_service, app_api_service, system_server_service, service_manager_type; +type appwidget_service, app_api_service, system_server_service, service_manager_type; +type assetatlas_service, app_api_service, system_server_service, service_manager_type; +type audio_service, app_api_service, system_server_service, service_manager_type; +type backup_service, app_api_service, system_server_service, service_manager_type; +type batterystats_service, app_api_service, system_server_service, service_manager_type; +type battery_service, system_server_service, service_manager_type; +type bluetooth_manager_service, app_api_service, system_server_service, service_manager_type; +type cameraproxy_service, system_server_service, service_manager_type; +type clipboard_service, app_api_service, system_server_service, service_manager_type; +type IProxyService_service, system_api_service, system_server_service, service_manager_type; +type commontime_management_service, system_server_service, service_manager_type; +type connectivity_service, app_api_service, system_server_service, service_manager_type; +type consumer_ir_service, app_api_service, system_server_service, service_manager_type; +type content_service, app_api_service, system_server_service, service_manager_type; +type country_detector_service, app_api_service, system_server_service, service_manager_type; +type cpuinfo_service, system_api_service, system_server_service, service_manager_type; +type dbinfo_service, system_api_service, system_server_service, service_manager_type; +type device_policy_service, app_api_service, system_server_service, service_manager_type; +type deviceidle_service, app_api_service, system_server_service, service_manager_type; +type devicestoragemonitor_service, system_server_service, service_manager_type; +type diskstats_service, system_api_service, system_server_service, service_manager_type; +type display_service, app_api_service, system_server_service, service_manager_type; +type DockObserver_service, system_server_service, service_manager_type; +type dreams_service, app_api_service, system_server_service, service_manager_type; +type dropbox_service, app_api_service, system_server_service, service_manager_type; +type ethernet_service, app_api_service, system_server_service, service_manager_type; +type fingerprint_service, app_api_service, system_server_service, service_manager_type; +type gfxinfo_service, system_api_service, system_server_service, service_manager_type; +type graphicsstats_service, app_api_service, system_server_service, service_manager_type; +type hardware_service, system_server_service, service_manager_type; +type hdmi_control_service, system_api_service, system_server_service, service_manager_type; +type input_method_service, app_api_service, system_server_service, service_manager_type; +type input_service, app_api_service, system_server_service, service_manager_type; +type imms_service, app_api_service, system_server_service, service_manager_type; +type jobscheduler_service, app_api_service, system_server_service, service_manager_type; +type launcherapps_service, app_api_service, system_server_service, service_manager_type; +type location_service, app_api_service, system_server_service, service_manager_type; +type lock_settings_service, system_api_service, system_server_service, service_manager_type; +type media_projection_service, app_api_service, system_server_service, service_manager_type; +type media_router_service, app_api_service, system_server_service, service_manager_type; +type media_session_service, app_api_service, system_server_service, service_manager_type; +type meminfo_service, system_api_service, system_server_service, service_manager_type; +type midi_service, app_api_service, system_server_service, service_manager_type; +type mount_service, app_api_service, system_server_service, service_manager_type; +type netpolicy_service, app_api_service, system_server_service, service_manager_type; +type netstats_service, app_api_service, system_server_service, service_manager_type; +type network_management_service, app_api_service, system_server_service, service_manager_type; +type network_score_service, system_api_service, system_server_service, service_manager_type; +type notification_service, app_api_service, system_server_service, service_manager_type; +type package_service, app_api_service, system_server_service, service_manager_type; +type permission_service, app_api_service, system_server_service, service_manager_type; +type persistent_data_block_service, system_api_service, system_server_service, service_manager_type; +type power_service, app_api_service, system_server_service, service_manager_type; +type print_service, app_api_service, system_server_service, service_manager_type; +type processinfo_service, system_server_service, service_manager_type; +type procstats_service, app_api_service, system_server_service, service_manager_type; +type recovery_service, system_server_service, service_manager_type; +type registry_service, app_api_service, system_server_service, service_manager_type; +type restrictions_service, app_api_service, system_server_service, service_manager_type; +type rttmanager_service, app_api_service, system_server_service, service_manager_type; +type samplingprofiler_service, system_server_service, service_manager_type; +type scheduling_policy_service, system_server_service, service_manager_type; +type search_service, app_api_service, system_server_service, service_manager_type; +type sensorservice_service, app_api_service, system_server_service, service_manager_type; +type serial_service, system_api_service, system_server_service, service_manager_type; +type servicediscovery_service, app_api_service, system_server_service, service_manager_type; +type statusbar_service, app_api_service, system_server_service, service_manager_type; +type task_service, system_server_service, service_manager_type; +type textservices_service, app_api_service, system_server_service, service_manager_type; +type telecom_service, app_api_service, system_server_service, service_manager_type; +type trust_service, app_api_service, system_server_service, service_manager_type; +type tv_input_service, app_api_service, system_server_service, service_manager_type; +type uimode_service, app_api_service, system_server_service, service_manager_type; +type updatelock_service, system_api_service, system_server_service, service_manager_type; +type usagestats_service, app_api_service, system_server_service, service_manager_type; +type usb_service, app_api_service, system_server_service, service_manager_type; +type user_service, app_api_service, system_server_service, service_manager_type; +type vibrator_service, app_api_service, system_server_service, service_manager_type; +type voiceinteraction_service, app_api_service, system_server_service, service_manager_type; +type wallpaper_service, app_api_service, system_server_service, service_manager_type; +type webviewupdate_service, app_api_service, system_server_service, service_manager_type; +type wifip2p_service, app_api_service, system_server_service, service_manager_type; +type wifiscanner_service, system_api_service, system_server_service, service_manager_type; +type wifi_service, app_api_service, system_server_service, service_manager_type; +type window_service, system_api_service, system_server_service, service_manager_type;
diff --git a/sepolicy/service_contexts b/sepolicy/service_contexts new file mode 100644 index 0000000..0e77818 --- /dev/null +++ b/sepolicy/service_contexts
@@ -0,0 +1,132 @@ +accessibility u:object_r:accessibility_service:s0 +account u:object_r:account_service:s0 +activity u:object_r:activity_service:s0 +alarm u:object_r:alarm_service:s0 +android.os.UpdateEngineService u:object_r:update_engine_service:s0 +android.security.keystore u:object_r:keystore_service:s0 +android.service.gatekeeper.IGateKeeperService u:object_r:gatekeeper_service:s0 +appops u:object_r:appops_service:s0 +appwidget u:object_r:appwidget_service:s0 +assetatlas u:object_r:assetatlas_service:s0 +audio u:object_r:audio_service:s0 +backup u:object_r:backup_service:s0 +batteryproperties u:object_r:batteryproperties_service:s0 +batterystats u:object_r:batterystats_service:s0 +battery u:object_r:battery_service:s0 +bluetooth_manager u:object_r:bluetooth_manager_service:s0 +bluetooth u:object_r:bluetooth_service:s0 +carrier_config u:object_r:radio_service:s0 +clipboard u:object_r:clipboard_service:s0 +com.android.net.IProxyService u:object_r:IProxyService_service:s0 +commontime_management u:object_r:commontime_management_service:s0 +common_time.clock u:object_r:mediaserver_service:s0 +common_time.config u:object_r:mediaserver_service:s0 +connectivity u:object_r:connectivity_service:s0 +consumer_ir u:object_r:consumer_ir_service:s0 +content u:object_r:content_service:s0 +country_detector u:object_r:country_detector_service:s0 +cpuinfo u:object_r:cpuinfo_service:s0 +dbinfo u:object_r:dbinfo_service:s0 +device_policy u:object_r:device_policy_service:s0 +deviceidle u:object_r:deviceidle_service:s0 +devicestoragemonitor u:object_r:devicestoragemonitor_service:s0 +diskstats u:object_r:diskstats_service:s0 +display.qservice u:object_r:surfaceflinger_service:s0 +display u:object_r:display_service:s0 +DockObserver u:object_r:DockObserver_service:s0 +dreams u:object_r:dreams_service:s0 +drm.drmManager u:object_r:drmserver_service:s0 +dropbox u:object_r:dropbox_service:s0 +ethernet u:object_r:ethernet_service:s0 +fingerprint u:object_r:fingerprint_service:s0 +android.hardware.fingerprint.IFingerprintDaemon u:object_r:fingerprintd_service:s0 +gfxinfo u:object_r:gfxinfo_service:s0 +graphicsstats u:object_r:graphicsstats_service:s0 +hardware u:object_r:hardware_service:s0 +hdmi_control u:object_r:hdmi_control_service:s0 +inputflinger u:object_r:inputflinger_service:s0 +input_method u:object_r:input_method_service:s0 +input u:object_r:input_service:s0 +iphonesubinfo_msim u:object_r:radio_service:s0 +iphonesubinfo2 u:object_r:radio_service:s0 +iphonesubinfo u:object_r:radio_service:s0 +ims u:object_r:radio_service:s0 +imms u:object_r:imms_service:s0 +isms_msim u:object_r:radio_service:s0 +isms2 u:object_r:radio_service:s0 +isms u:object_r:radio_service:s0 +isub u:object_r:radio_service:s0 +jobscheduler u:object_r:jobscheduler_service:s0 +launcherapps u:object_r:launcherapps_service:s0 +location u:object_r:location_service:s0 +lock_settings u:object_r:lock_settings_service:s0 +media.audio_flinger u:object_r:mediaserver_service:s0 +media.audio_policy u:object_r:mediaserver_service:s0 +media.camera u:object_r:mediaserver_service:s0 +media.camera.proxy u:object_r:cameraproxy_service:s0 +media.log u:object_r:mediaserver_service:s0 +media.player u:object_r:mediaserver_service:s0 +media.resource_manager u:object_r:mediaserver_service:s0 +media.radio u:object_r:mediaserver_service:s0 +media.sound_trigger_hw u:object_r:mediaserver_service:s0 +media_projection u:object_r:media_projection_service:s0 +media_router u:object_r:media_router_service:s0 +media_session u:object_r:media_session_service:s0 +meminfo u:object_r:meminfo_service:s0 +midi u:object_r:midi_service:s0 +mount u:object_r:mount_service:s0 +netpolicy u:object_r:netpolicy_service:s0 +netstats u:object_r:netstats_service:s0 +network_management u:object_r:network_management_service:s0 +network_score u:object_r:network_score_service:s0 +nfc u:object_r:nfc_service:s0 +notification u:object_r:notification_service:s0 +package u:object_r:package_service:s0 +permission u:object_r:permission_service:s0 +persistent_data_block u:object_r:persistent_data_block_service:s0 +phone_msim u:object_r:radio_service:s0 +phone1 u:object_r:radio_service:s0 +phone2 u:object_r:radio_service:s0 +phone u:object_r:radio_service:s0 +power u:object_r:power_service:s0 +print u:object_r:print_service:s0 +processinfo u:object_r:processinfo_service:s0 +procstats u:object_r:procstats_service:s0 +radio.phonesubinfo u:object_r:radio_service:s0 +radio.phone u:object_r:radio_service:s0 +radio.sms u:object_r:radio_service:s0 +recovery u:object_r:recovery_service:s0 +restrictions u:object_r:restrictions_service:s0 +rttmanager u:object_r:rttmanager_service:s0 +samplingprofiler u:object_r:samplingprofiler_service:s0 +scheduling_policy u:object_r:scheduling_policy_service:s0 +search u:object_r:search_service:s0 +sensorservice u:object_r:sensorservice_service:s0 +serial u:object_r:serial_service:s0 +servicediscovery u:object_r:servicediscovery_service:s0 +simphonebook_msim u:object_r:radio_service:s0 +simphonebook2 u:object_r:radio_service:s0 +simphonebook u:object_r:radio_service:s0 +sip u:object_r:radio_service:s0 +statusbar u:object_r:statusbar_service:s0 +SurfaceFlinger u:object_r:surfaceflinger_service:s0 +task u:object_r:task_service:s0 +telecom u:object_r:telecom_service:s0 +telephony.registry u:object_r:registry_service:s0 +textservices u:object_r:textservices_service:s0 +trust u:object_r:trust_service:s0 +tv_input u:object_r:tv_input_service:s0 +uimode u:object_r:uimode_service:s0 +updatelock u:object_r:updatelock_service:s0 +usagestats u:object_r:usagestats_service:s0 +usb u:object_r:usb_service:s0 +user u:object_r:user_service:s0 +vibrator u:object_r:vibrator_service:s0 +voiceinteraction u:object_r:voiceinteraction_service:s0 +wallpaper u:object_r:wallpaper_service:s0 +webviewupdate u:object_r:webviewupdate_service:s0 +wifip2p u:object_r:wifip2p_service:s0 +wifiscanner u:object_r:wifiscanner_service:s0 +wifi u:object_r:wifi_service:s0 +window u:object_r:window_service:s0 +* u:object_r:default_android_service:s0
diff --git a/sepolicy/servicemanager.te b/sepolicy/servicemanager.te new file mode 100644 index 0000000..84605d1 --- /dev/null +++ b/sepolicy/servicemanager.te
@@ -0,0 +1,17 @@ +# servicemanager - the Binder context manager +type servicemanager, domain, domain_deprecated, mlstrustedsubject; +type servicemanager_exec, exec_type, file_type; + +init_daemon_domain(servicemanager) + +# Note that we do not use the binder_* macros here. +# servicemanager is unique in that it only provides +# name service (aka context manager) for Binder. +# As such, it only ever receives and transfers other references +# created by other domains. It never passes its own references +# or initiates a Binder IPC. +allow servicemanager self:binder set_context_mgr; +allow servicemanager { domain -init }:binder transfer; + +# Check SELinux permissions. +selinux_check_access(servicemanager)
diff --git a/sepolicy/sgdisk.te b/sepolicy/sgdisk.te new file mode 100644 index 0000000..43636d4 --- /dev/null +++ b/sepolicy/sgdisk.te
@@ -0,0 +1,22 @@ +# sgdisk called from vold +type sgdisk, domain, domain_deprecated; +type sgdisk_exec, exec_type, file_type; + +# Allowed to read/write low-level partition tables +allow sgdisk block_device:dir search; +allow sgdisk vold_device:blk_file rw_file_perms; + +# Inherit and use pty created by android_fork_execvp() +allow sgdisk devpts:chr_file { read write ioctl getattr }; + +# Allow stdin/out back to vold +allow sgdisk vold:fd use; +allow sgdisk vold:fifo_file { read write getattr }; + +# Used to probe kernel to reload partition tables +allow sgdisk self:capability sys_admin; + +# Only allow entry from vold +neverallow { domain -vold } sgdisk:process transition; +neverallow * sgdisk:process dyntransition; +neverallow sgdisk { file_type fs_type -sgdisk_exec }:file entrypoint;
diff --git a/sepolicy/shared_relro.te b/sepolicy/shared_relro.te new file mode 100644 index 0000000..30af14a --- /dev/null +++ b/sepolicy/shared_relro.te
@@ -0,0 +1,13 @@ +# Process which creates/updates shared RELRO files to be used by other apps. +type shared_relro, domain, domain_deprecated; + +# The shared relro process is a Java program forked from the zygote, so it +# inherits from app to get basic permissions it needs to run. +app_domain(shared_relro) + +# Grant write access to the shared relro files/directory. +allow shared_relro shared_relro_file:dir rw_dir_perms; +allow shared_relro shared_relro_file:file create_file_perms; + +# Needs to contact the "webviewupdate" and "activity" services +allow shared_relro webviewupdate_service:service_manager find;
diff --git a/sepolicy/shell.te b/sepolicy/shell.te new file mode 100644 index 0000000..b7b4e03 --- /dev/null +++ b/sepolicy/shell.te
@@ -0,0 +1,168 @@ +# Domain for shell processes spawned by ADB or console service. +type shell, domain, mlstrustedsubject; +type shell_exec, exec_type, file_type; + +# Create and use network sockets. +net_domain(shell) + +# Run app_process. +# XXX Transition into its own domain? +app_domain(shell) + +# logcat +read_logd(shell) +control_logd(shell) +# logcat -L (directly, or via dumpstate) +allow shell pstorefs:dir search; +allow shell pstorefs:file r_file_perms; +# logpersistd (nee logcatd) files +userdebug_or_eng(` + allow shell misc_logd_file:dir r_dir_perms; + allow shell misc_logd_file:file r_file_perms; +') + +# Root fs. +allow shell rootfs:dir r_dir_perms; + +# read files in /data/anr +allow shell anr_data_file:dir r_dir_perms; +allow shell anr_data_file:file r_file_perms; + +# Access /data/local/tmp. +allow shell shell_data_file:dir create_dir_perms; +allow shell shell_data_file:file create_file_perms; +allow shell shell_data_file:file rx_file_perms; +allow shell shell_data_file:lnk_file create_file_perms; + +# Read/execute files in /data/nativetest +userdebug_or_eng(` + allow shell nativetest_data_file:dir r_dir_perms; + allow shell nativetest_data_file:file rx_file_perms; +') + +# adb bugreport +unix_socket_connect(shell, dumpstate, dumpstate) + +allow shell devpts:chr_file rw_file_perms; +allow shell tty_device:chr_file rw_file_perms; +allow shell console_device:chr_file rw_file_perms; +allow shell input_device:dir r_dir_perms; +allow shell input_device:chr_file rw_file_perms; +r_dir_file(shell, system_file) +allow shell system_file:file x_file_perms; +allow shell toolbox_exec:file rx_file_perms; +allow shell shell_exec:file rx_file_perms; +allow shell zygote_exec:file rx_file_perms; + +r_dir_file(shell, apk_data_file) + +# Set properties. +set_prop(shell, shell_prop) +set_prop(shell, ctl_bugreport_prop) +set_prop(shell, ctl_dumpstate_prop) +set_prop(shell, dumpstate_prop) +set_prop(shell, debug_prop) +set_prop(shell, powerctl_prop) +userdebug_or_eng(`set_prop(shell, logpersistd_logging_prop)') + +# systrace support - allow atrace to run +allow shell debugfs_tracing:dir r_dir_perms; +allow shell debugfs_tracing:file rw_file_perms; +allow shell debugfs_trace_marker:file getattr; +allow shell atrace_exec:file rx_file_perms; + +userdebug_or_eng(` + # "systrace --boot" support - allow boottrace service to run + allow shell boottrace_data_file:dir rw_dir_perms; + allow shell boottrace_data_file:file create_file_perms; + set_prop(shell, persist_debug_prop) +') + +# allow shell to run dmesg +allow shell kernel:system syslog_read; + +# allow shell access to services +allow shell servicemanager:service_manager list; +# don't allow shell to access GateKeeper service +allow shell { service_manager_type -gatekeeper_service }:service_manager find; + +# allow shell to look through /proc/ for ps, top, netstat +r_dir_file(shell, proc) +r_dir_file(shell, proc_net) +allow shell proc_interrupts:file r_file_perms; +allow shell proc_meminfo:file r_file_perms; +allow shell proc_stat:file r_file_perms; +allow shell proc_timer:file r_file_perms; +allow shell proc_zoneinfo:file r_file_perms; +r_dir_file(shell, cgroup) +allow shell domain:dir { search open read getattr }; +allow shell domain:{ file lnk_file } { open read getattr }; + +# statvfs() of /proc and other labeled filesystems +# (yaffs2, jffs2, ext2, ext3, ext4, xfs, btrfs, f2fs, squashfs) +allow shell { proc labeledfs }:filesystem getattr; + +# stat() of /dev +allow shell device:dir getattr; + +# allow shell to read /proc/pid/attr/current for ps -Z +allow shell domain:process getattr; + +# Allow pulling the SELinux policy for CTS purposes +allow shell selinuxfs:dir r_dir_perms; +allow shell selinuxfs:file r_file_perms; + +# enable shell domain to read/write files/dirs for bootchart data +# User will creates the start and stop file via adb shell +# and read other files created by init process under /data/bootchart +allow shell bootchart_data_file:dir rw_dir_perms; +allow shell bootchart_data_file:file create_file_perms; + +# Make sure strace works for the non-privileged shell user +allow shell self:process ptrace; + +# allow shell to get battery info +allow shell sysfs_batteryinfo:file r_file_perms; +allow shell sysfs:dir r_dir_perms; + +# Allow access to ion memory allocation device. +allow shell ion_device:chr_file rw_file_perms; + +# +# filesystem test for insecure chr_file's is done +# via a host side test +# +allow shell dev_type:dir r_dir_perms; +allow shell dev_type:chr_file getattr; + +# /dev/fd is a symlink +allow shell proc:lnk_file getattr; + +# +# filesystem test for insucre blk_file's is done +# via hostside test +# +allow shell dev_type:blk_file getattr; + +### +### Neverallow rules +### + +# Do not allow shell to hard link to any files. +# In particular, if shell hard links to app data +# files, installd will not be able to guarantee the deletion +# of the linked to file. Hard links also contribute to security +# bugs, so we want to ensure the shell user never has this +# capability. +neverallow shell file_type:file link; + +# limit shell access to sensitive char drivers to +# only getattr required for host side test. +neverallow shell { + fuse_device + hw_random_device + kmem_device +}:chr_file ~getattr; + +# Limit shell to only getattr on blk devices for host side tests. +neverallow shell dev_type:blk_file ~getattr;
diff --git a/sepolicy/slideshow.te b/sepolicy/slideshow.te new file mode 100644 index 0000000..3165a65 --- /dev/null +++ b/sepolicy/slideshow.te
@@ -0,0 +1,14 @@ +# slideshow seclabel is specified in init.rc since +# it lives in the rootfs and has no unique file type. +type slideshow, domain, domain_deprecated; + +allow slideshow kmsg_device:chr_file rw_file_perms; +wakelock_use(slideshow) +allow slideshow device:dir r_dir_perms; +allow slideshow self:capability sys_tty_config; +allow slideshow graphics_device:dir r_dir_perms; +allow slideshow graphics_device:chr_file rw_file_perms; +allow slideshow input_device:dir r_dir_perms; +allow slideshow input_device:chr_file r_file_perms; +allow slideshow tty_device:chr_file rw_file_perms; +
diff --git a/sepolicy/su.te b/sepolicy/su.te new file mode 100644 index 0000000..5c98258 --- /dev/null +++ b/sepolicy/su.te
@@ -0,0 +1,56 @@ +# File types must be defined for file_contexts. +type su_exec, exec_type, file_type; + +userdebug_or_eng(` + # Domain used for su processes, as well as for adbd and adb shell + # after performing an adb root command. The domain definition is + # wrapped to ensure that it does not exist at all on -user builds. + type su, domain, mlstrustedsubject; + domain_auto_trans(shell, su_exec, su) + + # Allow dumpstate to call su on userdebug / eng builds to collect + # additional information. + domain_auto_trans(dumpstate, su_exec, su) + + # Make sure that dumpstate runs the same from the "su" domain as + # from the "init" domain. + domain_auto_trans(su, dumpstate_exec, dumpstate) + + # su is also permissive to permit setenforce. + permissive su; + + # Add su to various domains + net_domain(su) + app_domain(su) + + dontaudit su self:capability_class_set *; + dontaudit su kernel:security *; + dontaudit su kernel:system *; + dontaudit su self:memprotect *; + dontaudit su domain:process *; + dontaudit su domain:fd *; + dontaudit su domain:dir *; + dontaudit su domain:lnk_file *; + dontaudit su domain:{ fifo_file file } *; + dontaudit su domain:socket_class_set *; + dontaudit su domain:ipc_class_set *; + dontaudit su domain:key *; + dontaudit su fs_type:filesystem *; + dontaudit su {fs_type dev_type file_type}:dir_file_class_set *; + dontaudit su node_type:node *; + dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *; + dontaudit su netif_type:netif *; + dontaudit su port_type:socket_class_set *; + dontaudit su port_type:{ tcp_socket dccp_socket } *; + dontaudit su domain:peer *; + dontaudit su domain:binder *; + dontaudit su property_type:property_service *; + dontaudit su property_type:file *; + dontaudit su service_manager_type:service_manager *; + dontaudit su servicemanager:service_manager list; + dontaudit su keystore:keystore_key *; + dontaudit su domain:debuggerd *; + dontaudit su domain:drmservice *; + dontaudit su unlabeled:filesystem *; + dontaudit su postinstall_file:filesystem *; +')
diff --git a/sepolicy/surfaceflinger.te b/sepolicy/surfaceflinger.te new file mode 100644 index 0000000..fbe1dd0 --- /dev/null +++ b/sepolicy/surfaceflinger.te
@@ -0,0 +1,68 @@ +# surfaceflinger - display compositor service +type surfaceflinger, domain, domain_deprecated; +type surfaceflinger_exec, exec_type, file_type; + +init_daemon_domain(surfaceflinger) +typeattribute surfaceflinger mlstrustedsubject; + +# Perform Binder IPC. +binder_use(surfaceflinger) +binder_call(surfaceflinger, binderservicedomain) +binder_call(surfaceflinger, appdomain) +binder_call(surfaceflinger, bootanim) +binder_service(surfaceflinger) + +# Binder IPC to bu, presently runs in adbd domain. +binder_call(surfaceflinger, adbd) + +# Read /proc/pid files for Binder clients. +r_dir_file(surfaceflinger, binderservicedomain) +r_dir_file(surfaceflinger, appdomain) + +# Access the GPU. +allow surfaceflinger gpu_device:chr_file rw_file_perms; + +# Access /dev/graphics/fb0. +allow surfaceflinger graphics_device:dir search; +allow surfaceflinger graphics_device:chr_file rw_file_perms; + +# Access /dev/video1. +allow surfaceflinger video_device:dir r_dir_perms; +allow surfaceflinger video_device:chr_file rw_file_perms; + +# Create and use netlink kobject uevent sockets. +allow surfaceflinger self:netlink_kobject_uevent_socket create_socket_perms; + +# Set properties. +set_prop(surfaceflinger, system_prop) +set_prop(surfaceflinger, ctl_bootanim_prop) + +# Use open files supplied by an app. +allow surfaceflinger app_data_file:file { read write }; + +# Allow a dumpstate triggered screenshot +binder_call(surfaceflinger, dumpstate) +binder_call(surfaceflinger, shell) +r_dir_file(surfaceflinger, dumpstate) + +# Needed on some devices for playing DRM protected content, +# but seems expected and appropriate for all devices. +allow surfaceflinger tee:unix_stream_socket connectto; +allow surfaceflinger tee_device:chr_file rw_file_perms; + + +# media.player service +allow surfaceflinger mediaserver_service:service_manager find; +allow surfaceflinger permission_service:service_manager find; +allow surfaceflinger power_service:service_manager find; +allow surfaceflinger surfaceflinger_service:service_manager { add find }; +allow surfaceflinger window_service:service_manager find; + +### +### Neverallow rules +### +### surfaceflinger should NEVER do any of this + +# Do not allow accessing SDcard files as unsafe ejection could +# cause the kernel to kill the process. +neverallow surfaceflinger sdcard_type:file rw_file_perms;
diff --git a/sepolicy/system_app.te b/sepolicy/system_app.te new file mode 100644 index 0000000..4c9c136 --- /dev/null +++ b/sepolicy/system_app.te
@@ -0,0 +1,74 @@ +# +# Apps that run with the system UID, e.g. com.android.system.ui, +# com.android.settings. These are not as privileged as the system +# server. +# +type system_app, domain, domain_deprecated; +app_domain(system_app) +net_domain(system_app) +binder_service(system_app) + +# Read and write /data/data subdirectory. +allow system_app system_app_data_file:dir create_dir_perms; +allow system_app system_app_data_file:{ file lnk_file } create_file_perms; + +# Read and write to /data/misc/user. +allow system_app misc_user_data_file:dir create_dir_perms; +allow system_app misc_user_data_file:file create_file_perms; + +# Access to vold-mounted storage for measuring free space +allow system_app mnt_media_rw_file:dir search; + +# Read wallpaper file. +allow system_app wallpaper_file:file r_file_perms; + +# Write to properties +set_prop(system_app, bluetooth_prop) +set_prop(system_app, debug_prop) +set_prop(system_app, system_prop) +set_prop(system_app, logd_prop) +set_prop(system_app, net_radio_prop) +set_prop(system_app, system_radio_prop) +userdebug_or_eng(`set_prop(system_app, logpersistd_logging_prop)') +auditallow system_app net_radio_prop:property_service set; +auditallow system_app system_radio_prop:property_service set; + +# ctl interface +set_prop(system_app, ctl_default_prop) +set_prop(system_app, ctl_bugreport_prop) + +# Create /data/anr/traces.txt. +allow system_app anr_data_file:dir ra_dir_perms; +allow system_app anr_data_file:file create_file_perms; + +# Settings need to access app name and icon from asec +allow system_app asec_apk_file:file r_file_perms; + +allow system_app servicemanager:service_manager list; +allow system_app service_manager_type:service_manager find; + +allow system_app keystore:keystore_key { + get_state + get + insert + delete + exist + list + reset + password + lock + unlock + is_empty + sign + verify + grant + duplicate + clear_uid + user_changed +}; + +# /sys access +allow system_app sysfs_zram:dir search; +allow system_app sysfs_zram:file r_file_perms; + +control_logd(system_app)
diff --git a/sepolicy/system_server.te b/sepolicy/system_server.te new file mode 100644 index 0000000..76e28d0 --- /dev/null +++ b/sepolicy/system_server.te
@@ -0,0 +1,508 @@ +# +# System Server aka system_server spawned by zygote. +# Most of the framework services run in this process. +# +type system_server, domain, domain_deprecated, mlstrustedsubject; + +# Define a type for tmpfs-backed ashmem regions. +tmpfs_domain(system_server) + +# For art. +allow system_server dalvikcache_data_file:file execute; +allow system_server dalvikcache_data_file:dir r_dir_perms; + +# /data/resource-cache +allow system_server resourcecache_data_file:file r_file_perms; +allow system_server resourcecache_data_file:dir r_dir_perms; + +# ptrace to processes in the same domain for debugging crashes. +allow system_server self:process ptrace; + +# Child of the zygote. +allow system_server zygote:fd use; +allow system_server zygote:process sigchld; +allow system_server zygote_tmpfs:file read; + +# May kill zygote on crashes. +allow system_server zygote:process sigkill; + +# Read /system/bin/app_process. +allow system_server zygote_exec:file r_file_perms; + +# Needed to close the zygote socket, which involves getopt / getattr +allow system_server zygote:unix_stream_socket { getopt getattr }; + +# system server gets network and bluetooth permissions. +net_domain(system_server) +bluetooth_domain(system_server) + +# These are the capabilities assigned by the zygote to the +# system server. +allow system_server self:capability { + kill + net_admin + net_bind_service + net_broadcast + net_raw + sys_boot + sys_nice + sys_resource + sys_time + sys_tty_config +}; + +wakelock_use(system_server) + +# Triggered by /proc/pid accesses, not allowed. +dontaudit system_server self:capability sys_ptrace; + +# Trigger module auto-load. +allow system_server kernel:system module_request; + +# Allow alarmtimers to be set +allow system_server self:capability2 wake_alarm; + +# Use netlink uevent sockets. +allow system_server self:netlink_kobject_uevent_socket create_socket_perms; + +# Use generic netlink sockets. +allow system_server self:netlink_socket create_socket_perms; +allow system_server self:netlink_generic_socket create_socket_perms; + +# Use generic "sockets" where the address family is not known +# to the kernel. +allow system_server self:socket create_socket_perms; + +# Set and get routes directly via netlink. +allow system_server self:netlink_route_socket nlmsg_write; + +# Kill apps. +allow system_server appdomain:process { sigkill signal }; + +# Set scheduling info for apps. +allow system_server appdomain:process { getsched setsched }; +allow system_server mediaserver:process { getsched setsched }; + +# Read /proc/pid data for all domains. This is used by ProcessCpuTracker +# within system_server to keep track of memory and CPU usage for +# all processes on the device. +r_dir_file(system_server, domain) + +# Read/Write to /proc/net/xt_qtaguid/ctrl and and /dev/xt_qtaguid. +allow system_server qtaguid_proc:file rw_file_perms; +allow system_server qtaguid_device:chr_file rw_file_perms; + +# Read /proc/uid_cputime/show_uid_stat. +allow system_server proc_uid_cputime_showstat:file r_file_perms; + +# Write /proc/uid_cputime/remove_uid_range. +allow system_server proc_uid_cputime_removeuid:file { w_file_perms getattr }; + +# Write to /proc/sysrq-trigger. +allow system_server proc_sysrq:file rw_file_perms; + +# Read /proc/stat for CPU usage statistics +allow system_server proc_stat:file r_file_perms; + +# Read /sys/kernel/debug/wakeup_sources. +allow system_server debugfs:file r_file_perms; + +# The DhcpClient and WifiWatchdog use packet_sockets +allow system_server self:packet_socket create_socket_perms; + +# NetworkDiagnostics requires explicit bind() calls to ping sockets. These aren't actually the same +# as raw sockets, but the kernel doesn't yet distinguish between the two. +allow system_server node:rawip_socket node_bind; + +# 3rd party VPN clients require a tun_socket to be created +allow system_server self:tun_socket create_socket_perms; + +# Talk to init and various daemons via sockets. +unix_socket_connect(system_server, installd, installd) +unix_socket_connect(system_server, lmkd, lmkd) +unix_socket_connect(system_server, mtpd, mtp) +unix_socket_connect(system_server, netd, netd) +unix_socket_connect(system_server, vold, vold) +unix_socket_connect(system_server, zygote, zygote) +unix_socket_connect(system_server, racoon, racoon) +unix_socket_send(system_server, wpa, wpa) + +# Communicate over a socket created by surfaceflinger. +allow system_server surfaceflinger:unix_stream_socket { read write setopt }; + +# Perform Binder IPC. +binder_use(system_server) +binder_call(system_server, binderservicedomain) +binder_call(system_server, gatekeeperd) +binder_call(system_server, fingerprintd) +binder_call(system_server, appdomain) +binder_call(system_server, dumpstate) +binder_service(system_server) + +# Ask debuggerd to dump backtraces for native stacks of interest. +allow system_server { mediaserver sdcardd surfaceflinger inputflinger }:debuggerd dump_backtrace; + +# Read /proc/pid files for dumping stack traces of native processes. +r_dir_file(system_server, mediaserver) +r_dir_file(system_server, sdcardd) +r_dir_file(system_server, surfaceflinger) +r_dir_file(system_server, inputflinger) + +# Use sockets received over binder from various services. +allow system_server mediaserver:tcp_socket rw_socket_perms; +allow system_server mediaserver:udp_socket rw_socket_perms; + +# Check SELinux permissions. +selinux_check_access(system_server) + +# XXX Label sysfs files with a specific type? +allow system_server sysfs:file rw_file_perms; +allow system_server sysfs_nfc_power_writable:file rw_file_perms; +allow system_server sysfs_devices_system_cpu:file w_file_perms; +allow system_server sysfs_mac_address:file r_file_perms; +allow system_server sysfs_thermal:dir search; +allow system_server sysfs_thermal:file r_file_perms; + +# Access devices. +allow system_server device:dir r_dir_perms; +allow system_server mdns_socket:sock_file rw_file_perms; +allow system_server alarm_device:chr_file rw_file_perms; +allow system_server gpu_device:chr_file rw_file_perms; +allow system_server iio_device:chr_file rw_file_perms; +allow system_server input_device:dir r_dir_perms; +allow system_server input_device:chr_file rw_file_perms; +allow system_server radio_device:chr_file r_file_perms; +allow system_server tty_device:chr_file rw_file_perms; +allow system_server usbaccessory_device:chr_file rw_file_perms; +allow system_server video_device:dir r_dir_perms; +allow system_server video_device:chr_file rw_file_perms; +allow system_server adbd_socket:sock_file rw_file_perms; +allow system_server rtc_device:chr_file rw_file_perms; +allow system_server audio_device:dir r_dir_perms; + +# write access needed for MIDI +allow system_server audio_device:chr_file rw_file_perms; + +# tun device used for 3rd party vpn apps +allow system_server tun_device:chr_file rw_file_perms; + +# Manage system data files. +allow system_server system_data_file:dir create_dir_perms; +allow system_server system_data_file:notdevfile_class_set create_file_perms; +allow system_server keychain_data_file:dir create_dir_perms; +allow system_server keychain_data_file:file create_file_perms; +allow system_server keychain_data_file:lnk_file create_file_perms; + +# Manage /data/app. +allow system_server apk_data_file:dir create_dir_perms; +allow system_server apk_data_file:file { create_file_perms link }; +allow system_server apk_tmp_file:dir create_dir_perms; +allow system_server apk_tmp_file:file create_file_perms; + +# Manage /data/app-private. +allow system_server apk_private_data_file:dir create_dir_perms; +allow system_server apk_private_data_file:file create_file_perms; +allow system_server apk_private_tmp_file:dir create_dir_perms; +allow system_server apk_private_tmp_file:file create_file_perms; + +# Manage files within asec containers. +allow system_server asec_apk_file:dir create_dir_perms; +allow system_server asec_apk_file:file create_file_perms; +allow system_server asec_public_file:file create_file_perms; + +# Manage /data/anr. +allow system_server anr_data_file:dir create_dir_perms; +allow system_server anr_data_file:file create_file_perms; + +# Manage /data/backup. +allow system_server backup_data_file:dir create_dir_perms; +allow system_server backup_data_file:file create_file_perms; + +# Write to /data/system/heapdump +allow system_server heapdump_data_file:dir rw_dir_perms; +allow system_server heapdump_data_file:file create_file_perms; + +# Manage /data/misc/adb. +allow system_server adb_keys_file:dir create_dir_perms; +allow system_server adb_keys_file:file create_file_perms; + +# Manage /data/misc/sms. +# TODO: Split into a separate type? +allow system_server radio_data_file:dir create_dir_perms; +allow system_server radio_data_file:file create_file_perms; + +# Manage /data/misc/systemkeys. +allow system_server systemkeys_data_file:dir create_dir_perms; +allow system_server systemkeys_data_file:file create_file_perms; + +# Access /data/tombstones. +allow system_server tombstone_data_file:dir r_dir_perms; +allow system_server tombstone_data_file:file r_file_perms; + +# Manage /data/misc/vpn. +allow system_server vpn_data_file:dir create_dir_perms; +allow system_server vpn_data_file:file create_file_perms; + +# Manage /data/misc/wifi. +allow system_server wifi_data_file:dir create_dir_perms; +allow system_server wifi_data_file:file create_file_perms; + +# Manage /data/misc/zoneinfo. +allow system_server zoneinfo_data_file:dir create_dir_perms; +allow system_server zoneinfo_data_file:file create_file_perms; + +# Walk /data/data subdirectories. +# Types extracted from seapp_contexts type= fields. +allow system_server { system_app_data_file bluetooth_data_file nfc_data_file radio_data_file shell_data_file app_data_file }:dir { getattr read search }; +# Also permit for unlabeled /data/data subdirectories and +# for unlabeled asec containers on upgrades from 4.2. +allow system_server unlabeled:dir r_dir_perms; +# Read pkg.apk file before it has been relabeled by vold. +allow system_server unlabeled:file r_file_perms; + +# Populate com.android.providers.settings/databases/settings.db. +allow system_server system_app_data_file:dir create_dir_perms; +allow system_server system_app_data_file:file create_file_perms; + +# Receive and use open app data files passed over binder IPC. +# Types extracted from seapp_contexts type= fields. +allow system_server { system_app_data_file bluetooth_data_file nfc_data_file radio_data_file shell_data_file app_data_file }:file { getattr read write }; + +# Receive and use open /data/media files passed over binder IPC. +allow system_server media_rw_data_file:file { getattr read write }; + +# Relabel apk files. +allow system_server { apk_tmp_file apk_private_tmp_file }:{ dir file } { relabelfrom relabelto }; +allow system_server { apk_data_file apk_private_data_file }:{ dir file } { relabelfrom relabelto }; + +# Relabel wallpaper. +allow system_server system_data_file:file relabelfrom; +allow system_server wallpaper_file:file relabelto; +allow system_server wallpaper_file:file { rw_file_perms unlink }; + +# FingerprintService.java does a restorecon of the directory /data/system/users/[0-9]+/fpdata(/.*)? +allow system_server system_data_file:dir relabelfrom; + +# Property Service write +set_prop(system_server, system_prop) +set_prop(system_server, safemode_prop) +set_prop(system_server, dhcp_prop) +set_prop(system_server, net_radio_prop) +set_prop(system_server, system_radio_prop) +set_prop(system_server, debug_prop) +set_prop(system_server, powerctl_prop) +set_prop(system_server, fingerprint_prop) +set_prop(system_server, device_logging_prop) + +# ctl interface +set_prop(system_server, ctl_default_prop) +set_prop(system_server, ctl_dhcp_pan_prop) +set_prop(system_server, ctl_bugreport_prop) + +# Create a socket for receiving info from wpa. +type_transition system_server wifi_data_file:sock_file system_wpa_socket; +type_transition system_server wpa_socket:sock_file system_wpa_socket; +allow system_server wpa_socket:dir rw_dir_perms; +allow system_server system_wpa_socket:sock_file create_file_perms; + +# Remove sockets created by wpa_supplicant +allow system_server wpa_socket:sock_file unlink; + +# Create a socket for connections from debuggerd. +type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket"; +allow system_server system_ndebug_socket:sock_file create_file_perms; + +# Manage cache files. +allow system_server { cache_file cache_recovery_file }:dir { relabelfrom create_dir_perms }; +allow system_server { cache_file cache_recovery_file }:file { relabelfrom create_file_perms }; +allow system_server { cache_file cache_recovery_file }:fifo_file create_file_perms; + +# Run system programs, e.g. dexopt. Needed? (b/28035297) +allow system_server system_file:file x_file_perms; +auditallow system_server system_file:file execute_no_trans; + +# LocationManager(e.g, GPS) needs to read and write +# to uart driver and ctrl proc entry +allow system_server gps_control:file rw_file_perms; + +# Allow system_server to use app-created sockets and pipes. +allow system_server appdomain:{ tcp_socket udp_socket } { getattr getopt setopt read write shutdown }; +allow system_server appdomain:{ fifo_file unix_stream_socket } { getattr read write }; + +# Allow abstract socket connection +allow system_server rild:unix_stream_socket connectto; + +# BackupManagerService lets PMS create a data backup file +allow system_server cache_backup_file:file create_file_perms; +# Relabel /data/backup +allow system_server backup_data_file:dir { relabelto relabelfrom }; +# Relabel /cache/.*\.{data|restore} +allow system_server cache_backup_file:file { relabelto relabelfrom }; +# LocalTransport creates and relabels /cache/backup +allow system_server cache_backup_file:dir { relabelto relabelfrom create_dir_perms }; + +# Allow system to talk to usb device +allow system_server usb_device:chr_file rw_file_perms; +allow system_server usb_device:dir r_dir_perms; + +# Allow system to talk to sensors +allow system_server sensors_device:chr_file rw_file_perms; + +# Read from HW RNG (needed by EntropyMixer). +allow system_server hw_random_device:chr_file r_file_perms; + +# Read and delete files under /dev/fscklogs. +r_dir_file(system_server, fscklogs) +allow system_server fscklogs:dir { write remove_name }; +allow system_server fscklogs:file unlink; + +# logd access, system_server inherit logd write socket +# (urge is to deprecate this long term) +allow system_server zygote:unix_dgram_socket write; + +# Read from log daemon. +read_logd(system_server) + +# Be consistent with DAC permissions. Allow system_server to write to +# /sys/module/lowmemorykiller/parameters/adj +# /sys/module/lowmemorykiller/parameters/minfree +allow system_server sysfs_lowmemorykiller:file { getattr w_file_perms }; + +# Read /sys/fs/pstore/console-ramoops +# Don't worry about overly broad permissions for now, as there's +# only one file in /sys/fs/pstore +allow system_server pstorefs:dir r_dir_perms; +allow system_server pstorefs:file r_file_perms; + +# /sys access +allow system_server sysfs_zram:dir search; +allow system_server sysfs_zram:file r_file_perms; + +allow system_server drmserver_service:service_manager find; +allow system_server batteryproperties_service:service_manager find; +allow system_server keystore_service:service_manager find; +allow system_server gatekeeper_service:service_manager find; +allow system_server fingerprintd_service:service_manager find; +allow system_server mediaserver_service:service_manager find; +allow system_server nfc_service:service_manager find; +allow system_server radio_service:service_manager find; +allow system_server system_server_service:service_manager { add find }; +allow system_server surfaceflinger_service:service_manager find; + +allow system_server keystore:keystore_key { + get_state + get + insert + delete + exist + list + reset + password + lock + unlock + is_empty + sign + verify + grant + duplicate + clear_uid + add_auth + user_changed +}; + +# Allow system server to search and write to the persistent factory reset +# protection partition. This block device does not get wiped in a factory reset. +allow system_server block_device:dir search; +allow system_server frp_block_device:blk_file rw_file_perms; + +# Clean up old cgroups +allow system_server cgroup:dir { remove_name rmdir }; + +# /oem access +r_dir_file(system_server, oemfs) + +# Allow resolving per-user storage symlinks +allow system_server { mnt_user_file storage_file }:dir { getattr search }; +allow system_server { mnt_user_file storage_file }:lnk_file { getattr read }; + +# Allow statfs() on storage devices, which happens fast enough that +# we shouldn't be killed during unsafe removal +allow system_server sdcard_type:dir { getattr search }; + +# Traverse into expanded storage +allow system_server mnt_expand_file:dir r_dir_perms; + +# Allow system process to relabel the fingerprint directory after mkdir +# and delete the directory and files when no longer needed +allow system_server fingerprintd_data_file:dir { r_dir_perms remove_name rmdir relabelto write }; +allow system_server fingerprintd_data_file:file { getattr unlink }; + +userdebug_or_eng(` + # Allow system server to create and write method traces in /data/misc/trace. + allow system_server method_trace_data_file:dir w_dir_perms; + allow system_server method_trace_data_file:file { create w_file_perms }; +') + +# For AppFuse. +allow system_server vold:fd use; +allow system_server fuse_device:chr_file { read write ioctl getattr }; + +# For configuring sdcardfs +allow system_server configfs:dir { create_dir_perms }; +allow system_server configfs:file { getattr open unlink write }; + +# Connect to adbd and use a socket transferred from it. +# Used for e.g. jdwp. +allow system_server adbd:unix_stream_socket connectto; +allow system_server adbd:fd use; +allow system_server adbd:unix_stream_socket { getattr getopt ioctl read write shutdown }; + +### +### Neverallow rules +### +### system_server should NEVER do any of this + +# Do not allow opening files from external storage as unsafe ejection +# could cause the kernel to kill the system_server. +neverallow system_server sdcard_type:dir { open read write }; +neverallow system_server sdcard_type:file rw_file_perms; + +# system server should never be operating on zygote spawned app data +# files directly. Rather, they should always be passed via a +# file descriptor. +# Types extracted from seapp_contexts type= fields, excluding +# those types that system_server needs to open directly. +neverallow system_server { bluetooth_data_file nfc_data_file shell_data_file app_data_file }:file { open create unlink link }; + +# Forking and execing is inherently dangerous and racy. See, for +# example, https://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them +# Prevent the addition of new file execs to stop the problem from +# getting worse. b/28035297 +neverallow system_server { file_type -toolbox_exec -logcat_exec -system_file }:file execute_no_trans; + +# System server should never transition to a new domain. This compliments +# and enforces the already pre-existing PR_SET_NO_NEW_PRIVS flag. +neverallow system_server *:process { transition dyntransition }; + +# system_server should never be executing dex2oat. This is either +# a bug (for example, bug 16317188), or represents an attempt by +# system server to dynamically load a dex file, something we do not +# want to allow. +neverallow system_server dex2oat_exec:file no_x_file_perms; + +# system_server should never execute or load executable shared libraries +# in /data except for /data/dalvik-cache files. +neverallow system_server { + data_file_type + -dalvikcache_data_file #mapping with PROT_EXEC +}:file no_x_file_perms; + +# The only block device system_server should be accessing is +# the frp_block_device. This helps avoid a system_server to root +# escalation by writing to raw block devices. +neverallow system_server { dev_type -frp_block_device }:blk_file no_rw_file_perms; + +# system_server should never use JIT functionality +neverallow system_server self:process execmem; +neverallow system_server ashmem_device:chr_file execute; +neverallow system_server system_server_tmpfs:file execute;
diff --git a/sepolicy/te_macros b/sepolicy/te_macros new file mode 100644 index 0000000..ec97b3f --- /dev/null +++ b/sepolicy/te_macros
@@ -0,0 +1,322 @@ +##################################### +# domain_trans(olddomain, type, newdomain) +# Allow a transition from olddomain to newdomain +# upon executing a file labeled with type. +# This only allows the transition; it does not +# cause it to occur automatically - use domain_auto_trans +# if that is what you want. +# +define(`domain_trans', ` +# Old domain may exec the file and transition to the new domain. +allow $1 $2:file { getattr open read execute }; +allow $1 $3:process transition; +# New domain is entered by executing the file. +allow $3 $2:file { entrypoint open read execute getattr }; +# New domain can send SIGCHLD to its caller. +ifelse($1, `init', `', `allow $3 $1:process sigchld;') +# Enable AT_SECURE, i.e. libc secure mode. +dontaudit $1 $3:process noatsecure; +# XXX dontaudit candidate but requires further study. +allow $1 $3:process { siginh rlimitinh }; +') + +##################################### +# domain_auto_trans(olddomain, type, newdomain) +# Automatically transition from olddomain to newdomain +# upon executing a file labeled with type. +# +define(`domain_auto_trans', ` +# Allow the necessary permissions. +domain_trans($1,$2,$3) +# Make the transition occur by default. +type_transition $1 $2:process $3; +') + +##################################### +# file_type_trans(domain, dir_type, file_type) +# Allow domain to create a file labeled file_type in a +# directory labeled dir_type. +# This only allows the transition; it does not +# cause it to occur automatically - use file_type_auto_trans +# if that is what you want. +# +define(`file_type_trans', ` +# Allow the domain to add entries to the directory. +allow $1 $2:dir ra_dir_perms; +# Allow the domain to create the file. +allow $1 $3:notdevfile_class_set create_file_perms; +allow $1 $3:dir create_dir_perms; +') + +##################################### +# file_type_auto_trans(domain, dir_type, file_type) +# Automatically label new files with file_type when +# they are created by domain in directories labeled dir_type. +# +define(`file_type_auto_trans', ` +# Allow the necessary permissions. +file_type_trans($1, $2, $3) +# Make the transition occur by default. +type_transition $1 $2:dir $3; +type_transition $1 $2:notdevfile_class_set $3; +') + +##################################### +# r_dir_file(domain, type) +# Allow the specified domain to read directories, files +# and symbolic links of the specified type. +define(`r_dir_file', ` +allow $1 $2:dir r_dir_perms; +allow $1 $2:{ file lnk_file } r_file_perms; +') + +##################################### +# tmpfs_domain(domain) +# Define and allow access to a unique type for +# this domain when creating tmpfs / shmem / ashmem files. +define(`tmpfs_domain', ` +type $1_tmpfs, file_type; +type_transition $1 tmpfs:file $1_tmpfs; +allow $1 $1_tmpfs:file { read write }; +') + +##################################### +# init_daemon_domain(domain) +# Set up a transition from init to the daemon domain +# upon executing its binary. +define(`init_daemon_domain', ` +domain_auto_trans(init, $1_exec, $1) +tmpfs_domain($1) +') + +##################################### +# app_domain(domain) +# Allow a base set of permissions required for all apps. +define(`app_domain', ` +typeattribute $1 appdomain; +# Label ashmem objects with our own unique type. +tmpfs_domain($1) +# Map with PROT_EXEC. +allow $1 $1_tmpfs:file execute; +') + +##################################### +# net_domain(domain) +# Allow a base set of permissions required for network access. +define(`net_domain', ` +typeattribute $1 netdomain; +') + +##################################### +# bluetooth_domain(domain) +# Allow a base set of permissions required for bluetooth access. +define(`bluetooth_domain', ` +typeattribute $1 bluetoothdomain; +') + +##################################### +# unix_socket_connect(clientdomain, socket, serverdomain) +# Allow a local socket connection from clientdomain via +# socket to serverdomain. +# +# Note: If you see denial records that distill to the +# following allow rules: +# allow clientdomain property_socket:sock_file write; +# allow clientdomain init:unix_stream_socket connectto; +# allow clientdomain something_prop:property_service set; +# +# This sequence is indicative of attempting to set a property. +# use set_prop(sourcedomain, targetproperty) +# +define(`unix_socket_connect', ` +ifelse($2, `property', ` + ifelse($3,`init', ` + print(`deprecated: unix_socket_connect($1, $2, $3) Please use set_prop($1, <property name>) instead.') + ') +') +__unix_socket_connect__($1, $2, $3) +') + +define(`__unix_socket_connect__', ` +allow $1 $2_socket:sock_file write; +allow $1 $3:unix_stream_socket connectto; +') + +##################################### +# set_prop(sourcedomain, targetproperty) +# Allows source domain to set the +# targetproperty. +# +define(`set_prop', ` +__unix_socket_connect__($1, property, init) +allow $1 $2:property_service set; +get_prop($1, $2) +') + +##################################### +# get_prop(sourcedomain, targetproperty) +# Allows source domain to read the +# targetproperty. +# +define(`get_prop', ` +allow $1 $2:file r_file_perms; +') + +##################################### +# unix_socket_send(clientdomain, socket, serverdomain) +# Allow a local socket send from clientdomain via +# socket to serverdomain. +define(`unix_socket_send', ` +allow $1 $2_socket:sock_file write; +allow $1 $3:unix_dgram_socket sendto; +') + +##################################### +# binder_use(domain) +# Allow domain to use Binder IPC. +define(`binder_use', ` +# Call the servicemanager and transfer references to it. +allow $1 servicemanager:binder { call transfer }; +# servicemanager performs getpidcon on clients. +allow servicemanager $1:dir search; +allow servicemanager $1:file { read open }; +allow servicemanager $1:process getattr; +# rw access to /dev/binder and /dev/ashmem is presently granted to +# all domains in domain.te. +') + +##################################### +# binder_call(clientdomain, serverdomain) +# Allow clientdomain to perform binder IPC to serverdomain. +define(`binder_call', ` +# Call the server domain and optionally transfer references to it. +allow $1 $2:binder { call transfer }; +# Allow the serverdomain to transfer references to the client on the reply. +allow $2 $1:binder transfer; +# Receive and use open files from the server. +allow $1 $2:fd use; +') + +##################################### +# binder_service(domain) +# Mark a domain as being a Binder service domain. +# Used to allow binder IPC to the various system services. +define(`binder_service', ` +typeattribute $1 binderservicedomain; +') + +##################################### +# wakelock_use(domain) +# Allow domain to manage wake locks +define(`wakelock_use', ` +# Access /sys/power/wake_lock and /sys/power/wake_unlock +allow $1 sysfs_wake_lock:file rw_file_perms; +# Accessing these files requires CAP_BLOCK_SUSPEND +allow $1 self:capability2 block_suspend; +') + +##################################### +# selinux_check_access(domain) +# Allow domain to check SELinux permissions via selinuxfs. +define(`selinux_check_access', ` +allow $1 selinuxfs:file rw_file_perms; +allow $1 kernel:security compute_av; +allow $1 self:netlink_selinux_socket *; +') + +##################################### +# selinux_check_context(domain) +# Allow domain to check SELinux contexts via selinuxfs. +define(`selinux_check_context', ` +allow $1 selinuxfs:file rw_file_perms; +allow $1 kernel:security check_context; +') + +##################################### +# create_pty(domain) +# Allow domain to create and use a pty, isolated from any other domain ptys. +define(`create_pty', ` +# Each domain gets a unique devpts type. +type $1_devpts, fs_type; +# Label the pty with the unique type when created. +type_transition $1 devpts:chr_file $1_devpts; +# Allow use of the pty after creation. +allow $1 $1_devpts:chr_file { open getattr read write ioctl }; +# Note: devpts:dir search and ptmx_device:chr_file rw_file_perms +# allowed to everyone via domain.te. +') + +##################################### +# Non system_app application set +# +define(`non_system_app_set', `{ appdomain -system_app }') + +##################################### +# Recovery only +# SELinux rules which apply only to recovery mode +# +define(`recovery_only', ifelse(target_recovery, `true', $1, )) + +##################################### +# Userdebug or eng builds +# SELinux rules which apply only to userdebug or eng builds +# +define(`userdebug_or_eng', ifelse(target_build_variant, `eng', $1, ifelse(target_build_variant, `userdebug', $1))) +define(`eng', ifelse(target_build_variant, `eng', $1)) + +##################################### +# write_logd(domain) +# Ability to write to android log +# daemon via sockets +define(`write_logd', ` +unix_socket_send($1, logdw, logd) +allow $1 pmsg_device:chr_file w_file_perms; +') + +##################################### +# read_logd(domain) +# Ability to run logcat and read from android +# log daemon via sockets +define(`read_logd', ` +allow $1 logcat_exec:file rx_file_perms; +unix_socket_connect($1, logdr, logd) +') + +##################################### +# control_logd(domain) +# Ability to control +# android log daemon via sockets +define(`control_logd', ` +# Group AID_LOG checked by filesystem & logd +# to permit control commands +unix_socket_connect($1, logd, logd) +') + +##################################### +# use_keystore(domain) +# Ability to use keystore. +# Keystore is requires the following permissions +# to call getpidcon. +define(`use_keystore', ` + allow keystore $1:dir search; + allow keystore $1:file { read open }; + allow keystore $1:process getattr; + allow $1 keystore_service:service_manager find; + binder_call($1, keystore) +') + +########################################### +# use_drmservice(domain) +# Ability to use DrmService which requires +# DrmService to call getpidcon. +define(`use_drmservice', ` + allow drmserver $1:dir search; + allow drmserver $1:file { read open }; + allow drmserver $1:process getattr; +') + +########################################## +# print a message with a trailing newline +# print(`args') +define(`print', `errprint(`m4: '__file__: __line__`: $* +')')
diff --git a/sepolicy/tee.te b/sepolicy/tee.te new file mode 100644 index 0000000..8ea6b95 --- /dev/null +++ b/sepolicy/tee.te
@@ -0,0 +1,15 @@ +## +# trusted execution environment (tee) daemon +# +type tee, domain, domain_deprecated; +type tee_exec, exec_type, file_type; +type tee_device, dev_type; +type tee_data_file, file_type, data_file_type; + +init_daemon_domain(tee) +allow tee self:capability { dac_override }; +allow tee tee_device:chr_file rw_file_perms; +allow tee tee_data_file:dir rw_dir_perms; +allow tee tee_data_file:file create_file_perms; +allow tee self:netlink_socket create_socket_perms; +allow tee self:netlink_generic_socket create_socket_perms;
diff --git a/sepolicy/toolbox.te b/sepolicy/toolbox.te new file mode 100644 index 0000000..55de7eb --- /dev/null +++ b/sepolicy/toolbox.te
@@ -0,0 +1,26 @@ +# Any toolbox command run by init. +# At present, the only known usage is for running mkswap via fs_mgr. +# Do NOT use this domain for toolbox when run by any other domain. +type toolbox, domain, domain_deprecated; +type toolbox_exec, exec_type, file_type; + +init_daemon_domain(toolbox) + +# /dev/__null__ created by init prior to policy load, +# open fd inherited by fsck. +allow toolbox tmpfs:chr_file { read write ioctl }; + +# Inherit and use pty created by android_fork_execvp_ext(). +allow toolbox devpts:chr_file { read write getattr ioctl }; + +# mkswap-specific. +# Read/write block devices used for swap partitions. +# Assign swap_block_device type any such partition in your +# device/<vendor>/<product>/sepolicy/file_contexts file. +allow toolbox block_device:dir search; +allow toolbox swap_block_device:blk_file rw_file_perms; + +# Only allow entry from init via the toolbox binary. +neverallow { domain -init } toolbox:process transition; +neverallow * toolbox:process dyntransition; +neverallow toolbox { file_type fs_type -toolbox_exec}:file entrypoint;
diff --git a/sepolicy/tools/Android.mk b/sepolicy/tools/Android.mk new file mode 100644 index 0000000..7ded3a3 --- /dev/null +++ b/sepolicy/tools/Android.mk
@@ -0,0 +1,54 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := checkseapp +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := \ + external/selinux/libsepol/include +LOCAL_CFLAGS := -DLINK_SEPOL_STATIC -Wall -Werror +LOCAL_SRC_FILES := check_seapp.c +LOCAL_STATIC_LIBRARIES := libsepol +LOCAL_WHOLE_STATIC_LIBRARIES := libpcre2 +LOCAL_CXX_STL := none + +include $(BUILD_HOST_EXECUTABLE) + +################################### +include $(CLEAR_VARS) + +LOCAL_MODULE := checkfc +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := external/selinux/libsepol/include \ + external/libselinux/include +LOCAL_CFLAGS := -Wall -Werror +LOCAL_SRC_FILES := checkfc.c +LOCAL_STATIC_LIBRARIES := libsepol libselinux +LOCAL_CXX_STL := none + +include $(BUILD_HOST_EXECUTABLE) + +################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := insertkeys.py +LOCAL_SRC_FILES := insertkeys.py +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_IS_HOST_MODULE := true +LOCAL_MODULE_TAGS := optional + +include $(BUILD_PREBUILT) +################################### +include $(CLEAR_VARS) + +LOCAL_MODULE := sepolicy-check +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := external/selinux/libsepol/include +LOCAL_CFLAGS := -Wall -Werror +LOCAL_SRC_FILES := sepolicy-check.c +LOCAL_STATIC_LIBRARIES := libsepol +LOCAL_CXX_STL := none + +include $(BUILD_HOST_EXECUTABLE) + +include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/sepolicy/tools/README b/sepolicy/tools/README new file mode 100644 index 0000000..6035c03 --- /dev/null +++ b/sepolicy/tools/README
@@ -0,0 +1,63 @@ +This directory contains a number of tools related to policy, some of +which are used in building and validating the policy and others are +available for help in auditing and analyzing policy. The tools are +described further below. + +checkfc + A utility for checking the validity of a file_contexts or a + property_contexts configuration file. Used as part of the policy + build to validate both files. Requires the sepolicy file as an + argument in order to check the validity of the security contexts + in the file_contexts or property_contexts file. + + Usage1: + checkfc sepolicy file_contexts + checkfc -p sepolicy property_contexts + + Also used to compare two file_contexts or file_contexts.bin files. + Displays one of subset, equal, superset, or incomparable. + + Usage2: + checkfc -c file_contexts1 file_contexts2 + + Example: + $ checkfc -c out/target/product/shamu/system/etc/general_file_contexts out/target/product/shamu/root/file_contexts.bin + subset + +checkseapp + A utility for merging together the main seapp_contexts + configuration and the device-specific one, and simultaneously + checking the validity of the configurations. Used as part of the + policy build process to merge and validate the configuration. + + Usage: + checkseapp -p sepolicy input_seapp_contexts0 [input_seapp_contexts1...] -o seapp_contexts + +insertkeys.py + A helper script for mapping tags in the signature stanzas of + mac_permissions.xml to public keys found in pem files. This + script is described further in the top-level sepolicy/README. + +post_process_mac_perms + A tool to help modify an existing mac_permissions.xml with additional app + certs not already found in that policy. This becomes useful when a directory + containing apps is searched and the certs from those apps are added to the + policy not already explicitly listed. + + Usage: + post_process_mac_perms [-h] -s SEINFO -d DIR -f POLICY + + -s SEINFO, --seinfo SEINFO seinfo tag for each generated stanza + -d DIR, --dir DIR Directory to search for apks + -f POLICY, --file POLICY mac_permissions.xml policy file + +sepolicy-check + A tool for auditing a sepolicy file for any allow rule that grants + a given permission. + + Usage: + sepolicy-check -s <domain> -t <type> -c <class> -p <permission> -P out/target/product/<board>/root/sepolicy + +sepolicy-analyze + A tool for performing various kinds of analysis on a sepolicy + file.
diff --git a/sepolicy/tools/check_seapp.c b/sepolicy/tools/check_seapp.c new file mode 100644 index 0000000..26a47b5 --- /dev/null +++ b/sepolicy/tools/check_seapp.c
@@ -0,0 +1,1252 @@ +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdint.h> +#include <search.h> +#include <stdbool.h> +#include <sepol/sepol.h> +#include <sepol/policydb/policydb.h> +#include <pcre2.h> + +#define TABLE_SIZE 1024 +#define KVP_NUM_OF_RULES (sizeof(rules) / sizeof(key_map)) +#define log_set_verbose() do { logging_verbose = 1; log_info("Enabling verbose\n"); } while(0) +#define log_error(fmt, ...) log_msg(stderr, "Error: ", fmt, ##__VA_ARGS__) +#define log_warn(fmt, ...) log_msg(stderr, "Warning: ", fmt, ##__VA_ARGS__) +#define log_info(fmt, ...) if (logging_verbose ) { log_msg(stdout, "Info: ", fmt, ##__VA_ARGS__); } + +/** + * Initializes an empty, static list. + */ +#define list_init(free_fn) { .head = NULL, .tail = NULL, .freefn = (free_fn) } + +/** + * given an item in the list, finds the offset for the container + * it was stored in. + * + * @element The element from the list + * @type The container type ie what you allocated that has the list_element structure in it. + * @name The name of the field that is the list_element + * + */ +#define list_entry(element, type, name) \ + (type *)(((uint8_t *)(element)) - (uint8_t *)&(((type *)NULL)->name)) + +/** + * Iterates over the list, do not free elements from the list when using this. + * @list The list head to walk + * @var The variable name for the cursor + */ +#define list_for_each(list, var) \ + for(var = (list)->head; var != NULL; var = var->next) /*NOLINT*/ + + +typedef struct hash_entry hash_entry; +typedef enum key_dir key_dir; +typedef enum data_type data_type; +typedef enum rule_map_switch rule_map_switch; +typedef enum map_match map_match; +typedef struct key_map key_map; +typedef struct kvp kvp; +typedef struct rule_map rule_map; +typedef struct policy_info policy_info; +typedef struct list_element list_element; +typedef struct list list; +typedef struct key_map_regex key_map_regex; +typedef struct file_info file_info; + +enum map_match { + map_no_matches, + map_input_matched, + map_matched +}; + +const char *map_match_str[] = { + "do not match", + "match on all inputs", + "match on everything" +}; + +/** + * Whether or not the "key" from a key vaue pair is considered an + * input or an output. + */ +enum key_dir { + dir_in, dir_out +}; + +struct list_element { + list_element *next; +}; + +struct list { + list_element *head; + list_element *tail; + void (*freefn)(list_element *e); +}; + +struct key_map_regex { + pcre2_code *compiled; + pcre2_match_data *match_data; +}; + +/** + * The workhorse of the logic. This struct maps key value pairs to + * an associated set of meta data maintained in rule_map_new() + */ +struct key_map { + char *name; + key_dir dir; + char *data; + key_map_regex regex; + bool (*fn_validate)(char *value, char **errmsg); +}; + +/** + * Key value pair struct, this represents the raw kvp values coming + * from the rules files. + */ +struct kvp { + char *key; + char *value; +}; + +/** + * Rules are made up of meta data and an associated set of kvp stored in a + * key_map array. + */ +struct rule_map { + bool is_never_allow; + list violations; + list_element listify; + char *key; /** key value before hashing */ + size_t length; /** length of the key map */ + int lineno; /** Line number rule was encounter on */ + char *filename; /** File it was found in */ + key_map m[]; /** key value mapping */ +}; + +struct hash_entry { + list_element listify; + rule_map *r; /** The rule map to store at that location */ +}; + +/** + * Data associated for a policy file + */ +struct policy_info { + + char *policy_file_name; /** policy file path name */ + FILE *policy_file; /** file handle to the policy file */ + sepol_policydb_t *db; + sepol_policy_file_t *pf; + sepol_handle_t *handle; + sepol_context_t *con; +}; + +struct file_info { + FILE *file; /** file itself */ + const char *name; /** name of file. do not free, these are not alloc'd */ + list_element listify; +}; + +static void input_file_list_freefn(list_element *e); +static void line_order_list_freefn(list_element *e); +static void rule_map_free(rule_map *rm, bool is_in_htable); + +/** Set to !0 to enable verbose logging */ +static int logging_verbose = 0; + +/** file handle to the output file */ +static file_info out_file; + +static list input_file_list = list_init(input_file_list_freefn); + +static policy_info pol = { + .policy_file_name = NULL, + .policy_file = NULL, + .db = NULL, + .pf = NULL, + .handle = NULL, + .con = NULL +}; + +/** + * Head pointer to a linked list of + * rule map table entries (hash_entry), used for + * preserving the order of entries + * based on "first encounter" + */ +static list line_order_list = list_init(line_order_list_freefn); + +/* + * List of hash_entrys for never allow rules. + */ +static list nallow_list = list_init(line_order_list_freefn); + +/* validation call backs */ +static bool validate_bool(char *value, char **errmsg); +static bool validate_levelFrom(char *value, char **errmsg); +static bool validate_selinux_type(char *value, char **errmsg); +static bool validate_selinux_level(char *value, char **errmsg); + +/** + * The heart of the mapping process, this must be updated if a new key value pair is added + * to a rule. + */ +key_map rules[] = { + /*Inputs*/ + { .name = "isSystemServer", .dir = dir_in, .fn_validate = validate_bool }, + { .name = "isOwner", .dir = dir_in, .fn_validate = validate_bool }, + { .name = "user", .dir = dir_in, }, + { .name = "seinfo", .dir = dir_in, }, + { .name = "name", .dir = dir_in, }, + { .name = "path", .dir = dir_in, }, + { .name = "isPrivApp", .dir = dir_in, .fn_validate = validate_bool }, + /*Outputs*/ + { .name = "domain", .dir = dir_out, .fn_validate = validate_selinux_type }, + { .name = "type", .dir = dir_out, .fn_validate = validate_selinux_type }, + { .name = "levelFromUid", .dir = dir_out, .fn_validate = validate_bool }, + { .name = "levelFrom", .dir = dir_out, .fn_validate = validate_levelFrom }, + { .name = "level", .dir = dir_out, .fn_validate = validate_selinux_level }, +}; + +/** + * Appends to the end of the list. + * @list The list to append to + * @e the element to append + */ +void list_append(list *list, list_element *e) { + + memset(e, 0, sizeof(*e)); + + if (list->head == NULL ) { + list->head = list->tail = e; + return; + } + + list->tail->next = e; + list->tail = e; + return; +} + +/** + * Free's all the elements in the specified list. + * @list The list to free + */ +static void list_free(list *list) { + + list_element *tmp; + list_element *cursor = list->head; + + while (cursor) { + tmp = cursor; + cursor = cursor->next; + if (list->freefn) { + list->freefn(tmp); + } + } +} + +/* + * called when the lists are freed + */ +static void line_order_list_freefn(list_element *e) { + hash_entry *h = list_entry(e, typeof(*h), listify); + rule_map_free(h->r, true); + free(h); +} + +static void input_file_list_freefn(list_element *e) { + file_info *f = list_entry(e, typeof(*f), listify); + + if (f->file) { + fclose(f->file); + } + free(f); +} + +/** + * Send a logging message to a file + * @param out + * Output file to send message too + * @param prefix + * A special prefix to write to the file, such as "Error:" + * @param fmt + * The printf style formatter to use, such as "%d" + */ +static void __attribute__ ((format(printf, 3, 4))) +log_msg(FILE *out, const char *prefix, const char *fmt, ...) { + + fprintf(out, "%s", prefix); + va_list args; + va_start(args, fmt); + vfprintf(out, fmt, args); + va_end(args); +} + +/** + * Checks for a type in the policy. + * @param db + * The policy db to search + * @param type + * The type to search for + * @return + * 1 if the type is found, 0 otherwise. + * @warning + * This function always returns 1 if libsepol is not linked + * statically to this executable and LINK_SEPOL_STATIC is not + * defined. + */ +static int check_type(sepol_policydb_t *db, char *type) { + + int rc = 1; +#if defined(LINK_SEPOL_STATIC) + policydb_t *d = (policydb_t *)db; + hashtab_datum_t dat; + dat = hashtab_search(d->p_types.table, type); + rc = (dat == NULL) ? 0 : 1; +#endif + return rc; +} + +static bool match_regex(key_map *assert, const key_map *check) { + + char *tomatch = check->data; + + int ret = pcre2_match(assert->regex.compiled, (PCRE2_SPTR) tomatch, + PCRE2_ZERO_TERMINATED, 0, 0, + assert->regex.match_data, NULL); + + /* ret > 0 from pcre2_match means matched */ + return ret > 0; +} + +static bool compile_regex(key_map *km, int *errcode, PCRE2_SIZE *erroff) { + + size_t size; + char *anchored; + + /* + * Explicitly anchor all regex's + * The size is the length of the string to anchor (km->data), the anchor + * characters ^ and $ and the null byte. Hence strlen(km->data) + 3 + */ + size = strlen(km->data) + 3; + anchored = alloca(size); + sprintf(anchored, "^%s$", km->data); + + km->regex.compiled = pcre2_compile((PCRE2_SPTR) anchored, + PCRE2_ZERO_TERMINATED, + PCRE2_DOTALL, + errcode, erroff, + NULL); + if (!km->regex.compiled) { + return false; + } + + km->regex.match_data = pcre2_match_data_create_from_pattern( + km->regex.compiled, NULL); + if (!km->regex.match_data) { + pcre2_code_free(km->regex.compiled); + return false; + } + return true; +} + +static bool validate_bool(char *value, char **errmsg) { + + if (!strcmp("true", value) || !strcmp("false", value)) { + return true; + } + + *errmsg = "Expecting \"true\" or \"false\""; + return false; +} + +static bool validate_levelFrom(char *value, char **errmsg) { + + if(strcasecmp(value, "none") && strcasecmp(value, "all") && + strcasecmp(value, "app") && strcasecmp(value, "user")) { + *errmsg = "Expecting one of: \"none\", \"all\", \"app\" or \"user\""; + return false; + } + return true; +} + +static bool validate_selinux_type(char *value, char **errmsg) { + + /* + * No policy file present means we cannot check + * SE Linux types + */ + if (!pol.policy_file) { + return true; + } + + if(!check_type(pol.db, value)) { + *errmsg = "Expecting a valid SELinux type"; + return false; + } + + return true; +} + +static bool validate_selinux_level(char *value, char **errmsg) { + + /* + * No policy file present means we cannot check + * SE Linux MLS + */ + if (!pol.policy_file) { + return true; + } + + int ret = sepol_mls_check(pol.handle, pol.db, value); + if (ret < 0) { + *errmsg = "Expecting a valid SELinux MLS value"; + return false; + } + + return true; +} + +/** + * Validates a key_map against a set of enforcement rules, this + * function exits the application on a type that cannot be properly + * checked + * + * @param m + * The key map to check + * @param lineno + * The line number in the source file for the corresponding key map + * @return + * true if valid, false if invalid + */ +static bool key_map_validate(key_map *m, const char *filename, int lineno, + bool is_neverallow) { + + PCRE2_SIZE erroff; + int errcode; + bool rc = true; + char *key = m->name; + char *value = m->data; + char *errmsg = NULL; + char errstr[256]; + + log_info("Validating %s=%s\n", key, value); + + /* + * Neverallows are completely skipped from sanity checking so you can match + * un-unspecified inputs. + */ + if (is_neverallow) { + if (!m->regex.compiled) { + rc = compile_regex(m, &errcode, &erroff); + if (!rc) { + pcre2_get_error_message(errcode, + (PCRE2_UCHAR*) errstr, + sizeof(errstr)); + log_error("Invalid regex on line %d : %s PCRE error: %s at offset %lu", + lineno, value, errstr, erroff); + } + } + goto out; + } + + /* If the key has a validation routine, call it */ + if (m->fn_validate) { + rc = m->fn_validate(value, &errmsg); + + if (!rc) { + log_error("Could not validate key \"%s\" for value \"%s\" on line: %d in file: \"%s\": %s\n", key, value, + lineno, filename, errmsg); + } + } + +out: + log_info("Key map validate returning: %d\n", rc); + return rc; +} + +/** + * Prints a rule map back to a file + * @param fp + * The file handle to print too + * @param r + * The rule map to print + */ +static void rule_map_print(FILE *fp, rule_map *r) { + + size_t i; + key_map *m; + + for (i = 0; i < r->length; i++) { + m = &(r->m[i]); + if (i < r->length - 1) + fprintf(fp, "%s=%s ", m->name, m->data); + else + fprintf(fp, "%s=%s", m->name, m->data); + } +} + +/** + * Compare two rule maps for equality + * @param rmA + * a rule map to check + * @param rmB + * a rule map to check + * @return + * a map_match enum indicating the result + */ +static map_match rule_map_cmp(rule_map *rmA, rule_map *rmB) { + + size_t i; + size_t j; + int inputs_found = 0; + int num_of_matched_inputs = 0; + int input_mode = 0; + size_t matches = 0; + key_map *mA; + key_map *mB; + + for (i = 0; i < rmA->length; i++) { + mA = &(rmA->m[i]); + + for (j = 0; j < rmB->length; j++) { + mB = &(rmB->m[j]); + input_mode = 0; + + if (strcmp(mA->name, mB->name)) + continue; + + if (strcmp(mA->data, mB->data)) + continue; + + if (mB->dir != mA->dir) + continue; + else if (mB->dir == dir_in) { + input_mode = 1; + inputs_found++; + } + + if (input_mode) { + log_info("Matched input lines: name=%s data=%s\n", mA->name, mA->data); + num_of_matched_inputs++; + } + + /* Match found, move on */ + log_info("Matched lines: name=%s data=%s", mA->name, mA->data); + matches++; + break; + } + } + + /* If they all matched*/ + if (matches == rmA->length) { + log_info("Rule map cmp MATCH\n"); + return map_matched; + } + + /* They didn't all match but the input's did */ + else if (num_of_matched_inputs == inputs_found) { + log_info("Rule map cmp INPUT MATCH\n"); + return map_input_matched; + } + + /* They didn't all match, and the inputs didn't match, ie it didn't + * match */ + else { + log_info("Rule map cmp NO MATCH\n"); + return map_no_matches; + } +} + +/** + * Frees a rule map + * @param rm + * rule map to be freed. + * @is_in_htable + * True if the rule map has been added to the hash table, false + * otherwise. + */ +static void rule_map_free(rule_map *rm, bool is_in_htable) { + + size_t i; + size_t len = rm->length; + for (i = 0; i < len; i++) { + key_map *m = &(rm->m[i]); + free(m->data); + + if (m->regex.compiled) { + pcre2_code_free(m->regex.compiled); + } + + if (m->regex.match_data) { + pcre2_match_data_free(m->regex.match_data); + } + } + + /* + * hdestroy() frees comparsion keys for non glibc + * on GLIBC we always free on NON-GLIBC we free if + * it is not in the htable. + */ + if (rm->key) { +#ifdef __GLIBC__ + /* silence unused warning */ + (void)is_in_htable; + free(rm->key); +#else + if (!is_in_htable) { + free(rm->key); + } +#endif + } + + free(rm->filename); + free(rm); +} + +static void free_kvp(kvp *k) { + free(k->key); + free(k->value); +} + +/** + * Checks a rule_map for any variation of KVP's that shouldn't be allowed. + * It builds an assertion failure list for each rule map. + * Note that this function logs all errors. + * + * Current Checks: + * 1. That a specified name entry should have a specified seinfo entry as well. + * 2. That no rule violates a neverallow + * @param rm + * The rule map to check for validity. + */ +static void rule_map_validate(rule_map *rm) { + + size_t i, j; + const key_map *rule; + key_map *nrule; + hash_entry *e; + rule_map *assert; + list_element *cursor; + + list_for_each(&nallow_list, cursor) { + e = list_entry(cursor, typeof(*e), listify); + assert = e->r; + + size_t cnt = 0; + + for (j = 0; j < assert->length; j++) { + nrule = &(assert->m[j]); + + // mark that nrule->name is for a null check + bool is_null_check = !strcmp(nrule->data, "\"\""); + + for (i = 0; i < rm->length; i++) { + rule = &(rm->m[i]); + + if (!strcmp(rule->name, nrule->name)) { + + /* the name was found, (data cannot be false) then it was specified */ + is_null_check = false; + + if (match_regex(nrule, rule)) { + cnt++; + } + } + } + + /* + * the nrule was marked in a null check and we never found a match on nrule, thus + * it matched and we update the cnt + */ + if (is_null_check) { + cnt++; + } + } + if (cnt == assert->length) { + list_append(&rm->violations, &assert->listify); + } + } +} + +/** + * Given a set of key value pairs, this will construct a new rule map. + * On error this function calls exit. + * @param keys + * Keys from a rule line to map + * @param num_of_keys + * The length of the keys array + * @param lineno + * The line number the keys were extracted from + * @return + * A rule map pointer. + */ +static rule_map *rule_map_new(kvp keys[], size_t num_of_keys, int lineno, + const char *filename, bool is_never_allow) { + + size_t i = 0, j = 0; + rule_map *new_map = NULL; + kvp *k = NULL; + key_map *r = NULL, *x = NULL; + bool seen[KVP_NUM_OF_RULES]; + + for (i = 0; i < KVP_NUM_OF_RULES; i++) + seen[i] = false; + + new_map = calloc(1, (num_of_keys * sizeof(key_map)) + sizeof(rule_map)); + if (!new_map) + goto oom; + + new_map->is_never_allow = is_never_allow; + new_map->length = num_of_keys; + new_map->lineno = lineno; + new_map->filename = strdup(filename); + if (!new_map->filename) { + goto oom; + } + + /* For all the keys in a rule line*/ + for (i = 0; i < num_of_keys; i++) { + k = &(keys[i]); + r = &(new_map->m[i]); + + for (j = 0; j < KVP_NUM_OF_RULES; j++) { + x = &(rules[j]); + + /* Only assign key name to map name */ + if (strcasecmp(k->key, x->name)) { + if (i == KVP_NUM_OF_RULES) { + log_error("No match for key: %s\n", k->key); + goto err; + } + continue; + } + + if (seen[j]) { + log_error("Duplicated key: %s\n", k->key); + goto err; + } + seen[j] = true; + + memcpy(r, x, sizeof(key_map)); + + /* Assign rule map value to one from file */ + r->data = strdup(k->value); + if (!r->data) + goto oom; + + /* Enforce type check*/ + log_info("Validating keys!\n"); + if (!key_map_validate(r, filename, lineno, new_map->is_never_allow)) { + log_error("Could not validate\n"); + goto err; + } + + /* + * Only build key off of inputs with the exception of neverallows. + * Neverallows are keyed off of all key value pairs, + */ + if (r->dir == dir_in || new_map->is_never_allow) { + char *tmp; + int key_len = strlen(k->key); + int val_len = strlen(k->value); + int l = (new_map->key) ? strlen(new_map->key) : 0; + l = l + key_len + val_len; + l += 1; + + tmp = realloc(new_map->key, l); + if (!tmp) + goto oom; + + if (!new_map->key) + memset(tmp, 0, l); + + new_map->key = tmp; + + strncat(new_map->key, k->key, key_len); + strncat(new_map->key, k->value, val_len); + } + break; + } + free_kvp(k); + } + + if (new_map->key == NULL) { + log_error("Strange, no keys found, input file corrupt perhaps?\n"); + goto err; + } + + return new_map; + +oom: + log_error("Out of memory!\n"); +err: + if(new_map) { + rule_map_free(new_map, false); + for (; i < num_of_keys; i++) { + k = &(keys[i]); + free_kvp(k); + } + } + return NULL; +} + +/** + * Print the usage of the program + */ +static void usage() { + printf( + "checkseapp [options] <input file>\n" + "Processes an seapp_contexts file specified by argument <input file> (default stdin) " + "and allows later declarations to override previous ones on a match.\n" + "Options:\n" + "-h - print this help message\n" + "-v - enable verbose debugging informations\n" + "-p policy file - specify policy file for strict checking of output selectors against the policy\n" + "-o output file - specify output file or - for stdout. No argument runs in silent mode and outputs nothing\n"); +} + +static void init() { + + bool has_out_file; + list_element *cursor; + file_info *tmp; + + /* input files if the list is empty, use stdin */ + if (!input_file_list.head) { + log_info("Using stdin for input\n"); + tmp = malloc(sizeof(*tmp)); + if (!tmp) { + log_error("oom"); + exit(EXIT_FAILURE); + } + tmp->name = "stdin"; + tmp->file = stdin; + list_append(&input_file_list, &(tmp->listify)); + } + else { + list_for_each(&input_file_list, cursor) { + tmp = list_entry(cursor, typeof(*tmp), listify); + + log_info("Opening input file: \"%s\"\n", tmp->name); + tmp->file = fopen(tmp->name, "r"); + if (!tmp->file) { + log_error("Could not open file: %s error: %s\n", tmp->name, + strerror(errno)); + exit(EXIT_FAILURE); + } + } + } + + has_out_file = out_file.name != NULL; + + /* If output file is -, then use stdout, else open the path */ + if (has_out_file && !strcmp(out_file.name, "-")) { + out_file.file = stdout; + out_file.name = "stdout"; + } + else if (has_out_file) { + out_file.file = fopen(out_file.name, "w+"); + } + + if (has_out_file && !out_file.file) { + log_error("Could not open file: \"%s\" error: \"%s\"\n", out_file.name, + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (pol.policy_file_name) { + log_info("Opening policy file: %s\n", pol.policy_file_name); + pol.policy_file = fopen(pol.policy_file_name, "rb"); + if (!pol.policy_file) { + log_error("Could not open file: %s error: %s\n", + pol.policy_file_name, strerror(errno)); + exit(EXIT_FAILURE); + } + + pol.handle = sepol_handle_create(); + if (!pol.handle) { + log_error("Could not create sepolicy handle: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (sepol_policy_file_create(&pol.pf) < 0) { + log_error("Could not create sepolicy file: %s!\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + + sepol_policy_file_set_fp(pol.pf, pol.policy_file); + sepol_policy_file_set_handle(pol.pf, pol.handle); + + if (sepol_policydb_create(&pol.db) < 0) { + log_error("Could not create sepolicy db: %s!\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (sepol_policydb_read(pol.db, pol.pf) < 0) { + log_error("Could not lod policy file to db: %s!\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + } + + list_for_each(&input_file_list, cursor) { + tmp = list_entry(cursor, typeof(*tmp), listify); + log_info("Input file set to: \"%s\"\n", tmp->name); + } + + log_info("Policy file set to: \"%s\"\n", + (pol.policy_file_name == NULL) ? "None" : pol.policy_file_name); + log_info("Output file set to: \"%s\"\n", out_file.name); + +#if !defined(LINK_SEPOL_STATIC) + log_warn("LINK_SEPOL_STATIC is not defined\n""Not checking types!"); +#endif + +} + +/** + * Handle parsing and setting the global flags for the command line + * options. This function calls exit on failure. + * @param argc + * argument count + * @param argv + * argument list + */ +static void handle_options(int argc, char *argv[]) { + + int c; + file_info *input_file; + + while ((c = getopt(argc, argv, "ho:p:v")) != -1) { + switch (c) { + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 'o': + out_file.name = optarg; + break; + case 'p': + pol.policy_file_name = optarg; + break; + case 'v': + log_set_verbose(); + break; + case '?': + if (optopt == 'o' || optopt == 'p') + log_error("Option -%c requires an argument.\n", optopt); + else if (isprint (optopt)) + log_error("Unknown option `-%c'.\n", optopt); + else { + log_error( + "Unknown option character `\\x%x'.\n", + optopt); + } + default: + exit(EXIT_FAILURE); + } + } + + for (c = optind; c < argc; c++) { + + input_file = calloc(1, sizeof(*input_file)); + if (!input_file) { + log_error("oom"); + exit(EXIT_FAILURE); + } + input_file->name = argv[c]; + list_append(&input_file_list, &input_file->listify); + } +} + +/** + * Adds a rule to the hash table and to the ordered list if needed. + * @param rm + * The rule map to add. + */ +static void rule_add(rule_map *rm) { + + map_match cmp; + ENTRY e; + ENTRY *f; + hash_entry *entry; + hash_entry *tmp; + list *list_to_addto; + + e.key = rm->key; + + log_info("Searching for key: %s\n", e.key); + /* Check to see if it has already been added*/ + f = hsearch(e, FIND); + + /* + * Since your only hashing on a partial key, the inputs we need to handle + * when you want to override the outputs for a given input set, as well as + * checking for duplicate entries. + */ + if(f) { + log_info("Existing entry found!\n"); + tmp = (hash_entry *)f->data; + cmp = rule_map_cmp(rm, tmp->r); + log_error("Duplicate line detected in file: %s\n" + "Lines %d and %d %s!\n", + rm->filename, tmp->r->lineno, rm->lineno, + map_match_str[cmp]); + rule_map_free(rm, false); + goto err; + } + /* It wasn't found, just add the rule map to the table */ + else { + + entry = malloc(sizeof(hash_entry)); + if (!entry) + goto oom; + + entry->r = rm; + e.data = entry; + + f = hsearch(e, ENTER); + if(f == NULL) { + goto oom; + } + + /* new entries must be added to the ordered list */ + entry->r = rm; + list_to_addto = rm->is_never_allow ? &nallow_list : &line_order_list; + list_append(list_to_addto, &entry->listify); + } + + return; +oom: + if (e.key) + free(e.key); + if (entry) + free(entry); + if (rm) + free(rm); + log_error("Out of memory in function: %s\n", __FUNCTION__); +err: + exit(EXIT_FAILURE); +} + +static void parse_file(file_info *in_file) { + + char *p; + size_t len; + char *token; + char *saveptr; + bool is_never_allow; + bool found_whitespace; + + size_t lineno = 0; + char *name = NULL; + char *value = NULL; + size_t token_cnt = 0; + + char line_buf[BUFSIZ]; + kvp keys[KVP_NUM_OF_RULES]; + + while (fgets(line_buf, sizeof(line_buf) - 1, in_file->file)) { + lineno++; + is_never_allow = false; + found_whitespace = false; + log_info("Got line %zu\n", lineno); + len = strlen(line_buf); + if (line_buf[len - 1] == '\n') + line_buf[len - 1] = '\0'; + p = line_buf; + + /* neverallow lines must start with neverallow (ie ^neverallow) */ + if (!strncasecmp(p, "neverallow", strlen("neverallow"))) { + p += strlen("neverallow"); + is_never_allow = true; + } + + /* strip trailing whitespace skip comments */ + while (isspace(*p)) { + p++; + found_whitespace = true; + } + if (*p == '#' || *p == '\0') + continue; + + token = strtok_r(p, " \t", &saveptr); + if (!token) + goto err; + + token_cnt = 0; + memset(keys, 0, sizeof(kvp) * KVP_NUM_OF_RULES); + while (1) { + + name = token; + value = strchr(name, '='); + if (!value) + goto err; + *value++ = 0; + + keys[token_cnt].key = strdup(name); + if (!keys[token_cnt].key) + goto oom; + + keys[token_cnt].value = strdup(value); + if (!keys[token_cnt].value) + goto oom; + + token_cnt++; + + token = strtok_r(NULL, " \t", &saveptr); + if (!token) + break; + + } /*End token parsing */ + + rule_map *r = rule_map_new(keys, token_cnt, lineno, in_file->name, is_never_allow); + if (!r) + goto err; + rule_add(r); + + } /* End file parsing */ + return; + +err: + log_error("Reading file: \"%s\" line: %zu name: \"%s\" value: \"%s\"\n", + in_file->name, lineno, name, value); + if(found_whitespace && name && !strcasecmp(name, "neverallow")) { + log_error("perhaps whitespace before neverallow\n"); + } + exit(EXIT_FAILURE); +oom: + log_error("In function %s: Out of memory\n", __FUNCTION__); + exit(EXIT_FAILURE); +} + +/** + * Parses the seapp_contexts file and neverallow file + * and adds them to the hash table and ordered list entries + * when it encounters them. + * Calls exit on failure. + */ +static void parse() { + + file_info *current; + list_element *cursor; + list_for_each(&input_file_list, cursor) { + current = list_entry(cursor, typeof(*current), listify); + parse_file(current); + } +} + +static void validate() { + + list_element *cursor, *v; + bool found_issues = false; + hash_entry *e; + rule_map *r; + list_for_each(&line_order_list, cursor) { + e = list_entry(cursor, typeof(*e), listify); + rule_map_validate(e->r); + } + + list_for_each(&line_order_list, cursor) { + e = list_entry(cursor, typeof(*e), listify); + r = e->r; + list_for_each(&r->violations, v) { + found_issues = true; + log_error("Rule in File \"%s\" on line %d: \"", e->r->filename, e->r->lineno); + rule_map_print(stderr, e->r); + r = list_entry(v, rule_map, listify); + fprintf(stderr, "\" violates neverallow in File \"%s\" on line %d: \"", r->filename, r->lineno); + rule_map_print(stderr, r); + fprintf(stderr, "\"\n"); + } + } + + if (found_issues) { + exit(EXIT_FAILURE); + } +} + +/** + * Should be called after parsing to cause the printing of the rule_maps + * stored in the ordered list, head first, which preserves the "first encountered" + * ordering. + */ +static void output() { + + hash_entry *e; + list_element *cursor; + + if (!out_file.file) { + log_info("No output file, not outputting.\n"); + return; + } + + list_for_each(&line_order_list, cursor) { + e = list_entry(cursor, hash_entry, listify); + rule_map_print(out_file.file, e->r); + fprintf(out_file.file, "\n"); + } +} + +/** + * This function is registered to the at exit handler and should clean up + * the programs dynamic resources, such as memory and fd's. + */ +static void cleanup() { + + /* Only close this when it was opened by me and not the crt */ + if (out_file.name && strcmp(out_file.name, "stdout") && out_file.file) { + log_info("Closing file: %s\n", out_file.name); + fclose(out_file.file); + } + + if (pol.policy_file) { + + log_info("Closing file: %s\n", pol.policy_file_name); + fclose(pol.policy_file); + + if (pol.db) + sepol_policydb_free(pol.db); + + if (pol.pf) + sepol_policy_file_free(pol.pf); + + if (pol.handle) + sepol_handle_destroy(pol.handle); + } + + log_info("Freeing lists\n"); + list_free(&input_file_list); + list_free(&line_order_list); + list_free(&nallow_list); + hdestroy(); +} + +int main(int argc, char *argv[]) { + if (!hcreate(TABLE_SIZE)) { + log_error("Could not create hash table: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + atexit(cleanup); + handle_options(argc, argv); + init(); + log_info("Starting to parse\n"); + parse(); + log_info("Parsing completed, generating output\n"); + validate(); + output(); + log_info("Success, generated output\n"); + exit(EXIT_SUCCESS); +}
diff --git a/sepolicy/tools/checkfc.c b/sepolicy/tools/checkfc.c new file mode 100644 index 0000000..e7d19b0 --- /dev/null +++ b/sepolicy/tools/checkfc.c
@@ -0,0 +1,379 @@ +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sepol/module.h> +#include <sepol/policydb/policydb.h> +#include <sepol/sepol.h> +#include <selinux/selinux.h> +#include <selinux/label.h> +#include <sys/stat.h> +#include <sys/types.h> + +static const char * const CHECK_FC_ASSERT_ATTRS[] = { "fs_type", "dev_type", "file_type", NULL }; +static const char * const CHECK_PC_ASSERT_ATTRS[] = { "property_type", NULL }; +static const char * const CHECK_SC_ASSERT_ATTRS[] = { "service_manager_type", NULL }; + +typedef enum filemode filemode; +enum filemode { + filemode_file_contexts = 0, + filemode_property_contexts, + filemode_service_contexts +}; + +static struct { + /* policy */ + struct { + union { + /* Union these so we don't have to cast */ + sepol_policydb_t *sdb; + policydb_t *pdb; + }; + sepol_policy_file_t *pf; + sepol_handle_t *handle; + FILE *file; +#define SEHANDLE_CNT 2 + struct selabel_handle *sehnd[SEHANDLE_CNT]; + } sepolicy; + + /* assertions */ + struct { + const char * const *attrs; /* for the original set to print on error */ + ebitmap_t set; /* the ebitmap representation of the attrs */ + } assert; + +} global_state; + +static const char * const *filemode_to_assert_attrs(filemode mode) +{ + switch (mode) { + case filemode_file_contexts: + return CHECK_FC_ASSERT_ATTRS; + case filemode_property_contexts: + return CHECK_PC_ASSERT_ATTRS; + case filemode_service_contexts: + return CHECK_SC_ASSERT_ATTRS; + } + /* die on invalid parameters */ + fprintf(stderr, "Error: Invalid mode of operation: %d\n", mode); + exit(1); +} + +static int get_attr_bit(policydb_t *policydb, const char *attr_name) +{ + struct type_datum *attr = hashtab_search(policydb->p_types.table, (char *)attr_name); + if (!attr) { + fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", attr_name); + return -1; + } + + if (attr->flavor != TYPE_ATTRIB) { + fprintf(stderr, "Error: \"%s\" is not an attribute in this policy.\n", attr_name); + return -1; + } + + return attr->s.value - 1; +} + +static bool ebitmap_attribute_assertion_init(ebitmap_t *assertions, const char * const attributes[]) +{ + + while (*attributes) { + + int bit_pos = get_attr_bit(global_state.sepolicy.pdb, *attributes); + if (bit_pos < 0) { + /* get_attr_bit() logs error */ + return false; + } + + int err = ebitmap_set_bit(assertions, bit_pos, 1); + if (err) { + fprintf(stderr, "Error: setting bit on assertion ebitmap!\n"); + return false; + } + attributes++; + } + return true; +} + +static bool is_type_of_attribute_set(policydb_t *policydb, const char *type_name, + ebitmap_t *attr_set) +{ + struct type_datum *type = hashtab_search(policydb->p_types.table, (char *)type_name); + if (!type) { + fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", type_name); + return false; + } + + if (type->flavor != TYPE_TYPE) { + fprintf(stderr, "Error: \"%s\" is not a type in this policy.\n", type_name); + return false; + } + + ebitmap_t dst; + ebitmap_init(&dst); + + /* Take the intersection, if the set is empty, then its a failure */ + int rc = ebitmap_and(&dst, attr_set, &policydb->type_attr_map[type->s.value - 1]); + if (rc) { + fprintf(stderr, "Error: Could not perform ebitmap_and: %d\n", rc); + exit(1); + } + + bool res = (bool)ebitmap_length(&dst); + + ebitmap_destroy(&dst); + return res; +} + +static void dump_char_array(FILE *stream, const char * const *strings) +{ + + const char * const *p = strings; + + fprintf(stream, "\""); + + while (*p) { + const char *s = *p++; + const char *fmt = *p ? "%s, " : "%s\""; + fprintf(stream, fmt, s); + } +} + +static int validate(char **contextp) +{ + bool res; + char *context = *contextp; + + sepol_context_t *ctx; + int rc = sepol_context_from_string(global_state.sepolicy.handle, context, + &ctx); + if (rc < 0) { + fprintf(stderr, "Error: Could not allocate context from string"); + exit(1); + } + + rc = sepol_context_check(global_state.sepolicy.handle, + global_state.sepolicy.sdb, ctx); + if (rc < 0) { + goto out; + } + + const char *type_name = sepol_context_get_type(ctx); + + uint32_t len = ebitmap_length(&global_state.assert.set); + if (len > 0) { + res = !is_type_of_attribute_set(global_state.sepolicy.pdb, type_name, + &global_state.assert.set); + if (res) { + fprintf(stderr, "Error: type \"%s\" is not of set: ", type_name); + dump_char_array(stderr, global_state.assert.attrs); + fprintf(stderr, "\n"); + /* The calls above did not affect rc, so set error before going to out */ + rc = -1; + goto out; + } + } + /* Success: Although it should be 0, we explicitly set rc to 0 for clarity */ + rc = 0; + + out: + sepol_context_free(ctx); + return rc; +} + +static void usage(char *name) { + fprintf(stderr, "usage1: %s [-p|-s] [-e] sepolicy context_file\n\n" + "Parses a context file and checks for syntax errors.\n" + "The context_file is assumed to be a file_contexts file\n" + "unless the -p or -s option is used to indicate the property or service backend respectively.\n" + "If -e is specified, then the context_file is allowed to be empty.\n\n" + + "usage2: %s -c file_contexts1 file_contexts2\n\n" + "Compares two file contexts files and reports one of subset, equal, superset, or incomparable.\n\n", + name, name); + exit(1); +} + +static void cleanup(void) { + + if (global_state.sepolicy.file) { + fclose(global_state.sepolicy.file); + } + + if (global_state.sepolicy.sdb) { + sepol_policydb_free(global_state.sepolicy.sdb); + } + + if (global_state.sepolicy.pf) { + sepol_policy_file_free(global_state.sepolicy.pf); + } + + if (global_state.sepolicy.handle) { + sepol_handle_destroy(global_state.sepolicy.handle); + } + + ebitmap_destroy(&global_state.assert.set); + + int i; + for (i = 0; i < SEHANDLE_CNT; i++) { + struct selabel_handle *sehnd = global_state.sepolicy.sehnd[i]; + if (sehnd) { + selabel_close(sehnd); + } + } +} + +static void do_compare_and_die_on_error(struct selinux_opt opts[], unsigned int backend, char *paths[]) +{ + enum selabel_cmp_result result; + char *result_str[] = { "subset", "equal", "superset", "incomparable" }; + int i; + + opts[0].value = NULL; /* not validating against a policy when comparing */ + + for (i = 0; i < SEHANDLE_CNT; i++) { + opts[1].value = paths[i]; + global_state.sepolicy.sehnd[i] = selabel_open(backend, opts, 2); + if (!global_state.sepolicy.sehnd[i]) { + fprintf(stderr, "Error: could not load context file from %s\n", paths[i]); + exit(1); + } + } + + result = selabel_cmp(global_state.sepolicy.sehnd[0], global_state.sepolicy.sehnd[1]); + printf("%s\n", result_str[result]); +} + +static void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode, + const char *sepolicy_file, const char *context_file, bool allow_empty) +{ + struct stat sb; + if (stat(context_file, &sb) < 0) { + perror("Error: could not get stat on file contexts file"); + exit(1); + } + + if (sb.st_size == 0) { + /* Nothing to check on empty file_contexts file if allowed*/ + if (allow_empty) { + return; + } + /* else: We could throw the error here, but libselinux backend will catch it */ + } + + global_state.sepolicy.file = fopen(sepolicy_file, "r"); + if (!global_state.sepolicy.file) { + perror("Error: could not open policy file"); + exit(1); + } + + global_state.sepolicy.handle = sepol_handle_create(); + if (!global_state.sepolicy.handle) { + fprintf(stderr, "Error: could not create policy handle: %s\n", strerror(errno)); + exit(1); + } + + if (sepol_policy_file_create(&global_state.sepolicy.pf) < 0) { + perror("Error: could not create policy handle"); + exit(1); + } + + sepol_policy_file_set_fp(global_state.sepolicy.pf, global_state.sepolicy.file); + sepol_policy_file_set_handle(global_state.sepolicy.pf, global_state.sepolicy.handle); + + int rc = sepol_policydb_create(&global_state.sepolicy.sdb); + if (rc < 0) { + perror("Error: could not create policy db"); + exit(1); + } + + rc = sepol_policydb_read(global_state.sepolicy.sdb, global_state.sepolicy.pf); + if (rc < 0) { + perror("Error: could not read file into policy db"); + exit(1); + } + + global_state.assert.attrs = filemode_to_assert_attrs(mode); + + bool ret = ebitmap_attribute_assertion_init(&global_state.assert.set, global_state.assert.attrs); + if (!ret) { + /* error messages logged by ebitmap_attribute_assertion_init() */ + exit(1); + } + + selinux_set_callback(SELINUX_CB_VALIDATE, + (union selinux_callback)&validate); + + opts[1].value = context_file; + + global_state.sepolicy.sehnd[0] = selabel_open(backend, opts, 2); + if (!global_state.sepolicy.sehnd[0]) { + fprintf(stderr, "Error: could not load context file from %s\n", context_file); + exit(1); + } +} + +int main(int argc, char **argv) +{ + struct selinux_opt opts[] = { + { SELABEL_OPT_VALIDATE, (void*)1 }, + { SELABEL_OPT_PATH, NULL } + }; + + // Default backend unless changed by input argument. + unsigned int backend = SELABEL_CTX_FILE; + + bool allow_empty = false; + bool compare = false; + char c; + + filemode mode = filemode_file_contexts; + + while ((c = getopt(argc, argv, "cpse")) != -1) { + switch (c) { + case 'c': + compare = true; + break; + case 'e': + allow_empty = true; + break; + case 'p': + mode = filemode_property_contexts; + backend = SELABEL_CTX_ANDROID_PROP; + break; + case 's': + mode = filemode_service_contexts; + backend = SELABEL_CTX_ANDROID_PROP; + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + int index = optind; + if (argc - optind != 2) { + usage(argv[0]); + } + + if (compare && backend != SELABEL_CTX_FILE) { + usage(argv[0]); + } + + atexit(cleanup); + + if (compare) { + do_compare_and_die_on_error(opts, backend, &(argv[index])); + } else { + /* remaining args are sepolicy file and context file */ + char *sepolicy_file = argv[index]; + char *context_file = argv[index + 1]; + + do_fc_check_and_die_on_error(opts, backend, mode, sepolicy_file, context_file, allow_empty); + } + exit(0); +}
diff --git a/sepolicy/tools/fc_sort/Android.mk b/sepolicy/tools/fc_sort/Android.mk new file mode 100644 index 0000000..f78d550 --- /dev/null +++ b/sepolicy/tools/fc_sort/Android.mk
@@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := fc_sort +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := fc_sort.c +LOCAL_CXX_STL := none + +include $(BUILD_HOST_EXECUTABLE) + +###################################
diff --git a/sepolicy/tools/fc_sort/MODULE_LICENSE_GPL b/sepolicy/tools/fc_sort/MODULE_LICENSE_GPL new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sepolicy/tools/fc_sort/MODULE_LICENSE_GPL
diff --git a/sepolicy/tools/fc_sort/NOTICE b/sepolicy/tools/fc_sort/NOTICE new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/sepolicy/tools/fc_sort/NOTICE
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License.
diff --git a/sepolicy/tools/fc_sort/README b/sepolicy/tools/fc_sort/README new file mode 100644 index 0000000..0210dc7 --- /dev/null +++ b/sepolicy/tools/fc_sort/README
@@ -0,0 +1,9 @@ +fc_sort is a tool used for sorting the file_contexts entries based on a heuristic that is + covered by a Fedora document. That document can be found here: + * https://fedoraproject.org/wiki/SELinux/ManagingFileContext + +The tool itself originates from: + * https://github.com/TresysTechnology/refpolicy + +It can be updated to the current tip of master branch with the below command: +$ wget https://raw.githubusercontent.com/TresysTechnology/refpolicy/master/support/fc_sort.c
diff --git a/sepolicy/tools/fc_sort/fc_sort.c b/sepolicy/tools/fc_sort/fc_sort.c new file mode 100644 index 0000000..f4d2cd0 --- /dev/null +++ b/sepolicy/tools/fc_sort/fc_sort.c
@@ -0,0 +1,567 @@ +/* Copyright 2005,2013 Tresys Technology + * + * Some parts of this came from matchpathcon.c in libselinux + */ + +/* PURPOSE OF THIS PROGRAM + * The original setfiles sorting algorithm did not take into + * account regular expression specificity. With the current + * strict and targeted policies this is not an issue because + * the file contexts are partially hand sorted and concatenated + * in the right order so that the matches are generally correct. + * The way reference policy and loadable policy modules handle + * file contexts makes them come out in an unpredictable order + * and therefore setfiles (or this standalone tool) need to sort + * the regular expressions in a deterministic and stable way. + */ + +#define BUF_SIZE 4096; +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +typedef unsigned char bool_t; + +/* file_context_node + * A node used in a linked list of file contexts.c + * Each node contains the regular expression, the type and + * the context, as well as information about the regular + * expression. The regular expression data (meta, stem_len + * and str_len) can be filled in by using the fc_fill_data + * function after the regular expression has been loaded. + * next points to the next node in the linked list. + */ +typedef struct file_context_node { + char *path; + char *file_type; + char *context; + bool_t meta; + int stem_len; + int str_len; + struct file_context_node *next; +} file_context_node_t; + +void file_context_node_destroy(file_context_node_t *x) +{ + free(x->path); + free(x->file_type); + free(x->context); +} + + + +/* file_context_bucket + * A node used in a linked list of buckets that contain + * file_context_node's. + * Each node contains a pointer to a file_context_node which + * is the header of its linked list. This linked list is the + * content of this bucket. + * next points to the next bucket in the linked list. + */ +typedef struct file_context_bucket { + file_context_node_t *data; + struct file_context_bucket *next; +} file_context_bucket_t; + + + +/* fc_compare + * Compares two file contexts' regular expressions and returns: + * -1 if a is less specific than b + * 0 if a and be are equally specific + * 1 if a is more specific than b + * The comparison is based on the following statements, + * in order from most important to least important, given a and b: + * If a is a regular expression and b is not, + * -> a is less specific than b. + * If a's stem length is shorter than b's stem length, + * -> a is less specific than b. + * If a's string length is shorter than b's string length, + * -> a is less specific than b. + * If a does not have a specified type and b does, + * -> a is less specific than b. + */ +int fc_compare(file_context_node_t *a, file_context_node_t *b) +{ + /* Check to see if either a or b have meta characters + * and the other doesn't. */ + if (a->meta && !b->meta) + return -1; + if (b->meta && !a->meta) + return 1; + + /* Check to see if either a or b have a shorter stem + * length than the other. */ + if (a->stem_len < b->stem_len) + return -1; + if (b->stem_len < a->stem_len) + return 1; + + /* Check to see if either a or b have a shorter string + * length than the other. */ + if (a->str_len < b->str_len) + return -1; + if (b->str_len < a->str_len) + return 1; + + /* Check to see if either a or b has a specified type + * and the other doesn't. */ + if (!a->file_type && b->file_type) + return -1; + if (!b->file_type && a->file_type) + return 1; + + /* If none of the above conditions were satisfied, + * then a and b are equally specific. */ + return 0; +} + + + +/* fc_merge + * Merges two sorted file context linked lists into one + * sorted one. + * Pass two lists a and b, and after the completion of fc_merge, + * the final list is contained in a, and b is empty. + */ +file_context_node_t *fc_merge(file_context_node_t *a, + file_context_node_t *b) +{ + file_context_node_t *a_current; + file_context_node_t *b_current; + file_context_node_t *temp; + file_context_node_t *jumpto; + + + + /* If a is a empty list, and b is not, + * set a as b and proceed to the end. */ + if (!a && b) + a = b; + /* If b is an empty list, leave a as it is. */ + else if (!b) { + } else { + /* Make it so the list a has the lesser + * first element always. */ + if (fc_compare(a, b) == 1) { + temp = a; + a = b; + b = temp; + } + a_current = a; + b_current = b; + + /* Merge by inserting b's nodes in between a's nodes. */ + while (a_current->next && b_current) { + jumpto = a_current->next; + + /* Insert b's nodes in between the current a node + * and the next a node.*/ + while (b_current && a_current->next && + fc_compare(a_current->next, + b_current) != -1) { + + + temp = a_current->next; + a_current->next = b_current; + b_current = b_current->next; + a_current->next->next = temp; + a_current = a_current->next; + } + + /* Skip all the inserted node from b to the + * next node in the original a. */ + a_current = jumpto; + } + + + /* if there is anything left in b to be inserted, + put it on the end */ + if (b_current) { + a_current->next = b_current; + } + } + + return a; +} + + + +/* fc_merge_sort + * Sorts file contexts from least specific to more specific. + * The bucket linked list is passed and after the completion + * of the fc_merge_sort function, there is only one bucket + * (pointed to by master) that contains a linked list + * of all the file contexts, in sorted order. + * Explanation of the algorithm: + * The algorithm implemented in fc_merge_sort is an iterative + * implementation of merge sort. + * At first, each bucket has a linked list of file contexts + * that are 1 element each. + * Each pass, each odd numbered bucket is merged into the bucket + * before it. This halves the number of buckets each pass. + * It will continue passing over the buckets (as described above) + * until there is only one bucket left, containing the list of + * file contexts, sorted. + */ +void fc_merge_sort(file_context_bucket_t *master) +{ + + + file_context_bucket_t *current; + file_context_bucket_t *temp; + + /* Loop until master is the only bucket left + * so that this will stop when master contains + * the sorted list. */ + while (master->next) { + current = master; + + /* This loop merges buckets two-by-two. */ + while (current) { + + if (current->next) { + + current->data = + fc_merge(current->data, + current->next->data); + + + + temp = current->next; + current->next = current->next->next; + + free(temp); + + } + + + current = current->next; + } + } + + +} + + + +/* fc_fill_data + * This processes a regular expression in a file context + * and sets the data held in file_context_node, namely + * meta, str_len and stem_len. + * The following changes are made to fc_node after the + * the completion of the function: + * fc_node->meta = 1 if path has a meta character, 0 if not. + * fc_node->str_len = The string length of the entire path + * fc_node->stem_len = The number of characters up until + * the first meta character. + */ +void fc_fill_data(file_context_node_t *fc_node) +{ + int c = 0; + + fc_node->meta = 0; + fc_node->stem_len = 0; + fc_node->str_len = 0; + + /* Process until the string termination character + * has been reached. + * Note: this while loop has been adapted from + * spec_hasMetaChars in matchpathcon.c from + * libselinux-1.22. */ + while (fc_node->path[c] != '\0') { + switch (fc_node->path[c]) { + case '.': + case '^': + case '$': + case '?': + case '*': + case '+': + case '|': + case '[': + case '(': + case '{': + /* If a meta character is found, + * set meta to one */ + fc_node->meta = 1; + break; + case '\\': + /* If a escape character is found, + * skip the next character. */ + c++; + default: + /* If no meta character has been found yet, + * add one to the stem length. */ + if (!fc_node->meta) + fc_node->stem_len++; + break; + } + + fc_node->str_len++; + c++; + } +} + +/* main + * This program takes in two arguments, the input filename and the + * output filename. The input file should be syntactically correct. + * Overall what is done in the main is read in the file and store each + * line of code, sort it, then output it to the output file. + */ +int main(int argc, char *argv[]) +{ + int lines; + size_t start, finish, regex_len, context_len; + size_t line_len, buf_len, i, j; + char *input_name, *output_name, *line_buf; + + file_context_node_t *temp; + file_context_node_t *head; + file_context_node_t *current; + file_context_bucket_t *master; + file_context_bucket_t *bcurrent; + + FILE *in_file, *out_file; + + + /* Check for the correct number of command line arguments. */ + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s <infile> [<outfile>]\n",argv[0]); + return 1; + } + + input_name = argv[1]; + output_name = (argc >= 3) ? argv[2] : NULL; + + i = j = lines = 0; + + /* Open the input file. */ + if (!(in_file = fopen(input_name, "r"))) { + fprintf(stderr, "Error: failure opening input file for read.\n"); + return 1; + } + + /* Initialize the head of the linked list. */ + head = current = (file_context_node_t*)malloc(sizeof(file_context_node_t)); + head->next = NULL; + + /* Parse the file into a file_context linked list. */ + line_buf = NULL; + + while ( getline(&line_buf, &buf_len, in_file) != -1 ){ + line_len = strlen(line_buf); + if( line_len == 0 || line_len == 1) + continue; + /* Get rid of whitespace from the front of the line. */ + for (i = 0; i < line_len; i++) { + if (!isspace(line_buf[i])) + break; + } + + + if (i >= line_len) + continue; + /* Check if the line isn't empty and isn't a comment */ + if (line_buf[i] == '#') + continue; + + /* We have a valid line - allocate a new node. */ + temp = (file_context_node_t *)malloc(sizeof(file_context_node_t)); + if (!temp) { + fprintf(stderr, "Error: failure allocating memory.\n"); + return 1; + } + temp->next = NULL; + memset(temp, 0, sizeof(file_context_node_t)); + + /* Parse out the regular expression from the line. */ + start = i; + + + while (i < line_len && (!isspace(line_buf[i]))) + i++; + finish = i; + + + regex_len = finish - start; + + if (regex_len == 0) { + file_context_node_destroy(temp); + free(temp); + + + continue; + } + + temp->path = (char*)strndup(&line_buf[start], regex_len); + if (!temp->path) { + file_context_node_destroy(temp); + free(temp); + fprintf(stderr, "Error: failure allocating memory.\n"); + return 1; + } + + /* Get rid of whitespace after the regular expression. */ + for (; i < line_len; i++) { + + if (!isspace(line_buf[i])) + break; + } + + if (i == line_len) { + file_context_node_destroy(temp); + free(temp); + continue; + } + + /* Parse out the type from the line (if it + * is there). */ + if (line_buf[i] == '-') { + temp->file_type = (char *)malloc(sizeof(char) * 3); + if (!(temp->file_type)) { + fprintf(stderr, "Error: failure allocating memory.\n"); + return 1; + } + + if( i + 2 >= line_len ) { + file_context_node_destroy(temp); + free(temp); + + continue; + } + + /* Fill the type into the array. */ + temp->file_type[0] = line_buf[i]; + temp->file_type[1] = line_buf[i + 1]; + i += 2; + temp->file_type[2] = 0; + + /* Get rid of whitespace after the type. */ + for (; i < line_len; i++) { + if (!isspace(line_buf[i])) + break; + } + + if (i == line_len) { + + file_context_node_destroy(temp); + free(temp); + continue; + } + } + + /* Parse out the context from the line. */ + start = i; + while (i < line_len && (!isspace(line_buf[i]))) + i++; + finish = i; + + context_len = finish - start; + + temp->context = (char*)strndup(&line_buf[start], context_len); + if (!temp->context) { + file_context_node_destroy(temp); + free(temp); + fprintf(stderr, "Error: failure allocating memory.\n"); + return 1; + } + + /* Set all the data about the regular + * expression. */ + fc_fill_data(temp); + + /* Link this line of code at the end of + * the linked list. */ + current->next = temp; + current = current->next; + lines++; + + + free(line_buf); + line_buf = NULL; + } + fclose(in_file); + + /* Create the bucket linked list from the earlier linked list. */ + current = head->next; + bcurrent = master = + (file_context_bucket_t *) + malloc(sizeof(file_context_bucket_t)); + bcurrent->next = NULL; + bcurrent->data = NULL; + + /* Go until all the nodes have been put in individual buckets. */ + while (current) { + /* Copy over the file context line into the bucket. */ + bcurrent->data = current; + current = current->next; + + /* Detach the node in the bucket from the old list. */ + bcurrent->data->next = NULL; + + /* If there should be another bucket, put one at the end. */ + if (current) { + bcurrent->next = + (file_context_bucket_t *) + malloc(sizeof(file_context_bucket_t)); + if (!(bcurrent->next)) { + printf + ("Error: failure allocating memory.\n"); + return -1; + } + + /* Make sure the new bucket thinks it's the end of the + * list. */ + bcurrent->next->next = NULL; + + bcurrent = bcurrent->next; + } + + } + + /* Sort the bucket list. */ + fc_merge_sort(master); + + /* Open the output file. */ + if (output_name) { + if (!(out_file = fopen(output_name, "w"))) { + printf("Error: failure opening output file for write.\n"); + return -1; + } + } else { + out_file = stdout; + } + + /* Output the sorted file_context linked list to the output file. */ + current = master->data; + while (current) { + /* Output the path. */ + fprintf(out_file, "%s\t\t", current->path); + + /* Output the type, if there is one. */ + if (current->file_type) { + fprintf(out_file, "%s\t", current->file_type); + } + + /* Output the context. */ + fprintf(out_file, "%s\n", current->context); + + /* Remove the node. */ + temp = current; + current = current->next; + + file_context_node_destroy(temp); + free(temp); + + } + free(master); + + if (output_name) { + fclose(out_file); + } + + return 0; +}
diff --git a/sepolicy/tools/insertkeys.py b/sepolicy/tools/insertkeys.py new file mode 100755 index 0000000..ca1e432 --- /dev/null +++ b/sepolicy/tools/insertkeys.py
@@ -0,0 +1,267 @@ +#!/usr/bin/env python + +from xml.sax import saxutils, handler, make_parser +from optparse import OptionParser +import ConfigParser +import logging +import base64 +import sys +import os + +__VERSION = (0, 1) + +''' +This tool reads a mac_permissions.xml and replaces keywords in the signature +clause with keys provided by pem files. +''' + +class GenerateKeys(object): + def __init__(self, path): + ''' + Generates an object with Base16 and Base64 encoded versions of the keys + found in the supplied pem file argument. PEM files can contain multiple + certs, however this seems to be unused in Android as pkg manager grabs + the first cert in the APK. This will however support multiple certs in + the resulting generation with index[0] being the first cert in the pem + file. + ''' + + self._base64Key = list() + self._base16Key = list() + + if not os.path.isfile(path): + sys.exit("Path " + path + " does not exist or is not a file!") + + pkFile = open(path, 'rb').readlines() + base64Key = "" + lineNo = 1 + certNo = 1 + inCert = False + for line in pkFile: + line = line.strip() + # Are we starting the certificate? + if line == "-----BEGIN CERTIFICATE-----": + if inCert: + sys.exit("Encountered another BEGIN CERTIFICATE without END CERTIFICATE on " + + "line: " + str(lineNo)) + + inCert = True + + # Are we ending the ceritifcate? + elif line == "-----END CERTIFICATE-----": + if not inCert: + sys.exit("Encountered END CERTIFICATE before BEGIN CERTIFICATE on line: " + + str(lineNo)) + + # If we ended the certificate trip the flag + inCert = False + + # Sanity check the input + if len(base64Key) == 0: + sys.exit("Empty certficate , certificate "+ str(certNo) + " found in file: " + + path) + + # ... and append the certificate to the list + # Base 64 includes uppercase. DO NOT tolower() + self._base64Key.append(base64Key) + try: + # Pkgmanager and setool see hex strings with lowercase, lets be consistent + self._base16Key.append(base64.b16encode(base64.b64decode(base64Key)).lower()) + except TypeError: + sys.exit("Invalid certificate, certificate "+ str(certNo) + " found in file: " + + path) + + # After adding the key, reset the accumulator as pem files may have subsequent keys + base64Key="" + + # And increment your cert number + certNo = certNo + 1 + + # If we haven't started the certificate, then we should not encounter any data + elif not inCert: + if line is not "": + sys.exit("Detected erroneous line \""+ line + "\" on " + str(lineNo) + + " in pem file: " + path) + + # else we have started the certicate and need to append the data + elif inCert: + base64Key += line + + else: + # We should never hit this assert, if we do then an unaccounted for state + # was entered that was NOT addressed by the if/elif statements above + assert(False == True) + + # The last thing to do before looping up is to increment line number + lineNo = lineNo + 1 + + def __len__(self): + return len(self._base16Key) + + def __str__(self): + return str(self.getBase16Keys()) + + def getBase16Keys(self): + return self._base16Key + + def getBase64Keys(self): + return self._base64Key + +class ParseConfig(ConfigParser.ConfigParser): + + # This must be lowercase + OPTION_WILDCARD_TAG = "all" + + def generateKeyMap(self, target_build_variant, key_directory): + + keyMap = dict() + + for tag in self.sections(): + + options = self.options(tag) + + for option in options: + + # Only generate the key map for debug or release, + # not both! + if option != target_build_variant and \ + option != ParseConfig.OPTION_WILDCARD_TAG: + logging.info("Skipping " + tag + " : " + option + + " because target build variant is set to " + + str(target_build_variant)) + continue + + if tag in keyMap: + sys.exit("Duplicate tag detected " + tag) + + tag_path = os.path.expandvars(self.get(tag, option)) + path = os.path.join(key_directory, tag_path) + + keyMap[tag] = GenerateKeys(path) + + # Multiple certificates may exist in + # the pem file. GenerateKeys supports + # this however, the mac_permissions.xml + # as well as PMS do not. + assert len(keyMap[tag]) == 1 + + return keyMap + +class ReplaceTags(handler.ContentHandler): + + DEFAULT_TAG = "default" + PACKAGE_TAG = "package" + POLICY_TAG = "policy" + SIGNER_TAG = "signer" + SIGNATURE_TAG = "signature" + + TAGS_WITH_CHILDREN = [ DEFAULT_TAG, PACKAGE_TAG, POLICY_TAG, SIGNER_TAG ] + + XML_ENCODING_TAG = '<?xml version="1.0" encoding="iso-8859-1"?>' + + def __init__(self, keyMap, out=sys.stdout): + + handler.ContentHandler.__init__(self) + self._keyMap = keyMap + self._out = out + self._out.write(ReplaceTags.XML_ENCODING_TAG) + self._out.write("<!-- AUTOGENERATED FILE DO NOT MODIFY -->") + self._out.write("<policy>") + + def __del__(self): + self._out.write("</policy>") + + def startElement(self, tag, attrs): + if tag == ReplaceTags.POLICY_TAG: + return + + self._out.write('<' + tag) + + for (name, value) in attrs.items(): + + if name == ReplaceTags.SIGNATURE_TAG and value in self._keyMap: + for key in self._keyMap[value].getBase16Keys(): + logging.info("Replacing " + name + " " + value + " with " + key) + self._out.write(' %s="%s"' % (name, saxutils.escape(key))) + else: + self._out.write(' %s="%s"' % (name, saxutils.escape(value))) + + if tag in ReplaceTags.TAGS_WITH_CHILDREN: + self._out.write('>') + else: + self._out.write('/>') + + def endElement(self, tag): + if tag == ReplaceTags.POLICY_TAG: + return + + if tag in ReplaceTags.TAGS_WITH_CHILDREN: + self._out.write('</%s>' % tag) + + def characters(self, content): + if not content.isspace(): + self._out.write(saxutils.escape(content)) + + def ignorableWhitespace(self, content): + pass + + def processingInstruction(self, target, data): + self._out.write('<?%s %s?>' % (target, data)) + +if __name__ == "__main__": + + # Intentional double space to line up equls signs and opening " for + # readability. + usage = "usage: %prog [options] CONFIG_FILE MAC_PERMISSIONS_FILE [MAC_PERMISSIONS_FILE...]\n" + usage += "This tool allows one to configure an automatic inclusion\n" + usage += "of signing keys into the mac_permision.xml file(s) from the\n" + usage += "pem files. If mulitple mac_permision.xml files are included\n" + usage += "then they are unioned to produce a final version." + + version = "%prog " + str(__VERSION) + + parser = OptionParser(usage=usage, version=version) + + parser.add_option("-v", "--verbose", + action="store_true", dest="verbose", default=False, + help="Print internal operations to stdout") + + parser.add_option("-o", "--output", default="stdout", dest="output_file", + metavar="FILE", help="Specify an output file, default is stdout") + + parser.add_option("-c", "--cwd", default=os.getcwd(), dest="root", + metavar="DIR", help="Specify a root (CWD) directory to run this from, it" \ + "chdirs' AFTER loading the config file") + + parser.add_option("-t", "--target-build-variant", default="eng", dest="target_build_variant", + help="Specify the TARGET_BUILD_VARIANT, defaults to eng") + + parser.add_option("-d", "--key-directory", default="", dest="key_directory", + help="Specify a parent directory for keys") + + (options, args) = parser.parse_args() + + if len(args) < 2: + parser.error("Must specify a config file (keys.conf) AND mac_permissions.xml file(s)!") + + logging.basicConfig(level=logging.INFO if options.verbose == True else logging.WARN) + + # Read the config file + config = ParseConfig() + config.read(args[0]) + + os.chdir(options.root) + + output_file = sys.stdout if options.output_file == "stdout" else open(options.output_file, "w") + logging.info("Setting output file to: " + options.output_file) + + # Generate the key list + key_map = config.generateKeyMap(options.target_build_variant.lower(), options.key_directory) + logging.info("Generate key map:") + for k in key_map: + logging.info(k + " : " + str(key_map[k])) + # Generate the XML file with markup replaced with keys + parser = make_parser() + parser.setContentHandler(ReplaceTags(key_map, output_file)) + for f in args[1:]: + parser.parse(f)
diff --git a/sepolicy/tools/post_process_mac_perms b/sepolicy/tools/post_process_mac_perms new file mode 100755 index 0000000..25893ed --- /dev/null +++ b/sepolicy/tools/post_process_mac_perms
@@ -0,0 +1,106 @@ +#!/usr/bin/env python +# +# Copyright (C) 2013 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. + +""" +Tool to help modify an existing mac_permissions.xml with additional app +certs not already found in that policy. This becomes useful when a directory +containing apps is searched and the certs from those apps are added to the +policy not already explicitly listed. +""" + +import sys +import os +import argparse +from base64 import b16encode, b64decode +import fileinput +import re +import subprocess +import zipfile + +PEM_CERT_RE = """-----BEGIN CERTIFICATE----- +(.+?) +-----END CERTIFICATE----- +""" +def collect_certs_for_app(filename): + app_certs = set() + with zipfile.ZipFile(filename, 'r') as apkzip: + for info in apkzip.infolist(): + name = info.filename + if name.startswith('META-INF/') and name.endswith(('.DSA', '.RSA')): + cmd = ['openssl', 'pkcs7', '-inform', 'DER', + '-outform', 'PEM', '-print_certs'] + p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + pem_string, err = p.communicate(apkzip.read(name)) + if err and err.strip(): + raise RuntimeError('Problem running openssl on %s (%s)' % (filename, e)) + + # turn multiline base64 to single line base16 + transform = lambda x: b16encode(b64decode(x.replace('\n', ''))).lower() + results = re.findall(PEM_CERT_RE, pem_string, re.DOTALL) + certs = [transform(i) for i in results] + + app_certs.update(certs) + + return app_certs + +def add_leftover_certs(args): + all_app_certs = set() + for dirpath, _, files in os.walk(args.dir): + transform = lambda x: os.path.join(dirpath, x) + condition = lambda x: x.endswith('.apk') + apps = [transform(i) for i in files if condition(i)] + + # Collect certs for each app found + for app in apps: + app_certs = collect_certs_for_app(app) + all_app_certs.update(app_certs) + + if all_app_certs: + policy_certs = set() + with open(args.policy, 'r') as f: + cert_pattern = 'signature="([a-fA-F0-9]+)"' + policy_certs = re.findall(cert_pattern, f.read()) + + cert_diff = all_app_certs.difference(policy_certs) + + # Build xml stanzas + inner_tag = '<seinfo value="%s"/>' % args.seinfo + stanza = '<signer signature="%s">%s</signer>' + new_stanzas = [stanza % (cert, inner_tag) for cert in cert_diff] + mac_perms_string = ''.join(new_stanzas) + mac_perms_string += '</policy>' + + # Inline replace with new policy stanzas + for line in fileinput.input(args.policy, inplace=True): + sys.stdout.write(line.replace('</policy>', mac_perms_string)) + +def main(argv): + parser = argparse.ArgumentParser(description=__doc__) + + parser.add_argument('-s', '--seinfo', dest='seinfo', required=True, + help='seinfo tag for each generated stanza') + parser.add_argument('-d', '--dir', dest='dir', required=True, + help='Directory to search for apks') + parser.add_argument('-f', '--file', dest='policy', required=True, + help='mac_permissions.xml policy file') + + parser.set_defaults(func=add_leftover_certs) + args = parser.parse_args() + args.func(args) + +if __name__ == '__main__': + main(sys.argv)
diff --git a/sepolicy/tools/sepolicy-analyze/Android.mk b/sepolicy/tools/sepolicy-analyze/Android.mk new file mode 100644 index 0000000..7568351 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/Android.mk
@@ -0,0 +1,14 @@ +LOCAL_PATH:= $(call my-dir) + +################################### +include $(CLEAR_VARS) + +LOCAL_MODULE := sepolicy-analyze +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := external/selinux/libsepol/include +LOCAL_CFLAGS := -Wall -Werror +LOCAL_SRC_FILES := sepolicy-analyze.c dups.c neverallow.c perm.c typecmp.c booleans.c attribute.c utils.c +LOCAL_STATIC_LIBRARIES := libsepol +LOCAL_CXX_STL := none + +include $(BUILD_HOST_EXECUTABLE)
diff --git a/sepolicy/tools/sepolicy-analyze/README b/sepolicy/tools/sepolicy-analyze/README new file mode 100644 index 0000000..d18609a --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/README
@@ -0,0 +1,94 @@ +sepolicy-analyze + A component-ized tool for performing various kinds of analysis on a + sepolicy file. The current kinds of analysis that are currently + supported include: + + TYPE EQUIVALENCE (typecmp) + sepolicy-analyze out/target/product/<board>/root/sepolicy typecmp -e + + Display all type pairs that are "equivalent", i.e. they are + identical with respect to allow rules, including indirect allow + rules via attributes and default-enabled conditional rules + (i.e. default boolean values yield a true conditional expression). + + Equivalent types are candidates for being coalesced into a single + type. However, there may be legitimate reasons for them to remain + separate, for example: - the types may differ in a respect not + included in the current analysis, such as default-disabled + conditional rules, audit-related rules (auditallow or dontaudit), + default type transitions, or constraints (e.g. mls), or - the + current policy may be overly permissive with respect to one or the + other of the types and thus the correct action may be to tighten + access to one or the other rather than coalescing them together, + or - the domains that would in fact have different accesses to the + types may not yet be defined or may be unconfined in the policy + you are analyzing. + + TYPE DIFFERENCE (typecmp) + sepolicy-analyze out/target/product/<board>/root/sepolicy typecmp -d + + Display type pairs that differ and the first difference found + between the two types. This may be used in looking for similar + types that are not equivalent but may be candidates for coalescing. + + DUPLICATE ALLOW RULES (dups) + sepolicy-analyze out/target/product/<board>/root/sepolicy dups + + Displays duplicate allow rules, i.e. pairs of allow rules that + grant the same permissions where one allow rule is written + directly in terms of individual types and the other is written in + terms of attributes associated with those same types. The rule + with individual types is a candidate for removal. The rule with + individual types may be directly represented in the source policy + or may be a result of expansion of a type negation (e.g. domain + -foo -bar is expanded to individual allow rules by the policy + compiler). Domains with unconfineddomain will typically have such + duplicate rules as a natural side effect and can be ignored. + + PERMISSIVE DOMAINS (permissive) + sepolicy-analyze out/target/product/<board>/root/sepolicy permissive + + Displays domains in the policy that are permissive, i.e. avc + denials are logged but not enforced for these domains. While + permissive domains can be helpful during development, they + should not be present in a final -user build. + + BOOLEANS (booleans) + sepolicy-analyze out/target/product/<board>/root/sepolicy booleans + + Displays the boolean names in the policy (if any). + Policy booleans are forbidden in Android policy, so if there is any + output, the policy will fail CTS. + + ATTRIBUTE (attribute) + sepolicy-analyze out/target/product/<board>/root/sepolicy attribute <name> + + Displays the types associated with the specified attribute name. + + NEVERALLOW CHECKING (neverallow) + sepolicy-analyze out/target/product/<board>/root/sepolicy neverallow \ + [-w] [-d] [-f neverallows.conf] | [-n "neverallow string"] + + Check whether the sepolicy file violates any of the neverallow rules + from the neverallows.conf file or a given string, which contain neverallow + statements in the same format as the SELinux policy.conf file, i.e. after + m4 macro expansion of the rules from a .te file. You can use an entire + policy.conf file as the neverallows.conf file and sepolicy-analyze will + ignore everything except for the neverallows within it. You can also + specify this as a command-line string argument, which could be useful for + quickly checking an individual expanded rule or group of rules. If there are + no violations, sepolicy-analyze will exit successfully with no output. + Otherwise, sepolicy-analyze will report all violations and exit + with a non-zero exit status. + + The -w or --warn option may be used to warn on any types, attributes, + classes, or permissions from a neverallow rule that could not be resolved + within the sepolicy file. This can be normal due to differences between + the policy from which the neverallow rules were taken and the policy + being checked. Such values are ignored for the purposes of neverallow + checking. + + The -d or --debug option may be used to cause sepolicy-analyze to emit the + neverallow rules as it parses them. This is principally a debugging facility + for the parser but could also be used to extract neverallow rules from + a full policy.conf file and output them in a more easily parsed format.
diff --git a/sepolicy/tools/sepolicy-analyze/attribute.c b/sepolicy/tools/sepolicy-analyze/attribute.c new file mode 100644 index 0000000..474bda2 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/attribute.c
@@ -0,0 +1,39 @@ +#include "attribute.h" + +void attribute_usage() { + fprintf(stderr, "\tattribute <attribute-name>\n"); +} + +static int list_attribute(policydb_t * policydb, char *name) +{ + struct type_datum *attr; + struct ebitmap_node *n; + unsigned int bit; + + attr = hashtab_search(policydb->p_types.table, name); + if (!attr) { + fprintf(stderr, "%s is not defined in this policy.\n", name); + return -1; + } + + if (attr->flavor != TYPE_ATTRIB) { + fprintf(stderr, "%s is a type not an attribute in this policy.\n", name); + return -1; + } + + ebitmap_for_each_bit(&policydb->attr_type_map[attr->s.value - 1], n, bit) { + if (!ebitmap_node_get_bit(n, bit)) + continue; + printf("%s\n", policydb->p_type_val_to_name[bit]); + } + + return 0; +} + +int attribute_func (int argc, char **argv, policydb_t *policydb) { + if (argc != 2) { + USAGE_ERROR = true; + return -1; + } + return list_attribute(policydb, argv[1]); +}
diff --git a/sepolicy/tools/sepolicy-analyze/attribute.h b/sepolicy/tools/sepolicy-analyze/attribute.h new file mode 100644 index 0000000..05adcbd --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/attribute.h
@@ -0,0 +1,11 @@ +#ifndef ATTRIBUTE_H +#define ATTRIBUTE_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void attribute_usage(void); +int attribute_func(int argc, char **argv, policydb_t *policydb); + +#endif /* ATTRIBUTE_H */
diff --git a/sepolicy/tools/sepolicy-analyze/booleans.c b/sepolicy/tools/sepolicy-analyze/booleans.c new file mode 100644 index 0000000..c3b605d --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/booleans.c
@@ -0,0 +1,22 @@ +#include "booleans.h" + +void booleans_usage() { + fprintf(stderr, "\tbooleans\n"); +} + +static int list_booleans(hashtab_key_t k, + __attribute__ ((unused)) hashtab_datum_t d, + __attribute__ ((unused)) void *args) +{ + const char *name = k; + printf("%s\n", name); + return 0; +} + +int booleans_func (int argc, __attribute__ ((unused)) char **argv, policydb_t *policydb) { + if (argc != 1) { + USAGE_ERROR = true; + return -1; + } + return hashtab_map(policydb->p_bools.table, list_booleans, NULL); +}
diff --git a/sepolicy/tools/sepolicy-analyze/booleans.h b/sepolicy/tools/sepolicy-analyze/booleans.h new file mode 100644 index 0000000..bfbe0e1 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/booleans.h
@@ -0,0 +1,11 @@ +#ifndef BOOLEANS_H +#define BOOLEANS_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void booleans_usage(void); +int booleans_func(int argc, char **argv, policydb_t *policydb); + +#endif /* BOOLEANS_H */
diff --git a/sepolicy/tools/sepolicy-analyze/dups.c b/sepolicy/tools/sepolicy-analyze/dups.c new file mode 100644 index 0000000..88c2be2 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/dups.c
@@ -0,0 +1,91 @@ +#include <stdbool.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "dups.h" + +void dups_usage() { + fprintf(stderr, "\tdups\n"); +} + +static int find_dups_helper(avtab_key_t * k, avtab_datum_t * d, + void *args) +{ + policydb_t *policydb = args; + ebitmap_t *sattr, *tattr; + ebitmap_node_t *snode, *tnode; + unsigned int i, j; + avtab_key_t avkey; + avtab_ptr_t node; + struct type_datum *stype, *ttype, *stype2, *ttype2; + bool attrib1, attrib2; + + if (!(k->specified & AVTAB_ALLOWED)) + return 0; + + if (k->source_type == k->target_type) + return 0; /* self rule */ + + avkey.target_class = k->target_class; + avkey.specified = k->specified; + + sattr = &policydb->type_attr_map[k->source_type - 1]; + tattr = &policydb->type_attr_map[k->target_type - 1]; + stype = policydb->type_val_to_struct[k->source_type - 1]; + ttype = policydb->type_val_to_struct[k->target_type - 1]; + attrib1 = stype->flavor || ttype->flavor; + ebitmap_for_each_bit(sattr, snode, i) { + if (!ebitmap_node_get_bit(snode, i)) + continue; + ebitmap_for_each_bit(tattr, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) + continue; + avkey.source_type = i + 1; + avkey.target_type = j + 1; + if (avkey.source_type == k->source_type && + avkey.target_type == k->target_type) + continue; + if (avkey.source_type == avkey.target_type) + continue; /* self rule */ + stype2 = policydb->type_val_to_struct[avkey.source_type - 1]; + ttype2 = policydb->type_val_to_struct[avkey.target_type - 1]; + attrib2 = stype2->flavor || ttype2->flavor; + if (attrib1 && attrib2) + continue; /* overlapping attribute-based rules */ + for (node = avtab_search_node(&policydb->te_avtab, &avkey); + node != NULL; + node = avtab_search_node_next(node, avkey.specified)) { + uint32_t perms = node->datum.data & d->data; + if ((attrib1 && perms == node->datum.data) || + (attrib2 && perms == d->data)) { + /* + * The attribute-based rule is a superset of the + * non-attribute-based rule. This is a dup. + */ + printf("Duplicate allow rule found:\n"); + display_allow(policydb, k, i, d->data); + display_allow(policydb, &node->key, i, node->datum.data); + printf("\n"); + } + } + } + } + + return 0; +} + +static int find_dups(policydb_t * policydb) +{ + if (avtab_map(&policydb->te_avtab, find_dups_helper, policydb)) + return -1; + return 0; +} + +int dups_func (int argc, __attribute__ ((unused)) char **argv, policydb_t *policydb) { + if (argc != 1) { + USAGE_ERROR = true; + return -1; + } + return find_dups(policydb); +}
diff --git a/sepolicy/tools/sepolicy-analyze/dups.h b/sepolicy/tools/sepolicy-analyze/dups.h new file mode 100644 index 0000000..0e77224 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/dups.h
@@ -0,0 +1,11 @@ +#ifndef DUPS_H +#define DUPS_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void dups_usage(void); +int dups_func(int argc, char **argv, policydb_t *policydb); + +#endif /* DUPS_H */
diff --git a/sepolicy/tools/sepolicy-analyze/neverallow.c b/sepolicy/tools/sepolicy-analyze/neverallow.c new file mode 100644 index 0000000..b288ea7 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/neverallow.c
@@ -0,0 +1,515 @@ +#include <ctype.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "neverallow.h" + +static int debug; +static int warn; + +void neverallow_usage() { + fprintf(stderr, "\tneverallow [-w|--warn] [-d|--debug] [-n|--neverallows <neverallow-rules>] | [-f|--file <neverallow-file>]\n"); +} + +static int read_typeset(policydb_t *policydb, char **ptr, char *end, + type_set_t *typeset, uint32_t *flags) +{ + const char *keyword = "self"; + size_t keyword_size = strlen(keyword), len; + char *p = *ptr; + unsigned openparens = 0; + char *start, *id; + type_datum_t *type; + struct ebitmap_node *n; + unsigned int bit; + bool negate = false; + int rc; + + do { + while (p < end && isspace(*p)) + p++; + + if (p == end) + goto err; + + if (*p == '~') { + if (debug) + printf(" ~"); + typeset->flags = TYPE_COMP; + p++; + while (p < end && isspace(*p)) + p++; + if (p == end) + goto err; + } + + if (*p == '{') { + if (debug && !openparens) + printf(" {"); + openparens++; + p++; + continue; + } + + if (*p == '}') { + if (debug && openparens == 1) + printf(" }"); + if (openparens == 0) + goto err; + openparens--; + p++; + continue; + } + + if (*p == '*') { + if (debug) + printf(" *"); + typeset->flags = TYPE_STAR; + p++; + continue; + } + + if (*p == '-') { + if (debug) + printf(" -"); + negate = true; + p++; + continue; + } + + if (*p == '#') { + while (p < end && *p != '\n') + p++; + continue; + } + + start = p; + while (p < end && !isspace(*p) && *p != ':' && *p != ';' && *p != '{' && *p != '}' && *p != '#') + p++; + + if (p == start) + goto err; + + len = p - start; + if (len == keyword_size && !strncmp(start, keyword, keyword_size)) { + if (debug) + printf(" self"); + *flags |= RULE_SELF; + continue; + } + + id = calloc(1, len + 1); + if (!id) + goto err; + memcpy(id, start, len); + if (debug) + printf(" %s", id); + type = hashtab_search(policydb->p_types.table, id); + if (!type) { + if (warn) + fprintf(stderr, "Warning! Type or attribute %s used in neverallow undefined in policy being checked.\n", id); + negate = false; + continue; + } + free(id); + + if (type->flavor == TYPE_ATTRIB) { + if (negate) + rc = ebitmap_union(&typeset->negset, &policydb->attr_type_map[type->s.value - 1]); + else + rc = ebitmap_union(&typeset->types, &policydb->attr_type_map[type->s.value - 1]); + } else if (negate) { + rc = ebitmap_set_bit(&typeset->negset, type->s.value - 1, 1); + } else { + rc = ebitmap_set_bit(&typeset->types, type->s.value - 1, 1); + } + + negate = false; + + if (rc) + goto err; + + } while (p < end && openparens); + + if (p == end) + goto err; + + if (typeset->flags & TYPE_STAR) { + for (bit = 0; bit < policydb->p_types.nprim; bit++) { + if (ebitmap_get_bit(&typeset->negset, bit)) + continue; + if (policydb->type_val_to_struct[bit] && + policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB) + continue; + if (ebitmap_set_bit(&typeset->types, bit, 1)) + goto err; + } + } + + ebitmap_for_each_bit(&typeset->negset, n, bit) { + if (!ebitmap_node_get_bit(n, bit)) + continue; + if (ebitmap_set_bit(&typeset->types, bit, 0)) + goto err; + } + + if (typeset->flags & TYPE_COMP) { + for (bit = 0; bit < policydb->p_types.nprim; bit++) { + if (policydb->type_val_to_struct[bit] && + policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB) + continue; + if (ebitmap_get_bit(&typeset->types, bit)) + ebitmap_set_bit(&typeset->types, bit, 0); + else { + if (ebitmap_set_bit(&typeset->types, bit, 1)) + goto err; + } + } + } + + if (warn && ebitmap_length(&typeset->types) == 0 && !(*flags)) + fprintf(stderr, "Warning! Empty type set\n"); + + *ptr = p; + return 0; +err: + return -1; +} + +static int read_classperms(policydb_t *policydb, char **ptr, char *end, + class_perm_node_t **perms) +{ + char *p = *ptr; + unsigned openparens = 0; + char *id, *start; + class_datum_t *cls = NULL; + perm_datum_t *perm = NULL; + class_perm_node_t *classperms = NULL, *node = NULL; + bool complement = false; + + while (p < end && isspace(*p)) + p++; + + if (p == end || *p != ':') + goto err; + p++; + + if (debug) + printf(" :"); + + do { + while (p < end && isspace(*p)) + p++; + + if (p == end) + goto err; + + if (*p == '{') { + if (debug && !openparens) + printf(" {"); + openparens++; + p++; + continue; + } + + if (*p == '}') { + if (debug && openparens == 1) + printf(" }"); + if (openparens == 0) + goto err; + openparens--; + p++; + continue; + } + + if (*p == '#') { + while (p < end && *p != '\n') + p++; + continue; + } + + start = p; + while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#') + p++; + + if (p == start) + goto err; + + id = calloc(1, p - start + 1); + if (!id) + goto err; + memcpy(id, start, p - start); + if (debug) + printf(" %s", id); + cls = hashtab_search(policydb->p_classes.table, id); + if (!cls) { + if (warn) + fprintf(stderr, "Warning! Class %s used in neverallow undefined in policy being checked.\n", id); + continue; + } + + node = calloc(1, sizeof *node); + if (!node) + goto err; + node->tclass = cls->s.value; + node->next = classperms; + classperms = node; + free(id); + } while (p < end && openparens); + + if (p == end) + goto err; + + if (warn && !classperms) + fprintf(stderr, "Warning! Empty class set\n"); + + do { + while (p < end && isspace(*p)) + p++; + + if (p == end) + goto err; + + if (*p == '~') { + if (debug) + printf(" ~"); + complement = true; + p++; + while (p < end && isspace(*p)) + p++; + if (p == end) + goto err; + } + + if (*p == '{') { + if (debug && !openparens) + printf(" {"); + openparens++; + p++; + continue; + } + + if (*p == '}') { + if (debug && openparens == 1) + printf(" }"); + if (openparens == 0) + goto err; + openparens--; + p++; + continue; + } + + if (*p == '#') { + while (p < end && *p != '\n') + p++; + continue; + } + + start = p; + while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#') + p++; + + if (p == start) + goto err; + + id = calloc(1, p - start + 1); + if (!id) + goto err; + memcpy(id, start, p - start); + if (debug) + printf(" %s", id); + + if (!strcmp(id, "*")) { + for (node = classperms; node; node = node->next) + node->data = ~0; + continue; + } + + for (node = classperms; node; node = node->next) { + cls = policydb->class_val_to_struct[node->tclass-1]; + perm = hashtab_search(cls->permissions.table, id); + if (cls->comdatum && !perm) + perm = hashtab_search(cls->comdatum->permissions.table, id); + if (!perm) { + if (warn) + fprintf(stderr, "Warning! Permission %s used in neverallow undefined in class %s in policy being checked.\n", id, policydb->p_class_val_to_name[node->tclass-1]); + continue; + } + node->data |= 1U << (perm->s.value - 1); + } + free(id); + } while (p < end && openparens); + + if (p == end) + goto err; + + if (complement) { + for (node = classperms; node; node = node->next) + node->data = ~node->data; + } + + if (warn) { + for (node = classperms; node; node = node->next) + if (!node->data) + fprintf(stderr, "Warning! Empty permission set\n"); + } + + *perms = classperms; + *ptr = p; + return 0; +err: + return -1; +} + +static int check_neverallows(policydb_t *policydb, char *text, char *end) +{ + const char *keyword = "neverallow"; + size_t keyword_size = strlen(keyword), len; + struct avrule *neverallows = NULL, *avrule; + char *p, *start; + + p = text; + while (p < end) { + while (p < end && isspace(*p)) + p++; + + if (*p == '#') { + while (p < end && *p != '\n') + p++; + continue; + } + + start = p; + while (p < end && !isspace(*p)) + p++; + + len = p - start; + if (len != keyword_size || strncmp(start, keyword, keyword_size)) + continue; + + if (debug) + printf("neverallow"); + + avrule = calloc(1, sizeof *avrule); + if (!avrule) + goto err; + + avrule->specified = AVRULE_NEVERALLOW; + + if (read_typeset(policydb, &p, end, &avrule->stypes, &avrule->flags)) + goto err; + + if (read_typeset(policydb, &p, end, &avrule->ttypes, &avrule->flags)) + goto err; + + if (read_classperms(policydb, &p, end, &avrule->perms)) + goto err; + + while (p < end && *p != ';') + p++; + + if (p == end || *p != ';') + goto err; + + if (debug) + printf(";\n"); + + avrule->next = neverallows; + neverallows = avrule; + } + + if (!neverallows) + goto err; + + return check_assertions(NULL, policydb, neverallows); +err: + if (errno == ENOMEM) { + fprintf(stderr, "Out of memory while parsing neverallow rules\n"); + } else + fprintf(stderr, "Error while parsing neverallow rules\n"); + return -1; +} + +static int check_neverallows_file(policydb_t *policydb, const char *filename) +{ + int fd; + struct stat sb; + char *text, *end; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); + return -1; + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); + close(fd); + return -1; + } + text = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + end = text + sb.st_size; + if (text == MAP_FAILED) { + fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); + close(fd); + return -1; + } + close(fd); + return check_neverallows(policydb, text, end); +} + +static int check_neverallows_string(policydb_t *policydb, char *string, size_t len) +{ + char *text, *end; + text = string; + end = text + len; + return check_neverallows(policydb, text, end); +} + +int neverallow_func (int argc, char **argv, policydb_t *policydb) { + char *rules = 0, *file = 0; + char ch; + + struct option neverallow_options[] = { + {"debug", no_argument, NULL, 'd'}, + {"file_input", required_argument, NULL, 'f'}, + {"neverallow", required_argument, NULL, 'n'}, + {"warn", no_argument, NULL, 'w'}, + {NULL, 0, NULL, 0} + }; + + while ((ch = getopt_long(argc, argv, "df:n:w", neverallow_options, NULL)) != -1) { + switch (ch) { + case 'd': + debug = 1; + break; + case 'f': + file = optarg; + break; + case 'n': + rules = optarg; + break; + case 'w': + warn = 1; + break; + default: + USAGE_ERROR = true; + return -1; + } + } + + if (!(rules || file) || (rules && file)){ + USAGE_ERROR = true; + return -1; + } + if (file) { + return check_neverallows_file(policydb, file); + } else { + return check_neverallows_string(policydb, rules, strlen(rules)); + } +}
diff --git a/sepolicy/tools/sepolicy-analyze/neverallow.h b/sepolicy/tools/sepolicy-analyze/neverallow.h new file mode 100644 index 0000000..be80822 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/neverallow.h
@@ -0,0 +1,11 @@ +#ifndef NEVERALLOW_H +#define NEVERALLOW_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void neverallow_usage(void); +int neverallow_func(int argc, char **argv, policydb_t *policydb); + +#endif /* NEVERALLOW_H */
diff --git a/sepolicy/tools/sepolicy-analyze/perm.c b/sepolicy/tools/sepolicy-analyze/perm.c new file mode 100644 index 0000000..4cc4869 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/perm.c
@@ -0,0 +1,30 @@ +#include "perm.h" + +void permissive_usage() { + fprintf(stderr, "\tpermissive\n"); +} + +static int list_permissive(policydb_t * policydb) +{ + struct ebitmap_node *n; + unsigned int bit; + + /* + * iterate over all domains and check if domain is in permissive + */ + ebitmap_for_each_bit(&policydb->permissive_map, n, bit) + { + if (ebitmap_node_get_bit(n, bit)) { + printf("%s\n", policydb->p_type_val_to_name[bit -1]); + } + } + return 0; +} + +int permissive_func (int argc, __attribute__ ((unused)) char **argv, policydb_t *policydb) { + if (argc != 1) { + USAGE_ERROR = true; + return -1; + } + return list_permissive(policydb); +}
diff --git a/sepolicy/tools/sepolicy-analyze/perm.h b/sepolicy/tools/sepolicy-analyze/perm.h new file mode 100644 index 0000000..16e619a --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/perm.h
@@ -0,0 +1,11 @@ +#ifndef PERM_H +#define PERM_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void permissive_usage(void); +int permissive_func(int argc, char **argv, policydb_t *policydb); + +#endif /* PERM_H */
diff --git a/sepolicy/tools/sepolicy-analyze/sepolicy-analyze.c b/sepolicy/tools/sepolicy-analyze/sepolicy-analyze.c new file mode 100644 index 0000000..b70eaaa --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/sepolicy-analyze.c
@@ -0,0 +1,65 @@ +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#include "dups.h" +#include "neverallow.h" +#include "perm.h" +#include "typecmp.h" +#include "booleans.h" +#include "attribute.h" +#include "utils.h" + +#define NUM_COMPONENTS (int) (sizeof(analyze_components)/sizeof(analyze_components[0])) + +#define COMP(x) { #x, sizeof(#x) - 1, x ##_usage, x ##_func } +static struct { + const char *key; + size_t keylen; + void (*usage) (void); + int (*func) (int argc, char **argv, policydb_t *policydb); +} analyze_components[] = { + COMP(dups), + COMP(neverallow), + COMP(permissive), + COMP(typecmp), + COMP(booleans), + COMP(attribute) +}; + +void usage(char *arg0) +{ + int i; + + fprintf(stderr, "%s must be called on a policy file with a component and the appropriate arguments specified\n", arg0); + fprintf(stderr, "%s <policy-file>:\n", arg0); + for(i = 0; i < NUM_COMPONENTS; i++) { + analyze_components[i].usage(); + } + exit(1); +} + +int main(int argc, char **argv) +{ + char *policy; + struct policy_file pf; + policydb_t policydb; + int rc; + int i; + + if (argc < 3) + usage(argv[0]); + policy = argv[1]; + if(load_policy(policy, &policydb, &pf)) + exit(1); + for(i = 0; i < NUM_COMPONENTS; i++) { + if (!strcmp(analyze_components[i].key, argv[2])) { + rc = analyze_components[i].func(argc - 2, argv + 2, &policydb); + if (rc && USAGE_ERROR) { + usage(argv[0]); } + return rc; + } + } + usage(argv[0]); + exit(0); +}
diff --git a/sepolicy/tools/sepolicy-analyze/typecmp.c b/sepolicy/tools/sepolicy-analyze/typecmp.c new file mode 100644 index 0000000..5fffd63 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/typecmp.c
@@ -0,0 +1,295 @@ +#include <getopt.h> +#include <sepol/policydb/expand.h> + +#include "typecmp.h" + +void typecmp_usage() { + fprintf(stderr, "\ttypecmp [-d|--diff] [-e|--equiv]\n"); +} + +static int insert_type_rule(avtab_key_t * k, avtab_datum_t * d, + struct avtab_node *type_rules) +{ + struct avtab_node *p, *c, *n; + + for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) { + /* + * Find the insertion point, keeping the list + * ordered by source type, then target type, then + * target class. + */ + if (k->source_type < c->key.source_type) + break; + if (k->source_type == c->key.source_type && + k->target_type < c->key.target_type) + break; + if (k->source_type == c->key.source_type && + k->target_type == c->key.target_type && + k->target_class <= c->key.target_class) + break; + } + + if (c && + k->source_type == c->key.source_type && + k->target_type == c->key.target_type && + k->target_class == c->key.target_class) { + c->datum.data |= d->data; + return 0; + } + + /* Insert the rule */ + n = malloc(sizeof(struct avtab_node)); + if (!n) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + n->key = *k; + n->datum = *d; + n->next = p->next; + p->next = n; + return 0; +} + +static int create_type_rules_helper(avtab_key_t * k, avtab_datum_t * d, + void *args) +{ + struct avtab_node *type_rules = args; + avtab_key_t key; + + /* + * Insert the rule into the list for + * the source type. The source type value + * is cleared as we want to compare against other type + * rules with different source types. + */ + key = *k; + key.source_type = 0; + if (k->source_type == k->target_type) { + /* Clear target type as well; this is a self rule. */ + key.target_type = 0; + } + if (insert_type_rule(&key, d, &type_rules[k->source_type - 1])) + return -1; + + if (k->source_type == k->target_type) + return 0; + + /* + * If the target type differs, then we also + * insert the rule into the list for the target + * type. We clear the target type value so that + * we can compare against other type rules with + * different target types. + */ + key = *k; + key.target_type = 0; + if (insert_type_rule(&key, d, &type_rules[k->target_type - 1])) + return -1; + + return 0; +} + +static int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args) +{ + if (k->specified & AVTAB_ALLOWED) + return create_type_rules_helper(k, d, args); + return 0; +} + +static int create_type_rules_cond(avtab_key_t * k, avtab_datum_t * d, + void *args) +{ + if ((k->specified & (AVTAB_ALLOWED|AVTAB_ENABLED)) == + (AVTAB_ALLOWED|AVTAB_ENABLED)) + return create_type_rules_helper(k, d, args); + return 0; +} + +static void free_type_rules(struct avtab_node *l) +{ + struct avtab_node *tmp; + + while (l) { + tmp = l; + l = l->next; + free(tmp); + } +} + +static int find_match(policydb_t *policydb, struct avtab_node *l1, + int idx1, struct avtab_node *l2, int idx2) +{ + struct avtab_node *c; + uint32_t perms1, perms2; + + for (c = l2; c; c = c->next) { + if (l1->key.source_type < c->key.source_type) + break; + if (l1->key.source_type == c->key.source_type && + l1->key.target_type < c->key.target_type) + break; + if (l1->key.source_type == c->key.source_type && + l1->key.target_type == c->key.target_type && + l1->key.target_class <= c->key.target_class) + break; + } + + if (c && + l1->key.source_type == c->key.source_type && + l1->key.target_type == c->key.target_type && + l1->key.target_class == c->key.target_class) { + perms1 = l1->datum.data & ~c->datum.data; + perms2 = c->datum.data & ~l1->datum.data; + if (perms1 || perms2) { + if (perms1) + display_allow(policydb, &l1->key, idx1, perms1); + if (perms2) + display_allow(policydb, &c->key, idx2, perms2); + printf("\n"); + return 1; + } + } + + return 0; +} + +static int analyze_types(policydb_t * policydb, char diff, char equiv) +{ + avtab_t exp_avtab, exp_cond_avtab; + struct avtab_node *type_rules, *l1, *l2; + struct type_datum *type; + size_t i, j; + + /* + * Create a list of access vector rules for each type + * from the access vector table. + */ + type_rules = malloc(sizeof(struct avtab_node) * policydb->p_types.nprim); + if (!type_rules) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + memset(type_rules, 0, sizeof(struct avtab_node) * policydb->p_types.nprim); + + if (avtab_init(&exp_avtab) || avtab_init(&exp_cond_avtab)) { + fputs("out of memory\n", stderr); + return -1; + } + + if (expand_avtab(policydb, &policydb->te_avtab, &exp_avtab)) { + fputs("out of memory\n", stderr); + avtab_destroy(&exp_avtab); + return -1; + } + + if (expand_avtab(policydb, &policydb->te_cond_avtab, &exp_cond_avtab)) { + fputs("out of memory\n", stderr); + avtab_destroy(&exp_avtab); /* */ + return -1; + } + + if (avtab_map(&exp_avtab, create_type_rules, type_rules)) + exit(1); + + if (avtab_map(&exp_cond_avtab, create_type_rules_cond, type_rules)) + exit(1); + + avtab_destroy(&exp_avtab); + avtab_destroy(&exp_cond_avtab); + + /* + * Compare the type lists and identify similar types. + */ + for (i = 0; i < policydb->p_types.nprim - 1; i++) { + if (!type_rules[i].next) + continue; + type = policydb->type_val_to_struct[i]; + if (type->flavor) { + free_type_rules(type_rules[i].next); + type_rules[i].next = NULL; + continue; + } + for (j = i + 1; j < policydb->p_types.nprim; j++) { + type = policydb->type_val_to_struct[j]; + if (type->flavor) { + free_type_rules(type_rules[j].next); + type_rules[j].next = NULL; + continue; + } + for (l1 = type_rules[i].next, l2 = type_rules[j].next; + l1 && l2; l1 = l1->next, l2 = l2->next) { + if (l1->key.source_type != l2->key.source_type) + break; + if (l1->key.target_type != l2->key.target_type) + break; + if (l1->key.target_class != l2->key.target_class + || l1->datum.data != l2->datum.data) + break; + } + if (l1 || l2) { + if (diff) { + printf + ("Types %s and %s differ, starting with:\n", + policydb->p_type_val_to_name[i], + policydb->p_type_val_to_name[j]); + + if (l1 && l2) { + if (find_match(policydb, l1, i, l2, j)) + continue; + if (find_match(policydb, l2, j, l1, i)) + continue; + } + if (l1) + display_allow(policydb, &l1->key, i, l1->datum.data); + if (l2) + display_allow(policydb, &l2->key, j, l2->datum.data); + printf("\n"); + } + continue; + } + free_type_rules(type_rules[j].next); + type_rules[j].next = NULL; + if (equiv) { + printf("Types %s and %s are equivalent.\n", + policydb->p_type_val_to_name[i], + policydb->p_type_val_to_name[j]); + } + } + free_type_rules(type_rules[i].next); + type_rules[i].next = NULL; + } + + free(type_rules); + return 0; +} + +int typecmp_func (int argc, char **argv, policydb_t *policydb) { + char ch, diff = 0, equiv = 0; + + struct option typecmp_options[] = { + {"diff", no_argument, NULL, 'd'}, + {"equiv", no_argument, NULL, 'e'}, + {NULL, 0, NULL, 0} + }; + + while ((ch = getopt_long(argc, argv, "de", typecmp_options, NULL)) != -1) { + switch (ch) { + case 'd': + diff = 1; + break; + case 'e': + equiv = 1; + break; + default: + USAGE_ERROR = true; + return -1; + } + } + + if (!(diff || equiv)) { + USAGE_ERROR = true; + return -1; + } + return analyze_types(policydb, diff, equiv); +}
diff --git a/sepolicy/tools/sepolicy-analyze/typecmp.h b/sepolicy/tools/sepolicy-analyze/typecmp.h new file mode 100644 index 0000000..f93daaa --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/typecmp.h
@@ -0,0 +1,11 @@ +#ifndef TYPECMP_H +#define TYPECMP_H + +#include <sepol/policydb/policydb.h> + +#include "utils.h" + +void typecmp_usage(void); +int typecmp_func(int argc, char **argv, policydb_t *policydb); + +#endif /* TYPECMP_H */
diff --git a/sepolicy/tools/sepolicy-analyze/utils.c b/sepolicy/tools/sepolicy-analyze/utils.c new file mode 100644 index 0000000..5e52f59 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/utils.c
@@ -0,0 +1,68 @@ +#include <fcntl.h> +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/util.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "utils.h" + +bool USAGE_ERROR = false; + +void display_allow(policydb_t *policydb, avtab_key_t *key, int idx, uint32_t perms) +{ + printf(" allow %s %s:%s { %s };\n", + policydb->p_type_val_to_name[key->source_type + ? key->source_type - 1 : idx], + key->target_type == key->source_type ? "self" : + policydb->p_type_val_to_name[key->target_type + ? key->target_type - 1 : idx], + policydb->p_class_val_to_name[key->target_class - 1], + sepol_av_to_string + (policydb, key->target_class, perms)); +} + +int load_policy(char *filename, policydb_t * policydb, struct policy_file *pf) +{ + int fd; + struct stat sb; + void *map; + int ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); + return 1; + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); + close(fd); + return 1; + } + map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); + close(fd); + return 1; + } + + policy_file_init(pf); + pf->type = PF_USE_MEMORY; + pf->data = map; + pf->len = sb.st_size; + if (policydb_init(policydb)) { + fprintf(stderr, "Could not initialize policydb!\n"); + close(fd); + munmap(map, sb.st_size); + return 1; + } + ret = policydb_read(policydb, pf, 0); + if (ret) { + fprintf(stderr, "error(s) encountered while parsing configuration\n"); + close(fd); + munmap(map, sb.st_size); + return 1; + } + + return 0; +}
diff --git a/sepolicy/tools/sepolicy-analyze/utils.h b/sepolicy/tools/sepolicy-analyze/utils.h new file mode 100644 index 0000000..83f5a78 --- /dev/null +++ b/sepolicy/tools/sepolicy-analyze/utils.h
@@ -0,0 +1,16 @@ +#ifndef UTILS_H +#define UTILS_H + +#include <stdbool.h> +#include <stdint.h> +#include <sepol/policydb/avtab.h> +#include <sepol/policydb/policydb.h> + + +extern bool USAGE_ERROR; + +void display_allow(policydb_t *policydb, avtab_key_t *key, int idx, uint32_t perms); + +int load_policy(char *filename, policydb_t * policydb, struct policy_file *pf); + +#endif /* UTILS_H */
diff --git a/sepolicy/tools/sepolicy-check.c b/sepolicy/tools/sepolicy-check.c new file mode 100644 index 0000000..713e7c1 --- /dev/null +++ b/sepolicy/tools/sepolicy-check.c
@@ -0,0 +1,296 @@ +#include <getopt.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/services.h> +#include <sepol/policydb/expand.h> + +#define EQUALS 0 +#define NOT 1 +#define ANY 2 + +void usage(char *arg0) { + fprintf(stderr, "%s -s <source> -t <target> -c <class> -p <perm> -P <policy file>\n", arg0); + exit(1); +} + +void *cmalloc(size_t s) { + void *t = malloc(s); + if (t == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + return t; +} + +int parse_ops(char **arg) { + switch (*arg[0]) { + case '-': + *arg = *arg + 1; + return NOT; + case '*': + return ANY; + default: + return EQUALS; + } +} + +int check(int op, uint16_t arg1, uint16_t arg2) { + switch (op) { + case EQUALS: + return arg1 == arg2; + case NOT: + return arg1 != arg2; + case ANY: + return 1; + default: + fprintf(stderr, "Bad op while checking!"); + return 2; + } +} + +int check_perm(avtab_ptr_t current, perm_datum_t *perm) { + uint16_t perm_bitmask = 1U << (perm->s.value - 1); + return (current->datum.data & perm_bitmask) != 0; +} + + +int expand_and_check(int s_op, uint32_t source_type, + int t_op, uint32_t target_type, + int c_op, uint32_t target_class, + perm_datum_t *perm, policydb_t *policy, avtab_t *avtab) { + avtab_t exp_avtab; + avtab_ptr_t cur; + unsigned int i; + int match; + + if (avtab_init(&exp_avtab)) { + fputs("out of memory\n", stderr); + return -1; + } + + if (expand_avtab(policy, avtab, &exp_avtab)) { + fputs("out of memory\n", stderr); + avtab_destroy(&exp_avtab); + return -1; + } + + for (i = 0; i < exp_avtab.nslot; i++) { + for (cur = exp_avtab.htable[i]; cur; cur = cur->next) { + match = 1; + match &= check(s_op, source_type, cur->key.source_type); + match &= check(t_op, target_type, cur->key.target_type); + match &= check(c_op, target_class, cur->key.target_class); + match &= check_perm(cur, perm); + if (match) { + avtab_destroy(&exp_avtab); + return 1; + } + } + } + + avtab_destroy(&exp_avtab); + return 0; +} + +/* + * Checks to see if a rule matching the given arguments already exists. + * + * The format for the arguments is as follows: + * + * - A bare string is treated as a literal and will be matched by equality. + * - A string starting with "-" will be matched by inequality. + * - A string starting with "*" will be treated as a wildcard. + * + * The return codes for this function are as follows: + * + * - 0 indicates a successful return without a match + * - 1 indicates a successful return with a match + * - -1 indicates an error + */ +int check_rule(char *s, char *t, char *c, char *p, policydb_t *policy) { + type_datum_t *src = NULL; + type_datum_t *tgt = NULL; + class_datum_t *cls = NULL; + perm_datum_t *perm = NULL; + int s_op = parse_ops(&s); + int t_op = parse_ops(&t); + int c_op = parse_ops(&c); + int p_op = parse_ops(&p); + avtab_key_t key; + int match; + + key.source_type = key.target_type = key.target_class = 0; + + if (s_op != ANY) { + src = hashtab_search(policy->p_types.table, s); + if (src == NULL) { + fprintf(stderr, "source type %s does not exist\n", s); + return -1; + } + } + if (t_op != ANY) { + tgt = hashtab_search(policy->p_types.table, t); + if (tgt == NULL) { + fprintf(stderr, "target type %s does not exist\n", t); + return -1; + } + } + if (c_op != ANY) { + cls = hashtab_search(policy->p_classes.table, c); + if (cls == NULL) { + fprintf(stderr, "class %s does not exist\n", c); + return -1; + } + } + if (p_op != ANY) { + perm = hashtab_search(cls->permissions.table, p); + if (perm == NULL) { + if (cls->comdatum == NULL) { + fprintf(stderr, "perm %s does not exist in class %s\n", p, c); + return -1; + } + perm = hashtab_search(cls->comdatum->permissions.table, p); + if (perm == NULL) { + fprintf(stderr, "perm %s does not exist in class %s\n", p, c); + return -1; + } + } + } + + if (s_op != ANY) + key.source_type = src->s.value; + if (t_op != ANY) + key.target_type = tgt->s.value; + if (c_op != ANY) + key.target_class = cls->s.value; + + /* Check unconditional rules after attribute expansion. */ + match = expand_and_check(s_op, key.source_type, + t_op, key.target_type, + c_op, key.target_class, + perm, policy, &policy->te_avtab); + if (match) + return match; + + /* Check conditional rules after attribute expansion. */ + return expand_and_check(s_op, key.source_type, + t_op, key.target_type, + c_op, key.target_class, + perm, policy, &policy->te_cond_avtab); +} + +int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) { + int fd; + struct stat sb; + void *map; + int ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); + return 1; + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); + close(fd); + return 1; + } + map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); + close(fd); + return 1; + } + + policy_file_init(pf); + pf->type = PF_USE_MEMORY; + pf->data = map; + pf->len = sb.st_size; + if (policydb_init(policydb)) { + fprintf(stderr, "Could not initialize policydb!\n"); + close(fd); + munmap(map, sb.st_size); + return 1; + } + ret = policydb_read(policydb, pf, 0); + if (ret) { + fprintf(stderr, "error(s) encountered while parsing configuration\n"); + close(fd); + munmap(map, sb.st_size); + return 1; + } + + return 0; +} + + +int main(int argc, char **argv) +{ + char *policy = NULL, *source = NULL, *target = NULL, *class = NULL, *perm = NULL; + policydb_t policydb; + struct policy_file pf; + sidtab_t sidtab; + char ch; + int match = 1; + + struct option long_options[] = { + {"source", required_argument, NULL, 's'}, + {"target", required_argument, NULL, 't'}, + {"class", required_argument, NULL, 'c'}, + {"perm", required_argument, NULL, 'p'}, + {"policy", required_argument, NULL, 'P'}, + {NULL, 0, NULL, 0} + }; + + while ((ch = getopt_long(argc, argv, "s:t:c:p:P:", long_options, NULL)) != -1) { + switch (ch) { + case 's': + source = optarg; + break; + case 't': + target = optarg; + break; + case 'c': + class = optarg; + break; + case 'p': + perm = optarg; + break; + case 'P': + policy = optarg; + break; + default: + usage(argv[0]); + } + } + + if (!source || !target || !class || !perm || !policy) + usage(argv[0]); + + sepol_set_policydb(&policydb); + sepol_set_sidtab(&sidtab); + + if (load_policy(policy, &policydb, &pf)) + goto out; + + match = check_rule(source, target, class, perm, &policydb); + if (match < 0) { + fprintf(stderr, "Error checking rules!\n"); + goto out; + } else if (match > 0) { + printf("Match found!\n"); + goto out; + } + + match = 0; + +out: + policydb_destroy(&policydb); + return match; +}
diff --git a/sepolicy/tzdatacheck.te b/sepolicy/tzdatacheck.te new file mode 100644 index 0000000..f61cb47 --- /dev/null +++ b/sepolicy/tzdatacheck.te
@@ -0,0 +1,8 @@ +# The tzdatacheck command run by init. +type tzdatacheck, domain, domain_deprecated; +type tzdatacheck_exec, exec_type, file_type; + +init_daemon_domain(tzdatacheck) + +allow tzdatacheck zoneinfo_data_file:dir create_dir_perms; +allow tzdatacheck zoneinfo_data_file:file unlink;
diff --git a/sepolicy/ueventd.te b/sepolicy/ueventd.te new file mode 100644 index 0000000..f1576e7 --- /dev/null +++ b/sepolicy/ueventd.te
@@ -0,0 +1,45 @@ +# ueventd seclabel is specified in init.rc since +# it lives in the rootfs and has no unique file type. +type ueventd, domain, domain_deprecated; +tmpfs_domain(ueventd) + +# Write to /dev/kmsg. +allow ueventd kmsg_device:chr_file rw_file_perms; + +allow ueventd self:capability { chown mknod net_admin setgid fsetid sys_rawio dac_override fowner }; +allow ueventd device:file create_file_perms; +allow ueventd device:chr_file rw_file_perms; +allow ueventd sysfs:file rw_file_perms; +allow ueventd sysfs_hwrandom:file w_file_perms; +allow ueventd sysfs_zram_uevent:file w_file_perms; +allow ueventd sysfs_type:{ file lnk_file } { relabelfrom relabelto setattr getattr }; +allow ueventd sysfs_type:dir { relabelfrom relabelto setattr r_dir_perms }; +allow ueventd sysfs_devices_system_cpu:file rw_file_perms; +allow ueventd tmpfs:chr_file rw_file_perms; +allow ueventd dev_type:dir create_dir_perms; +allow ueventd dev_type:lnk_file { create unlink }; +allow ueventd dev_type:chr_file { getattr create setattr unlink }; +allow ueventd dev_type:blk_file { getattr relabelfrom relabelto create setattr unlink }; +allow ueventd self:netlink_kobject_uevent_socket create_socket_perms; +allow ueventd efs_file:dir search; +allow ueventd efs_file:file r_file_perms; + +# Use setfscreatecon() to label /dev directories and files. +allow ueventd self:process setfscreate; + +##### +##### neverallow rules +##### + +# ueventd must never set properties, otherwise deadlocks may occur. +# https://android-review.googlesource.com/#/c/133120/6/init/devices.cpp@941 +# No writing to the property socket, connecting to init, or setting properties. +neverallow ueventd property_socket:sock_file write; +neverallow ueventd init:unix_stream_socket connectto; +neverallow ueventd property_type:property_service set; + +# Restrict ueventd access on block devices to maintenence operations. +neverallow ueventd dev_type:blk_file ~{ getattr relabelfrom relabelto create setattr unlink }; + +# Only relabelto as we would never want to relabelfrom kmem_device +neverallow ueventd kmem_device:chr_file ~{ getattr create setattr unlink relabelto };
diff --git a/sepolicy/uncrypt.te b/sepolicy/uncrypt.te new file mode 100644 index 0000000..9231a4d --- /dev/null +++ b/sepolicy/uncrypt.te
@@ -0,0 +1,33 @@ +# uncrypt +type uncrypt, domain, domain_deprecated, mlstrustedsubject; +type uncrypt_exec, exec_type, file_type; + +init_daemon_domain(uncrypt) + +allow uncrypt self:capability dac_override; + +# Read OTA zip file from /data/data/com.google.android.gsf/app_download +r_dir_file(uncrypt, app_data_file) + +userdebug_or_eng(` + # For debugging, allow /data/local/tmp access + r_dir_file(uncrypt, shell_data_file) +') + +# Read /cache/recovery/command +# Read /cache/recovery/uncrypt_file +# Write to pipe file /cache/recovery/uncrypt_status +allow uncrypt cache_recovery_file:dir rw_dir_perms; +allow uncrypt cache_recovery_file:file create_file_perms; +allow uncrypt cache_recovery_file:fifo_file w_file_perms; + +# Set a property to reboot the device. +set_prop(uncrypt, powerctl_prop) + +# Raw writes to block device +allow uncrypt self:capability sys_rawio; +allow uncrypt misc_block_device:blk_file w_file_perms; +allow uncrypt block_device:dir r_dir_perms; + +# Access userdata block device. +allow uncrypt userdata_block_device:blk_file w_file_perms;
diff --git a/sepolicy/untrusted_app.te b/sepolicy/untrusted_app.te new file mode 100644 index 0000000..3f2f9dd --- /dev/null +++ b/sepolicy/untrusted_app.te
@@ -0,0 +1,170 @@ +### +### Untrusted apps. +### +### This file defines the rules for untrusted apps. +### Apps are labeled based on mac_permissions.xml (maps signer and +### optionally package name to seinfo value) and seapp_contexts (maps UID +### and optionally seinfo value to domain for process and type for data +### directory). The untrusted_app domain is the default assignment in +### seapp_contexts for any app with UID between APP_AID (10000) +### and AID_ISOLATED_START (99000) if the app has no specific seinfo +### value as determined from mac_permissions.xml. In current AOSP, this +### domain is assigned to all non-system apps as well as to any system apps +### that are not signed by the platform key. To move +### a system app into a specific domain, add a signer entry for it to +### mac_permissions.xml and assign it one of the pre-existing seinfo values +### or define and use a new seinfo value in both mac_permissions.xml and +### seapp_contexts. +### +### untrusted_app includes all the appdomain rules, plus the +### additional following rules: +### + +type untrusted_app, domain; +app_domain(untrusted_app) +net_domain(untrusted_app) +bluetooth_domain(untrusted_app) + +# Some apps ship with shared libraries and binaries that they write out +# to their sandbox directory and then execute. +allow untrusted_app app_data_file:file { rx_file_perms execmod }; + +# ASEC +allow untrusted_app asec_apk_file:file r_file_perms; +allow untrusted_app asec_apk_file:dir r_dir_perms; +# Execute libs in asec containers. +allow untrusted_app asec_public_file:file { execute execmod }; + +# Allow the allocation and use of ptys +# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm +create_pty(untrusted_app) + +# Used by Finsky / Android "Verify Apps" functionality when +# running "adb install foo.apk". +# TODO: Long term, we don't want apps probing into shell data files. +# Figure out a way to remove these rules. +allow untrusted_app shell_data_file:file r_file_perms; +allow untrusted_app shell_data_file:dir r_dir_perms; + +# Read and write system app data files passed over Binder. +# Motivating case was /data/data/com.android.settings/cache/*.jpg for +# cropping or taking user photos. +allow untrusted_app system_app_data_file:file { read write getattr }; + +# +# Rules migrated from old app domains coalesced into untrusted_app. +# This includes what used to be media_app, shared_app, and release_app. +# + +# Access to /data/media. +allow untrusted_app media_rw_data_file:dir create_dir_perms; +allow untrusted_app media_rw_data_file:file create_file_perms; + +# Traverse into /mnt/media_rw for bypassing FUSE daemon +# TODO: narrow this to just MediaProvider +allow untrusted_app mnt_media_rw_file:dir search; + +# allow cts to query all services +allow untrusted_app servicemanager:service_manager list; + +allow untrusted_app drmserver_service:service_manager find; +allow untrusted_app mediaserver_service:service_manager find; +allow untrusted_app nfc_service:service_manager find; +allow untrusted_app radio_service:service_manager find; +allow untrusted_app surfaceflinger_service:service_manager find; +allow untrusted_app app_api_service:service_manager find; + +# Allow GMS core to access perfprofd output, which is stored +# in /data/misc/perfprofd/. GMS core will need to list all +# data stored in that directory to process them one by one. +userdebug_or_eng(` + allow untrusted_app perfprofd_data_file:file r_file_perms; + allow untrusted_app perfprofd_data_file:dir r_dir_perms; +') + +# gdbserver for ndk-gdb ptrace attaches to app process. +allow untrusted_app self:process ptrace; + +# access /proc/net/xt_qtguid/stats +r_dir_file(untrusted_app, proc_net) + +# Cts: HwRngTest +allow untrusted_app sysfs_hwrandom:dir search; +allow untrusted_app sysfs_hwrandom:file r_file_perms; + +### +### neverallow rules +### + +# Receive or send uevent messages. +neverallow untrusted_app domain:netlink_kobject_uevent_socket *; + +# Receive or send generic netlink messages +neverallow untrusted_app domain:netlink_socket *; + +# Too much leaky information in debugfs. It's a security +# best practice to ensure these files aren't readable. +neverallow untrusted_app debugfs_type:file read; + +# Do not allow untrusted apps to register services. +# Only trusted components of Android should be registering +# services. +neverallow untrusted_app service_manager_type:service_manager add; + +# Do not allow untrusted_apps to connect to the property service +# or set properties. b/10243159 +neverallow untrusted_app property_socket:sock_file write; +neverallow untrusted_app init:unix_stream_socket connectto; +neverallow untrusted_app property_type:property_service set; + +# Do not allow untrusted_app to be assigned mlstrustedsubject. +# This would undermine the per-user isolation model being +# enforced via levelFrom=user in seapp_contexts and the mls +# constraints. As there is no direct way to specify a neverallow +# on attribute assignment, this relies on the fact that fork +# permission only makes sense within a domain (hence should +# never be granted to any other domain within mlstrustedsubject) +# and untrusted_app is allowed fork permission to itself. +neverallow untrusted_app mlstrustedsubject:process fork; + +# Do not allow untrusted_app to hard link to any files. +# In particular, if untrusted_app links to other app data +# files, installd will not be able to guarantee the deletion +# of the linked to file. Hard links also contribute to security +# bugs, so we want to ensure untrusted_app never has this +# capability. +neverallow untrusted_app file_type:file link; + +# Do not allow untrusted_app to access network MAC address file +neverallow untrusted_app sysfs_mac_address:file no_rw_file_perms; + +# Do not allow untrusted_app access to /cache +neverallow untrusted_app { cache_file cache_recovery_file }:dir ~{ r_dir_perms }; +neverallow untrusted_app { cache_file cache_recovery_file }:file ~{ read getattr }; + +# Do not allow untrusted_app to create/unlink files outside of its sandbox, +# internal storage or sdcard. +# World accessible data locations allow application to fill the device +# with unaccounted for data. This data will not get removed during +# application un-installation. +neverallow untrusted_app { + fs_type + -fuse # sdcard + -sdcardfs # sdcard + -vfat + file_type + -app_data_file # The apps sandbox itself + -media_rw_data_file # Internal storage. Known that apps can + # leave artfacts here after uninstall. + userdebug_or_eng(` + -method_trace_data_file # only on ro.debuggable=1 + ') + -coredump_file +}:dir_file_class_set { create unlink }; + +# Do not allow untrusted_app to directly open tun_device +neverallow untrusted_app tun_device:chr_file open; + +# Only allow appending to /data/anr/traces.txt (b/27853304, b/18340553) +neverallow untrusted_app anr_data_file:file ~{ open append }; +neverallow untrusted_app anr_data_file:dir ~search;
diff --git a/sepolicy/update_engine.te b/sepolicy/update_engine.te new file mode 100644 index 0000000..69e84cc --- /dev/null +++ b/sepolicy/update_engine.te
@@ -0,0 +1,32 @@ +# Domain for update_engine daemon. +# update_engine uses the boot_control_hal. +type update_engine, domain, domain_deprecated, update_engine_common, boot_control_hal; +type update_engine_exec, exec_type, file_type; +type update_engine_data_file, file_type, data_file_type; + +init_daemon_domain(update_engine); +net_domain(update_engine); + +# Following permissions are needed for update_engine. +allow update_engine self:process { setsched }; +allow update_engine self:capability { fowner sys_admin }; +allow update_engine kmsg_device:chr_file w_file_perms; +allow update_engine update_engine_exec:file rx_file_perms; +wakelock_use(update_engine); + +# Ignore these denials. +dontaudit update_engine kernel:process setsched; + +# Allow using persistent storage in /data/misc/update_engine. +allow update_engine update_engine_data_file:dir { create_dir_perms }; +allow update_engine update_engine_data_file:file { create_file_perms }; + +# Don't allow kernel module loading, just silence the logs. +dontaudit update_engine kernel:system module_request; + +# Register the service to perform Binder IPC. +binder_use(update_engine) +allow update_engine update_engine_service:service_manager { add }; + +# Allow update_engine to call the callback function provided by priv_app. +binder_call(update_engine, priv_app)
diff --git a/sepolicy/update_engine_common.te b/sepolicy/update_engine_common.te new file mode 100644 index 0000000..e70e44d --- /dev/null +++ b/sepolicy/update_engine_common.te
@@ -0,0 +1,37 @@ +# update_engine payload application permissions. These are shared between the +# background daemon and the recovery tool to sideload an update. + +# Allow update_engine to reach block devices in /dev/block. +allow update_engine_common block_device:dir search; + +# Allow read/write on system and boot partitions. +allow update_engine_common boot_block_device:blk_file rw_file_perms; +allow update_engine_common system_block_device:blk_file rw_file_perms; + +# Allow to set recovery options in the BCB. Used to trigger factory reset when +# the update to an older version (channel change) or incompatible version +# requires it. +allow update_engine_common misc_block_device:blk_file rw_file_perms; + +# Allow update_engine_common to mount on the /postinstall directory and reset the +# labels on the mounted filesystem to postinstall_file. +allow update_engine_common postinstall_mnt_dir:dir mounton; +allow update_engine_common postinstall_file:filesystem { mount unmount relabelfrom relabelto }; +allow update_engine_common labeledfs:filesystem relabelfrom; + +# Allow update_engine_common to read and execute postinstall_file. +allow update_engine_common postinstall_file:file rx_file_perms; +allow update_engine_common postinstall_file:lnk_file r_file_perms; +allow update_engine_common postinstall_file:dir r_dir_perms; + +# The postinstall program is run by update_engine_common and will always be tagged as a +# postinstall_file regardless of its attributes in the new system. +domain_auto_trans(update_engine_common, postinstall_file, postinstall) + +# A postinstall program is typically a shell script (with a #!), so we allow +# to execute those. +allow update_engine_common shell_exec:file rx_file_perms; + +# Allow update_engine_common to suspend, resume and kill the postinstall program. +allow update_engine_common postinstall:process { signal sigstop }; +
diff --git a/sepolicy/update_verifier.te b/sepolicy/update_verifier.te new file mode 100644 index 0000000..65438d3 --- /dev/null +++ b/sepolicy/update_verifier.te
@@ -0,0 +1,8 @@ +# update_verifier +# update_verifier uses the boot_control_hal. +type update_verifier, domain, boot_control_hal; +type update_verifier_exec, exec_type, file_type; + +init_daemon_domain(update_verifier) + +# TODO: Add rules to allow update_verifier to read system_block_device.
diff --git a/sepolicy/users b/sepolicy/users new file mode 100644 index 0000000..51b7b57 --- /dev/null +++ b/sepolicy/users
@@ -0,0 +1 @@ +user u roles { r } level s0 range s0 - mls_systemhigh;
diff --git a/sepolicy/vdc.te b/sepolicy/vdc.te new file mode 100644 index 0000000..5478965 --- /dev/null +++ b/sepolicy/vdc.te
@@ -0,0 +1,23 @@ +# vdc spawned from init for the following services: +# defaultcrypto +# encrypt +# +# We also transition into this domain from dumpstate, when +# collecting bug reports. + +type vdc, domain, domain_deprecated; +type vdc_exec, exec_type, file_type; + +init_daemon_domain(vdc) + +unix_socket_connect(vdc, vold, vold) + +# vdc sends information back to dumpstate when "adb bugreport" is used +allow vdc dumpstate:fd use; +allow vdc dumpstate:unix_stream_socket { read write getattr }; + +# vdc information is written to shell owned bugreport files +allow vdc shell_data_file:file { write getattr }; + +# Why? +allow vdc dumpstate:unix_dgram_socket { read write };
diff --git a/sepolicy/vold.te b/sepolicy/vold.te new file mode 100644 index 0000000..737037d --- /dev/null +++ b/sepolicy/vold.te
@@ -0,0 +1,193 @@ +# volume manager +type vold, domain, domain_deprecated; +type vold_exec, exec_type, file_type; + +init_daemon_domain(vold) + +# Switch to more restrictive domains when executing common tools +domain_auto_trans(vold, sgdisk_exec, sgdisk); +domain_auto_trans(vold, sdcardd_exec, sdcardd); + +# Read already opened /cache files. +allow vold cache_file:dir r_dir_perms; +allow vold cache_file:file { getattr read }; +allow vold cache_file:lnk_file r_file_perms; + +# Read access to pseudo filesystems. +r_dir_file(vold, proc) +r_dir_file(vold, proc_net) +r_dir_file(vold, sysfs) +r_dir_file(vold, rootfs) + +# For a handful of probing tools, we choose an even more restrictive +# domain when working with untrusted block devices +domain_trans(vold, shell_exec, blkid); +domain_trans(vold, shell_exec, blkid_untrusted); +domain_trans(vold, fsck_exec, fsck); +domain_trans(vold, fsck_exec, fsck_untrusted); + +# Allow us to jump into execution domains of above tools +allow vold self:process setexec; + +# For sgdisk launched through popen() +allow vold shell_exec:file rx_file_perms; + +typeattribute vold mlstrustedsubject; +allow vold self:process setfscreate; +allow vold system_file:file x_file_perms; +allow vold block_device:dir create_dir_perms; +allow vold device:dir write; +allow vold devpts:chr_file rw_file_perms; +allow vold rootfs:dir mounton; +allow vold sdcard_type:dir mounton; # TODO: deprecated in M +allow vold sdcard_type:filesystem { mount remount unmount }; # TODO: deprecated in M +allow vold sdcard_type:dir create_dir_perms; # TODO: deprecated in M +allow vold sdcard_type:file create_file_perms; # TODO: deprecated in M + +# Manage locations where storage is mounted +allow vold { mnt_media_rw_file storage_file sdcard_type }:dir create_dir_perms; +allow vold { mnt_media_rw_file storage_file sdcard_type }:file create_file_perms; + +# Access to storage that backs emulated FUSE daemons for migration optimization +allow vold media_rw_data_file:dir create_dir_perms; +allow vold media_rw_data_file:file create_file_perms; + +# Newly created storage dirs are always treated as mount stubs to prevent us +# from accidentally writing when the mount point isn't present. +type_transition vold storage_file:dir storage_stub_file; +type_transition vold mnt_media_rw_file:dir mnt_media_rw_stub_file; + +# Allow mounting of storage devices +allow vold { mnt_media_rw_stub_file storage_stub_file }:dir { mounton create rmdir getattr setattr }; +allow vold sdcard_type:filesystem { mount unmount remount }; + +# Manage per-user primary symlinks +allow vold mnt_user_file:dir create_dir_perms; +allow vold mnt_user_file:lnk_file create_file_perms; + +# Allow to create and mount expanded storage +allow vold mnt_expand_file:dir { create_dir_perms mounton }; +allow vold apk_data_file:dir { create getattr setattr }; +allow vold shell_data_file:dir { create getattr setattr }; + +allow vold tmpfs:filesystem { mount unmount }; +allow vold tmpfs:dir create_dir_perms; +allow vold tmpfs:dir mounton; +allow vold self:capability { net_admin dac_override mknod sys_admin chown fowner fsetid }; +allow vold self:netlink_kobject_uevent_socket create_socket_perms; +allow vold app_data_file:dir search; +allow vold app_data_file:file rw_file_perms; +allow vold loop_device:blk_file create_file_perms; +allow vold vold_device:blk_file create_file_perms; +allow vold dm_device:chr_file rw_file_perms; +allow vold dm_device:blk_file rw_file_perms; +# For vold Process::killProcessesWithOpenFiles function. +allow vold domain:dir r_dir_perms; +allow vold domain:{ file lnk_file } r_file_perms; +allow vold domain:process { signal sigkill }; +allow vold self:capability { sys_ptrace kill }; + +# XXX Label sysfs files with a specific type? +allow vold sysfs:file rw_file_perms; + +allow vold kmsg_device:chr_file rw_file_perms; + +# Run fsck in the fsck domain. +allow vold fsck_exec:file { r_file_perms execute }; + +# Log fsck results +allow vold fscklogs:dir rw_dir_perms; +allow vold fscklogs:file create_file_perms; + +# +# Rules to support encrypted fs support. +# + +# Unmount and mount the fs. +allow vold labeledfs:filesystem { mount unmount remount }; + +# Access /efs/userdata_footer. +# XXX Split into a separate type? +allow vold efs_file:file rw_file_perms; + +# Create and mount on /data/tmp_mnt and management of expansion mounts +allow vold system_data_file:dir { create rw_dir_perms mounton setattr rmdir }; + +# Set scheduling policy of kernel processes +allow vold kernel:process setsched; + +# Property Service +set_prop(vold, vold_prop) +set_prop(vold, powerctl_prop) +set_prop(vold, ctl_fuse_prop) +set_prop(vold, restorecon_prop) + +# ASEC +allow vold asec_image_file:file create_file_perms; +allow vold asec_image_file:dir rw_dir_perms; +allow vold asec_apk_file:dir { create_dir_perms mounton relabelfrom relabelto }; +allow vold asec_public_file:dir { relabelto setattr }; +allow vold asec_apk_file:file { r_file_perms setattr relabelfrom relabelto }; +allow vold asec_public_file:file { relabelto setattr }; +# restorecon files in asec containers created on 4.2 or earlier. +allow vold unlabeled:dir { r_dir_perms setattr relabelfrom }; +allow vold unlabeled:file { r_file_perms setattr relabelfrom }; + +# Handle wake locks (used for device encryption) +wakelock_use(vold) + +# talk to batteryservice +binder_use(vold) +binder_call(vold, healthd) + +# talk to keymaster +allow vold tee_device:chr_file rw_file_perms; + +# Access userdata block device. +allow vold userdata_block_device:blk_file rw_file_perms; + +# Access metadata block device used for encryption meta-data. +allow vold metadata_block_device:blk_file rw_file_perms; + +# Allow vold to manipulate /data/unencrypted +allow vold unencrypted_data_file:{ file } create_file_perms; +allow vold unencrypted_data_file:dir create_dir_perms; + +# Write to /proc/sys/vm/drop_caches +allow vold proc_drop_caches:file w_file_perms; + +# Give vold a place where only vold can store files; everyone else is off limits +allow vold vold_data_file:dir create_dir_perms; +allow vold vold_data_file:file create_file_perms; + +# linux keyring configuration +allow vold init:key { write search setattr }; +allow vold vold:key { write search setattr }; + +# vold temporarily changes its priority when running benchmarks +allow vold self:capability sys_nice; + +# vold needs to chroot into app namespaces to remount when runtime permissions change +allow vold self:capability sys_chroot; +allow vold storage_file:dir mounton; + +# For AppFuse. +allow vold fuse_device:chr_file rw_file_perms; +allow vold fuse:filesystem { relabelfrom }; +allow vold app_fusefs:filesystem { relabelfrom relabelto }; +allow vold app_fusefs:filesystem { mount unmount }; + +# coldboot of /sys/block +allow vold sysfs_zram:dir r_dir_perms; +allow vold sysfs_zram_uevent:file rw_file_perms; + +# MoveTask.cpp executes cp and rm +allow vold toolbox_exec:file rx_file_perms; + +neverallow { domain -vold } vold_data_file:dir ~{ open create read getattr setattr search relabelto ioctl }; +neverallow { domain -vold } vold_data_file:notdevfile_class_set ~{ relabelto getattr }; +neverallow { domain -vold -init } vold_data_file:dir *; +neverallow { domain -vold -init } vold_data_file:notdevfile_class_set *; +neverallow { domain -vold -init } restorecon_prop:property_service set; + +neverallow vold fsck_exec:file execute_no_trans;
diff --git a/sepolicy/watchdogd.te b/sepolicy/watchdogd.te new file mode 100644 index 0000000..00292a9 --- /dev/null +++ b/sepolicy/watchdogd.te
@@ -0,0 +1,4 @@ +# watchdogd seclabel is specified in init.<board>.rc +type watchdogd, domain; +allow watchdogd watchdog_device:chr_file rw_file_perms; +allow watchdogd kmsg_device:chr_file rw_file_perms;
diff --git a/sepolicy/wpa.te b/sepolicy/wpa.te new file mode 100644 index 0000000..46d975b --- /dev/null +++ b/sepolicy/wpa.te
@@ -0,0 +1,48 @@ +# wpa - wpa supplicant or equivalent +type wpa, domain, domain_deprecated; +type wpa_exec, exec_type, file_type; + +init_daemon_domain(wpa) + +net_domain(wpa) + +allow wpa kernel:system module_request; +allow wpa self:capability { setuid net_admin setgid net_raw }; +allow wpa cgroup:dir create_dir_perms; +allow wpa self:netlink_route_socket nlmsg_write; +allow wpa self:netlink_socket create_socket_perms; +allow wpa self:netlink_generic_socket create_socket_perms; +allow wpa self:packet_socket create_socket_perms; +allow wpa wifi_data_file:dir create_dir_perms; +allow wpa wifi_data_file:file create_file_perms; +unix_socket_send(wpa, system_wpa, system_server) + +binder_use(wpa) + +# Create a socket for receiving info from wpa +type_transition wpa wifi_data_file:dir wpa_socket "sockets"; +allow wpa wpa_socket:dir create_dir_perms; +allow wpa wpa_socket:sock_file create_file_perms; + +use_keystore(wpa) + +# WPA (wifi) has a restricted set of permissions from the default. +allow wpa keystore:keystore_key { + get + sign + verify +}; + +# Allow wpa_cli to work. wpa_cli creates a socket in +# /data/misc/wifi/sockets which wpa supplicant communicates with. +userdebug_or_eng(` + unix_socket_send(wpa, wpa, su) +') + +### +### neverallow rules +### + +# wpa_supplicant should not trust any data from sdcards +neverallow wpa sdcard_type:dir ~getattr; +neverallow wpa sdcard_type:file *;
diff --git a/sepolicy/zygote.te b/sepolicy/zygote.te new file mode 100644 index 0000000..83f2c76 --- /dev/null +++ b/sepolicy/zygote.te
@@ -0,0 +1,98 @@ +# zygote +type zygote, domain, domain_deprecated; +type zygote_exec, exec_type, file_type; + +init_daemon_domain(zygote) +typeattribute zygote mlstrustedsubject; +# Override DAC on files and switch uid/gid. +allow zygote self:capability { dac_override setgid setuid fowner chown }; +# Drop capabilities from bounding set. +allow zygote self:capability setpcap; +# Switch SELinux context to app domains. +allow zygote self:process setcurrent; +allow zygote system_server:process dyntransition; +allow zygote appdomain:process dyntransition; +# Allow zygote to read app /proc/pid dirs (b/10455872) +allow zygote appdomain:dir { getattr search }; +allow zygote appdomain:file { r_file_perms }; +# Move children into the peer process group. +allow zygote system_server:process { getpgid setpgid }; +allow zygote appdomain:process { getpgid setpgid }; +# Read system data. +allow zygote system_data_file:dir r_dir_perms; +allow zygote system_data_file:file r_file_perms; +# Write to /data/dalvik-cache. +allow zygote dalvikcache_data_file:dir create_dir_perms; +allow zygote dalvikcache_data_file:file create_file_perms; +# Create symlinks in /data/dalvik-cache +allow zygote dalvikcache_data_file:lnk_file create_file_perms; +# Write to /data/resource-cache +allow zygote resourcecache_data_file:dir rw_dir_perms; +allow zygote resourcecache_data_file:file create_file_perms; +# For art. +allow zygote dalvikcache_data_file:file execute; +# Execute idmap and dex2oat within zygote's own domain. +# TODO: Should either of these be transitioned to the same domain +# used by installd or stay in-domain for zygote? +allow zygote idmap_exec:file rx_file_perms; +allow zygote dex2oat_exec:file rx_file_perms; +# Control cgroups. +allow zygote cgroup:dir create_dir_perms; +allow zygote self:capability sys_admin; +# Check validity of SELinux context before use. +selinux_check_context(zygote) +# Check SELinux permissions. +selinux_check_access(zygote) + +# Native bridge functionality requires that zygote replaces +# /proc/cpuinfo with /system/lib/<ISA>/cpuinfo using a bind mount +allow zygote proc_cpuinfo:file mounton; + +# Allow remounting rootfs as MS_SLAVE +allow zygote rootfs:dir mounton; +allow zygote tmpfs:filesystem { mount unmount }; +allow zygote fuse:filesystem { unmount }; +allow zygote sdcardfs:filesystem { unmount }; + +# Allowed to create user-specific storage source if started before vold +allow zygote mnt_user_file:dir create_dir_perms; +allow zygote mnt_user_file:lnk_file create_file_perms; +# Allowed to mount user-specific storage into place +allow zygote storage_file:dir { search mounton }; + +# Handle --invoke-with command when launching Zygote with a wrapper command. +allow zygote zygote_exec:file rx_file_perms; + +# Read access to pseudo filesystems. +r_dir_file(zygote, proc_net) + +# Root fs. +allow zygote rootfs:file r_file_perms; + +# System file accesses. +allow zygote system_file:dir r_dir_perms; +allow zygote system_file:file r_file_perms; + +userdebug_or_eng(` + # Allow zygote to create and write method traces in /data/misc/trace. + allow zygote method_trace_data_file:dir w_dir_perms; + allow zygote method_trace_data_file:file { create w_file_perms }; +') + +### +### neverallow rules +### + +# Ensure that all types assigned to app processes are included +# in the appdomain attribute, so that all allow and neverallow rules +# written on appdomain are applied to all app processes. +# This is achieved by ensuring that it is impossible for zygote to +# setcon (dyntransition) to any types other than those associated +# with appdomain plus system_server. +neverallow zygote ~{ appdomain system_server }:process dyntransition; + +# Zygote should never execute anything from /data except for /data/dalvik-cache files. +neverallow zygote { + data_file_type + -dalvikcache_data_file # map PROT_EXEC +}:file no_x_file_perms;