内容简介:这个阶段搞了很多和Android文件权限相关的问题,虽然一知半解,但也算是对Android权限机制有一些自己的理解。遂将这些内容整理出来。因为权限这部分涉及到的内容很多,故将知识分为几块内容分别去整理。目前能想到的概要如下:这是第一篇。2,3,4已经有一些草稿了,但离发出来还有一些时间。5,6,7还在规划中。可以关注新弄的公众号softard,后面比较完善的文章都会在这个号上及时更新。这里再推荐一本书
这个阶段搞了很多和Android文件权限相关的问题,虽然一知半解,但也算是对Android权限机制有一些自己的理解。遂将这些内容整理出来。因为权限这部分涉及到的内容很多,故将知识分为几块内容分别去整理。目前能想到的概要如下:
- Android 权限底层实现原理概述
- Android uid,gid的生成与权限机制的联系
- Android packageManagerService与权限的千丝万缕(源码解析)
- Android 从recovery模式下的OTA升级理解权限
- Android ROOT 原理
- Android 签名
- Android 权限大杀器 — Selinux的策略
这是第一篇。2,3,4已经有一些草稿了,但离发出来还有一些时间。5,6,7还在规划中。可以关注新弄的公众号softard,后面比较完善的文章都会在这个号上及时更新。
这里再推荐一本书
0001 Overview
Linux File Permission
众所周知,Android的内核是 linux 的内核。对于linux来说,系统的一切都是文件。同时,linux为文件系统设计了一套完善的权限机制。下面简单提一下linux文件权限的核心:
比如在Android手机adb shell下查看一个目录
# ls -ld data/data/ drwxrwx--x 113 system system 4096 1970-01-01 15:08 data/data/
其中, drwxrwx--x
这10位代表文件权限,第一位文件类型可以忽略(这里类型是文件夹),后面每三位代表文件拥有的权限,包括rwx(可读,可写,可执行)。 system system
表示文件属于system用户和属于system组。
翻译过来是,system用户对该文件拥有读写执行权限,system组对该文件拥有读写执行权限,其他用户对该文件拥有执行权限。简单来说就是771权限。
Android Permission
Permission权限是Android系统定义的一套权限机制,用于控制APP访问某个硬件设备或某个Android系统的组件。
举两个常见的例子:
- 如果你的App想要访问存储卡,你需要在你的AndroidManifest文件中使用对应的permission用于向系统请求权限 。
- 你可以给你的Activity组件加个自定义的访问权限,这样任何想启动该Activity的程序必须在它的AndroidManifest中进行权限的请求。见 Android自定义权限 。
那么为什么你在AndroidManifest文件请求storage权限你就可以访问设备文件?linux文件属性的权限和Permission到底是怎么联系起来的呢?下面我们来具体来讲。
0010 packages.list & packages.xml
Android开机阶段会扫描所有App,从Manifest文件中把App信息和权限存到 packages.xml
和 packages.list
文件中,具体的处理过程会在后面第三篇去分析。
因为文件包含所有已安装应用的信息,所以我们尝试安装一个App(com.softard.test),并且查看其信息:
packages.list
com.softard.test 10052 1 /data/user/0/com.softard.test default none
这里10052是uid,至于其怎么生成的后面第二篇再详谈。
packages.xml
<package name="com.softard.test" codePath="/data/app/com.softard.test-1" nativeLibraryPath="/data/app/com.softard.test-1/lib" publicFlags="944291654" privateFlags="0" ft="8bbd70" it="89023c" ut="8bc04d" version="1" userId="10052"> <sigs count="1"> <cert index="10" key="308..../> </sigs> <proper-signing-keyset identifier="11" /> </package>
然后对App做个修改,将其改成系统App并签名放到 system/app/Test
下,再看这两个文件:
com.softard.test 1000 0 /data/user/0/com.softard.test platform 3009,3002,1023,1015,3003,3001,1021,1000,2002,2950,1010,1007
看到uid变成了1000,selinux从default变成platform,权限组从none变成3009,3002,1023,1015,3003,3001,1021,1000,2002,2950,1010,1007。而且应用一下子增加了一堆权限:
<package name="com.softard.test" codePath="/system/app/Test" nativeLibraryPath="/system/app/Test/lib" primaryCpuAbi="armeabi-v7a" publicFlags="944291397" privateFlags="0" ft="1683b80c790" it="1683b80c790" ut="1683b80c790" version="1" sharedUserId="1000" isOrphaned="true"> <sigs count="1"> <cert index="0" /> </sigs> <perms> <item name="android.permission.BIND_INCALL_SERVICE" granted="true" flags="0" /> <item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" /> <item name="android.permission.CONFIGURE_WIFI_DISPLAY" granted="true" flags="0" /> <item name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" granted="true" flags="0" /> <item name="android.permission.ACCESS_WIMAX_STATE" granted="true" flags="0" /> <item name="android.permission.RECOVERY" granted="true" flags="0" /> <item name="com.qualcomm.permission.READPROC" granted="true" flags="0" /> <item name="android.permission.USE_CREDENTIALS" granted="true" flags="0" /> <item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" /> <item name="android.permission.ACCESS_CHECKIN_PROPERTIES" granted="true" flags="0" /> <item name="com.zqautomotive.oris.wechat.provider.WRITE" granted="true" flags="0" /> <item name="android.permission.INSTALL_LOCATION_PROVIDER" granted="true" flags="0" /> <item name="android.permission.MANAGE_ACCOUNTS" granted="true" flags="0" /> <item name="android.permission.SYSTEM_ALERT_WINDOW" granted="true" flags="0" /> <item name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION" granted="true" flags="0" /> <item name="android.permission.CONTROL_LOCATION_UPDATES" granted="true" flags="0" /> <item name="android.permission.CLEAR_APP_USER_DATA" granted="true" flags="0" /> <item name="com.zqautomotive.oris.wechat.provider.READ" granted="true" flags="0" /> <item name="android.permission.BROADCAST_CALLLOG_INFO" granted="true" flags="0" /> <item name="android.permission.NFC" granted="true" flags="0" /> <item name="android.permission.CALL_PRIVILEGED" granted="true" flags="0" /> <item name="android.permission.CHANGE_NETWORK_STATE" granted="true" flags="0" /> <item name="android.permission.MASTER_CLEAR" granted="true" flags="0" /> <item name="android.permission.WRITE_SYNC_SETTINGS" granted="true" flags="0" /> <item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" /> <item name="android.permission.PEERS_MAC_ADDRESS" granted="true" flags="0" /> <item name="android.permission.DEVICE_POWER" granted="true" flags="0" /> <item name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" granted="true" flags="0" /> <item name="android.permission.READ_PROFILE" granted="true" flags="0" /> <item name="android.permission.BLUETOOTH" granted="true" flags="0" /> <item name="android.permission.WRITE_MEDIA_STORAGE" granted="true" flags="0" /> <item name="android.permission.WRITE_BLOCKED_NUMBERS" granted="true" flags="0" /> <item name="com.qualcomm.permission.USE_QCRIL_MSG_TUNNEL" granted="true" flags="0" /> <item name="android.permission.ACCESS_SURFACE_FLINGER" granted="true" flags="0" /> <item name="com.zqautomotive.voice_controller.GET_SPEECH_RESULT" granted="true" flags="0" /> <item name="android.permission.AUTHENTICATE_ACCOUNTS" granted="true" flags="0" /> <item name="android.permission.INTERNET" granted="true" flags="0" /> <item name="android.permission.REORDER_TASKS" granted="true" flags="0" /> <item name="zq.permissio.CONNECTION_MQTT_SERVICE" granted="true" flags="0" /> <item name="android.permission.BLUETOOTH_ADMIN" granted="true" flags="0" /> <item name="android.permission.CONTROL_VPN" granted="true" flags="0" /> <item name="android.permission.UPDATE_DEVICE_STATS" granted="true" flags="0" /> <item name="android.permission.MANAGE_FINGERPRINT" granted="true" flags="0" /> <item name="com.qualcomm.permission.IZAT" granted="true" flags="0" /> <item name="android.permission.BIND_CONNECTION_SERVICE" granted="true" flags="0" /> <item name="android.permission.MANAGE_USB" granted="true" flags="0" /> <item name="android.permission.INTERACT_ACROSS_USERS_FULL" granted="true" flags="0" /> <item name="android.permission.STOP_APP_SWITCHES" granted="true" flags="0" /> <item name="android.permission.BATTERY_STATS" granted="true" flags="0" /> <item name="android.permission.PACKAGE_USAGE_STATS" granted="true" flags="0" /> <item name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" granted="true" flags="0" /> <item name="android.permission.TETHER_PRIVILEGED" granted="true" flags="0" /> <item name="android.permission.WRITE_SECURE_SETTINGS" granted="true" flags="0" /> <item name="android.permission.MOVE_PACKAGE" granted="true" flags="0" /> <item name="android.permission.READ_BLOCKED_NUMBERS" granted="true" flags="0" /> <item name="com.qualcomm.permission.wfd.QC_WFD" granted="true" flags="0" /> <item name="android.permission.READ_SEARCH_INDEXABLES" granted="true" flags="0" /> <item name="android.permission.ACCESS_IMS_CALL_SERVICE" granted="true" flags="0" /> <item name="android.permission.BLUETOOTH_PRIVILEGED" granted="true" flags="0" /> <item name="android.permission.HARDWARE_TEST" granted="true" flags="0" /> <item name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE" granted="true" flags="0" /> <item name="android.permission.BIND_JOB_SERVICE" granted="true" flags="0" /> <item name="android.permission.CONFIRM_FULL_BACKUP" granted="true" flags="0" /> <item name="android.permission.SET_TIME" granted="true" flags="0" /> <item name="android.permission.WRITE_APN_SETTINGS" granted="true" flags="0" /> <item name="android.permission.CHANGE_WIFI_STATE" granted="true" flags="0" /> <item name="android.permission.MANAGE_USERS" granted="true" flags="0" /> <item name="android.permission.SET_PREFERRED_APPLICATIONS" granted="true" flags="0" /> <item name="android.permission.DELETE_CACHE_FILES" granted="true" flags="0" /> <item name="android.permission.ACCESS_NETWORK_STATE" granted="true" flags="0" /> <item name="zq.permissio.CONNECTION_ACTIVATION_SERVICE" granted="true" flags="0" /> <item name="android.permission.DISABLE_KEYGUARD" granted="true" flags="0" /> <item name="android.permission.BACKUP" granted="true" flags="0" /> <item name="android.permission.CHANGE_CONFIGURATION" granted="true" flags="0" /> <item name="android.permission.USER_ACTIVITY" granted="true" flags="0" /> <item name="android.permission.READ_LOGS" granted="true" flags="0" /> <item name="android.permission.COPY_PROTECTED_DATA" granted="true" flags="0" /> <item name="android.permission.INTERACT_ACROSS_USERS" granted="true" flags="0" /> <item name="android.permission.SET_KEYBOARD_LAYOUT" granted="true" flags="0" /> <item name="android.permission.USE_FINGERPRINT" granted="true" flags="0" /> <item name="android.permission.WRITE_USER_DICTIONARY" granted="true" flags="0" /> <item name="android.permission.READ_SYNC_STATS" granted="true" flags="0" /> <item name="android.permission.REBOOT" granted="true" flags="0" /> <item name="android.permission.OEM_UNLOCK_STATE" granted="true" flags="0" /> <item name="android.permission.MANAGE_DEVICE_ADMINS" granted="true" flags="0" /> <item name="android.permission.CHANGE_APP_IDLE_STATE" granted="true" flags="0" /> <item name="android.permission.SET_POINTER_SPEED" granted="true" flags="0" /> <item name="android.permission.MANAGE_NOTIFICATIONS" granted="true" flags="0" /> <item name="android.permission.READ_SYNC_SETTINGS" granted="true" flags="0" /> <item name="android.permission.OVERRIDE_WIFI_CONFIG" granted="true" flags="0" /> <item name="android.permission.FORCE_STOP_PACKAGES" granted="true" flags="0" /> <item name="android.permission.ACCESS_NOTIFICATIONS" granted="true" flags="0" /> <item name="android.permission.VIBRATE" granted="true" flags="0" /> <item name="com.android.certinstaller.INSTALL_AS_USER" granted="true" flags="0" /> <item name="android.permission.READ_USER_DICTIONARY" granted="true" flags="0" /> <item name="android.permission.ACCESS_WIFI_STATE" granted="true" flags="0" /> <item name="android.permission.CHANGE_WIMAX_STATE" granted="true" flags="0" /> <item name="android.permission.MODIFY_PHONE_STATE" granted="true" flags="0" /> <item name="android.permission.STATUS_BAR" granted="true" flags="0" /> <item name="android.permission.READ_FRAME_BUFFER" granted="true" flags="0" /> <item name="android.permission.LOCATION_HARDWARE" granted="true" flags="0" /> <item name="android.permission.WAKE_LOCK" granted="true" flags="0" /> <item name="android.permission.INJECT_EVENTS" granted="true" flags="0" /> <item name="android.permission.DELETE_PACKAGES" granted="true" flags="0" /> </perms> <proper-signing-keyset identifier="1" /> </package>
所以问题来了,改成系统应用后uid为什么变成1000?后面代表权限组的一串数字又都是什么?
0011 Android File Permission
android_filesystem_config.h
在Android中,所有权限的定义都在: system/core/include/private/android_filesystem_config.h
在这个头文件中定义了Android系统的一些用户,包含root用户,system用户,shell用户所对应的值等等。
/* This is the master Users and Groups config for the platform. * DO NOT EVER RENUMBER */ #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 */ #define AID_LOG 1007 /* log devices */ #define AID_COMPASS 1008 /* compass device */ #define AID_MOUNT 1009 /* mountd socket */ #define AID_WIFI 1010 /* wifi subsystem */ #define AID_ADB 1011 /* android debug bridge (adbd) */ #define AID_INSTALL 1012 /* group for installing packages */ #define AID_MEDIA 1013 /* mediaserver process */ #define AID_DHCP 1014 /* dhcp client */ #define AID_SDCARD_RW 1015 /* external storage write access */ #define AID_VPN 1016 /* vpn system */ #define AID_KEYSTORE 1017 /* keystore subsystem */ #define AID_USB 1018 /* USB devices */ #define AID_DRM 1019 /* DRM server */ #define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */ #define AID_GPS 1021 /* GPS daemon */ #define AID_UNUSED1 1022 /* deprecated, DO NOT USE */ #define AID_MEDIA_RW 1023 /* internal media storage write access */ #define AID_MTP 1024 /* MTP USB driver access */ #define AID_UNUSED2 1025 /* deprecated, DO NOT USE */ #define AID_DRMRPC 1026 /* group for drm rpc */ #define AID_NFC 1027 /* nfc subsystem */ #define AID_SDCARD_R 1028 /* external storage read access */ #define AID_CLAT 1029 /* clat part of nat464 */ #define AID_LOOP_RADIO 1030 /* loop radio devices */ #define AID_MEDIA_DRM 1031 /* MediaDrm plugins */ #define AID_PACKAGE_INFO 1032 /* access to installed package details */ #define AID_SDCARD_PICS 1033 /* external storage photos access */ #define AID_SDCARD_AV 1034 /* external storage audio/video access */ #define AID_SDCARD_ALL 1035 /* access all users external storage */ #define AID_LOGD 1036 /* log daemon */ #define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */ #define AID_DBUS 1038 /* dbus-daemon IPC broker process */ #define AID_TLSDATE 1039 /* tlsdate unprivileged user */ #define AID_MEDIA_EX 1040 /* mediaextractor process */ #define AID_AUDIOSERVER 1041 /* audioserver process */ #define AID_METRICS_COLL 1042 /* metrics_collector process */ #define AID_METRICSD 1043 /* metricsd process */ #define AID_WEBSERV 1044 /* webservd process */ #define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */ #define AID_MEDIA_CODEC 1046 /* mediacodec process */ #define AID_CAMERASERVER 1047 /* cameraserver process */ #define AID_FIREWALL 1048 /* firewalld process */ #define AID_TRUNKS 1049 /* trunksd process (TPM daemon) */ #define AID_NVRAM 1050 /* Access-controlled NVRAM */ #define AID_DNS 1051 /* DNS resolution daemon (system: netd) */ #define AID_DNS_TETHER 1052 /* DNS resolution daemon (tether: dnsmasq) */ /* Changes to this file must be made in AOSP, *not* in internal branches. */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ #define AID_DIAG 2002 /* access to diagnostic resources */ /* The range 2900-2999 is reserved for OEM, and must never be * used here */ #define AID_OEM_RESERVED_START 2900 #define AID_OEM_RESERVED_END 2999 /* The 3000 series are intended for use as supplemental group id's only. * They indicate special Android capabilities that the kernel is aware of. */ #define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */ #define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */ #define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */ #define AID_NET_RAW 3004 /* can create raw INET sockets */ #define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */ #define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ #define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ #define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ #define AID_READPROC 3009 /* Allow /proc read access */ #define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */ /* The range 5000-5999 is also reserved for OEM, and must never be used here. */ #define AID_OEM_RESERVED_2_START 5000 #define AID_OEM_RESERVED_2_END 5999 #define AID_EVERYBODY 9997 /* shared between all apps in the same profile */ #define AID_MISC 9998 /* access to misc storage */ #define AID_NOBODY 9999 #define AID_APP 10000 /* first app user */ #define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ #define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ #define AID_USER 100000 /* offset for uid ranges for each user */ #define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ #define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */
从头文件定义,就知道每个权限组都是由一串数字代表的。除了数字,该文件还定义了一个结构体数组,映射数字对应的字符串:
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, }, { "log", AID_LOG, }, { "compass", AID_COMPASS, }, { "mount", AID_MOUNT, }, { "wifi", AID_WIFI, }, { "adb", AID_ADB, }, { "install", AID_INSTALL, }, { "media", AID_MEDIA, }, { "dhcp", AID_DHCP, }, { "sdcard_rw", AID_SDCARD_RW, }, { "vpn", AID_VPN, }, { "keystore", AID_KEYSTORE, }, { "usb", AID_USB, }, { "drm", AID_DRM, }, { "mdnsr", AID_MDNSR, }, { "gps", AID_GPS, }, // AID_UNUSED1 { "media_rw", AID_MEDIA_RW, }, { "mtp", AID_MTP, }, // AID_UNUSED2 { "drmrpc", AID_DRMRPC, }, { "nfc", AID_NFC, }, { "sdcard_r", AID_SDCARD_R, }, { "clat", AID_CLAT, }, { "loop_radio", AID_LOOP_RADIO, }, { "mediadrm", AID_MEDIA_DRM, }, { "package_info", AID_PACKAGE_INFO, }, { "sdcard_pics", AID_SDCARD_PICS, }, { "sdcard_av", AID_SDCARD_AV, }, { "sdcard_all", AID_SDCARD_ALL, }, { "logd", AID_LOGD, }, { "shared_relro", AID_SHARED_RELRO, }, { "dbus", AID_DBUS, }, { "tlsdate", AID_TLSDATE, }, { "mediaex", AID_MEDIA_EX, }, { "audioserver", AID_AUDIOSERVER, }, { "metrics_coll", AID_METRICS_COLL }, { "metricsd", AID_METRICSD }, { "webserv", AID_WEBSERV }, { "debuggerd", AID_DEBUGGERD, }, { "mediacodec", AID_MEDIA_CODEC, }, { "cameraserver", AID_CAMERASERVER, }, { "firewall", AID_FIREWALL, }, { "trunks", AID_TRUNKS, }, { "nvram", AID_NVRAM, }, { "dns", AID_DNS, }, { "dns_tether", AID_DNS_TETHER, }, { "shell", AID_SHELL, }, { "cache", AID_CACHE, }, { "diag", AID_DIAG, }, { "net_bt_admin", AID_NET_BT_ADMIN, }, { "net_bt", AID_NET_BT, }, { "inet", AID_INET, }, { "net_raw", AID_NET_RAW, }, { "net_admin", AID_NET_ADMIN, }, { "net_bw_stats", AID_NET_BW_STATS, }, { "net_bw_acct", AID_NET_BW_ACCT, }, { "net_bt_stack", AID_NET_BT_STACK, }, { "readproc", AID_READPROC, }, { "wakelock", AID_WAKELOCK, }, { "everybody", AID_EVERYBODY, }, { "misc", AID_MISC, }, { "nobody", AID_NOBODY, }, };
好了,了解这个文件我们再来看我们应用的信息:
com.softard.test 1000 0 /data/user/0/com.softard.test platform 3009,3002,1023,1015,3003,3001,1021,1000,2002,1010,1007
我们把数字对应的信息截取下来:
#define AID_SYSTEM 1000 "system" /* system server */ #define AID_LOG 1007 "log" /* log devices */ #define AID_WIFI 1010 "wifi" /* wifi subsystem */ #define AID_SDCARD_RW 1015 "sdcard_rw" /* external storage write access */ #define AID_GPS 1021 "gps" /* GPS daemon */ #define AID_MEDIA_RW 1023 "media_rw" /* internal media storage write access */ #define AID_DIAG 2002 "diag" /* access to diagnostic resources */ #define AID_NET_BT_ADMIN 3001 "net_bt_admin"/* bluetooth: create any socket */ #define AID_NET_BT 3002 "net_bt" /* bluetooth: create sco, rfcomm or l2cap sockets */ #define AID_INET 3003 "inet" /* can create AF_INET and AF_INET6 sockets */ #define AID_READPROC 3009 "readproc" /* Allow /proc read access */
所以,当我指定应用为系统应用时,就将uid指定为了1000。并且拥有了各种属于系统的权限组。
那么,指定系统应用后是怎么获得这一系列的gid呢?这一块源码流程很多,放到后面集中分析。
好了,现在我们了解 system/core/include/private/android_filesystem_config.h
文件定义以后,其实就前进了一大步。注意一下代码所在源码位置,位于 system/core
下,其实它已经是Android内核部分了,所以后面涉及到权限内容,都会导入这个头文件。
现在来看一段源码再来熟悉一下这部分内容:
FileUtils.setPermissions(fstr.getFD(), 0640, SYSTEM_UID, PACKAGE_INFO_GID);
这是位于 frameworks/base/services/core/java/com/android/server/pm/Settings.java
的一段代码,功能就是创建 packages.list
文件。从函数名称和参数可以知道,它是给文件添加权限的,通过这段代码可以推测出:它给packages.list文件赋予了0640的权限,权限隶属于system,权限组为package_info。
然后我们进入系统看一看是不是这样:
/data/system # ls -l packages.list -rw-r----- 1 system package_info 13627 1970-01-01 11:27 packages.list
有没有发现原来Android底层权限其实也不是很难理解嘛?
这时,又有一个问题了,创建文件你可以这样设定权限,但系统文件/文件夹的默认权限又是从哪来的?这就要引入另外一个文件了。
fs_config.c
写过Android App的你肯定知道,App的一些数据都放在 /data/data
目录下。正常情况下这个目录是不可以访问的:
/data/data $ ls ls: .: Permission denied
我们看一下这个目录的权限:
/data/data $ ls -ld drwxrwx--x 310 system system 12288 2019-01-11 09:51 .
我们作为 shell 用户,只有一个x权限, 当然访问不了。那如果我要给shell赋予访问权限改怎么改呢?
这就需要了解一下 system/core/libcutils/fs_config.c
文件了。系统目录和文件的用户组以及权限都是在这个文件里定义的:
/* Rules for directories. ** These rules are applied based on "first match", so they ** should start with the most specific path and work their ** way up to the root. */ static const struct fs_path_config android_dirs[] = { { 00770, AID_SYSTEM, AID_CACHE, 0, "cache" }, { 00500, AID_ROOT, AID_ROOT, 0, "config" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral" }, { 00771, AID_ROOT, AID_ROOT, 0, "data/dalvik-cache" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" }, { 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" }, { 00771, AID_SHELL, AID_SHELL, 0, "data/local" }, { 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" }, { 00770, AID_DHCP, AID_DHCP, 0, "data/misc/dhcp" }, { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" }, { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" }, { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" }, { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" }, { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" }, { 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" }, { 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" }, { 00755, AID_ROOT, AID_ROOT, 0, "root" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin" }, { 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor" }, { 00777, AID_ROOT, AID_ROOT, 0, "sdcard" }, { 00755, AID_ROOT, AID_ROOT, 0, 0 }, }; /* Rules for files. ** These rules are applied based on "first match", so they ** should start with the most specific path and work their ** way up to the root. Prefixes ending in * denotes wildcard ** and will allow partial matches. */ static const char conf_dir[] = "/system/etc/fs_config_dirs"; static const char conf_file[] = "/system/etc/fs_config_files"; static const struct fs_path_config android_files[] = { { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" }, { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" }, { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, { 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" }, { 00444, AID_ROOT, AID_ROOT, 0, conf_dir + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, conf_file + 1 }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" }, { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral/*" }, { 00644, AID_APP, AID_APP, 0, "data/data/*" }, { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest/tests.txt" }, { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest64/tests.txt" }, { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest/*" }, { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64/*" }, /* the following two files are INTENTIONALLY set-uid, but they * are NOT included on user builds. */ { 04750, AID_ROOT, AID_SHELL, 0, "system/xbin/su" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" }, /* the following files have enhanced capabilities and ARE included in user builds. */ { 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) | CAP_MASK_LONG(CAP_SETGID), "system/bin/run-as" }, { 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND), "system/bin/inputflinger" }, /* Support FIFO scheduling mode in SurfaceFlinger. */ { 00755, AID_SYSTEM, AID_GRAPHICS, CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" }, { 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" }, { 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" }, { 00750, AID_ROOT, AID_SHELL, 0, "init*" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" }, { 00644, AID_ROOT, AID_ROOT, 0, 0 }, };
感觉也不用多说, android_dirs[]
负责文件夹的权限配置, android_files[]
负责文件的权限配置。
从里面定义找找刚提到的 /data/data
目录
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
你看,就是这么回事儿而已。如果要改成shell权限的话,只需要这样改就可以了:
{ 00771, AID_SYSTEM, AID_SHELL, 0, "data/data" },
当然,如果系统里还要添加其他目录、文件需要指定权限,只需要在这个文件里添加一行即可。
0100 Android App Permission
讲到这里,还遗留一个开头提出的问题:
为什么你在AndroidManifest文件请求storage权限你就可以访问设备文件?
0010里提到过,PackageManagerService在启动后会扫描所有已经安装的App,然后加载和解析他们的Androidmanifest文件,生成 packages.list
和 packages.xml
等文件。解析过程就包括了permission的解析与拦截。
frameworks/base/core/res/AndroidManifest.xml
这个文件中定义了Permission拦截规则,下面列举几个:
<!-- Allows an application to read from external storage. <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly granted this permission.</p> <p>This permission is enforced starting in API level 19. Before API level 19, this permission is not enforced and all apps still have access to read from external storage. You can test your app with the permission enforced by enabling <em>Protect USB storage</em> under Developer options in the Settings app on a device running Android 4.1 or higher.</p> <p>Also starting in API level 19, this permission is <em>not</em> required to read/write files in your application-specific directories returned by {@link android.content.Context#getExternalFilesDir} and {@link android.content.Context#getExternalCacheDir}. <p class="note"><strong>Note:</strong> If <em>both</em> your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> values are set to 3 or lower, the system implicitly grants your app this permission. If you don't need this permission, be sure your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> is 4 or higher. <p>Protection level: dangerous --> <permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:permissionGroup="android.permission-group.STORAGE" android:label="@string/permlab_sdcardRead" android:description="@string/permdesc_sdcardRead" android:protectionLevel="dangerous" /> <!-- Allows applications to access information about Wi-Fi networks. <p>Protection level: normal --> <permission android:name="android.permission.ACCESS_WIFI_STATE" android:description="@string/permdesc_accessWifiState" android:label="@string/permlab_accessWifiState" android:protectionLevel="normal" /> <!-- @SystemApi Allows applications to set the system time. <p>Not for use by third-party applications. --> <permission android:name="android.permission.SET_TIME" android:protectionLevel="signature|privileged" />
这里看一下 protectionLevel
,normal是一般权限,即不需要动态申请,直接在Manifest里注册即可获得的权限。dangerous是敏感权限,需要动态申请告知用户才能获取的权限。signature|privileged一般是系统priv-app才拥有的权限,也就是拥有系统签名的系统应用。
他的拦截规则大概是,如果App申请了signature|privileged权限,但他是普通开发者的三方App,PMS就会将其从申请权限的列表里将该权限删除。这样你的App实际上就没有获得对应的权限了。
那么,文件属性的权限是怎么和Permission联系起来的?不出意外,系统也有一个关联文件的定义 frameworks/base/data/etc/platform.xml
:
<!-- This file is used to define the mappings between lower-level system user and group IDs and the higher-level permission names managed by the platform. Be VERY careful when editing this file! Mistakes made here can open big security holes. --> <permissions> <!-- ================================================================== --> <!-- ================================================================== --> <!-- ================================================================== --> <!-- The following tags are associating low-level group IDs with permission names. By specifying such a mapping, you are saying that any application process granted the given permission will also be running with the given group ID attached to its process, so it can perform any filesystem (read, write, execute) operations allowed for that group. --> <permission name="android.permission.BLUETOOTH_ADMIN" > <group gid="net_bt_admin" /> </permission> <permission name="android.permission.BLUETOOTH" > <group gid="net_bt" /> </permission> <permission name="android.permission.BLUETOOTH_STACK" > <group gid="net_bt_stack" /> <group gid="wakelock" /> </permission> <permission name="android.permission.NET_TUNNELING" > <group gid="vpn" /> </permission> <permission name="android.permission.INTERNET" > <group gid="inet" /> </permission> <permission name="android.permission.READ_LOGS" > <group gid="log" /> </permission> <permission name="android.permission.WRITE_MEDIA_STORAGE" > <group gid="media_rw" /> <group gid="sdcard_rw" /> </permission> <permission name="android.permission.ACCESS_MTP" > <group gid="mtp" /> </permission> <permission name="android.permission.NET_ADMIN" > <group gid="net_admin" /> </permission> <!-- The group that /cache belongs to, linked to the permission set on the applications that can access /cache --> <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" > <group gid="cache" /> </permission> <!-- RW permissions to any system resources owned by group 'diag'. This is for carrier and manufacture diagnostics tools that must be installable from the framework. Be careful. --> <permission name="android.permission.DIAGNOSTIC" > <group gid="input" /> <group gid="diag" /> </permission> <!-- Group that can read detailed network usage statistics --> <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"> <group gid="net_bw_stats" /> </permission> <!-- Group that can modify how network statistics are accounted --> <permission name="android.permission.MODIFY_NETWORK_ACCOUNTING"> <group gid="net_bw_acct" /> </permission> <permission name="android.permission.LOOP_RADIO" > <group gid="loop_radio" /> </permission> <!-- Hotword training apps sometimes need a GID to talk with low-level hardware; give them audio for now until full HAL support is added. --> <permission name="android.permission.MANAGE_VOICE_KEYPHRASES"> <group gid="audio" /> </permission> <permission name="android.permission.ACCESS_FM_RADIO" > <!-- /dev/fm is gid media, not audio --> <group gid="media" /> </permission> <!-- These are permissions that were mapped to gids but we need to keep them here until an upgrade from L to the current version is to be supported. These permissions are built-in and in L were not stored in packages.xml as a result if they are not defined here while parsing packages.xml we would ignore these permissions being granted to apps and not propagate the granted state. From N we are storing the built-in permissions in packages.xml as the saved storage is negligible (one tag with the permission) compared to the fragility as one can remove a built-in permission which no longer needs to be mapped to gids and break grant propagation. --> <permission name="android.permission.READ_EXTERNAL_STORAGE" /> <permission name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- ================================================================== --> <!-- ================================================================== --> <!-- ================================================================== --> <!-- The following tags are assigning high-level permissions to specific user IDs. These are used to allow specific core system users to perform the given operations with the higher-level framework. For example, we give a wide variety of permissions to the shell user since that is the user the adb shell runs under and developers and others should have a fairly open environment in which to interact with the system. --> <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" /> <assign-permission name="android.permission.WAKE_LOCK" uid="media" /> <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" /> <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" /> <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" /> <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="audioserver" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="audioserver" /> <assign-permission name="android.permission.WAKE_LOCK" uid="audioserver" /> <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" /> <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" /> <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" /> <assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" /> <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" /> <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" /> <!-- This is a list of all the libraries available for application code to link against. --> <library name="android.test.runner" file="/system/framework/android.test.runner.jar" /> <library name="javax.obex" file="/system/framework/javax.obex.jar" /> <library name="org.apache.http.legacy" file="/system/framework/org.apache.http.legacy.jar" /> <!-- These are the standard packages that are white-listed to always have internet access while in power save mode, even if they aren't in the foreground. --> <allow-in-power-save package="com.android.providers.downloads" /> <!-- These are the standard packages that are white-listed to always have internet access while in data mode, even if they aren't in the foreground. --> <allow-in-data-usage-save package="com.android.providers.downloads" /> <!-- These are the packages that are white-listed to be able to run as system user --> <system-user-whitelisted-app package="com.android.settings" /> <!-- These are the packages that shouldn't run as system user --> <system-user-blacklisted-app package="com.android.wallpaper.livepicker" /> </permissions>
这个文件定义了所有权限所属的gid。从里面找一下 READ_EXTERNAL_STORAGE
权限,emmmm,什么都没做。这是因为6.0之后存储权限变成动态,需要用户确认才可以获取权限,所以这里不作处理。动态权限这部分代码先不分析了,来看一下老版本的文件:
<permission name="android.permission.READ_EXTERNAL_STORAGE" > <group gid="sdcard_r" /> </permission>
那明确了, READ_EXTERNAL_STORAGE
权限获取的gid是 sdcard_r
,然后查看上面的文件定义,对应 AID_SDCARD_R
,数值是1028。实际上在7.0上得到的是 sdcard_rw
,即1015。
PMS在解析每个Permission时会根据这个文件将Permission关联的gid 加入到一个gid的数组中去,从而硬件设备所对应的设备文件就能被该应用程序访问。这块具体代码流程放到下一篇去分析。想自己跟代码的话可以从该函数看起:
private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds, String[] grantedPermissions) { for (int userId : userIds) { grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions); } // We could have touched GID membership, so flush out packages.list synchronized (mPackages) { mSettings.writePackageListLPr(); } }
回到存储权限,既然系统会根据permission给App添加合适的gid,那么我们在看下内置存储的权限为
/sdcard # ls -ld drwxrwx--x 27 root sdcard_rw 4096 1970-01-01 18:30 .
所以获得 sdcard_rw
权限组的应用才可以访问内置存储。
到此Android权限的底层实现原理简单介绍完了,不过目前这里还留有一个坑,那就是我在测试App里添加STORAGE权限后,安装到设备里,通过查看进程属性,发现:
# ps | grep softard u0_a53 3530 638 969076 30720 binder_thr b07244fc S com.softard.test # cat /proc/3530/status Name: com.softard.test State: S (sleeping) Tgid: 3530 Pid: 3530 PPid: 638 TracerPid: 0 Uid: 10053 10053 10053 10053 Gid: 10053 10053 10053 10053 Ngid: 0 FDSize: 256 Groups: 9997 50053
Groups没有对应的gid,但是程序的确可以访问 /sdcard
然后我又给App系统签名,作为系统应用放进去再看,
# ps | grep soft system 3560 629 985352 49184 SyS_epoll_ abea53b8 S com.softard.test # cat /proc/3560/status Name: com.softard.test State: S (sleeping) Tgid: 3560 Pid: 3560 PPid: 629 TracerPid: 0 Uid: 1000 1000 1000 1000 Gid: 1000 1000 1000 1000 Ngid: 0 FDSize: 256 Groups: 1000 1007 1010 1015 1021 1023 2002 2950 3001 3002 3003 3009 9997 41000
这时候Groups有sdcard_rw权限了。然后从设置里手动关掉存储权限,App无法读取文件,再次检查gid发现这个1015依旧存在。
WTF,7.0的表现跟5.0完全不一样?又是一个坑…后面抽空再填吧…
行吧,这篇概览就这样了,后面就开始从眼花缭乱的源码角度去看这一切的实现。
以上所述就是小编给大家介绍的《[Framework] 全方位理解Android权限之底层实现概览》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
物联网导论(第2版)
刘云浩 / 科学出版社 / 2013-8 / 45.00元
物联网是一个基于互联网、传统电信网等信息承载体,让所有能够被独立寻址的普通物理对象实现互联互通的网络。它具有普通对象设备化、自治终端互联化和普适服务智能化三个重要特征。 《物联网工程专业系列教材:物联网导论(第2版)》从物联网的感知识别层、网络构建层、管理服务层和综合应用层这四层分别进行阐述,深入浅出地为读者拨开萦绕于物联网这个概念的重重迷雾,引领求知者渐渐步入物联网世界,帮助探索者把握第三......一起来看看 《物联网导论(第2版)》 这本书的介绍吧!