SEAndroid系統架構總體分析


 1.前言

  在Linux中NSN開發了SELinux,來保護linux系統的安全,因為Android有着獨特的用戶運行時空間,

  所以SELinux並不完全適用Android,故而在SELinux的基礎上有了SEAndroid,SEAndroid主要保護的

  對象就是系統中的資源例如文件,屬性等和系統中的進程,Socket,IPC等。

 2.SELinux的整體結構

  

     在SEAndroid的整體結構中,通過SELinux的文件系統,將其划分為了用戶空間和內核空間。用戶空間中包含了

  Security Context,Security Server,selinux庫libselinux。內核空間包含了LSM.

  1.Security Context:描述了對象安全上下,安全策略就是由資源安全上下文決定的

  2.Security Server:一方面到Security Context中去檢索安全上下文,另一方面也到內核空間操作安全上下文

  3.SEAndroid Policy:安全策略。在系統啟動的時候,Security Server會將其加載到內核空間的LSM中。

  4.libselinux:是SELinux庫,可以用來讀寫SELinux文件系統,加載SEAndroid Policy,檢索和操作安全上下文等都是由libselinux完成的

  5.LSM:負責內核資源的訪問控制

3.內核空間

  LSM:LSM是內核MAC機制的一個通用的模塊,而SEAndroid僅僅是LSM的一個實現。這體現了內核設計的一個思想。在LSM中包含了Access Vector Cache

  和Security Server兩個模塊。當要訪問一個資源的時候,首先會到Access Vector Cache檢查是否允許訪問,如果不允許訪問,則到Security Server

  中查詢是否可以訪問,如果可以訪問在訪問的同時,也會在Access Vector Cache中將結果進行保存。

  SELinux LSM 和內核子系統的交互:當訪問內核子系統中的資源的時候,LSM就會調用他的Hook代碼,而Hook代碼就會回調SELinux中的回調方法。

  例如當調用系統的read函數的時候,進入到內核子系統中的文件系統。在文件子系統中負責讀取文件的vfs_read函數,就會回調LSM加入的Hook代碼,

  Hook代碼就會回調SELinux中的回調函數,以確保安全性的檢查

  安全訪問資源的流程:

  

進行了三次錯誤性檢查:

1. 檢查對象是否存在,訪問參數是否正確等

2. Linux UID/GID是否允許

3. 安全策略是否允許

 

4.用戶空間

 1.Security Context:對象安全上下文,用來定制安全策略。由用戶,角色,類型和安全級別組成。在第一篇文章我們可知

  查看上下文的方法。對象安全上下文又分為主體(指進程)和客體(指資源如文件等)。

  其實用戶和角色並不重要,重要的是類型。下面分別來對其進行介紹。

 用戶和角色只是用來限制進程可以標注的類型,而對文件來說是可以完成不記的。對所有主體和客體來說,只有一個SELinux用戶,那就是

 u(系統中只定義了這一個SELinux用戶),對客體來說通常將它的角色定為object_r。而對所有的主體來說,只定義了一個角色那就是r。

 在src/system/sepolicy/private/users中可以看到系統定義的SELinux用戶

 user u roles { r } level s0 range s0 - mls_systemhigh;

 表明了一個SELinux的用戶u,他可用的角色為r,安全級別默認為s0,而安全級別的范圍為s0-mls_systemhigh

 在src/system/sepolicy/private/roles_decl中可以看到角色的定義

 role r;

 在src/system/sepolicy/public/roles中可以看到角色可以關聯的類型:

 role r types domain;

 表明角色r可以關聯的類型為domain

 可以看到u和r關聯,而r又和類型domain關聯。換句話說如果沒有定義其他的用戶,角色和類型,那么只有u,r和domain的組合才是正確的。

 可是我們又會看到

  $ ps -Z

  LABEL USER PID PPID NAME
  u:r:init:s0 root 1 0 /init

 難道u:r:init:s0的組合是錯誤的嗎?當然不是了。在src/system/sepolicy/public/init.te中

  type init, domain, mlstrustedsubject;表明了將domain定義為init的屬性,那么能用domain的地方就能用init.所以上面的說法也是正確的。

 安全級別:在SELinux中安全級別是由敏感性(sensitivity)和類別(category)兩部分組成的.但是類別這部分是可以省略的。一般的形式為sensitivity[:category]

 如由敏感性s0和策略c0,c1組成的安全級別就為s0[:c0,c1]. 在SEAndroid中,低安全級別可以向高安全級別的寫入數據,但是不能讀。高安全級別的可以讀取低安全

 級別的數據,但是不能寫入。如果兩個安全級別是相同的,那么既可以讀又可以寫。

 類型:類型是SEAndroid中最為重要的。在src/system/sepolicy/public/roles中我們可以看到

 role r types domain

 domain表示的是進程的類型。每一個進程的類型都會將domain作為屬性,每一個文件的類型都會將file_context作為屬性。

 那么安全策略又是如何定義的呢?

 主要分析四種安全策略的定義,app進程,app數據文件,系統文件已經系統屬性。與其相關的文件有

 src/system/sepolicy/private/mac_permissions.xml,src/system/sepolicy/private/seapp_contexts,src/system/sepolicy/private/file_contexts,

 property_contexts.

 安全策略的確定首先要確定安全上下文,其實也就是確定最為重要的類型。

 看mac_permissions.xml

