SELinux(Security-Enhanced Linux)是 Linux 內核的一個安全模塊,它提供了一種強制訪問控制(Mandatory Access Control, MAC)機制。與傳統的 Linux 自主訪問控制(Discretionary Access Control, DAC)不同,SELinux 不依賴于文件的所有者和權限來控制訪問,而是通過一套預先定義的策略,強制性地對所有進程和資源(如文件、目錄、端口等)進行訪問控制。即使是 root 用戶,其行為也會受到 SELinux 策略的限制,這大大增強了系統的安全性。
1. SELinux 原理介紹
SELinux 的核心是基于 "域-類型"(Domain-Type)模型的強制訪問控制。
主體(Subject)和客體(Object):
主體通常是指一個正在運行的進程,它試圖訪問某些資源。
客體是指被訪問的資源,如文件、目錄、網絡端口等。
安全上下文(Security Context):
這是 SELinux 工作的基石。每個主體和客體都有一個唯一的安全上下文標簽。
一個完整的安全上下文通常由四個部分組成:user:role:type:sensitivity。
在 Android 中,最重要的是 type,它決定了進程可以訪問哪些資源,以及資源可以被哪些進程訪問。通常以 _t 結尾,例如 untrusted_app_t、system_server_t。
策略(Policy)和規則(Rule):
策略是 SELinux 的核心,它定義了系統中的所有訪問控制規則。
規則的形式通常為:allow <source_type> <target_type>:<class> <permissions>;
source_type:請求訪問的主體的類型。
target_type:被訪問的客體的類型。
class:客體的類別,如 file, dir, socket 等。
permissions:允許的操作,如 read, write, execute 等。
簡而言之,當一個進程(主體)試圖對一個資源(客體)執行某個操作時,SELinux 會首先檢查它們各自的安全上下文。然后,它會在策略中查找是否存在一條允許 source_type 對 target_type 執行該 class 的 permission 的規則。如果找不到,訪問就會被拒絕。
2. SELinux 的運行模式
SELinux 有三種主要運行模式,你可以通過adb shell?getenforce 命令查看當前模式,并使用 adb shell setenforce 命令臨時切換。
強制模式(enforcing):
這是最嚴格的模式。SELinux 策略被嚴格執行,任何違反策略的訪問都會被拒絕并記錄到日志中。
在生產環境中,系統通常運行在強制模式下以確保最大安全性。
寬容模式(permissive):
SELinux 策略不會被強制執行。所有違反策略的訪問都會被允許,但會像在強制模式下一樣,將拒絕信息記錄到日志中。
這個模式非常適合開發和調試,你可以通過日志來發現策略中存在的缺陷,而不會導致系統功能異常。
禁用模式(disabled):
SELinux 完全不工作。不進行任何訪問控制,也不記錄任何日志。
不建議在任何情況下使用此模式,因為它會極大地降低系統的安全性。
Android 高通平臺上的 SELinux 示例方法
在 Android 系統中,SELinux 是其安全模型的重要組成部分。對于高通(Qualcomm)平臺,SELinux 的應用尤為關鍵。以下是一些常見場景及其 SELinux 策略的示例:
示例 1: 訪問自定義設備節點
假設你開發了一個自定義的驅動程序,并在 /dev/my_device 創建了一個設備節點。現在,一個名為 my_service 的服務進程需要訪問它。
定義設備節點的類型: 在策略文件中(通常是 .te 文件,如 vendor/qcom/proprietary/common/sepolicy/my_service.te),你需要為這個設備節點定義一個類型。
代碼段
# 定義設備節點 my_device 的類型為 my_device_dev
type my_device_dev, dev_type;
設置文件上下文: 接下來,你需要告訴系統,/dev/my_device 這個路徑下的文件應該被打上 my_device_dev 的標簽。這通常在 file_contexts 文件中完成。
代碼段
# file_contexts 文件
/dev/my_device ?u:object_r:my_device_dev:s0
為服務進程定義訪問權限: 最后,你需要為 my_service 進程定義一個 domain(域),并授予它訪問 my_device_dev 類型的權限。
代碼段
# my_service.te 文件
# 定義 my_service 進程的 domain
type my_service_t, domain;
# 授予 my_service_t 對 my_device_dev 的讀寫權限
allow my_service_t my_device_dev:chr_file { read write };
示例 2: 訪問自定義屬性文件
如果你的服務需要通過 sysfs(/sys)來控制硬件,例如通過 /sys/class/my_hw/status 文件讀取狀態。
定義 sysfs 文件的類型: sysfs 文件也有自己的類型。
代碼段
# 在 sysfs_entry.te 中定義
type my_hw_status_sysfs, sysfs_type, fs_type;
設置文件上下文: 在 file_contexts 中指定這個 sysfs 文件的類型。
代碼段
# file_contexts 文件
/sys/class/my_hw/status ?u:object_r:my_hw_status_sysfs:s0
為服務進程授予權限: 給 my_service 進程授予讀取 my_hw_status_sysfs 類型的權限。
代碼段
# my_service.te 文件
allow my_service_t my_hw_status_sysfs:file { read };
調試手段與日志分析
調試 SELinux 問題是開發過程中不可或缺的一部分。當出現 Permission denied 錯誤時,往往就是 SELinux 策略阻止了訪問。
日志打印
SELinux 的拒絕信息(denials)會被內核記錄到 dmesg 和 auditd 日志中。你可以通過以下命令查看這些日志。
查看內核日志: 在 adb shell 中使用 dmesg 命令。拒絕信息通常包含 avc: denied 關鍵詞。
Shell
adb shell "dmesg | grep 'avc: denied'"
一條典型的拒絕日志如下:
avc: denied { read } for pid=1234 comm="my_service" name="my_device" dev="tmpfs" ino=12345 scontext=u:r:my_service_t:s0 tcontext=u:object_r:my_device_dev:s0 tclass=chr_file permissive=0
日志解讀:
denied { read }:被拒絕的操作是 read。
pid=1234 comm="my_service":請求訪問的進程 ID 和名稱。
scontext=u:r:my_service_t:s0:主體的安全上下文。
tcontext=u:object_r:my_device_dev:s0:客體(被訪問資源)的安全上下文。
tclass=chr_file:客體的類別,這里是字符設備文件。
permissive=0:表示當前處于強制模式。如果是 permissive=1,則表示處于寬容模式,此次訪問被允許,但仍有日志記錄。
調試工具
audit2allow: 這是一個強大的工具,它可以根據日志中的拒絕信息自動生成 SELinux 策略規則。
首先,在寬容模式下復現問題,確保日志中記錄了所有拒絕信息。
將 dmesg 日志導出到文件中。
Shell
adb shell "dmesg | grep 'avc: denied'" > avc.log
使用 audit2allow 工具生成規則。
Shell
audit2allow -i avc.log -M my_service_policy
這個命令會生成兩個文件:my_service_policy.te 和 my_service_policy.cil。my_service_policy.te 文件中包含了建議添加的規則,你可以將其合并到你的策略文件中。
seinfo 和 sesearch:
seinfo 可以用來查看當前加載的 SELinux 策略信息,例如所有類型、屬性等。
sesearch 允許你查詢策略中是否存在特定的規則,是分析現有策略的利器。
2 neverallow 策略簡介
2.1?neverallow 是一種特殊的 SELinux 策略,顧名思義,它永遠不允許某些特定的訪問。它的存在是為了強化系統的安全,防止策略編寫者無意中授予過于寬泛或危險的權限。
與普通的 allow 規則不同,neverallow 規則一旦被定義,就無法通過任何方式(包括添加 allow 規則)來覆蓋。如果你的策略中任何一條 allow 規則與 neverallow 規則沖突,SELinux 策略編譯器(sepolicy-compile)就會報錯,導致編譯失敗。
neverallow 的典型用途:
限制特權進程的行為:例如,防止像 init 這樣的高權限進程訪問普通應用程序的數據。
防止跨域訪問:確保不同安全域(如 system、vendor、app)之間的隔離。
禁止危險操作:例如,阻止任何非 init 進程創建 dev_t 類型的文件。
2.2?如何規避 neverallow 策略
因為 neverallow 無法被直接覆蓋,所以“規避”它并不是指“繞過”它的限制,而是指通過修改你的策略設計來避免觸發 neverallow 規則。
這里有幾種常見的方法:
方法一:使用特定屬性(attribute)
neverallow 規則通常是針對一個**屬性(attribute)**而不是一個具體的類型。例如,一個 neverallow 規則可能禁止所有具有 untrusted_app 屬性的類型訪問 system_data 目錄。
代碼段
# 這是一個 hypothetical (假設的) neverallow 規則
neverallow untrusted_app system_data_file:dir { read write };
如果你有一個自定義的 app 類型 my_app_t,并且它被賦予了 untrusted_app 屬性,那么它就無法訪問 system_data_file。
規避方法:
不要將你的類型與受限屬性關聯。如果你的 my_app_t 不需要 untrusted_app 的所有權限,你可以不把它定義為 untrusted_app。
創建新的、更細粒度的屬性。如果你需要訪問某些受限資源,可以考慮創建一個新的屬性,并讓 neverallow 規則只針對舊的、寬泛的屬性。但這需要修改 AOSP 的核心策略,通常不推薦。
方法二:修改你的代碼邏輯
很多時候,觸發 neverallow 是因為你的代碼試圖以一種不安全的方式訪問資源。
規避方法:
不要直接訪問受限資源。如果你的進程需要訪問一個被 neverallow 規則禁止的資源,你應該重新設計你的代碼。例如,通過調用一個有權限的**服務(service)**來間接操作,而不是直接訪問。
使用 SELinux 允許的接口。Android 提供了 binder、hwservice 等多種 IPC(進程間通信)機制。你應該通過這些機制調用有權限的服務,讓服務來完成操作,而不是自己去突破限制。
方法三:修改 SELinux 策略,但要謹慎
這是最后的手段,通常只在特殊情況下才需要。修改 neverallow 規則本身可能會削弱系統的安全性。
規避方法:
在 OEM 策略中添加例外。在某些高通平臺,允許在 vendor/qcom/proprietary/common/sepolicy 目錄下添加一些 OEM 特有的策略。如果 AOSP 的 neverallow 規則對你的特定功能造成了不合理的限制,并且你確定該操作是安全的,你可以考慮在 OEM 策略中添加更細粒度的 neverallow 規則或調整現有規則。但這需要非常小心,并進行充分的安全審計。
3. system_app 添加 per-property 屬性的注意事項
在 Android 系統中,system_app 是一種特殊的應用程序,它們通常具有比普通應用更高的權限。為 system_app 添加 per-property 屬性(即每個屬性都有獨立的 SELinux 類型)是常見的需求,尤其是在需要和自定義服務通信時。
示例:system_app 和自定義屬性
假設你有一個 system_app,其進程類型是 system_app_t,你需要讓它能設置一個自定義的系統屬性 vendor.my.custom.prop。
定義屬性類型: 在你的策略文件(如 vendor/qcom/proprietary/common/sepolicy/vendor.te)中,首先定義這個屬性的類型。
代碼段
# 定義自定義屬性的類型
type my_custom_prop, property_type;
設置屬性上下文: 在 property_contexts 文件中,將你的屬性和類型關聯起來。
代碼段
# property_contexts 文件
vendor.my.custom.prop ????u:object_r:my_custom_prop:s0
授予 system_app 設置權限: 現在,你需要允許 system_app_t 類型的進程設置這個屬性。
代碼段
# system_app.te (或者你的自定義策略文件)
# 允許 system_app_t 對 my_custom_prop 類型進行 set 權限
allow system_app_t my_custom_prop:property_service set;
注意事項:
neverallow 檢查:即使是 system_app_t,也可能會受到一些 neverallow 規則的限制。例如,可能存在 neverallow system_app_t property_type:property_service set; 這樣的規則,禁止 system_app 設置某些核心系統屬性。在添加新的 allow 規則之前,最好檢查一下是否存在相關的 neverallow 限制。
權限最小化原則:永遠遵循最小權限原則。只授予 system_app 必要的權限,不要為了方便而授予過于寬泛的權限,例如 allow system_app_t property_type:property_service *;。
區分 system_app 和 vendor 進程:system_app 運行在 system 分區,而 vendor 進程運行在 vendor 分區。兩者有不同的 SELinux 域,不能混用。確保你的 system_app 策略只影響 system_app_t 域,而不會影響到 vendor 域。
SELinux 策略隔離:Android GSI (Generic System Image) 要求 vendor 策略和 system 策略隔離。因此,你不能在 system 分區的策略中直接引用 vendor 策略中定義的類型,反之亦然。你需要通過 vendor_init_t 等中間類型或特定的屬性來橋接這兩個分區。
總之,neverallow 策略是 SELinux 安全模型的重要保障。理解它的原理并采取正確的策略設計,而不是試圖繞過它,才能確保你所構建的 Android 系統既安全又穩定。
3、SELinux 策略修改示例與規范
在 Android 高通平臺上的 SELinux 策略修改,旨在實現對工廠端回讀信息的支持。這些修改涉及多個核心 SELinux 策略文件,體現了在自定義系統功能時如何正確擴展策略。
下面是根據你的提交內容,對 SELinux 策略修改的詳細分析、解釋和注意事項。
3.1.策略文件修改分析
你的修改主要集中在 shell.te、property.te、property_contexts 和 init 相關的策略文件中。這些修改的核心目標是:
定義新的屬性類型:為 xxx相關的持久化屬性(如 sn, snPcba, product.model)創建了新的 SELinux 類型。
允許 shell 和 init 訪問這些屬性:授予 shell 和 vendor_init 域的進程讀寫這些新定義屬性的權限。
允許 shell 訪問特定文件:為 shell 域添加了對特定文件(如 em_bluetooth_prop 和 mnt_vendor_file)的讀取權限。
Vendor分區屬性在BoradConfig.mk中添加?BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE 標記,這通常用于繞過對 vendor 屬性命名空間的嚴格檢查。
3.2?SELinux 策略修改示例詳解
以下是根據你提供的 diff 內容,對每個重要修改點的具體分析。
示例 1:在 shell.te 中添加文件訪問權限
Diff
--- a/LA.QSSI.12.0.r1/LINUX/android/system/sepolicy/prebuilts/api/32.0/private/shell.te+++ b/LA.QSSI.12.0.r1/LINUX/android/system/sepolicy/prebuilts/api/32.0/private/shell.te@@ -48,6 +48,9 @@ allow shell perfetto:process signal;
allow shell self:udp_socket { ioctl getopt setopt };
allow shell self:tcp_socket { ioctl getopt setopt };
allow shell mnt_vendor_file:dir { read getattr search open };+allow shell xx_bluetooth_prop:file { read open getattr map };+allow shell sysfs:file { open read getattr map };+allow shell mnt_vendor_file:file { open read getattr map};
修改目的:允許 shell 進程讀取 xx_bluetooth_prop 類型的文件,以及 sysfs 和 mnt_vendor_file 類型的文件。
規范分析:這是一個典型的權限擴展。當你需要通過 adb shell 或其他 shell 腳本訪問特定文件時,必須顯式地在 shell.te 中添加相應的 allow 規則。這里的 xxx_bluetooth_prop 顯然是一個自定義類型,需要在 file_contexts 中進行定義和關聯。
示例 2:定義和設置新的 property 屬性
Diff
--- a/LINUX/android/device/qcom/sepolicy_vndr/generic/vendor/common/property.te+++ b/LA.VENDOR.12.2.r1/LINUX/android/device/qcom/sepolicy_vndr/generic/vendor/common/property.te@@ -80,6 +80,9 @@ vendor_internal_prop(vendor_sensors_prop);
vendor_restricted_prop(vendor_tee_listener_prop);
vendor_restricted_prop(vendor_km_strongbox_version_prop);
vendor_restricted_prop(vendor_display_prop);+vendor_restricted_prop(vendor_xxx_product_model_prop);+vendor_restricted_prop(vendor_xxx_snpcba_prop);+vendor_restricted_prop(vendor_xxxx_sn_prop);
vendor_internal_prop(vendor_usb_prop);
vendor_restricted_prop(vendor_radio_prop);
vendor_internal_prop(vendor_qteeconnector_opti_prop);
修改目的:為 xxx?相關的屬性定義了新的類型,并將其聲明為 vendor_restricted_prop。
規范分析:將自定義屬性聲明為 vendor_restricted_prop 是一種推薦做法。這意味著這些屬性只能由特定的 vendor 進程讀寫,從而確保了屬性的隔離和安全。
示例 3:在 init_shell.te 中授予屬性讀寫權限
Diff
--- LINUX/android/device/qcom/sepolicy_vndr/generic/vendor/common/init_shell.te+++ LINUX/android/device/qcom/sepolicy_vndr/generic/vendor/common/init_shell.te@@ -122,6 +122,12 @@ get_prop(vendor_qti_init_shell, radio_control_prop)
set_prop(vendor_qti_init_shell, vendor_gpu_prop)
set_prop(vendor_qti_init_shell, vendor_sensors_prop)
set_prop(vendor_qti_init_shell, vendor_adsprpc_prop)+set_prop(vendor_qti_init_shell, vendor_xxx_product_model_prop)+get_prop(vendor_qti_init_shell, vendor_xxx_product_model_prop)+set_prop(vendor_qti_init_shell, vendor_xxx_snpcba_prop)+get_prop(vendor_qti_init_shell, vendor_xxx_snpcba_prop)+set_prop(vendor_qti_init_shell, vendor_xxx_sn_prop)+get_prop(vendor_qti_init_shell, vendor_emdoor_sn_prop)
修改目的:允許 vendor_qti_init_shell 進程讀寫新定義的 emdoor 屬性。
規范分析:在 init 腳本中設置或獲取屬性是常見操作,因此需要在 init 進程對應的 SELinux 域中添加相應的權限。這里的 set_prop 和 get_prop 宏是標準的 SELinux 策略寫法,用于簡化對屬性服務的訪問規則定義。
示例 4:在 BoardConfig.mk 中規避命名空間檢查
Diff
--- LINUX/android/device/qcom/neo/BoardConfig.mk+++ LINUX/android/device/qcom/neo/BoardConfig.mk@@ -117,7 +117,7 @@ BOARD_METADATAIMAGE_PARTITION_SIZE := 16777216
BOARD_DTBOIMG_PARTITION_SIZE := 0x1700000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 131072 # (BOARD_KERNEL_PAGESIZE * 64)-+BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE := true????# selinux name not to check
修改目的:由于你定義的屬性 persist.xxx.* 不遵循標準的 vendor 屬性命名規則(例如,必須以 vendor. 開頭),這個標記用于暫時禁用策略編譯器的嚴格檢查。
規范分析:這種做法應該被視為臨時解決方案,不推薦在長期項目中保留。標準的 vendor 屬性應該以 vendor. 作為前綴,或者遵循 AOSP 規定的其他命名空間。使用這個標記雖然能解決編譯問題,但可能會在未來的 Android 版本中遇到兼容性問題,并可能隱藏潛在的安全風險。
4、SELinux 最佳實踐與注意事項
當你對 SELinux 策略進行修改時,應始終遵循以下原則:
4.1. 最小權限原則(Principle of Least Privilege)
只授予必要的權限:不要為了方便而使用過于寬泛的權限,例如 allow my_domain all_file_types:file *;。這會大大增加攻擊面。
細化權限:精確到具體的操作。例如,如果只需要讀取文件,就使用 read 和 getattr,而不是 read write。
4.2. neverallow 策略的應對
避免觸發 neverallow:在編寫新策略時,要先了解現有的 neverallow 規則,并確保你的 allow 規則不會與之沖突。例如,不要嘗試讓 untrusted_app 訪問核心系統文件。
通過 IPC (Inter-Process Communication) 間接訪問:如果一個進程需要訪問被 neverallow 規則限制的資源,不要直接修改策略去繞過它。正確的做法是,讓你的進程通過 Binder 或其他 IPC 機制,調用一個已經有權限的服務來完成這個操作。這是一種安全的設計模式。
4.3. 策略版本與兼容性
保持更新:SELinux 策略會隨著 Android 版本不斷演進,新的版本可能會引入新的 neverallow 規則或修改現有規則。當升級 Android 版本時,務必檢查你的自定義策略是否仍然兼容。
vendor 和 system 策略隔離:在 Android 10 (Q) 及以后版本,Google 強制要求 vendor 策略和 system 策略必須嚴格隔離。這意味著 vendor 策略不能直接引用 system 策略中定義的類型。你提供的提交中,shell.te 和 vendor 策略都進行了修改,但它們是分開的,這符合隔離原則。
4. 4常見 AVC 錯誤解析
當 SELinux 拒絕你的訪問時,它會在日志里留下一個詳細的“案發現場報告”,也就是我們常說的 AVC(Access Vector Cache) 報錯。
以下是一些你可能會遇到的經典“案發現場”,以及我們的偵查和破案技巧。
AVC 錯誤示例 1:無法訪問 /sys/ 下的屬性文件
案發現場報告:
type=1400 audit(8445.739:50): avc: denied { write } for comm="init" name="brightness" dev="sysfs" ino=78557 scontext=u:r:init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
案情分析:
誰干的? init 進程,身份是 init_t。
想干啥? write(寫入)brightness 文件。
被誰攔了? SELinux 安檢員。
為什么攔? init_t 沒有權限去 write 類型為 sysfs 的 file。
破案手法(解決方案): 在 init.te 文件中添加以下規則:
代碼段
allow init sysfs:file { write };
AVC 錯誤示例 2:服務無法讀取 sysfs 文件
案發現場報告:
type=1400 audit(8445.211:14): avc: denied { read } for comm="android.hardware" name="type" dev="sysfs" ino=81076 scontext=u:r:hal_health_default:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
案情分析:
誰干的? android.hardware?進程(可能是 HAL 服務),身份是 hal_health_default_t。
想干啥? read(讀取)type 文件。
被誰攔了? SELinux 安檢員。
為什么攔? hal_health_default_t 沒有權限去 read 類型為 sysfs 的 file。
破案手法(解決方案):?在 system/sepolicy/vendor/hal_health_default.te 中添加以下規則:
代碼段
allow hal_health_default sysfs:file { read };
AVC 錯誤示例 3:init 腳本無法寫入 sysfs 文件
案發現場報告:
type=1400 audit(8440.707:12): avc: denied { write } for comm="sh" name="read_ahead_kb" dev="sysfs" ino=60930 scontext=u:r:vendor_qti_init_shell:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
案情分析:
誰干的? sh 進程(init 腳本),身份是 vendor_qti_init_shell_t。
想干啥? write(寫入)read_ahead_kb 文件。
被誰攔了? SELinux 安檢員。
為什么攔? vendor_qti_init_shell_t 沒有權限去 write 類型為 sysfs 的 file。
破案手法(解決方案): 在 vendor_qti_init_shell.te 中添加以下規則:
代碼段
allow vendor_qti_init_shell sysfs:file { write };
5總結:
5.1?終極武器:排查與修復四板斧
現在,我們把前面學到的知識總結成一套“三板斧”式的方法論,保證你在其他平臺上也能快速上手。
第一板斧:快速確認
當你遇到 Permission denied 時,不要急著改代碼。
檢查模式:adb shell getenforce
如果是 permissive,那問題就不是 SELinux,去查傳統權限(chown,chmod)。
如果是 enforcing,好戲開場了!
調出日志:adb shell "dmesg | grep 'avc: denied'"
如果這條命令有輸出,恭喜你,你已經抓到了 SELinux 的“犯罪現場報告”。
如果沒輸出,但系統又報錯,那可能是別的地方的策略問題,需要更深入地排查。
第二板斧:寬容模式下的“偵查”
將設備切換到寬容模式:adb shell setenforce 0。
復現問題,讓 SELinux 把所有拒絕信息都記錄下來。
導出日志:adb shell "dmesg | grep 'avc: denied'" > avc.log。
第三板斧:用 audit2allow 快速破案
audit2allow 是一個強大的工具,能根據你的日志自動生成策略規則。
使用 audit2allow 生成策略:audit2allow -i avc.log -M my_policy。
這條命令會生成 my_policy.te 和 my_policy.cil。my_policy.te 里面就是工具為你生成的 allow 規則。
注意! 盲目復制粘貼是禁忌!你需要仔細審查這些規則,只保留你需要的,然后把它們加到你的策略文件里。
最后一步: 將你的策略文件重新編譯,刷入設備,再把 SELinux 切換回 enforcing 模式:adb shell setenforce 1。
第四板斧:vendor 目錄下的排查與修復流程
快速確認:使用 dmesg | grep 'avc: denied' 抓取報錯日志。
分析日志:
scontext=u:r:<進程域>:s0:確定是哪個進程(進程域)犯錯。
tcontext=u:object_r:<資源類型>:s0:確定受害者的類型(資源類型)。
denied { <權限> }:確定具體是什么操作被拒絕。
定位策略文件:根據 進程域,定位到 vendor 目錄下對應的 .te 文件。
審查與添加規則:
在 .te 文件中,添加一條精確的 allow 規則。
如果涉及到新的可執行文件或設備,可能需要在 file_contexts 中添加新類型。
如果涉及到新的屬性,可能需要在 property_contexts 中添加新類型。
編譯與刷機:重新編譯 vendor 分區,刷入設備,驗證問題是否解決。
記住,在 vendor 目錄中解決問題是 Android 平臺 SELinux 開發的黃金法則。遵循這個原則,你的設備將更穩定,也更易于維護和升級。
轉載請注明出處SELinux 入門指南-CSDN博客,謝謝!