深入理解SELinux SEAndroid(3最后部分)_restorecon lsetfileconon read-only file system-程序员宅基地

技术标签: Linux-Android 安全  

     深入理解SELinux SEAndroid(结局)

 

 

二  SEAndroid源码分析

有了上文的SELinux的基础知识,本节再来看看Google是如何在Android平台定制SELinux的。如前文所示,Android平台中的SELinuxSEAndroid

先来看SEAndroid安全策略文件的编译。

 

1.  编译sepolicy

Android平台中:

  • external/sepolicy:提供了Android平台中的安全策略源文件。同时,该目录下的tools还提供了诸如m4,checkpolicy等编译安全策略文件的工具。注意,这些工具运行于主机(即不是提供给Android系统使用的)
  • external/libselinux:提供了Android平台中的libselinux,供Android系统使用。
  • external/libsepol:提供了供安全策略文件编译时使用的一个工具checkcon

对我们而言,最重要的还是external/sepolicy。所以先来看它。

读者还记得上文提到的如何查看make命令的执行情况吗?通过:

mmm external/sepolicy  --just-print

,我们可以看到sepolicy编译时都干了些什么。

#以后用SEPOLICY_TEMP代替

#     out/target/product/generic/obj/ETC/sepolicy_intermediates字符串

 

#创建临时目录

mkdir -p out/target/product/generic/obj/ETC/sepolicy_intermediates/

 

#----->处理一堆输入源文件,最终输出为policy.conf

#执行m4命令,用来生成plicy.conf文件。m4命令将扩展SEAndroid定义的一些宏

m4 -D mls_num_sens=1 -D mls_num_cats=1024 -s

#m4的输入文件。下面标黑体的是SEAndroid一些系统相关的文件,一般不会修改它

security_classes   initial_sids access_vectors

global_macros mls_macros mls

policy_capabilities te_macros attributes

#Android系统中的te文件。

adbd.te app.te bluetoothd.te  bluetooth.te   clatd.te dbusd.te debuggerd.te device.te dhcp.te dnsmasq.te domain.te drmserver.te file.te gpsd.te hci_attach.te healthd.te hostapd.te init_shell.te init.te installd.te isolated_app.te kernel.te keystore.te media_app.te mediaserver.te mtp.te netd.te net.te nfc.te ping.te platform_app.te ppp.te property.te qemud.te racoon.te radio.te release_app.te rild.te runas.te sdcardd.te servicemanager.te shared_app.te shell.te surfaceflinger.te su.te system.te tee.te ueventd.te unconfined.te untrusted_app.te vold.te watchdogd.te wpa_supplicant.te zygote.te

#其他文件

roles  users initial_sid_contexts fs_use genfs_contexts port_contexts

#m4:将上述源文件处理完后,生成policy.conf

> SEPOLICY_TEMP/policy.conf

 

 

#下面这个命令将根据policy.conf中的内容,再生成一个policy.conf.dontaudit文件

sed '/dontaudit/d'

           SEPOLICY_TEMP/policy.conf >

           SEPOLICY_TEMP/policy.conf.dontaudit

 

mkdir -p SEPOLICY_TEMP/

#------>根据policy.conf文件,生成二进制文件。SEAndroid中,它叫sepolicy

#执行checkpolicy,输入是policy.conf,输出是sepolicy

#-M选项表示支持MLS

checkpolicy -M -c 26 -o SEPOLICY_TEMP/sepolicy

                             SEPOLICY_TEMP/policy.conf

#执行checkpolicy,输入是policy.conf.dontaudit,输出是sepolicy.dontaudit

checkpolicy -M -c 26 -o

            SEPOLICY_TEMP/sepolicy.dontaudit    

           SEPOLICY_TEMP/policy.conf.dontaudit

 

#--->将sepolicy拷贝到对应目标平台的root目录下

echo "Install: out/target/product/generic/root/sepolicy"

acp -fp SEPOLICY_TEMP/sepolicy

                  out/target/product/generic/root/sepolicy

 

#---->生成file_context文件

#用FILE_CONTEXT_TEMP代替

#    out/target/product/generic/obj/ETC/file_contexts_intermediates字符串

mkdir -p FILE_CONTEXT_TEMP/

