• Aucun résultat trouvé

Although Android’s foundation, the Linux kernel, is fairly well documented and understood, there are some notable differences between the vanilla Linux kernel and that which is used by Android. This section explains some of those changes, especially those which are pertinent to Android security.

The Android Fork

Early on, Google created an Android-centric fork of the Linux kernel, as many modifi cations and additions weren’t compatible with the Linux kernel mainline tree. Overall, this includes approximately 250 patches, ranging from fi le system support and networking tweaks to process and memory management facili-ties. According to one kernel engineer, most of these patches “represent[ed] a limitation that the Android developers found in the Linux kernel.” In March 2012, the Linux kernel maintainers merged the Android-specifi c kernel modi-fi cations into the mainline tree. Table 2-3 highlights some of the additions/

changes to the mainline kernel. We discuss several of these in more detail later in this section.

Table 2-3: Android’s major changes to Linux kernel KERNEL CHANGE DESCRIPTION

Binder IPC mechanism with additional features such as security validation of callers/callees; used by numerous system and framework services

ashmem Anonymous Shared Memory; fi le-based shared memory allocator;

uses Binder IPC to allow processes to identify memory region fi le descriptors

pmem Process Memory Allocator; used for managing large, contiguous regions of shared memory

logger System-wide logging facility

RAM_CONSOLE Stores kernel log messages in RAM for viewing after a kernel panic

“oom” modifi cations “Out of memory”-killer kills processes as memory runs low; in Android fork, OOM kills processes sooner than vanilla kernel, as memory is being depleted

wakelocks Power management feature to keep a device from entering low-power state, and staying responsive

Alarm Timers Kernel interface for AlarmManager, to instruct kernel to schedule “waking up”

Paranoid Networking Restricts certain networking operations and features to specifi c group IDs

timed output / gpio Allows user-space programs to change and restore GPIO registers after a period of time

yaff s2 Support for the yaff s2 fl ash fi le system

Binder

Perhaps one of the most important additions to Android’s Linux kernel was a driver known as Binder. Binder is an IPC mechanism based on a modifi ed version of OpenBinder, originally developed by Be, Inc., and later Palm, Inc. Android’s Binder is relatively small (approximately 4,000 lines of source code across two fi les), but is pivotal to much of Android’s functionality.

In a nutshell, the Binder kernel driver facilitates the overall Binder archi-tecture. The Binder—as an architecture—operates in a client-server model. It allows a process to invoke methods in “remote” processes synchronously. The Binder architecture abstracts away underlying details, making such method calls seem as though they were local function calls. Figure 2-3 shows Binder’s communication fl ow.

Process A Proxy

Binder Driver Process B with Threads

Figure 2-3: Binder communication

Binder also uses process ID (PID) and UID information as a means of identifying the calling process, allowing the callee to make decisions about access control. This typically occurs through calls to methods like Binder .getCallingUid and Binder.getCallingPid, or through higher-level checks such as checkCallingPermission.

An example of this in practice would be the ACCESS_SURFACE_FLINGER permis-sion. This permission is typically granted only to the graphics system user, and allows access to the Binder IPC interface of the Surface Flinger graphics service.

Furthermore, the caller’s group membership—and subsequent bearing of the required permission—is checked through a series of calls to the aforementioned functions, as illustrated by the following code snippet:

const int pid = ipc->getCallingPid();

const int uid = ipc->getCallingUid();

if ((uid != AID_GRAPHICS) &&

!PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {

ALOGE("Permission Denial: "

"can't read framebuffer pid=%d, uid=%d", pid, uid);

return PERMISSION_DENIED;

}

At a higher level, exposed IPC methods, such as those provided by bound Services, are typically distilled into an abstract interface via Android Interface Defi nition Language (AIDL). AIDL allows for two applications to use “agreed-upon” or stan-dard interfaces for sending and receiving data, keeping the interface separate from the implementation. AIDL is akin to other Interface Defi nition Language fi les or, in a way, C/C++ header fi les. Consider the following sample AIDL snippet:

// IRemoteService.aidl package com.example.android;

// Declare any non-default types here with import statements /** Example service interface */

interface IRemoteService {

/** Request the process ID of this service, to do evil things with it. */

int getPid();

/** Demonstrates some basic types that you can use as parameters * and return values in AIDL.

*/

void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,

double aDouble, String aString);

}

This AIDL example defi nes a simple interface, IRemoteService, along with two methods: getPid and basicTypes. An application that binds to the service exposing this interface would subsequently be able to call the aforementioned methods—facilitated by Binder.

ashmem

Anonymous Shared Memory, or ashmem for short, was another addition to the Android Linux kernel fork. The ashmem driver basically provides a fi le-based, reference-counted shared memory interface. Its use is prevalent across much of Android’s core components, such as Surface Flinger, Audio Flinger, System Server, and the DalvikVM. Because ashmem is designed to automatically shrink memory caches and reclaim memory regions when available system-wide memory is low, it is well suited for low-memory environments.

At a low level, using ashmem is as simple as calling ashmem_create_region, and using mmap on the returned fi le descriptor:

int fd = ashmem_create_region("SomeAshmem", size);

