安全策略的生成----SEAndroid in Android 5.x

android系统中第一个启动的进程是init进程,这个进程会执行系统初始化,其中就包括加载SEAndroid安全策略,查看文件system/core/init/init.c的main函数,其中有:
 
   unionselinux_callback cb;
    cb.func_log= log_callback;
   selinux_set_callback(SELINUX_CB_LOG, cb);

   cb.func_audit = audit_callback;
   selinux_set_callback(SELINUX_CB_AUDIT, cb);

   selinux_initialize();


            这里调用了两个与SEAndroid相关的函数:
1.selinux_set_callback,用来向libselinux设置SEAndroid日志和审计回调函数。该函数的实现在external/libselinux/src/callbacks.c文件中:
void
selinux_set_callback(int type, union selinux_callback cb)
{
    switch(type) {
    caseSELINUX_CB_LOG:
       selinux_log= cb.func_log;
       break;
    caseSELINUX_CB_AUDIT:
      selinux_audit = cb.func_audit;
       break;
    caseSELINUX_CB_VALIDATE:
      selinux_validate = cb.func_validate;
       break;
    caseSELINUX_CB_SETENFORCE:
      selinux_netlink_setenforce = cb.func_setenforce;
       break;
    caseSELINUX_CB_POLICYLOAD:
      selinux_netlink_policyload = cb.func_policyload;
       break;
    }
}



2.selinux_initialize(),查看这个函数的实现:
static void selinux_initialize(void)
{
    if(selinux_is_disabled()) {
       return;
    }

   INFO("loading selinux policy\n");
    if(selinux_android_load_policy()< 0){
       ERROR("SELinux: Failed to load policy; rebooting into recoverymode\n");
       android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
       while (1) { pause(); }  // never reached
    }

    selinux_init_all_handles();
    boolis_enforcing = selinux_is_enforcing();
   INFO("SELinux: security_setenforce(%d)\n", is_enforcing);
   security_setenforce(is_enforcing);
}


              查看该函数调用到的其他函数:
  • selinux_init_all_handles(),这个函数在system/core/init/init.c文件中,它通过调用libselinux的函数来打开前面分析file_contexts和property_contexts文件,以便可以用来查询系统文件和系统属性的安全上下文。 
      void selinux_init_all_handles(void)
{
    sehandle =selinux_android_file_context_handle();
   selinux_android_set_sehandle(sehandle);
   sehandle_prop = selinux_android_prop_context_handle();
}


  • selinux_android_load_policy,这个函数用来加载安全策略到内核空间的SELinuxLSM模块中,实现在external/libselinux/android.c中,查看这个函数的实现,并且将其中的常量的值标注出来(常量值定义在external/libselinx/src/policy.h中):
int selinux_android_load_policy(void)
{
    const char*mnt = SELINUXMNT;  //"/sys/fs/selinux"
    intrc;
    rc =mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); //"selinuxfs"
    if (rc <0) {
       if (errno ==ENODEV) {
         
          return-1;
       }
       if (errno ==ENOENT) {
         
          mnt =OLDSELINUXMNT;  //"/selinux"
          rc =mkdir(mnt, 0755);
          if (rc == -1&& errno != EEXIST) {
            selinux_log(SELINUX_ERROR,"SELinux:  Could notmkdir:  %s\n",
               strerror(errno));
             return-1;
          }
          rc =mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
       }
    }
    if (rc <0) {
      selinux_log(SELINUX_ERROR,"SELinux:  Could notmount selinuxfs:  %s\n",
            strerror(errno));
       return-1;
    }
   set_selinuxmnt(mnt);

    returnselinux_android_load_policy_helper(false);
}


            这个函数首先尝试以/sys/fs/selinux为安装点,安装SELinux文件系统,来和内核的LSM模块通信,如果失败,则将安装点改为/selinux。
            安装系统安装完毕后,调用selinux_android_load_policy_helper()函数,将安全策略写入到LSM模块中。查看这个函数的实现:
static int selinux_android_load_policy_helper(bool reload)
{
    int fd = -1,rc;
    struct statsb;
    void *map =NULL;

    if (reload&& !selinux_android_use_data_policy())
       return0;

    fd =open(sepolicy_file[policy_index], O_RDONLY |O_NOFOLLOW);
    if (fd <0) {
      selinux_log(SELINUX_ERROR, "SELinux:  Could notopen sepolicy:  %s\n",
            strerror(errno));
       return-1;
    }
    if(fstat(fd, &sb) < 0) {
      selinux_log(SELINUX_ERROR, "SELinux:  Could notstat %s:  %s\n",
            sepolicy_file[policy_index], strerror(errno));
      close(fd);
       return-1;
    }
    map =mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (map ==MAP_FAILED) {
      selinux_log(SELINUX_ERROR, "SELinux:  Could notmap %s:  %s\n",
         sepolicy_file[policy_index], strerror(errno));
      close(fd);
       return-1;
    }

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

    munmap(map,sb.st_size);
   close(fd);
   selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n",sepolicy_file[policy_index]);

    return0;
}

              函数open(sepolicy_file[policy_index], O_RDONLY |O_NOFOLLOW)的作用是查找sepolicy文件。按照sepolicy_file的定义:
static const char *const sepolicy_file[] = {
   "/sepolicy",
   "/data/security/current/sepolicy",
    NULL};

函数会按照这个顺序查找sepolicy文件(在当前运行的版本中,该sepolicy文件在/sepolicy)。如果找不到,或者版本错误或disabled,则报错。如果找到,将文件的内容映射到内存当中,起始地址是map。然后,调用security_load_policy函数。这个函数的实现在external/libselinux/src/load_policy.c中:
 
 int security_load_policy(void *data, size_tlen)
  {
         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);
         if (fd < 0)
                 return -1;
 
         ret = write(fd, data, len);
         close(fd);
         if (ret < 0)
                 return -1;
         return 0;
  }

        selinux_mnt是一个全局变量,是SELinux文件系统的安装点。在当前系统中,它的值就等于/sys/fs/selinux。函数security_load_policy的实现很简单,它首先打开/sys/fs/selinux/load文件,然后将参数data所描述的安全策略写入到这个文件中去。由于/sys/fs/selinux是由内核空间的SELinuxLSM模块导出来的文件系统接口,因此当我们将安全策略写入到位于该文件系统中的load文件时,就相当于是将安全策略从用户空间加载到SELinuxLSM模块中去了。以后SELinux LSM模块中的Security Server就可以通过它来进行安全检查。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值