m4 -s  external/sepolicy/file_contexts  > FILE_CONTEXT_TEMP/file_contexts

checkfc  SEPOLICY_TEMP/sepolicy

                  FILE_CONTEXT_TEMP/file_contexts

echo "Install: out/target/product/generic/root/file_contexts"

acp -fp FILE_CONTEXT_TEMP/file_contexts

                     out/target/product/generic/root/file_contexts

 

#--->生成seapp_context文件,这个是Android平台特有的,其作用我们下文再介绍

#用SEAPP_CONTEXT_TEMP代替

#     out/target/product/generic/obj/ETC/seapp_contexts_intermediates

mkdir -p SEAPP_CONTEXT_TEMP/

checkseapp -p SEPOLICY_TEMP /sepolicy

-o SEAPP_CONTEXT_TEMP/seapp_contexts SEAPP_CONTEXT_TEMP/seapp_contexts.tmp

echo "Install: out/target/product/generic/root/seapp_contexts"

acp -fp SEAPP_CONTEXT_TEMP/seapp_contexts

                        out/target/product/generic/root/seapp_contexts

 

#---->和Android平台中的属性相关。SEAndroid中,设置属性也需要相关权限

#用PROPERTY_CONTEXT_TMP代替:

#         out/target/product/generic/obj/ETC/property_contexts_intermediates

mkdir -p PROPERTY_CONTEXT_TMP/

m4 -s  external/sepolicy/property_contexts  >

                         PROPERTY_CONTEXT_TMP/property_contexts

checkfc -p TARGET_SEPOLICY_TEMP/sepolicy

               PROPERTY_CONTEXT_TMP/property_contexts

echo "Install: out/target/product/generic/root/property_contexts"

acp -fp PROPERTY_CONTEXT_TMP/property_contexts

                      out/target/product/generic/root/property_contexts

上面展示了sepolicy编译的执行情况,读者最好自己尝试一下。注意,checkfccheckseapp等都是SEAndroid编译时使用的工具,它们用来做策略检查,看看是否有规则不符合的地方。

总结:

  • sepolicy的重头工作是编译sepolicy安全策略文件。这个文件来源于众多的te文件,初始化相关的文件(initial_sid,initial_sid_context,users,roles,fs_context等)。
  • file_context:该文件记载了不同目录的初始化SContext,所以它和死货打标签有关。
  • seapp_context:和Android中的应用程序打标签有关。
  • property_contexts:和Android系统中的属性服务(property_service)有关,它为各种不同的属性打标签。

下面我们来看看和SEAndroid相关的代码,故事从init开始。

2.  initSEAndroid定制

Android平台中,SEAndroid的初始化由进程的祖先initmain函数完成,相关代码如下所示:

[-->init.c:main]

 

  process_kernel_cmdline();

  //向SELinux设置两个回调函数,主要是打印log

 union selinux_callback cb;

 cb.func_log = klog_write;

 selinux_set_callback(SELINUX_CB_LOG, cb);

  cb.func_audit = audit_callback;

  //selinux_set_callback由libselinux提供。读者可google libselinux各个API

  //的作用

  selinux_set_callback(SELINUX_CB_AUDIT, cb);

   //①初始化SEAndroid

    selinux_initialize(); 

   //②给下面几个目录打标签!

   restorecon("/dev"); 

   restorecon("/dev/socket");

   restorecon("/dev/__properties__");

   restorecon_recursive("/sys");

上述代码中的两个重要函数:

  • selinux_initialize:初始化SEAndroid
  • 一堆的restoercon,全称应该是restore context:就是根据file_contexts中的内容给一些目录打标签。

先来看selinux_initialize

2.1  selinux_initialize分析

[-->init.c:: selinux_initialize]

static void selinux_initialize(void)

{

   /*判断selinux功能是否启用。方法是:

   1) /sys/fs/selinux 是否存在。或者

   2)  ro.boot.selinux 属性不为disabled

  */

   if (selinux_is_disabled()) return;

 

      //加载sepolicy文件

    if (selinux_android_load_policy() < 0) {......}

 

    selinux_init_all_handles();

   /*selinux有两种工作模式

    “permissive”:所有操作都被允许(即没有MAC),但是如果有违反权限的话,会记录日志

    “enforcing”:所有操作都会进行权限检查

    */

    bool is_enforcing = selinux_is_enforcing();

    //设置SELinux的模式

    security_setenforce(is_enforcing);

}

