【framework】framework中为systemserver添加权限(添加用户组)

转载:https://blog.csdn.net/smilefyx/article/details/78880428

   之前以为在framework中不需要申请权限就可以直接使用,直到最近移植android6.0时,发现原来4.4上的代码移植到6.0上后无法正常使用,排查原因发现是在读写sdcard时因为没有读写权限导致出错,这才直到原来framework中的服务也是需要配置权限相关的东西的,只是方法和app中配置的方法不一样。如下记录该问题解决的方法:

1、测试代码

我在system server中自定义的服务中加入一段读写外置存储的测试代码,代码实现的功能非常简单,主要用三个方法构成,一个用于检测外置存储设备的挂载状态,一个用于读取显示外置存储中的文件列表,第三个方法用于向外置存储设备中创建一个测试文件,创建前如果存在就先删除。

[java]  view plain  copy
  1. private final static String[] sStorageArray = { "/mnt/extsd",  
  2.     "/mnt/extsd2""/mnt/usbhost/Storage01""/mnt/usbhost/Storage02",  
  3.     "/mnt/usbhost/Storage03" };  
  4.   
  5. @RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE""android.permission.WRITE_EXTERNAL_STORAGE"})  
  6. private static void checkStorageState() {  
  7.     String state = Environment.getExtsdStorageState();  
  8.     Log.d(TAG, "getExtsdStorageState=" + state);  
  9.     state = Environment.getExtsd2StorageState();  
  10.     Log.d(TAG, "getExtsd2StorageState=" + state);  
  11.     state = Environment.getUsbStorageState();  
  12.     Log.d(TAG, "getUsbStorageState=" + state);  
  13.     state = Environment.getExtsd2StorageState();  
  14.     Log.d(TAG, "getExtsd2StorageState=" + state);  
  15. }  
  16.   
  17. @RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE""android.permission.WRITE_EXTERNAL_STORAGE"})  
  18. private static void listFile(final String home) {  
  19.     Log.d(TAG, "Home ="+home);  
  20.     File f = new File(home);  
  21.     if (null != f && f.exists()) {  
  22.         Log.d(TAG, "Home " + home + "  is avaiable!");  
  23.         File list[] = f.listFiles();  
  24.         if (null != list && 0 < list.length) {  
  25.             Log.d(TAG, "File list is not empty.");  
  26.             for (File tf : list) {  
  27.                 if (null != tf) {  
  28.                     Log.d(TAG, "File name=" + tf.getName());  
  29.                 }  
  30.             }  
  31.         }  
  32.         else {  
  33.             Log.e(TAG, "File list is empty.");  
  34.         }  
  35.     } else {  
  36.         Log.e(TAG, "Home " + home + " is not avaiable.");  
  37.     }  
  38. }  
  39.   
  40. @RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE""android.permission.WRITE_EXTERNAL_STORAGE"})  
  41. private static void writeFile(final String home) {  
  42.     Log.d(TAG, "Home ="+home);  
  43.     File f = new File(home);  
  44.     if (null != f && f.exists()) {  
  45.         Log.d(TAG, "Home " + home + "  is avaiable!");  
  46.         final String fname = new StringBuilder().append(home).append(File.separatorChar).append("test.file").toString();  
  47.         File tf = new File(fname);            
  48.         try {  
  49.             tf.deleteOnExit();  
  50.             tf.createNewFile();  
  51.             Log.d(TAG, "Create "+fname+" success!");  
  52.         } catch (IOException e) {  
  53.             Log.e(TAG, "Write file:"+fname+" failed.");  
  54.             e.printStackTrace();  
  55.         }  
  56.     } else {  
  57.         Log.e(TAG, "Home " + home + " is not avaiable.");  
  58.     }         
  59. }     

2、问题描述

执行上述的测试代码后,发现获取存储设备状态成功,但是读取设备列表时始终为null,而创建文件时则直接抛出异常,异常原因是无权限。报错的主要日志如下:

[html]  view plain  copy
  1. 01-01 08:00:50.661 E/UpdateManagerService( 2591): Write file:/mnt/usbhost/Storage02/test.file failed.  
  2. 01-01 08:00:50.661 W/System.err( 2591): java.io.IOException: open failed: EACCES (Permission denied)  
  3. 01-01 08:00:50.665 W/System.err( 2591):     at java.io.File.createNewFile(File.java:939)  
  4. 01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService.writeFile(UpdateManagerService.java:77)  
  5. 01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService.-wrap2(UpdateManagerService.java)  
  6. 01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService$Lifecycle$1.run(UpdateManagerService.java:119)  
  7. 01-01 08:00:50.665 W/System.err( 2591):     at java.lang.Thread.run(Thread.java:818)  
  8. 01-01 08:00:50.665 W/System.err( 2591): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)  
  9. 01-01 08:00:50.669 W/System.err( 2591):     at libcore.io.Posix.open(Native Method)  
  10. 01-01 08:00:50.670 W/System.err( 2591):     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)  
  11. 01-01 08:00:50.670 W/System.err( 2591):     at java.io.File.createNewFile(File.java:932)  
  12. 01-01 08:00:50.670 W/System.err( 2591):     ... 4 more  

