SeLinux全称为安全增强式 Security-Enhanced Linux(SeLinux),是一个在内核的强制存取控制(MAC)安全性机制。SeLinux的整体架构和原理都比较简单,使用也不复杂,其复杂的地方在于规则非常复杂,每个进程都要有规则策略;

图片来源:https://www.cnblogs.com/klb561/p/14411953.html
SeLinux 遵从最小权限的理念,在开启SeLinux的情况下(enforcing 模式),所有访问默认是被拒绝的,而有一系列例外的策略来允许系统的元素(服务、进程、用户)具备访问资源的权限,例外的策略通过类型强制描述文件进行描述。不同于基于用户和角色的权限访问控制,Selinux的规则可以做到,与用户/角色没有关系,策略针对每一个可运行的进程进行配置,很好的避免了越权访问的问题,但正因为麻烦,所以很多服务器上默认是关闭了Selinux配置;
Linux内核提供了一个安全模块框架层,这个公共框架类似于文件系统中的VFS。它为调用者提供统一的接口。之所以要提供统一接口是因为Linux内核不仅仅支持SELinux安全特性,还支持Apparmor等很多安全特性。以打开文件为例,当我们调用内核中打开文件的接口是,在其内部会调用security_file_open函数。该函数就是Linux内核安全框架(LSM)的公共接口。然后该函数通过函数指针的方式调用所有注册到LSM的安全模块。以SELinux为例,最终会调用到selinux_file_open函数。

