Android系统上SELinux的攻与防

SELinux是Linux系统一个访问控制策略,android中称之为SEAndroid,做系统开发大都会遇到SEAndroid权限问题,之前一直都有在解决相关问题,但是都没有形成文字记录。今天在帮同事调试程序的时候又遇到类似问题,借此机会做以记录,方便以后查询,也给受此问题困扰的朋友以指导。


一、SELinux的攻


andorid5.x后就引入了非常严格的selinux权限管理机制,我们经常会遇到“avc denied”问题。下面就结合实际问题来探讨如何解决。

遇到这类问题,一般在logcat或kmsg都会出现avc denied字样。我们可以用如下command输出日志。

cat proc/kmsg |grep -irn "avc" 或 dmesg |grep -irn "avc"

type=1400 audit(7585.579:118): avc: denied { search } for pid=8290 comm="prvlogcat" name="user" dev="tmpfs" ino=2475 scontext=u:r:dtlog:s0 tcontext=u:object_r:mnt_user_file:s0 tclass=dir permissive=0

我们采取的原则,“谁少补谁,少什么补什么”。首先我们要理解这段日志里关键字段是什么意思,我们才能知道谁少以及少什么。

scontext访问主体,dtlog,谁缺少权限

tcontext: 被访问主体,mnt_user_file,访问的是哪个对象,这个对象少什么权限。

tclass:访问对象的类型

{ search }:访问对象类型缺少的具体权限。

这几个关键点找到后,我们可以做一个组合。

action scontext tcontext:tclass { permission },按照这个组合转换得到如下语句。

allow dtlog mnt_user_file:dir { search };

我们在来看一个日志来验证下这个组合,是不是可以作为一个万能公式来用。

type=1400 audit(6518.009:788): avc: denied { read } for pid=10414 comm="prvlogcat" name="primary" dev="tmpfs" ino=10272 scontext=u:r:dtlog:s0 tcontext=u:object_r:storage_file:s0 tclass=lnk_file permissive=0

套用上面这个组合。

action scontext tcontext:tclass { permission }

allow    dtlog    storage_file    lnk_file    { read }

转换:

allow dtlog storage_file:lnk_file { read };

完美,从而可以证明上面的组合可以作为一个万能公式来使用,解决avc denied的问题。

另外我们也可以通过设置selinux工作方式,来绕过权限检查。

adb shell setenforce 0 or 1

0 表示permissive: 所有操作都被允许,但是如果有违反权限的话,还是会输出avc相关日志。

1 表示enforcing:所有操作都会进行权限检查


二、SELinux的防

我们可以根据上面总结的公式来解决avc denied问题,但是我们如何来编写自己的sepolicy te文件?

andorid系统中默认的sepolicy文件位于project/external/sepolicy,但是一般的芯片厂商都会定义一套自己的sepolicy,所以修改这部分建议大家不要去修改默认,按照各自芯片厂商的平台来修改,mtk平台一般是在这个目录\device\mediatek\common\sepolicy,qcom平台在\device\qcom\sepolicy\common目录下。我们可以打开这里面任意一个te文件,来参考学习如何编写自己的te。下面是我在项目里用的一个自定义te,大家可以参考下:

type dtlog, domain;
type dtlog_exec, exec_type, file_type;

init_daemon_domain(dtlog)

allow dtlog self:capability { setuid setgid sys_nice audit_control dac_override    dac_override dac_override };
allow dtlog self:capability2 { syslog };
allow dtlog kernel:system { syslog_read syslog_mod };

allow dtlog storage_file:dir { add_name remove_name open create write read search };
allow dtlog storage_file:file { open create write read append setattr getattr lock rename link unlink };
allow dtlog storage_file:lnk_file { read write };
allow dtlog mnt_user_file:dir { add_name remove_name open create write read search };
allow dtlog mnt_user_file:lnk_file { read write };

allow dtlog fuse:dir { add_name remove_name open create write read search };
allow dtlog fuse:file { open create write read append setattr getattr lock rename link unlink };
allow dtlog logdr_socket:sock_file { write read };
allow dtlog logd:unix_stream_socket { connectto };

在te文件中,所有的概念都被定义为类型,进程,资源,属性,这些都是类型。

1、type 类型名称    属性类型名称

type dtlog  domain;将dtlog关联到domain,即将domain设置为dtlog类型的属性。

type dtlog_exec, exec_type, file_type; dtlog_exec类型,属性为可执行属性,文件属性。

2、访问向量(AV)的规则。

av是用来描述访问主体对被访问主体的许可,通常有四种类型:

  • allow:表示允许主体对被访问主体执行许可的操作。

  • neverallow:表示不允许主体对被访问主体执行制定的操作。

  • auditallow: 表示允许操作并记录访问决策信息。

  • dontaudit:表示不记录违反规则的决策信息,切违反规则不影响运行。

通常使用的te规则:

allow dtlog mnt_user_file:lnk_file { read write };

将te规则编写完成后,我们需要根据访问类型将其添加到相应的上下文文件中。如上面te文件需要修改file_context。

/system/bin/prvlogcat   u:object_r:dtlog_exec:s0
/system/bin/kmsgcat     u:object_r:dtlog_exec:s0


参考资料:

  1. MyArrow的专栏: 看懂SELinux策略语言–类型强制(编写TE规则)

  2. 重庆鲳鱼:andorid中SELinux规则分析和语法简介


原创不易,如果您觉得好,可以分享此公众号给你更多的人。

Android系统上SELinux的攻与防