<?xml version="1.0" encoding="utf-8"?>
<policy>

<!--

    * A signature is a hex encoded X.509 certificate or a tag defined in
      keys.conf and is required for each signer tag. The signature can
      either appear as a set of attached cert child tags or as an attribute.
    * A signer tag must contain a seinfo tag XOR multiple package stanzas.
    * Each signer/package tag is allowed to contain one seinfo tag. This tag
      represents additional info that each app can use in setting a SELinux security
      context on the eventual process as well as the apps data directory.
    * seinfo assignments are made according to the following rules:
      - Stanzas with package name refinements will be checked first.
      - Stanzas w/o package name refinements will be checked second.
      - The "default" seinfo label is automatically applied.

    * valid stanzas can take one of the following forms:
  
-->

    <!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
      <seinfo value="platform" />
    </signer>

    <!-- Media key in AOSP -->
    <signer signature="@MEDIA" >
      <seinfo value="media" />
    </signer>

</policy>

如果我們的app使用的是系統的簽名,那么從該文件中得知,對應的seinfo為platform.從當前代碼中我們可以看到系統只提供了兩個簽名(nexus8.1的代碼),如果

還有其他的簽名的app怎么辦?從注釋中我們可以看到,它將會用seinfo為"default"。seinfo並不是app進程的類型,接下來再看seapp_contexts文件

 

# Input selectors:
#       isSystemServer (boolean)
#       isEphemeralApp (boolean)
#       isV2App (boolean)
#       isOwner (boolean)
#       user (string)
#       seinfo (string)
#       name (string)
#       path (string)
#       isPrivApp (boolean)
#       minTargetSdkVersion (unsigned integer)
# isSystemServer=true can only be used once.
# An unspecified isSystemServer defaults to false.
# isEphemeralApp=true will match apps marked by PackageManager as Ephemeral
# isV2App=true will match apps in the v2 app sandbox.
# isOwner=true will only match for the owner/primary user.
# isOwner=false will only match for secondary users.
# If unspecified, the entry can match either case.
# An unspecified string selector will match any value.
# A user string selector that ends in * will perform a prefix match.
# user=_app will match any regular app UID.
# user=_isolated will match any isolated service UID.
# isPrivApp=true will only match for applications preinstalled in
#       /system/priv-app.
# minTargetSdkVersion will match applications with a targetSdkVersion
#       greater than or equal to the specified value. If unspecified,
#       it has a default value of 0.
# All specified input selectors in an entry must match (i.e. logical AND).
# Matching is case-insensitive.
......
#

isSystemServer=true domain=system_server
user=system seinfo=platform domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
user=nfc seinfo=platform domain=nfc type=nfc_data_file
user=radio seinfo=platform domain=radio type=radio_data_file
user=shared_relro domain=shared_relro
user=shell seinfo=platform domain=shell type=shell_data_file
user=_isolated domain=isolated_app levelFrom=user
user=_app seinfo=media domain=mediaprovider name=android.process.media type=app_data_file levelFrom=user
user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
user=_app isV2App=true isEphemeralApp=true domain=ephemeral_app type=app_data_file levelFrom=user
user=_app isPrivApp=true domain=priv_app type=app_data_file levelFrom=user
user=_app minTargetSdkVersion=26 domain=untrusted_app type=app_data_file levelFrom=user
user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user

