Security basics of the Android operating system. Native user space, part 1

    Introduction


    In this article I will try to consider security a little higher than the kernel, namely: how security works in Native user space. We will cover the theme of the operating system boot process and consider the structure of the Android file system. As I said, I'm not very strong on Linux, so if you notice inaccuracies, then fix it - teach me and improve the article. Since this topic is quite extensive, I decided to break it into two parts. In the first part we will consider the process of loading the operating system and the features of the file system. Everyone who is interested, welcome!



    List of Articles

    Here are links to my articles from this topic:
    1. Security basics of the Android operating system. Core level
    2. Security basics of the Android operating system. Native user space, part 1
    3. Security basics of the Android operating system. Native user space, part 2
    4. Security basics of the Android operating system. Security at the Application Framework level. Binder IPC



    What is meant by native user space

    Native user space refers to all user space components that run outside the Dalvik Virtual Machine and which are not part of the Linux kernel.



    Android file system


    First, let's look at the structure of the Android file system. Although Android is based on the Linux kernel, we will not see the file system structure familiar to our eyes here. Let's run the emulator and see what we have. To do this, run the command:

    adb shell ls -al
    

    In my terminal for an emulator on Android 4.2, I see the following result:

    drwxr-xr-x root     root              2013-04-10 08:13 acct
    drwxrwx--- system   cache             2013-04-10 08:13 cache
    dr-x------ root     root              2013-04-10 08:13 config
    lrwxrwxrwx root     root              2013-04-10 08:13 d -> /sys/kernel/debug
    drwxrwx--x system   system            2013-04-10 08:14 data
    -rw-r--r-- root     root          116 1970-01-01 00:00 default.prop
    drwxr-xr-x root     root              2013-04-10 08:13 dev
    lrwxrwxrwx root     root              2013-04-10 08:13 etc -> /system/etc
    -rwxr-x--- root     root       244536 1970-01-01 00:00 init
    -rwxr-x--- root     root         2487 1970-01-01 00:00 init.goldfish.rc
    -rwxr-x--- root     root        18247 1970-01-01 00:00 init.rc
    -rwxr-x--- root     root         1795 1970-01-01 00:00 init.trace.rc
    -rwxr-x--- root     root         3915 1970-01-01 00:00 init.usb.rc
    drwxrwxr-x root     system            2013-04-10 08:13 mnt
    dr-xr-xr-x root     root              2013-04-10 08:13 proc
    drwx------ root     root              2012-11-15 05:31 root
    drwxr-x--- root     root              1970-01-01 00:00 sbin
    lrwxrwxrwx root     root              2013-04-10 08:13 sdcard -> /mnt/sdcard
    d---r-x--- root     sdcard_r          2013-04-10 08:13 storage
    drwxr-xr-x root     root              2013-04-10 08:13 sys
    drwxr-xr-x root     root              2012-12-31 03:20 system
    -rw-r--r-- root     root          272 1970-01-01 00:00 ueventd.goldfish.rc
    -rw-r--r-- root     root         4024 1970-01-01 00:00 ueventd.rc
    lrwxrwxrwx root     root              2013-04-10 08:13 vendor -> /system/vendor
    

    I will mark here only the main directories and those that will be useful to us in the future. On the Internet you can find a description and the purpose of other directories. You may notice that some directories are the same as on Linux, for example, / dev , / proc , / sys , / mnt , / etc, and their purpose is basically the same as on Linux. By the way, note that we do not see the / bin and / lib directories. Where they hid, I will tell a little later.

    On the other hand, you will notice directories that Linux does not have at all. Among them, we are interested in / data , / system , / cache , / init ,/init.rc Let's look at their purpose in more detail.
    / system This is the main directory where the immutable components of the Android system are stored. If we draw an analogy, then this folder is similar to the read-only C: \ windows \ folder . Those. we cannot change the data in this directory. This is where you can find the / bin and / lib directories where various executables and shared libraries are stored. In addition, there are also system applications that are built into the operating system and which, by default, cannot be deleted. The contents of this directory are generated during compilation of the operating system.
    / data Because / systemIf we have read-only access, then there should be a directory where mutable data is stored. / data is just that. For example, apk files of installed applications are stored in this directory in / data / app , and their data is stored in / data / data (we examined this directory in detail in the previous article).
    / cache This is just temporary storage. Also, this directory is saved, and then system updates are launched from it.

    To understand what an / init file is and why we need obscure files with the * .rc extension, consider the system boot process.



    Android boot process





    Let's look at a few steps in the process of loading the Android operating system. This picture is taken from the book "Embedded Android", there you can find a more detailed description. Although in general I understand the process, but for me it is more magic :)

    CPU. When you press the power button, voltage starts to be applied to the processor of your device. Since until this moment the processor was turned off, and since it is not able to maintain its state without applying voltage, then immediately after the start it is in some uninitialized state. In this case, the processor reads some hard-wired address from its special register and starts to execute instructions starting from it. Most often, this address points to the chip in which the bootloader (bootloader) is wired.
    Bootloader.Bootloader initializes the RAM and loads the Linux kernel into it. In addition, Bootloader creates a RAMdisk.
    Linux kernel. The kernel initializes various subsystems, built-in drivers and mounts root filesystem (root file system). After that, the kernel can run the first program.
    This ends the magic and then everything becomes more or less clear.



    Init


    The first program in the case of Android is init . The executable file is located in the root directory ( / init ). It is this program that the kernel starts after it boots. Its sources are located in the system / core / init / folder . Let's dig into them a little. We are interested in system / core / init / init.c :

    ...
    int main(int argc, char **argv)
    {
        ...
        /* clear the umask */
        umask(0);
            /* Get the basic filesystem setup we need put
             * together in the initramdisk on / and then we will
             * let the rc file figure out the rest.
             */
        mkdir("/dev", 0755);
        mkdir("/proc", 0755);
        mkdir("/sys", 0755);
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        mount("proc", "/proc", "proc", 0, NULL);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        ...
        init_parse_config_file("/init.rc");
        ...
    }
    

    At first, we create and install some necessary for the directory, and then parse the file /init.rc and do what parsed. The format of the /init.rc file is very well described in readme , where you can also find an example. In short, this file is a set of actions (sections - a named sequence of commands). Each sequence of commands is triggered by a specific trigger (trigger). For example, the following in sequence is action, in which trigger is fs, and the sequence of commands is a set of mount commands:

    on fs
        # mount mtd partitions
        # Mount /system rw first to give the filesystem a chance to save a checkpoint
        mount yaffs2 mtd@system /system
        mount yaffs2 mtd@system /system ro remount
        mount yaffs2 mtd@userdata /data nosuid nodev
        mount yaffs2 mtd@cache /cache nosuid nodev
    

    The source file /init.rc is located in system / core / rootdir / init.rc. Let's look at some of its main parts, although I highly recommend that you look at its fullness. After that, many things should become clear to you. So, our file begins with the following lines:

    import /init.usb.rc
    import /init.${ro.hardware}.rc
    import /init.trace.rc
    

    They mean that in addition to the init.rc file, you also need to import the settings from the init.usb.rc , init.trace.rc files and from the file with the strange name init. $ {Ro.hardware} .rc However, $ {ro.hardware} Is just a variable whose value determines the type of iron. In the case of an emulator, its value, for example, is goldfish . Next, environment variables are defined:

    ...
    on init
        ...
        # setup the global environment
        export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
        export LD_LIBRARY_PATH /vendor/lib:/system/lib
        export ANDROID_BOOTLOGO 1
        export ANDROID_ROOT /system
        export ANDROID_ASSETS /system/app
        export ANDROID_DATA /data
        export ANDROID_STORAGE /storage
        export ASEC_MOUNTPOINT /mnt/asec
        export LOOP_MOUNTPOINT /mnt/obb
        export BOOTCLASSPATH /system/framework/core.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
        ...
    

    After this, the variables necessary for the operation of the device are initialized. If you are interested in this topic, then you can easily find information about a particular command. Let's take a closer look at the following block (which I already cited in this article):

    on fs
        # mount mtd partitions
        # Mount /system rw first to give the filesystem a chance to save a checkpoint
        mount yaffs2 mtd@system /system
        mount yaffs2 mtd@system /system ro remount
        mount yaffs2 mtd@userdata /data nosuid nodev
        mount yaffs2 mtd@cache /cache nosuid nodev
    

    MTD - Memory Technology Devices. In general terms, MTD is a special chip with non-volatile (i.e., data on this chip is saved after a reboot or shutdown) with flash memory (such as NOR or NAND), on which disk images are saved. In thisThe article talks in more detail about this type of device, as well as limitations. Specifically for these varieties of flash-memory special file systems were developed, for example, YAFFS. One of the most important limitations of these types of memory is that in order to write data to a sector where some data has already been written, you must completely erase the entire sector first. Therefore, manufacturers began to switch to a new type of block flash memory (eMMC), on which you can put a regular ext4 file system and get rid of this limitation. Because I am showing an init.rc examplefile for the emulator, where all the work is emulated, then it uses the YAFFS2 file system by default (I think that these are relics of the past, because YAFFS2 was used for all devices up to Android 2.2). In a real device (this is just one example when you need to use the init.rc file for a specific hardware), these commands will be overwritten. For example, in the case of a herring device (Google Nexus S), in the init.herring.rc file , this section looks like this:

    on fs
        mkdir /efs 0775 radio radio
        mount yaffs2 mtd@efs /efs noatime nosuid nodev
        chmod 770 /efs/bluetooth
        chmod 770 /efs/imei
        mount_all /fstab.herring
        ...
    

    Where fstab.herring is a file whose contents are as follows:

    ...
    /dev/block/platform/s3c-sdhci.0/by-name/system          /system             ext4      ro                                                    wait
    /dev/block/platform/s3c-sdhci.0/by-name/userdata        /data               ext4      noatime,nosuid,nodev,nomblk_io_submit,errors=panic    wait,encryptable=/efs/userdata_footer
    

    As you may have noticed, / system , / data , / cache are simply mounting points (mount points of the file system) that indicate either MTD devices (in the case of an emulator) or block devices (in the case of a real device) where corresponding disk images (system.img, userdata.img and cache.img). I'm not sure, but I think that inside the smartphone there is one single chip with flash-memory, divided into partitions (volumes), each of which contains the corresponding image. This flash memory chip is what we know by the name Internal storage , the volume of which is one of the main parameters of a smartphone.

    It should be noted that / systemmounted read-only (read-only). This means that the contents of this section does not change during the operation of the device, but only when you, for example, update the system on your device (using system updates).

    We continue to look at our init.rc . The post-fs-data trigger generates the basic structure of the / data partition file system . There, in general, everything is clear - a set of mkdir , chown , chmod commands.

    Next init.rclaunches several demons. If you return to the figure at the beginning of the article, they are listed in the Native daemons block. We will stop here for now. As you can see from the figure, I did not fully consider the process of loading the operating system. Some uncovered steps I will consider in the following article.



    Conclusion


    In the next part I will tell you where the images system.img, userdata.img and cache.img come from and consider security at the Native user space level. As always, corrections, additions, as well as suggestions about what to write are welcome. And although I already have some plan about what to write in the next article, I am ready to correct it.


    References


    1. Working with MTD Devices
    2. "Embedded Android" by Karim Yaghmour
    3. Android Security Underpinnings by Marko Gargenta



    Update
    • Comment from bmx666 user about various options for placing the loader on MTD devices.
    • Comment from SamOwaR user about CPU initialization on different SoCs

    Also popular now: