SEAndroid策略分析(三):类型强制和角色声明

类型强制

TE规则语法: 规则名称源类型目标类型:客体类别许可

规则名称    allow,dontaudit,auditallow和neverallow。
源类型      授予访问的类型,通常是进程尝试访问的域类型。
目标类型    客体的类型,它被授权可以访问源类型。
客体类别    客体的类别。
许可        表示主体对客体访问时允许的操作类型(也叫做访问向量)。

 

规则名称

1允许规则:allow

allow 源类型 目标类型:客体类别许可

allow domain device:fileread;(来自domain.te45)

这个allow规则的源类型为domain,目标类型为device,客体类别file,许可read,这个规则可以解读为"允许domain读取类型为device的文件"。

2审核规则:audit

默认情况下,SELinux不会记录任何允许的访问检查,只会记录被拒绝的访问检查。

dontaudit规则,它指出哪一个访问尝试被拒绝时不审核,这样就覆盖了SELinux默认的审核所有拒绝的访问尝试的行为。

SEAndroid策略分析(三):类型强制和角色声明_第1张图片

auditallow规则

记录允许的访问

暂时没发现SEAndroid中有这种规则

Neverallow规则

指定永远不会被allow规则执行的访问,主要是以防万一的作用。因为在载入规则时,neverallow规则会先于allow规则载入,所以,当规则冲突时(同时存在neverallow禁止规则和allow允许规则),会产生编译错误。

SEAndroid策略分析(三):类型强制和角色声明_第2张图片

源类型与目的类型

类型声明

使用type语句进行声明:type类型名称[,属性集];

type adbd, domain,mlstrustedsubject;来自adbd.te3

seandroid的20个attributes在 文件:attributes 中定义

源类型和目标类型都可以是attribute,并且没有数量限制,可以在源和目标字段处列出多个类型和属性,如果有多个类型或属性时,它们之间使用空格进行分隔,并使用大括号将它们括起来,如:

allow bluetooth { tun_device uhid_device hci_attach_dev}:chr_filerw_file_perms;  来自bluetooth.te13

l        特殊类型self:

关键字self说明目标类型使用的源类型自身,即目标类型等于源类型。只能出现在目的类型的位置。

allow domain self:dir r_dir_perms;来自domain.te19

等同于 allowdomain domain:dir r_dir_perms

l        “非”特殊操作符

用于从一个属性中移除某个类型

allow domain { exec_type -sbin_t } : fileexecute;

allow domain { -sbin_t exec_type } : fileexecute;

 

客体类别

客体类别可以是多个,使用大括号括起来

allow appdomain domain:{ file lnk_file }r_file_perms; 来自cts.te14

等同于:

allow appdomain domain:file   r_file_perms;

allow appdomain domain:lnk_file  r_file_perms;

 

许可

许可可以是多个,使用大括号括起来,用空格隔开

Line 8: allow domain tmpfs:file { read getattr };来自domain.te8

特殊许可操作符

l        通配符*

包括了客体类别的所有许可

allow adbd self:tcp_socket *;  来自adbd.te9

l        求补算操作符~

除了类出的许可外,其它的许可都包括

SEAndroid策略分析(三):类型强制和角色声明_第3张图片

类型规则

类型规则在创建客体或在运行过程中重新标记时指定其默认类型

type_transition    在域转换过程中标记行为发生时以及创建客体时,指定其默认的类型。

域转换

这是一个SELinux当中的域转换经典例子,在这里引用它,只为了更好地理解域转换

SEAndroid策略分析(三):类型强制和角色声明_第4张图片
用户joe的进程在user_t域,他想要修改密码,于是fork出一个新的process企图去修改密码。密码们都存在/etc/shadow当中,规则说,只有passwd_t类型的进程才可以去修改这个文件,joe同学fork出来的新进程继承了父进程的user_t域怎么办?得找个方法完成域转换,方法就是,运行/usr/bin/passwd文件,这是一个可执行文件,它的类型是passwd_exec_t,运行了它,就可以把自己的域转换到passwd_t了。这个过程中,包括了三个许可规则。

1、 进程的新域类型对可执行文件类型有entrypoint 访问权

只有运行了passwd_exec_t类型的file(/usr/bin/passwd),进程才能转到passwd_t域

allow passwd_t passwd_exec_t : file entrypoint;

passwd_t域将passwd_exec_t类型的file(/usr/bin/passwd)作为entrypoint

2、进程的当前(或旧的)域类型对入口文件类型有execute访问权

user_t类型的进程有权去运行passwd_exec_t类型的file(/usr/bin/passwd)

allow user_t passwd_exec_t : file {getattr execute};

user_t域对passwd_exec_t类型的file(/usr/bin/passwd)有execute权限

