由上圖得知,send_prop_msg 會透過 socket 將 cmd message 送給 INIT,當 INIT 接收到後,會呼叫 handle_property_set_fd 來做處理,該函式就會呼叫 check_perms 檢查權限,這也是為什麼有時候設定屬性會失敗的原因。check_perms 參考底下的 ACL (Access Control List) 做判斷:
<PATH>
system/core/init/property_service.c
struct { const char *prefix; unsigned int uid; unsigned int gid; } property_perms[] = { { "net.rmnet0.", AID_RADIO, 0 }, { "net.usb", AID_RADIO, 0 }, { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, { "ril.", AID_RADIO, 0 }, { "gsm.", AID_RADIO, 0 }, { "persist.radio", AID_RADIO, 0 }, { "net.dns", AID_RADIO, 0 }, { "net.", AID_SYSTEM, 0 }, { "dev.", AID_SYSTEM, 0 }, { "runtime.", AID_SYSTEM, 0 }, { "hw.", AID_SYSTEM, 0 }, { "sys.", AID_SYSTEM, 0 }, { "service.", AID_SYSTEM, 0 }, { "wlan.", AID_SYSTEM, 0 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 0 }, { "vpn.", AID_SYSTEM, 0 }, { "vpn.", AID_VPN, 0 }, { "debug.", AID_SHELL, 0 }, { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, { "service.adb.tcp.port", AID_SHELL, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, { "persist.security.", AID_SYSTEM, 0 }, { NULL, 0, 0 } };「check_perms」檢查的流程為:
如果 UID 為 ROOT .. PASS。 - 如果屬性為 ro 開頭,就接續判斷 ro. 之後的字串。
- 和 ACL 一一比對,prefix 要相同、且 uid/gid 有一個相同 .. PASS。
<PATH>
#define AID_ROOT 0 /* traditional unix root user */ #define AID_SYSTEM 1000 /* system server */ #define AID_RADIO 1001 /* telephony subsystem, RIL */ #define AID_BLUETOOTH 1002 /* bluetooth subsystem */ #define AID_GRAPHICS 1003 /* graphics devices */ #define AID_INPUT 1004 /* input devices */ #define AID_AUDIO 1005 /* audio devices */ #define AID_CAMERA 1006 /* camera devices */ ... ... static const struct android_id_info android_ids[] = { { "root", AID_ROOT, }, { "system", AID_SYSTEM, }, { "radio", AID_RADIO, }, { "bluetooth", AID_BLUETOOTH, }, { "graphics", AID_GRAPHICS, }, { "input", AID_INPUT, }, { "audio", AID_AUDIO, }, { "camera", AID_CAMERA, }, ... };
之前為了在 BluetoothService.java (UID/GID 皆為 system) 設定屬性,定義了 persist.bluetooth.a2dp 和 audioflinger.bluetooth.a2dp,但怎麼設定都設定不動,後來胡亂地嘗試 persist.service.bluetooth.a2dp 就成功了,回過頭來看,就是因為滿足 ACL 的要求啦!
如果自行定義的 prefix 可以正常存取,要嘛 UID/GID 為 ROOT;不然就只能唯讀。最後補充一點,在 /default.prop 這個檔案內看到的屬性,是 makefile 中由 ADDITIONAL_DEFAULT_PROPERTIES 這個變數產生;而 /system/build.prop 的是 build/tools/buildinfo.sh 和以下這段所產生。
ADDITIONAL_BUILD_PROPERTIES := $(ADDITIONAL_BUILD_PROPERTIES) \ $(PROPERTY_PROPERTY_OVERRIDES)
參考資料
5 則留言:
請問從哪裡可以確認
BluetoothService.java 的 UID/GID 皆為 system?
因為從android_filesystem_config.h看到的AID_BLUETOOTH 1002 而不是
AID_SYSTEM 1000
還是說不是從這邊看出來呢?
挖兩年前的文章了, 我想想喔, 我記得是利用adb shell進去看被啟動的process的權限, 因為android開機啟動的服務, 都是利用system server這個服務去喚起, 而system server的權限是system/system, 所以被喚起的服務, 例如bluetooth service就會繼承system server的權限
在這邊對原文補充一下, 就是在定義屬性名稱的時候, 盡量以property_perms提供的pattern去命名, 否則可能會有失敗的情況發生(當然我也是有看到有root權限的init, 裡頭隨便設定一個屬性名稱也可以, 這部分我就不知道怎麼解釋了XDD)
android_filesystem_config.h我只是想要對照system/core/init/property_service.c裡頭的property_perms, 所以想說一併貼出來, bluetooth service不是用AID_BLUETOOTH做為他的權限
張貼留言