安全策略的生成----SEAndroid in Android 5.x
2015-12-09 16:08
351 查看
android系统中第一个启动的进程是init进程,这个进程会执行系统初始化,其中就包括加载SEAndroid安全策略,查看文件system/core/init/init.c的main函数,其中有:
这里调用了两个与SEAndroid相关的函数:
1.selinux_set_callback,用来向libselinux设置SEAndroid日志和审计回调函数。该函数的实现在external/libselinux/src/callbacks.c文件中:
2.selinux_initialize(),查看这个函数的实现:
查看该函数调用到的其他函数:
selinux_init_all_handles(),这个函数在system/core/init/init.c文件中,它通过调用libselinux的函数来打开前面分析file_contexts和property_contexts文件,以便可以用来查询系统文件和系统属性的安全上下文。
selinux_android_load_policy,这个函数用来加载安全策略到内核空间的SELinuxLSM模块中,实现在external/libselinux/android.c中,查看这个函数的实现,并且将其中的常量的值标注出来(常量值定义在external/libselinx/src/policy.h中):
这个函数首先尝试以/sys/fs/selinux为安装点,安装SELinux文件系统,来和内核的LSM模块通信,如果失败,则将安装点改为/selinux。
安装系统安装完毕后,调用selinux_android_load_policy_helper()函数,将安全策略写入到LSM模块中。查看这个函数的实现:
函数open(sepolicy_file[policy_index], O_RDONLY |O_NOFOLLOW)的作用是查找sepolicy文件。按照sepolicy_file的定义:
函数会按照这个顺序查找sepolicy文件(在当前运行的版本中,该sepolicy文件在/sepolicy)。如果找不到,或者版本错误或disabled,则报错。如果找到,将文件的内容映射到内存当中,起始地址是map。然后,调用security_load_policy函数。这个函数的实现在external/libselinux/src/load_policy.c中:
selinux_mnt是一个全局变量,是SELinux文件系统的安装点。在当前系统中,它的值就等于/sys/fs/selinux。函数security_load_policy的实现很简单,它首先打开/sys/fs/selinux/load文件,然后将参数data所描述的安全策略写入到这个文件中去。由于/sys/fs/selinux是由内核空间的SELinuxLSM模块导出来的文件系统接口,因此当我们将安全策略写入到位于该文件系统中的load文件时,就相当于是将安全策略从用户空间加载到SELinuxLSM模块中去了。以后SELinux
LSM模块中的Security Server就可以通过它来进行安全检查。
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就可以通过它来进行安全检查。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories