正确姿势临时和永久开启关闭Android的SELinux

正确姿势临时和永久开启关闭Android的SELinux      正确姿势临时和永久关闭Android的SELinux前言  自从Android4.4强制开启SELinux以后,在开发中我们经常会遇到avcdenied的问题,为了方便开发调试我们会将SELinux关闭,那么本章将带领读者怎么临时和永久关闭Android的SELinux。正确姿势临时和永久关闭Android的SELinux1.1临时关闭Andro…

大家好,又见面了,我是你们的朋友全栈君。

      正确姿势临时和永久关闭Android的SELinux

Android SELinux开发多场景实战指南目录:

Android SELinux开发入门指南之SELinux基础知识
Android SEAndroid权限问题指南
Android SELinux开发入门指南之如何增加Java Binder Service权限
Android SELinux开发入门指南之权限解决万能规则
Android SELinux开发入门指南之如何增加Native Binder Service权限
Android SELinux开发入门指南之正确姿势解决访问data目录权限问题
正确姿势临时和永久关闭Android的SELinux


引言

   自从Android 4.4强制开启SELinux以后,在开发中我们经常会遇到avc denied的问题,为了方便开发调试我们会将SELinux关闭,那么本章将带领读者怎么临时和永久关闭Android的SELinux。

注意:这里的源码是以Android 8.0为基准的。


正确姿势临时和永久关闭Android的SELinux

1.1 临时关闭Android的SELinux

这个操作比较简单,但是前提条件是机器能被root,且固件里面没有限制setenforce命令的执行。下面让我们看看怎么执行:

XXX:/ # getenforce //获取当前SELinux状态
Enforcing
XXX:/ # setenforce 0 //临时关闭SELinux状态
XXX:/ # getenforce //获取SELinux状态
Permissive
XXX:/ # setenforce 1 //永久开启SELinux状态
XXX:/ # getenforce
Enforcing
XXX:/ #

注意点:

  • 上述的方法是临时关闭SELinux,机器重启以后还是会恢复的
  • 上述命令一定要在Root模式下运行,且必须是终端没有对setenforce进行限制,否则会报如下的错误
setenforce: Could not set enforcing status: Permission denied   //非root情况
  • 对于一些定制了内核的Room来说,哪怕你已经获取了Root权限,当执行setenforce命令时依然会提示如下错误,因为在SELinux模式下,Root不是万能的。
setenforce: Couldn't set enforcing status to '0': Invalid argument //Root情况,但是Room做了定制不允许setenforce

1.2 永久关闭Android的SELinux

init进程是Android内核启动的第一个用户级进程,其中的SELinux也是在init进程中启动的,代码位置在system/core/init/init.cpp中。

int main(int argc, char** argv) { 
   
	...
	selinux_initialize(true);
	...
}

static void selinux_initialize(bool in_kernel_domain) { 
   
    Timer t;

    selinux_callback cb;
    cb.func_log = selinux_klog_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    if (in_kernel_domain) { 
   
        LOG(INFO) << "Loading SELinux policy";
        if (!selinux_load_policy()) { 
   
            panic();
        }

        bool kernel_enforcing = (security_getenforce() == 1);//判断条件1
        bool is_enforcing = selinux_is_enforcing();//判断条件2
        if (kernel_enforcing != is_enforcing) { 
   
            if (security_setenforce(is_enforcing)) { 
   
                PLOG(ERROR) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
                security_failure();
            }
        }

        std::string err;
        if (!WriteFile("/sys/fs/selinux/checkreqprot", "0", &err)) { 
   
            LOG(ERROR) << err;
            security_failure();
        }
        // 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);
    } else { 
   
        selinux_init_all_handles();
    }
}

通过代码我们可以看出,init会通过security_getenforce()和selinux_is_enforcing()的值是否一致来判断是否开启SELinux,当不一致的时候会设置security_setenforce的值为is_enforcing。

下面让我么看看security_getenforce()的实现,通过全局搜索我们发现,该代码的位置在在external/selinux/libselinux/src/getenforce.c目录下:

int security_getenforce(void)
{ 
   
    int fd, ret, enforce = 0;
    char path[PATH_MAX];
    char buf[20];

    if (!selinux_mnt) { 
   
        errno = ENOENT;
        return -1; 
    }   

    snprintf(path, sizeof path, "%s/enforce", selinux_mnt);
    fd = open(path, O_RDONLY | O_CLOEXEC);
    if (fd < 0)
        return -1; 

    memset(buf, 0, sizeof buf);
    ret = read(fd, buf, sizeof buf - 1); 
    close(fd);
    if (ret < 0)
        return -1; 

    if (sscanf(buf, "%d", &enforce) != 1)
        return -1; 

    return !!enforce;
}

