Android selinux权限设置

在做指纹的过程中遇到了很多权限设置的问题,sepolicy权限。

selinux权限设置

案例一 db访问不了了

背景

有需求需要db目录修改,由/data目录转到/data/app目录之后,结果出现生成不了db文件的问题。

解决方案及过程

  • 最终解决方案

在系统fingerprint.te里添加权限

allow fingerprintserver apk_data_file:dir {read write open ioctl execute search getattr add_name create_dir_perms};

allow fingerprintserver apk_data_file:file {read write open ioctl create_file_perms};

第一句意思是允许fingerprintserver类型对apk_data_file类型的目录(dir)执行 read 、 write 、open 等操作

第二句意思是允许fingerprintserver类型对apk_data_file类型的文件(file)执行 read 、 write 、open 等操作

  • 如何判断的fingerprintserver类型、apk_data_file类型以及要执行什么操作

由于db文件是在/data/app目录下,那么肯定是要对/data/app目录下的文件进行操作。

所以我们只要找一下/data/app所在的域

查看/data/app目录所在的域 , adb shell 进入data目录,并执行如下命令

root@XXX :/data # ls -Z

drwxrwx— system system u:object_r:system_data_file:s0 amit

drwxrwxr-x system system u:object_r:anr_data_file:s0 anr

drwxrwx–x system system u:object_r:apk_data_file:s0 app

drwx—— root root u:object_r:asec_image_file:s0 app-asec

drwxrwx–x system system u:object_r:system_data_file:s0 app-lib

可以看出来data目录下有很多子目录,这里列出了amit 、anr、app、app-asec、app-lib等子目录,

其中app目录所在的域为apk_data_file就是这么找的。

  • 那为什么是 fingerprintserver 类型

前提是我们知道谁即哪个进程操作了这个db,

本例中是fp_native_service访问db

知道谁操作了这个db可以用以下方法查找进程所在的域 , adb shell 然后作如下操作

root@XXX :ps -Z

u:r:drmserver:s0 drm 302 1 /system/bin/drmserver

u:r:mediaserver:s0 media 303 1 /system/bin/mediaserver

u:r:fingerprintserver:s0 system 258 1 /system/bin/fp_native_service

u:r:installd:s0 install 304 1 /system/bin/installd

u:r:keystore:s0 keystore 306 1 /system/bin/keystore

这里没有将所有进程都列出来,只列出了部分进程,

但可以看到fp_native_service所在的域是fingerprintserver

即fingerprintserver类型的进程要对apk_data_file类型的文件进行某些操作

  • 如何判断要执行什么操作

即排查是哪个权限问题

kenel.log中关键错误信息如下 这里搜的是 avc: denied

[ 486.936152] (0)[286:logd.auditd]type=1400 audit(1420041749.210:15756): avc: denied { write } for pid=5927 comm=”fp_native_servi” name=”app” dev=”mmcblk0p22″ ino=425985 scontext=u:r:fingerprintserver:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0

其实log里已经包含了所有问题了。

scontext=u:r:fingerprintserver:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0

那怎么知道是不是sepolicy权限引起的问题

判断是否是sepolicy权限问题

adb shell 之后执行setenforce 0可以暂时去除sepolicy权限 (不用重启机器,而且重启之后权限又恢复成原来的了)

具体操作为:

C:\Users>adb shell root@XXX :/ # setenforce 0 setenforce 0

sepolicy权限去除之后发现db文件可以生成了。说明是sepolicy权限的问题。

这个setenforce 0 后面的零是什么意思 (只能是0或者1)

usage: setenforce [ Enforcing | Permissive | 1 | 0 ]

setenforce 0 设置SELinux 成为Permissive模式 (不检测sepolicy权限,但是会将违反权限的操作记录到log)

setenforce 1 设置SELinux 成为Enforcing模式 (强制检测sepolicy权限)

selinux sepolicy权限语法规则

查看当前进程拥有的selinux权限

查看进程拥有的selinux权限,adb shell 然后执行 ps -Z

LABEL USER PID PPID NAME

u:r:servicemanager:s0 system 260 1 /system/bin/servicemanager

u:r:vold:s0 root 261 1 /system/bin/vold

u:r:surfaceflinger:s0 system 262 1 /system/bin/surfaceflinger

u:r:init:s0 root 263 1 /system/bin/sh

