SElinux-3

来源:互联网 发布:基于大数据的风险管理 编辑:程序博客网 时间:2024/05/07 02:57
1. 将SELinux 调整到Permissive 模式测试.
将SELinux 模式调整到Permissive 模式,然后再测试确认是否与SELinux 约束相关.
ENG 版本:
adb shell setenforce 0
如果还能复现问题,则与SELinux 无关, 如果原本很容易复现, 而Permissive mode 不能再复现, 那么就可能关系比较大.
 
2. 查看LOG 中是否有标准的SELinux Policy Exception.
在Kernel LOG / Main Log 中查询关键字 "avc:" 看看是否有SELinux Policy Exception, 并进一步确认这个异常是否与当时的逻辑相关.

19如何设置确认SELinux 模式?

1. 如何确认SELinux 模式 ?
在ENG/USER 版本中,都可以使用getenforce 命令进行查询,如:
 root@mt6589_phone_720pv2:/ # getenforce
 getenforce
 Enforcing
 
2. 如何设置SELinux 模式 ?
在ENG/USERDEBUG 版本中, 可以使用setenforce 命令进行设置:
adb shell setenforce 0    //设置成permissive 模式
adb shell setenforce 1    //设置成enforce 模式
在USER 版本中无法设置.
 
3. 如何开机设置SELinux 模式 ?
3.1 更新配置
 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
  
3.2 允许USER 版本 disable SELinux (如果你需要在USER Build 上开启)
 修改system/core/init/Android.mk 新增
       ifeq ($(strip $(TARGET_BUILD_VARIANT)),user)
       LOCAL_CFLAGS += -DALLOW_DISABLE_SELINUX=1
       Endif

20如何分析SELinux Policy Exception

1. 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)
 
 
2. 基本分析流程
 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 Exception
21快速验证SELinux Policy 问题

1. 快速编译测试.
 
在已经编译过的版本上, 首先编译出新的selinux policy, 然后打包boot image.
KK: ./mk project_name mm external/sepolicy
./mk project_name bootimage

L:
mmm external/sepolicy
make -j24 ramdisk-nodeps
make -j24 bootimage-nodeps

然后再重新刷bootimage 测试.
 
因为目前L 版本默认使用加密, 直接用/data/security/current 中的文件替换根目录下的文件,可能直接受影响,目前不推荐使用.
 
特别注意点:  如果更新了file_contexts, 给system 下面的文件重新设置了SELinux Label, 那么你需要将system image 重新打包, 不然不会起到作用.
make -j24 snod

22如何处理与Google 定义neverallow冲突

1. 总体原则
当我们修改或者增加一些SELinux Policy 后, 发现无法编译通过,或者与CTS 测试相冲突, 此时我们需要如何处理呢。

Google 在external/sepolicy 中有使用相关neverallow 规则, 对SELinux Policy 的更新进行了限制, 以防止开发者过度开放权限,从而引发安全问题。并且通过CTS Test 检测开发者是否有违法相关的规则.

为此,我们要求开发者,严格遵守Google 定义的规则,具体即是:
*  严禁直接修改external/sepolicy 下面的相关SELinux Policy, 使之保持与Google 一致, 特别是严禁直接删除或者修改Google 定义的neverallow 规则.
*  遇到与Google 定义相违背之处, 只能绕道, 或者修改设计.
 
下面,我们就一些典型问题进行说明.
 
 
2. CTS fail of android.security.cts.SELinuxDomainTest # testInitDomain
说明:  Google 要求只有一个init domain,  init 启动任何service 都要求进行domian 切换.
解决方式:  请开发者为新建的service 新增 process domain, 并设置相关权限
           http://online.mediatek.com/_layouts/15/mol/topic/ext/Topic.aspx?id=158
 
 
3. Android L APP 如何获取sys 或者 proc file system 中节点的写权限
说明: Google 默认禁止app , 包括system app, radio app 等直接写/sys 目录以u:object_r:sysfs:s0 为标签的文件以及/proc 目录以u:object_r:proc:s0文件, 认为这个是有安全风险的。如果直接放开SELinux 权限, 会导致CTS 无法通过.