3、问题分析

(1)、查看当前进程所属的用户组

通过上述错误日志,找到对应的进程号,如本例中的进程号为2591。进入/proc虚拟文件系统下进程的相关目录,查看进程的运行信息,如本例中的进程目录:

[html]  view plain  copy
  1. cd /proc/2951  
通过如下命令查看进程的信息:

[html]  view plain  copy
  1. cat status  
进程信息中有一个Groups属性,包含了当前进程所属的用户组,该进程仅仅拥有所属组所具备的权限。


上面的里面是我修改过具备读写外置存储设备后的status,修改之前Groups中不包含1015组。

(2)、查看所属用户组具备的权限

上一步得到的用户组都是int型,其定义在android/system/core/include/private/android_filesystem_config.h文件中,本文列出其中部分定义说明,具体的可以自行查阅相关代码。从代码中可以看到外置存储卡写权限属于AID_SDCARD_RW组,即1015(上面说过,我在修改前system_server是不具备1015的用户组的,所以导致读写外置存储卡时抛出了权限问题)。

[html]  view plain  copy
  1. /* This is the master Users and Groups config for the platform.  
  2.  * DO NOT EVER RENUMBER  
  3.  */  
  4.   
  5. #define AID_ROOT             0  /* traditional unix root user */  
  6.   
  7. #define AID_SYSTEM        1000  /* system server */  
  8.   
  9. #define AID_RADIO         1001  /* telephony subsystem, RIL */  
  10. #define AID_BLUETOOTH     1002  /* bluetooth subsystem */  
  11. #define AID_GRAPHICS      1003  /* graphics devices */  
  12. #define AID_INPUT         1004  /* input devices */  
  13. #define AID_AUDIO         1005  /* audio devices */  
  14. #define AID_CAMERA        1006  /* camera devices */  
  15. #define AID_LOG           1007  /* log devices */  
  16. #define AID_COMPASS       1008  /* compass device */  
  17. #define AID_MOUNT         1009  /* mountd socket */  
  18. #define AID_WIFI          1010  /* wifi subsystem */  
  19. #define AID_ADB           1011  /* android debug bridge (adbd) */  
  20. #define AID_INSTALL       1012  /* group for installing packages */  
  21. #define AID_MEDIA         1013  /* mediaserver process */  
  22. #define AID_DHCP          1014  /* dhcp client */  
  23. #define AID_SDCARD_RW     1015  /* external storage write access */  
  24. #define AID_VPN           1016  /* vpn system */  
  25. #define AID_KEYSTORE      1017  /* keystore subsystem */  
  26. #define AID_USB           1018  /* USB devices */  
  27. #define AID_DRM           1019  /* DRM server */  
  28. #define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */  
  29. #define AID_GPS           1021  /* GPS daemon */  
  30. #define AID_UNUSED1       1022  /* deprecated, DO NOT USE */  
  31. #define AID_MEDIA_RW      1023  /* internal media storage write access */  
  32. #define AID_MTP           1024  /* MTP USB driver access */  
  33. #define AID_UNUSED2       1025  /* deprecated, DO NOT USE */  
  34. #define AID_DRMRPC        1026  /* group for drm rpc */  
  35. #define AID_NFC           1027  /* nfc subsystem */  
  36. #define AID_SDCARD_R      1028  /* external storage read access */  
  37. #define AID_CLAT          1029  /* clat part of nat464 */  
  38. #define AID_LOOP_RADIO    1030  /* loop radio devices */  
  39. #define AID_MEDIA_DRM     1031  /* MediaDrm plugins */  
  40. #define AID_PACKAGE_INFO  1032  /* access to installed package details */  
  41. #define AID_SDCARD_PICS   1033  /* external storage photos access */  
  42. #define AID_SDCARD_AV     1034  /* external storage audio/video access */  
  43. #define AID_SDCARD_ALL    1035  /* access all users external storage */  
  44. #define AID_LOGD          1036  /* log daemon */  
  45. #define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */  
  46.   
  47. #define AID_SHELL         2000  /* adb and debug shell user */  
  48. #define AID_CACHE         2001  /* cache access */  
  49. #define AID_DIAG          2002  /* access to diagnostic resources */  
  50.   
  51. /* The range 2900-2999 is reserved for OEM, and must never be  
  52.  * used here */  
  53. #define AID_OEM_RESERVED_START 2900  
  54. #define AID_OEM_RESERVED_END   2999  
  55.   
  56. /* The 3000 series are intended for use as supplemental group id's only.  
  57.  * They indicate special Android capabilities that the kernel is aware of. */  
  58. #define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */  
  59. #define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */  
  60. #define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */  
  61. #define AID_NET_RAW       3004  /* can create raw INET sockets */  
  62. #define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */  
  63. #define AID_NET_BW_STATS  3006  /* read bandwidth statistics */  
  64. #define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */  
  65. #define AID_NET_BT_STACK  3008  /* bluetooth: access config files */  
  66.   
  67. #define AID_EVERYBODY     9997  /* shared between all apps in the same profile */  
  68. #define AID_MISC          9998  /* access to misc storage */  
  69. #define AID_NOBODY        9999  
  70.   
  71. #define AID_APP          10000  /* first app user */  
  72.   
  73. #define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */  
  74. #define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */  
  75.   
  76. #define AID_USER        100000  /* offset for uid ranges for each user */  
  77.   
  78. #define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */  
  79. #define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */  