u:r:kernel:s0 root 273 2 kauditd

u:r:ccci_fsd:s0 radio 274 1 /system/bin/ccci_fsd

u:r:ccci_mdinit:s0 system 275 1 /system/bin/ccci_mdinit

u:r:kernel:s0 root 277 2 kworker/3:2H

LABEL里

u:r:servicemanager:s0

uandroid只定义了一个user r:进程统一定义成r  文件统一定义成 object_r servicemanager:进程所属的域 , 不唯一。 s0:一种安全等级

查看当前文件拥有的selinux权限

查看文件拥有的selinux权限需要执行 ls -Z

root@XXX :/data # ls -Z

drwxrwx— system system u:object_r:system_data_file:s0 amit

drwxrwxr-x system system u:object_r:anr_data_file:s0 anr

drwxrwx–x system system u:object_r:apk_data_file:s0 app

drwx—— root root u:object_r:asec_image_file:s0 app-asec

drwxrwx–x system system u:object_r:system_data_file:s0 app-lib

u:android定义的user,只有一个 object_r:代表是一个文件 apk_data_file:这种代表文件所属的域,看有的解释说可以理解成type s0:一种安全等级

mtk平台 selinux有三种工作模式

\bootable\bootloader\lk\platform\mtXXXX\rules.mk

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

SELINUX_STATUS值代表的含义如下:

1:disabled (不检测权限)

2:permissive (警告模式运行,所有操作都被允许,但是如果违反权限会被记录到日志,目测就是kernel.log)

3:enforcing (强制检测)

sepolicy权限设置报错

ERROR: end of file in comment

这是由于文件最后加了 注释

例如 type gx_fpd_data_file, file_type, data_file_type; ######## end ####

Multiple same specifications for 这个是重复定义了。

本来是external/sepolicy权限已经定义了 结果在device/mediatek/common/sepolicy目录下又定义了一遍
 
///////////////////////////////////////////////////////////////////////

SELinux/SEAndroid 实例简述 TE语言规则

一. 基本语法
很多te文件集中在\external\sepolicy文件夹下,MTK也有很多自定义的在\device\mediatek\common\sepolicy。它的最基本样式是
      

  1. allow factory powerctl_prop:property_service set;
  2. allow factory ttyGS_device:chr_file { read write open ioctl};
  3. allow factory ttyMT_device:chr_file { read write open ioctl};
  4. allow factory irtx_device:chr_file { read write ioctl open };
  5. allow factory devpts:chr_file { read write getattr ioctl };

这些allow语句就是最基本的te语句了,相似的te语句的会被归类在一个的te文件下面。如上面的语句是作用于factory,则会在
factory
.te文件里。
\external\sepolicy集中了很多系统定义的te文件 

文件名归类
mac_permissions.xmlApp进程
seapp_contextsApp数据文件
file_contexts系统文件
property_contexts系统属性

最基本的语法为:
   

  1. /*
  2. rule_name:规则名,分别有allow,dontaudit,neverallow等
  3. source_type:主要作用是用来填写一个域(domain)
  4. target_type:类型
  5. class:类别,主要有File,Dir,Socket,SEAndroid还有Binder等
  6. perm_set:动作集
  7. */
  8. rule_name source_type target_type:class perm_set

我们
 
从上面拿一个实例下来分析一下:

  1. /*
  2. 用中文来表述是:允许factory域里的进程或服务
  3. 对类型为ttyMT_device的类别为文件(file)
  4. 执行open,read,write,ioctl权限
  5. */
  6. allow factory ttyMT_device:chr_file { read write open ioctl};

file_contexts里面显式定义了哪些文件属于ttyMT_device类型的

  1. /dev/ttyMT.* u:object_r:ttyMT_device:s0

te表达式基本上就是这样: rule_name:规则名称,除了有allow还有dontaudit,auditallow和neverallow source_type:源类型,对应一个很重要的概念——–域(domain) tartget_type:目标的类型,SELinux一个重要的判断对象 class:类别,目标(客体)是哪种类别,主要有File,Dir,Socket,SEAndroid还有Binder等,在这些基础上又细分出设备字符类型(chr_file),链接文件(lnk_file)等。可以通过ls -l查看文件类型 perm_set:动作集

