如何设置SELinux策略规则

了解并配置SELinux1。
获取当前SELinux运行状态,getenforce可以返回三种结果:Enforced、Allowed、Disabled。
禁用表示禁用SELinux,启用表示仅记录安全警告但不阻止可疑行为,强制表示记录警告并阻止可疑行为...

SELinux权限

在了解SELinux之前,我们先了解一下Linux的两种访问控制策略:DAC和MAC

DAC,自主访问控制。
系统只提供基本的认证,完整的访问控制由开发者自己控制。
DAC将资源访问者分为三类:所有者、组和其他。
将访问权限分为读、写、执行资源三类,为资源访问者设置不同的访问权限。
访问者通常是每个用户的进程,有自己的uid/gid,匹配uid/gid和文件权限决定是否可以访问。
根据DAC机制,每个用户进程默认拥有所有用户权限。
DAC有两个严重的问题:问题一:由于Root用户拥有所有权限,DAC对Root用户的限制无效。
而LinuxKernel2.1之后,Linux根据不同的应用场景将Root权限划分为很多RootCapability,甚至普通用户也可以设置为某个RootCapability。
如果设置了CAP_DAC_OVERRIDE,普通用户也可以覆盖DAC限制。
问题2:用户进程拥有用户的所有权限,可以修改/删除用户的所有文件资源,难以防范恶意软件。

可见DAC有明显的缺陷。
一旦被入侵,获得root权限的用户进程可能是非法的并且行为异常。

MAC,强制访问控制(MandatoryAccesscontrol)。
系统对每次访问进行严格限制,具体限制策略由开发者提供。

针对DAC的缺点,LinuxMAC要求系统根据为每次登录和访问的每个文件资源定义的策略进行有针对性的审计。
系统可以控制特定进程和特定文件资源的权限。
即使root用户是root用户,其所属的不同进程也不一定能够获得root权限。
这取决于预先为进程定义的访问限制策略。
如果MAC验证无法通过,则无法进行相关操作。

与DAC相比,MAC访问控制的“主体”变成了“进程”而不是用户。
这样可以限制Root权限的滥用,同时也需要对每个权限进行更彻底的细化,从而可以限制用户对资源的访问。

SELinux是目前最好的MAC机制,也是当前的行业标准。

SELinux,即安全增强型Linux(Security-EnhancedLinux),是由美国国家安全局(NSA)发起、多个非政府组织参与制定的强制安全审查机制(MandatoryAccesscontrol,简称MAC)。
营利性组织和大学。
SELinux于2000年12月首次在GPL下发布。
目前,LinuxKernel2.6及更高版本都内置了SELinux。

SELinux分为三种模式:

Android5.x及更高版本是强制开启的,所以禁用(关闭)模式是没有用的。
通常在调试时,我们会启用Permissve(宽容模式)来尽可能多地发现问题并立即修复。
启用Enfocingmode(强制模式)以在批量生产期间保护您的系统。

显示SELinux模式:adbshel​​lgetenforce设置SELinux模式:adbshel​​lsetenforce1//0为Permissve,1为Enfocing

访问控制图SELinux:

通常我们开发过程都会涉及到配置Object、Object和SecurityPolicy。

SELinux为Linux中的所有对象分配一个安全上下文(SecurityContext),它被描述为一个标准字符串。

SecurityLabel用于关联访问的资源和安全上下文,并描述它们的对应关系。
标准格式为:resource_security_context。
即:reseser:角色:类型[:范围]。
在这种情况下,您还可以使用通配符。
例如,网。
可以匹配所有以net.开头的属性。
此外,还有*,?等正则表达式。
等待小丑。
SecurityLabel在type_contexts中定义,例如file在file_contexts中定义,service在service_contexts中定义,property在property_contexts中定义。
示例:file_contexts:

service_contexts:

显示进程的安全上下文:ps-AZ。
例如查看Settings进程的安全上下文,ps-AZ|grepsettings:u:r:system_app:s0system1381585423450420107200Scom.android.settings查看文件的安全上下文:ls-Z。
例如,查看build.prop文件的安全上下文:u:object_r:system_file:s0build.prop

