歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 為Android應用程序讀取/dev下設備而提權

為Android應用程序讀取/dev下設備而提權

日期:2017/3/1 11:03:04   编辑:Linux編程

倘若應用程序需要對/dev/xxx進行讀寫操作,就需要提升其權限。提權方法不唯一,需要根據具體需求情況而選擇。歸根結底,終究都落到chmod 777 /dev/xxx 上,不同的是,chmod操作被執行在何時何地,在此做個分析總結。

內核啟動後會執行/system/init,傳說中的系統1號進程,init程序起初的任務是初始化,包括各種mkdir來構建文件系統,得到硬件信息建立設備節點,安裝SIGCHLD信號來回收僵屍進程的資源,解析init.rc啟動腳本等等,然後init程序變身為property_service來管理系統的權限。我們可以下手的地方有兩處: device_init和init.rc


✿ init.rc

這個方案是大家用的比較多的,在其中添加chmod操作很簡單不多說。


✿ device.c

這個方案用的比較少,先了解下device.c。
device_init在/system/core/init/device.c中,詳細分析如下:
  1. //分別遍歷/sys/class /sys/block /sys/devices
  2. device_init()
  3. {
  4. coldboot(fd,"/sys/class");
  5. coldboot(fd,"/sys/block");
  6. coldboot(fd,"/sys/devices");
  7. }
  8. //後面有個遞歸 /sys下是內核生成的設備,這就相當於udev的作用
  9. do_coldboot()
  10. {
  11. if(fd>= 0) {
  12. write(fd,"add\n", 4);
  13. close(fd);
  14. handle_device_fd(event_fd);
  15. }
  16. }
  17. //從socket裡讀出add處理
  18. handle_device_fd()
  19. {
  20. if(!strcmp(uevent->action,"add")) {
  21. make_device(devpath,block, uevent->major, uevent->minor);
  22. return;
  23. }
  24. }
  25. //得到設備的相關信息創建設備節點
  26. make_device()
  27. {
  28. mode= get_device_perm(path,&uid, &gid) | (block ? S_IFBLK : S_IFCHR);
  29. dev= (major << 8) | minor;
  30. mknod(path,mode, dev);
  31. chown(path,uid, gid);
  32. }
  33. get_device_perm()
  34. {
  35. if(get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) {
  36. returnperm;
  37. }elseif(get_device_perm_inner(devperms,path, uid, gid, &perm) == 0){
  38. returnperm;
  39. }else{
  40. …….
  41. }
  42. //得到devperms結構體的信息
  43. get_device_perm_inner
  44. {
  45. for(i= 0; perms[i].name; i++) {
  46. if(perms[i].prefix){
  47. if(strncmp(path,perms[i].name, strlen(perms[i].name)))
  48. continue;
  49. }else{
  50. if(strcmp(path,perms[i].name))
  51. continue;
  52. }
  53. *uid= perms[i].uid;
  54. *gid= perms[i].gid;
  55. *perm= perms[i].perm; //權限位
  56. return0;
  57. }
  58. }
  59. 這是devperms的具體內容
  60. structperms_ {
  61. char*name;
  62. mode_tperm;
  63. unsignedintuid;
  64. unsignedintgid;
  65. unsignedshortprefix;
  66. };
  67. staticstructperms_ devperms[] = {
  68. {"/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
  69. {"/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 },
  70. {"/dev/full", 0666, AID_ROOT, AID_ROOT, 0 },
  71. {"/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 },
  72. {"/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 },
  73. {"/dev/random", 0666, AID_ROOT, AID_ROOT, 0 },
  74. {"/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 },
  75. {"/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 },
  76. {"/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 },
  77. /* logger should be world writable (for logging) but not readable*/
  78. {"/dev/log/", 0662, AID_ROOT, AID_LOG, 1 },
  79. /*these should not be world writable */
  80. {"/dev/Android_adb", 0660, AID_ADB, AID_ADB, 0 },
  81. {"/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 },
  82. {"/dev/ttyMSM0", 0660, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
  83. {"/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 },
  84. {"/dev/tty0", 0666, AID_ROOT, AID_SYSTEM, 0 },
  85. {"/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 },
  86. {"/dev/hw3d", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
  87. {"/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 },
  88. {"/dev/eac", 0660, AID_ROOT, AID_AUDIO, 0 },
  89. {"/dev/cam", 0660, AID_ROOT, AID_CAMERA, 0 },
  90. {"/dev/pmem", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
  91. {"/dev/pmem_gpu", 0660, AID_SYSTEM, AID_GRAPHICS, 1 },
  92. {"/dev/pmem_adsp", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  93. {"/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 },
  94. {"/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
  95. {"/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  96. {"/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
  97. {"/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
  98. {"/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
  99. {"/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
  100. {"/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  101. {"/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  102. {"/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  103. {"/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
  104. {"/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
  105. {"/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
  106. {"/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
  107. {"/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
  108. {"/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
  109. {"/dev/htc-acoustic", 0640, AID_RADIO, AID_RADIO, 0 },
  110. {NULL, 0, 0, 0, 0 },
  111. };

✿ init.c

init.rc腳本和老版本android中的init.goldfish.rc腳本很早就被parse_config_file()函數解析將腳本內容分為幾個段,early-init,init,early-boot,boot,和各個服務。然後在不同的時間點上執行各個段得命令或者開啟各種服務。

init.c的一段節選:
  1. int main(intargc, char**argv)
  2. {
  3. ……
  4. mkdir("/dev",0755);
  5. mkdir("/proc",0755);
  6. mkdir("/sys",0755);
  7. mount("tmpfs","/dev", "tmpfs", 0, "mode=0755");
  8. mkdir("/dev/pts",0755);
  9. mkdir("/dev/socket",0755);
  10. mount("devpts","/dev/pts", "devpts", 0, NULL);
  11. mount("proc","/proc", "proc", 0, NULL);
  12. mount("sysfs","/sys", "sysfs", 0, NULL);
  13. … …
  14. INFO("readingconfig file\n");
  15. parse_config_file("/init.rc");
  16. //調用parse_config解析init.rc腳本
  17. //經過解析,init.rc的內容就被分為多少個段,被串在action_list鏈表中。
  18. //on開頭的都是action類型的段,比如init段,init段用一個結構體struct action表示,其中name是init,
  19. //所有這個段內的命令,都被串在commands鏈表中。
  20. action_for_each_trigger("early-init",action_add_queue_tail);
  21. //遍歷action_list鏈表,查找name是early-init的那個action,將這個節點放在action_queue的尾部。
  22. drain_action_queue();
  23. //將action_queue尾部的節點遍歷,然後刪除。
  24. //就相當於遍歷name是early-init的action節點內的commands鏈表。
  25. //就是在執行init.rc腳本中onearly-init段內的所有命令。
  26. ……
  27. INFO("deviceinit\n");
  28. device_fd= device_init(); //常見必要的設備節點
  29. property_init();//init 以後的任務就是proper_service
  30. action_for_each_trigger("init",action_add_queue_tail); //將init段,加入action_queue
  31. drain_action_queue();// 執行init段得命令
  32. … …
  33. }

✿ 本節小結

device_init其實就是linux中的udev的一個簡單的替代。把/sys/下的所有內核提供的設備都安排在/dev下創建設備節點。如果要改動/dev/一些設備的權限,可以把chmod 777寫在init.rc中,但是要注意寫的位置,不能太早執行,不能寫在early-init段內,因為那時/dev/下的設備節點還沒有被創建。
在devices.c中修改的方法隱藏的較深不容易被發現,但是如果init.rc內再次修改就可能把之前的修改覆蓋掉。
Copyright © Linux教程網 All Rights Reserved