图片来源:https://www.cnblogs.com/klb561/p/14411953.html
TE: TYPE ENFORECE 规则 类型强制策略;
用来描述SeLinux规则的文件就是TE文件,TE 规则是将权限与程序的访问结合在一起;
一个简单的 AV 规则有:
规则名称,源类型,目标类型,客体类别和许可操作,如:
allow user_t bin_t : file execute;
这个 allow 规则的源类型为 user_t,目标类型为 bin_t,客体类别 file,许可 execute,这个规则可以解读为"允许 user_t 执行类型为 bin_t 的文件"。
规则名称包括:
allow 表示允许主体对客体执行允许的操作。
dontaudit 表示不记录违反规则的决策信息,且违反规则不影响运行。
auditallow 表示允许操作并记录访问决策信息。
neverallow 表示不允许主体对客体执行指定的操作
如auditallow 规则,只需要替换掉规则名称即可:
auditallow user_t bin_t : file execute;
源类型通常是进程名,目标类型则是操作的客体类别
与文件有关的客体类别  | blk_file  | 块文件  | 
che_file  | 字符文件  | |
dir  | 目录  | |
fd  | 文件描述符  | |
fifo_file  | 命名管道  | |
file  | 普通文件  | |
filesystem  | 文件系统(如一个真实的分区)  | |
lnk_file  | 符号链接  | |
sock_file  | UNIX域套接字  | |
与网络有关的客体类别  | ||
association  | IPSec安全联盟  | |
key_socket  | PF_KEY协议家族的套接字、用于管理IPSec中的密钥  | |
netif  | 网络接口 如eth0  | |
netlink_audit_socket  | 用于控制审核的Netlink套接字  | |
netlink_dnrt_socket  | 用于控制DECnet路由的Netlink套接字  | |
netlink_firewall_socket  | 用于创建用户空间防火墙过滤器的Netlink套接字  | |
netlink_ip6fw_socket  | 用于创建用户空间防火墙过滤器的Netlink套接字  | |
netlink_kobject_uevent_socket  | 用于创建用户空间接收内核事件通知的Netlink套接字  | |
netlink_route_socket  | 用于控制和管理网络资源如路由表和IP地址的Netlink套接字  | |
netlink_selinux_socket  | 用于接收策略载入通知,强制模式切换和清空AVC缓存的Netlink套接字  | |
netlink_tcpdiag_socket  | 用于监视TCP连接的Netlink套接字  | |
netlink_soecket  | 所有其它的Netlink套接字  | |
netlink_xfrm_socket  | 用于获取、管理和设置 IPsec 参数的  | |
Netlink  | 套接字  | |
node  | 代表一个 IP 地址或一段 IP 地址的主机  | |
packet_socket  | 协议在用户空间执行的原始套接字  | |
rawip_socket  | 既不是 TCP 也不是 UDP 的 IP 套接字  | |
tcp_socket  | TCP 套接字  | |
udp_socket  | UDP 套接字  | |
unix_dgram_socket  | 本地机器上(unix 域)的 IPC 数据报套接字  | |
unix_stream_socket  | 本地机器上(unix 域)的 IPC 流套接字  | |
IPC有关的客体类别  | ipc  | 已经没有使用了  | 
msg  | 消息队列中的消息  | |
msgq  | 消息队列  | |
sem  | 信号量  | |
shm  | 共享内存段  | |
其它杂类客体类别  | capability  | Linux中标识权利的特权  | 
process  | Selinux中的进程  | |
security  | 内核中的Selinux安全服务器  | |
system  | 整个系统  | |
文件客体类别  | file  | |
append  | 附加到文件内容(即用 o_append 标记打开)  | |
create  | 创建一个新文件  | |
entrypoint*  | 通过域转换,可以用作新域的入口点的文件  | |
execmod*  | 使被修改过的文件可执行(含有写时复制的意思)  | |
execute  | 执行,与标准 Linux 下的 x 访问权一致  | |
execute_no_trans*  | 在访问者域转换的执行文件(即没有域转换)  | |
ioctl  | ioctl(2)系统调用请求  | |
link  | 创建一个硬链接  | |
lock  | 设置和清除文件锁  | |
mounton  | 用作挂载点  | |
quotaon  | 允许文件用作一个限额数据库  | |
swapon  | 不赞成使用。它用于将文件当做换页/交换空间  | |
relabelfrom  | 从现有类型改变安全上下文  | |
relabelto  | 改变新类型的安全上下文  | |
rename  | 重命名一个硬链接  | |
setattr  | 改变文件的属性,如访问模式(例如:chmod,部分 ioctls)  | |
getattr  | 获取文件的属性,如访问模式(例如:stat,部分ioctls)  | |
unlink  | 移除硬链接(删除)  | |
write  | 写入文件内容,对应标准 Linux 下的 w 访问权  | |
read  | 读取文件内容,对应标准 Linux 下的 r 访问权  | |
进程许可类别  | dyntransition  | 允许进程动态地转移到新的上下文中  | 
process  | execheap  | 产生一个堆栈可执行体  | 
{read.execute, getattr}  | execmem  | 产生一个匿名的映像、堆栈和堆的创建,或可写的私有文件映像可执行体  | 
execstack  | 产生进程堆栈可执行体  | |
fork  | 派生两个进程  | |
getattr  | 通过/proc/[pid]/attr/目录获取进程的属性  | |
setcap  | 为进程设置允许的 Linux 能力  | |
getcap  | 获取这个进程允许的 Linux 能力  | |
setpgid  | 设置进程的组进程 ID  | |
getpgid  | 获取进程的组进程 ID  | |
setsched  | 设置进程的优先级  | |
getsched  | 获取进程的优先级  | |
getsession  | 获取进程的会话 ID  | |
noatsecure  | 禁用清除安全模式环境,允许进程在 execve(2)上禁用glibc 的安全模式特性  | |
ptrace  | 跟踪程序执行的父进程或子进程  | |
rlimitnh  | 在 execve(2 上)继承进程资源限制  | |
setcurrent  | 设置当前的进程上下文,当进程试图执行一个动态域转换时,这是第一个检查的能力  | |
setexec  | 下一次调用 execve(2)时覆盖默认的上下文  | |
setfscreate  | 允许进程设置由其创建的客体的上下文  | |
setrlimit  | 改变进程硬性资源限制  | |
share  | 允许与克隆的或派生的进程共享状态  | |
siginh  | 在 execve(2)上继承信号状态  | |
sigkill  | 发送 sigkill 信号  | |
sigchld  | 发送 sigchld 信号  | |
signal  | 发送一个非 sigkill,sigstop 或 sigchld 的信号  | |
signull  | 不发送信号测试另一个进程的存在性  | |
sigstop  | 发送 sigstop 信号  | |
transition  | 在 execve(2)上转换到一个新的上下文  | 
特殊类型 self
策略语言保留了一个关键字 self,它用于 AV 规则中的目标区域,可以当做一个类型使
用,如下面这两条规则是相等的:
# 这两条规则是相等的
allow user_t user_t : process signal;
allow user_t self : process signal
2021/07/22更新:Android系统对Selinux的配置,关键搞清楚如何配置新增进程的规则:
SELinux 依靠标签来匹配操作和政策。标签用于决定允许的事项。套接字、文件和进程在 SELinux 中都有标签。
SELinux 在做决定时需参照两点:
一是为这些对象分配的标签;
二是定义这些对象如何交互的政策;
标签采用以下形式表示:user:role:type:mls_level,其中 type 是访问决定的主要组成部分,可通过构成标签的其他组成部分进行修改。对象会映射到类,对每个类的不同访问类型由权限表示。
域(domain):一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。
域的声明使用
type backup_t;
政策规则采用以下形式:
allow domains types:classes permissions;,其中:
domains - 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。
types - 一个对象(例如,文件、套接字)或一组对象的标签。
classes - 要访问的对象(例如,文件、套接字)的类型。
permissions- 要执行的操作(例如,读取、写入)。
使用政策规则时将遵循的结构示例:
allow appdomain app_data_file:file rw_file_perms;
表示所有应用域都可以读取和写入带有 app_data_file 标签的文件。请注意,该规则依赖于在 global_macros 文件中定义的宏,您还可以在 te_macros 文件中找到一些其他非常实用的宏。
可以通过属性引用一组域或类型。简单来说,属性是一组域或类型的名称。每个域或类型都可以与任意数量的属性相关联。当编写的规则指定了某个属性名称时,该名称会自动扩展为列出与该属性关联的所有域或类型。例如,domain 属性与所有进程域相关联,file_type 属性与所有文件类型相关联。
属性与类型关联
type http_user_content_t,file_type;
type httpd_user_content_t, file_type, httpdcontent;
typeattribute 语句,这个语句允许我们在声明类型时单独关联属性
#下面是两条语句
type httpd_user_content_t;
typeattribute httpd_user_content_t file_type, 
httpdcontent;
参考:https://www.cnblogs.com/klb561/p/14411953.html
2021/08/31更新
------
策略文件的加载,核心就是通过security_load_policy接口,对用户空间传进来的te镜像文件进行解析并加载(见:https://blog.csdn.net/bruk_spp/article/details/107283935)
----
init进程上下文的恢复,selinux.cpp的SetupSelinux方法中会执行selinux_android_restorecon
--
avc:access vector cache,用来缓存MAC访问控制策略,在进行策略检查的时候,先到avc中进行检查,如果没有找到,则进行根据安全上下文进行计算,将结果缓存到AVC中:
security/selinux/avc.c
struct avc_entry {
u32ssid;
u32tsid;
u16tclass;
struct av_decisionavd;
struct avc_xperms_node*xp_node;
};
ssid怎么来的:
security/selinux/ss/mls.c
int mls_context_to_sid(struct policydb *pol,
char oldc,
char **scontext,
struct context *context,
struct sidtab *s,
u32 def_sid);
void mls_sid_to_context(struct policydb *p,
struct context *context,
char **scontext);
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
 本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com