TypeEnforcement(TE)是检查SecurityContext中基于类型的权限并检查给定的类型类主体类型与客体类型的某种权限是否具有访问权限是目前应用最广泛的MAC审核机制,简单易用。

TypeEnforcement规则说明:

例如logd.te和tombstoned.te中定义的TE规则: allowlogdruntime_event_log_tags_file:filerw_file_perms; dontauditdomainruntime_event_log_tags_file:文件{openread};  Auditallowtombstonedanr_data_file:文件{appendwrite}; neverallowlogd{app_data_filesystem_data_file}:dir_file_class_setwrite;

SELinux中的每个进程或文件都对应一种类型,每种类型对应一个或多个属性。
所有通用属性均在以下文件中定义:system/sepolicy/public/attributessystem/sepolicy/prebuilts/api/[buildversion]/public/attributessystem/sepolicy/prebuilts/api/[buildversion]/private/attributes其中[buildversion]是Android版本号,例如androidO是28.0。
常用属性定义:

类型对应一个或多个属性。
类型定义的格式为:typetype_name,attribute1,attribute2类型定义通常分散在各个te文件中。
例如,常用的普通文件类型在file.te中定义:

SEAndroid针对不同类型的资源定义了不同的类。
比如普通文件、套接字等,比如SELinux使用的安全性,比如为每个进程参数定义相关的类。
每个类都有相应的权限。
例如文件有读、写、创建、getattr、setattr、lock、ioctl等。
例如进程有fork、sigchld、sigkill、ptrace、getpgid、setpgid等。
这些相关类及其拥有的权限在以下文件中定义:system/sepolicy/private/access_vectorssystem/sepolicy/reqd_mask/access_vectorssystem/sepolicy/prebuilts/api/version/private/access_vectors例如:

定义完成后,在下面相应的security_classes文件中声明定义的类。
system/sepolicy/private/security_classessystem/sepolicy/reqd_mask/security_classessystem/sepolicy/prebuilts/api/versionnumber/private/security_classes例如:

请注意,类和权限定义与内核中的API相关相关性强,普通用户严禁修改。

在SELinux中,我们通常称进程为领域。
当一个进程fork另一个进程并执行(exec)一个可执行文件时,我们经常会涉及到域切换。
比如init进程,SELinux赋予了很大的权限,我们必须限制它调用的服务的权限,这涉及到从一个域切换到另一个域。
否则,将默认使用init进程。

SELinux中有一种特殊的语法:type_transitionstatement在准备转换之前,我们首先需要确保有相关的授权操作:

如下demo所示,初始化。
打开apache并切换到apache域(1)。
首先,您需要启用init_t域中的进程来执行apache_exec_t  类型的文件。
允许init_tapache_exec_t:文件{readgetattrexecute};(2)。
然后,您需要告诉SELinux允许init_t执行DT开关来访问apache_tallowinit_tapache_t:processtransition;(3)域。
然后,你必须告诉SELinux更改入口点(对应于正确的(有限)入口点来执行apache_exec_tallowapache_tapache_exec_t:fileentrypoint类型的文件;(4)最后,DomainTransitiontype_transizioninit_tapache_exec_t:processapache_t;

你如何可以看到,整个改变域的过程写起来非常复杂因此,对于为了使用方便,Google在文件系统/sepolicy/public/te_macros中定义了宏:

我们可以使用这些宏来完成域切换

示例:内核启动初始化。
处理并更改域: domain_auto_trans(kernel,init_exec,init)init启动netd、vold、zygote和installd来更改域:init_daemon_domain(netd)init_daemon_domain(vold)init_daemon_domain(zygote)init_daemon_domain(installd)

在目录中创建文件中创建进程,设置文件时默认使用根目录的SecurityContext。
如果要将其设置为特定标签,则需要运行ObjectTransitions。
同样使用:type_transitionstatement必须有两个匹配的先决条件。

下面是一个演示。
ext_gateway_t域在in_queue_t类型的目录中创建一个in_file_t类型的文件。

(1)首先必须匹配ext_gateway_t目录中的_queue_t具有访问权限allowext_gateway_tin_queue_t:dir{writesearchadd_name};(2然后,必须告诉SELinux允许ext_gateway_t访问该文件in_file_tallowext_gateway_tin_file_t:file{writecreategetattr};(3)t_gateway_tin_queue_t:filein_file_t;

同样,为了方便使用,Google也在/sepolicy/public/te_macros文件系统中定义了宏:

使用示例:file_type_auto_trans(factory,system_data_file,前面提到Android中SELinux变化的主要历史时,AndroidO重点关注了启动映像中的sepolicy,其中提到从androidO开始,Google将systemimage和sellerimage分开。
也分别存储在systemimage和sellerimage中。
系统相关的sepolicy存储在systemimage中,SoCvendor相关的sepolicy存储在sellerimage中。

对于原生AOSP,Google设置了多个存储目录进行分离,以Google默认的sepolicy为例,sepolicy的根目录为/system/sepolicy。
我们主要关注三个子目录:

对于不同的平台,不同的平台厂商也创建了不同的存储目录,以MTK平台为例:一、根据共享sepolicy从不同平台,针对平台唯一,针对项目唯一,分为:

因此,不同版本的Sepolicy配置会导入到不同的目录

以mt6763平台为例,导入时:[common]路径为:/device/mediatek/sepolicy[platfrom]路径为:/device/mediatek/mt6763/sepolicy/具体定义在BoardConfig.mk文件中:

所以,主要可以分为basic、bsp和full

Google在system/sepolicy中定义了相关的neverallow规则,并对SELinuxPolicy进行了有限的更新,以防止开发者在权限上过度开放,导致安全问题。
而CTS测试也将用于检测开发商是否违反了相关规定。

因此,需要注意以下几点:

出现SELinuxPolicyException时常见的两种解决方案:

(1)更改对应节点的SELinuxSecurityLabel,对特定主题开放权限,如system_app、platform_app、priv_app,如settings、SystemUI等内置APP,但严禁对unrstedapp开放权限。
(2)。
通过systemserverservice或init启动服务读写操作,然后应用程序通过binder/socket等连接并登录。
该类型安全可靠,建议在服务中进行相关安全审查。

场景:定义init进程启动的服务和工厂,对应的执行文件为/vendor/bin/工厂。

(1)。
在device/mediatek/mt6763/sepolicy/basic/non_plat目录下创建factory.te,然后将te文件添加到build中。
如果放在这个指定目录下,不需要额外配置,system/sepolicy/Android.mk中定义的build_policy函数会遍历指定目录并导入te。

(2)。
在factory.te中定义工厂类型,键入init启动服务时的转换,typefactory,domain;exec_type,file_type,vendor_file_type;>(3在file_contexts  /().system/vendor|vendor)/bin/factoryu:object_r:factory_exec:s0中关联可执行文件

(4)基于工厂必须要关联的文件和设备登录,在factory.te中定义其他权限:Forkeyandtoucheventallowfactoryinput_device:chr_filer_file_perms;allowfactoryinput_device:dirrw_dir_perms;

场景:添加自定义系统属性:persist.demo,并为platform_app设置读写权限

(1)在property.te中定义系统属性类型typedemo_prop,property_type

(2)。
将systemproperty的安全上下文映射到property_contexts。
-persist.demou:object_r:demo_prop:s0

(3)。
要向platform_app.te添加写权限,可以使用set_prop宏。
^set_prop(platform_app,demo_prop)

(4).为platform_app.te添加读取权限并使用get_prop宏。
 get_prop(platform_app,demo_prop)

场景:有一个/dev/demo设备节点,并且有一个platform_app进程需要读写该设备节点。

(1)。
在device.t中定义设备类型,typedemo_devicedev_type;

(2在file_contexts/dev/demou:object_r:demo_device:s0中关联demo_device

)。

(3)。
在platform_app.te中,允许platform_app使用demo设备权限-allowplatform_appdemo_device:chr_filerw_file_perms;

场景:有一个APP可以调用的扩展系统服务demo_service。

(1)。
在service.te中定义服务类型-typedemo_service、app_api_service、system_server_service、service_manager_type

(2)。
关联ce_contexts demou:object_r:demo_service:s0中的服务

(3)定义服务常量Frameworks/base/core/java/android/content/Context.java p。
ublicstaticfinalStringDEMO_SERVICE="演示";

(4)。
在frameworks/base/core/java/android/app/SystemServiceRegistry.java中,引用其他系统服务注册demo_service

(5)。
在frameworks/base/services/java/com/android/server/SystemServer.java中,启动DemoService,并将其添加到service_manager中进行管理。

(6)。
最后一步是引用其他系统服务来实现DemoManager和DemoService,并定义ID​​emoService等AIDL接口。

场景:本机服务通过init创建套接字并将其附加到/dev/socket/demo并允许某些进程访问它。

(1)。
定义socket类型为t typedemo_socket,file_type;

(2)在file_contexts /dev/socket/demo_sockettu:object_r:demo_socket:s0

(3)中绑定socket类型。
允许访问所有进程,在unix_socket_connect(appdomain,demo,demo)上使用宏unix_socket_connect(clientdomain,socket,serverdomain)

(1)。
在device/mediatek/mt6763/sepolicy/basic/non_plat目录下创建demo.te。

(2)。
在demo.te中定义demo类型,并在init启动服务时进行类型转换。
并且您可以根据demo需要访问的文件和设备,在demo.te中定义其他权限。
输入演示,域;类型demo_exec,exec_type,file_type;init_daemon_domain(demo)

(3)关联可执行文件file_context类型/vendor/bin/demou:object_r:demo_exec:s0

(4)。
创建demo_exec演示入口执行文件并配置相应权限。

(1)。
将SELinux调整为Permissive模式,然后使用eng/userdebug版本重试。
Adbshel​​lsetenforce0将SELinux模式调整为Permissive模式,然后重试。
如果仍然可以重现问题,则与SELinux无关;如果很容易玩,但在Permissive模式下玩不了,可能与SELinux有关。

(2)。
检查LOG中是否有标准的SELinuxPolicyException。
查询KernelLOG/MainLog中的“avc:denied”关键字,查看是否存在与目标进程相关的SELinuxPolicyException,并进一步确认。
这个例外是否与当时的逻辑有关。

一般情况下,在尊重Googlesepolicy和neverallow政策的前提下,我们可以根据LOG中的内容添加任何必要的权限。
例如日志:2020-03-2714:11:02.5961228-1228/com.android.systemuiW/FaceIdThread:type=1400audit(0.0:481):avc:denied{read}forname="als_ps"dev="tmpfs"ino=10279scontext=u:r:platform_app:s0:c512,c768tcontext=u:object_r:als_ps_device:s0tclass=chr_filepermissive=0

LOG的描述如下:

总的来说,我们需要关注的是四:authorization,sourcetype,targettype,targetclass

根据这个就可以配置所需的selinux权限了single:allow[源类型][目标类型]:[目标类][权限]示例1:03-2703:45:22.63229582958WCamera:type=1400audit(0.0:314):avc:拒绝{读取}forname=“u:object_r:graphics_debug_prop:s0”dev=“tmpfs”ino=2649scontext=u:r:platform_app:s0:c512,c768tcontext=u:object_r:graphics_debug_prop:s0tclass=filepermissive=0

解决方法:根据公式正常情况下,platform_app.te应该这样修改,添加: allowplatform_appgraphics_debug_prop:filer_file_perms;这里我们使用system/sepolicy/te_macros中定义的get_prop宏:

更多相关宏定义参考:system/sepolicy/public/te_macros.然后,在最终简化后,编辑platform_app.te并添加:get_prop(platform_app,graphics_debug_prop)

示例2:03-2714:11:02.5961228-1228/com.android.systemuiW/BackThread:type=1400audit(0.0:481):avc:拒绝{读取}forname=“als_ps”dev=“tmpfs”ino=10279scontext=u:r:platform_app:s0:c512,c768tcontext=u:object_r:als_ps_device:s0tclass=chr_filepermissive=0

解决方案:编辑platform_app.teeadd: allowplatform_appals_ps_device:chr_filer_file_perms;

(1)未能遵守neverallow规则或更改neverallow规则后编译错误: neverallowcheckfailedatxxxCTS测试项失败: android.cts.security.SELinuxNeverallowRulesTest#testNeverallowRulesXXX此类问题尤其严重可能会在分手后发生androidOvendor和系统。
基本上,此类问题是由于修改或添加的配置不遵守neverallow规则而引起的,从而导致编译错误。
为了解决编译错误,neverallow规则已被修改。
最后运行CTS时,其测试项目无法通过。

解:

(2)。
初始化过程分叉新进程而不更改域。
CTS测试项失败:android.security.cts.SELinuxDomainTest#testInitDomain

>

解决办法:fork进程时,域切换参考3.4节。

本文主要参考了MTK-Online快速入门中“SELinux问题快速分析”的内容。
我要感谢原作者的辛勤工作。
此外,结合源码和自己的开发实践,增加了一些实用的、个人理解的内容。

selinux环境下网络服务应该如何设置?

SELinux,全称Security-EnhancedLinux,是一种为Linux系统提供MAC(强制访问控制)的安全机制。
限制进程和用户对系统资源的访问,提高系统的安全性和稳定性。
在设置网络服务时,SELinux的三种状态——Enforcing(强制执行)、Permissive(允许)和Disabling(禁用)对网络服务设置有不同的影响。
在Enforcement状态下,网络服务必须遵守SELinux策略的规则,否则将被拒绝或终止。
这些设置提高了系统安全性,但也可能导致一些常见的网络功能受到限制。
例如,如果SELinux不允许Apache服务器访问某个目录,那么Apache就无法在该目录中提供Web服务。
尽管处于Permissive状态的网络服务不会被SELinux阻止或终止,但所有策略规则违规行为都会被记录并生成警告消息。
这有助于管理员调试和优化SELinux策略设置,以实现安全性和功能之间的平衡。
在Disabled状态下,网络服务不受SELinux的任何控制和监控,可以自由地访问和使用系统资源。
这种设置提高了系统的灵活性和兼容性,但可能会导致安全风险,例如Apache服务器被黑客攻击。
在处理SELinux设置时,了解其工作原理、策略规则、日志信息、管理工具等基础知识非常重要。
选择适当的状态和模式来实现功能,同时保持安全性。
SELinux的工作原理基于策略规则,策略规则定义了对象(如文件、目录、端口、进程等)的安全上下文以及它们之间允许或拒绝的操作。
安全上下文由三部分组成:用户、角色和类型。
SELinux具有三种运行模式:强制模式、警告模式和禁用模式。
在强制模式下,SELinux根据策略规则进行访问控制,并在警告模式下记录违反规则的操作,所有操作都被允许,但在禁用模式下,违反规则的操作仍被记录,所有功能被禁用;日志信息通常存储在/var/log/audit/audit.log文件中,auditd服务用于管理和分析日志文件。
日志信息可以帮助识别潜在的安全问题并调整策略规则以满足系统需求。
SELinux有很多管理工具,包括setenforce、getenforce、sestatus、semanage、restorecon和chcon等命令行工具,以及system-config-selinux等图形界面工具。
该工具有助于查看和修改SELinux操作模式、策略类型、安全上下文和其他设置。
setenforce命令用于更改SELinux操作模式,例如setenforce0更改为警告模式,setenforce1更改为强制模式。
getenforce命令检查当前SELinux操作模式如果getenforce发出Enforcement,则表示处于强制模式。
sestatus命令显示SELinux状态和配置信息例如,sestatus-b列出所有启用和禁用的布尔设置。
semanage命令管理SELinux策略设置例如,semanageport-a-thttp_port_t-ptcp8080将端口8080添加到http_port_t类型,允许httpd服务访问该端口。
Restorecon命令恢复文件或目录的默认安全上下文。
例如,restorecon-Rv/var/www/html恢复目录/var/www/html及其子目录和文件的默认安全上下文。
chcon命令临时更改文件或目录的安全上下文。
例如,chcon-tsamba_share_t/home/user/share将/home/user/share目录的类型更改为samba_share_t,允许Samba服务访问该目录。

我的SElinux怎么变成permissive了,原来是enforcing

通过配置文件调整SELinux参数:

[root@www~]#vi/etc/selinux/config

SELINUX=enforce<==fixenforce|disabled|pageermissive

SELINUXTYPE=target<==当前目标和严格

SELinux启动和关闭【重要常识】:

如果更改命令,必须重新启动计算机。

SELinux已集成到核心中。

您还应该将SELinux从禁用重置为启用。

SELinux有三种运行模式:

enforcement:强制模式

permissive:容忍模式

禁用:关闭

[root@www~]#enforce强制

如何解决SELinux问题

首先,您需要确认SELinux已激活。
可以使用getenforce命令:shell>getenforceEnforcing或使用sestatus命令:shell>sestatusSELinuxstatus:enabledSELinuxfsmount:/selinuxCurrentmode:enforcingModefromconfigfile:enforcingPolicyversion:24Policyfromconfigfile:targeted注:有关SELinux基础知识的介绍,请参考相关的鸟哥的Linux私盘里有介绍。
我们还需要确认Apache已在系统上安装并启动。
如果没有,请使用YUM安装。
这个很简单,我就不详细说了。
然后在根目录下创建一个测试文件test.html,如下:shell>cat/root/test.htmlhello,world。
然后将此测试文件复制到Apache的DocumentRoot目录中。
如果我的Apache是​​通过YUM安装的,默认是/var/www/html目录,如下:shell>cp/root/test.html/var/www/html然后浏览一下,如果没有任何反应就一切正常了一切都在预料之中,如下:shell>curlhttp://localhost/test.htmlhello,world。
看到这里,你可能认为我在胡说八道,别担心,是时候见证奇迹了:仍然是测试文件test.html,只不过这次不再是复制,而是移动了,如下:shell>mv/root/test.html/var/www/html然后浏览一下,怎么样,结果很意外,提示权限错误,如下:shell>curlhttp://localhost/test.html<!DOCTYPEHTMLPUBLIC"-//IETF//DTDHTML2.0//EN"><html><head><title>403Forbidden</title></head><body>

Forbidden

Youdonthavepermissiontoaccess/test.htmlonthisserver.

</body></html>当然,我们现在知道这个问题是由SELinux引起的,但是我们仍然不知道为什么。
其实问题的原因已经被审计进程记录在相应的日志中,可以这样查看:shell>audit2whyyuminstallsetroubleshoot它本身是一个GUI软件包,但它包含一个对我们命令行用户非常有用的sealert命令:shell>sealert-a/var/log/audit/audit.log总结:SELinuxispreventing/usr/sbin/httpd"getattr"accessto/var/www/html/test.html.详细描述:SELinuxdeniedaccehttpd./var/www/html/test.html请求的ss可能被标记为./var/www/html/test.html默认SELinux类型是httpd_sys_content_t,但其当前类型是admin_home_t。
将此文件更改回默认类型,可能会解决您的问题。
可以通过以下方式将文件上下文分配给文件。
*在目录中创建的文件默认接收父目录的文件上下文。
*SELinux策略可能会通过指定在上下文中运行的进程来覆盖从父目录继承的默认标签,该进程创建标记为B的目录中的文件将改为创建带有标签C的文件。
此示例是使用dhclient_t类型运行的dhcp客户端,并在/etc目录中创建文件。
由于父级继承,该文件通常会接收etc_t类型,但该文件会被标记为net_conf_t类型,因为SELinux策略指定了这一点。
*用户可以使用诸如schcon或Restorecon之类的工具更改文件上下文。
此文件可能因用户错误而被错误标记,或者通常限制的应用程序在错误的域下运行。
但是,这也可能表明SELinux中存在错误,因为该文件不应使用此类型标记。
如果您认为这是错误,请提交abugreportagainstthispackage.AllowingAccess:您可以通过执行therestorecon命令将默认系统上下文恢复到此文件。
restorecon'/var/www/html/test.html',如果此文件是目录,您可以使用restorecon-R'/var/www/html/test.html'递归恢复。
FixCommand:/sbin/restorecon'/var/www/html/test.html'这次你应该明白了吧!原因是Apache下的文件上下文类型应该是httpd_sys_content_t,但现在是admin_home_t,所以权限不对,最后给出了修复命令。
​但是您如何看待httpd_sys_content_t和admin_home_t?很简单,借用-Z即可ls命令的参数:shell>ls-Z/path回到问题最开始,复制没有问题的原因是因为cp自动修改了上下文属性,而移动出现问题的原因是因为mv保留了原始文件上下文属性。
注:关于SELinux和Apache的详细介绍,请参考“manhttpd_selinux”。
既然你知道了如何解决SELinux问题,以后如果遇到类似的情况,不要急于随意关闭SELinux。