This page describes how Android handles the policy compatibility issues with platform over-the-air (OTA) updates, where new platform SELinux settings might differ from old vendor SELinux settings.
Object ownership and labeling
Ownership must be clearly defined for each object to keep platform and vendor policy separate. For example, if the vendor policy labels /dev/foo and the platform policy labels /dev/foo in a subsequent OTA, there is undefined behavior like an unexpected denial, or more critically, a boot failure. For SELinux, this manifests as a labeling collision. The device node can have only a single label that resolves to whichever label is applied last. As a result:
- Processes that need access to the unsuccessfully applied label loses access to the resource.
- Processes that gain access to the file might break because the wrong device node was created.
Collisions between platform and vendor labels can occur for any object that has an SELinux label, including properties, services, processes, files, and sockets. To avoid these issues, clearly define ownership of these objects.
Type/attribute namespacing
In addition to label collisions, SELinux type and attribute names can also collide. SELinux doesn't allow multiple declarations of the same types and attributes. A policy with duplicate declarations fails to compile. To avoid type and attribute name collisions, all vendor declarations are highly recommended to start with the vendor_ prefix. For example, vendors should use type vendor_foo, domain; instead of type foo, domain;.
File ownership
Preventing collisions for files is challenging because platform and vendor policy both commonly provide labels for all filesystems. Unlike type naming, namespacing of files isn't practical since many of them are created by the kernel. To prevent these collisions, follow the naming guidance for filesystems in this section. For Android 8.0, these are recommendations without technical enforcement. In the future, these recommendations will be enforced by the Vendor Test Suite (VTS).
System (/system)
Only the system image must provide labels for /system components through file_contexts, service_contexts, etc. If labels for /system components are added in the vendor policy, a framework-only OTA update might not be possible.
Vendor (/vendor)
The AOSP SELinux policy already labels parts of the vendor partition the platform interacts with, which enables writing SELinux rules for platform processes to be able to talk or access parts of the vendor partition. Examples:
| /vendor path | Platform-provided label | Platform processes depending on the label |
|---|---|---|
/vendor(/.*)? | vendor_file | All HAL clients in framework, ueventd, etc. |
/vendor/framework(/.*)? | vendor_framework_file | dex2oat, appdomain, etc. |
/vendor/app(/.*)? | vendor_app_file | dex2oat, installd, idmap, etc. |
/vendor/overlay(/.*) | vendor_overlay_file | system_server, zygote, idmap, etc. |
As a result, specific rules must be followed (enforced through neverallows) when labelling additional files in the vendor partition:
vendor_filemust be the default label for all files in thevendorpartition. The platform policy requires this to access passthrough HAL implementations.- All new
exec_typesadded in thevendorpartition through the vendor policy must havevendor_file_typeattribute. This is enforced through neverallows. - To avoid conflicts with future platform/framework updates, avoid labelling files other than
exec_typesin thevendorpartition. - All library dependencies for AOSP-identified same process HALs must be labelled as
same_process_hal_file.
Procfs (/proc)
Files in /proc may be labeled using only the genfscon label. In Android 7.0, both the platform and vendor policy used genfscon to label files in procfs.
Recommendation: Only platform policy labels /proc. If vendor processes need access to files in /proc that are currently labeled with the default label (proc), the vendor policy shouldn't explicitly label them and should instead use the generic proc type to add rules for vendor domains. This allows the platform updates to accommodate future kernel interfaces exposed through procfs and label them explicitly as needed.
Debugfs (/sys/kernel/debug)
Debugfs can be labeled in both file_contexts and genfscon. In Android 7.0 to Android 10, both platform and vendor label debugfs.
In Android 11, debugfs can't be accessed or mounted on production devices. Device manufacturers should remove debugfs.
Tracefs (/sys/kernel/debug/tracing)
Tracefs can be labeled in both file_contexts and genfscon. In Android 7.0, only the platform labels tracefs.
Recommendation: Only platform may label tracefs.
Sysfs (/sys)
Files in /sys may be labeled using both file_contexts and genfscon. In Android 7.0, both the platform and the vendor use genfscon to label files in sysfs.
Recommendation: The platform may label sysfs nodes that aren't device-specific. Otherwise, only vendor may label files.
tmpfs (/dev)
Files in /dev may be labeled in file_contexts. In Android 7.0, both the platform and the vendor label files here.
Recommendation: Vendor may label only files in /dev/vendor (for example, /dev/vendor/foo, /dev/vendor/socket/bar).
Rootfs (/)
Files in / may be labeled in file_contexts. In Android 7.0, both platform and vendor label files here.
Recommendation: Only system may label files in /.
Data (/data)
Data is labeled through a combination of file_contexts and seapp_contexts.
Recommendation: Disallow vendor labeling outside /data/vendor. Only platform may label other parts of /data.
Genfs labels version
Starting with vendor API level 202504, newer SELinux labels assigned with genfscon in system/sepolicy/compat/plat_sepolicy_genfs_ver.cil are optional for older vendor partitions. This allows older vendor partitions to keep their existing SEPolicy implementation. This is controlled by the Makefile variable BOARD_GENFS_LABELS_VERSION which is stored in /vendor/etc/selinux/genfs_labels_version.txt.
Example:
- In vendor API level 202404, the
/sys/class/udcnode is labeledsysfsby default. - Starting from vendor API level 202504,
/sys/class/udcis labeledsysfs_udc.
However, /sys/class/udc might be in use by vendor partitions using API level 202404, either with the default sysfs label or a vendor-specific label. Unconditionally labeling /sys/class/udc as sysfs_udc could break compatibility with these vendor partitions. By checking BOARD_GENFS_LABELS_VERSION, the platform keeps using the previous labels and permissions for the older vendor partitions.
BOARD_GENFS_LABELS_VERSION can be greater than or equal to vendor API level. For instance, vendor partitions using API level 202404 can set BOARD_GENFS_LABELS_VERSION to 202504 to adopt new labels introduced in 202504. See the list of 202504-specific genfs labels.
When labeling genfscon nodes, the platform must consider older vendor partitions and implement fallback mechanisms for compatibility when needed. The platform can use platform-only libraries to query the genfs labels version.
- On native, use
libgenfslabelsversion. Seegenfslabelsversion.hfor the header file oflibgenfslabelsversion. - On Java, use
android.os.SELinux.getGenfsLabelsVersion().
Platform-public policy
The platform SELinux policy is divided into private and public. The platform-public policy consists of types and attributes that are always available for a vendor API level, acting as an API between platform and vendor. This policy is exposed to vendor policy writers to enable vendors to build vendor policy files, which when combined with the platform-private policy, results in a fully functional policy for a device. The platform-public policy is defined in system/sepolicy/public.
For example, a type vendor_init, representing the init process in the context of vendor, is defined under system/sepolicy/public/vendor_init.te:
type vendor_init, domain;
Vendors can refer to the type vendor_init to write custom policy rules:
# Allow vendor_init to set vendor_audio_prop in vendor's init scripts set_prop(vendor_init, vendor_audio_prop)Compatibility attributes
SELinux policy is an interaction between source and target types for specific object classes and permissions. Every object (for example, processes, files) affected by SELinux policy can have only one type, but that type might have multiple attributes.
The policy is written mostly in terms of existing types. Here, both vendor_init and debugfs are types:
allow vendor_init debugfs:dir { mounton };
This works because the policy was written with knowledge of all types. However, if the vendor policy and platform policy use specific types, and the label of a specific object changes in only one of those policies, the other might contain policy that gained or lost access previously relied upon. For example, suppose that the platform policy labels sysfs nodes as sysfs:
/sys(/.*)? u:object_r:sysfs:s0
The vendor policy grants access to /sys/usb, labeled as sysfs:
allow vendor_init sysfs:chr_file rw_file_perms;
If the platform policy is changed to label /sys/usb as sysfs_usb, the vendor policy remains the same, but vendor_init loses access to /sys/usb due to the lack of policy for the new sysfs_usb type:
/sys/usb u:object_r:sysfs_usb:s0
To solve this issue, Android introduces a concept of versioned attributes. At compile time, the build system automatically translates platform public types used in the vendor policy into these versioned attributes. This translation is enabled by mapping files that associate a versioned attribute with one or more public types from the platform.
For example, suppose that /sys/usb is labeled as sysfs in 202504 platform policy, and 202504 vendor policy grants vendor_init access to /sys/usb. In this case:
- The vendor policy writes a rule
allow vendor_init sysfs:chr_file rw_file_perms;, because/sys/usbis labeled assysfsin 202504 platform policy. When the build system compiles vendor policy, it automatically translates the rule intoallow vendor_init_202504 sysfs_202504:chr_file rw_file_perms;. The attributesvendor_init_202504andsysfs_202504correspond to the typesvendor_initandsysfs, which are the types defined by the platform. - The build system generates an identity mapping file
/system/etc/selinux/mapping/202504.cil. As both thesystemandvendorpartitions use the same202504version, the mapping file contains identity mappings fromtype_202504totype. For example,vendor_init_202504is mapped tovendor_init, andsysfs_202504is mapped tosysfs:(typeattributeset sysfs_202504 (sysfs)) (typeattributeset vendor_init_202504 (vendor_init)) ...
When the version is bumped from 202504 to 202604, a new mapping file for 202504 vendor partitions is created under system/sepolicy/private/compat/202504/202504.cil, which is installed to /system/etc/selinux/mapping/202504.cil for the 202604 or newer system partitions. Initially, this mapping file contains identity mappings, as previously described. If a new label sysfs_usb for /sys/usb is added to the 202604 platform policy, the mapping file is updated to map sysfs_202504 to sysfs_usb:
(typeattributeset sysfs_202504 (sysfs sysfs_usb)) (typeattributeset vendor_init_202504 (vendor_init)) ...
This update allows the converted vendor policy rule allow vendor_init_202504 sysfs_202504:chr_file rw_file_perms; to automatically grant vendor_init access to the new sysfs_usb type.
To maintain compatibility with older vendor partitions, whenever a new public type is added, that type must be mapped to at least one of versioned attributes in the mapping file system/sepolicy/private/compat/ver/ver.cil, or be listed under system/sepolicy/private/compat/ver/ver.ignore.cil to state that there is no matching type in the previous vendor versions.
The combination of the platform policy, the vendor policy, and the mapping file allows the system to update without updating the vendor policy. Also the conversion into the versioned attributes happens automatically, so the vendor policy doesn't need to take care of the versioning, keeping using the public types as is.
system_ext public and product public policy
Starting in Android 11, the system_ext and the product partitions are allowed to export their designated public types to the vendor partition. Like the platform public policy, the vendor policy uses types and rules automatically translated into the versioned attributes, for example, from type into type_ver, where ver is the vendor API level of the vendor partition.
When the system_ext and the product partitions are based on the same platform version ver, the build system generates base mapping files to system_ext/etc/selinux/mapping/ver.cil and product/etc/selinux/mapping/ver.cil, which contain identity mappings from type to type_ver. The vendor policy can access type with the versioned attribute type_ver.
In case that only the system_ext and the product partitions are updated, say ver to ver+1 (or later), while the vendor partition stays at ver, the vendor policy might lose access to the types of the system_ext and the product partitions. To prevent breakage, the system_ext and the product partitions should provide mapping files from concrete types into type_ver attributes. Each partner is responsible for maintaining the mapping files, if they support ver vendor partition with ver+1 (or later) system_ext and product partitions.
To install mapping files to the system_ext and the product partitions, device implementers, or vendors are expected to:
- Copy the generated base mapping files from ver
system_extandproductpartitions to their source tree. - Amend the mapping files as needed.
- Install the mapping files to ver+1 (or later)
system_extandproductpartitions.
For example, suppose that the 202504 system_ext partition has one public type named foo_type. Then system_ext/etc/selinux/mapping/202504.cil in the 202504 system_ext partition looks like this:
(typeattributeset foo_type_202504 (foo_type)) (expandtypeattribute foo_type_202504 true) (typeattribute foo_type_202504)
If bar_type is added to the 202604 system_ext, and if bar_type should be mapped to foo_type for the 202504 vendor partition, 202504.cil can be updated from (typeattributeset foo_type_202504 (foo_type)) to (typeattributeset foo_type_202504 (foo_type bar_type)) and then installed to the 202604 system_ext partition. The 202504 vendor partition can continue accessing to the 202604 system_ext's foo_type and bar_type.
Attribute changes for Android 9
Devices upgrading to Android 9 can use the following attributes, but devices launching with Android 9 must not.
Violator attributes
Android 9 includes these domain-related attributes:
data_between_core_and_vendor_violators. Attribute for all domains that violate the requirement of not sharing files by path betweenvendorandcoredomains. Platform and vendor processes shouldn't use on-disk files to communicate (unstable ABI). Recommendation:- Vendor code should use
/data/vendor. - System shouldn't use
/data/vendor.
- Vendor code should use
system_executes_vendor_violators. Attribute for all system domains (exceptinitandshell domains) that violate the requirement of not executing vendor binaries. Execution of vendor binaries has unstable API. Platform shouldn't execute vendor binaries directly. Recommendation:- Such platform dependencies on vendor binaries must be behind HIDL HALs.
OR
coredomainsthat need access to vendor binaries should be moved to thevendorpartition and thus, stop beingcoredomain.
- Such platform dependencies on vendor binaries must be behind HIDL HALs.
Untrusted attributes
Untrusted apps that host arbitrary code shouldn't have access to HwBinder services, except those considered sufficiently safe for access from such apps (see safe services below). The two main reasons for this are:
- HwBinder servers don't perform client authentication because HIDL currently doesn't expose caller UID information. Even if HIDL did expose such data, many HwBinder services either operate at a level below that of apps (such as, HALs) or must not rely on app identity for authorization. Thus, to be safe, the default assumption is that every HwBinder service treats all its clients as equally authorized to perform operations offered by the service.
- HAL servers (a subset of HwBinder services) contain code with higher incidence rate of security issues than
system/corecomponents and have access to the lower layers of the stack (all the way down to hardware) thus increasing opportunities for bypassing the Android security model.
Safe services
Safe services include:
same_process_hwservice. These services (by definition) run in the process of the client and thus have the same access as the client domain in which the process runs.coredomain_hwservice. These services don't pose risks associated with reason #2.hal_configstore_ISurfaceFlingerConfigs. This service is specifically designed for use by any domain.hal_graphics_allocator_hwservice. These operations are also offered bysurfaceflingerBinder service, which apps are permitted to access.hal_omx_hwservice. This is a HwBinder version of themediacodecBinder service, which apps are permitted to access.hal_codec2_hwservice. This is a newer version ofhal_omx_hwservice.
Useable attributes
All hwservices not considered safe have the attribute untrusted_app_visible_hwservice. The corresponding HAL servers have the attribute untrusted_app_visible_halserver. Devices launching with Android 9 MUST NOT use either untrusted attribute.
Recommendation:
- Untrusted apps should instead talk to a system service that talks to the vendor HIDL HAL. For example, apps can talk to
binderservicedomain, thenmediaserver(which is abinderservicedomain) in turn talks to thehal_graphics_allocator.OR
- Apps that need direct access to
vendorHALs should have their own vendor-defined sepolicy domain.
File attribute tests
Android 9 includes build time tests that ensure all files in specific locations have the appropriate attributes (such as, all files in sysfs have the required sysfs_type attribute).
SELinux contexts labeling
To support the distinction between platform and vendor sepolicy, the system builds SELinux context files differently to keep them separate.
File contexts
Android 8.0 introduced the following changes for file_contexts:
- To avoid additional compilation overhead on device during boot,
file_contextscease to exist in the binary form. Instead, they are readable, regular expression text file such as{property, service}_contexts(as they were pre-7.0). - The
file_contextsare split between two files:plat_file_contexts- Android platform
file_contextthat has no device-specific labels, except for labeling parts of/vendorpartition that must be labeled precisely to ensure proper functioning of the sepolicy files. - Must reside in
systempartition at/system/etc/selinux/plat_file_contextson device and be loaded byinitat the start along with the vendorfile_context.
- Android platform
vendor_file_contexts- Device-specific
file_contextbuilt by combiningfile_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mkfiles. - Must be installed at
/vendor/etc/selinux/vendor_file_contextsinvendorpartition and be loaded byinitat the start along with the platformfile_context.
- Device-specific
Property contexts
In Android 8.0, the property_contexts is split between two files:
plat_property_contexts- Android platform
property_contextthat has no device-specific labels. - Must reside in
systempartition at/system/etc/selinux/plat_property_contextsand be loaded byinitat the start along with the vendorproperty_contexts.
- Android platform
vendor_property_contexts- Device-specific
property_contextbuilt by combiningproperty_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin device'sBoardconfig.mkfiles. - Must reside in
vendorpartition at/vendor/etc/selinux/vendor_property_contextsand be loaded byinitat the start along with the platformproperty_context
- Device-specific
Service contexts
In Android 8.0, the service_contexts is split between the following files:
plat_service_contexts- Android platform-specific
service_contextfor theservicemanager. Theservice_contexthas no device-specific labels. - Must reside in
systempartition at/system/etc/selinux/plat_service_contextsand be loaded byservicemanagerat the start along with the vendorservice_contexts.
- Android platform-specific
vendor_service_contexts- Device-specific
service_contextbuilt by combiningservice_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mkfiles. - Must reside in
vendorpartition at/vendor/etc/selinux/vendor_service_contextsand be loaded byservicemanagerat the start along with the platformservice_contexts. - Although
servicemanagerlooks for this file at boot time, for a fully compliantTREBLEdevice, thevendor_service_contextsMUST NOT exist. This is because all interaction betweenvendorandsystemprocesses MUST go throughhwservicemanager/hwbinder.
- Device-specific
plat_hwservice_contexts- Android platform
hwservice_contextforhwservicemanagerthat has no device-specific labels. - Must reside in
systempartition at/system/etc/selinux/plat_hwservice_contextsand be loaded byhwservicemanagerat the start along with thevendor_hwservice_contexts.
- Android platform
vendor_hwservice_contexts- Device-specific
hwservice_contextbuilt by combininghwservice_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mkfiles. - Must reside in
vendorpartition at/vendor/etc/selinux/vendor_hwservice_contextsand be loaded byhwservicemanagerat the start along with theplat_service_contexts.
- Device-specific
vndservice_contexts- Device-specific
service_contextfor thevndservicemanagerbuilt by combiningvndservice_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mk. - This file must reside in
vendorpartition at/vendor/etc/selinux/vndservice_contextsand be loaded byvndservicemanagerat the start.
- Device-specific
Seapp contexts
In Android 8.0, the seapp_contexts is split between two files:
plat_seapp_contexts- Android platform
seapp_contextthat has no device-specific changes. - Must reside in
systempartition at/system/etc/selinux/plat_seapp_contexts.
- Android platform
vendor_seapp_contexts- Device-specific extension to platform
seapp_contextbuilt by combiningseapp_contextsfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mkfiles. - Must reside in
vendorpartition at/vendor/etc/selinux/vendor_seapp_contexts.
- Device-specific extension to platform
MAC permissions
In Android 8.0, the mac_permissions.xml is split between two files:
- Platform
mac_permissions.xml- Android platform
mac_permissions.xmlthat has no device-specific changes. - Must reside in
systempartition at/system/etc/selinux/.
- Android platform
- Non-Platform
mac_permissions.xml- Device-specific extension to platform
mac_permissions.xmlbuilt frommac_permissions.xmlfound in the directories pointed to byBOARD_SEPOLICY_DIRSin the device'sBoardconfig.mkfiles. - Must reside in
vendorpartition at/vendor/etc/selinux/.
- Device-specific extension to platform