if(fd == 0) {

data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

...

At a higher level, the Android Framework provides the MemoryFile class, which serves as a wrapper around the ashmem driver. Furthermore, processes can use the Binder facility to later share these memory objects, leveraging the security features of Binder to restrict access. Incidentally, ashmem proved to be the source of a pretty serious fl aw in early 2011, allowing for a privilege escalation via Android properties. This is covered in greater detail in Chapter 3.

pmem

Another Android-specifi c custom driver is pmem, which manages large, physi-cally contiguous memory ranging between 1 megabyte (MB) and 16MB (or more, depending on the implementation). These regions are special, in that they are shared between user-space processes and other kernel drivers (such as GPU drivers). Unlike ashmem, the pmem driver requires the allocating process to hold a fi le descriptor to the pmem memory heap until all other references are closed.

Logger

Though Android’s kernel still maintains its own Linux-based kernel-logging mechanism, it also uses another logging subsystem, colloquially referred to as the logger. This driver acts as the support for the logcat command, used to view log buffers. It provides four separate log buffers, depending on the type of information: main, radio, event, and system. Figure 2-4 shows the fl ow of log events and components that assist logger.

The main buffer is often the most voluminous, and is the source for application-related events. Applications typically call a method from the android.util.Log class, where the invoked method corresponds to the log entry priority level—for example, the Log.i method for “informational,” Log.d for “debug,” or Log.e for

“error” level logs (much like syslog).

Native program

Figure 2-4: Android logging system architecture

The system buffer is also a source of much information, namely for system-wide events generated by system processes. These processes utilize the println_native method in the android.util.Slog class. This method in turn calls native code specifi c to logging to this particular buffer.

Log messages can be retrieved using the logcat command, with both the main and system buffers being the default sources. In the following code, we run adb -d logcat to see what is happening on the attached device:

$ adb -d logcat

--- beginning of /dev/log/system

D/MobileDataStateTracker( 1600): null: Broadcast received:

ACTION_ANY_DATA_CONNECTION_STATE_CHANGEDmApnType=null != received apnType=internet

D/MobileDataStateTracker( 1600): null: Broadcast received:

ACTION_ANY_DATA_CONNECTION_STATE_CHANGEDmApnType=null != received apnType=internet

D/MobileDataStateTracker( 1600): httpproxy: Broadcast received:

ACTION_ANY_DATA_CONNECTION_STATE_CHANGEDmApnType=httpproxy != received apnType=internet

D/MobileDataStateTracker( 1600): null: Broadcast received:

ACTION_ANY_DATA_CONNECTION_STATE_CHANGEDmApnType=null != received apnType=internet

...

--- beginning of /dev/log/main ...

D/memalloc( 1743): /dev/pmem: Unmapping buffer base:0x5396a000 size:12820480 offset:11284480

D/memalloc( 1743): /dev/pmem: Unmapping buffer base:0x532f8000 size:1536000 offset:0

D/memalloc( 1743): /dev/pmem: Unmapping buffer base:0x546e7000 size:3072000 offset:1536000

D/libEGL ( 4887): loaded /system/lib/egl/libGLESv1_CM_adreno200.so D/libEGL ( 4887): loaded /system/lib/egl/libGLESv2_adreno200.so I/Adreno200-EGLSUB( 4887): <ConfigWindowMatch:2078>: Format RGBA_8888.

D/OpenGLRenderer( 4887): Enabling debug mode 0

V/chromium( 4887): external/chromium/net/host_resolver_helper/host_ V/WebRequest( 4887): WebRequest::WebRequest, setPriority = 0

I/InputManagerService( 1600): [unbindCurrentClientLocked] Disable input method client.

I/InputManagerService( 1600): [startInputLocked] Enable input method client.

V/chromium( 4887): external/chromium/net/disk_cache/

hostres_plugin_bridge.cc:52: [0204/172737:INFO:hostres_

plugin_bridge.cc(52)] StatHubCreateHostResPlugin initializing...

...

The logcat command is so commonly executed that ADB actually provides a shortcut for running it on a target device. Throughout the course of the book, we make extensive use of the logcat command to monitor processes and overall system state.

Paranoid Networking

The Android kernel restricts network operations based on supplementary group membership of the calling process—a kernel modifi cation known as Paranoid Networking. At a high level, this involves mapping an AID, and subsequently a GID, to an application-level permission declaration or request. For example, the manifest permission android.permission.INTERNET effectively maps to the AID_INET AID—or GID 3003. These groups, IDs, and their respective capabilities are defi ned in include/linux/android_aid.h in the kernel source tree, and are described in Table 2-4.

Table 2-4: Networking capabilities by group

AID DEFINITION GROUP ID / NAME CAPABILITY AID_NET_BT_ADMIN 3001 / net_bt_admin

Allows for creation of any Bluetooth socket, as well as diagnoses and manages Bluetooth connections AID_NET_BT 3002 / net_bt Allows for creation of SCO, RFCOMM,

or L2CAP (Bluetooth) sockets AID_INET 3003 / inet Allows for creation of AF_INET and

AF_INET6 sockets

AID_NET_RAW 3004 / net_raw Allows the use of RAW and PACKET sockets

AID_NET_ADMIN 3005 / net_admin Grants the CAP_NET_ADMIN capability, allowing for network interface, routing table, and socket manipulation

You can fi nd additional Android-specifi c group IDs in the AOSP source repository in system/core/include/private/android_filesystem_config.h.

Dans le document ffi rs.indd 01:50:14:PM 02/28/2014 Page ii (Page 81-87)