(3)、查看system_server启动参数

system_server是由ZygoteInit类负责初始化和启动的,相关的代码在sdk的android/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中。其中关键的启动代码如下。从代码中可以看到,在启动sysetm_server时通过--setgroups为其设置了所属用户组。

[java]  view plain  copy
  1. private static boolean startSystemServer(String abiList, String socketName)  
  2.         throws MethodAndArgsCaller, RuntimeException {  
  3.     long capabilities = posixCapabilitiesAsBits(  
  4.         OsConstants.CAP_BLOCK_SUSPEND,  
  5.         OsConstants.CAP_KILL,  
  6.         OsConstants.CAP_NET_ADMIN,  
  7.         OsConstants.CAP_NET_BIND_SERVICE,  
  8.         OsConstants.CAP_NET_BROADCAST,  
  9.         OsConstants.CAP_NET_RAW,  
  10.         OsConstants.CAP_SYS_MODULE,  
  11.         OsConstants.CAP_SYS_NICE,  
  12.         OsConstants.CAP_SYS_RESOURCE,  
  13.         OsConstants.CAP_SYS_TIME,  
  14.         OsConstants.CAP_SYS_TTY_CONFIG  
  15.     );  
  16.     /* Hardcoded command line to start the system server */  
  17.     String args[] = {  
  18.         "--setuid=1000",  
  19.         "--setgid=1000",  
  20.         "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1015,1018,1021,1032,3001,3002,3003,3006,3007",  
  21.         "--capabilities=" + capabilities + "," + capabilities,  
  22.         "--nice-name=system_server",  
  23.         "--runtime-args",  
  24.         "com.android.server.SystemServer",  
  25.     };  
  26.     ZygoteConnection.Arguments parsedArgs = null;  
  27.   
  28.     int pid;  
  29.   
  30.     try {  
  31.         parsedArgs = new ZygoteConnection.Arguments(args);  
  32.         ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);  
  33.         ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);  
  34.   
  35.         /* Request to fork the system server process */  
  36.         pid = Zygote.forkSystemServer(  
  37.                 parsedArgs.uid, parsedArgs.gid,  
  38.                 parsedArgs.gids,  
  39.                 parsedArgs.debugFlags,  
  40.                 null,  
  41.                 parsedArgs.permittedCapabilities,  
  42.                 parsedArgs.effectiveCapabilities);  
  43.     } catch (IllegalArgumentException ex) {  
  44.         throw new RuntimeException(ex);  
  45.     }  
  46.   
  47.     /* For child process */  
  48.     if (pid == 0) {  
  49.         if (hasSecondZygote(abiList)) {  
  50.             waitForSecondaryZygote(socketName);  
  51.         }  
  52.   
  53.         handleSystemServerProcess(parsedArgs);  
  54.     }  
  55.   
  56.     return true;  
  57. }  
注意:上述代码已经是我修改后(即添加用户组1015后)的代码,此时编译的system_server已经具备了读写外置存储的权限。

4、解决方法

在第三步的“问题分析”的最中其实已经给出了解决办法,但是这里还是重新说明下。问题总结主要几个方面:

(1)、查看进程当前所属的组;

(2)、查看所需权限所属的组;

(3)、比对当前进程是否属于需要权限的组;

(4)、修改启动参数添加组;

故,本文最后修改了ZygoteInit.java类,然后在--setgroups参数中增加了1015用户组。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值