Merge "Move sysfs cpu hotplug labeling to genfs_contexts" into oc-dev
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..9952a8f
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1 @@
+subdirs = ["tests"]
diff --git a/Android.mk b/Android.mk
index dd37341..1a01644 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,7 +10,7 @@
# is made which breaks compatibility with the previous platform sepolicy version,
# not just on every increase in PLATFORM_SDK_VERSION. The minor version should
# be reset to 0 on every bump of the PLATFORM_SDK_VERSION.
-sepolicy_major_vers := 25
+sepolicy_major_vers := 26
sepolicy_minor_vers := 0
ifneq ($(sepolicy_major_vers), $(PLATFORM_SDK_VERSION))
@@ -80,7 +80,21 @@
# - compile output binary policy file
PLAT_PUBLIC_POLICY := $(LOCAL_PATH)/public
+ifneq ( ,$(BOARD_PLAT_PUBLIC_SEPOLICY_DIR))
+ifneq (1, $(words $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR)))
+$(error BOARD_PLAT_PUBLIC_SEPOLICY_DIR must only contain one directory)
+else
+PLAT_PUBLIC_POLICY += $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR)
+endif
+endif
PLAT_PRIVATE_POLICY := $(LOCAL_PATH)/private
+ifneq ( ,$(BOARD_PLAT_PRIVATE_SEPOLICY_DIR))
+ifneq (1, $(words $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR)))
+$(error BOARD_PLAT_PRIVATE_SEPOLICY_DIR must only contain one directory)
+else
+PLAT_PRIVATE_POLICY += $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR)
+endif
+endif
PLAT_VENDOR_POLICY := $(LOCAL_PATH)/vendor
REQD_MASK_POLICY := $(LOCAL_PATH)/reqd_mask
@@ -178,7 +192,8 @@
secilc \
nonplat_file_contexts \
plat_file_contexts \
- plat_sepolicy_vers.txt
+ plat_sepolicy_vers.txt \
+ treble_sepolicy_tests
# Include precompiled policy, unless told otherwise
ifneq ($(PRODUCT_PRECOMPILED_SEPOLICY),false)
@@ -344,22 +359,25 @@
include $(BUILD_SYSTEM)/base_rules.mk
+current_mapping.cil := $(intermediates)/mapping/$(PLATFORM_SEPOLICY_VERSION).cil
+ifeq ($(BOARD_SEPOLICY_VERS), $(PLATFORM_SEPOLICY_VERSION))
# auto-generate the mapping file for current platform policy, since it needs to
# track platform policy development
-current_mapping.cil := $(intermediates)/mapping/$(PLATFORM_SEPOLICY_VERSION).cil
$(current_mapping.cil) : PRIVATE_VERS := $(PLATFORM_SEPOLICY_VERSION)
$(current_mapping.cil) : $(plat_pub_policy.cil) $(HOST_OUT_EXECUTABLES)/version_policy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/version_policy -b $< -m -n $(PRIVATE_VERS) -o $@
+else # ifeq ($(BOARD_SEPOLICY_VERS), $(PLATFORM_SEPOLICY_VERSION))
+prebuilt_mapping_files := $(wildcard $(addsuffix /mapping/$(BOARD_SEPOLICY_VERS).cil, $(PLAT_PRIVATE_POLICY)))
+$(current_mapping.cil) : $(prebuilt_mapping_files)
+ @mkdir -p $(dir $@)
+ cat $^ > $@
-ifeq ($(BOARD_SEPOLICY_VERS), $(PLATFORM_SEPOLICY_VERSION))
-mapping_policy := $(current_mapping.cil)
-else
-mapping_policy := $(addsuffix /$(BOARD_SEPOLICY_VERS).cil, $(PLAT_PRIVATE_POLICY)/mapping)
+prebuilt_mapping_files :=
endif
-$(LOCAL_BUILT_MODULE): $(mapping_policy) $(ACP)
+$(LOCAL_BUILT_MODULE): $(current_mapping.cil) $(ACP)
$(hide) $(ACP) $< $@
built_mapping_cil := $(LOCAL_BUILT_MODULE)
@@ -610,9 +628,10 @@
# 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 := $(PLAT_PRIVATE_POLICY)/file_contexts
+local_fc_files := $(call build_policy, file_contexts, $(PLAT_PRIVATE_POLICY))
+
ifneq ($(filter address,$(SANITIZE_TARGET)),)
- local_fc_files := $(local_fc_files) $(PLAT_PRIVATE_POLICY)/file_contexts_asan
+ local_fc_files := $(local_fc_files) $(wildcard $(addsuffix /file_contexts_asan, $(PLAT_PRIVATE_POLICY)))
endif
local_fcfiles_with_nl := $(call add_nl, $(local_fc_files), $(built_nl))
@@ -682,9 +701,9 @@
include $(BUILD_SYSTEM)/base_rules.mk
-local_fc_files := $(PLAT_PRIVATE_POLICY)/file_contexts
+local_fc_files := $(call build_policy, file_contexts, $(PLAT_PRIVATE_POLICY))
ifneq ($(filter address,$(SANITIZE_TARGET)),)
- local_fc_files += $(PLAT_PRIVATE_POLICY)/file_contexts_asan
+ local_fc_files += $(wildcard $(addsuffix /file_contexts_asan, $(PLAT_PRIVATE_POLICY)))
endif
local_fcfiles_with_nl := $(call add_nl, $(local_fc_files), $(built_nl))
@@ -767,7 +786,7 @@
include $(BUILD_SYSTEM)/base_rules.mk
nonplat_sc_files := $(call build_policy, seapp_contexts, $(PLAT_VENDOR_POLICY) $(BOARD_SEPOLICY_DIRS) $(REQD_MASK_POLICY))
-plat_sc_neverallow_files := $(addprefix $(PLAT_PRIVATE_POLICY)/, seapp_contexts)
+plat_sc_neverallow_files := $(call build_policy, seapp_contexts, $(PLAT_PRIVATE_POLICY))
$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
$(LOCAL_BUILT_MODULE): PRIVATE_SC_FILES := $(nonplat_sc_files)
@@ -1112,6 +1131,27 @@
all_nonplat_mac_perms_files :=
##################################
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+include $(CLEAR_VARS)
+# For Treble builds run tests verifying that processes are properly labeled and
+# permissions granted do not violate the treble model.
+LOCAL_MODULE := treble_sepolicy_tests
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+treble_sepolicy_tests := $(intermediates)/treble_sepolicy_tests
+$(treble_sepolicy_tests): PRIVATE_PLAT_FC := $(built_plat_fc)
+$(treble_sepolicy_tests): PRIVATE_NONPLAT_FC := $(built_nonplat_fc)
+$(treble_sepolicy_tests): PRIVATE_SEPOLICY := $(built_sepolicy)
+$(treble_sepolicy_tests): $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py \
+$(built_plat_fc) $(built_nonplat_fc) $(built_sepolicy)
+ @mkdir -p $(dir $@)
+ $(hide) python $(HOST_OUT_EXECUTABLES)/treble_sepolicy_tests.py -l $(HOST_OUT)/lib64 -f $(PRIVATE_PLAT_FC) -f $(PRIVATE_NONPLAT_FC) -p $(PRIVATE_SEPOLICY)
+ $(hide) touch $@
+endif # ($(PRODUCT_FULL_TREBLE),true)
+#################################
add_nl :=
build_device_policy :=
diff --git a/private/app.te b/private/app.te
index 309d27c..4b9d87d 100644
--- a/private/app.te
+++ b/private/app.te
@@ -114,6 +114,7 @@
# Allow apps access to /vendor/app except for privileged
# apps which cannot be in /vendor.
r_dir_file({ appdomain -ephemeral_app -untrusted_v2_app }, vendor_app_file)
+allow { appdomain -ephemeral_app -untrusted_v2_app } vendor_app_file:file execute;
# Allow apps access to /vendor/overlay
r_dir_file(appdomain, vendor_overlay_file)
diff --git a/private/attributes b/private/attributes
new file mode 100644
index 0000000..fcbfecf
--- /dev/null
+++ b/private/attributes
@@ -0,0 +1,9 @@
+# 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;
diff --git a/private/clatd.te b/private/clatd.te
index 5ba0fc5..c09398d 100644
--- a/private/clatd.te
+++ b/private/clatd.te
@@ -1 +1,2 @@
typeattribute clatd coredomain;
+typeattribute clatd domain_deprecated;
diff --git a/private/dex2oat.te b/private/dex2oat.te
index fd45484..89c3970 100644
--- a/private/dex2oat.te
+++ b/private/dex2oat.te
@@ -1 +1,2 @@
typeattribute dex2oat coredomain;
+typeattribute dex2oat domain_deprecated;
diff --git a/private/dhcp.te b/private/dhcp.te
index b2f8ac7..6a6a139 100644
--- a/private/dhcp.te
+++ b/private/dhcp.te
@@ -1,4 +1,5 @@
typeattribute dhcp coredomain;
+typeattribute dhcp domain_deprecated;
init_daemon_domain(dhcp)
type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
diff --git a/public/domain_deprecated.te b/private/domain_deprecated.te
similarity index 98%
rename from public/domain_deprecated.te
rename to private/domain_deprecated.te
index 7a26bec..aefb724 100644
--- a/public/domain_deprecated.te
+++ b/private/domain_deprecated.te
@@ -79,7 +79,6 @@
-fingerprintd
-installd
-keystore
- -rild
-surfaceflinger
-system_server
-update_engine
@@ -193,7 +192,6 @@
domain_deprecated
-fsck
-fsck_untrusted
- -rild
-sdcardd
-system_server
-update_engine
@@ -203,7 +201,6 @@
domain_deprecated
-fsck
-fsck_untrusted
- -rild
-system_server
-vold
} proc:lnk_file { open ioctl lock }; # getattr read granted in domain
@@ -213,7 +210,6 @@
-fingerprintd
-healthd
-netd
- -rild
-system_app
-surfaceflinger
-system_server
@@ -227,7 +223,6 @@
-fingerprintd
-healthd
-netd
- -rild
-system_app
-surfaceflinger
-system_server
@@ -241,7 +236,6 @@
-fingerprintd
-healthd
-netd
- -rild
-system_app
-surfaceflinger
-system_server
@@ -259,7 +253,6 @@
-installd
-keystore
-netd
- -rild
-surfaceflinger
-system_server
-zygote
@@ -274,7 +267,6 @@
-installd
-keystore
-netd
- -rild
-surfaceflinger
-system_server
-zygote
diff --git a/private/dumpstate.te b/private/dumpstate.te
index b8f8152..0fe2adf 100644
--- a/private/dumpstate.te
+++ b/private/dumpstate.te
@@ -1,4 +1,5 @@
typeattribute dumpstate coredomain;
+typeattribute dumpstate domain_deprecated;
init_daemon_domain(dumpstate)
diff --git a/private/ephemeral_app.te b/private/ephemeral_app.te
index 2d4b1f1..d664a50 100644
--- a/private/ephemeral_app.te
+++ b/private/ephemeral_app.te
@@ -26,6 +26,7 @@
allow ephemeral_app mediaextractor_service:service_manager find;
allow ephemeral_app mediacodec_service:service_manager find;
allow ephemeral_app mediametrics_service:service_manager find;
+allow ephemeral_app mediadrmserver_service:service_manager find;
allow ephemeral_app mediacasserver_service:service_manager find;
allow ephemeral_app surfaceflinger_service:service_manager find;
allow ephemeral_app radio_service:service_manager find;
diff --git a/private/file_contexts b/private/file_contexts
index 4867796..aefd95f 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -282,6 +282,7 @@
# TODO: b/36790901 move this to /vendor/etc
/(vendor|system/vendor)/manifest.xml u:object_r:vendor_configs_file:s0
+/(vendor|system/vendor)/compatibility_matrix.xml u:object_r:vendor_configs_file:s0
/(vendor|system/vendor)/app(/.*)? u:object_r:vendor_app_file:s0
/(vendor|system/vendor)/overlay(/.*)? u:object_r:vendor_overlay_file:s0
/(vendor|system/vendor)/framework(/.*)? u:object_r:vendor_framework_file:s0
diff --git a/private/fingerprintd.te b/private/fingerprintd.te
index eb73ef8..0c1dfaa 100644
--- a/private/fingerprintd.te
+++ b/private/fingerprintd.te
@@ -1,3 +1,4 @@
typeattribute fingerprintd coredomain;
+typeattribute fingerprintd domain_deprecated;
init_daemon_domain(fingerprintd)
diff --git a/private/fsck.te b/private/fsck.te
index 3a36329..e846797 100644
--- a/private/fsck.te
+++ b/private/fsck.te
@@ -1,3 +1,4 @@
typeattribute fsck coredomain;
+typeattribute fsck domain_deprecated;
init_daemon_domain(fsck)
diff --git a/private/fsck_untrusted.te b/private/fsck_untrusted.te
index 9a57bf0..2a1a39f 100644
--- a/private/fsck_untrusted.te
+++ b/private/fsck_untrusted.te
@@ -1 +1,2 @@
typeattribute fsck_untrusted coredomain;
+typeattribute fsck_untrusted domain_deprecated;
diff --git a/private/hwservice_contexts b/private/hwservice_contexts
index ecac57e..0516364 100644
--- a/private/hwservice_contexts
+++ b/private/hwservice_contexts
@@ -1,3 +1,4 @@
+android.frameworks.displayservice::IDisplayService u:object_r:fwk_display_hwservice:s0
android.frameworks.schedulerservice::ISchedulingPolicyService u:object_r:fwk_scheduler_hwservice:s0
android.frameworks.sensorservice::ISensorManager u:object_r:fwk_sensor_hwservice:s0
android.hardware.audio.effect::IEffectsFactory u:object_r:hal_audio_hwservice:s0
@@ -25,6 +26,7 @@
android.hardware.media.omx::IOmxStore u:object_r:hal_omx_hwservice:s0
android.hardware.memtrack::IMemtrack u:object_r:hal_memtrack_hwservice:s0
android.hardware.nfc::INfc u:object_r:hal_nfc_hwservice:s0
+android.hardware.oemlock::IOemLock u:object_r:hal_oemlock_hwservice:s0
android.hardware.power::IPower u:object_r:hal_power_hwservice:s0
android.hardware.radio.deprecated::IOemHook u:object_r:hal_telephony_hwservice:s0
android.hardware.radio::IRadio u:object_r:hal_telephony_hwservice:s0
@@ -38,6 +40,7 @@
android.hardware.usb::IUsb u:object_r:hal_usb_hwservice:s0
android.hardware.vibrator::IVibrator u:object_r:hal_vibrator_hwservice:s0
android.hardware.vr::IVr u:object_r:hal_vr_hwservice:s0
+android.hardware.weaver::IWeaver u:object_r:hal_weaver_hwservice:s0
android.hardware.wifi::IWifi u:object_r:hal_wifi_hwservice:s0
android.hardware.wifi.supplicant::ISupplicant u:object_r:hal_wifi_supplicant_hwservice:s0
android.hidl.allocator::IAllocator u:object_r:hidl_allocator_hwservice:s0
diff --git a/private/init.te b/private/init.te
index f84d87e..568e0d3 100644
--- a/private/init.te
+++ b/private/init.te
@@ -13,8 +13,7 @@
domain_trans(init, shell_exec, shell)
domain_trans(init, init_exec, ueventd)
domain_trans(init, init_exec, watchdogd)
-domain_trans(init, rootfs, modprobe)
-domain_trans(init, toolbox_exec, modprobe)
+domain_trans(init, { rootfs toolbox_exec }, modprobe)
# case where logpersistd is actually logcat -f in logd context (nee: logcatd)
userdebug_or_eng(`
domain_auto_trans(init, logcat_exec, logpersist)
diff --git a/private/installd.te b/private/installd.te
index f74843d..d726e7d 100644
--- a/private/installd.te
+++ b/private/installd.te
@@ -1,4 +1,5 @@
typeattribute installd coredomain;
+typeattribute installd domain_deprecated;
init_daemon_domain(installd)
diff --git a/private/keystore.te b/private/keystore.te
index a9647c6..1e56338 100644
--- a/private/keystore.te
+++ b/private/keystore.te
@@ -1,4 +1,5 @@
typeattribute keystore coredomain;
+typeattribute keystore domain_deprecated;
init_daemon_domain(keystore)
diff --git a/private/mtp.te b/private/mtp.te
index 732e111..3cfda0b 100644
--- a/private/mtp.te
+++ b/private/mtp.te
@@ -1,3 +1,4 @@
typeattribute mtp coredomain;
+typeattribute mtp domain_deprecated;
init_daemon_domain(mtp)
diff --git a/private/netd.te b/private/netd.te
index f501f25..3a824af 100644
--- a/private/netd.te
+++ b/private/netd.te
@@ -1,4 +1,5 @@
typeattribute netd coredomain;
+typeattribute netd domain_deprecated;
init_daemon_domain(netd)
diff --git a/private/perfprofd.te b/private/perfprofd.te
index 9c249fd..a655f1d 100644
--- a/private/perfprofd.te
+++ b/private/perfprofd.te
@@ -1,4 +1,5 @@
userdebug_or_eng(`
typeattribute perfprofd coredomain;
+ typeattribute perfprofd domain_deprecated;
init_daemon_domain(perfprofd)
')
diff --git a/private/ppp.te b/private/ppp.te
index 968b221..9b301f4 100644
--- a/private/ppp.te
+++ b/private/ppp.te
@@ -1,3 +1,4 @@
typeattribute ppp coredomain;
+typeattribute ppp domain_deprecated;
domain_auto_trans(mtp, ppp_exec, ppp)
diff --git a/private/radio.te b/private/radio.te
index b4f5390..83b5b41 100644
--- a/private/radio.te
+++ b/private/radio.te
@@ -1,4 +1,5 @@
typeattribute radio coredomain;
+typeattribute radio domain_deprecated;
app_domain(radio)
diff --git a/private/recovery.te b/private/recovery.te
index 2a7fdc7..b7b2847 100644
--- a/private/recovery.te
+++ b/private/recovery.te
@@ -1 +1,2 @@
typeattribute recovery coredomain;
+typeattribute recovery domain_deprecated;
diff --git a/private/runas.te b/private/runas.te
index ef31aac..73a91ff 100644
--- a/private/runas.te
+++ b/private/runas.te
@@ -1,4 +1,5 @@
typeattribute runas coredomain;
+typeattribute runas domain_deprecated;
# ndk-gdb invokes adb shell run-as.
domain_auto_trans(shell, runas_exec, runas)
diff --git a/private/sdcardd.te b/private/sdcardd.te
index 126d643..ac6bb4e 100644
--- a/private/sdcardd.te
+++ b/private/sdcardd.te
@@ -1,3 +1,4 @@
typeattribute sdcardd coredomain;
+typeattribute sdcardd domain_deprecated;
type_transition sdcardd system_data_file:{ dir file } media_rw_data_file;
diff --git a/private/shared_relro.te b/private/shared_relro.te
index 02f7206..8d06294 100644
--- a/private/shared_relro.te
+++ b/private/shared_relro.te
@@ -1,4 +1,5 @@
typeattribute shared_relro coredomain;
+typeattribute shared_relro 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.
diff --git a/private/surfaceflinger.te b/private/surfaceflinger.te
index f04a984..3595ee4 100644
--- a/private/surfaceflinger.te
+++ b/private/surfaceflinger.te
@@ -6,6 +6,7 @@
init_daemon_domain(surfaceflinger)
typeattribute surfaceflinger mlstrustedsubject;
+typeattribute surfaceflinger display_service_server;
read_runtime_log_tags(surfaceflinger)
diff --git a/private/system_server.te b/private/system_server.te
index f391aa5..05e4773 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -86,6 +86,9 @@
allow system_server self:netlink_socket create_socket_perms_no_ioctl;
allow system_server self:netlink_generic_socket create_socket_perms_no_ioctl;
+# libvintf reads the kernel config to verify vendor interface compatibility.
+allow system_server config_gz:file { read open };
+
# Use generic "sockets" where the address family is not known
# to the kernel. The ioctl permission is specifically omitted here, but may
# be added to device specific policy along with the ioctl commands to be
@@ -181,17 +184,21 @@
hal_client_domain(system_server, hal_ir)
hal_client_domain(system_server, hal_light)
hal_client_domain(system_server, hal_memtrack)
+hal_client_domain(system_server, hal_oemlock)
allow system_server hal_omx_hwservice:hwservice_manager find;
allow system_server hidl_token_hwservice:hwservice_manager find;
hal_client_domain(system_server, hal_power)
hal_client_domain(system_server, hal_sensors)
+hal_client_domain(system_server, hal_tetheroffload)
hal_client_domain(system_server, hal_thermal)
hal_client_domain(system_server, hal_tv_cec)
hal_client_domain(system_server, hal_tv_input)
hal_client_domain(system_server, hal_usb)
hal_client_domain(system_server, hal_vibrator)
hal_client_domain(system_server, hal_vr)
+hal_client_domain(system_server, hal_weaver)
hal_client_domain(system_server, hal_wifi)
+hal_client_domain(system_server, hal_wifi_offload)
hal_client_domain(system_server, hal_wifi_supplicant)
binder_call(system_server, mediacodec)
diff --git a/private/ueventd.te b/private/ueventd.te
index 1bd6773..0df587f 100644
--- a/private/ueventd.te
+++ b/private/ueventd.te
@@ -1,3 +1,4 @@
typeattribute ueventd coredomain;
+typeattribute ueventd domain_deprecated;
tmpfs_domain(ueventd)
diff --git a/private/uncrypt.te b/private/uncrypt.te
index e4e9224..fde686b 100644
--- a/private/uncrypt.te
+++ b/private/uncrypt.te
@@ -1,3 +1,4 @@
typeattribute uncrypt coredomain;
+typeattribute uncrypt domain_deprecated;
init_daemon_domain(uncrypt)
diff --git a/private/update_engine.te b/private/update_engine.te
index 5af7db6..f460272 100644
--- a/private/update_engine.te
+++ b/private/update_engine.te
@@ -1,3 +1,4 @@
typeattribute update_engine coredomain;
+typeattribute update_engine domain_deprecated;
init_daemon_domain(update_engine);
diff --git a/private/vold.te b/private/vold.te
index a6d1001..f2416f8 100644
--- a/private/vold.te
+++ b/private/vold.te
@@ -1,4 +1,5 @@
typeattribute vold coredomain;
+typeattribute vold domain_deprecated;
init_daemon_domain(vold)
diff --git a/private/wificond.te b/private/wificond.te
index 5476e33..cc76447 100644
--- a/private/wificond.te
+++ b/private/wificond.te
@@ -1,3 +1,4 @@
typeattribute wificond coredomain;
init_daemon_domain(wificond)
+hal_client_domain(wificond, hal_wifi_offload)
diff --git a/public/attributes b/public/attributes
index c449a08..90740d4 100644
--- a/public/attributes
+++ b/public/attributes
@@ -10,16 +10,6 @@
# 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.
@@ -232,6 +222,9 @@
attribute hal_nfc;
attribute hal_nfc_client;
attribute hal_nfc_server;
+attribute hal_oemlock;
+attribute hal_oemlock_client;
+attribute hal_oemlock_server;
attribute hal_power;
attribute hal_power_client;
attribute hal_power_server;
@@ -241,6 +234,9 @@
attribute hal_telephony;
attribute hal_telephony_client;
attribute hal_telephony_server;
+attribute hal_tetheroffload;
+attribute hal_tetheroffload_client;
+attribute hal_tetheroffload_server;
attribute hal_thermal;
attribute hal_thermal_client;
attribute hal_thermal_server;
@@ -259,12 +255,18 @@
attribute hal_vr;
attribute hal_vr_client;
attribute hal_vr_server;
+attribute hal_weaver;
+attribute hal_weaver_client;
+attribute hal_weaver_server;
attribute hal_wifi;
attribute hal_wifi_client;
attribute hal_wifi_server;
attribute hal_wifi_keystore;
attribute hal_wifi_keystore_client;
attribute hal_wifi_keystore_server;
+attribute hal_wifi_offload;
+attribute hal_wifi_offload_client;
+attribute hal_wifi_offload_server;
attribute hal_wifi_supplicant;
attribute hal_wifi_supplicant_client;
attribute hal_wifi_supplicant_server;
@@ -276,4 +278,5 @@
# from one core domain to another, without having to update the vendor image
# which contains clients of this service.
+attribute display_service_server;
attribute wifi_keystore_service_server;
diff --git a/public/clatd.te b/public/clatd.te
index 8632087..212b76e 100644
--- a/public/clatd.te
+++ b/public/clatd.te
@@ -1,5 +1,5 @@
# 464xlat daemon
-type clatd, domain, domain_deprecated;
+type clatd, domain;
type clatd_exec, exec_type, file_type;
net_domain(clatd)
diff --git a/public/dex2oat.te b/public/dex2oat.te
index cc8111f..47f3bcb 100644
--- a/public/dex2oat.te
+++ b/public/dex2oat.te
@@ -1,5 +1,5 @@
# dex2oat
-type dex2oat, domain, domain_deprecated;
+type dex2oat, domain;
type dex2oat_exec, exec_type, file_type;
r_dir_file(dex2oat, apk_data_file)
diff --git a/public/dhcp.te b/public/dhcp.te
index 22351ed..2b54b7f 100644
--- a/public/dhcp.te
+++ b/public/dhcp.te
@@ -1,4 +1,4 @@
-type dhcp, domain, domain_deprecated;
+type dhcp, domain;
type dhcp_exec, exec_type, file_type;
net_domain(dhcp)
diff --git a/public/display_service_server.te b/public/display_service_server.te
new file mode 100644
index 0000000..c5839fa
--- /dev/null
+++ b/public/display_service_server.te
@@ -0,0 +1 @@
+add_hwservice(display_service_server, fwk_display_hwservice)
diff --git a/public/domain.te b/public/domain.te
index 8f63624..34cbadc 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -489,6 +489,7 @@
neverallow {
domain
userdebug_or_eng(`-domain') # exclude debuggable builds
+ -hal_bootctl
-init
-uncrypt
-update_engine
diff --git a/public/dumpstate.te b/public/dumpstate.te
index 503f359..4f66ffb 100644
--- a/public/dumpstate.te
+++ b/public/dumpstate.te
@@ -1,5 +1,5 @@
# dumpstate
-type dumpstate, domain, domain_deprecated, mlstrustedsubject;
+type dumpstate, domain, mlstrustedsubject;
type dumpstate_exec, exec_type, file_type;
net_domain(dumpstate)
diff --git a/public/fingerprintd.te b/public/fingerprintd.te
index 57cde1d..5dd18a3 100644
--- a/public/fingerprintd.te
+++ b/public/fingerprintd.te
@@ -1,4 +1,4 @@
-type fingerprintd, domain, domain_deprecated;
+type fingerprintd, domain;
type fingerprintd_exec, exec_type, file_type;
binder_use(fingerprintd)
diff --git a/public/fsck.te b/public/fsck.te
index 8f3b17a..b682a87 100644
--- a/public/fsck.te
+++ b/public/fsck.te
@@ -1,5 +1,5 @@
# Any fsck program run by init
-type fsck, domain, domain_deprecated;
+type fsck, domain;
type fsck_exec, exec_type, file_type;
# /dev/__null__ created by init prior to policy load,
diff --git a/public/fsck_untrusted.te b/public/fsck_untrusted.te
index a9dd805..e2aceb8 100644
--- a/public/fsck_untrusted.te
+++ b/public/fsck_untrusted.te
@@ -1,5 +1,5 @@
# Any fsck program run on untrusted block devices
-type fsck_untrusted, domain, domain_deprecated;
+type fsck_untrusted, domain;
# Inherit and use pty created by android_fork_execvp_ext().
allow fsck_untrusted devpts:chr_file { read write ioctl getattr };
diff --git a/public/hal_camera.te b/public/hal_camera.te
index 3c15e85..413a057 100644
--- a/public/hal_camera.te
+++ b/public/hal_camera.te
@@ -32,6 +32,5 @@
# hal_camera should never need network access. Disallow network sockets.
neverallow hal_camera domain:{ tcp_socket udp_socket rawip_socket } *;
-# Only camera HAL may directly access the camera and video hardware
+# Only camera HAL may directly access the camera hardware
neverallow { halserverdomain -hal_camera_server } camera_device:chr_file *;
-neverallow { halserverdomain -coredomain -hal_camera_server } video_device:chr_file *;
diff --git a/public/hal_graphics_composer.te b/public/hal_graphics_composer.te
index 2d8483d..287037c 100644
--- a/public/hal_graphics_composer.te
+++ b/public/hal_graphics_composer.te
@@ -5,6 +5,9 @@
add_hwservice(hal_graphics_composer_server, hal_graphics_composer_hwservice)
allow hal_graphics_composer_client hal_graphics_composer_hwservice:hwservice_manager find;
+# Coordinate with hal_graphics_mapper
+allow hal_graphics_composer_server hal_graphics_mapper_hwservice:hwservice_manager find;
+
# GPU device access
allow hal_graphics_composer gpu_device:chr_file rw_file_perms;
allow hal_graphics_composer ion_device:chr_file r_file_perms;
diff --git a/public/hal_neverallows.te b/public/hal_neverallows.te
index 130a8f6..feadcda 100644
--- a/public/hal_neverallows.te
+++ b/public/hal_neverallows.te
@@ -12,7 +12,6 @@
# using network sockets.
neverallow {
halserverdomain
- -hal_gnss # TODO b/36085168 b/35757613
-hal_wifi_server
-hal_wifi_supplicant_server
-rild
diff --git a/public/hal_oemlock.te b/public/hal_oemlock.te
new file mode 100644
index 0000000..3fb5a18
--- /dev/null
+++ b/public/hal_oemlock.te
@@ -0,0 +1,5 @@
+# HwBinder IPC from client to server
+binder_call(hal_oemlock_client, hal_oemlock_server)
+
+add_hwservice(hal_oemlock_server, hal_oemlock_hwservice)
+allow hal_oemlock_client hal_oemlock_hwservice:hwservice_manager find;
diff --git a/public/hal_tetheroffload.te b/public/hal_tetheroffload.te
new file mode 100644
index 0000000..a4c21fcd
--- /dev/null
+++ b/public/hal_tetheroffload.te
@@ -0,0 +1,3 @@
+## HwBinder IPC from client to server, and callbacks
+binder_call(hal_tetheroffload_client, hal_tetheroffload_server)
+binder_call(hal_tetheroffload_server, hal_tetheroffload_client)
diff --git a/public/hal_weaver.te b/public/hal_weaver.te
new file mode 100644
index 0000000..b80ba29
--- /dev/null
+++ b/public/hal_weaver.te
@@ -0,0 +1,5 @@
+# HwBinder IPC from client to server
+binder_call(hal_weaver_client, hal_weaver_server)
+
+add_hwservice(hal_weaver_server, hal_weaver_hwservice)
+allow hal_weaver_client hal_weaver_hwservice:hwservice_manager find;
diff --git a/public/hal_wifi_offload.te b/public/hal_wifi_offload.te
new file mode 100644
index 0000000..dac5171
--- /dev/null
+++ b/public/hal_wifi_offload.te
@@ -0,0 +1,6 @@
+## HwBinder IPC from client to server, and callbacks
+binder_call(hal_wifi_offload_client, hal_wifi_offload_server)
+binder_call(hal_wifi_offload_server, hal_wifi_offload_client)
+
+r_dir_file(hal_wifi_offload, proc_net)
+r_dir_file(hal_wifi_offload, sysfs_type)
diff --git a/public/hwservice.te b/public/hwservice.te
index 2b1ffcf..65c52a2 100644
--- a/public/hwservice.te
+++ b/public/hwservice.te
@@ -1,4 +1,5 @@
type default_android_hwservice, hwservice_manager_type;
+type fwk_display_hwservice, hwservice_manager_type, coredomain_hwservice;
type fwk_scheduler_hwservice, hwservice_manager_type, coredomain_hwservice;
type fwk_sensor_hwservice, hwservice_manager_type, coredomain_hwservice;
type hal_audio_hwservice, hwservice_manager_type;
@@ -21,6 +22,7 @@
type hal_light_hwservice, hwservice_manager_type;
type hal_memtrack_hwservice, hwservice_manager_type;
type hal_nfc_hwservice, hwservice_manager_type;
+type hal_oemlock_hwservice, hwservice_manager_type;
type hal_omx_hwservice, hwservice_manager_type;
type hal_power_hwservice, hwservice_manager_type;
type hal_renderscript_hwservice, hwservice_manager_type, same_process_hwservice;
@@ -32,6 +34,7 @@
type hal_usb_hwservice, hwservice_manager_type;
type hal_vibrator_hwservice, hwservice_manager_type;
type hal_vr_hwservice, hwservice_manager_type;
+type hal_weaver_hwservice, hwservice_manager_type;
type hal_wifi_hwservice, hwservice_manager_type;
type hal_wifi_supplicant_hwservice, hwservice_manager_type;
type hidl_allocator_hwservice, hwservice_manager_type, coredomain_hwservice;
diff --git a/public/installd.te b/public/installd.te
index 359356a..939a481 100644
--- a/public/installd.te
+++ b/public/installd.te
@@ -1,5 +1,5 @@
# installer daemon
-type installd, domain, domain_deprecated;
+type installd, domain;
type installd_exec, exec_type, file_type;
typeattribute installd mlstrustedsubject;
allow installd self:capability { chown dac_override fowner fsetid setgid setuid sys_admin };
diff --git a/public/keystore.te b/public/keystore.te
index 2c31185..ee5e675 100644
--- a/public/keystore.te
+++ b/public/keystore.te
@@ -1,4 +1,4 @@
-type keystore, domain, domain_deprecated;
+type keystore, domain;
type keystore_exec, exec_type, file_type;
# keystore daemon
diff --git a/public/mediaextractor.te b/public/mediaextractor.te
index e1b460d..94824b7 100644
--- a/public/mediaextractor.te
+++ b/public/mediaextractor.te
@@ -22,6 +22,7 @@
# allow mediaextractor read permissions for file sources
allow mediaextractor media_rw_data_file:file { getattr read };
+allow mediaextractor app_data_file:file { getattr read };
# Read resources from open apk files passed over Binder
allow mediaextractor apk_data_file:file { read getattr };
diff --git a/public/modprobe.te b/public/modprobe.te
index 24a6b3b..3ed320e 100644
--- a/public/modprobe.te
+++ b/public/modprobe.te
@@ -2,9 +2,10 @@
allow modprobe proc_modules:file r_file_perms;
allow modprobe self:capability sys_module;
+allow modprobe kernel:key search;
recovery_only(`
allow modprobe rootfs:system module_load;
allow modprobe rootfs:file r_file_perms;
')
-allow modprobe { system_file vendor_file }:system module_load;
-r_dir_file(modprobe, { system_file vendor_file })
+allow modprobe { system_file }:system module_load;
+r_dir_file(modprobe, { system_file })
diff --git a/public/mtp.te b/public/mtp.te
index 0ca7cea..a776240 100644
--- a/public/mtp.te
+++ b/public/mtp.te
@@ -1,5 +1,5 @@
# vpn tunneling protocol manager
-type mtp, domain, domain_deprecated;
+type mtp, domain;
type mtp_exec, exec_type, file_type;
net_domain(mtp)
diff --git a/public/netd.te b/public/netd.te
index 1694aec..691887f 100644
--- a/public/netd.te
+++ b/public/netd.te
@@ -1,5 +1,5 @@
# network manager
-type netd, domain, domain_deprecated, mlstrustedsubject;
+type netd, domain, mlstrustedsubject;
type netd_exec, exec_type, file_type;
net_domain(netd)
diff --git a/public/perfprofd.te b/public/perfprofd.te
index f0df6a0..bfb8693 100644
--- a/public/perfprofd.te
+++ b/public/perfprofd.te
@@ -4,7 +4,6 @@
userdebug_or_eng(`
- typeattribute perfprofd domain_deprecated;
typeattribute perfprofd coredomain;
typeattribute perfprofd mlstrustedsubject;
diff --git a/public/ppp.te b/public/ppp.te
index 918ef5e..04e17f5 100644
--- a/public/ppp.te
+++ b/public/ppp.te
@@ -1,5 +1,5 @@
# Point to Point Protocol daemon
-type ppp, domain, domain_deprecated;
+type ppp, domain;
type ppp_device, dev_type;
type ppp_exec, exec_type, file_type;
diff --git a/public/radio.te b/public/radio.te
index f5604fd..87329d9 100644
--- a/public/radio.te
+++ b/public/radio.te
@@ -1,5 +1,5 @@
# phone subsystem
-type radio, domain, domain_deprecated, mlstrustedsubject;
+type radio, domain, mlstrustedsubject;
net_domain(radio)
bluetooth_domain(radio)
diff --git a/public/recovery.te b/public/recovery.te
index f0ac97d..f55dc8a 100644
--- a/public/recovery.te
+++ b/public/recovery.te
@@ -2,7 +2,7 @@
# Declare the domain unconditionally so we can always reference it
# in neverallow rules.
-type recovery, domain, domain_deprecated;
+type recovery, domain;
# But the allow rules are only included in the recovery policy.
# Otherwise recovery is only allowed the domain rules.
diff --git a/public/rild.te b/public/rild.te
index e4b0186..14420df 100644
--- a/public/rild.te
+++ b/public/rild.te
@@ -1,5 +1,5 @@
# rild - radio interface layer daemon
-type rild, domain, domain_deprecated;
+type rild, domain;
hal_server_domain(rild, hal_telephony)
net_domain(rild)
diff --git a/public/runas.te b/public/runas.te
index 046165d..cda02ef 100644
--- a/public/runas.te
+++ b/public/runas.te
@@ -1,4 +1,4 @@
-type runas, domain, domain_deprecated, mlstrustedsubject;
+type runas, domain, mlstrustedsubject;
type runas_exec, exec_type, file_type;
allow runas adbd:process sigchld;
diff --git a/public/sdcardd.te b/public/sdcardd.te
index 3cb69be..47a2f80 100644
--- a/public/sdcardd.te
+++ b/public/sdcardd.te
@@ -1,4 +1,4 @@
-type sdcardd, domain, domain_deprecated;
+type sdcardd, domain;
type sdcardd_exec, exec_type, file_type;
allow sdcardd cgroup:dir create_dir_perms;
diff --git a/public/shared_relro.te b/public/shared_relro.te
index 9794b0b..91cf44d 100644
--- a/public/shared_relro.te
+++ b/public/shared_relro.te
@@ -1,5 +1,5 @@
# Process which creates/updates shared RELRO files to be used by other apps.
-type shared_relro, domain, domain_deprecated;
+type shared_relro, domain;
# Grant write access to the shared relro files/directory.
allow shared_relro shared_relro_file:dir rw_dir_perms;
diff --git a/public/te_macros b/public/te_macros
index 80b5696..b1937d8 100644
--- a/public/te_macros
+++ b/public/te_macros
@@ -469,6 +469,9 @@
allow $1 su:fifo_file append;
')
allow $1 anr_data_file:file append;
+allow $1 dumpstate:fd use;
+# TODO: Figure out why write is needed and remove.
+allow $1 dumpstate:fifo_file { append write };
allow $1 tombstoned:unix_stream_socket connectto;
allow $1 tombstoned:fd use;
allow $1 tombstoned_crash_socket:sock_file write;
diff --git a/public/ueventd.te b/public/ueventd.te
index 8ec667e..4c77e11 100644
--- a/public/ueventd.te
+++ b/public/ueventd.te
@@ -1,6 +1,6 @@
# ueventd seclabel is specified in init.rc since
# it lives in the rootfs and has no unique file type.
-type ueventd, domain, domain_deprecated;
+type ueventd, domain;
# Write to /dev/kmsg.
allow ueventd kmsg_device:chr_file rw_file_perms;
diff --git a/public/uncrypt.te b/public/uncrypt.te
index ef1289c..7ae7d39 100644
--- a/public/uncrypt.te
+++ b/public/uncrypt.te
@@ -1,5 +1,5 @@
# uncrypt
-type uncrypt, domain, domain_deprecated, mlstrustedsubject;
+type uncrypt, domain, mlstrustedsubject;
type uncrypt_exec, exec_type, file_type;
allow uncrypt self:capability dac_override;
diff --git a/public/update_engine.te b/public/update_engine.te
index 69ee7c8..b8f0035 100644
--- a/public/update_engine.te
+++ b/public/update_engine.te
@@ -1,5 +1,5 @@
# Domain for update_engine daemon.
-type update_engine, domain, domain_deprecated, update_engine_common;
+type update_engine, domain, update_engine_common;
type update_engine_exec, exec_type, file_type;
net_domain(update_engine);
diff --git a/public/vendor_toolbox.te b/public/vendor_toolbox.te
index 39462f8..eb292ca 100644
--- a/public/vendor_toolbox.te
+++ b/public/vendor_toolbox.te
@@ -7,6 +7,10 @@
# or read, execute the vendor_toolbox file.
full_treble_only(`
# Do not allow non-vendor domains to transition
- # to vendor toolbox
- neverallow coredomain vendor_toolbox_exec:file { entrypoint execute execute_no_trans };
+ # to vendor toolbox except for the whitelisted domains.
+ neverallow {
+ coredomain
+ -init
+ -modprobe
+ } vendor_toolbox_exec:file { entrypoint execute execute_no_trans };
')
diff --git a/public/vold.te b/public/vold.te
index 20181d1..81ee28c 100644
--- a/public/vold.te
+++ b/public/vold.te
@@ -1,5 +1,5 @@
# volume manager
-type vold, domain, domain_deprecated;
+type vold, domain;
type vold_exec, exec_type, file_type;
# Read already opened /cache files.
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..2c70f36
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,21 @@
+cc_library_host_shared {
+ name: "libsepolwrap",
+ srcs: ["sepol_wrap.cpp"],
+ shared_libs: ["libbase", "libsepol"],
+ cflags: ["-Wall", "-Werror",],
+ export_include_dirs: ["include"],
+}
+
+cc_prebuilt_binary {
+ name: "policy.py",
+ srcs: ["policy.py"],
+ host_supported: true,
+ required: ["libsepolwrap"],
+}
+
+cc_prebuilt_binary {
+ name: "treble_sepolicy_tests.py",
+ srcs: ["treble_sepolicy_tests.py"],
+ host_supported: true,
+ required: ["policy.py"],
+}
diff --git a/tests/include/sepol_wrap.h b/tests/include/sepol_wrap.h
new file mode 100644
index 0000000..0683a3b
--- /dev/null
+++ b/tests/include/sepol_wrap.h
@@ -0,0 +1,20 @@
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp);
+bool init_libsepol(const char *policy_path);
+void *load_policy(const char *policy_path);
+void destroy_policy(void *policydbp);
+void *init_avtab(void *policydbp);
+void *init_cond_avtab(void *policydbp);
+void destroy_avtab(void *avtab_iterp);
+int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp);
+void *init_type_iter(void *policydbp, const char *type, bool is_attr);
+void destroy_type_iter(void *type_iterp);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tests/policy.py b/tests/policy.py
new file mode 100644
index 0000000..74a8ef7
--- /dev/null
+++ b/tests/policy.py
@@ -0,0 +1,157 @@
+from ctypes import *
+import re
+import os
+import sys
+
+class TERule:
+ def __init__(self, rule):
+ data = rule.split(',')
+ self.flavor = data[0]
+ self.sctx = data[1]
+ self.tctx = data[2]
+ self.tclass = data[3]
+ self.perms = set((data[4].strip()).split(' '))
+ self.rule = rule
+
+class Policy:
+ __Rules = None
+ __FcDict = None
+ __libsepolwrap = None
+ __policydbP = None
+
+ # Return all file_contexts entries that map to the input Type.
+ def QueryFc(self, Type):
+ if Type in self.__FcDict:
+ return self.__FcDict[Type]
+ else:
+ return None
+
+ # Return all attributes associated with a type if IsAttr=False or
+ # all types associated with an attribute if IsAttr=True
+ def QueryTypeAttribute(self, Type, IsAttr):
+ init_type_iter = self.__libsepolwrap.init_type_iter
+ init_type_iter.restype = c_void_p
+ TypeIterP = init_type_iter(c_void_p(self.__policydbP),
+ create_string_buffer(Type), c_bool(IsAttr))
+ if (TypeIterP == None):
+ sys.exit("Failed to initialize type iterator")
+ buf = create_string_buffer(2048)
+
+ while True:
+ ret = self.__libsepolwrap.get_type(buf, c_int(2048),
+ c_void_p(self.__policydbP), c_void_p(TypeIterP))
+ if ret == 0:
+ yield buf.value
+ continue
+ if ret == 1:
+ break;
+ # We should never get here.
+ sys.exit("Failed to import policy")
+ self.__libsepolwrap.destroy_type_iter(c_void_p(TypeIterP))
+
+ # Return all TERules that match:
+ # (any scontext) or (any tcontext) or (any tclass) or (any perms),
+ # perms.
+ # Any unspecified paramenter will match all.
+ #
+ # Example: QueryTERule(tcontext=["foo", "bar"], perms=["entrypoint"])
+ # Will return any rule with:
+ # (tcontext="foo" or tcontext="bar") and ("entrypoint" in perms)
+ def QueryTERule(self, **kwargs):
+ if self.__Rules is None:
+ self.__InitTERules()
+ for Rule in self.__Rules:
+ # Match source type
+ if "scontext" in kwargs and Rule.sctx not in kwargs['scontext']:
+ continue
+ # Match target type
+ if "tcontext" in kwargs and Rule.tctx not in kwargs['tcontext']:
+ continue
+ # Match target class
+ if "tclass" in kwargs and Rule.tclass not in kwargs['tclass']:
+ continue
+ # Match any perms
+ if "perms" in kwargs and not bool(Rule.perms & set(kwargs['perms'])):
+ continue
+ yield Rule
+
+
+ def __GetTERules(self, policydbP, avtabIterP):
+ if self.__Rules is None:
+ self.__Rules = set()
+ buf = create_string_buffer(2048)
+ ret = 0
+ while True:
+ ret = self.__libsepolwrap.get_allow_rule(buf, c_int(2048),
+ c_void_p(policydbP), c_void_p(avtabIterP))
+ if ret == 0:
+ Rule = TERule(buf.value)
+ self.__Rules.add(Rule)
+ continue
+ if ret == 1:
+ break;
+ # We should never get here.
+ sys.exit("Failed to import policy")
+
+ def __InitTERules(self):
+ init_avtab = self.__libsepolwrap.init_avtab
+ init_avtab.restype = c_void_p
+ avtabIterP = init_avtab(c_void_p(self.__policydbP))
+ if (avtabIterP == None):
+ sys.exit("Failed to initialize avtab")
+ self.__GetTERules(self.__policydbP, avtabIterP)
+ self.__libsepolwrap.destroy_avtab(c_void_p(avtabIterP))
+ init_cond_avtab = self.__libsepolwrap.init_cond_avtab
+ init_cond_avtab.restype = c_void_p
+ avtabIterP = init_cond_avtab(c_void_p(self.__policydbP))
+ if (avtabIterP == None):
+ sys.exit("Failed to initialize conditional avtab")
+ self.__GetTERules(self.__policydbP, avtabIterP)
+ self.__libsepolwrap.destroy_avtab(c_void_p(avtabIterP))
+
+ # load ctypes-ified libsepol wrapper
+ def __InitLibsepolwrap(self, LibPath):
+ if "linux" in sys.platform:
+ self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.so")
+ elif "darwin" in sys.platform:
+ self.__libsepolwrap = CDLL(LibPath + "/libsepolwrap.dylib")
+ else:
+ sys.exit("only Linux and Mac currrently supported")
+
+ # load file_contexts
+ def __InitFC(self, FcPaths):
+ fc = []
+ for path in FcPaths:
+ if not os.path.exists(path):
+ sys.exit("file_contexts file " + path + " does not exist.")
+ fd = open(path, "r")
+ fc += fd.readlines()
+ fd.close()
+ self.__FcDict = {}
+ for i in fc:
+ rec = i.split()
+ try:
+ t = rec[-1].split(":")[2]
+ if t in self.__FcDict:
+ self.__FcDict[t].append(rec[0])
+ else:
+ self.__FcDict[t] = [rec[0]]
+ except:
+ pass
+
+ # load policy
+ def __InitPolicy(self, PolicyPath):
+ load_policy = self.__libsepolwrap.load_policy
+ load_policy.restype = c_void_p
+ self.__policydbP = load_policy(create_string_buffer(PolicyPath))
+ if (self.__policydbP is None):
+ sys.exit("Failed to load policy")
+
+ def __init__(self, PolicyPath, FcPaths, LibPath):
+ self.__InitLibsepolwrap(LibPath)
+ self.__InitFC(FcPaths)
+ self.__InitPolicy(PolicyPath)
+
+ def __del__(self):
+ if self.__policydbP is not None:
+ self.__libsepolwrap.destroy_policy(c_void_p(self.__policydbP))
diff --git a/tests/sepol_wrap.cpp b/tests/sepol_wrap.cpp
new file mode 100644
index 0000000..a12d438
--- /dev/null
+++ b/tests/sepol_wrap.cpp
@@ -0,0 +1,266 @@
+#include <stdio.h>
+#include <string>
+#include <sstream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sepol/policydb/avtab.h>
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/services.h>
+#include <sepol/policydb/util.h>
+#include <sys/types.h>
+#include <fstream>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <sepol_wrap.h>
+
+
+struct type_iter {
+ type_datum *d;
+ ebitmap_node *n;
+ unsigned int length;
+ unsigned int bit;
+};
+
+void *init_type_iter(void *policydbp, const char *type, bool is_attr)
+{
+ policydb_t *db = static_cast<policydb_t *>(policydbp);
+ struct type_iter *out = (struct type_iter *)
+ calloc(1, sizeof(struct type_iter));
+
+ if (!out) {
+ std::cerr << "Failed to allocate type type iterator" << std::endl;
+ return NULL;
+ }
+
+ out->d = static_cast<type_datum *>(hashtab_search(db->p_types.table, type));
+ if (is_attr && out->d->flavor != TYPE_ATTRIB) {
+ std::cerr << "\"" << type << "\" MUST be an attribute in the policy" << std::endl;
+ free(out);
+ return NULL;
+ } else if (!is_attr && out->d->flavor !=TYPE_TYPE) {
+ std::cerr << "\"" << type << "\" MUST be a type in the policy" << std::endl;
+ free(out);
+ return NULL;
+ }
+
+ if (is_attr) {
+ out->bit = ebitmap_start(&db->attr_type_map[out->d->s.value - 1], &out->n);
+ out->length = ebitmap_length(&db->attr_type_map[out->d->s.value - 1]);
+ } else {
+ out->bit = ebitmap_start(&db->type_attr_map[out->d->s.value - 1], &out->n);
+ out->length = ebitmap_length(&db->type_attr_map[out->d->s.value - 1]);
+ }
+
+ return static_cast<void *>(out);
+}
+
+void destroy_type_iter(void *type_iterp)
+{
+ struct type_iter *type_i = static_cast<struct type_iter *>(type_iterp);
+ free(type_i);
+}
+
+/*
+ * print allow rule into *out buffer.
+ *
+ * Returns -1 on error.
+ * Returns 0 on successfully reading an avtab entry.
+ * Returns 1 on complete
+ */
+int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp)
+{
+ size_t len;
+ policydb_t *db = static_cast<policydb_t *>(policydbp);
+ struct type_iter *i = static_cast<struct type_iter *>(type_iterp);
+
+ for (; i->bit < i->length; i->bit = ebitmap_next(&i->n, i->bit)) {
+ if (!ebitmap_node_get_bit(i->n, i->bit)) {
+ continue;
+ }
+ len = snprintf(out, max_size, "%s", db->p_type_val_to_name[i->bit]);
+ if (len >= max_size) {
+ std::cerr << "type name exceeds buffer size." << std::endl;
+ return -1;
+ }
+ i->bit = ebitmap_next(&i->n, i->bit);
+ return 0;
+ }
+
+ return 1;
+}
+
+void *load_policy(const char *policy_path)
+{
+ FILE *fp;
+ policydb_t *db;
+
+ fp = fopen(policy_path, "re");
+ if (!fp) {
+ std::cerr << "Invalid or non-existing policy file: " << policy_path << std::endl;
+ return NULL;
+ }
+
+ db = (policydb_t *) calloc(1, sizeof(policydb_t));
+ if (!db) {
+ std::cerr << "Failed to allocate memory for policy db." << std::endl;
+ fclose(fp);
+ return NULL;
+ }
+
+ sidtab_t sidtab;
+ sepol_set_sidtab(&sidtab);
+ sepol_set_policydb(db);
+
+ struct stat sb;
+ if (fstat(fileno(fp), &sb)) {
+ std::cerr << "Failed to stat the policy file" << std::endl;
+ free(db);
+ fclose(fp);
+ return NULL;
+ }
+
+ auto unmap = [=](void *ptr) { munmap(ptr, sb.st_size); };
+ std::unique_ptr<void, decltype(unmap)> map(
+ mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileno(fp), 0), unmap);
+ if (!map) {
+ std::cerr << "Failed to map the policy file" << std::endl;
+ free(db);
+ fclose(fp);
+ return NULL;
+ }
+
+ struct policy_file pf;
+ policy_file_init(&pf);
+ pf.type = PF_USE_MEMORY;
+ pf.data = static_cast<char *>(map.get());
+ pf.len = sb.st_size;
+ if (policydb_init(db)) {
+ std::cerr << "Failed to initialize policydb" << std::endl;
+ free(db);
+ fclose(fp);
+ return NULL;
+ }
+
+ if (policydb_read(db, &pf, 0)) {
+ std::cerr << "Failed to read binary policy" << std::endl;
+ policydb_destroy(db);
+ free(db);
+ fclose(fp);
+ return NULL;
+ }
+
+ return static_cast<void *>(db);
+}
+
+/* items needed to iterate over the avtab */
+struct avtab_iter {
+ avtab_t avtab;
+ uint32_t i;
+ avtab_ptr_t cur;
+};
+
+/*
+ * print allow rule into *out buffer.
+ *
+ * Returns -1 on error.
+ * Returns 0 on successfully reading an avtab entry.
+ * Returns 1 on complete
+ */
+static int get_avtab_allow_rule(char *out, size_t max_size, policydb_t *db,
+ struct avtab_iter *avtab_i)
+{
+ size_t len;
+
+ for (; avtab_i->i < avtab_i->avtab.nslot; (avtab_i->i)++) {
+ if (avtab_i->cur == NULL) {
+ avtab_i->cur = avtab_i->avtab.htable[avtab_i->i];
+ }
+ for (; avtab_i->cur; avtab_i->cur = (avtab_i->cur)->next) {
+ if (!((avtab_i->cur)->key.specified & AVTAB_ALLOWED)) continue;
+
+ len = snprintf(out, max_size, "allow,%s,%s,%s,%s",
+ db->p_type_val_to_name[(avtab_i->cur)->key.source_type - 1],
+ db->p_type_val_to_name[(avtab_i->cur)->key.target_type - 1],
+ db->p_class_val_to_name[(avtab_i->cur)->key.target_class - 1],
+ sepol_av_to_string(db, (avtab_i->cur)->key.target_class, (avtab_i->cur)->datum.data));
+ avtab_i->cur = (avtab_i->cur)->next;
+ if (!(avtab_i->cur))
+ (avtab_i->i)++;
+ if (len >= max_size) {
+ std::cerr << "Allow rule exceeds buffer size." << std::endl;
+ return -1;
+ }
+ return 0;
+ }
+ avtab_i->cur = NULL;
+ }
+
+ return 1;
+}
+
+int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp)
+{
+ policydb_t *db = static_cast<policydb_t *>(policydbp);
+ struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
+
+ return get_avtab_allow_rule(out, len, db, avtab_i);
+}
+
+/*
+ * <sepol/policydb/expand.h->conditional.h> uses 'bool' as a variable name
+ * inside extern "C" { .. } construct, which clang doesn't like.
+ * So, declare the function we need from expand.h ourselves.
+ */
+extern "C" int expand_avtab(policydb_t *p, avtab_t *a, avtab_t *expa);
+
+static avtab_iter *init_avtab_common(avtab_t *in, policydb_t *p)
+{
+ struct avtab_iter *out = (struct avtab_iter *)
+ calloc(1, sizeof(struct avtab_iter));
+ if (!out) {
+ std::cerr << "Failed to allocate avtab" << std::endl;
+ return NULL;
+ }
+
+ if (avtab_init(&out->avtab)) {
+ std::cerr << "Failed to initialize avtab" << std::endl;
+ free(out);
+ return NULL;
+ }
+
+ if (expand_avtab(p, in, &out->avtab)) {
+ std::cerr << "Failed to expand avtab" << std::endl;
+ free(out);
+ return NULL;
+ }
+ return out;
+}
+
+void *init_avtab(void *policydbp)
+{
+ policydb_t *p = static_cast<policydb_t *>(policydbp);
+ return static_cast<void *>(init_avtab_common(&p->te_avtab, p));
+}
+
+void *init_cond_avtab(void *policydbp)
+{
+ policydb_t *p = static_cast<policydb_t *>(policydbp);
+ return static_cast<void *>(init_avtab_common(&p->te_cond_avtab, p));
+}
+
+void destroy_avtab(void *avtab_iterp)
+{
+ struct avtab_iter *avtab_i = static_cast<struct avtab_iter *>(avtab_iterp);
+ avtab_destroy(&avtab_i->avtab);
+ free(avtab_i);
+}
+
+void destroy_policy(void *policydbp)
+{
+ policydb_t *p = static_cast<policydb_t *>(policydbp);
+ policydb_destroy(p);
+}
diff --git a/tests/treble_sepolicy_tests.py b/tests/treble_sepolicy_tests.py
new file mode 100644
index 0000000..3d6a480
--- /dev/null
+++ b/tests/treble_sepolicy_tests.py
@@ -0,0 +1,274 @@
+from optparse import OptionParser
+from optparse import Option, OptionValueError
+import os
+import policy
+import re
+import sys
+
+DEBUG=False
+
+'''
+Use file_contexts and policy to verify Treble requirements
+are not violated.
+'''
+###
+# Differentiate between domains that are part of the core Android platform and
+# domains introduced by vendors
+coreAppdomain = {
+ 'bluetooth',
+ 'ephemeral_app',
+ 'isolated_app',
+ 'nfc',
+ 'platform_app',
+ 'priv_app',
+ 'radio',
+ 'shared_relro',
+ 'shell',
+ 'system_app',
+ 'untrusted_app',
+ 'untrusted_app_25',
+ 'untrusted_v2_app',
+ }
+coredomainWhitelist = {
+ 'adbd',
+ 'kernel',
+ 'postinstall',
+ 'postinstall_dexopt',
+ 'recovery',
+ 'system_server',
+ }
+coredomainWhitelist |= coreAppdomain
+
+class scontext:
+ def __init__(self):
+ self.fromSystem = False
+ self.fromVendor = False
+ self.coredomain = False
+ self.appdomain = False
+ self.attributes = set()
+ self.entrypoints = []
+ self.entrypointpaths = []
+
+def PrintScontexts():
+ for d in sorted(alldomains.keys()):
+ sctx = alldomains[d]
+ print d
+ print "\tcoredomain="+str(sctx.coredomain)
+ print "\tappdomain="+str(sctx.appdomain)
+ print "\tfromSystem="+str(sctx.fromSystem)
+ print "\tfromVendor="+str(sctx.fromVendor)
+ print "\tattributes="+str(sctx.attributes)
+ print "\tentrypoints="+str(sctx.entrypoints)
+ print "\tentrypointpaths="
+ if sctx.entrypointpaths is not None:
+ for path in sctx.entrypointpaths:
+ print "\t\t"+str(path)
+
+alldomains = {}
+coredomains = set()
+appdomains = set()
+vendordomains = set()
+
+###
+# Check whether the regex will match a file path starting with the provided
+# prefix
+#
+# Compares regex entries in file_contexts with a path prefix. Regex entries
+# are often more specific than this file prefix. For example, the regex could
+# be /system/bin/foo\.sh and the prefix could be /system. This function
+# loops over the regex removing characters from the end until
+# 1) there is a match - return True or 2) run out of characters - return
+# False.
+#
+def MatchPathPrefix(pathregex, prefix):
+ for i in range(len(pathregex), 0, -1):
+ try:
+ pattern = re.compile('^' + pathregex[0:i] + "$")
+ except:
+ continue
+ if pattern.match(prefix):
+ return True
+ return False
+
+def GetAllDomains(pol):
+ global alldomains
+ for result in pol.QueryTypeAttribute("domain", True):
+ alldomains[result] = scontext()
+
+def GetAppDomains():
+ global appdomains
+ global alldomains
+ for d in alldomains:
+ # The application of the "appdomain" attribute is trusted because core
+ # selinux policy contains neverallow rules that enforce that only zygote
+ # and runas spawned processes may transition to processes that have
+ # the appdomain attribute.
+ if "appdomain" in alldomains[d].attributes:
+ alldomains[d].appdomain = True
+ appdomains.add(d)
+
+
+def GetCoreDomains():
+ global alldomains
+ global coredomains
+ for d in alldomains:
+ # TestCoredomainViolators will verify if coredomain was incorrectly
+ # applied.
+ if "coredomain" in alldomains[d].attributes:
+ alldomains[d].coredomain = True
+ coredomains.add(d)
+ # check whether domains are executed off of /system or /vendor
+ if d in coredomainWhitelist:
+ continue
+ # TODO, add checks to prevent app domains from being incorrectly
+ # labeled as coredomain. Apps don't have entrypoints as they're always
+ # dynamically transitioned to by zygote.
+ if d in appdomains:
+ continue
+ if not alldomains[d].entrypointpaths:
+ continue
+ for path in alldomains[d].entrypointpaths:
+ # Processes with entrypoint on /system
+ if ((MatchPathPrefix(path, "/system") and not
+ MatchPathPrefix(path, "/system/vendor")) or
+ MatchPathPrefix(path, "/init") or
+ MatchPathPrefix(path, "/charger")):
+ alldomains[d].fromSystem = True
+ # Processes with entrypoint on /vendor or /system/vendor
+ if (MatchPathPrefix(path, "/vendor") or
+ MatchPathPrefix(path, "/system/vendor")):
+ alldomains[d].fromVendor = True
+
+###
+# Add the entrypoint type and path(s) to each domain.
+#
+def GetDomainEntrypoints(pol):
+ global alldomains
+ for x in pol.QueryTERule(tclass="file", perms=["entrypoint"]):
+ if not x.sctx in alldomains:
+ continue
+ alldomains[x.sctx].entrypoints.append(str(x.tctx))
+ # postinstall_file represents a special case specific to A/B OTAs.
+ # Update_engine mounts a partition and relabels it postinstall_file.
+ # There is no file_contexts entry associated with postinstall_file
+ # so skip the lookup.
+ if x.tctx == "postinstall_file":
+ continue
+ entrypointpath = pol.QueryFc(x.tctx)
+ if not entrypointpath:
+ continue
+ alldomains[x.sctx].entrypointpaths.extend(entrypointpath)
+###
+# Get attributes associated with each domain
+#
+def GetAttributes(pol):
+ global alldomains
+ for domain in alldomains:
+ for result in pol.QueryTypeAttribute(domain, False):
+ alldomains[domain].attributes.add(result)
+
+def setup(pol):
+ GetAllDomains(pol)
+ GetAttributes(pol)
+ GetDomainEntrypoints(pol)
+ GetAppDomains()
+ GetCoreDomains()
+
+#############################################################
+# Tests
+#############################################################
+def TestCoredomainViolations():
+ global alldomains
+ # verify that all domains launched from /system have the coredomain
+ # attribute
+ ret = ""
+ violators = []
+ for d in alldomains:
+ domain = alldomains[d]
+ if domain.fromSystem and "coredomain" not in domain.attributes:
+ violators.append(d);
+ if len(violators) > 0:
+ ret += "The following domain(s) must be associated with the "
+ ret += "\"coredomain\" attribute because they are executed off of "
+ ret += "/system:\n"
+ ret += " ".join(str(x) for x in sorted(violators)) + "\n"
+
+ # verify that all domains launched form /vendor do not have the coredomain
+ # attribute
+ violators = []
+ for d in alldomains:
+ domain = alldomains[d]
+ if domain.fromVendor and "coredomain" in domain.attributes:
+ violators.append(d)
+ if len(violators) > 0:
+ ret += "The following domains must not be associated with the "
+ ret += "\"coredomain\" attribute because they are executed off of "
+ ret += "/vendor or /system/vendor:\n"
+ ret += " ".join(str(x) for x in sorted(violators)) + "\n"
+
+ return ret
+
+###
+# extend OptionParser to allow the same option flag to be used multiple times.
+# This is used to allow multiple file_contexts files and tests to be
+# specified.
+#
+class MultipleOption(Option):
+ ACTIONS = Option.ACTIONS + ("extend",)
+ STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
+ TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
+ ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
+
+ def take_action(self, action, dest, opt, value, values, parser):
+ if action == "extend":
+ values.ensure_value(dest, []).append(value)
+ else:
+ Option.take_action(self, action, dest, opt, value, values, parser)
+
+Tests = ["CoredomainViolators"]
+
+if __name__ == '__main__':
+ usage = "sepolicy-trebletests -f nonplat_file_contexts -f "
+ usage +="plat_file_contexts -p policy [--test test] [--help]"
+ parser = OptionParser(option_class=MultipleOption, usage=usage)
+ parser.add_option("-f", "--file_contexts", dest="file_contexts",
+ metavar="FILE", action="extend", type="string")
+ parser.add_option("-p", "--policy", dest="policy", metavar="FILE")
+ parser.add_option("-l", "--library-path", dest="libpath", metavar="FILE")
+ parser.add_option("-t", "--test", dest="test", action="extend",
+ help="Test options include "+str(Tests))
+
+ (options, args) = parser.parse_args()
+
+ if not options.libpath:
+ sys.exit("Must specify path to host libraries\n" + parser.usage)
+ if not os.path.exists(options.libpath):
+ sys.exit("Error: library-path " + options.libpath + " does not exist\n"
+ + parser.usage)
+
+ if not options.policy:
+ sys.exit("Must specify monolithic policy file\n" + parser.usage)
+ if not os.path.exists(options.policy):
+ sys.exit("Error: policy file " + options.policy + " does not exist\n"
+ + parser.usage)
+
+ if not options.file_contexts:
+ sys.exit("Error: Must specify file_contexts file(s)\n" + parser.usage)
+ for f in options.file_contexts:
+ if not os.path.exists(f):
+ sys.exit("Error: File_contexts file " + f + " does not exist\n" +
+ parser.usage)
+
+ pol = policy.Policy(options.policy, options.file_contexts, options.libpath)
+ setup(pol)
+
+ if DEBUG:
+ PrintScontexts()
+
+ results = ""
+ # If an individual test is not specified, run all tests.
+ if options.test is None or "CoredomainViolations" in options.tests:
+ results += TestCoredomainViolations()
+
+ if len(results) > 0:
+ sys.exit(results)
diff --git a/vendor/file_contexts b/vendor/file_contexts
index ac5d1d0..e7a371a 100644
--- a/vendor/file_contexts
+++ b/vendor/file_contexts
@@ -30,6 +30,7 @@
/(vendor|system/vendor)/bin/hw/android\.hardware\.usb@1\.0-service u:object_r:hal_usb_default_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.vibrator@1\.0-service u:object_r:hal_vibrator_default_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.vr@1\.0-service u:object_r:hal_vr_default_exec:s0
+/(vendor|system/vendor)/bin/hw/android\.hardware\.wifi\.offload@1\.0-service u:object_r:hal_wifi_offload_default_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.wifi@1\.0-service u:object_r:hal_wifi_default_exec:s0
/(vendor|system/vendor)/bin/hw/wpa_supplicant u:object_r:hal_wifi_supplicant_default_exec:s0
/(vendor|system/vendor)/bin/hostapd u:object_r:hostapd_exec:s0
diff --git a/vendor/hal_wifi_offload_default.te b/vendor/hal_wifi_offload_default.te
new file mode 100644
index 0000000..44bd306
--- /dev/null
+++ b/vendor/hal_wifi_offload_default.te
@@ -0,0 +1,5 @@
+type hal_wifi_offload_default, domain;
+hal_server_domain(hal_wifi_offload_default, hal_wifi_offload)
+
+type hal_wifi_offload_default_exec, exec_type, vendor_file_type, file_type;
+init_daemon_domain(hal_wifi_offload_default)
diff --git a/vendor/tee.te b/vendor/tee.te
index f7c2cb5..348d715 100644
--- a/vendor/tee.te
+++ b/vendor/tee.te
@@ -1,8 +1,6 @@
##
# trusted execution environment (tee) daemon
#
-typeattribute tee domain_deprecated;
-
type tee_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(tee)
diff --git a/vendor/vendor_modprobe.te b/vendor/vendor_modprobe.te
new file mode 100644
index 0000000..b8a1edb
--- /dev/null
+++ b/vendor/vendor_modprobe.te
@@ -0,0 +1,11 @@
+type vendor_modprobe, domain;
+
+# For the use of /vendor/bin/modprobe from vendor init.rc fragments
+domain_trans(init, vendor_toolbox_exec, vendor_modprobe)
+
+allow vendor_modprobe proc_modules:file r_file_perms;
+allow vendor_modprobe self:capability sys_module;
+allow vendor_modprobe kernel:key search;
+
+allow vendor_modprobe { vendor_file }:system module_load;
+r_dir_file(vendor_modprobe, { vendor_file })