解决方式:
通常遇到此类情况,你有两种做法:
(1). 通过system server service 或者 init 启动的service 读写操作, 然后app 通过binder/socket 等方式连接APP 访问. 此类安全可靠, 并且可以在service 中做相关的安全审查, 推崇这种方法.
 
(2). 修改对应节点的SELinux Security Label, 为特定的APP, 如system app, radio, bluetooth 等内置APP开启权限, 但严禁为untrsted app 开启权限. 具体的做法下面以 system app 控制/sys/class/leds/lcd-backlight/brightness 来说明.
 
* 在device/mediatek/common/sepolicy/file.te 定义brightness SELinux type
type sys_lcd_brightness_file, fs_type,sysfs_type;
 
* 在device/mediatek/common/sepolicy/file_contexts 绑定 brightness 对应的label, 注意对应的节点是实际节点,而不是链接.
/sys/devices/platform/leds-mt65xx/leds/lcd-backlight/brightness u:object_r:sys_lcd_brightness_file:s0
 
* 在device/mediatek/common/sepolicy/system_app.te 中申请权限.
allow system_app sys_lcd_brightness_file:file rw_file_perms;
 
* 为其它的process 申请相关的权限,如system_server, 在device/mediatek/common/sepolicy/system_server.te
allow system_server sys_lcd_brightness_file:file rw_file_perms;
 
原则上我们都推崇使用第一种方式处理.
 
 
4. Process 无法访问某个新增device
说明: Google 默认禁止除unconfineddomain 的进程以及ueventd 之外的进程直接访问某个普通定义的device, 所谓普通定义即device 对应的SELinux Label 是u:object_r:device:s0.
解决方式: 需要为新增的device 定义具体的Label, 然后再给对应的process 开启相关的权限.
 http://online.mediatek.com/_layouts/15/mol/topic/ext/Topic.aspx?id=158
 
5. Native Process 运行java 程序
说明: 以往我们在上下层通讯中, 比如某个native process/service 通常会借用如am 命令, 向ActivityManagerService 发送broadcast, 或者start activity 等. 通知上层某个事件已经发生了. 在android 5.0 以后, Google 严禁非app 以及几个特别的domain 的程序执行非rootfs or /system 分区的文件, 具体定义如:
neverallow { domain -appdomain -dumpstate -shell -su -system_server -zygote } { file_type -system_file -exec_type }:file execute;

解决方式:
(第一种方法).借用am 命令,实质上还是通过获取AMS 的binder 引用,再通过binder 向AMS 发送命令, 同样的你可以直接binder 来操作, 代表案例有: mediaserver 中使用的/frameworks/av/media/libmediaplayerservice/ActivityManager.cpp.  先获取servicemanager, 然后再获取activty binder 接口, 然后再封装parcel 后发送相关的命令给AMS.
具体对应的function cmd 以及parcel 的封装格式可以参考: frameworks/base/core/java/android/app/ActivityManagerNative.java.
注意的是如果这个process 没有申请binder 权限, 则需要先申请binder 权限, 可以使用 binder_use, binder_call, binder_service
 
(第二种方法). 将这个process 纳入appdomain, 但这个带来的影响是, 这个process 的权限会受到更大的限制, 因为Google 对appdomain 有非常严格的限制. 比如某个process 是demo
device/mediatek/common/sepolicy/demo.te 里面新增
app_domain(demo)
 
6. system app 读写nvram 操作
说明: 以往我们可以通过jni 直接读写nvram, 目前Google 已经严禁app 去读写系统块设备文件.
解决方式: 参考FAQ, 已经做好了nvram_agent_binder 这样一个服务进程,贵司使用时就是去访问它这个service 即可.
请参考:FAQ ID: FAQ04542 NvRAM】APK(应用层)读写NvRAM
 
7. UEventObserver 在APP 中使用.
说明:
(1). Google 禁止UEventObserver API在第三方APP 使用,即任何不可信任的APP 都禁止使用此API.
(2). 如果是系统APP ,比如phone app, settings 等使用,那么就要根据app 使用的domain, 添加相关的SELinux 权限.
解决方式: 确保你的APP 是系统的APP, 非untrusted app.
如针对settings app, 在device/mediatek/common/sepolicy/system_app.te 里面新增
allow system_app self:netlink_kobject_uevent_socket { create ioctl read getattr setattr bind connect getopt setopt shutdown };
 
