加载中……
SELinux安全策略简介及log分析

安全策略基本概念

首先看一张Linux权限检测流程图

如图所示:Linux系统先做DAC检查。如果没有通过DAC权限检查,则操作直接失败。通过DAC检查之后,再做MAC权限检查。

DAC:全称是Discretionary Access Control,翻译为自主访问控制。即普通的 owner:group:other 文件权限机制。

MAC:强制访问控制,SELinux就是一种MAC机制。任何进程想在SELinux系统中干任何事情,都必须先在安全策略配置文件中赋予权限。凡是没有出现在安全策略配置文件中的权限,进程就没有该权限。

SELinux中也有用户的概念,但它和Linux中原有的user概念不是同一个东西。什么意思呢?比如,Linux中的超级用户root在SELinux中可能就是一个没权限,没地位,打打酱油的”路人甲“。当然,这一切都由SELinux安全策略的制定者来决定。

SELinux System Property 语法

Security Context:

SELinux中,每种东西都会被赋予一个安全属性,官方说法叫Security Context。Security Context是一个字符串,查看命令:文件–> ls -Z 进程–>ps -Z
根据SELinux规范,完整的Security Context字符串,主要由三部分组成,格式如下:

user:role:type[:range]

方括号中的内容表示可选项。s0属于range中的一部分,如:

u:r:init:s0
  • u为user的意思。SEAndroid中定义了一个SELinux用户,值为u。
  • r为role的意思。role是角色之意,它是SELinux中一种比较高层次,更方便的权限管理思路,简单点说,一个u可以属于多个role,不同的role具有不同的权限。另外文件为死的东西,无法扮演角色,所以通常用object_r来表示它的role。
  • init,代表该进程所属的Domain,也可叫type为init。另外文件通常设置type为rootfs
  • s0是SELinux为了满足军用和教育行业而设计的Multi-Level Security(MLS)机制。简单点说,MLS将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问。

te介绍:

te,即安全策略配置文件。是SELinux权限管理的核心。通常可以在如下路径找到他们:

  • device/xx/sepolicy/ xx.te
  • external/selinux/sepolicy/ xx.te
  • system/sepolicy

根据SELinux规范,定义一条完整的配置,语句格式为:

rule_name source_type target_type:object_class perm_set

rule_name

可用选项:
allow:允许
neverallow:绝不允许,没有声明权限时默认就没有权限。原理上neverallow语句没必要存在,但可以起到限制allow的作用。
allowaudit:记录某项操作,
dontaudit:忽略某项操作。

object_class

需要通过class语句申明,这些申明一般放在一个叫security_class的文件中,class和kernel中相关模块紧密结合。

 file-related classes

class filesystem
class file #代表普通文件
class dir #代表目录
class fd #代表文件描述符
class lnk_file #代表链接文件
class chr_file #代表字符设备文件
……

network-related classes

class socket #socket
class tcp_socket
class udp_socket
……

Android平台特有的class

class binder
class zygote
class property_service #userspace和用户空间中的SELinux权限检查有关

Perm set

Perm set指的是某种Object class所拥有的操作。SELinux规范中,定义perm set有两种方式,一种是使用下面的common命令,其格式为:

common common_name { permission_name ... }

common定义的perm set能被另外一种perm set命令class所继承

以下是Android平台中,file对应的权限(perm set)。

common file {ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton }

除了common外,还有一种class命令也可定义perm set,语法为:

class class_name [ inherits common_name ] { permission_name ... }

如下面的例子:

class dir inherits file { add_name remove_name reparent search rmdir open audit_access execmod }

inherits表示继承了某个common定义的权限,但它不能被其他class继承。

type

type定义命令的完整格式为

type type_id [alias alias_id,] [attribute_id]

其中,方括号中的内容为可选。alias指定了type的别名,可以指定多个别名。下面这个例子定义了一个名为shell的type,它和一个名为domain的属性(attribute)关联。

type shell, domain; #本例来自shell.te

可理解为shell为domain的一员。

属性由attribute关键字定义,如attributes文件中定义的SEAndroid使用的属性有:

attribute domain;
attribute file_type;

另外,可以关联多个attribute:

type shell, domain;
type shell, file_type;

案例:

allow netd proc:file write;

允许netd域中的进程向proc type的file进行写操作。

 

allow zygote init:process sigchld;

允许zygote域中的进程向init type的进程(Object Class为process)发送sigchld信号

 

allow zygote appdomain:dir { getattr search };

允许zygote域中的进程search或getattr类型为appdomain的dir。注意,多个perm_set可用{}括起来

 

allow from_role_id to_role_id;

允许from_role_id切换到to_role_id。

 

allow unconfineddomain {fs_type dev_type file_type}:{ chr_file file } ~{entrypoint relabelto};

perm_set语法比较奇特,前面有一个~号。它表示除了{entrypoint relabelto}之外,{chr_file file}这两个object_class拥有的其他所有操作。

特殊符号除了~外,还有-号和*号,其中:
-号表示去除某项内容。
*号表示所有内容。

实现基于Role或User的权限控制

SELinux提供了一个新的关键词,叫constrain,constrain标准格式为

constrain object_classs perm_set expression ;

下面这句话表示只有source和target的user相同,并且role也相同,才允许进行写操作。