这里有个要注意点,sizeof path,这个不是错误的,因为这里的sizeof是一个运算符,这里的代码所以首先获取一个节点数值,Android改节点路为/sys/fs/selinux/enforce,这个值表示是否开启selinux,让我们手动cat一下该节点,然后查看一下值:

XXX:/ # cat /sys/fs/selinux/enforce
1

这里另一个判定条件是selinux_is_enforcing()函数。其定义如下:

enum selinux_enforcing_status { 
    SELINUX_PERMISSIVE, SELINUX_ENFORCING };
        
static selinux_enforcing_status selinux_status_from_cmdline() { 
   
    selinux_enforcing_status status = SELINUX_ENFORCING;
        
    import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) { 
   
        if (key == "androidboot.selinux" && value == "permissive") { 
   
            status = SELINUX_PERMISSIVE;
        }
    });     
                
    return status;
}           
        
static bool selinux_is_enforcing(void)
{ 
          
    if (ALLOW_PERMISSIVE_SELINUX) { 
   
        return selinux_status_from_cmdline() == SELINUX_ENFORCING;
    }       
    return true;
}  

此处从cmdline中获取androidboot.selinux的值,如果是permissive,则返回SELINUX_PERMISSIVE,即0,否则返回SELINUX_ENFORCING。如果enforce节点和cmdline设置不一致,则调用security_setenforce重新设置selinux的enforce节点值。
因此想要关闭selinux,可以直接将selinux_is_enforcing返回false,网上也有人从驱动返回,这个驱动这边不是很熟悉,所以就在这里直接注释掉从驱动获取的值直接返回false即可。

static bool selinux_is_enforcing(void)
{ 
                
    return false;
}  

最后重新编译boot.img,烧入固件这样重新启。启动完成后调用getenforce命令可以看到已经特地关闭SELinux了。

关于从驱动层返回修改的,可以参考下面的这篇博文:
https://blog.csdn.net/zhangdaxia2/article/details/98243665


结语

   关于SELinxu都是些偏向实战类型的博客,所以也没有过多好说的,跟着规则实际操作几把就基本OK了。好了今天的博客正确姿势临时和永久开启关闭Android的SELinux到这里就结束了,各位青山不改绿水长流,江湖见!欢迎点赞或者关注本博主,当然由于博主知识有限,批评或者踩也无妨!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153550.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Arduino使用HC05蓝牙模块与手机连接[通俗易懂]

    Arduino使用HC05蓝牙模块与手机连接[通俗易懂]通过本文,可以了解到以下内容:进入AT模式进行蓝牙基本参数设置Arduino蓝牙控制LED电路设计以及代码编写利用Andorid蓝牙串口调试软件测试功能进入At模式进行蓝牙基本参数设置想要使用Arduino的蓝牙模块,首先要对蓝牙模块进行基本参数设置。基本参数设置主要包含:蓝牙名称、模式以及匹配密码等。设置蓝牙模块可以使用USB-TTL连接电脑使用串口调试软

    2022年5月9日
    70
  • springmvc整合swagger 与 常用注解说明

    springmvc整合swagger 与 常用注解说明

    2021年9月26日
    112
  • linux下安装php+apache+mysql集成环境

    linux下安装php+apache+mysql集成环境不多说,直接走起,实践才是道理,就算出错再说sudoapt-getinstallapache2php5-mysqllibapache2-mod-php5mysql-server意思差不多是:最小化安装amp也就是apache,php5和mysql在加上一个phpmysql扩展后面回出现差不多是这样的文字吧:解压后消耗掉xxMB的额外空间。您希望继续执行吗?[y/

    2022年6月28日
    27
  • 一起学JAVA 反射学习(超详细)

    一起学JAVA 反射学习(超详细)1什么是反射?Reflection(反射)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,也有称作“自省”。反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。2为什么需要反射?

    2022年6月11日
    35
  • 统信UOS命令大全 麒麟系统命令大全 Linux常用命令操作大全(非常全非常详细) ubuntu命令大全常用操作命令大全

    Linux常用命令大全(非常全!!!)最近都在和Linux打交道,感觉还不错。我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短小但却功能强大。我将我了解到的命令列举一下,仅供大家参考:系统信息arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DMI)hdparm-i/dev/hd…

    2022年4月9日
    171
  • 中国雇主品牌年会_雇主品牌怎么做

    中国雇主品牌年会_雇主品牌怎么做第十三届新雇主品牌年会在北京举行

    2022年4月21日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号