OpenSource For You

What A Native Developer Should About Android Security

-

First version of the Android was built over the Linux 2.6 kernel and is customised to embedded (smartphone or tablet) needs. This article provides a basic overview of the Android security architectu­re and mentions some important changes that may have an impact while porting your native code to Android.

Android applicatio­ns are written in Java. However, the Android framework for executing applicatio­ns, which is written in Java, does not take the traditiona­l JsMLJRE approach. Instead, the Java code is compiled into byte-code (as in a pure JsM environmen­t), which is then FRPSLOHG LnWR DnRWKHU AnGURLG-VSHFLfiF IRUPDW NnRZn DV WKH Dalvik Euecutable (DEu) format. This is run in an AndroidVSH­FLfiF YLUWXDO PDFKLnH, NnRZn DV WKH 'DOYLN VM, ZKLFK LV the heart of Android—and the biggest diversion from the pure Java-JsM approach. The Dalvik sM is highly optimised, ERWK Ln VLzH DnG HxHFXWLRn HIfiFLHnFy. 7KH GLIIHUHnW DSSURDFK is because of three primary factors: Size: A . dex file is composed of several . class files; this gives an opportunit­y for duplicate data or code to be merged and shared among multiple . class files, which results in a smaller DEu file than possible with multiple . class files. RXn-WLPH HIficLHncy: The Dalvik sM is highly optimised to execute DEu code—a major factor in the market's considerat­ions of usable operating systems. We will later look at how this is achieved with ‘zygotes’. An HxWra OayHr RI sHcXrLWy: DEu code is like the next level of abstractio­n over Java byte-code. The Dalvik sM and the Androidise­d Linux kernel constitute the Android framework for applicatio­ns, providing full separation between various applicatio­ns— every applicatio­n has its own unique instance of the Dalvik sM. This constitute­s a very secure design. This means that for every applicatio­n, Android starts a new instance of Dalvik. At first, this design may appear inefficien­t. However, a very important concept known as Zygote is primarily meant to address this problem. Zygote, which is always running in the background, is responsibl­e for speeding up Dalvik instance creation as it has a pre- initialise­d footprint of Dalvik core components always ready in memory. Whenever a new instance of Dalvik needs to be created, Zygote speeds it up by using the pre- initialise­d core.

Android end-user applicatio­ns and exposed libraries are written in Java. The applicatio­n developer selects suitable Java classes that expose the required functional­ity or service.

The Native Developmen­t Kit (NDK)

kative code is written in C. So how can native code be integrated in the Android framework, which is Java dominant? Android has a solution for this—kative Developmen­t (kD). All code written in C (or in other words, all code that can directly run on Linux, outside Dalvik) is called ‘native code’. You compile your native code through the kDK provided by Android, and generate a Linux shared library (not DEu format). This shared library can be used in Java applicatio­ns through the Java kative Interface (JkI) mechanism. It does not run in the Dalvik sM, of course, but directly on the Linux kernel.

The Android security framework

From the developer’s perspectiv­e, Android provides two levels of security to applicatio­ns. Before discussing the details, let’s look at how Android applicatio­ns are shipped and installed on the device.

An Android applicatio­n package is a file with the extension . apk. When a user installs such a file, the Android Package Manager (PM) identifies all the native libraries, along with the other components in the package, and puts these libraries in some package-specific location. Also, this applicatio­n is assigned a unique rID (Linux user ID) and dID (group ID), based on the developer who signed the applicatio­n package. From then onwards, this applicatio­n is identified by the Linux kernel as a unique user—a one-app-one-user philosophy. Thus, all the separation provided to one user from another is now applicable to the Android applicatio­n! Also, permission­s to the location where all applicatio­n data (including native libraries) resides, are as per the assigned rIDLdID.

kow let's come back to the security framework.

Applicatio­n sand-boxing

In Android, this term is used to describe the encapsulat­ion provided to an applicatio­n, with the help of Linux userlevel (unique rIDLdID) security. Each applicatio­n runs in its own sandbox, and the Linux kernel maintains that separation, making every applicatio­n’s code and data accessible to that applicatio­n only. Since this sand-boxing is directly by the kernel, it is very secure.

However, there is an exception to this rule: applicatio­n developers can choose to share some data or native libraries between multiple applicatio­ns. The restrictio­n is that such applicatio­ns should be created and signed by the same developer. In this case, more than one applicatio­n (owned by the same vendor or developer) is assigned the same rIDLdID by the Android package manager. This means that the default applicatio­n sand-boxing can be ‘broken’ by the developers, making everything shared among their applicatio­ns.

Let’s look at how this model affects native code. Let us suppose an applicatio­n is assigned a user ID <X>, and the applicatio­n data storage location is <PATe>. kow, only <PATe> has the desired Linux permission­s for the user ID <X>. So, if native code running as a part of this applicatio­n tries to access anything at some other location, the Linux kernel will ensure that this access is denied!

Android permission framework

At the top level, which has the Android (Java) APIs, Android also has another security layer. Android defines a large set of security types (also known as capabiliti­es), which are necessary for an applicatio­n to exhibit in order to use a specific service from the Android runtime. For example, a permission with the name ‘ INTERNET’ is necessary if the applicatio­n wants access to network-

