SELinux in Android Background Android uses Security-Enhanced Linux (SELinux) to enforce mandatory access control over all processes, even processes running with root/superuser privileges. The Android security model is based in part on the concept of application sandboxes. Each application runs in its own sandbox. Android 4.3 and later uses SELinux to define the boundaries of the Android application sandbox. SELinux operates on the principle of default denial: Anything not explicitly allowed is denied. SELinux can operate in two global modes: 1. Permissive mode , in which permission denials are logged but not enforced. 2. Enforcing mode , in which permissions denials are both logged and enforced. Android includes SELinux in enforcing mode and a corresponding security policy that works by default across AOSP. In enforcing mode, disallowed actions are prevented and all attempted violations are logged by the kernel to dmesg and logcat. Concepts Discretionary Access Control (DAC) It is a control system used in Linux, windows and many other places. DAC is a means of restricting access to a particular resource based on the identity of the subjects and/or groups to which it belongs. This is subject to unintended privilege escalation. For example, in a Linux system, a use can only operate on a particular resource if the user or user group owns it. If the user is login as root/superuser, the root owns everything in the system which means this user can operate on all the things. Also, when root runs a executable such as a browser, in DAC, the privilege of the root is escalated to the browser. Mandatory Access Control (MAC) It is a type of access control let the operating system constrains the ability of a subject to access or perform some sort of operation on a particular resource or a target. Whenever a subject attempts to access an resource, an authorization rule enforced by the operating system kernel examines these security attributes and decides whether the access can take place. For example, when a browser wants to write a cookie into filesystem. The kernel will first check if there is a rule (policy) allows the browser to perform the create/write operation to the filesystem. Summary Both access control systems are running simultaneously as both systems are target different subjects. In DAC, the subject is user and in MAC is process or thread. Therefore, under SELinux(MAC) even a user login as root, the root user still cannot perform an action unless this action is explicitly allowed. Security Context(Label) and policies The security context is also known as a 'security label' or just label. SELinux depends upon labels to match actions and policies. Labels determine what is allowed. Sockets, files, and processes all have labels in SELinux. SELinux decisions are based on labels assigned to these objects and the policy defining how they may interact. A label takes the form: user:role:type:mls_level , where the type is the primary component of the access decisions, which may be modified by the other sections components that make up the label. (NOTE: The term type is used for a label assigned to an object (such as files, sockets ...), although sometimes the term is also used for the label of a process , i.e. a domain. This is because in a SELinux context, the third field is called the SELinux type.) For label in filesystem, it can be viewed by using ls -Z . 1 u:object_r:system_data_file:s0 data 2 u:object_r:proc:s0 proc 3 u:object_r:system_file:s0 system 4 u:object_r:vendor_file:s0 vendor Process label can be viewed by using ps -Z 1 u:r:zygote:s0 root 3494 1 1557416 93776 root 3563 3539 14664 1856 root 3712 1 220672 14176 a8a975ac S zygote 2 u:r:nxserver:s0 b61e224c S nxserver 3 u:r:primeserver:s0 a8acb24c S primeserver The policy rules come in the form: <AV type> domains types:classes permissions ;, where: AV type - type of access vector. allow - Specifies access allowed between two types dontaudit - Specifies access denial messages to not record auditallow - Specified access allowed events to record neverallow - Specifies access permissions that may never be granted by any allow rule Domain - A label for the process or set of processes. Also called a domain type as it is just a type for a process. Type - A label for the object (e.g. file, socket) or set of objects. Class - The kind of object (e.g. file, socket) being accessed. It is defined in system/sepolicy/private/security_classes Permission - The operation (e.g. read, write) being performed. If there are more than one operation, if can be grouped with {} . It is defined in system/sepolicy/private/access_vectors For example: 1 allow primeserver vfat:file {create read write open getattr unlink }; This policy says that primeserver domain is allowed to do create/read/write ... operations on files labeled as vfat . In addition to individually listing domains or types in a rule, one can also refer to a set of domains or types via an attribute . An attribute is simply a name for a set of domains or types. Each domain or type can be associated with any number of attributes. When a rule is written that specifies an attribute name, that name is automatically expanded to the list of domains or types associated with the attribute. For example: 1 allow domain null_device:chr_file { open }; This rule allows a process with any domain associated with the domain attribute to take the action described by the permission open on an object of class chr_file (character device file) that has the target_type label of null_device . \ (More example about domain can be found in ..system/sepolicy/public/domain.te) Neverallow SELinux neverallow rules prohibit behavior that should never occur. It is intended to help policy writer to avoid error during build phase which can help speed up developement. If an allow rule violates an neverallow rule, the checkpolicy compiler will generate a compile error. For example: 1 # Limit access to /vendor/app 2 neverallow { 3 coredomain 4 -appdomain 5 -dex2oat 6 -idmap 7 -init 8 -installd 9 -postinstall_dexopt 10 11 -system_server } vendor_app_file:dir { open read getattr search }; This never allow rule prevents process (domain) which has coredomain attribute to open, read, getattr, search a dir with vendor_app_file type. However, -<domain name> means exclude. So the appdomain, dex2oat... does not limit by this rule. Implementing SELinux In general, you should not modify the system/sepolicy files directly. Instead, add or edit policy files in the /device/broadcom/common/treble/sepolicy directory. For more spcific policy for different broadcom platoform /device/broadcom/<platform>/sepolicy directory should be used. <platform> can be elfin or cypress or others. Key files Policy files Files that end with *.te are SELinux policy source files, which define domains and their labels. We need to create new policy files in /device/broadcom/common/treble/sepolicy , but you should try to update existing files where possible. Context files Context files are where you specify labels for your objects. file_contexts assigns labels to files and is used by various userspace components. As you create new policies, create or update this file to assign new labels to files. example: /(vendor|system/vendor)/bin/primeserver u:object_r:primeserver_exec:s0 genfs_contexts assigns labels to filesystems, such as proc or vfat that do not support extended attributes. This configuration is loaded as part of the kernel policy but changes may not take effect for in-core inodes, requiring a reboot or unmounting and re-mounting the filesystem to fully apply the change. Specific labels may also be assigned to specific mounts, such as vfat using the context=mount option. example: genfscon cramfs / u:object_r:readonlyfs:s0 property_contexts assigns labels to Android system properties to control what processes can set them. This configuration is read by the init process during startup. example: ro.nexus. u:object_r:nexus_prop:s0 service_contexts / vndservice_contexts assigns labels to Android binder services to control what processes can add (register) and find (lookup) a binder reference for the service. This configuration is read by the servicemanager process during startup. example: com.broadcom.tunerhal.TunerInterface u:object_r:tv_input_service:s0 seapp_contexts assigns labels to app processes and /data/data directories. This configuration is read by the zygote process on each app launch and by installd during startup. example: user=_app seinfo=primestb domain=primestb_app type=app_data_file mac_permissions.xml assigns a seinfo tag to apps based on their signature and optionally their package name. The seinfo tag can then be used as a key in the seapp_contexts file to assign a specific label to all apps with that seinfo tag. This configuration is read by system_server during startup. example: 1 <?xml version="1.0" encoding="utf-8"?> 2 <policy> 3 4 5 <signer signature="@BCMSTB" > <seinfo value="bcmstb" /> </signer> 6 7 8 9 10 <signer signature="@PRIMESTB" > <seinfo value="primestb" /> </signer> </policy> Customization To get started with SELinux: 1. Enable SELinux in the kernel: CONFIG_SECURITY_SELINUX=y (This is already enabled by Broadcom released Android). 2. Change the kernel_cmdline parameter so that: LOCAL_DEVICE_KERNEL_CMDLINE += androidboot.selinux=permissive This can be moidfied in /device/broadcom/<platform>/<platform>.mk, where platform can be elfin or cypress or others. NOTE: This is only for development of policy for the device. After you have an initial bootstrap policy, remove this parameter so the box is enforcing or it will fail CTS. 3. Boot up the system in permissive and see what denials are encountered on boot: 1 ## Before using adb, please do source build/envsetup.sh 2 ## to set up correct path 3 4 adb pull /sys/fs/selinux/policy 5 adb logcat -b all -d | audit2allow -p policy This will copy the binary policy file from the booted box and use audit2allow tool to generate policies based on SELinux violation message. The following is typical output of audit2allow. 1 #============= nxserver ============== 2 allow nxserver wifi_prop:file { getattr open read }; 3 4 #============= primeserver ============== 5 allow primeserver vndbinder_service:service_manager add; 6 7 #============= primestb_app ============== 8 allow primestb_app vndbinder_service:service_manager find; 9 10 #============= priv_app ============== 11 allow priv_app ffs_prop:property_service set; 12 allow priv_app init:unix_stream_socket connectto; 13 allow priv_app property_socket:sock_file write; 14 15 #============= untrusted_app ============== 16 allow untrusted_app sysfs_zram:dir search; 17 allow untrusted_app sysfs_zram:file { getattr open read }; 18 IMPORTANT: Adding the policies generate from audit2allow does NOT guarantee these policies pass the SELinux validation. They may create neverallow error during the build. 4. Identify devices, and other new files that need labeling. 5. Use existing or new labels for your objects. Look at the *_contexts files mentioned above. 6. Identify domains/processes that should have their own security domains. Macro SELinux is based upon the M4 computer language and therefore supports a variety of macros to save time. System level marco can be found at system/sepolicy/public/te_macros and device level macro is located at device/broadcom/common/sepolicy/treble/te_macros . Example The following is the partial policy file for our primeserver device/broadcom/common/sepolicy/treble/primeserver.te 1 ## the type declaration, the primeserver daemon inherits from the base security policy 2 ## (domain), and have vndservice_manager_type attribute as it will use vndservice. (This also ## means primeserver is a domain type) 3 type primeserver, domain, mlstrustedsubject, vndservice_manager_type; 4 5 ## the type declaration, for primeserver executable to have exec_type, vendor_file_type, 6 ## file_type attribute (primeserver_exec is defined in file_contexts as it is a file type.) 7 type primeserver_exec, exec_type, vendor_file_type, file_type; 8 9 ## the policy states primeserver is spawned from init and is allowed to communicate with it. 10 init_daemon_domain(primeserver); ## it is a macro 11 12 ## the policy allows primeserver to use common network functionalities from the net domain 13 ## such as reading and writing TCP packets, communicating over sockets, and conducting DNS 14 ## requests. 15 net_domain(primeserver); 16 17 ## Allow primeserver to access nexus data files 18 nexus_verified_client(primeserver); 19 set_prop(primeserver, nexus_prop); 20 21 ## Allow primeserver domain to use Binder IPC. 22 vndbinder_use(primeserver); 23 binder_call(primeserver, primestb_app); 24 25 allow primeserver self:capability { sys_nice kill dac_override }; 26 allow primeserver self:unix_stream_socket connectto; 27 allow primeserver nexus_prop:property_service set; 28 29 type_transition primeserver system_data_file:file prime_db_file "mwds.sl3"; 30 allow primeserver prime_db_file:file { open create read write setattr getattr unlink lock }; 31 allow primeserver system_data_file:dir { create read open write add_name remove_name }; 32 33 allow primeserver vfat:dir {search add_name write remove_name }; 34 allow primeserver vfat:file {create read write open getattr unlink }; 35 36 allow primeserver vndbinder_service:service_manager add; Reference Security-Enhanced Linux in Android