从上到下按顺序介绍一下:
rule_name:
《Android selinux权限设置》  allow:允许某个进程执行某个动作 auditallow:audit含义就是记录某项操作。默认SELinux只记录那些权限检查失败的操作。 auditallow则使得权限检查成功的操作也被记录。注意,allowaudit只是允许记录,它和赋予权限没关系。赋予权限必须且只能使用allow语句。 dontaudit:对那些权限检查失败的操作不做记录。 neverallow:没有被allow到的动作默认就不允许执行的。neverallow只是显式地写出某个动作不被允许,如果添加了该动作的allow,则会编译错误

source_type:

指定一个“域”(domain),一般用于描述进程,该域内的的进程,受该条TE语句的限制。用type关键字,把一个自定义的域与原有的域相关联 最简单地定义一个新域的方式为:

  1. type shell, domain

上面这句话的意思是,赋予shell给domain属性,同时,shell与属于domain这个集合里。如果有一个allow domain xxxxx 的语句,同样地也给了shell xxxxx的属性

target_type:

指定进程需要操作的客体(文件,文件夹等)类型,同样是用type与一些已有的类型,属性相关联
以上面的
ttyMT_device为例:

  1. //定义一个类型,属于dev_type属性
  2. type ttyMT_device, dev_type;
  3. //属性dev_type在external/sepolicyattributes的定义如下
  4. attribute dev_type;

attribute关键字定义一个属性,type可以与一个或多个属性关联,如

  1. type usb_device, dev_type, mlstrustedobject;

另外,还有一个关键字typeattribute,type有两个作用,定义(声明)并关联某个属性。可以把这两个作用分开,type定义,typeattribute进行关联

  1. #定义httpd_user_content_t,并关联两个属性
  2. type httpd_user_content_t, file_type, httpdcontent;
  3. 分成两条语句进行表述:
  4. #定义httpd_user_content_t
  5. type httpd_user_content_t;
  6. #关联属性
  7. typeattribute httpd_user_content_t file_type, httpdcontent;

然后你会有一个疑问,这么多属性,这些属性有什么作用,这些属性会有一个地方显式地说明这个属性拥有什么权限,在external/sepolicy/domain里就有非常详细的描述。另个在external/sepolicy/attributes里定义了很多属性,下面截取了一些常见的定义

  1. # All types used for devices.
  2. attribute dev_type;
  3. # All types used for processes.
  4. attribute domain;
  5. # All types used for filesystems.
  6. attribute fs_type;
  7. # All types used for files that can exist on a labeled fs.
  8. # Do not use for pseudo file types.
  9. attribute file_type;
  10. # All types used for domain entry points.
  11. attribute exec_type;
  12. # All types used for property service
  13. attribute property_type;
  14. # All service_manager types created by system_server
  15. attribute system_server_service;
  16. # All domains that can override MLS restrictions.
  17. # i.e. processes that can read up and write down.
  18. attribute mlstrustedsubject;
  19. # All types that can override MLS restrictions.
  20. # i.e. files that can be read by lower and written by higher
  21. attribute mlstrustedobject;
  22. # All domains used for apps.
  23. attribute appdomain;
  24. # All domains used for apps with network access.
  25. attribute netdomain;
  26. # All domains used for binder service domains.
  27. attribute binderservicedomain;

class: 客体的具体类别。用class来定义一个客体类别,具体定义方式 如下

  1. [external/sepolicy/security_classes示例]
  2. # file-related classes
  3. class filesystem
  4. class file #代表普通文件
  5. class dir #代表目录
  6. class fd #代表文件描述符
  7. class lnk_file #代表链接文件
  8. class chr_file #代表字符设备文件
  9. ......
  10. # network-related classes
  11. class socket #socket
  12. class tcp_socket
  13. class udp_socket
  14. ......
  15. class binder #Android平台特有的binder
  16. class zygote #Android平台特有的zygote