related resources. If an applicatio­n tries to use a service or resource for which it has no permission, then the service or resource is denied. The particular permission or capability is declared by the applicatio­n developer, in the applicatio­n’s Manifest file. This level of security is over and above applicatio­n sand-boxing. The important point here is that the Android security framework works evenly for Java code and native code, even though the native code is running outside the Dalvik sM.

/HW’V ORRN DW Dn HxDPSOH RI KRZ WKLV PRGHO LnflXHnFHV native code. When native code makes any calls to the Linux API ‘socket’ , it needs to have the Android permission ‘ INTERNET’. Similarly, if native code tries to write to the SD card, it should have a permission known as ‘ tRITE_ EXTERNAL_STORAGE’, and so the list goes on.

The Android filesystem hierarchy

7UDGLWLRnD­O 81,; GLVWULEXWL­RnV IROORZ D fiOHVyVWHP VWDnGDUG known as the Filesystem Hierarchy Standard (FHS). However, Android does not follow this or any other existing VWDnGDUG, DV IDU DV fiOH VyVWHP KLHUDUFKy LV FRnFHUnHG. VDULRXV AnGURLG-VSHFLfiF fiOH VyVWHPV DUH PRXnWHG Ey WKH kernel at start-up, at not-very-standard mount points. So, native code should avoid making any assumption­s about the DYDLODELOL­Wy RI D VSHFLfiF PRXnW SRLnW. (YHn LI D SDUWLFXODU mount point (or path like /dev, /tmp etc.) exists on the Android device, we will still not be sure if this is used in the same way it is used in Linux.

As mentioned earlier, Android provides applicatio­n sandboxing at the kernel level, which is implicitly applicable to WKH fiOH VyVWHP DV ZHOO. )RU HxDPSOH, RnOy WKDW SDUW RI WKH fiOH system is accessible to the applicatio­n that has appropriat­e permission­s, as determined by the applicatio­n developer. However, there exists a concept of 'rooting' an Android device. This mechanism allows the user to escalate to ‘root’ user privileges. Once this is done, the user can access or PRGLIy DnyWKLnJ Rn WKH fiOH VyVWHP. 7KH UHDVRn IRU WKLV LV WKDW the root user is not subject to any constraint­s or restrictio­ns, even at the kernel level—in line with traditiona­l Linux.

Here are some points to consider: 1. Although Android provides an applicatio­n separation mechanism, the developer has an option to override this behaviour. You, as a developer, can decide whether your applicatio­n needs to use this feature. 2. Syss IPC is not supported in the Android C run-time library because of security considerat­ions; so native-code locking primitives that depend on Syss IPC, if any, need to be changed to use an alternativ­e mechanism. 3. Android never stops a (Linux) process, unless the system is extremely low on resources. So, you should optimise the system to minimise memory consumptio­n. 4. Android has tweaked the Linux kernel’s timer

mechanism (along with other features not directly related here) in order to cater for the sleepLsusp­endL wake-up functional­ity of the device. If your native code uses any such mechanism, then make sure you check with the latest Android documentat­ion. 5. Since any access to protected resources or services is guarded by the applicatio­n permission framework, all access in native code needs to be analysed, and the UHTXLUHG SHUPLVVLRn­V VKRXOG EH LGHnWLfiHG. :KDWHYHU permission­s the native code may need should be published for developers, so that they can include these permission­s Ln WKHLU DSSOLFDWLR­n’V MDnLIHVW fiOH. S. kative code should not rely on any code or mechanism that needs root access, as this won’t be available on standard Android. kative code should rely only on the permission­s governed by Android’s applicatio­n permission framework—which can be specified in the applicatio­n Manifest file. T. Any hard-coded paths, like / tmp, which is in itself a bad practice, need to be removed, because such a path may not be available on the Android device, as discussed earlier. Yet, such code is still written, so you should scan your code to be sure! U. Android is designed for the smartphone and tablet market. These devices need to have a very reliable user-response mechanism. If an applicatio­n does not UHVSRnG ZLWKLn D VSHFLfiHG WLPH SHULRG, LW’V SRVVLEOH WKDW the user is unable to switch to another applicatio­n— which is annoying! In Android, this has been taken care of very well. If an applicatio­n does not respond ZLWKLn D VSHFLfiHG SHULRG RI WLPH (WKH GHIDXOW LV 10 VHFRnGV—,’P nRW VXUH LI WKLV LV FRnfiJXUDE­OH RU nRW) WKHn Android assumes that there is something wrong with the applicatio­n, and prompts the user with a message like, “ASSOLcaWLR­n sR-anG-sR nRW rHsSRnGLng, GR yRX wanW WR sWRS LW IRrcLEOy?”. So, it’s very important that native code does not wait for too long, like in locks, etc. As mentioned at the start, this is not a complete descriptio­n of the Android security model. However, I believe this should give readers enough insight into the Android security framework for one to understand how it works, especially for native code developers.

 ??  ??
 ??  ??

Newspapers in English

Newspapers from India