SEAndroid - SELinux for Android [Part Three] : SEAndroid source code walkthrough.




Introduction:


Assuming that we now have a basic knowledge of SELinux. In this tutorial, we will try to look at how Google customized SELinux on the Android platform. 

SELinux in the Android platform is called SEAndroid.


Let us start by looking at some of the main stages in our journey.



Let us understand the compilation of the SEAndroid security policy file.

Compiling sepolicy on Android Platform.


The following folders are of high importance to understand the generation of the sepolicy on Android during compilation.

 external/sepolicy: Provides security policy source files in the Android platform. At the same time, the tools in this directory also provide tools for compiling security policy files such as m4 and checkpolicy.

Note that these tools run on the host machine [check out/target/host].
                i.          external/libselinux : Provides Android platform libselinux for the Android system.
              ii.          external/libsepol: Provides a tool checkcon for use when compiling security policy files.

We know that mmm $(PATH) –just-print details out the different execution steps in the make command for the patch.

We start by understanding external/sepolicy/Android.mk.

NOTE: We know if we want to understand the make command steps in detail we need to use mmm command.

Please do the following.

mmm external/sepolicy –just-print.

  

============================================
Checking build tools versions...
make: Entering directory `/GOOGLE_ANDROID/android-6.0.1_r81'
mkdir -p out/target/product/mini-emulator-armv7-a-neon/obj/ETC/sepolicy_intermediates/
m4 -D mls_num_sens=1 -D mls_num_cats=1024 \
          -D target_build_variant=userdebug \
          -s external/sepolicy/security_classes
          external/sepolicy/initial_sids
          external/sepolicy/access_vectors
          external/sepolicy/global_macros
          external/sepolicy/neverallow_macros
          external/sepolicy/mls_macros
          external/sepolicy/mls
          external/sepolicy/policy_capabilities
          external/sepolicy/te_macros
          external/sepolicy/attributes
          external/sepolicy/ioctl_macros
          external/sepolicy/adbd.te
          external/sepolicy/app.te
          external/sepolicy/binderservicedomain.te
          external/sepolicy/blkid.te
          external/sepolicy/blkid_untrusted.te
          external/sepolicy/bluetooth.te
          external/sepolicy/bootanim.te
          external/sepolicy/clatd.te
          external/sepolicy/debuggerd.te
          external/sepolicy/device.te
          external/sepolicy/dex2oat.te
          external/sepolicy/dhcp.te
          external/sepolicy/dnsmasq.te
          external/sepolicy/domain.te
          external/sepolicy/drmserver.te
          external/sepolicy/dumpstate.te
          external/sepolicy/file.te
          external/sepolicy/fingerprintd.te
          external/sepolicy/fsck.te
          external/sepolicy/fsck_untrusted.te
          external/sepolicy/gatekeeperd.te
          external/sepolicy/gpsd.te
          external/sepolicy/hci_attach.te
          external/sepolicy/healthd.te
          external/sepolicy/hostapd.te
          external/sepolicy/init.te
          external/sepolicy/inputflinger.te
          external/sepolicy/installd.te
          external/sepolicy/install_recovery.te
          external/sepolicy/isolated_app.te
          external/sepolicy/kernel.te
          external/sepolicy/keystore.te
          external/sepolicy/lmkd.te
          external/sepolicy/logd.te
          external/sepolicy/mdnsd.te
          external/sepolicy/mediaserver.te
          external/sepolicy/mtp.te
          external/sepolicy/netd.te
          external/sepolicy/net.te
          external/sepolicy/nfc.te
          external/sepolicy/perfprofd.te
          external/sepolicy/platform_app.te
          external/sepolicy/ppp.te
          external/sepolicy/procrank.te
          external/sepolicy/property.te
          external/sepolicy/racoon.te
          external/sepolicy/radio.te
          external/sepolicy/recovery.te
          external/sepolicy/rild.te
          external/sepolicy/runas.te
          external/sepolicy/sdcardd.te
          external/sepolicy/servicemanager.te
          external/sepolicy/service.te
          external/sepolicy/sgdisk.te
          external/sepolicy/shared_relro.te
          external/sepolicy/shell.te
          external/sepolicy/slideshow.te
          external/sepolicy/surfaceflinger.te
          external/sepolicy/su.te
          external/sepolicy/system_app.te
          external/sepolicy/system_server.te
          external/sepolicy/tee.te
          external/sepolicy/toolbox.te
          external/sepolicy/tzdatacheck.te
          external/sepolicy/ueventd.te
          external/sepolicy/uncrypt.te
          external/sepolicy/untrusted_app.te
          external/sepolicy/vdc.te
          external/sepolicy/vold.te
          external/sepolicy/watchdogd.te
          external/sepolicy/wpa.te
          external/sepolicy/zygote.te
          build/target/board/generic/sepolicy/bootanim.te
          build/target/board/generic/sepolicy/device.te
          build/target/board/generic/sepolicy/domain.te
          build/target/board/generic/sepolicy/file.te
          build/target/board/generic/sepolicy/goldfish_setup.te
          build/target/board/generic/sepolicy/init.te
          build/target/board/generic/sepolicy/logd.te
          build/target/board/generic/sepolicy/property.te
          build/target/board/generic/sepolicy/qemud.te
          build/target/board/generic/sepolicy/qemu_props.te
          build/target/board/generic/sepolicy/rild.te
          build/target/board/generic/sepolicy/shell.te
          build/target/board/generic/sepolicy/surfaceflinger.te
          build/target/board/generic/sepolicy/system_server.te
          external/sepolicy/roles
          external/sepolicy/users
          external/sepolicy/initial_sid_contexts
          external/sepolicy/fs_use
          external/sepolicy/genfs_contexts
          external/sepolicy/port_contexts
          >
out/target/product/mini-emulator-armv7-a-neon/obj/ETC/sepolicy_intermediates/policy.conf
sed '/dontaudit/d' out/target/product/mini-emulator-armv7-a-neon/obj/ETC/sepolicy_intermediates/policy.conf > out/target/product/mini-emulator-armv7-a-neon/obj/ETC/sepolicy_intermediates/policy.conf.dontaudit

 ============================================

 Explanation:

On a broad level, the following steps are performed while compiling the sepolicy file.

a.     mkdir -p out/target/product/mini-emulator-armv7-a-neon/obj/ETC/sepolicy_intermediates/
                                    i.          Create a temporary directory.
b.     m4 -D mls_num_sens=1 -D mls_num_cats=1024 -D target_build_variant=userd ebug.
                                              i.          Handle a bunch of input sources [individual TEC files] and create a policy.conf file.
                                            ii.          M4 command will expand some macros defined by SEAndroid.
c.     sed '/dontaudit/d'
                                                             i.     This command will generate policy.conf.dontaudit file.
d.     Checkpolicy[If any never rule is broken by an allow rule etc ] and copying the sepolicy file happens at the end.
e.     Finally, the sepolicy.conf file gets copied to /ETC directory in the root.


There are a bunch of tools which Android compiles and uses for creating the policy file.
For details check and grep for LOCAL_MODULE in  external/sepolicy

tools/sepolicy-analyze/Android.mk:6:LOCAL_MODULE := sepolicy-analyze
tools/Android.mk:5:LOCAL_MODULE := checkseapp
tools/Android.mk:18:LOCAL_MODULE := checkfc
tools/Android.mk:32:LOCAL_MODULE := insertkeys.py
tools/Android.mk:42:LOCAL_MODULE := sepolicy-check

Initializationof SELinux during boot.

After successful compilation and other steps in creating the SELinux support, We now look at the initialization of SELinux[SEAndroid].

This begins right form the init() in init.cpp while the system is booting.


Two important functions in the above code.
1)    Selinux_initialize : Initializes SEAndroid.
2)    A bunch of restoercon.
a.     The full name is restore context.
b.     Based on the contents of the file_contexts some directories are re-labelled.

Let us look at selinux_initialize first.



 Again, Two important functions in the above code.
1)    Selinux_android_load_policy: Load the sepolicy file.
2)    Selinux_init_all_handles: Initializes file_context , seapp_context, and property_context related content.




Finally, the selinux_android_load_policy_helper () is called which loads the policy file in SEAndroid.

This is implemented in external/libselinux/src/android.c.


Some of the paths and files used are.



Going back to the init code, Let us now look at selinux_init_all_handles()


As mentioned earlier, init should tag some files and properties. To achieve this task and in accordance with libselinux API’s init creates two handlers.

These handlers will be used for subsequent labelling and access control. 
Let us have a look at the file and prop context handle functions.




We already saw the paths to these contexts [file,service,property] in selinux filesystem.


Let us now have a look at the restore context or restorecon function.







Want to know how selinux  labels a file or directory? 
The answer is in lsetfilecon.


Setting and getting properties in Android.

One of the most common operations done in Android is the getting and setting of different properties. Remember getprop/setprop?

We will see how SELinux/SEAndroid plays its role in setting a property.


In general, SELinux permission checking is done by the kernel.
But a property in the Android platform is completely a user-space content.

So, let's take a look at how init uses libselinux to perform userspace permission checks

Assume that a process wants to set properties through the setprop function. There is call to check_perms in property_service.cpp.




Simple is it not?

User space permission checking is done through selinux_check_access and its input parameters include.
1)    Source SContext: This is the SContext of the process that called setprop.
2)    The SContext of the target: different attributes have different SContexts, which are defined in property_context.
3)    The Object class to check (classes supported by the system are defined in the external/sepolicy/security_classes file).

The operation name ( perm , defined by the access vector . For the Object class of Property, the only operation it needs to do permission checking is set.

Please remember we have already seen access vectors in external/sepolicy/access_vectors file.

Please refer to the official documentation for more details.

SELinux in Android Applications.

Until now, we were only seeing how the Android native part of things use SELinux/SEAndroid.

Let us broaden our horizon of understanding and see how the Applications [Android apps] are bound by SELinux rules.

We understand 2 scenarios.

1)    APK getting installed after forked from Zygote.
2)    After apk is installed, it will create its own folder under the /data/data/ directory.
a.     This is done by installd.
b.     installd should label these different folders with the corresponding labels.


Installation and Package Scanning:

Let us look at PackageManagerService.java.

The following function will use
 1)/data/security/mac_permissions.xml
 2) The contents of /system/etc/security/mac_permissions.xml.


In the same function, we see.


Note that mac_permissions.xml is located in external/sepolicy.
After successful compilation, the contents of RELEASE and PLATFORM will be replaced by RELEASE and PLATFORM signature information.




For your reference above is an older version of mac_permissions.xml. This file stores the seinfo corresponding to different signatures.

Application PackageScanning.

When the APK is installed,  It is scanned by APK is scanned by PackageManagerService.
Let us look at the code.





This function will assign seinfo value to the corresponding apk according to the signature information in mac_permisssions.xml.



NOTE:
seInfo is analogous to the Domain in the SContext defined by Android for the App .


ActivityManagerService:

The ActivityManagerService is responsible for starting the target application process. The relevant code is as follows.




We know that after this the zygote process will fork a child process.
 Let us directly see how SELinux kicks in [Zygote can be understood as a part of some other tutorial].










In the same function as shown above, we see the setSELinuxContext.

Finally, it boils to selinux_android_setcontext.



And the same flow as in case of Native calls start and selinux_android_seapp_context_reload is called.





For more details see, 

external/sepolicy/seapp_contexts is loaded when seapp_context_lookup is called as below.


Let us look at seapp_contexts.


seapp_context_lookup is an important function that finishes the mapping from the contents of the seapp_context file to which domain it corresponds to as if it were a native entity.

So, In a nutshell.

In SEAndroid, different applications will get SContext based on their signature information. This sContext is used for labelling the different things based on the seinfo.

App data directory creation and Labelling.

Once the application is installed, installd() is used to create the /data/data/ directory of the application. In this case, also SELinux is used to label the different contents in this directory.

Let us see how this is achieved.





 Finally, installd gets invoked and which calls selinux_android_setfilecon.




In a similar way as earlier.It will eventually set the pkgdir's SContext which again is obtained from the mac_permissions.


AVC Denials.
So, Now that we have learnt what SELinux is and how Android uses it. What do we do when we get AVC [Access vector] denials when we bringup a system, service or an executable.

We use the following programs to understand and fix the AVC denials.

NAME
audit2allow - generate SELinux policy allow/dontaudit rules from logs of denied operations
audit2why - translates SELinux audit messages into a description of why the access was denied (audit2allow -w)


On Android systems we can follow the following steps.

# Goto android source code root and then execute following commands
# Keep the logcat.log in the root directory of the source code.

export ANDROID_BUILD_TOP=$(pwd)
./external/selinux/prebuilts/bin/audit2allow -p out/target/product/{devicename}/root/sepolicy < logcat.log>

# Copy the generated rules in respective files in the device/XYZ/ directory.
#Ensure that we do not overwrite a neverallow rule with an allow rule as sometimes this is the easiest way out.



We now have completed our source code analysis of SEAndroid [Though concise , I Hope we covered both Native and Java layer SELinux fundamentals].

Comments

Popular posts from this blog

Android Audio Tutorial [Part Three] : AudioFlinger Introduction and Initialization

Android External Storage Support: Volume Daemon (vold) Architecture

Android Audio Tutorial [Part One] : Introduction