Security when it comes to Android has always been a hotly debated topic in the industry. As OEMs try and adapt Android to new devices,security (or the lack of it) is a big concern to them. This is especially true for OEMs using Android to develop Business IP phones, medical devicesand other such devices that have a greater need for security than consumer-grade home entertainment devices. HSC works with many such OEMs and helps then not just customize Android for their purposes, but to also apply and enforce the appropriate security policies for their industry verticals. In the recent past, SE Android and SE Linux have played an important part in HSC’s security implementations for OEMs. The following is a technology primer on what SELinux and SE Android are, and how they can help in fortifying Android-based devices.
SELinux is an implementation of Mandatory Access Control for the Linux operating system. It provides an access control framework where access to operating system resources by users/processes is controlled based on a predefined security policy. The security policy is centrally defined and managed by a system admin, enforced at the Linux kernel level.
Linux uses a discretionary access control (DAC) system to control access to operating system resources. DAC controls how a process interacts with another process and how a process interacts with system resources (files, devices etc.). In DAC systems, a user assigns access permissions to resources owned by them. For example, every file in Linux has read, write and execute permissions – these permissions may be modified by the owner of the file. Processes started by a user have all the permissions of that user. In this type of access control system, if a process is compromised that process can perform all the tasks at the user’s access level. So an exploited “root” process can cause significant damage.
On the other hand, a Mandatory Access Control (MAC) system works on the principle of least privilege. As per the principle of least privileges, a process should only have access to resources that are necessary for its operations and not have access to any other resource. For example, a TCP server should be able to create TCP sockets and accept connection. However it should not be allowed to create NETLINK sockets. With this kind of access control, even when a process is compromised, damage done by it will be restricted because MAC will allow it to only have privileges required to perform its job. Red Hat Magazine describes some of the exploits that have been stopped by Mandatory Access Control in SELinux
This section describes some of the important terms that are used in SELinux:
Object – system resources like files, directories, socket, network interface, etc. are referred as objects.
Subject – a subject is an entity that causes an action to be taken on object. A subject may be a person, a process or a device.
Security Server – a security server is the entity in Linux kernel that takes the decision if an action on an object by a subject is allowed, per security policy.
Access Vector Cache – access vector cache (AVC) improves the system performance by caching the security decisions taken by the security server.
Object Manager – the object manager manages the actions on the objects. Whenever a subject requests actions on an object, object manager queries the security server to check if that action is allowed. Access decisions taken by the security server are enforced by the object manager.
Type Identifier – SELinux associates a type identifier with every subject and object. The type identifier is used to enforce policy rules. SELinux type identifiers are variable length strings that are defined in the security policy. A type identifier associated with a subject is called domain and a type identifier associated with an object is called object type.
SELinux User – SELinux users’ names are not same as Linux users’ names. Linux user names are associated with a person using Linux, whereas SELinux user names are associated with a group or class of users related to security policies at the SELinux level. Every Linux user name has an associated SELinux user name. A single SELinux user name may be assigned to more than one Linux user name – for example all standard Linux users may be assigned user_u SELinux user name and administrators may be assigned admin_u. This is a very useful property because this way, SELinux can apply much more granular security policies and not be restricted to linux uid/gid level security permissions.
SELinux Role – in SELinux each user is associated with one or more SELinux roles, and the SELinux role is again associated with one or more domains. This structure is used to enforce role base access (RBAC).
Security Context – the SELinux security server uses a security context to decide if an access is allowed. SELinux Security context is a variable length string consisting of SELinux user, role, type identifier and optional MCS/MLS1 range.
Security context is also called “security label” or “label.” For access decision regarding a subject, all components of the security context are used, for access decision regarding an object-only role, the type and range fields are used.
Security Policy – a SELinux policy is a set of rules that categorizes processes into various domains, and partitions system resources into object categories. Policy defines whether an object is accessible from a domain or not. It also determines if interaction between two domains is permitted or not. Types allowed for entry into a domain are also defined in policy. Anything which is not explicitly permitted in policy is denied by the security server.
SELinux MAC is implemented as a security module that uses the Linux Security Module (LSM) framework.
The Linux Security Modules provide a general purpose framework for access control. LSM mediates the access to kernel objects such as i-nodes, open file, network interfaces, etc.
Whenever a user space process attempts to access a kernel object, control goes through a Linux system call mechanism, and just before the kernel attempts to access the internal object, an LSM hook is invoked to find out if access to kernel object should be allowed.
Linux Security Module (LSM) Hook Architecture
LSM provides a variety of hooks to mediate access to kernel objects. The following are some of LSM hooks for kernel objects:
Task Hooks – task hooks cover the full life cycle of a task and are used to check a task’s eligibility to create a task, wait for a task, signal a task or kill a task.
Program Loading Hooks – program loading hooks provide access checks during a new program load (execve).
File System Hooks – file system hooks provide access control checks during file system mount, unmount, file create, delete, link, rename, unlink, fnctl, ioctl, etc.
IPC Hooks – IPC hooks control access to Linux shared memory, semaphores, message queues.
Module Hooks – module hooks provide access control during kernel module load and unload.
Socket Hooks – socket hooks perform access checks for socket operations like socket create, bind, connect, listen, and sendmsg.
In summary, the Linux kernel has LSM hooks at every point where a resource access needs to be mediated. The LSM interface is implemented as a structure of callback methods, and a security module is responsible for implementing these callbacks. The SELinux security server registers itself with LSM as a security module and implements the callbacks invoked by the LSM.
LSM Hooks
An LSM hook consults the security server to check if access to an object is allowed. Then, using the security context of subject, security context of object and object class, the security server consults the security policy and decides if access should be allowed or not. Decisions taken by the security server are cached in the access vector cache to speed up future access decisions for the same object.
Android devices are increasingly being used for access to enterprise applications and banking services. This has resulted in a need for improved security in the Android operating system, and further, there is a need for increased isolation between enterprise and non-enterprise apps in order to prevent enterprise data leaks by malicious apps. It is also essential to prevent privilege escalation by apps to maintain the integrity of apps and data. SEAndroid can help in achieving all these objectives.
The Security Mechanism Android Already Has
Android already has kernel-level application sandboxing. This sandboxing works on Linux user-based protection. Android assigns a unique user ID for each application, and the applications are then executed in separate processes with the assigned user ID. This isolates the application processes from each other and prevents one application from accessing private data of another.
Android has its own user-based permission model. In this model, an application is only able to access the services for which a user has explicitly granted permissions; using DAC to restrict access to system resources. Only privileged apps are allowed to access system resources directly, and other apps can access these resources through the privileged app.
Android maintains the kernel, Android framework, and system apps on a separate system partition. This partition is mounted read-only to prevent any malicious app from tampering with binaries which are important for the operation of the system.
Uploading malicious applications to Google Play is easy, since there is no code inspection/testing done by Google before making an application available to users. Privilege escalation attacks have been used by malicious apps to trigger unauthorized downloads, sending SMS to premium numbers. “GingerBreak” exploits have been used on Android Gingerbread to obtain root access on device. All too easy.
Android has most of the problems typical of DAC-based systems, where an unintentional access permission granted by a user or application might be heavily exploited by malicious apps.
Some of the known Android exploits have been fixed, others have not. Find a full list here.
SEAndroid, which builds on top of SELinux, helps in confining privileged system daemons in case they are compromised, and limits the damage caused by them. It helps in creating a stronger Application Sandbox too, on top of existing DAC-based mechanisms. SEAndroid strengthens the data isolation between apps by controlling IPC between apps and between applications and system services.
SEAndroid brings all the features of SELinux to Android and makes the security infrastructure much more robust. The Android kernel is slightly different from a standard Linux kernel (Additional Android-specific components have been added), but the Android user space is completely different from standard Linux distributions. So simply enabling SELinux on Android is not sufficient to completely protect it from malicious apps; you must employ SEAndroid.
The following subsections describe the features implemented by SEAndroid in order to take care of Android specific components and issues.
The Android kernel has some components that are not present in the standard Linux kernel. These components include Binder, ashmem, logger, and out of memory killer. Binder forms the basis of the inter component communication framework in Android and is heavily used by applications and Android system processes. Since Binder is a new component, new LSM hooks were defined and added to the Binder driver. So, SEAndroid provides implementations of these LSM hooks for Binder. Through these LSM hooks, SEAndroid controls which applications can communicate with each other, and performs audit control operations on Binder.
SELinux has instrumented the Android Framework code; inserting various hooks for enforcement of SEAndroid security policies. Some of the Android user space components that have been modified for SEAndroid include init, Zygote, Bionic, installd and Dalvik. All of these components utilize services of “libselinux” which enables user space process to interact with kernel MAC and enforce security policies.
Init
The init process of Android is different from standard Linux distributions. Android init interprets init.rc commands on its own, instead of relying on a shell interpreter. Because of this, the Android init process is extended to support various SEAndroid commands that can be added to init.rc. These commands include functions to set security labels and commands to set SEAndroid mode. Android init has been modified to load the security policy early during the boot process, and has also been modified to enforce security policy upon access of system “properties.”
Dalvik/Zygote
In Android, applications are created by the Zygote process. Zygote gets the command from “system_server” over a socket, and then invokes a function in Dalvik to spawn a new process for applications. Dalvik creates new processes for applications and sets appropriate DAC credentials. SEAndroid has modified Dalvik to set the security context for application so that the applications are labeled differently from Zygote/Dalvik. Zygote has also been modified to set the security label of the socket interface which is used to receive commands for creating new applications. This socket interface is restricted so that only system_server can instruct Zygote to spawn a new process.
Bionic
Android does not use glibc. Instead, it has its own implementation of C library, called Bionic. Bionic has been extended to provide support to set and get the extended attributes from file systems. Extended attributes are used to store security labels for files.
Package Manager
In SEAndroid, Package Manager has been modified to consult the Android-specific policy file “mac_permissions.xml” and decide if the permissions requested by the application can actually be granted to it; application installation is aborted if permissions cannot be granted. More detail on this is provided in the Application Installation section below.
installd
“installd” daemon on Android creates the application directory at the time of the application’s installation. “installd” in SEAndroid is modified to refer to “mac_permission.xml” and “seapps_context” policy files to determine the security context for the application attempting to be installed. Based on the security context for the application, installd labels the application data directory appropriately for future access.
The following section describes the operations performed by SEAndroid starting from Android build through to Android application execution.
Android Build
The Android tool “make_ext4fs” is used to create Android images (system.img, userdata.img etc) from compiled binaries. This tool is modified for SEAndroid to set initial security labels of files in “system” and “userdata” partition. “make_ext4fs” consults SEAndroid policy “file_contexts” to create initial security labels. “file_contexts” is also included in recovery image so that appropriate security labels are applied after system update.
Android Boot
Android init is modified to load the security policies. The security context of “init” is explicitly set from “init.rc.” SEAndroid has defined separate domains for all the system services, so system processes started by init are automatically transitioned to their own domain, as per their security labels and transition rules in the security policy.
Application Installation
SEAndroid has introduced a new concept of Install-time MAC. This approach provides a centralized mechanism used to control the maximum permissions that can be granted to an application. In Android, normally a user decides if he or she is willing to provide the permissions requested by application, and the application is only installed if the user is willing to provide all the permissions. However, with SEAndroid, ”Install-time” MAC adds another layer where a policy is consulted to check if the requested permissions can be assigned to an application, even if the user is willing to provide those permissions. The application is not installed if the application-requested permission cannot be granted per the security policy. This mechanism can be used in enterprise-level devices to better control the permissions assigned to applications.
The install-time MAC policy is specified in “mac_permissions.xml.” Based on the security certificate and package name of the application, “mac_permissions.xml” provides a “seinfo” string for the application. At the time of the application’s installation, Android “Package Manager” consults “mac_permissions.xml” to get the “seinfo” string for application and checks whether the requested permissions can be assigned to the application. Following is the format of “mac_permissions.xml”:
After the install-time MAC checks, the application is installed by the Package Manager per the standard Android procedure. After installation, Package Manger instructs “installd” to create “data” directory for the application. SEAndroid has modified “installd” to use “seinfo” for the application from “mac_permissions.xml” and information from “seapp_contexts” to determine the security label for the application data directory. So “installd” can create the data directory and label it as per the “type” information from “seapp_contexts”. The following is a subset of “seapp_context” file:
Application Execution
As mentioned earlier, Zygote on Android creates each and every application process. At the time of spawning of an Application process, Zygote consults the “seapp_contexts” file to get the domain name for the application process. “seapp_contexts” provides domain for application process based on “seinfo”, “package name”, “user name” of the application.
On top of bringing in the SELinux facility of the Mandatory Access Control, SEAndroid has added the concept of Middleware MAC (MMAC). Middle MAC, applies mandatory access control functions on IPC and Android permissions. Some of the concepts of the MMAC have already been introduced previously; the following section will summarize those concepts.
Install-Time MAC
Install-time MAC assigns a “seinfo” value to an application based on the package name of the application, and the certificate with which the application was signed. “seinfo” for the application, along with the information in “seapp_contexts,” is used to decide on the security context for the application.
Intent Firewall
Based on the security policy, the Intent Firewall allows Android intents to be blocked from delivery to certain applications. This can be used to restrict untrusted applications from getting information about system-specific events, which are generally broadcasted as intents. Intent Firewall is work in progress, but obsoletes the earlier “Intent MAC” of SEAndroid.
Enterprise Ops
Enterprise Ops in built on top of Android AppOps which was introduced in Android 4.3. Enterprise Ops provides support to control runtime operations by Applications. “Enterprise Ops” groups the applications based on “seinfo” and on “eops.xml.” It decides which operations should be blocked for applications.
SEAndroid policy files use the same syntax as SELinux policy files and are available in the external/sepolicy directory in the Android source tree. Policy files are compiled as “sepolicy” binaries using policy compiler “checkpolicy.” Policy file “sepolicy,” “file_contexts,” and “seapp_contexts” are copied on Android device in “/.” “mac_permissions.xml” is copied to /system/etc/security.
Android allows device vendors to add to or override AOSP definitions. Therefore, a device vendor may configure BOARD_SEPOLICY_UNION and/orBOARD_SEPOLICY_REPLACE variables in BoardConfig.mk to add to or replace AOSP policies as needed. Directories that need to be searched for vendor-specific policies may be defined using BOARD_SEPOLICY_DIRS in BoardConfig.mk.
Starting with Android 4.4, SEAndroid is in “enforcing” mode. However, as of October 2014, only 4 domains were confined, while the rest were set in “permissive” mode. Currently, on AOSP master all of the domains except for “kernel,” “init,” and “init_shell” are in the confined domain. Even process in the “unconfined” domain cannot perform all the operations as “unconfined” domain process are not allowed to execute files outside “/system” directory.
AOSP does not include most of the MMAC mechanisms, including install-time MAC. However, “mac_permissions.xml” is being used to assign “seinfo” to applications based on their signature.
(Do you find this article interesting? You may want to check out our Embedded Android pages to read more about what we do in this space.)
External References