SELinux 介绍和基本使用

SELinux 介绍和基本使用

文章目录

  • [SELinux 介绍和基本使用](#SELinux 介绍和基本使用)
    • [1. SELinux 介绍](#1. SELinux 介绍)
      • [1.1 SELinux 发展史](#1.1 SELinux 发展史)
      • [1.2 SELinux 基础原理](#1.2 SELinux 基础原理)
        • [1.2.1 DAC 和MAC](#1.2.1 DAC 和MAC)
          • [1.2.1.1 DAC](#1.2.1.1 DAC)
          • [1.2.1.2 MAC](#1.2.1.2 MAC)
        • [1.2.2 Core SELinux Components](#1.2.2 Core SELinux Components)
        • [1.2.3 SELinux(MAC)基本访问流程](#1.2.3 SELinux(MAC)基本访问流程)
        • [1.2.4 Security Context](#1.2.4 Security Context)
      • [1.3 SELinux 语法](#1.3 SELinux 语法)
        • [1.3.1 关键词](#1.3.1 关键词)
        • [1.3.2 TE 部分](#1.3.2 TE 部分)
        • [1.3.3 SELinux 涉及到的文件](#1.3.3 SELinux 涉及到的文件)
      • [1.4 SELinux in Qualcomm](#1.4 SELinux in Qualcomm)
      • [1.5 class](#1.5 class)
      • [1.6 权限缩写](#1.6 权限缩写)
    • [2. SELinux 使用](#2. SELinux 使用)
      • [2.1 AVC 报错解析](#2.1 AVC 报错解析)
      • [2.2 调试](#2.2 调试)
        • [2.2.1 临时关闭SELinux](#2.2.1 临时关闭SELinux)
        • [2.2.2 开机关闭SELinux](#2.2.2 开机关闭SELinux)
        • [2.2.3 代码关闭SELinux](#2.2.3 代码关闭SELinux)
      • [2.3 添加一个权限](#2.3 添加一个权限)
        • [2.3.1 报错信息:](#2.3.1 报错信息:)
        • [2.3.2 分析:](#2.3.2 分析:)
        • [2.3.3 权限添加:](#2.3.3 权限添加:)
        • [2.3.4 权限添加步骤:](#2.3.4 权限添加步骤:)
      • [2.4 添加一个新的label](#2.4 添加一个新的label)
        • [2.4.1 定义](#2.4.1 定义)
        • [2.4.2 使用](#2.4.2 使用)
      • [2.5 添加一个新的domian](#2.5 添加一个新的domian)
    • [3. 附录](#3. 附录)
      • [3.1 The SELinux Notebook](#3.1 The SELinux Notebook)
      • [3.2 SELinux for Android 8.0](#3.2 SELinux for Android 8.0)
      • [3.3 NB_SEforAndroid_1](#3.3 NB_SEforAndroid_1)
      • [3.4 80-PE644-7 - SELinux Overview and Update for Android O](#3.4 80-PE644-7 - SELinux Overview and Update for Android O)
      • [3.5 KBA-000000030298 - How to add a new domain for a new executable file and its policy for Android Q](#3.5 KBA-000000030298 - How to add a new domain for a new executable file and its policy for Android Q)
      • [3.6 80-PN330-8 - SELinux Rules and CVE](#3.6 80-PN330-8 - SELinux Rules and CVE)
      • [3.7 80-PJ388-21 - SELinux Overview](#3.7 80-PJ388-21 - SELinux Overview)
      • [3.8 KBA-200921030517 - quick build to verify sepolicy changes](#3.8 KBA-200921030517 - quick build to verify sepolicy changes)
      • [3.9 KBA-210521021443 - KBA list for Selinux](#3.9 KBA-210521021443 - KBA list for Selinux)
      • [3.10 SELinux 概念的直观解释](#3.10 SELinux 概念的直观解释)
      • [3.11 Google 关于SELinux 的介绍和使用](#3.11 Google 关于SELinux 的介绍和使用)

1. SELinux 介绍

1.1 SELinux 发展史

SELinux 即Security-Enhanced Linux,由美国国家安全局(NSA)发起,Secure Computing Corporation (SCC) 和 MITRE 直接参与开发,以及很多研究机构(如犹他大学)一起参与的强制性安全审查机制,该系统最初是作为一款通用访问软件,发布于 2000 年 12 月(代码采用 GPL 许可发布)。并在Linux Kernel 2.6版本后,有直接整合进入SELinux,搭建在Linux Security Module(LSM)基础上,目前已经成为最受欢迎,使用最广泛的安全方案。SELinux 是典型的MAC(Mandatory Access Controls)实现,对系统中每个对象都生成一个安全上下文(Security Context),每一个对象访问系统的资源都要进行安全上下文审查。审查的规则包括类型强制检测(type enforcement),多层安全审查(Multi-Level Security),以及基于角色的访问控制(RBAC: Role Based Access Control)。SELinux 搭建在Linux Security Module(LSM)基础上,关于 LSM 架构的详细描述请参见文章 "Linux Security Modules: General Security Support for the Linux Kernel",该文章在 2002 年的 USENIX Security 会议上发表。有完整的实现LSM 的所有hook function。

SELinux 包含五个基本组成:

  • 用于处理文件系统的辅助模块, 即SELinuxFS;

  • 集成Linux Security Modules 的hooks sets;

  • Security Policy Database;

  • Security Label 验证模块;

  • Access Vector Cache (AVC),访问向量缓存,以便提高验证速度。

SEAndroid

Android 安全模型部分基于应用沙盒的概念。每个应用都在自己的沙盒内运行。在 Android 4.3 之前的版本中,这些沙盒是通过为每个应用创建独一无二的 Linux UID(在应用安装时创建)来定义的。Android 4.3 及更高版本使用 SELinux 进一步定义 Android 应用沙盒的边界。

作为 Android 安全模型的一部分,Android 使用SELinux 对所有进程强制执行强制访问控制 (MAC),甚至包括以 Root/超级用户权限运行的进程(Linux 功能)。借助SELinux,Android 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、降低恶意软件的影响,并保护用户免遭移动设备上的代码可能存在的缺陷的影响。SELinux 按照默认拒绝的原则运行:任何未经明确允许的行为都会被拒绝。SELinux 可按两种全局模式运行:

  • 宽容模式(Permissive mode):权限拒绝事件会被记录下来,但不会被强制执行。
  • 强制模式(Enforcing mode):权限拒绝事件会被记录下来并强制执行。
    Android 中包含 SELinux(处于强制模式)和默认适用于整个 AOSP 的相应安全策略。在强制模式下,非法操作会被阻止,并且尝试进行的所有违规行为都会被内核记录到 dmesg 和 logcat 中。

基于 Android 4.3(宽容模式)和 Android 4.4(部分强制模式),在 Android 5.0 及更高版本中,已全面强制执行 SELinux。通过此项变更,Android 已从对有限的一组关键域(installd、netd、vold 和 zygote)强制执行 SELinux 转为对所有域(超过 60 个)强制执行 SELinux。具体而言:

  • 在 Android 5.x 及更高版本中,所有域均处于强制模式。
  • init 以外的任何进程都不应在 init 域中运行。
  • 出现任何常规拒绝事件(对于 block_device、socket_device、default_service),都表示设备需要一
    个特殊域。Android 6.0 通过降低策略的宽容度强化了系统安全,从而实现更好的用户隔离和 IOCTL 过滤、降低可从设备/系统之外访问的服务面临的威胁、进一步强化 SELinux 域,以及高度限制对 /proc 的访问。Android 7.0 更新了 SELinux 配置,以进一步锁定应用沙盒并缩小受攻击面。此版本还将单片式mediaserver 堆栈拆分为较小的进程,以缩小其权限范围。Android 8.0 更新了 SELinux 以便与 Treble 配合使用,后者可将较低级别的供应商代码与 Android系统框架分离开来,其中限制了System/Vendor 之间的交叉使用,如VNDK 的权限控制就主要由selinux来控制。此版本更新了 SELinux 策略以允许设备制造商和 SOC 供应商更新自己的策略部分、构建自己的镜像(vendor.img、boot.img 等),然后更新这些镜像而不受平台影响,反之亦然。

虽然可以在设备上运行更高/更新版本的平台(framework),但反之并不成立;供应商镜像(vendor.img/odm.img) 的版本不能高于平台 (system.img) 的版本。因此,新平台可能会带来 SELinux 兼容性问题,因为平台 SELinux 策略的版本要比该策略的供应商SELinux 部分更新。

关于SEAndroid 部分,可到附录中查阅SELinux for Android 8.0

1.2 SELinux 基础原理

1.2.1 DAC 和MAC

DAC 即 Discretionary Access control,自主访问控制,即系统只提供基本的验证,完整的访问控制由开发者自己控制。MAC 即 Mandatory Access control,强制性访问控制,即系统针对每一项访问都进行严格限制,具体的限制策略由开发者给出。

1.2.1.1 DAC

Linux DAC 采用了一种非常简单的策略,将资源访问者分成三类,分别是Owner、Group、Other。资源针对这三类访问者设置不同的访问权限。而访问权限又分成 read、write、execute。访问者通常是进程,有自己的uid/gid,通过uid/gid 和文件权限匹配,来确定是否可以访问。将Root 权限根据不同的应用场景划分成许多的Root Capabilities,其中如果有CAP_DAC_OVERRIDE 这项的话,可以直接绕过Linux DAC

限制。Linux DAC 有明显的不足,其中一个重要点就是Root 权限 "无法无天",几乎可以做任意事情,一旦入侵者拿到root 权限,即已经完全掌控了系统。另外,每一个进程默认都拿到对应这个用户的所有权限,可以改动/删除这个用户的所有文件资源。很明显,这个难以防止恶意软件。

1.2.1.2 MAC

Linux MAC 针对DAC 的不足,要求系统对每一项访问进行检查,每访问一个文件资源都需要进行针对性的验证。而这个针对性的验证是根据已经定义好了的策略进行的。在Linux Kernel,所有的MAC 机制都是搭建在Linux Security Modules (LSM) 基础上,包括有:SELinux、Apparmor、Smack 和 TOMOYO Linux等。针对Linux DAC,MAC 可以明显弥补DAC 的缺陷,一方面限制Root 权限,即使你有root 权限,如果无法通过MAC 验证,那么一样的无法真正执行相关的操作.。另外对每一项权限进行了更加完整的细化,可限制用户对资源的访问行为。

MAC 的两种形式:

  1. Type Enforcement (TE)顾名思义,Type Enforcement 是根据Security Label 中的type 进行权限审查,审查subject type

    对object type 的某个class 类型中某种permission 是否具有访问权限,是目前使用最为广泛的MAC审查机制,简单易用。

  2. Multi-Level Security (MLS)多层安全机制,是基于Bell-La Padula (BLP)模型,将Subject 和 Object 定义成多层次的安全等

    级,不同安全等级之间有相关的访问约束,常见的访问约束是 "no write down" 和 "no read up"。它是根据Security Label 里面的最后一个字段label 进行确认的。

目前在Android 中,重点启用了Type Enforcement 机制,Multi-Level Security (MLS) 虽然有定义,但没有深入使用。

1.2.2 Core SELinux Components

图2 SELinux 核心组件

  • Subject 通常是指触发访问行为的对象,在Linux 里面通常是一个进程(Process);

  • Object Manager 即是对象访问管理器,即可以知道Subject 需要访问哪些资源,并且

    触发验证机制;

  • Security Server 即安全服务器,用来验证某个Subject 是否可以真正的访问某个

    Object,而这个验证机制是基于定义好的Security Policy;

  • Security Policy 是一种描述SELinux Policy 的语言;

  • Access Vector Cache (AVC) 是访问缓存,用来记录以往的访问验证情况,以便提高效

    率,快速处理。

1.2.3 SELinux(MAC)基本访问流程

流程如下:

  • 进程通过系统调用(System Call) 访问某个资源,进入Kernel 后,先会做基本的检测,如果异常则

    直接返回;

  • Linux Kernel DAC 审查,如果异常则直接返回;

  • 调用Linux Kernel Modules 的相关hooks,对接到SELinux 的hooks,进而进行MAC 验证,如

    果异常则直接返回;

  • 访问真正的系统资源;

  • 返回用户态,将结果反馈

1.2.4 Security Context

SELinux 给Linux 的所有对象都分配一个安全上下文(Security Context),描述成一个标准的字符串。SElinux 是一个标签系统。系统中的每个进程、每个文件/目录对象,甚至每个网络端口、设备以及每个可能的主机名都会被打上一个标签,所有操作都由标签控制。

两种类型:

  • Subject 主体,linux 通常以进程为单位

  • Object 访问对象,linux 通常以文件为单位

    如:scontext=u:r:system_app:s0

标准格式:user:role:type:range,

  • user:用户,非Linux UID;

  • role:角色,一个user 可以属于多个role,不同的role 具有不同的权限。Android 中r 角色表示进程,是活的,能发起动作的角色,object_r 这个角色,是死的,只能被人操作、

    访问,一般是文件、设备、属性等;

  • type:Subject 或者Object 的类型。MAC 的基础管理思路是所谓的Type Enforcement

    Access Control(简称TEAC,一般用TE 表示)。对进程来说,Type 就是Domain。在SEAndroid 中,有一百多种type;

  • range:Multi-Level Security(MLS)的级别。MLS 将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问。通常格式为sensitivity:category list[-

    sensitivity:category list],例如s0 - s15:c0.c1023,其中s0 之后的内容可以不需要,冒号后面的内容是category,sensitivity 和category 组合一起声明了当前的安全级别(security level),"-"号左右分别标识了安全级别的最低和最高,这一列的参数将在MLS 约束检查时用到,"15"、"1023"表示了sensitivity 和category 的最大值。

如图5,来自于高通文档的说明

每一个对象都有一个Class,比如一个文件,它是File Class 类型,每个Class 类型都会根据实际情况定义权限类型项,如:read、write、exec、ioctl、append 等等。Subject 即前面提到的主体,它能够产生访问行为,Linux 里面通常是一个process,但process本身也可能是一个Object,比如另外一个进程对它发送Signal,去对它进行ptrace 操作。

1.3 SELinux 语法

1.3.1 关键词

常用关键词:

  • allow:赋予某项权限。
  • dontaudit:对那些权限检查失败的操作不做记录,XTS 的bug 可能会用到。
  • neverallow:用来检查安全策略文件中是否有违反该项规则的allow 语句。
1.3.2 TE 部分

控制语句格式:rule_name source_type target_type:class perm_set;

  • rule_name:控制类型,分成两方面 allow 以及 audit。

  • source_type:也叫subject,通常是domain。

  • target_type:代表请求的资源的类型。

  • class perm_set:代表对资源访问的操作。

    如:allow NetworkManager_t var_t:file read;

1.3.3 SELinux 涉及到的文件
  1. file_contexts

系统文件以及device 所对应的security context。格式:regexp <-type> (<security_contexts>)如:

复制代码
/opt/cvs(/.*)?      u:object_r:cvs_data_t:s0
/mnt(/[^/]*)?  -d  u:object_r:mnt_t:s0
/dev/tts/[^/]*  -c  u:object_r:tty_device_t:s0
/etc/ppp(/.*)?  --  u:object_r:pppd_etc_rw_t:s0

regexp 是一个文件路径标签,它提供了正则表达式格式的文件路径(例如 /etc/init.d(/.*)?)。 匹配文件路径可以提供安全上下文;-type 是可选的,可以留空。 当它被填充时,它类似于 ls 命令的模式字段,如-d 表示仅匹配目录,-- 表示仅匹配文件

  1. genfs_contexts genfs 中的gen 为generalized 的意思,用于为不支持扩展属性的文件系统(例如,proc 或 vfat)分配标签,一般对/目录,proc 目录,sysfs 等使用genfscon 关键词;此配置会作为内核策略的一部分进行加载,但更改可能对内核 inode 无效。如:

    genfscon proc /asound/cards u:object_r:vendor_proc_audiod:s0
    genfscon sysfs /devices/virtual/fts/touch_aoi u:object_r:vendor_sysfs_touch_aoi:s0

  2. hwservice_contexts

声明HIDL service 安全上下文。如:

  1. service_contexts用于为 Android Binder 服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)Binder 引用。在启动期间,servicemanager 进程会读取此配置。如:

    com.fingerprints.extension::IFingerprintSenseTouch u:object_r:hal_fingerprint_hwservice:s0
    vendor.qti.hardware.alarm::IAlarm u:object_r:vendor_hal_alarm_qti_hwservice:s0

  2. property_contexts用于为 Android 系统属性分配标签,以便控制哪些进程可以设置这些属性。在启动期间,init进程会读取此配置。如:

    power u:object_r:power_service:s0
    android.os.UpdateEngineService u:object_r:update_engine_service:s0

  3. seapp_contexts用于为应用进程和 /data/data 目录分配标签。在每次应用启动时,zygote 进程都会读取此配置;在启动期间,installd 会读取此配置。如:

    vendor.sys.boot_mode u:object_r:vendor_boot_mode_prop:s0
    vendor.sxr. u:object_r:vendor_sxr_prop:s0

    user=_isolated domain=isolated_app levelFrom=user
    user=_app seinfo=app_zygote domain=app_zygote levelFrom=user
    user=_app isPrivApp=true name=com.google.android.gsf domain=gmscore_app
    type=privapp_data_file levelFrom=user
    user=_app minTargetSdkVersion=28 fromRunAs=true domain=runas_app levelFrom=all

  4. vndservice_contexts用于和vendor service 通信

如:

  1. mac_permissions.xml用于根据应用签名和应用软件包名称(后者可选)为应用分配 seinfo 标记。随后,分配的 seinfo 标记可在 seapp_contexts 文件中用作密钥,以便为带有该 seinfo 标记的所有应用分配特定标签。在启动期间,system_server 会读取此配置。如:

    wfdhdcpvndservice u:object_r:vendor_wfdhdcpvndservice_service:s0
    DisplayFeatureControl u:object_r:DisplayFeatureControl_service:s0

1.4 SELinux in Qualcomm

关于Android 平台sepolicy 中private/public/vendor 三个文件夹的解释

  • private: Elements defined in this folder is used by core domain only.
  • public: Elements are packed into system image. They are exported to vendor domain.
  • vendor: Elements are packed into vendor image.如果想知道知道system/sepolicy 和device/qcom/sepolicy*下哪些文件或文件夹参与编译,可查看对
    应的mk 文件,Android 平台在system/sepolicy/Android.mk,QC 平台在device/qcom/sepolicy/SEPolicy.mk和device/qcom/sepolicy_vndr/SEPolicy.mk

1.5 class

定义路径:system/sepolicy/private/security_classes,如:

每个class 可允许的操作:system/sepolicy/private/access_vectors,如:

复制代码
# file-related classes
class filesystem
class file
class anon_inode
class dir
class fd
class lnk_file
class chr_file

common file {
  ioctl read write create getattr setattr lock ......
}

1.6 权限缩写

用一个字段代替若干个操作权限:system/sepolicy/public/global_macros,如:

复制代码
define(`x_file_perms', `{ getattr execute execute_no_trans map }')
define(`r_file_perms', `{ getattr open read ioctl lock map watch watch_reads }')
define(`w_file_perms', `{ open append write lock map }')
define(`rx_file_perms', `{ r_file_perms x_file_perms }')
define(`ra_file_perms', `{ r_file_perms append }')
define(`rw_file_perms', `{ r_file_perms w_file_perms }')

2. SELinux 使用

2.1 AVC 报错解析

复制代码
type=1400 audit(1642146837.807:73): avc: denied { read write } for comm="sensors.qti" name="diag"
dev="tmpfs" ino=27832 scontext=u:r:vendor_sensors_qti:s0 tcontext=u:object_r:vendor_diag_device:s0
tclass=chr_file permissive=0

翻译上面avc 报错:进程"sensors.qti"对"diag"进行操作类型为chr_file 的{ read write }操作被拒绝,

2.2 调试

2.2.1 临时关闭SELinux
  1. adb root
  2. adb shell setenforce 0 1:打开
  3. adb shell getenforce
2.2.2 开机关闭SELinux
  1. adb root
  2. adb shell setenforce 0
  3. adb shell stop
  4. adb shell start
    NOTE: 上述四步操作之后,DUT 可能无法开机,原因之一就是因为SELinux 被关闭,导致有些进程有权限进行相关操作,但由于缺少进程所依赖的资源导致进程无法启动,进而无法启动Android。
2.2.3 代码关闭SELinux
  1. 在BoardConfig.mk 添加BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive
  2. 在system/core/init/selinux.cpp 中,把is_enforcing 强制赋值为false(原代码bool is_enforcing
    = IsEnforcing();)

2.3 添加一个权限

2.3.1 报错信息:
复制代码
updater_engine: type=1400 audit(0.0:1900): avc: denied { use } for path="/storage/emulated/0/xxx.zip"
dev="sdcardfs" ino=10872 scontext=u:r:update_engine:s0
tcontext=u:r:mediaprovider_app:s0:c228,c256,c512,c768 tclass=fd permissive=0
2.3.2 分析:

从log 上看,是update_engine 对mediaprovider_app 缺少fd 类型的use 权限,对于上述avc 报错,update_engine 的te 文件通常是在system/sepolicy 下,device/qcom 下也可能有,还无法确定是要在哪个路径下添加这个权限,可以看一下mediaprovider_app 对应的te 文件在哪,并不是所有的文件可以直接添加权限,在system/sepolicy 下定义的te,它的范围仅限于system/sepolicy,其他路径访问不到,此题的mediaprovider_app.te 也在system/sepolicy 下;其次,还需要注意的是,对于主体的update_engine.te,在system/sepolicy 下,除了public|private 下有之外,还在prebuilts/api 下有很多,那就说明,不能只在

public/private对应的update_engine.te添加权限,还要在最新的prebuilts/api/xx.0/public|private/update_engine.te 添加权限

2.3.3 权限添加:

在system/sepolicy 下添加权限

  • 在private/update_engine.te 下添加:

    allow update_engine mediaprovider_app:fd use;

  • 在prebuilts/api/31.0/private/update_engine.te 添加相同语句

    allow update_engine mediaprovider_app:fd use;

2.3.4 权限添加步骤:
  1. 确认主体和目标控制范围(是在system/sepolicy 还是device/qcom 或者其他路径下);
  2. 确认主体te 文件是否在prebuilts/api 下也有;
  3. 确认上述两点后,添加对应权限

2.4 添加一个新的label

2.4.1 定义

如果是要访问文件,可以在file_contexts 添加,属性的话在property_contexts 添加;如:代码中需要获取手机中sys/bootinfo 路径下的内容,需要在genfs_contexts 定义一个label 来指代这个路径,给这个代码所属的进程或服务使用

genfs_contexts:

复制代码
genfscon sysfs /bootinfo u:object_r:sysfs_bootinfo:s0

然后,需要给这个label 添class(见security_classes,具体定义了哪些操作类型),表示这个label只能被这种类型的操作使用

file.te:

复制代码
type sysfs_bootinfo, fs_type, sysfs_type;
2.4.2 使用

如果某个进程或服务需要访问手机中这个路径下的内容,就在这个服务或进程的主体te 文件中添加相关操作,只需要允许进程或服务访问定义的label 即可,表示进程或服务可以访问手机中这个路径下的所有内容dumpstate.te:

复制代码
allow dumpstate sysfs_bootinfo:file r_file_perms;

2.5 添加一个新的domian

Inite.te:

复制代码
type init, domain, mlstrustedsubject;
type init_exec, exec_type, file_type;

allow init kernel:fd use;
allow init {
  metadata_block_device
  misc_block_device
  recovery_block_device
  system_block_device
  userdata_block_device
}:{ blk_file lnk_file } relabelto;

file_contexts:

复制代码
/init u:object_r:init_exec:s0

3. 附录

3.1 The SELinux Notebook

https://freecomputerbooks.com/books/The_SELinux_Notebook-4th_Edition.pdf

3.2 SELinux for Android 8.0

https://source.android.com/security/selinux/images/SELinux_Treble.pdf

3.3 NB_SEforAndroid_1

http://selinuxproject.org/page/NB_SEforAndroid_1

3.4 80-PE644-7 - SELinux Overview and Update for Android O

3.5 KBA-000000030298 - How to add a new domain for a new executable file and its policy for Android Q

3.6 80-PN330-8 - SELinux Rules and CVE

3.7 80-PJ388-21 - SELinux Overview

3.8 KBA-200921030517 - quick build to verify sepolicy changes

3.9 KBA-210521021443 - KBA list for Selinux

3.10 SELinux 概念的直观解释

https://www.jianshu.com/p/115650a5bf41

3.11 Google 关于SELinux 的介绍和使用

https://source.android.com/security/selinux/

相关推荐
女神下凡2 小时前
芯参谋(30):EMMC eMCP 软件设计规范
arm开发·单片机·嵌入式硬件·设计规范
xingzhemengyou14 小时前
STM32F427将函数设定在固定位置
stm32·单片机·嵌入式硬件
殷忆枫8 小时前
基于ESP32 的局域网全双工对讲系统
单片机·嵌入式硬件·esp32·对讲系统
szxinmai主板定制专家9 小时前
工业视觉新思路:FPGA图像预处理+RK NPU推理,实现高速缺陷检测
人工智能·嵌入式硬件·fpga开发·rk3576+codesys
FPGA小徐12 小时前
【硬件实战】立创 EDA 绘制 TF/SD 卡模块电路|SPI 模式原理图 + 阻抗匹配 + PCB 布局布线全教程
单片机·嵌入式硬件·fpga开发
狂奔蜗牛(bradley)13 小时前
EtherCAT DC 分布式时钟同步的 ModelSim 仿真:从帧模板到从站行为建模
人工智能·嵌入式硬件·fpga开发·架构
铅笔小新z13 小时前
【stm32】I2C 中断模式数据收发
stm32·单片机·嵌入式硬件
铅笔小新z13 小时前
【stm32】理解弱引用
javascript·stm32·嵌入式硬件
铅笔小新z14 小时前
【stm32】DMA
stm32·单片机·嵌入式硬件