constrain file write (u1 == u2 and r1 == r2);
SEAndroid中没有使用constrain,而是用了MLS中的mlsconstrain
SELinux中,设置或分配SContext给进程或文件的工作叫Security Labeling

 

如何确认问题是否与SELinux有关

将 SELinux 调整到 Permissive 模式测试

注意:在 USER 版本中无法设置!如需在USER版中设置,转到源码中设置。
ENG 版本设置方法: 

adb shell setenforce 0 //设置成 permissive 模式
adb shell setenforce 1 //设置成 enforce 模式

如果设置成 permissive 模式还能复现问题,则与 SELinux 无关, 如果原本很容易复现, 而 Permissive mode 不能再复现, 那么就可能关系比较大,使用

adb shell getenforce

可以确认SELinux模式。

 

查看 LOG 中是否有标准的 SELinux Policy Exception.

在 Kernel LOG / Main Log 中查询关键字 “avc”,看看是否有 SELinux Policy Exception, 并进一
步确认这个异常是否与当时的逻辑相关

 

源码中设置

开机设置 SELinux 模式

bootable/bootloader/lk/platform/mt6xxx/rules.mk更新配置

# choose one of following value -> 1: disabled/ 2: permissive /3: enforcing
SELINUX_STATUS := 3

可直接调整这个 SELINUX_STATUS 这个的值为 2 或者 1

 

允许 USER 版本 disable SELinux

修改 system/core/init/Android.mk 新增

ifeq ($(strip $(TARGET_BUILD_VARIANT)),user)
LOCAL_CFLAGS += -DALLOW_DISABLE_SELINUX=1
endif

 

LOG分析及调试

SELinux Policy Exception Log 格式:
SELinux Policy Exception 的 LOG 关键字是 “avc: denied” 或者 “avc: denied”, 下面就是一句
典型的 LOG:
<5>[ 27.706805] (3) [304:logd.auditd] type=1400 audit(1420041991.220:17): avc: denied { execute } for pid=2182 comm=”app_process” path=”/data/dalvik-cache/arm64/system@framework@boot.oat” dev=”mmcblk0p18″ ino=15109 scontext=u:r:root_channel:s0 tcontext=u:object_r:dalvikcache_data_file:s0 tclass=file permissive=0

具体说明如下:

<5> : kernel log level
[ 27.706805] : kernel time
(3) : cpu number
[304:logd.auditd] : 表示此 LOG 是通过 auditd 打印的.
type=1400 : SYSCALL
type=AVC – for kernel events
type=USER_AVC – for user-space object manager events
audit(1420041991.220:17) : audit(time:serial_number)
avc: denied { execute } : field depend on what type of event is being audited.
pid=2182 comm=”app_process” : If a task, then log the process id (pid) and the name of the executable file (comm).
path=”/data/dalvik-cache/arm64/system@framework@boot.oat” dev=”mmcblk0p18″ ino=15109: The information of target.
subject context : u:r:root_channel:s0
target context : u:object_r:dalvikcache_data_file:s0
tclass : the object class of the target class=system
permissive: permissive (1) or enforcing (0)

基本分析流程

  1.  将 SELinux 调到 permissive mode, 然后一次性抓取出所有的”avc:” 的 LOG.
    * 如果问题与开机流程无关, 并且 eng 版本能够复现.
    adb shell setenforce 0
    * 如果问题与开机流程相关, 或者只有 user build 能够复现. 按下列 FAQ 设置 permissive mode
  2. 确认访问是否是必须的?是否是违法恶意访问?
  3. 如果是正常访问, 确认访问的目标类型是否太过广泛,如果太过广泛, 细化具体的文件目标。
  4. 添加对应的 SELinux Policy 到对应的 Policy 文件。
  5. 如果是违法恶意访问, 追查上层 feature owner 的责任。

验证 SELinux Policy 问题

快速编译测试.

此处只是简述流程,具体编译方式请参考实际项目编译方式

在已经编译过的版本上, 首先编译出新的 selinux policy, 然后打包 boot image.
KK:

./mk project_name mm external/sepolicy
./mk project_name bootimage

L:

source build/envsetup.sh
lunch XXX
mmm system/sepolicy
make -j8 ramdisk-nodeps
make -j8 bootimage-nodeps

然后再重新刷 bootimage 测试.

或者使用

source build/envsetup.sh
lunch XXX
mma system/sepolicy

然后使用adb push sepolicy规则:

#添加到 tct_sepolicy 目录的 selinux 规则:
adb push out/target/product/project/vendor/etc/selinux/      /vendor/etc/
#添加到 plat_public,plat_private 目录的 selinux 规则:
adb push out/target/product/project/system/etc/selinux/      /system/etc/
#同时添加了 selinux 规则到 tct_sepolicy 目录以及另外两个目录:
adb push out/target/product/project/vendor/etc/selinux/     /vendor/etc/
adb push out/target/product/project/system/etc/selinux/     /system/etc/

注意: 如果更新了 file_contexts, 给 system 下面的文件重新设置了 SELinux Label, 那么你需要将 system image 重新打包, 不然不会起到作用.

make -j8 snod

 

参考链接

SEAndroid安全机制简要介绍和学习计划
深入理解SELinux SEAndroid

版权声明: 若无特殊说明,文章均为原创,版权归本文作者所有,转载请保留出处和此说明!
本文链接: SELinux安全策略简介及log分析
本文作者: Jan.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