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
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.
Comments
Post a Comment