Android Security: An Overview Of Application Sandbox

September 10, 2016

The Problem:

Define a policy to control how various clients can access different resources.

A solution:

  1. Each resource has an owner and belongs to a group.
  2. Each client has an owner but can belongs to multiple groups.
  3. Each resource has a mode stating the access permissions allowed for its ownergroup members and others, respectively.

In the context of operating system, or Linux specifically, the resources can be files, sockets, etc; the clients are actually processes; and we have three access permissions:read, write and execute.

Yes, this is just Linux's UID/GID based access control model, and the rules are enforced by Linux kernel. What we will discuss in this article is how it works Android. By the end of the article, we should be able to answer following questions.

  1. How does Android set up the owner, groups and mode of a resource?
  2. How does Android set up the owner and groups of a process?
  3. What does it mean for users and apps? For example, is it possible for app1 access app2's data? Will a normal app be able to access device node directly?

The discussion here is based on the latest android master (Android N) but we'll mention some history in the hope it helps your understanding..

Android Users and Groups ID

Before we jumping in and answering above questions, let first take a look how the user and group are represented in Android. Yes, with an ID, obliviously. Here lists all the users and groups IDs for the system, their meaning and designated ranges for different purposes.

/* This is the master Users and Groups config for the platform.*/
#define AID_ROOT             0  /* traditional unix root user */
#define AID_SYSTEM        1000  /* system server */
#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
#define AID_GRAPHICS      1003  /* graphics devices */
#define AID_INPUT         1004  /* input devices */
#define AID_AUDIO         1005  /* audio devices */
#define AID_CAMERA        1006  /* camera devices */
#define AID_LOG           1007  /* log devices */
#define AID_COMPASS       1008  /* compass device */
#define AID_MOUNT         1009  /* mountd socket */
#define AID_WIFI          1010  /* wifi subsystem */
#define ...
#define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
/* The 3000 series are intended for use as supplemental group id's only*/
#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */
#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or
#define AID_APP          10000  /* first app user */
#define AID_USER        100000  /* offset for uid ranges for each user */

Then, we will look at the first question - How and when to set up the owner, groups and mode of a resource? Roughly speaking, there are two categories. The first is to set it when the file system is created; the second is to set it during the system init.

File System Configuration

When creating the file systems, following information will be utilized to set the mode, uid and guid of corresponding directories and files. Since M, OEM are allowed to override those rules with customized configuration.