SELinux vs ROOT
23ADB root permission
ADB root permission
1. adb root permission
* ENG Build/userdebug Build 不受影响,  SELinux 给adb 使用u:r:su:s0 的permissive mode label.
 ** adb root uid/capabilities.
 ** su permissive SELinux mode
 
* User Build 维持u:r:adbd:s0 和 当使用shell 时, 切换到u:r:shell:s0 的label. 权限受到严格限制.
 ** Root ===> shell
 ** No any capabilities. Retain CAP_SETUID/CATP_SETGID boundset bits for run-as
 ** shell use SELinux Enforcing mode
 
2. adb root in User Build
尽可能的保持User Build 的完整性. 只开启adb 完整root 权限.
(1).  alps/build/core/main.mk, 设置system property ro.secure = 0
ifneq (,$(user_variant))
 # Target is secure in user builds.
 ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
 将ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1 改成
 ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
 
(2). alps/system/core/adb/android.mk 放开权限控制宏. ALLOW_ADBD_ROOT, 如果没有打开这个选项,那么adb.c 中将不会根据ro.secure 去选择root 还是shell 权限,直接返回shell 权限。因此您必须需要Android.mk 中的第124行:
   ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 ===>
    ifneq (,$(filter userdebug user eng,$(TARGET_BUILD_VARIANT)))
 
(3). 放开SELinux 的限制. 更新alps/external/sepolicy/Android.mk 115 行,  将su label 默认编译进入sepolicy.
include $(BUILD_SYSTEM)/base_rules.mk
sepolicy_policy.conf := $(intermediates)/policy.conf
$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(sepolicy_policy.conf) : $(call build_policy, $(sepolicy_build_files))
 @mkdir -p $(dir $@)
 $(hide) m4 -D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
  -D target_build_variant=$(TARGET_BUILD_VARIANT) \
  -D force_permissive_to_unconfined=$(FORCE_PERMISSIVE_TO_UNCONFINED) \
  -s $^ > $@
 $(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 -D target_build_variant=$(TARGET_BUILD_VARIANT) \ 改成
     -D target_build_variant=eng \
 
 
3. adb root and permissive SELinux Mode 
目标: adb 默认root 权限, 并且将SELinux 调整到permissive mode.
在build 时导入特别的参数:
    MTK_BUILD_ROOT=yes
I.E
    MTK_BUILD_ROOT=yes make –j24 2>&1 | tee build.log
重新download lk, bootimage

24APP root permiss

1. app root permission
* 从KK 开始Google 不遗余力的禁止APP 使用root 权限, 通常如执行su.
 ** 去除app 的root capabilities of boundset.
    com_android_internal_os_zygote.cpp drop capabilities bounding set
 ** 去除app 的执行SUID/SGID 文件权限.
    app_main.cpp prctl set no_new_privs = 1
* L 版本进一步从SELinux 上严禁执行
 ** User build 上无su label,  app label 无法切换到su.
 ** SELinux Poicy 严格限制app 的访问行为.
 
 
2. 目前ROOT 后门通用做法.
因为app 直接fork SU 的做法, Google 已经限制死, 目前通用做法换成了使用原本具有root 权限的进行fork 出SU, 然后app 再使用SU Client 通过socket 连接到SU Server 的做法来达成. 常见的都是利用init 来达成, 第一个init 具有强大的root 权限,第二个就是init 非常好扩展。如下图所示。
 
3. L  规避SELinux 
L 版本上, 在android.c 中使用了特别的判定函数 set_policy_index,  此用来比较
/selinux_version
/data/security/current/selinux_version
两只文件是否都存在, 并且完全一致, 只有这样才会使用/data/security/current 下面的文件, 其它情况下都会使用根目录的配置文件.

selinux_version 中存储的是build 的BUILD_FINGERPRINT 即system property:ro.build.fingerprint
0 0
原创粉丝点击