Selinux 语言:
左边的一列是Security Context。
u:r:init:s0的意思是
- u为user。SEAndroid中定义了一个SELinux,值为u
- r为role的意思。一个u可以属于多个r,不同的role具有不同的权限。
- init 表示该进程所属的domain 为init。
- s0和SELinux是为了满足军用和教育行业而设计的MultiLevel Security。
- u:是user的意思,表示创建这个文件的SELinux user。
- object_r:文件是死的,他没法扮演角色,所以在SELinux中,死的东西都用objec_r来表示它的role。
- cgroup是死的东西的Type,和进程的domain是一个意思。
- s0,MLS的级别
SELinux的规范,完整的SContext字符串是:
user:role:type[:range]
TE模块
/external/sepolicy/heathd.te
语法意义如下:
- allow: TE的allow语句,表示允许,此外还有allowaudit, dontaudit,neverallow等
- healthd: source type,常用domain称之
- self:target type,这里的self表示和source type是一样的。
- capability:是object class,表示给domain赋予的能力。还有file,dirsocket等
- { net_admin sys_tty_config dac_override } 是其允许的操作,dac_override,是调过DAC(discretionary access control)策略的读写以及执行检查。可以使用man capabilities, net_admin是网络相关的各种权限。
其完整格式为:
Rule_name source_type target_type: class perm_set
allow 语句中的object class和perm class
/external/sepolicy/security_classes
# Classes marked as userspace are classes
# for userspace object managers
class security
class process
class system
class capability
# file-related classes
class filesystem
class file
class dir
class fd
class lnk_file
class chr_file
class blk_file
class sock_file
class fifo_file
文件permission set
[external/sepolicy/access_vectors]
common file
{
ioctl
read
write
create
getattr
setattr
lock
relabelfrom
relabelto
append
unlink
link
rename
execute
swapon
quotaon
mounton
}
Labeling
sid和sid_context
Android系统启动后,init进程会将一个编译完的安全策略文件传递给kernel以初始化linux kernel中的SELinux相关的模块,然后kernel根据其中信息进行打标签。
Linux security Module(LSM)初始化时需要的信息以及SContext信息保存在两个特殊的文件中,以Android为例,它们是:
initial_ids:定义了LSM初始化时相关的信息。SID是SELinux中的Security Identifier。
initial_sid_context:为SID设置的最初的SContext值。
[/external/sepolicy/initial_sids]
# Define initial security identifiers
#
sid kernel
sid security
sid unlabeled
sid fs
sid file
sid file_labels
sid init
sid any_socket
sid port
sid netif
sid netmsg
sid node
sid igmp_packet
sid icmp_socket
sid tcp_socket
sid sysctl_modprobe
sid sysctl
sid sysctl_fs
sid sysctl_kernel
sid sysctl_net
sid sysctl_net_unix
sid sysctl_vm
sid sysctl_dev
sid kmod
sid policy
sid scmp_packet
sid devnull
#initial_sid_context
sid kernel u:r:kernel:s0
sid security u:object_r:kernel:s0
sid unlabeled u:object_r:unlabeled:s0
sid fs u:object_r:labeledfs:s0
sid file u:object_r:unlabeled:s0
sid file_labels u:object_r:unlabeled:s0
sid init u:object_r:unlabeled:s0
sid any_socket u:object_r:unlabeled:s0
sid port u:object_r:port:s0
sid netif u:object_r:netif:s0
sid netmsg u:object_r:unlabeled:s0
sid node u:object_r:node:s0
sid igmp_packet u:object_r:unlabeled:s0
sid icmp_socket u:object_r:unlabeled:s0
sid tcp_socket u:object_r:unlabeled:s0
sid sysctl_modprobe u:object_r:unlabeled:s0
sid sysctl u:object_r:proc:s0
sid sysctl_fs u:object_r:unlabeled:s0
sid sysctl_kernel u:object_r:unlabeled:s0
sid sysctl_net u:object_r:unlabeled:s0
sid sysctl_net_unix u:object_r:unlabeled:s0
sid sysctl_vm u:object_r:unlabeled:s0
sid sysctl_dev u:object_r:unlabeled:s0
sid kmod u:object_r:unlabeled:s0
sid policy u:object_r:unlabeled:s0
sid scmp_packet u:object_r:unlabeled:s0
sid devnull u:object_r:null_device:s0
Domain/Type Transtion和宏
SEAndroid中,init进程的SContext为u:r:init:s0,而init创建的子进程显然不会也不可能拥有和init进程一样的SContext。那么这些子进程的SContext是怎么被打上和其父进程不一样的SContext呢?
SELinux中,上述问题被成为Domain Transtition,即某个进程的Domain切换到一个更合适的Domain中去。Domain Transitition也是需要在安全策略文件中来配置的,而且有相关的关键词。
#先要使用type_transition语句告诉SELinux
#type_transition的完整格式为:
#type_transition source_type target_type : class default_type;
#对Domain Transition 而言有如下例子:
type_transion init_t appache_exec_t:process_apache_t;
上面这个例子的解释如下:
- 当init_t Domain 中的进程执行type为apache_exec_t类型的可执行文件(fork并execv)时,其class(此处是process)所属Domain(对process 而言,肯定指Domain)需要切换到apache_t域。
要做DT,肯定要先fork一个子进程,然后通过execv打开一个新的可执行文件,所以,在type_transition语句中,target_type往往是那个可执行文件的type,default_type则表示execv执行之后,该进程默认的Domain。另外,对DT来说,class一定会是process。
DT属于Labeling一部分,但这个事情还没结束,因为打标签也需要相关权限。所以,上述type_transition不过是开了一个头而已,要真正实时成功这个DT,还需要下面至少三个allow语句。
#首先,让init_t域中的进程能够执行type为apach_exec_t的文件
allow init_t apache_exec_t: file execute;
#然后,告诉SELinux,允许init_t做DT切换以进入apache_t域
allow init_t apache_t:process transition;
#最后,还得告诉SELinux,切换入口为执行apache_exec_t类型的文件
allow apache_t apache_exec_t : file entrypoint
因为kernel中,从fork到execv工设置了三处security检查点,所以需要三个权限。
除了DT外,还有针对Type的Transition。举个例子,假设目录A的SContext为u:r:dir_a,那么默认情况下在该目录下创建的文件都具有u:r:dir_a这个SContext。
和DT类似TT语句也是type_transion,而且要顺利完成Transition,也需要申请相关权限。
[external/sepolicy/te_macros]
# 定义file_type_trans(domain, dir_type, file_type)宏
#
define(`file_type_trans', `
# ra_dir_perms是一个宏,由global_macros文件定义,其值为:
#define(`ra_dir_perms', `{ r_dir_perms add_name write }')
allow $1 $2:dir ra_dir_perms;
# create_file_perms也是一个宏,定义在global_macros文件中,其值为:
# define(`create_file_perms', `{ create setattr rw_file_perms
# link_file_perms }')
#而r_dir_perms=define(`r_dir_perms', `{ open getattr read search ioctl }
allow $1 $3:notdevfile_class_set create_file_perms;
allow $1 $3:dir create_dir_perms;
')
# 定义file_type_auto_trans(domain, dir_type, file_type)宏
#该宏的含义是:当domain域中的进程在某个Type为dir_type的目录中创建文件时,该文件的
#SContext应该是file_type
define(`file_type_auto_trans', `
file_type_trans($1, $2, $3)
type_transition $1 $2:dir $3;
#notdevfile_class_set也是一个宏,由global_macros文件定义,其值为
# define(`notdevfile_class_set', `{ file lnk_file sock_file fifo_file }')
type_transition $1 $2:notdevfile_class_set $3;
')
在上面的例子中,scontext是init,init里如不允许execute+no_trans等权限,如何修改让其变成如下的的呢
《device/qcom/sepolicy/common/file_context》
/system/bin/XXflinger u:object_r:XXflinger_exec:s0
《external/sepolicy/XXflinger.te》
type XXflinger, domain;
type XXflinger_exec, exec_type, file_type;
init_daemon_domain(lumenflinger);
allow XXflinger self:capability { dac_override };
allow XXflinger system_file:file { execute_no_trans };
allow XXflinger servicemanager:binder { call transfer};
allow XXflinger platform_app:binder { call transfer};
allow XXflinger sysfs:file { write };