来看上述代码中的两个函数:

  • selinux_android_load_policy:加载sepolicy文件。
  • selinux_init_all_handles:初始化file_contextseapp_contextproperty_context相关内容。
(1)  selinux_android_load_policy

来看selinux_android_load_policy,其代码如下所示:

[-->external/libselinux/src/android.c:: selinux_android_load_policy]

int selinux_android_load_policy(void)

{

    char *mnt = SELINUXMNT;// 值为/sys/fs/selinux

    int rc;//挂载/sys/fs/selinux,SELINUXFS值为"selinuxfs"

    rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);

     ......

    // /sys/fs/selinux为userpace和kernel中的SELinux模块交互的通道

    set_selinuxmnt(mnt);//此函数定义在selinux.h中,属于libselinux API.

 

    return selinux_android_reload_policy(); //加载SEAndroid中的policy文件

}

11展示了Nexus 7/sys/fs/selinux的内容:

11  /sys/fs/selinux的内容

用户空间进程可同读写/sys/fs/selinux的各个文件或其中的子目录来通知Kernel中的SELinux完成相关的操作。

我们此处此处举一个例子,如图11下方红框中的booleans文件夹:

  • 我们可以SELinux的安全配置文件中写一些类似if/else的语句。if中的是布尔判断条件。比如booleans文件夹下有一个in_qemu文件,这个就是sepolicy安全配置文件中的一个布尔变量。in_qemu定义在domain.te文件中,关键词是bool
  • cat booleans/in_qemu:打印in_qemu布尔变量的取值。读者会发现它的值为“0 0”。为什么有两个零呢,这第一个0是它的当前值,第二个零代表pending取值。即还没有赋值给当前值的一个中间变量。如果我们通过 echo "1" > booleans/in_qemu的话,第二个零将变成1
  • 为什么需要有中间变量呢?读者注意图11的右上方有一个commit_pending_bools文件。原来,通过在布尔变量中设置一个pending变量,我们可以实现批处理操作。即先修改1个或多个布尔变量的pending变量,然后往commit_pending_bools1,这样这些一个或多个的布尔变量将使用pending变量取代当前值。

接下来看看selinux_android_reload_policy函数:

 [-->external/libselinux/src/android.c:: selinux_android_reload_policy]

int selinux_android_reload_policy(void)

{

    int fd = -1, rc;  struct stat sb;   void *map = NULL;

    int i = 0;

   // sepolicy_file指明sepolicy文件的路径。Android中有两处,第一个是

  // /data/security/current/sepolicy。第二个是root目录下的sepolicy文件。

  //下面这段逻辑可知,SEAndroid只使用其中的一个,如果/data/目录下有sepolicy文件,则

  //优先使用它

    while (fd < 0 && sepolicy_file[i]) {

        fd = open(sepolicy_file[i], O_RDONLY | O_NOFOLLOW);

        i++;

    }

    ......

    map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

    ......

   //假设使用根目录下的sepolicy文件。下面这个函数由selinux.h定义,它将此文件加载到

   //内核中

    rc = security_load_policy(map, sb.st_size);

    ......

    munmap(map, sb.st_size);

    close(fd);

     return 0;

}

init通过mmap的方式,将sepolicy文件传递给了kernelinit使用了libselinux提供的API函数来完成相关操作。而libselinux则是通过操作/sys/fs/selinux下的文件来完成和KernelSELinux模块的交互。libselinux库的API不是我们研究的重点,感兴趣的兄弟请自己研究源码。

总之,selinux_android_load_policy干得最重要的一件事情就是将sepolicy文件传递给Kernel,这样Kernel就有了安全策略配置文件,后续的MAC才能开展起来。

在此,请读者注意sepolicy文件的位置:

  • 首先查看/data/security/current/sepolicy:笔者自定义的策略文件一般放在这里,init优先使用它。
  • /sepolicyroot根目录下的sepolicy,如果data目录下没有sepolicy,则使用它。系统默认的sepolicy在此。
(2)  selinux_init_all_handles

