Android10系统定制开发之修改安卓源码关闭selinux
The following article is from 卓码空间 Author QDroid88888
一、seandroid简介
/home/qiang/lineageOs/system/sepolicy
C:\Users\Qiang>adb shell ls -la /sys/class/net/wlan0/address
-r--r--r-- 1 root root 4096 2021-01-12 14:57 /sys/class/net/wlan0/address
二、安卓中关闭seandroid的方式讨论
1.使用setenforce命令临时关闭
命令如下
adb shell setenforce 0
setenforce命令只能暂时关闭seandroid,如果手机重启了会被恢复为正常状态。
setenforce在安卓源码中的路径如下:
external/toybox/toys/android/setenforce.c
setenforce实现代码如下:
#define FOR_setenforce
#include "toys.h"
void setenforce_main(void)
{
char *new = *toys.optargs;
int state, ret;
if (!is_selinux_enabled()) error_exit("SELinux is disabled");
else if (!strcmp(new, "1") || !strcasecmp(new, "enforcing")) state = 1;
else if (!strcmp(new, "0") || !strcasecmp(new, "permissive")) state = 0;
else error_exit("Invalid state: %s", new);
ret = security_setenforce(state);
if (ret == -1) perror_msg("Couldn't set enforcing status to '%s'", new);
}
从以上代码可知,setenforce最终调用的是函数security_setenforce完成selinux的控制。
2.在kernel 关闭 selinux
在内核中配置SECURITY_SELINUX设置为 false,重新编译kernel刷机。可以永久关闭seandroid。
以下是测试的内核编译中.config文件中关闭selinux之后的配置信息:
CONFIG_SECURITY_SELINUX=n
3.在init进程启动的时候关闭selinux
安卓系统启动过程中,init进程会进行selinux的初始化。通过读取/proc/cmdline文件,判断androidboot.selinux的值是否需要开启selinux。因此,我们可以init进程初始化selinux的时候强制执行关闭操作。
以下将讨论第三种方案来实现全局关闭selinux。
三、init进程中全局关闭selinux
1.init进程中selinux的初始化流程分析
init进程中selinux初始化相关的文件路径如下:
system/core/init/selinux.cpp
system/core/init/main.cpp
大概的初始化流程如下:
a. main.cpp中的main函数调用selinux.cpp中的SetupSelinux:
int main(int argc, char** argv) {
...省略
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
...省略
}
b. selinux.cpp中SetupSelinux函数实现如下:
int SetupSelinux(char** argv) {
...省略
SelinuxInitialize();
...省略
return 1;
}
c. SetupSelinux调用了SelinuxInitialize方法。SelinuxInitialize方法代码如下:
//SelinuxInitialize 中可以看到调用了IsEnforcing方法判断
void SelinuxInitialize() {
...省略
bool kernel_enforcing = (security_getenforce() == 1);
//判断是否强制模式
bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) {
//调用security_setenforce函数,和setenforce原理一样
if (security_setenforce(is_enforcing)) {
PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
}
}
...省略
}
d.IsEnforcing方法实现如下:
//判断是否需要强制模式
bool IsEnforcing() {
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
从IsEnforcing中可以知道,如果一直返回false,那么将会关闭selinux。
2.全局强制关闭selinux修改
从以上init进程初始化selinux的流程可以提供两种修改方案来全局关闭。
第一种修改IsEnforcing函数永远返回false。 修改如下:
bool IsEnforcing() {
///ADD START
if(1>0)
{
//一直返回false
return false;
}
///ADD END
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
第二种修改SelinuxInitialize方法,在函数中主动调用security_setenforce(false)。修改之后如下:
void SelinuxInitialize() {
Timer t;
LOG(INFO) << "Loading SELinux policy";
if (!LoadPolicy()) {
LOG(FATAL) << "Unable to load SELinux policy";
}
bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) {
PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
}
}
//直接调用security_setenforce方法来关闭
///ADD START
security_setenforce(false);
///ADD END
if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
}
// 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);
}
修改之后编译源码刷机,开机之后生效。
玩转Android10系统源码开发定制更多文章:
玩转Android10源码开发定制(二)刷机操作之fastboot刷机演示
玩转Android10源码开发定制(二)刷机操作之Recovery刷机演示
玩转Android10源码开发定制(三)源码中编译手机刷机包
玩转Android10源码开发定制(五)源码编译开发中常用命令
玩转Android10源码开发定制(六)修改内核源码绕过反调试检测
玩转Android10源码开发定制(七)修改ptrace绕过反调试
玩转Android10源码开发定制(九)内置frida-gadget so文件和frida-server可执行文件到系统
玩转Android10源码开发定制(十)增加获取当前运行最顶层的Activity命令
玩转Android10源码开发定制(11)内核篇之安卓内核模块开发编译
玩转Android10源码开发定制(12)内核篇之logcat输出内核日志
关注公众号获取更多最新文章