Android下添加自启动应用

回到顶部

1. 介绍

这里介绍的是基于开启selinux的Android 4.4及以上版本添加自启用应用的方法

回到顶部

2. 关于selinux

Android下的selinux被称为SEAndroid, 其原理可以参考Linux下的selinux, 这里不详细介绍

回到顶部

3. 为sshd添加自启动

在前面文章中, 笔者为sshd添加自启动由于selinux的存在一直失败
这里作为一个补充为sshd添加seplicy以保证能成功启动

3.1 修改init.rc

对于CM, 其init.rc位于/system/core/rootdir/目录下
笔者这里不使用启动start-sshd脚本的方法, 而直接启动应用程序,
在init.rc将sshd启动配置修改如下

service sshd /system/bin/sshd -f /system/etc/ssh/sshd_config -D
    class main
    user  root
    oneshot

3.2 添加sshd.te文件

为sshd定义sepolicy

Android默认的sepolicy位于external/sepolicy/
而厂商自定义sepolicy通常位于devices/platform/platform-sub/sepolicy/
对于i9100, 位于device/samsung/galaxys2-common/selinux

对于CM, 我们添加到external/sepolicy/目录下即可
sshd.te内容如下, 这里只是申明, 并没有规则

# sshd daemon
type sshd, domain;
type sshd_exec, exec_type, file_type;
init_daemon_domain(sshd)