當在mac_permissions.xml中查詢到seinfo信息后,就會到該文件查詢對應類型。如platform對應的app的進程的類型就為platform_app,而由該app創建的文件的類型

就為app_data_file。而對於seinfo為default的app進程的類型為untrusted_app_25,由該app進程所創建的文件的類型為app_data_file.知道了安全上下文是如何定義的

之后就可以看看安全策略是如何定義的了。

繼續看init.te文件

 

ypeattribute init coredomain;

tmpfs_domain(init)

# Transitions to seclabel processes in init.rc
domain_trans(init, rootfs, charger)
domain_trans(init, rootfs, healthd)
domain_trans(init, rootfs, slideshow)
domain_auto_trans(init, e2fs_exec, e2fs)
recovery_only(`
  domain_trans(init, rootfs, adbd)
  domain_trans(init, rootfs, recovery)
')
domain_trans(init, shell_exec, shell)
domain_trans(init, init_exec, ueventd)
domain_trans(init, init_exec, watchdogd)
domain_trans(init, { rootfs toolbox_exec }, modprobe)
# case where logpersistd is actually logcat -f in logd context (nee: logcatd)
userdebug_or_eng(`
  domain_auto_trans(init, logcat_exec, logpersist)
')

 

 

 

 可以看到類似於tmpfs_domain(init)的調用,這是所定義的宏,為init類型添加一些權限

再看文件src/system/sepolicy/te_macros

 
         

......

define(`tmpfs_domain', `
type $1_tmpfs, file_type;
type_transition $1 tmpfs:file $1_tmpfs;
allow $1 $1_tmpfs:file { read write getattr };
allow $1 tmpfs:dir { getattr search };
')

......

 

可以看到tmpfs_domain為將file_type設置為init_tmpfs的屬性,那么init_tmpfs將也是描述文件的類型,之后還通過allow語句為init設置了其他權限。

系統文件的權限設置。file_contexts文件中的內容如下

 

......
/system(/.*)? u:object_r:system_file:s0 /system/bin/atrace u:object_r:atrace_exec:s0 /system/bin/e2fsdroid u:object_r:e2fs_exec:s0 /system/bin/mke2fs u:object_r:e2fs_exec:s0 /system/bin/e2fsck -- u:object_r:fsck_exec:s0 /system/bin/fsck\.f2fs -- u:object_r:fsck_exec:s0 /system/bin/make_f2fs -- u:object_r:fsck_exec:s0 /system/bin/fsck_msdos -- u:object_r:fsck_exec:s0 /system/bin/tune2fs -- u:object_r:fsck_exec:s0 /system/bin/toolbox -- u:object_r:toolbox_exec:s0 /system/bin/toybox -- u:object_r:toolbox_exec:s0 /system/bin/logcat -- u:object_r:logcat_exec:s0 /system/bin/logcatd -- u:object_r:logcat_exec:s0 /system/bin/sh -- u:object_r:shell_exec:s0 /system/bin/run-as -- u:object_r:runas_exec:s0 /system/bin/bootanimation u:object_r:bootanim_exec:s0 /system/bin/bootstat u:object_r:bootstat_exec:s0 /system/bin/app_process32 u:object_r:zygote_exec:s0 /system/bin/app_process64 u:object_r:zygote_exec:s0 /system/bin/servicemanager u:object_r:servicemanager_exec:s0 /system/bin/hwservicemanager u:object_r:hwservicemanager_exec:s0 /system/bin/surfaceflinger u:object_r:surfaceflinger_exec:s0 /system/bin/bufferhubd u:object_r:bufferhubd_exec:s0 /system/bin/performanced u:object_r:performanced_exec:s0 /system/bin/drmserver u:object_r:drmserver_exec:s0 /system/bin/dumpstate u:object_r:dumpstate_exec:s0 /system/bin/incident u:object_r:incident_exec:s0 /system/bin/incidentd u:object_r:incidentd_exec:s0 /system/bin/netutils-wrapper-1\.0 u:object_r:netutils_wrapper_exec:s0 /system/bin/vold u:object_r:vold_exec:s0 /system/bin/netd u:object_r:netd_exec:s0 /system/bin/wificond u:object_r:wificond_exec:s0 /system/bin/audioserver u:object_r:audioserver_exec:s0 /system/bin/mediadrmserver u:object_r:mediadrmserver_exec:s0 /system/bin/mediaserver u:object_r:mediaserver_exec:s0 /system/bin/mediametrics u:object_r:mediametrics_exec:s0 /system/bin/cameraserver u:object_r:cameraserver_exec:s0 /system/bin/mediaextractor u:object_r:mediaextractor_exec:s0 /system/bin/mdnsd u:object_r:mdnsd_exec:s0 /system/bin/installd u:object_r:installd_exec:s0 /system/bin/otapreopt_chroot u:object_r:otapreopt_chroot_exec:s0 /system/bin/otapreopt_slot u:object_r:otapreopt_slot_exec:s0 /system/bin/keystore u:object_r:keystore_exec:s0 /system/bin/fingerprintd u:object_r:fingerprintd_exec:s0 /system/bin/gatekeeperd u:object_r:gatekeeperd_exec:s0 /system/bin/crash_dump32 u:object_r:crash_dump_exec:s0
......
/system(/.*)?        u:object_r:system_file:s0 表明了在system目錄中的文件的安全上下文都是u:object_r:system_file:s0.
但是在之后,發現對system中的一些文件進行了詳細的安全上下文的定義。所以這些文件的安全上下文,由最后以單獨定義的安全上下文為主。
再看屬性上下文的定義,文件property_contexts的內容如下:
......
net.rmnet u:object_r:net_radio_prop:s0 net.gprs u:object_r:net_radio_prop:s0 net.ppp u:object_r:net_radio_prop:s0 net.qmi u:object_r:net_radio_prop:s0 net.lte u:object_r:net_radio_prop:s0 net.cdma u:object_r:net_radio_prop:s0 net.dns u:object_r:net_dns_prop:s0 sys.usb.config u:object_r:system_radio_prop:s0 ril. u:object_r:radio_prop:s0 ro.ril. u:object_r:radio_prop:s0 gsm. u:object_r:radio_prop:s0 persist.radio u:object_r:radio_prop:s0
......

 

由net.rmnet可以指定,只有能夠訪問類型為net_radio_prop的進程才能訪問這個屬性。
當在用戶空間完成策略的定義之后,還需要在系統開機的時候把它加載到內核的LMS模塊中,這主要是借助了libselinux來實現。
在src/system/core/init/init.cpp中可以看到
int main(int argc, char** argv) {
        ......
    if (is_fist_stage){
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);// Set up SELinux, loading the SELinux policy. selinux_initialize(true);
...... }

  return 0; }
在init的初始化的第一階段會做如下幾件事:
1.將selinux系統掛載在/sys/fs/selinux
2.調用selinux_initialize(true)對selinux策略進行初始化
selinux_initialize函數也是在init.cpp中定義,內容如下:
  
static void selinux_initialize(bool in_kernel_domain) {
    Timer t;

    selinux_callback cb;
    cb.func_log = selinux_klog_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    if (in_kernel_domain) {
        LOG(INFO) << "Loading SELinux policy";
        if (!selinux_load_policy()) {
            panic();
        }

        bool kernel_enforcing = (security_getenforce() == 1);
        bool is_enforcing = selinux_is_enforcing();
        if (kernel_enforcing != is_enforcing) {
            if (security_setenforce(is_enforcing)) {
                PLOG(ERROR) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
                security_failure();
            }
        }

        std::string err;
        if (!WriteFile("/sys/fs/selinux/checkreqprot", "0", &err)) {
            LOG(ERROR) << err;
            security_failure();
        }

        // init's first stage can't set properties, so pass the time to the second stage.
        setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
    } else {
        selinux_init_all_handles();
    }
}
 
        
1.首先是設置selinux回調
2.調用selinux_load_policy加載SELinux policy
3.設置selinux的模式。在開啟了selinux的系統中,通過getenforce可以看到系統中selinux的模式。有Enforcing和Permissive。Enforcing即為生效。
 permissive為即使違反了SELinux policy,只做提示但不拒絕。
selinux_load_policy函數同樣是在init.cpp中
static bool selinux_load_policy() {
    return selinux_is_split_policy_device() ? selinux_load_split_policy()
                                            : selinux_load_monolithic_policy();
}
 selinux_is_split_policy_device()同樣是在init.cpp中,這個函數主要是判斷"/system/etc/selinux/plat_sepolicy.cil"這個文件是否是可用的
可用時就會調用selinux_load_split_policy()否則調用selinux_load_monolithic_policy()。
先看selinux_load_split_policy()
static bool selinux_load_split_policy() {
    // IMPLEMENTATION NOTE: Split policy consists of three CIL files:
    // * platform -- policy needed due to logic contained in the system image,
    // * non-platform -- policy needed due to logic contained in the vendor image,
    // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
    //   with newer versions of platform policy.
    //
    // secilc is invoked to compile the above three policy files into a single monolithic policy
    // file. This file is then loaded into the kernel.

    // Load precompiled policy from vendor image, if a matching policy is found there. The policy
    // must match the platform policy on the system image.
    std::string precompiled_sepolicy_file;
    if (selinux_find_precompiled_split_policy(&precompiled_sepolicy_file)) {
        android::base::unique_fd fd(
            open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
        if (fd != -1) {
            if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
                LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
                return false;
            }
            return true;
        }
    }
    // No suitable precompiled policy could be loaded

    LOG(INFO) << "Compiling SELinux policy";

    // Determine the highest policy language version supported by the kernel
    set_selinuxmnt("/sys/fs/selinux");
    int max_policy_version = security_policyvers();
    if (max_policy_version == -1) {
        PLOG(ERROR) << "Failed to determine highest policy version supported by kernel";
        return false;
    }

    // We store the output of the compilation on /dev because this is the most convenient tmpfs
    // storage mount available this early in the boot sequence.
    char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
    android::base::unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
    if (compiled_sepolicy_fd < 0) {
        PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
        return false;
    }

    // Determine which mapping file to include
    std::string vend_plat_vers;
    if (!selinux_get_vendor_mapping_version(&vend_plat_vers)) {
        return false;
    }
    std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
    const std::string version_as_string = std::to_string(max_policy_version);

    // clang-format off
    const char* compile_args[] = {
        "/system/bin/secilc",
        plat_policy_cil_file,
        "-M", "true", "-G", "-N",
        // Target the highest policy language version supported by the kernel
        "-c", version_as_string.c_str(),
        mapping_file.c_str(),
        "/vendor/etc/selinux/nonplat_sepolicy.cil",
        "-o", compiled_sepolicy,
        // We don't care about file_contexts output by the compiler
        "-f", "/sys/fs/selinux/null",  // /dev/null is not yet available
        nullptr};
    // clang-format on

    if (!fork_execve_and_wait_for_completion(compile_args[0], (char**)compile_args, (char**)ENV)) {
        unlink(compiled_sepolicy);
        return false;
    }
    unlink(compiled_sepolicy);

    LOG(INFO) << "Loading compiled SELinux policy";
    if (selinux_android_load_policy_from_fd(compiled_sepolicy_fd, compiled_sepolicy) < 0) {
        LOG(ERROR) << "Failed to load SELinux policy from " << compiled_sepolicy;
        return false;
    }

    return true;
}

 

這個函數主要做三件事:
1.通過
selinux_find_precompiled_split_policy函數檢查系統中是否存在預編譯的CIL格式的策略文件。CIL格式的策略文件存在三種類型系統所要用的,
廠商要使用的和幫助廠商實現向前兼容。
2.如果已經存在預編譯好的策略文件就直接進行加載,如果不存在則調用secilc,對策略文件進行編譯。
3.獲取到策略文件后調用selinux_android_load_policy_from_fd函數將策略文件添加到內核的LSM中。這個函數是libselinux中的
在src/external/selinux/libselinux/src/android/android_platform.c中
int selinux_android_load_policy_from_fd(int fd, const char *description)
{
    int rc;
    struct stat sb;
    void *map = NULL;
    static int load_successful = 0;

    /*
     * Since updating policy at runtime has been abolished
     * we just check whether a policy has been loaded before
     * and return if this is the case.
     * There is no point in reloading policy.
     */
    if (load_successful){
      selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n");
      return 0;
    }

    set_selinuxmnt(SELINUXMNT);
    if (fstat(fd, &sb) < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
                description, strerror(errno));
        return -1;
    }
    map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (map == MAP_FAILED) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
                description, strerror(errno));
        return -1;
    }

    rc = security_load_policy(map, sb.st_size);
    if (rc < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not load policy:  %s\n",
                strerror(errno));
        munmap(map, sb.st_size);
        return -1;
    }

    munmap(map, sb.st_size);
    selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", description);
    load_successful = 1;
    return 0;
} 