前面讲过,init要给一些死货和property打标签,为了完成这个工作,根据libselinuxAPIinit需要先创建两个handler,代码在selinux_init_all_handles中:

[-->init.c:: selinux_init_all_handles]

void selinux_init_all_handles(void)

{

    sehandle = selinux_android_file_context_handle();

    sehandle_prop = selinux_android_prop_context_handle();

}

创建两个handler,主要为后续做labeling控制。我们来看看propcontext

[-->init.c::selinux_android_prop_context_handle]

struct selabel_handle* selinux_android_prop_context_handle(void)

{

    int i = 0;

    struct selabel_handle* sehandle = NULL;

   //setopts_prop也有两个值:

   //第一个是/data/security/property_contexts。第二个是/property_contexts

    while ((sehandle == NULL) && seopts_prop[i].value) {

        sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, &seopts_prop[i], 1);

        i++;

    }

  //假设采用的是根目录下的property_context文件

  ......

  return sehandle;

}

handler其实就是为了打开xxx_context文件。由于它们和restorecon有关,下面直接来看restorecon函数,看看这些handler是怎么个用法。

2.2  restorecon分析

[-->init.c::restorecon]

int restorecon(const char *pathname)

{

    char *secontext = NULL;

    struct stat sb;

    int i;

 

    if (is_selinux_enabled() <= 0 || !sehandle)

        return 0;

 

    if (lstat(pathname, &sb) < 0)   return -errno;

    //查找file_context文件中是否包含有pathname路径的控制选项

    if (selabel_lookup(sehandle, &secontext, pathname, sb.st_mode) < 0)

        return -errno;

   //设置patchname目录的security_context,lsetfilecon的实现非常简单,就是调用

   //

    if (lsetfilecon(pathname, secontext) < 0) {

        freecon(secontext);

        return -errno;

    }

    freecon(secontext);

    return 0;

}

想知道selinux是如何labeling一个文件或目录的吗?答案在lsetfilecon中:

[-->external/libselinux/src/lsetfilecon.c:: lsetfilecon]

int lsetfilecon(const char *path, const security_context_t context)

{

 //设置文件系统的属性

 return lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,0);

}

2.3  property权限检查

一般而言,SELinux权限检查都是由kernel来完成的,不过对于Android平台中的Property而言,这却完全是一个用户空间的内容。所以,我们看看init是如何使用libselinux来完成用户空间的权限检查的。

每当其他进程通过setprop函数设置属性时,property_service中有一个叫check_

[system/core/init/property_service.c:: check_mac_perms]

static int check_mac_perms(const char *name, char *sctx)

{

    if (is_selinux_enabled() <= 0)  return 1;

 

    char *tctx = NULL;

    const char *class = "property_service";

    const char *perm = "set";

    int result = 0;

    ......

    //检查property_context中是否定义了目标SContext,即tctx。

    if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0) goto err;

   //将源SContext和目标SContext进行比较,判断是否有相关权限。name是属性的名字

   //源SContext是调用setprop进程的SContext。目标SContext是property_context

   //文件中定义的SContext。

    if (selinux_check_access(sctx, tctx, class, perm, name) == 0)

        result = 1;

    freecon(tctx);

 err:

    return result;

}

怎么样?理解起来并不困难吧?用户空间的权限检查主要就是通过selinux_check_access完成,其输入参数包括:

  • 源的SContext:它就是调用setprop的进程的SContext
  • 目标的SContext:不同的属性有不同的SContext,这是在property_context中定义的。
  • 要检查的Object class(系统所支持的类在external/sepolicy/security_classes文件中定义)。
  • 操作名称(perm,由access vector定义。对Property这种Object class而言,其唯一需要做权限检查的操作就是set。读者可参考external/sepolicy/access_vectors这个文件)。

具体的哪一个属性(name参数指定,就是具体指明哪一文件)。

提示:关于这些API的说明,读者请参考http://selinuxproject.org/page/User_Resources中的Manual pages文档。

下面我们来看Android中应用程序是如何使用SELinux的。

3.  应用程序中的SELinux

