android 5.x Native Service SELinux 调试记录

在开发android项目时,需要在init.rc中加入我们自己的native service xxx;但是在android 5.x系统上添加服务后发现服务没有正常启动,log中会报avc: denied错误。被SELinux拒绝权限了。所以我们就需要添加权限了。

与之前android版本一样,修改init rc文件添加我们需要的服务
service xxx/system/vendor/bin/xxx
class main
user root
group root

好啦!这样开机就可以执行服务了,但是不能正常启动,因为没有权限....,所以就要添加相应的权限策略使服务正常启动。

1.查看文件的安全上下文
先要用ls -Z命令查看安全上下文:
ls -Z
-rwxr-xr-x root shell u:object_r:system_file:s0 xxx

type是system_file并不是所期望的xxx_exec,这就要修改file_contexts,将它进行labeling。
file_contexts策略文件中添加:
/system/vendor/bin/xxx u:object_r:xxx_exec:s0

添加xxx.te策略文件:
type xxxr, domain;
type xxx_exec, exec_type, file_type;

修改了sepolicy策略文件就需要重新编译sepolicy:
mmm external/sepolicy/
因为编译生成的目标在root根文件系统中,需要重新编译boot.img:
make bootimage
重新烧录boot.img:
dd if=/tmp/boot.img of=/dev/block/by-name/boot
这样重新编译,再用ls -Z查看的时候,type就是xxx_exec了。

注意:进行labeling的文件不能使用adb push 到系统中,否则可能用ls -Z查看时没有打上预期的标签。

2. 根据log来写出需要的权限
<36>[ 28.725369] type=1400 audit(1481091758.000:6): avc: denied { execute_no_trans } for pid=2861 comm="init" path="/system/vendor/bin/xxx" dev="mmcblk0p7" ino=1984 scontext=u:r:init:s0 tcontext=u:object_r:xxx_exec:s0 tclass=file permissive=0
从日志看是没有权限execute_no_trans,所以在 xxx.te策略文件添加:
init_daemon_domain(xxx)
init_daemon_domain这是个宏,可以在te_macros文件中找到声明,里面就有trans相关,当然不用宏自己编写也可以,那样要写多条allow语句就太繁琐了。

<36>[ 14.175149] type=1400 audit(1481092361.220:3): avc: denied { call } for pid=1658 comm="xxx" scontext=u:r:xxx:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=0
从日志看是没有权限进行binder call,不要急着写allow,有宏可以快速搞定, xxx.te文件添加:
binder_use(xxx)

E/SELinux ( 1531): avc: denied { add } for service=xxx.service scontext=u:r:xxx:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager
根据 日志 可以写出相应的allow语句:
allow xxx default_android_service:service_manager add;
但是这样sepolicy编译会报错:
libsepol.check_assertions: 1 neverallow failures occurred
Error while expanding policy
default_android_service会导致权限放大,所以要写在 service.te文件中添加:
type xxx_service, service_manager_type;

相应的allow语句改成这样:
allow xxx xxx_service:service_manager add;

service_contexts文件中添加:
xxx.service u:object_r:xxx_service:s0
其中的xxx.service就是Native Service代码中defaultServiceManager()->addService的名字。

至此服务可以正常启动了.
完整的xxx.te:
# xxx - xxx daemontype
xxx, domain;
type xxx_exec, exec_type, file_type;
init_daemon_domain(xxx)
binder_use(xxx)
allow xxx xxx_service:service_manager add;

猜你喜欢

转载自blog.csdn.net/dpppppp/article/details/53513389