perm_set:
具体的操作,系统的定义在
external/sepolicy/access_vectors。
有两种定义方法。
用common命令定义:

  1. 格式为:common common_name { permission_name ... }
  2. common定义的perm set能被另外一种perm set命令class所继承
  3. 如:
  4. common file {
  5. ioctl read write create getattr setattr lock relabelfrom relabelto
  6. append unlink link rename execute swapon quotaon mounton

用class命令定义:

  1. class class_name [ inherits common_name ] { permission_name ... }
  2. inherits表示继承了某个common定义的权限
  3. 注意,class命令它不能被其他class继承
  4. 继承一个common,如继承了file common
  5. class dir
  6. inherits file
  7. {
  8. add_name
  9. remove_name
  10. reparent
  11. search
  12. rmdir
  13. open
  14. audit_access
  15. execmod
  16. }
  17. 不继承任何common,如
  18. class binder
  19. {
  20. impersonate
  21. call
  22. set_context_mgr
  23. transfer
  24. }
  1. 然后是一些特殊的配置文件:
  2. a. external/sepolicy/attributes -> 所有定义的attributes都在这个文件
  3. b. external/sepolicy/access_vectors -> 对应了每一个class可以被允许执行的命令
  4. c. external/sepolicy/roles -> Android中只定义了一个role,名字就是r,将rattribute domain关联起来
  5. d. external/sepolicy/users -> 其实是将userroles进行了关联,设置了user的安全级别,s0为最低级是默认的级别,mls_systemHigh是最高的级别
  6. e. external/sepolicy/security_classes -> 指的是上文命令中的class,个人认为这个class的内容是指在android运行过程中,程序或者系统可能用到的操作的模块
  7. f. external/sepolicy/te_macros -> 系统定义的宏全在te_macros文件
  8. g. external/sepolicy/***.te -> 一些配置的文件,包含了各种运行的规则

                                                                                                    —————-引用于《
android中SELINUX规则分析和语法简介



二. TE的正则表达式和集合
TE文件支持正则表达式,从下面可以看到,通配符是常用的通配符,可以度娘

  1. /sys/devices/system/cpu(/.*)? u:object_r:sysfs_devices_system_cpu:s0
  2. /sys/power/wake_lock -- u:object_r:sysfs_wake_lock:s0
  3. /sys/power/wake_unlock -- u:object_r:sysfs_wake_lock:s0
  4. /sys/kernel/uevent_helper -- u:object_r:usermodehelper:s0
  5. /sys/module/lowmemorykiller(/.*)? -- u:object_r:sysfs_lowmemorykiller:s0
  6. #############################
  7. # asec containers
  8. /mnt/asec(/.*)? u:object_r:asec_apk_file:s0
  9. /mnt/asec/[^/]+/[^/]+\.zip u:object_r:asec_public_file:s0

需要注意的是上面的”–“,这里的“–”表示二进制文件,类似的还有

  1. #‘-b’ - Block Device ‘-c’ - Character Device
  2. #‘-d’ - Directory ‘-p’ - Named Pipe
  3. #‘-l’ - Symbolic Link ‘-s’ - Socket
  4. #‘--’ - Ordinary file

TE表达式里可以用“{}”来表示一个集合,如:

  1. /*
  2. 允许user_t对bin_t类型的文件和文件夹执行read,getattr操作
  3. */
  4. allow user_t bin_t : { file dir } { read getattr };
  5. /*
  6. 允许domain对exec_type,sbin_t类型的文件执行execute的动作
  7. */
  8. allow domain { exec_type sbin_t } : file execute;

可以在集合里使用“*”,“-” 和 “~” 三个通配符

  1. /*
  2. 允许user_t对bin_t类型的文件和文件夹执行所有操作
  3. */
  4. allow user_t bin_t : { file dir } *;
  5. /*
  6. 允许user_t对bin_t类型的文件和文件夹执行除了read,getattr以外的所有操作
  7. */
  8. allow user_t bin_t : { file dir } ~{ read getattr };
  9. /*
  10. 允许domain对exec_type类型的文件执行execute的动作,除了sbin_t以外
  11. */
  12. allow domain { exec_type -sbin_t } : file execute;

三. TE的类型转换规则
为什么要转换类型

init进程拥有系统的最高权限,如果由Init进程fork,execu出来的进程默认是与init相同的权限,这肯定是不安全的。另一个场景是,由init生成的文件,默认也是init的读写权限,不方便其他低权限的文件进行访问。

类型转换有两种类型转换: 1. 主体的域的转换 2. 客体的转换

域的转换
type_transition的完整格式为:

  1. type_transition source_type target_type : class default_type;
  2. 举个例子
  3. type_transition init_t apache_exec_t : process apache_t;

type_transition init_t apache_exec_t : process apache_t;

 init_t 进程执行type为apache_exec_t的可执行文件时,新的进程转换到apache_t域
但是上面只是告诉了转换的过程,却没有说明,有转换的权限,如果要上面的转换成功,还需要下面的语句:

  1. #首先,你得让init_t域中的进程能够执行type为apache_exec_t的文件
  2. allow init_t apache_exec_t : file execute;
  3. #然后,你还得告诉SELiux,允许init_t做DT切换以进入apache_t域
  4. allow init_t apache_t : process transition;
  5. #最后,你还得告诉SELinux,切换入口(对应为entrypoint权限)为执行pache_exec_t类型的文件
  6. allow apache_t apache_exec_t : file entrypoint;

客体的转换
例子:

  1. type_transition passwd_t tmp_t : file passwd_tmp_t;

passwd_t在tmp_t目录下创建文件时,该文件的类型转化为passwd_tmp_t。这里默认隐含了一个tmp_t类型dir,因为file的容器只能是个dir。同样的,如果要上面的语句运行成功,与需要有相应的权限说明:

  1. 对应的必须有两个前提条件:
  2. * The source domain needs permission to add file entries into the directory
  3. 这个process 必须有在这个目录下添加文件的权限.
  4. * The source domain needs permission to create file entries
  5. 这个process 必须有在这个目录下创建以这个Security Context Label 的文件权限.

如果每个转换之前都需要这样繁锁地权限声音实在很麻烦。TE里允许把这些相同的,重复使用的语句定义成一个宏,类似于函数一样。

四. TE的宏 如果把上面domain转换的例子定义成一个宏,应该定义如下:

  1. #定义domain_auto_trans宏,$1,$2等等代表宏的第一个,第二个....参数
  2. define(`domain_auto_trans', `
  3. # 先allow相关权限,domain_trans宏定义在后面
  4. domain_trans($1,$2,$3)
  5. # 然后设置type_transition
  6. type_transition $1 $2:process $3;
  7. ')
  8. #定义domain_trans宏。
  9. define(`domain_trans', `
  10. # SEAndroid在上述三个最小权限上,还添加了自己的一些权限
  11. allow $1 $2:file { getattr open read execute };
  12. allow $1 $3:process transition;
  13. allow $3 $2:file { entrypoint read execute };
  14. allow $3 $1:process sigchld;
  15. dontaudit $1 $3:process noatsecure;
  16. allow $1 $3:process { siginh rlimitinh };
  17. ')

上面的宏定义在external/sepolicy/te_macros里。客体的转换定义如下:

  1. #####################################
  2. # file_type_auto_trans(domain, dir_type, file_type)
  3. # Automatically label new files with file_type when
  4. # they are created by domain in directories labeled dir_type.
  5. #
  6. define(`file_type_auto_trans', `
  7. # Allow the necessary permissions.
  8. file_type_trans($1, $2, $3)
  9. # Make the transition occur by default.
  10. type_transition $1 $2:dir $3;
  11. type_transition $1 $2:notdevfile_class_set $3;
  12. ')
  13. define(`file_type_trans', `
  14. # Allow the domain to add entries to the directory.
  15. allow $1 $2:dir ra_dir_perms;
  16. # Allow the domain to create the file.
  17. allow $1 $3:notdevfile_class_set create_file_perms;
  18. allow $1 $3:dir create_dir_perms;
  19. ')

TE的集合也可以定义成一个宏代替,如读写文件操作集的宏:

  1. define(`x_file_perms', `{ getattr execute execute_no_trans }')
  2. define(`r_file_perms', `{ getattr open read ioctl lock }')
  3. define(`w_file_perms', `{ open append write }')
  4. define(`rx_file_perms', `{ r_file_perms x_file_perms }')
  5. define(`ra_file_perms', `{ r_file_perms append }')
  6. define(`rw_file_perms', `{ r_file_perms w_file_perms }')
  7. define(`rwx_file_perms', `{ rw_file_perms x_file_perms }')
  8. define(`create_file_perms', `{ create rename setattr unlink rw_file_perms }')

使用方式是:

  1. allow demo demo_device:chr_file rw_file_perms;

 参考文章:
http://blog.csdn.net/Innost/article/details/19299937?locationNum=2   系列文章
http://www.2cto.com/kf/201504/390742.html
http://blog.csdn.net/luoshengyang/article/details/35392905  系列文章
http://blog.csdn.net/myarrow/article/details/10105961

    原文作者:jaczen
    原文地址: https://blog.csdn.net/jaczen/article/details/73028302
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