对应用程序而言,最重要的工作就是管理它们的DTTT

  • 所有AndroidApplication对应的进程都是从zygote进程中fork出来的。从前文介绍DT的知识可知,在做DT时,可以根据所执行的不同Type的文件来转换到不同的DT。但这个对Android而言不可行。因为zygotefork子进程后,并没有执行execv
  • apk在安装后,都会在/data/data/目录下建立自己对于的文件夹,这个工作是由installd来完成的。同样,installd应该给这些不同的文件夹打上对应的label

我们先来看应用程序的DT

3.1  Java应用程序的DT

Android中应用进程(就是APK所在的进程)的DT转换其实很简单,它及其具有Android特色:

  • 普通的DT是根据所execv文件的Type来设置DT转换条件。
  • Android中则根据该APK签名信息来讲最终的进程转换到几种预设值的Domain中。
(1)  mac_permissions.xml的用途

我们先来看PackageManagerService

[-->PackageManagerService.java::PackageManageService]

......

/*下面这个函数将尝试解析

 1)/data/security/mac_permissions.xml 或

 2)/system/etc/security/mac_permissions.xml 中的内容。

*/

mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();

注意,mac_permissions.xml位于external/sepolicy中,图12所示为该文件的原始:

12  mac_permissions.xml的内容

在系统过程中,图12中的@RELEASE@PLATFORM等内容会被RELEASEPLATFORM签名信息替换。图13所示为Nexus 7中该文件的内容。

13  Nexus7mac_permissions.xml内容

mac_permissions.xml保存了不同签名所对应的seinfo:如seinfoplatform时的签名是什么,seinfomedia的时候签名又是什么。那么,这些信息有啥用呢?来看下文。

(2)  扫描APK

APK安装时,也就是APKPKMGS扫描的时候,有如下的代码:

[-->PackageManagerService.java::ScanPackageLI]

if (mFoundPolicyFile) {

     //下面这个函数将根据签名信息赋值seinfo值给对应的apk

     SELinuxMMAC.assignSeinfoValue(pkg);

   }

[-->SELinuxMMAC.java::assignSeinfoValue]

public static void assignSeinfoValue(PackageParser.Package pkg) {

 

     //对于系统app(预装的,位于system目录下的)

     if (((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ||

          ((pkg.applicationInfo.flags &

                         ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {

   

        for (Signature s : pkg.mSignatures) {

                if (s == null)  continue;

              //sSigSeinfo存储了mac_permissions.xml中seinfo标签的内容

              if (sSigSeinfo.containsKey(s)) {

                    String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s);

                    return;

                }

            }

            //sPackageSeinfo存储了xml中package标签下seinfo子标签的内容

            if (sPackageSeinfo.containsKey(pkg.packageName)) {

                String seinfo = pkg.applicationInfo.seinfo =

                              sPackageSeinfo.get(pkg.packageName);

                 return;

            }

        }

        //default标签中seinfo的值

        String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null);

        ......

  }

assignSeinfoValue的功能如上代码所示,它根据apk的签名信息来赋值不同的seinfo,也就是诸如"platform",”media“之类的值。

提示:大家能想出为什么要设置seinfo吗?恩,它就是AndroidApp定义的SContext中的Domain的值。

(3)  App的DT转换

ActivityManagerService负责启动目标应用进程,相关代码如下所示:

[-->ActivityManagerService.java:: startProcessLocked]

Process.ProcessStartResult startResult =

                     Process.start("android.app.ActivityThread",

                    app.processName, uid, uid, gids, debugFlags, mountExternal,

                    app.info.targetSdkVersion, app.info.seinfo, null);

根据《深入理解AndroidI》第4章对zygote的介绍,zygote进程将fork一个子进程,相关函数在:

[-->ZygoteConnection.java::runOnce]

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,

                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal,

                    parsedArgs.seInfo,parsedArgs.niceName);

该函数由JNI实现,代码在dalvik/vm/native/ dalvik_system_Zygote.cpp中,其中最重要的是内部所调用的forkAndSpecializeCommon

[-->dalvik_system_Zygote.cpp:: forkAndSpecializeCommon]

pid = fork();

if (pid == 0) {

  ......

    err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);

  .....}

 

[-->external/libselinux/android.c::selinux_android_setcontext]

int selinux_android_setcontext(uid_t uid,int isSystemServer,

                   const char *seinfo,const char *pkgname)

{

    char *orig_ctx_str = NULL, *ctx_str;  context_t ctx = NULL;

    int rc = -1;

    if (is_selinux_enabled() <= 0)  return 0;

   

    //重要函数:seapp_context_init,内部将调用selinux_android_seapp_context_reload

   //以加载seapp_contexts文件。

   // 1) /data/security/current/seapp_contexts 或者

   // 2) /seapp_contexts   本例而言,就是根目录下的这个seapp_context文件

    __selinux_once(once, seapp_context_init);

   

    rc = getcon(&ctx_str);

    ctx = context_new(ctx_str);

    orig_ctx_str = ctx_str;

    //从zygote进程fork出来后,最初的SContext取值为u:r:zygote:s0

   //下面这个函数将根据uid,pkgname等设置最终的SC。例如u:r:system_app:s0等

    rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname,

     ctx);

   ctx_str = context_str(ctx);

   rc = security_check_context(ctx_str);

   if (strcmp(ctx_str, orig_ctx_str)) {

        rc = setcon(ctx_str);

    }

 

    rc = 0;

    ......

    return rc;

}