同时要保证sshd.te文件要编译到sepolicy中, 部分系统可能需要修改external/sepolicy/Android.mk
将sshd.te加入BOARD_SEPOLICY_UNION中
笔者使用的CM会自动添加external/sepolicy/*.te, 故只要添加文件即编译到sepolicy中

3.3 修改file_contexts

file_contexts位于external/sepolicy/目录下, 厂商同样也有自定义该
该文件通过正则表达式来描述系统文件的安全上下文

为sshd加入如下内容

/system/bin/sshd     u:object_r:sshd_exec:s0
...
/data/ssh(/.*)?	u:object_r:sshd_data_file:s0

上面的内容将sshd定义为sshd_exec文件类型, 将sshd配置文件设置为sshd_data_file类型

同时修改external/sepolicy/file.te, 定义sshd_data_file类型

# /data/ssh - sshd conf files
type sshd_data_file, file_type, data_file_type;

3.4 修改selinux模式

在CentOS中selinux有如下三种模式

# SELINUX= can take one of these three values:
#     enforcing  - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled   - No SELinux policy is loaded.

而在Android中则精简为enforcing (1)和permissive (0)两种模式
enforcing模式会严格执行权限操作, 一旦越权则禁止运行; permissive则只是记录行为, 并不终止运行
我们的目的是为了让sshd工作在enforcing模式下, 这里先设置为permissive模式
selinux相关命令如下

 # getenforce
Enforcing
# setenforce 0
# getenforce
Permissive

但是上面的命令只能临时生效, 重启后就恢复为默认的模式(enforcing)
所以我们需要编译出默认就是permissive模式的Android版本, 方法有下面两种

3.4.1 通过脚本设置selinux模式

参考的做法
写一个脚本, 在脚本中设置selinux模式, 放在init.d或者su.d目录下, 让init或者su在启动时执行
笔者没有使用该方法, 因为感觉对sshd不一定起作用, 而且这也不是标准做法

3.4.2 配置默认selinux模式

在参考了解到
selinux由init进程(system/core/init/init.cpp)来初始化, 调用时序为

main() -> selinux_initialize() -> selinux_is_disabled()/selinux_is_enforcing()
-> ALLOW_DISABLE_SELINUX -> selinux_status_from_cmdline()

其中ALLOW_DISABLE_SELINUX宏来判断selinux是否允许被禁用(包括disable和permissive), 否则后面不用再进行判断
ALLOW_DISABLE_SELINUX是在编译时就制定, 位于system/core/init/Android.mk(userdebug和eng为1)

selinux_status_from_cmdline()通过读取内核传递的命令行中androidboot.selinux的值来判断selinux模式
判读依据为disabled和permissive或其他

在笔者的Android上, 命令行参数如下

# cat /proc/cmdline
console=ttySAC2,115200 consoleblank=0 androidboot.hardware=smdk4210 loglevel=4 console=ram sec_debug.enable=0 sec_debug.enable_user=0 c1_watchdog.sec_pet=5 sec_log=0x100000@0x4d900000 s3cfb.bootloaderfb=0x5ec00000 ld9040.get_lcdtype=0x2 consoleblank=0 lpj=3981312 vmalloc=144m

那么我们可以配置内核命令行参数来控制selinux的默认模式
内核命令行参数是在编译时通过BOARD_KERNEL_CMDLINE来指定
笔者使用的i9100中该值位于 device/samsung/galaxys2-common/BoardCommonConfig.mk
找到对应位置在后面加上androidboot.selinux=permissive

3.5 编译Android

在上面的修改之后, 重新编译Android

笔者使用lunch xxx命令重新编译升级后发现selinux仍然是enforcing模式
通过/proc/cmdline获取内核命令发现并没有生效
查看编译中间件$PACKG/BOOT/cmdline, $PACKG/BOOT/cmdline也是如此
$PACKG = out/target/product/i9100/obj/PACKAGING/target_files_intermediates/
于是笔者删除$PACKG目录下的所有内容, 再次编译升级

这次仍然没有成功, 也不清楚是什么原因, 这卧槽谁受得了
懒得去折腾了, 修改selinux_is_enforcing()函数直接返回SELINUX_PERMISSIVE

3.6 sshd权限

3.6.1 截取avc log

此时sshd应该已经成功启动, 为了查看所有sshd需要的权限, 使用ssh client进行一次连接
同时连接sftp及scp,  传递文件等动作

然后通过logcat截取log, 然后找到所有sshd相关的log

12-13 19:28:25.050  2009  2009 I sshd    : type=1400 audit(0.0:15): avc: denied { 
open
 } for name="ssh_host_rsa_key" dev=mmcblk0p10 ino=49165 scontext=u:r:
sshd
:s0 tcontext=u:object_r:
system_data_file
:s0 tclass=
file
 permissive=1

3.6.2 生成规则

对照被deny的项目可以按照如下方法来生产规则

         scontext   tcontext        tclass   avc denied
 allow   
sshd system_data_file: file  open

网上称使用audit2allow工具可以批量生成规则
由于在我的CentOS 7上一直提示指定policy文件, 不深究

3.6.3 添加规则

将所有生成的规则加入到sshd.te中, 然后重新编译升级

sshd.te文件内容如下

# sshd daemon
type sshd, domain; type sshd_exec, exec_type, file_type; #init_daemon_domain(sshd) net_domain(sshd) allow sshd self:capability { setuid setgid net_admin net_raw net_bind_service }; allow sshd sshd_exec:file execute_no_trans; allow sshd sshd_data_file:file { open read create getattr setattr append write link unlink rename }; allow sshd sshd_data_file:dir { create setattr add_name remove_name rmdir rename }; allow sshd ptmx_device:chr_file { open read write ioctl getattr setattr }; allow sshd devpts:chr_file { open read write ioctl getattr setattr }; allow sshd shell_exec:file rx_file_perms; allow sshd system_file:file rx_file_perms;

上面的方法在一定程度上适用, 但部分功能仍然受限制
不折腾了, init.cpp中的修改已经完全够用了

回到顶部

4. 应用层的自启动

上面的自启动是基于C或者说底层的自启动,下面介绍一种在应用层面或者Java层面的自启动方法

具体

参考:

<深入理解SELinux SEAndroid>


 
分类:  Android

转载于:https://www.cnblogs.com/wangzhe1635/p/8675989.html

你可能感兴趣的:(Android下添加自启动应用)