該函數會將SEAndroid的策略添加到LSM中。

1.判斷之前是否加載過,如果加載過則不再加載

2.將策略文件添加到內存中

3.調用security_load_policy將安全策略添加到LSM中。security_load_policy在src/external/selinux/libselinux/src/load_policy.c

int security_load_policy(void *data, size_t len)
{
    char path[PATH_MAX];
    int fd, ret;

    if (!selinux_mnt) {
        errno = ENOENT;
        return -1;
    }

    snprintf(path, sizeof path, "%s/load", selinux_mnt);
    fd = open(path, O_RDWR | O_CLOEXEC);
    if (fd < 0)
        return -1;

    ret = write(fd, data, len);
    close(fd);
    if (ret < 0)
        return -1;
    return 0;
}

 

selinux_mnt最終的值為/sys/fs/selinux或者為/selinux.

判斷selinux_mnt是否存在,如果存在就打開該文件將安全策略寫入到該文件中。其實將安全策略加載到LSM中就是將安全策略寫入到該文件中,從此內核和selinux

的交互就是通過該文件。

再看selinux_load_monolithic_policy() 

static bool selinux_load_monolithic_policy() {
    LOG(VERBOSE) << "Loading SELinux policy from monolithic file";
    if (selinux_android_load_policy() < 0) {
        PLOG(ERROR) << "Failed to load monolithic SELinux policy";
        return false;
    }
    return true;
}