14所示为seapp_context的内容,非常简单:

14  seapp_context内容

上面代码中的seapp_context_lookup将根据图14的内容,通过不同的apk所对应的seinfo,找到他们的目标domain,然后再设置为它们新的SContext。例如图15Nexus 7ps -Z的结果图。

15  ps -Z查看apk进程的SContext

seapp_context_lookup是完成从seapp_context文件内容映射到具体对应为哪个Domain的关键函数,该函数第一次看起来吓死人,其实蛮简单。这里就不再多说。

anywaySEAndroid中,不同应用程序将根据它们的签名信息得到对应的SContext(主要是DomainMLS其实没用上,但以后可以用上,这是通过图14中的levelFrom语句来控制的,具体可参考seapp_context_lookup的实现)。

DT完成后,我们看系统如何为它们的对应文件夹打标签

3.2  App data目录的TT

还是在PackageManagerServicescanPackageLI函数中,

[-->PackageManagerService.java:: scanPackageLI]

int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,

                                           pkg.applicationInfo.seinfo);

createDataDirsLI最终会调用installd实现的函数:

[-->installd/commands.c::install]

//内部调用selinux_android_setfilecon2,它和上文的selinux_android_setcontext

//几乎一样。最终它将设置pkgdir的SContext。注意,它主要根据seapp_context文件中的

//type字段来确定最终的Type值。

if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) {

     ......

 }

16展示了ls -Z /data/data目录下的结果。

16  /data/data目录下ls -Z的结果

是不是和图14seapp_context文件的type字段描述一样一样的?

 

4  小试牛刀

下面,笔者将通过修改shell的权限,使其无法设置属性。

先来看shellte,如下所示:

[external/sepolicy/shell.te]

# Domain for shell processes spawned by ADB

type shell, domain;

type shell_exec, file_type;

#shell属于unconfined_domain,unconfined即是不受限制的意思

unconfined_domain(shell)

 

# Run app_process.

# XXX Split into its own domain?

app_domain(shell)

unconfied_domain是一个宏,它将shell和如下两个attribute相关联:

[external/sepolicy/te_macros]

#####################################

# unconfined_domain(domain)

# Allow the specified domain to do anything.

#