3、进程当前的域类型对新的域类型有transition访问权

user_t域有权转换到passwd_t域

allow user_t passwd_t : process transition;

user_t域对passwd_t类型的process有transition权限

 

特别的dyntransition

process客体类别许可dyntransition,引入这个许可主要是为了和其它系统保持兼容,它允许进程在请求时转换它的域类型,而不是在刚刚执行时,这种进程转换不安全,因为它允许域在新的域中执行任何代码,这样就消除了两个域之间的距离。

 SEAndroid策略分析(三):类型强制和角色声明_第5张图片


默认域转换:type_transition

type_transition user_t passwd_exec_t : process passwd_t;

在上面的例子中的三个许可,只是保证了修改密码时需要的域转换能够成功,可是用户才不懂什么域转换,更不会知道修改一下密码都要转来转去的。好吧,用户既然不知道,那就让计算机知道吧。。。

当一个类型为user_t的进程执行一个类型为passwd_exec_t的文件时,进程类型将会尝试转换,除非有其它请求,默认是换到passwd_t。这是一个默认转换规则,有了它,计算机在发现用户想要改密码时,就会根据这条规则进行必要的域转换。

规则中可以同时指定多个源类型,只要使用大括号将它们括起来,并用空格进行分隔就可以了,同样,我们还可以使用属性,在类型规则中列出类型和属性集,如:

type_transition { user_t sysadm_t }passwd_exec_t : process passwd_t;

这条type_transition规则在源列表中包括两个类型:user_t和sysadm_t。这条规则将会展开为两条规则,前面这条规则与下面这两条规则的含义完全一样:

#这两条规则.
type_transition user_t passwd_exec_t : process passwd_t;
type_transition sysadm_t passwd_exec_t : processpasswd_t;

 

在SEAndroid中,以下两种情况会发生域转换:

  1. 某个程序被执行时,其相应的进程会处在相应的domain中,但当程序根据需要又执行了另一个程序时,进程就需要根据typetransition规则进行domaintransition以获得必要的权限从而使新进程能顺利访问到相关文件。
  2. 另一个transition的原因是原有的domain权限过大,为了不让新启动的进程也继承过大的权限,因此需要domaintransition。在SEAndroid中几乎全部daemon进程都需要从init进程中启动,这就需要从initdomian转换到daemondomain这一操作

(客体)类型转换 

客体转换规则为新创建的客体指定一个默认的类型,实际上,我们通常是在与文件系统有关的客体(如filedirlnk_file等)上使用这种type_transition规则,和域转换一样,这些规则只会引发一个默认客体标记尝试,也只有策略允许了有关的访问权时,尝试才会成功。

SEAndroid策略分析(三):类型强制和角色声明_第6张图片

这条type_transition规则指出当一个类型为wpa的进程在一个类型为wifi_data_file的目录下创建一个sock_file文件时,默认情况下,新创建的文件类型应该为wifi_data_file,这条规则使得新建的文件从wifi_data_file转到wpa_socket域。

在这个例子中,wifi_data_file隐含关联了dir客体类别,因为它是唯一能够容纳文件的客体类别,同样,和前面一样,策略必须允许对默认标记的访问,对于这个例子,对类型为wifi_data_file的目录的访问权需要包括add_namewritesearch,对类型为wpa_socket的文件要有readwrite访问权。

 

角色声明

关联用户和角色

SEAndroid策略分析(三):类型强制和角色声明_第7张图片

useru roles { r }

将用户u和角色r关联起来,这条语句告诉用户u和角色r在安全上下文中是可以共存的,如果没有这条语句,用户u和角色r进程安全上下文将是无效的,SELinux将会拒绝创建它们,最后拒绝进行域转换。

SEAndroid只有一个用户u

关联角色和类型

SEAndroid当中只有两个角色:r和object_r

 SEAndroid策略分析(三):类型强制和角色声明_第8张图片

role语句声明角色标识符以及与声明的角色有关的类型,前面的语句声明角色r以及与这个角色关联的类型domain,这个关联意味着domain类型在安全上下文中允许与角色r共存,如果没有这个role语句,就不能创建新的上下文u:r:domain,

domain是一个attribute,所以u:r:xxx,xxx是属于domain的就可以创建。(关于attribute,参看文件 attributes)

user语句类似,要使进程安全上下文有效,role语句也是必需要有的,如果没有role语句关联类型domain,即使TE策略允许,域转换也会失败。

 

客体都有特殊的角色object_r,它是所有客体代表性的角色,这个角色是硬编码进SELinux的,它是不需要声明的,对于所有类型都是隐含允许的,你不要尝试声明角色object_r

你可能感兴趣的:(SEAndroid)