Android coredomain 如何使用自定義的 property type?

背景

Android 8.1 中引入了 Project Treble 架構,用於將 vendor 下的驅動和 Android system 系統分開,Android system 可以單獨升級。SELinux 同樣分成了兩部分,位於 /system/etc/selinux 下的 platform 部分和位於 /vendor/etc/selinux 下的 vendor 部分。本文分析 Android 大版本升級過程中對 property 增加的一些限制,以及如何繞過這些限制。

Coredomain

哪些是 coredomain?

Coredomain 是 attribute,屬於 domain (針對進程)或者 type(針對對象,如文件等)的集合。coremain 可以理解爲包含 system 下可執行文件和 apps 所運行的 domain 或者說包含所有屬於 Android 的 domain。

如何查看?

代碼中查看

有兩種定義方式:

    1. type XXX ..., coredomain ...;
    2. typeattribute XXX coredomain;

上面兩種方式都是將 XXX 放入到 coredomain 集合中,即 XXX 是屬於 coredomain,對 coredomain 配置的權限也會同步給 XXX,同樣對 coredomain 的限制也會限制 XXX。

工具查看

Android system/sepolicy 源碼下有 sepolicy-analyze 工具,然後需要編譯好的 sepolicy 文件,使用下面命令可以查看 coredomain 都包含那些 domain:

    sepolicy-analyze 編譯好的sepolicy  attribute coredomain

{:.warning}
編譯好的policy,手機上可以從這兩個地方取:1. /vendor(或者odm)/etc/selinux/precompiled_sepolicy; 2. /sys/fs/selinux/policy

Android P

新增限制

升級 Android P 後發現 property 新增了一個 neverallow(neverallow 用於限制配置,明確指定不能幹什麼)。來看下該 neverallow:

#https://cs.android.com/android/platform/superproject/+/android-9.0.0_r11:system/sepolicy/public/property.te;l=314
compatible_property_only(`
  # Neverallow coredomain to set vendor properties
  neverallow {
    coredomain
    -init
    -system_writes_vendor_properties_violators
  } {
    property_type
    -apexd_prop
    -audio_prop
    -bluetooth_a2dp_offload_prop
    -bluetooth_audio_hal_prop
    -bluetooth_prop
    -bootloader_boot_reason_prop
    -boottime_prop
    -bpf_progs_loaded_prop
    -config_prop
    -cppreopt_prop
    -ctl_adbd_prop
    -ctl_bootanim_prop
    -ctl_bugreport_prop
    -ctl_console_prop
    -ctl_default_prop
    -ctl_dumpstate_prop
    -ctl_fuse_prop
    -ctl_gsid_prop
    -ctl_interface_restart_prop
    -ctl_interface_start_prop
    -ctl_interface_stop_prop
    -ctl_mdnsd_prop
    -ctl_restart_prop
    -ctl_rildaemon_prop
    -ctl_sigstop_prop
    -ctl_start_prop
    -ctl_stop_prop
    -dalvik_prop
    -debug_prop
    -debuggerd_prop
    -default_prop
    -device_logging_prop
    -dhcp_prop
    -dumpstate_options_prop
    -dumpstate_prop
    -exported2_config_prop
    -exported2_default_prop
    -exported2_radio_prop
    -exported2_system_prop
    -exported2_vold_prop
    -exported3_default_prop
    -exported3_radio_prop
    -exported3_system_prop
    -exported_bluetooth_prop
    -exported_config_prop
    -exported_dalvik_prop
    -exported_default_prop
    -exported_dumpstate_prop
    -exported_ffs_prop
    -exported_fingerprint_prop
    -exported_overlay_prop
    -exported_pm_prop
    -exported_radio_prop
    -exported_secure_prop
    -exported_system_prop
    -exported_system_radio_prop
    -exported_vold_prop
    -exported_wifi_prop
    -extended_core_property_type
    -ffs_prop
    -fingerprint_prop
    -firstboot_prop
    -device_config_activity_manager_native_boot_prop
    -device_config_reset_performed_prop
    -device_config_boot_count_prop
    -device_config_input_native_boot_prop
    -device_config_netd_native_prop
    -device_config_runtime_native_boot_prop
    -device_config_runtime_native_prop
    -device_config_media_native_prop
    -dynamic_system_prop
    -gsid_prop
    -heapprofd_enabled_prop
    -heapprofd_prop
    -hwservicemanager_prop
    -last_boot_reason_prop
    -system_lmk_prop
    -log_prop
    -log_tag_prop
    -logd_prop
    -logpersistd_logging_prop
    -lowpan_prop
    -lpdumpd_prop
    -mmc_prop
    -net_dns_prop
    -net_radio_prop
    -netd_stable_secret_prop
    -nfc_prop
    -overlay_prop
    -pan_result_prop
    -persist_debug_prop
    -persistent_properties_ready_prop
    -pm_prop
    -powerctl_prop
    -radio_prop
    -restorecon_prop
    -safemode_prop
    -serialno_prop
    -shell_prop
    -system_boot_reason_prop
    -system_prop
    -system_radio_prop
    -system_trace_prop
    -test_boot_reason_prop
    -test_harness_prop
    -theme_prop
    -time_prop
    -traced_enabled_prop
    -traced_lazy_prop
    -vendor_default_prop
    -vendor_security_patch_level_prop
    -vold_prop
    -wifi_log_prop
    -wifi_prop
  }:property_service set;
')

可以看到限制的是除了 init 和 system_writes_vendor_properties_violators 的 coredomain, 這些 domains 不能設置上述白名單之外的 property type, 這些屬於AOSP 定義的 types,所以是限制 system domains 不能設置 vendor properties,符合 Prject Treble 設計思想。

如何繞過限制?

由於廠商基本都會:

  1. 定義新的 property type,用於細粒度控制訪問權限,如 platform_app 或者 system_app 設置新的property,三方 app 可以讀;
  2. coredomain 需要設置 vendor properties。

但現在增加了 neverallow 限制,這些規則在編譯階段就會報錯,所以需要想辦法繞過限制。

從上面可以看到限制會排除 init 和 system_writes_vendor_properties_violators,init 是 domain,不能滿足要求,我們是需要 platform_app 或者 system_app 有權限。看下 system_writes_vendor_properties_violators 的定義:

# All system domains which violate the requirement of not writing vendor
# properties.
# TODO(b/78598545): Remove this once there are no violations
attribute system_writes_vendor_properties_violators;

首先是 attribute,不是具體的 type, 並且從註釋上看到,表示 system domains 違反去寫 vendor properties 的集合。這個也是 google 用於在升級中故意新增的,用於臨時繞過 neverallow 限制。所以,我們可以需要違反 neverallow 的添加上該 attribute。

解決方案爲: 爲需要違反的 domain 添加 system_writes_vendor_properties_violators。

如要給 platform_app 添加,配置下面規則:

    typeattribute platform_app system_writes_vendor_properties_violators;

Android Q

新增限制

google 在 GTS 中新增了一條測試 case:

com.google.android.security.gts.SELinuxHostTest#testNoExemptionsForCoreWritingVendorSysprops

SELinuxHostTest 是在 GTS GtsSecurityHostTestCases.jar 中,使用 JD-GUI 反編譯找到 testNoExemptionsForCoreWritingVendorSysprops 方法:

  public void testNoExemptionsForCoreWritingVendorSysprops() {
    if (this.mFirstApiLevel < 29) { // 使用 firstApi 排除升級的老機型
      return;
    }
    
    // 是獲取有 attribute 是 system_writes_vendor_properties_violators 的 domain
    Set<String> types = sepolicyAnalyzeGetTypesAssociatedWithAttribute("system_writes_vendor_properties_violators"); 
    
    if (!types.isEmpty()) {
      List<String> sortedTypes = new ArrayList<String>(types);
      Collections.sort(sortedTypes);
      fail("Policy exempts core domains from ban on writing vendor system properties: " + sortedTypes); // 不爲空,則測試失敗
    } 
  }
}

從上面看到: 1)針對的是 Q 新機型; 2)若指定有 system_writes_vendor_properties_violators 的則失敗,即不能爲 domain 指定 system_writes_vendor_properties_violators。

所有針對 Q 新機型,不能採用 P 繞過方式。

如何繞過限制?

使用現有的 AOSP property type

Neverallow 不能從 domain 進行繞過,只能選擇從 property type,即不能定義新的 property,只能使用現有的。這樣有兩個弊端:

  1. 不能對權限細粒度控制,只能在現有權限的基礎上增加,而不能減少,這樣修改的話勢必導致權限擴大;
  2. type 名字選擇都是有意義,但現在只能從權限和名字上找到平衡,可能權限滿足,但名字意義差太遠。

那有沒有更好的方式?

定義新的 property type

通過對 neverallow 中的每個 type 分析,發現 extended_core_property_type 是 attribute,而不是具體的 type:


# All properties that are not specific to device but are added from
# outside of AOSP. (e.g. OEM-specific properties)
# These properties are not accessible from device-specific domains
attribute extended_core_property_type;

從註釋可以看到,這個 attribute 是 google 專門給廠商保留的,太好了。 但是 “These properties are not accessible from device-specific domains” 表示 device-specific domains 不能訪問,來看下是怎麼限制的:

# Prevent properties from being read
  neverallow {
    domain
    -coredomain
    -appdomain
    -vendor_init
  } {
    core_property_type
    extended_core_property_type # it
    exported_dalvik_prop
    exported_ffs_prop
    exported_system_radio_prop
    exported2_config_prop
    exported2_system_prop
    exported2_vold_prop
    exported3_default_prop
    exported3_system_prop
    -debug_prop
    -logd_prop
    -nfc_prop
    -powerctl_prop
    -radio_prop
  }:file no_rw_file_perms;

可以看到除了 coredomain, appdomain, vendor_init 外都不能訪問,那這種方式定義的 property 只能由 coredomain, appdomain 和 vendor_init 來訪問。雖然有限制,但是已經能滿足大部分需求,如上面提到的規則: platform_app 或者 system_app 設置,三方 apps 去讀。

解決方案:爲新定義的 property type 指定 extended_core_property_type。

{:.warning}
這種方式 vendor domain沒有權限去讀寫。

思考

如果有需求是需要 coredomain 和 vendor domain 同時有讀寫權限,那怎麼辦?

目前來看,新建 property type不能滿足需求,現有 AOSP 存在的 property type 如果沒有限制,也儘量不要使用,防止以後有變動,建議:

1. 業務邏輯上重新設計,儘量避免這種情況出現;

2. 使用 init 或者 vendor_init 代替設置,init 和 vendor_init 權限較高,並且限制較少,如對 init script 中配置自動 setprop 規則。

end

關注公衆號,瞭解更多信息!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章