define(`unconfined_domain', `

typeattribute $1 mlstrustedsubject; #这个和MLS有关

typeattribute $1 unconfineddomain;

')

unconfineddomain权限很多,它的allow语句定义在unconfined.te中:

[external/sepolicy/unconfined.te]

......

allow unconfineddomain property_type:property_service set;

从上面可以看出,shell所关联的unconfineddomain有权限设置属性。所以,我们把它改成:

allow {unconfineddomain -shell} property_type:property_service set;

通过一个“-”号,将shell的权限排除。

然后:

  • 我们mmm external/sepolicy,得到sepolicy文件。
  • 将其push/data/security/current/sepolicy目录下
  • 接着调用setprop selinux.reload_policy 1,使得init重新加载sepolicy,由于/data目录下有了sepolicy,所以它将使用这个新的。

17所示为整个测试的例子:

17  测试结果

根据图17

  • 重新加载sepolicy之前,笔者可通过"setprop wlan.driver.status test_ok"设置该属性的值为test_ok。注意,这个值笔者瞎设的。
  • 当通过setprop selinux.reload_policy 1的命令后,init重新加载了sepolicy
  • 从此,笔者再setprop wlan.driver.status 都不能修改该属性的值。

18所示为dmesg输出,可以看出,当selinux使用了data目录下这个新的sepolicy后,shellsetprop权限就被否了!

18  dmesg输出

提示:前面曾提到过audit,日志一类的事情。恩,这个日志由kernel输出,可借助诸如audit2allowhost上的工具查看哪些地方有违反权限的地方。系统会将源,目标SContext等信息都打印出来。

 

  全文总结

本文对SELinux的核心知识进行了介绍。从入门角度来说,有了这些内容,SELinux大概80%左右的知识都已经介绍,剩下来的工作就是不断去修改和尝试不同的安全配置文件。

然后我们对SEAndroid进行了相关介绍,这部分基本上反映了Android是如何利用这些安全配置文件来构造自己的安全环境的。

从目前AOSP SEAndroid安全配置源文件来看,很多te文件中都使用了如下这样的语句:

19  permissive定义

其中,permissive关键词表示不用对上述这些type/domain进行MAC监管。permissive一般用于测试某个策略,看是否对整个系统有影响。一旦测验通过,就可以把permissve语句移掉,以真正提升安全。

基于SEAndroid,广大搞机人可以:

  • 针对行业,开发更加安全的安全策略。
  • 定制MLS,针对企业级或军用级的多层权限管理。
  • 不知道google有没有意向实现Modular Policy,这样的话,SELinux灵活性更高。

另外,要提醒读者的是,安全配置需要考虑的东西非常多,稍有不甚,就会影响系统其他模块的运行。比如笔者在研究SELinux时,不小心把Ubuntu的图像界面系统启动不了,后来只能移除SELinux后才解决。这也是为什么SELinux出来这么多年,但是大家好像碰到它的机会很少的原因,因为它的配置实在是太麻烦,很容易出错!

最后,反复提醒读者,一旦修改了策略文件,务必进行全方位,多层面测试。

关于SEAndroid的更多官方说明,请参考

http://source.android.com/devices/tech/security/se-linux.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhuxiaoping54532/article/details/51753546

智能推荐

[大海战] Freepascal之Crt单元-程序员宅基地

文章浏览阅读135次。{这是我的首个一千行程序所以很多地方有冗余 不是很成熟况且程序上了千行用譬如Freepascal 等等这类的面向过程的平台就力不从心了Delphi7以前用过 不是很会用凭着对Crt单元的好奇 我写了这个小游戏}先给代码 可以直接copy走http://files.cnblogs.com/Booble/D_Game_CRT.rar可以先试试用用具体..._{$m $4000,0,0} uses dos,crt;

Tcpdump详解linux tcpdump抓包分析工具_tcpdump自动分包-程序员宅基地

文章浏览阅读1.2k次。Tcpdump详解实用命令实例默认启动tcpdump普通情况下,直接启动tcpdump将监视第一个网络接口上所有流过的数据包。 监视指定网络接口的数据包tcpdump -i eth1如果不指定网卡,默认tcpdump只会监视第一个网络接口,一般是eth0,下面的例子都没有指定网络接口。  监视指定主机的数据包打印所有进入或离开sundown的数据包._tcpdump自动分包

单片机GPRS模块与web端通信_web远程通信单片机-程序员宅基地

文章浏览阅读1.7k次,点赞7次,收藏22次。最近开搞毕设,拿起了单片机,因为最近实习一直在前端和gis,所以就想弄个gps和web端地图的交互软件。 说在前面--这里都是简单的东西,大神轻喷。用的是STM32芯片和MC20开发板,这个开发板上有GPS北斗模组,GPRS模组,图个方便,就直接选一个现成的,不用自己画板子焊板子了,如果大家对,单片机的源码感兴趣,私聊我,我私发给你们。最终就是把GPS获取的信息解析出经纬度信息,然后通过GPRS模组发送到自己搭建的服务器上。GPRS模组走的是TCP协议,而web端是HTTP协议,这时候就开始疯._web远程通信单片机

Java IO: Input Parsing_inputparser-程序员宅基地

文章浏览阅读586次。原文连接:http://tutorials.jenkov.com/java-io/input-parsing.html ,并发编程网有更多该作者关于java IO 的译文:http://ifeve.com/java-io在Java IO API中有设计一些类用来帮助你解析 input。这些类包括:1. PusbackInputStream 2. PusbackReader 3. Stream_inputparser

PhalApi-Xhprof -- Facebook开源的轻量级PHP性能分析工具_phalapi 性能-程序员宅基地

文章浏览阅读982次。PhalApi-Xhprof – Facebook开源的轻量级PHP性能分析工具前言Facebook开源的轻量级PHP性能分析工具,非常爽希望大家喜欢附上:官网地址:http://www.phalapi.net/开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release开源中国拓展Git地址:http://git.oschina.net_phalapi 性能

Android:content uri转 file uri_content uri 转 file-程序员宅基地

文章浏览阅读5k次。Android:content uri转 file uri在android开发中我们在处理一图片时,经常需要将android uri如content://media/external/image/media/102这样格式转换成File类型或者获取真实文件路径。网上有不少示例代码,但是我看到的都是只支持英文的,如果路径中含中文,会出现空指针异常:网上的代码:Uri uri = _content uri 转 file

随便推点

字节跳动面试官问:微服务下如何保证分布式事务的最终一致性?-程序员宅基地

文章浏览阅读765次。提起「微服务架构」,有两个永恒话题:服务治理、分布式事务。数据库和业务模块的垂直拆分为我们带来了系统性能、稳定性和开发效率的提升的同时也引入了一些更复杂的问题,例如在数据一致性问题上,我们..._微服务中分布式事务用什么保证强一致性

微信小程序中navigator无法跳转的问题_微信浏览器 window.navigator 获取不到-程序员宅基地

文章浏览阅读1.7w次,点赞7次,收藏7次。 本来写的navigator语句正确,可页面就是无法跳转,百度过后才找到了问题所在,特地总结如下:出现这种情况可能有三种问题:1.跳转的页面没有在app.json页面中注册。如果是这种问题会在控制台弹出错误,留意控制台即可;2.跳转的路径不正确。初学时不太注意会出现这种问题,这种问题同样会在控制台弹出错误。3.跳转的页面位于TabBar中。这种情况不会在控制台弹出错误,需要自己去检查..._微信浏览器 window.navigator 获取不到

linuxpgrepgrep_linux命令详解:pgrep命令-程序员宅基地

文章浏览阅读494次。前言经常要查看进程的信息,包括进程的是否已经消亡,通过pgrep来获得正在被调度的进程的相关信息。pgrep通过匹配其程序名,找到匹配的进程重要选项-l 同时显示进程名和PID-o 当匹配多个进程时,显示进程号最小的那个-n 当匹配多个进程时,显示进程号最大的那个注:进程号越大,并不一定意味着进程的启动时间越晚使用说明查看指定名称的进程信息默认只显示PID[root@master~]#pgre..._grep $(pgrep -f $pwd)

企业微信Api-程序员宅基地

文章浏览阅读321次。https://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F

0c400汇编语言地址,DS80C400的Keil C语言编程.doc-程序员宅基地

文章浏览阅读100次。DS80C400的Keil C语言编程摘要:在设计DS80C400网络微控制器的ROM时,一组功能被公开出来,可以在8051汇编、C或Java?程序中访问。DS80C400的ROM可以被视作一个构建C或汇编程序的起跑架,它提供TINI?经过验证的网栈、进程调度器和存储器管理器。简单程序,如网络扬声器,可以用汇编语言轻松实现,更复杂一点的,如HTTP服务器这种需要与文件系统交互的程序,可以使用C语言..._keil 中 far memory type support

查看SHA1-程序员宅基地

文章浏览阅读1.7k次。一.SHA1查看1、打开android studio 在最下面找到Terminal 如下图2、 输入命令 C: 进入c盘3、 输入命令 cd Users\Administrator 其中Administrator是自己的用户名 Administrator文件下有个.adnroid文件4、 输入命令 cd .android 如下图5、输入命令 keytool ..._查看sha1

推荐文章

热门文章

相关标签