可以看到會調用selinux_android_load_policy(),該函數在src/external/selinux/libselinux/src/android/android_platform.c中

 

int selinux_android_load_policy()
{
    int fd = -1;

    fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
    if (fd < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not open %s:  %s\n",
                sepolicy_file, strerror(errno));
        return -1;
    }
    int ret = selinux_android_load_policy_from_fd(fd, sepolicy_file);
    close(fd);
    return ret;
}

 sepolicy_file的值為/sepolicy,該函數主要就是打開該文件,之后調用selinux_android_load_policy_from_fd這個函數。

2.Security Server

Security Server是用來保護用戶空間的資源和訪問內核空間對象的安全上下文的。它由應用程序安裝服務PackageManagerService,應用程序安裝守護進程

Installd,創建應用程序進程Zygote,以及init進程。

PackageManagerService和Installd負責創建app的數據目錄。在創建數據目錄時,PackageManagerService會根據包名或者簽名查詢mac_permission.xml文件

找到與之對應的seinfo,之后將seinfo傳遞給Installd,Installd根據libselinux提供的selable_lookup查詢seapp_contexts文件得到與之對應的類型,設置

該app數據目錄的安全上下文。

當ActivityManagerService向Zygote發出創建app進程的請求的時候,ActivityManagerService會去PackageManagerService找到對應的seinfo,並且將其傳遞

給Zygote,Zygote根據libselinux提供的setlabel_lookup找到對應的類型,設置該app進程的安全上下文。

在系統啟動的時候,init進程會維護一段內存空間存放系統屬性,並且啟動Property服務,Property提供Socket接口,供其他進程訪問系統屬性。當其他進程訪

問系統屬性的時候,Property會獲取到該進程的安全上下文,之后會去property_contexts,查詢該屬性的安全上下文,以此來判斷該進程是否可以訪問該屬性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM