程序地带

修改Android10系统源码关闭selinux


一、seandroid简介


       SEAndroid是Google在Android4.4上正式推出的一套以SELinux为核心的系统安全机制。在Android源码中,系统默认的seandroid配置存放如下路径:


/home/qiang/lineageOs/system/sepolicy

  目录中存放了比如adbd、system_server、系统app、第三方app等te配置文件。


    由于Android系统引进了seandroid策略。强化了app对资源的访问限制。安全性大大提高。比如举一个获取wifi mac的例子为例说明:


     在android app中很多app通过读取/sys/class/net/wlan0/address来获取手机的wifi mac地址。通过adb 命令查看该文件的权限如下:


C:UsersQiang>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

     以上说明手机的app都可以读取访问该文件。但是在Android10中,系统配置了普通App不能读取/sys/class/net/wlan0/address的seandroid策略权限。导致Android 10 中读取失败,提示权限拒绝。由于seandroid强化了系统安全性,要想一个App访问访问系统的某一个目录或者路径,需要专门去配置te文件策略。对于不熟悉seandroid配置的开发者配置起来有点难度。那有没有办法不配置seandroid策略文件,设置文件或者目录可读权限就能访问的方法。答案就是全局关闭seandroid。


 


二、安卓中关闭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.cppsystem/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源码开发定制(一)源码下载编译


玩转Android10源码开发定制(二)刷机操作


玩转Android10源码开发定制(二)刷机操作之fastboot刷机演示


玩转Android10源码开发定制(二)刷机操作之Recovery刷机演示


玩转Android10源码开发定制(三)源码中编译手机刷机包


玩转Android10源码开发定制(四)源码开发环境搭建


玩转Android10源码开发定制(五)源码编译开发中常用命令


玩转Android10源码开发定制(六)修改内核源码绕过反调试检测


玩转Android10源码开发定制(七)修改ptrace绕过反调试


玩转Android10源码开发定制(八)内置Apk到系统


玩转Android10源码开发定制(九)内置frida-gadget so文件和frida-server可执行文件到系统


玩转Android10源码开发定制(十)增加获取当前运行最顶层的Activity命令


玩转Android10源码开发定制(11)内核篇之安卓内核模块开发编译


玩转Android10源码开发定制(12)内核篇之logcat输出内核日志


 


关注公众号获取更多最新文章图片图片图片图片


图片


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

随机推荐

leaflet地图原理_leaflet 加载地图

您好,就是我按照您说的这些网址,还有supermap提供的视频辅导之类的,写下如下的代码,然后经纬度也是按照视频讲解那样写的,结果...

weixin_39615499 阅读(277)

idea gitignore 文件不生效

问题原因:自动生成的.git文件和.gitignore文件中没有添加.idea文件,但是这个自动创建的.gitignore文件配置在创建本地库的同时已经添加进了本地库的缓存...

小白同学a 阅读(234)

ios 通知注销_ios证书注销

关于ios证书注销的搜索结果回答详细解答可以参考官方帮助文档1.检查手机端App允许接收通知。App在后台运行,因为在iOS系统中,如果App在前台,就不会收...

阮春阳 阅读(999)

生成树协议

生成树协议二层环路带来的问题生成树定义STP相关概念BPDU定义分类STP的选举机制在所有交换机中选举一台作为根网桥选举规则Brideg-id每台非根网桥(交换机)选举一个...

李十八0501 阅读(494)