由上圖得知,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做為他的權限
張貼留言