static const struct fs_path_config android_dirs[] = {
    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
    { 00500, AID_ROOT,   AID_ROOT,   0, "config" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
    { 00755, AID_ROOT,   AID_SYSTEM, 0, "mnt" },
    { 00755, AID_ROOT,   AID_ROOT,   0, "root" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
};

static const struct fs_path_config android_files[] = {
    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
};

System Init and init.rc

The second place to set mode/uid/gid of a particular file or directory is the init.rcs, which will be read by init process - the first user space program will be executed after kernel is ready.

The full description of the init.rc and the boot process is outside of the scope of this article. As far as what is relevant to the discussing here, it boils down to use chown and chmod to set the owner and mode for a particular file and directory.

on post fs-data
    # We chown/chmod /data again so because mount is run as root + defaults
    chown system system /data
    chmod 0771 /data

Ueventd and Device Node

One thing we are of particular interest are the UID and GID of device node. Since device nodes are the interface to the system hardware resources, a failure to enforce permission control on device node indicates a big security vulnerability.

ueventd is responsible for taking are of assigning the correct mode, UID and GID to the device node. It starts very early and will parse uventd.*.rc and set up the mode/uid/gid of corresponding device node. This is the third place you can tweak the mode, uid and guid for a file but it is specific for the device node.

ueventd.rc
/dev/alarm                0664   system     radio
/dev/rtc0                 0640   system     system
/dev/tty0                 0660   root       system
/dev/graphics/*           0660   root       graphics
/dev/input/*              0660   root       input
/dev/eac                  0660   root       audio
/dev/cam                  0660   root       camera
...

To recap, we have covered three places where you can set the mode/uid/gid for files and directories, that is 1) when you creating the file system, 2) when the system start running and 3) a special handling of the device nodes using ueventd.

Now, it is time to look at another part of the story - how the uid/gid are set for processes. First, we will check the system processes. And, normal app processes.

UID/GID of System Process

At the late stage of the init process, the core system services, such as servicemanager, vold and surfaceflinger, will be started. The UID and GID of the system process are specified in its corresponding .rc file. For example forsurfaceflinger, it's configuration is in the surfaceflinger.rc. It might worth note that, before M, the system process and its settings are all put into a centralized file called init.rc.

service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /sys/fs/cgroup/stune/foreground/tasks

As you can see, each process is assigned a user and multiple groups. For example, surfaceflinger's UID is system and it belongs to three groups: graphics, drmrpc and readproc.

To show the USER ID of a process, use ps

myDevice # ps
system    427   1     171224 23988 S /system/bin/surfaceflinger

To show the Group IDs of a process, we can check the process’ related proc file.

myDevice # cat /proc/427/status
Name:   surfaceflinger
State:  S (sleeping)
Tgid:   427
Pid:    427
PPid:   1
TracerPid:  0
Uid:    1000    1000    1000    1000
Gid:    1003    1003    1003    1003
FDSize: 256
Groups: 1026 3009

We can see that surfaceflinger belongs to 1003 and 1026 groups, which are graphics and drmrpc respectively. (*1003 is the gid, 1026 and 3009 are the supplementary group it belongs to. See the proc main page for detail)

UID/GID of Normal App Process

Normal app will be assigned AID above 10000, and the GUID will be the same as AID.

To show the UID, use ps:

USER      PID   PPID  VSIZE   RSS            PC   NAME
u0_a46    5833  1096  2283376 144908 7e739ecab4 S com.android.camera2

To check the GID, check its proc file:

myDevice:/ # cat /proc/5833/status
Name:   android.camera2
State:  S (sleeping)
Tgid:   5833
Pid:    5833
PPid:   1096
TracerPid:  0
Uid:    10046   10046   10046   10046
Gid:    10046   10046   10046   10046
FDSize: 128
Groups: 3003

Note that the GID is the same as UID, which are 10046. It is easy to find out how it is related to the name u0_a46.

You may have noticed that there is supplementary groups ID the camera2 process belongs, 3003 (i.e AID_INET). It is related with what permission this app has been granted.

Permission and GUID for Apps

If an application requests certain permission and is granted, the corresponding group ID will be added to the process of the application. Part of the mapping between the permission and group id is shown as below:

<permission name="android.permission.BLUETOOTH" >
    <group gid="net_bt" />
</permission>
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
    <group gid="media_rw" />
    <group gid="sdcard_rw" />
</permission>
<permission name="android.permission.INTERNET" >
    <group gid="inet" />
</permission>

We will use above camera2 app as an example to show how the permission is related to the group it is assigned.

To show the permissions granted for camera2 application, use dumpsys package: adb shell dumpsys package com.android.camera2

  install permissions:
  // other permissions are removed for clarity
  android.permission.INTERNET: granted=true
  gids=[3003]

As we can see, since camera2 app is granted INTERNET permission, which maps to the inet group, it has the supplementary groups 3003.

Apps With Special UID

One particular interest is to assign an app a special UID so it will be allowed to access resource that otherwise won't be able to access. By special UID, we usually mean the UID defined for system, i.e those belong to the range of 1000 to 1999. Can that be achieved?

Yes, we can do that by declaring android:sharedUserId="android.uid.xxxx" in the AndroidManifest.xml. In addition, the application also should be signed with the platform key by adding LOCAL_CERTIFICATE := platform in the Android.mk.

One example is the NFC app. Instead of having a normal u0_axx UID, Nfc app has the User ID nfc.

    nfc       4414  1096  1579708 59440 SyS_epoll_ 7e739ecab4 S com.android.nfc

And that is AID_NFC, 1027.

arche:/ # cat /proc/4414/status
Name:   com.android.nfc
Tgid:   4414
Pid:    4414
PPid:   1096
Uid:    1027    1027    1027    1027
Gid:    1027    1027    1027    1027
Groups: 3001 3002 3003 9997 41027

And that means the nfc app can access following device node directly!

myDevice:/ # ls -l /dev/pn54x
crw-rw---- 1 nfc nfc 10,  73 1970-01-09 20:14 /dev/pn54x

Here is an example how that is achieved in nfc app.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.nfc"
    android:sharedUserId="android.uid.nfc">

Being able to access the device node directly means lots of trusts; that is the reason the application request system UID must also be signed with platform certification.

LOCAL_PACKAGE_NAME := Nfc
LOCAL_CERTIFICATE := platform

Now, it is time to have some exercises.

Exercises

1. Can app1 can access app2’s data?

Normally, they can't.

drwxr-x--x u0_a21   u0_a21            1970-01-01 04:12 com.android.calendar
drwxr-x--x u0_a22   u0_a22            1970-01-01 00:54 com.android.camera2

App’s uid/gid are unique and the mode is set to “rw” only for the owner. So, app1 can’t access the data of app2.

But it can be done by sharing same uid and signed with same certification, as we discussed in Apps with Special UID.

2. Whether a process can access a certain device node?

It depends.

case 1 : same UID

root@myBoard:/ # ll /dev/ion
crw-rw-rw- system   media     10,  62 1970-01-01 00:00 ion

surfacflinger can access /dev/ion because surfaceflinger’s user is system and so is the /dev/ion.

A recap that the mode/uid/gid of /dev/ion is set in the ueventd.device.rc/dev/ion 0666 system media

case 2 : same Group

root@myBoard:/ # ll /dev/video0
crw-rw----   root     camera    81,   0 1970-01-01 00:00 video0

Despite that UID of video0 and the mediaserver are different (root and media respectively), but since they belongs to the same group (camera), and also the permission for group member is “rw”, so mediaserver can read and write /dev/video0node.

UID and Binder call

So far, we limit our definition of resources to be files. However, it can be something else, such as the ability to trigger certain system action, or more general, to do a Binder call.

For each binder call, at the server side, you can get its calling PID and UID, which can be used determine whether the call will be served or denied. This is the most basic but fundamental practice in Android to ensure the IPC security.

Summary

UID/GID based security control is a type of Discretionary Access Control(DAC). It is the fundamental part of Android's sandbox and security model to ensure the data and system security, so it's important to understand how it works.

Since Android 4.3, SELinux, as an implementation of Mandatory Access Control(MAC), has been utilized to overcome the limitation of DAC and to further improve the security of Android. We can talk it about it someday as well.

EDIT: Well, SELinux is discussed here.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值