1.應(yīng)用權(quán)限機(jī)制
2.Android版本權(quán)限變更
3.應(yīng)用權(quán)限變更適配實(shí)例
4.默認(rèn)授權(quán)
5.AppOps機(jī)制
6.Selinux權(quán)限介紹
1.應(yīng)用權(quán)限機(jī)制
權(quán)限機(jī)制陌知?
Android 是一個(gè)權(quán)限分離的系統(tǒng)。這是利用 Linux 已有的權(quán)限管理機(jī)制礼仗,通過(guò)為每一個(gè) Application 分配不同的 uid 和 gid,從而使得不同的 Application 之間的私有數(shù)據(jù)和訪問(wèn)(native 以及 Java 層通過(guò)這種機(jī)制,都可以)達(dá)到隔離的目的元践。與此同時(shí)韭脊,Android 還在此基礎(chǔ)上進(jìn)行擴(kuò)展,提供了permission機(jī)制单旁,它主要是用來(lái)對(duì) Application 可以執(zhí)行的某些具體操作進(jìn)行權(quán)限細(xì)分和訪問(wèn)控制沪羔,同時(shí)提供了URI permission機(jī)制,用來(lái)提供對(duì)某些特定的數(shù)據(jù)塊進(jìn)行專(zhuān)門(mén)權(quán)限進(jìn)行限制象浑。
Android Permission權(quán)限機(jī)制是對(duì)Android安全機(jī)制的一個(gè)重要補(bǔ)充蔫饰,控制了應(yīng)用對(duì)于系統(tǒng)接口或者對(duì)外接口的訪問(wèn)。
權(quán)限信息:
可以使用adb shell pm list permissions -f 命令詳細(xì)查看 Android 預(yù)定義的權(quán)限詳細(xì)信息(危險(xiǎn)權(quán)限組未在此列表中), 例如下所示:
系統(tǒng)目錄下查看聲明的權(quán)限信息路徑:
frameworks/base/core/res/AndroidManifest.xml
常用權(quán)限命令:
pm list permission-groups
打印所有已知的權(quán)限組
pm list permissions [options] [GROUP]
打印權(quán)限
例如:pm list permissions –g -d (危險(xiǎn)權(quán)限組信息)
其它常用參數(shù):
權(quán)限級(jí)別:
描述權(quán)限中隱含的潛在風(fēng)險(xiǎn)愉豺,并指示系統(tǒng)在確定是否將權(quán)限授予請(qǐng)求它的應(yīng)用程序時(shí)應(yīng)遵循的程序死嗦。Standard permissions具有預(yù)定義的永久保護(hù)級(jí)別。如果您在應(yīng)用程序中創(chuàng)建自定義權(quán)限粒氧,您可以使用下面列出的值之一定義 protectionLevel 屬性。如果沒(méi)有為自定義權(quán)限定義 protectionLevel节腐,則系統(tǒng)分配默認(rèn)值(“normal”)外盯。
每個(gè)保護(hù)級(jí)別由基本權(quán)限類(lèi)型和零個(gè)或多個(gè)標(biāo)志組成(5個(gè)基本類(lèi)型, 22個(gè)附加類(lèi)型)。
使用以下函數(shù)來(lái)提取它們:
int basePermissionType = permissionInfo.getProtection(); --- 基本權(quán)限類(lèi)型
int permissionFlags = permissionInfo.getProtectionFlags(); --- 附加權(quán)限標(biāo)志
基本權(quán)限類(lèi)型:
其它附加權(quán)限標(biāo)志,見(jiàn)如下google官網(wǎng)說(shuō)明:
https://developer.android.com/reference/android/R.attr?hl=zh-cn#protectionLevel
權(quán)限管理:
應(yīng)用安裝時(shí)翼雀,就給權(quán)限賦予了對(duì)應(yīng)的狀態(tài)饱苟,系統(tǒng)是使用PMS來(lái)管理權(quán)限。PMS維護(hù)管理權(quán)限狀態(tài)數(shù)據(jù)狼渊,Android6.0之前箱熬,保存在data/system/packages.xml中;6.0之后增加了data/*../runtime-permissions.xml,數(shù)據(jù)持久化存儲(chǔ)文件狈邑,用于記錄著運(yùn)行時(shí)權(quán)限的授予和拒絕狀態(tài)城须,當(dāng)權(quán)限狀態(tài)變更時(shí),申請(qǐng)的結(jié)果會(huì)動(dòng)態(tài)更新 granted 值和flags狀態(tài)米苹。
權(quán)限查看:
Android12的runtime-permissions.xml被默認(rèn)設(shè)置二進(jìn)制xml格式糕伐,直接打開(kāi)是亂碼。
通過(guò)修改配置將其改為普通的xml格式: adb shell setprop persist.sys.binary_xml false
重啟手機(jī)蘸嘶,再獲取runtime-permissions.xml良瞧,就是普通xml格式。
權(quán)限授予
動(dòng)態(tài)授權(quán):
Android6.0 此版本引入了一種新的權(quán)限模式训唱,用戶可直接在運(yùn)行時(shí)管理應(yīng)用權(quán)限褥蚯。這種模式讓用戶能夠更好地了解和控制權(quán)限,同時(shí)為應(yīng)用開(kāi)發(fā)者精簡(jiǎn)了安裝和自動(dòng)更新過(guò)程况增。用戶可為所安裝的各個(gè)應(yīng)用分別授予或撤銷(xiāo)權(quán)限赞庶。
權(quán)限申請(qǐng):
權(quán)限檢查:
檢查用戶是否已向您的應(yīng)用授予特定權(quán)限,將該權(quán)限傳入checkSelfPermission() 方法。根據(jù)您的應(yīng)用是否具有相應(yīng)權(quán)限尘执,此方法會(huì)返回PackageManager.PERMISSION_GRANTED(0)
或PackageManager.PERMISSION_DENIED(-1)舍哄。
檢查應(yīng)用自身權(quán)限,建議使用checkSelfPermission誊锭;
檢查IPC的調(diào)用進(jìn)程權(quán)限表悬,建議使用checkCallingPermission(或者checkCallingOrSelfPermission);
指定PID、UID檢查權(quán)限丧靡,建議使用checkPermission蟆沫;
訪問(wèn)其它應(yīng)用數(shù)據(jù)庫(kù),建議先檢查訪問(wèn)的URI是否有權(quán)限温治;
底層進(jìn)行權(quán)限檢查:
我們了解了運(yùn)行時(shí)權(quán)限在系統(tǒng)API接口調(diào)用的時(shí)候會(huì)去檢查權(quán)限狀態(tài)饭庞,但有些權(quán)限例如INTERNET、READ_LOGS熬荆、BLUETOOTH等調(diào)用框架層接口的時(shí)候并沒(méi)有去檢查權(quán)限舟山,這類(lèi)權(quán)限是如何檢查授權(quán)的呢?
在底層卤恳,Linux內(nèi)核使用用戶和用戶組來(lái)實(shí)施權(quán)限控制累盗,這套權(quán)限模型是從Linux繼承過(guò)來(lái)的,用于對(duì)文件系統(tǒng)實(shí)體進(jìn)行訪問(wèn)控制突琳,也可以對(duì)其他Android特定資源進(jìn)行控制若债。這一模型通常被稱為Android沙箱。以DalvikVM和Android框架形式存在的Android運(yùn)行時(shí)實(shí)施了第二套權(quán)限模型拆融。這套模型在用戶安裝應(yīng)用時(shí)是向用戶公開(kāi)的蠢琳,定義了應(yīng)用擁有的權(quán)限,從而限制Android應(yīng)用的能力镜豹。事實(shí)上傲须,第二套權(quán)限模型中的某些權(quán)限直接映射到底層操作系統(tǒng)上的特定用戶、用戶組和權(quán)能趟脂。
內(nèi)核和系統(tǒng)守護(hù)進(jìn)程通過(guò)進(jìn)程分配的 GID躏碳、UID和補(bǔ)充 GID來(lái)決定是否要賦予進(jìn)程權(quán)限。
Android的權(quán)限模型是多方面的散怖,有API權(quán)限菇绵、文件系統(tǒng)權(quán)限和IPC權(quán)限。在很多情況下镇眷,這些權(quán)限都會(huì)交織在一起咬最。一些高級(jí)權(quán)限會(huì)后退映射到低級(jí)別的操作系統(tǒng)權(quán)能,這可能包括打開(kāi)套接字欠动、藍(lán)牙設(shè)備和文件系統(tǒng)路徑等永乌。
應(yīng)用在AndroidMainfest.xml申明的權(quán)限如何映射到底層的UID惑申、GID?
內(nèi)置權(quán)限到GID的映射定義在/etc/permissions/platform.xml 中
包管理器在啟動(dòng)時(shí)讀取 platform.xml翅雏,并維護(hù)「permission-GID」對(duì)應(yīng)的列表圈驼。當(dāng)它給安裝中的包授權(quán)時(shí),會(huì)把權(quán)限對(duì)應(yīng)的 GID 加入到該應(yīng)用進(jìn)程的補(bǔ)充 GID 中望几。
權(quán)限對(duì)應(yīng)的 GID 加入到該應(yīng)用進(jìn)程的補(bǔ)充 GID 中绩脆,可以通過(guò)adb shell--cd proc--cd PID--cat status查看:
system/core/libcutils/include/private/android_filesystem_config.h
static const struct android_id_info android_ids[] = {
{ "camera", AID_CAMERA, },
{ "sdcard_r", AID_SDCARD_R, },
{ "sdcard_rw", AID_SDCARD_RW, },
{ "inet", AID_INET},
···
};
注:AndroidN及之前android_ids放在android_filesystem_config.h中之后版本遷移到pwd/grp functionality.
Android定義了從名稱到獨(dú)特標(biāo)識(shí)符Android ID(AID)的映射表。初始的AID映射表包含了一些與特權(quán)用戶及系統(tǒng)關(guān)鍵用戶(如system用戶/用戶組)對(duì)應(yīng)的靜態(tài)保留條目橄抹。Android還保留了一段AID范圍靴迫,用于提供原生應(yīng)用的UID。Android 4.1之后的版本為多用戶資料檔案和隔離進(jìn)程用戶增加了額外的AID范圍段(如Chrome沙箱)楼誓。
除了AID玉锌,Android還使用了輔助用戶組機(jī)制,以允許進(jìn)程訪問(wèn)共享或受保護(hù)的資源疟羹。例如主守,sdcard_rw用戶組中的成員允許進(jìn)程讀寫(xiě)/sdcard目錄,因?yàn)樗募虞d項(xiàng)規(guī)定了哪些用戶組可以讀寫(xiě)該目錄榄融。這與許多Linux發(fā)行版中對(duì)輔助用戶組機(jī)制的使用是類(lèi)似的丸逸。
注意 盡管所有的AID條目都映射到一個(gè)UID和GID,但是UID在描述系統(tǒng)上的一個(gè)用戶時(shí)并不是必需的剃袍。例如,AID_SDCARD_RW映射到sdcard_rw捎谨,但是它僅僅用作一個(gè)輔助用戶組民效,而不是系統(tǒng)上的UID。
在應(yīng)用執(zhí)行時(shí)涛救,它們的UID畏邢、GID和輔助用戶組都會(huì)被分配給新創(chuàng)建的進(jìn)程。在一個(gè)獨(dú)特UID和GID環(huán)境下運(yùn)行检吆,使得操作系統(tǒng)可以在內(nèi)核中實(shí)施底層的限制措施舒萎,也讓運(yùn)行環(huán)境能夠控制應(yīng)用之間的交互。這就是Android沙箱的關(guān)鍵所在蹭沛。
在應(yīng)用包條目中定義的權(quán)限后面會(huì)通過(guò)兩種方式實(shí)施檢查:一種檢查在調(diào)用給定方法時(shí)進(jìn)行臂寝,由運(yùn)行環(huán)境實(shí)施;另一種檢查在操作系統(tǒng)底層進(jìn)行摊灭,由庫(kù)或內(nèi)核實(shí)施咆贬。
權(quán)限對(duì)應(yīng)的 GID 何時(shí)被加入到應(yīng)用進(jìn)程的補(bǔ)充 GID 中?
每個(gè)應(yīng)用都會(huì)運(yùn)行在自己的 Dalvik 虛擬機(jī)進(jìn)程中帚呼,但是為了提高啟動(dòng)效率掏缎,Android 不會(huì)為每個(gè)應(yīng)用都新建一個(gè) Dalvik 進(jìn)程皱蹦,而是采用 fork 的形式。每個(gè)進(jìn)程都 fork form zygote 進(jìn)程眷蜈。
因?yàn)?zygote 進(jìn)程已經(jīng)預(yù)加載了大部分核心和 Java 應(yīng)用框架庫(kù)沪哺,fork 的子進(jìn)程會(huì)繼承 zygote 的進(jìn)程空間,也就是說(shuō)酌儒,fork 的子進(jìn)程辜妓,可以共享這些預(yù)加載的副本(記住,是副本今豆,不是直接共享嫌拣。fork 時(shí),會(huì) copy-on-write 預(yù)加載的內(nèi)容)呆躲,減少了重新加載核心庫(kù)的時(shí)間异逐。
當(dāng) zygote 收到啟動(dòng)新進(jìn)程的請(qǐng)求時(shí),它會(huì) fork 自身出一個(gè)子進(jìn)程插掂,并對(duì)該子進(jìn)程做特殊化處理灰瞻。其源代碼位于 framework/base/core/jni/com_android_internal_os_Zygote.cpp 中。SpecializeCommon() 的主要代碼如下:
這里設(shè)置進(jìn)程的組 ID 和用戶 ID辅甥,通過(guò) fork 創(chuàng)建的子進(jìn)程調(diào)用 setgroups Intarray 設(shè)置該進(jìn)程所屬的組酝润,這樣應(yīng)用程序就擁有了該組的權(quán)限,并且可以通過(guò) setgid() 及 setuid() 確定應(yīng)用程序的 GID 及 UID 值璃弄。
每個(gè)應(yīng)用進(jìn)程都分配好自己的 GID要销、UID和補(bǔ)充 GID,系統(tǒng)內(nèi)核和守護(hù)進(jìn)程就可以用這些標(biāo)識(shí)來(lái)決定夏块,是否要賦予進(jìn)程權(quán)限疏咐。
應(yīng)用權(quán)限內(nèi)容:
2.Android版本權(quán)限變更
Android從1.0開(kāi)始其根基Linux繼承了已經(jīng)深入人心的類(lèi)Unix進(jìn)程隔離機(jī)制與最小權(quán)限原則。引入了Android沙箱及擴(kuò)展了Android使用的權(quán)限模型脐供,包括Android對(duì)Unix系統(tǒng)UID/GID映射關(guān)系的特殊實(shí)現(xiàn)AID浑塞,以及在整個(gè)系統(tǒng)中實(shí)施的限制和權(quán)能。
目前到Android13.0各版本中有關(guān)權(quán)限變更的重要調(diào)整如下:
版本 | 重要變更 |
---|---|
1.6 | 新增WRITE_EXTERNAL_STORAGE權(quán)限政己,允許程序?qū)懭胪獠看鎯?chǔ) |
2.2 | android.permission.KILL_BACKGROUND_PROCESSES— 允許應(yīng)用程序調(diào)用killBackgroundProcesses(String) |
2.3 | image.png
|
3.0 | image.png
|
4.0 | image.png
|
4.0.3 | image.png
|
4.1 | image.png
|
4.2 | 精細(xì)化區(qū)分ACCESS_COARSE_LOCATION權(quán)限和ACCESS_FINE_LOCATION,不請(qǐng)求FINE_LOCATION獲取的位置結(jié)果可能不太準(zhǔn)確 |
4.3 | BIND_NOTIFICATION_LISTENER_SERVICE:需要使用新的 NotificationListenerService API |
4.4 | 從 Android 4.4 開(kāi)始酌壕,當(dāng)您僅訪問(wèn)您的應(yīng)用特定外部存儲(chǔ)區(qū)域時(shí),此平臺(tái)不再要求您的應(yīng)用獲取 WRITE_EXTERNAL_STORAGE 或 READ_EXTERNAL_STORAGE歇由。不過(guò)卵牍,如果您要訪問(wèn) getExternalStoragePublicDirectory() 提供的外部存儲(chǔ)空間的可共享區(qū)域,則需要這些權(quán)限 |
5.0 | image.png
|
6.0 | 此版本引入了一種新的權(quán)限模式沦泌,如今辽慕,用戶可直接在運(yùn)行時(shí)管理應(yīng)用權(quán)限。這種模式讓用戶能夠更好地了解和控制權(quán)限赦肃,同時(shí)為應(yīng)用開(kāi)發(fā)者精簡(jiǎn)了安裝和自動(dòng)更新過(guò)程溅蛉。用戶可為所安裝的各個(gè)應(yīng)用分別授予或撤銷(xiāo)權(quán)限公浪。對(duì)于以 Android 6.0(API 級(jí)別 23)或更高版本為目標(biāo)平臺(tái)的應(yīng)用,請(qǐng)務(wù)必在運(yùn)行時(shí)檢查和請(qǐng)求權(quán)限船侧。要確定您的應(yīng)用是否已被授予權(quán)限欠气,請(qǐng)調(diào)用新增的 checkSelfPermission() 方法。要請(qǐng)求權(quán)限镜撩,請(qǐng)調(diào)用新增的 requestPermissions() 方法预柒。即使您的應(yīng)用并不以 Android 6.0(API 級(jí)別 23)為目標(biāo)平臺(tái),您也應(yīng)該在新權(quán)限模式下測(cè)試您的應(yīng)用袁梗。 |
7.0 | 文件系統(tǒng)權(quán)限更改:為了提高隱私文件的安全性宜鸯,Android 7.0 或更高版本的應(yīng)用程序的隱私目錄已限制訪問(wèn)。 |
8.0 | 在 Android 8.0 之前遮怜,如果應(yīng)用在運(yùn)行時(shí)請(qǐng)求權(quán)限并且被授予該權(quán)限淋袖,系統(tǒng)會(huì)錯(cuò)誤地將屬于同一權(quán)限組并且在清單中注冊(cè)的其他權(quán)限也一起授予應(yīng)用。對(duì)于針對(duì) Android 8.0 的應(yīng)用锯梁,此行為已被糾正即碗。系統(tǒng)只會(huì)授予應(yīng)用明確請(qǐng)求的權(quán)限。然而陌凳,一旦用戶為應(yīng)用授予某個(gè)權(quán)限剥懒,則所有后續(xù)對(duì)該權(quán)限組中權(quán)限的請(qǐng)求都將被自動(dòng)批準(zhǔn)。 |
9.0 | 為了增強(qiáng)用戶隱私合敦,Android 9 引入了若干行為變更初橘,如限制后臺(tái)應(yīng)用訪問(wèn)設(shè)備傳感器、限制通過(guò) Wi-Fi 掃描檢索到的信息充岛,以及與通話保檐、手機(jī)狀態(tài)和 Wi-Fi 掃描相關(guān)的新權(quán)限規(guī)則和權(quán)限組。無(wú)論采用哪一種目標(biāo) SDK 版本裸准,這些變更都會(huì)影響運(yùn)行于 Android 9 上的所有應(yīng)用。 |
10 | image.png
|
11 | Android 11 對(duì)應(yīng)用授予權(quán)限的方式進(jìn)行了多項(xiàng)更改赔硫。這些更改旨在通過(guò)更加有意地授予權(quán)限來(lái)保護(hù)用戶炒俱。強(qiáng)制執(zhí)行分區(qū)存儲(chǔ)、單次授權(quán)爪膊、自動(dòng)重置權(quán)限权悟、后臺(tái)位置信息訪問(wèn)權(quán)限、軟件包可見(jiàn)性推盛、前臺(tái)服務(wù)等的調(diào)整峦阁。 |
12 | 在搭載 Android 12 或更高版本的設(shè)備上,用戶可以要求您的應(yīng)用只能訪問(wèn)大致位置信息耘成。 |
13 | 存儲(chǔ)權(quán)限變更榔昔、新增通知權(quán)限驹闰、后臺(tái)使用身體傳感器權(quán)限。 |
總結(jié):從Android版本迭代有關(guān)權(quán)限變更來(lái)看撒会,Android6.0之前基本是針對(duì)權(quán)限進(jìn)行擴(kuò)展調(diào)整嘹朗,Android6.0之后加強(qiáng)了用戶對(duì)系統(tǒng)的安全管控,Android10.0之后權(quán)限管控更加嚴(yán)格诵肛,進(jìn)一步提升用戶安全性屹培。
Google各版本變更信息:https://developer.android.com/about/versions
3.應(yīng)用權(quán)限變更適配實(shí)例
實(shí)例一:后臺(tái)定位權(quán)限適配
為了讓用戶更好地控制應(yīng)用對(duì)位置信息的訪問(wèn)權(quán)限,Android 10 引入了 ACCESS_BACKGROUND_LOCATION 權(quán)限怔檩。與 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 權(quán)限不同褪秀,ACCESS_BACKGROUND_LOCATION 權(quán)限僅會(huì)影響應(yīng)用在后臺(tái)運(yùn)行時(shí)對(duì)位置信息的訪問(wèn)權(quán)限。除非符合以下條件之一薛训,否則應(yīng)用將被視為在后臺(tái)訪問(wèn)位置信息:
.屬于該應(yīng)用的 Activity 可見(jiàn)媒吗。
.該應(yīng)用運(yùn)行的某個(gè)前臺(tái)設(shè)備已聲明前臺(tái)服務(wù)類(lèi)型為 location。
.要聲明您的應(yīng)用中的某個(gè)服務(wù)的前臺(tái)服務(wù)類(lèi)型许蓖,請(qǐng)將應(yīng)用的 targetSdkVersion 或 compileSdkVersion 設(shè)置為 29 或更高版本蝴猪。
AndroidQ(10) 獲取后臺(tái)定位權(quán)限:
1.Android 10 之前只有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION;
2.Android 10 新增加了后臺(tái)定位權(quán)限:ACCESS_BACKGROUND_LOCATION膊爪,該權(quán)限對(duì)應(yīng)始終允許自阱;老的權(quán)限: ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION代表僅前臺(tái)使用允許;
3.應(yīng)用的targetSdkVersion<Q米酬,谷歌提供了兼容性方案沛豌,只要應(yīng)用申請(qǐng)了老的位置權(quán)限ACCESS_FINE_LOCATION或者ACCESS_COARSE_LOCATION,會(huì)默認(rèn)請(qǐng)求ACCESS_BACKGROUND_LOCATION權(quán)限赃额,動(dòng)態(tài)彈框根據(jù)用戶選擇授權(quán)加派。
4.應(yīng)用的targetSdkVersion>=Q,如果應(yīng)用必須要始終定位跳芳,可以只申請(qǐng)ACCESS_BACKGROUND_LOCATION即可芍锦;如果應(yīng)用只需要申請(qǐng)前臺(tái)定位,則只需要申請(qǐng)老的定位權(quán)限即可飞盆。
5.如果用戶選擇僅前臺(tái)使用允許娄琉,應(yīng)用的頁(yè)面退后臺(tái),通過(guò)啟動(dòng)前臺(tái)服務(wù)讓?xiě)?yīng)用處于前臺(tái)狀態(tài)吓歇,必須把前臺(tái)服務(wù)標(biāo)為:foregroundServiceType=“l(fā)ocation”孽水,才能獲取位置信息。
<manifest> ...
<service android:name="com.amap.api.location.APSService"
android:foregroundServiceType="location" />
</manifest>
Android R(11) 獲取后臺(tái)位置權(quán)限:
當(dāng)應(yīng)用申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限時(shí),讓用戶授予權(quán)限的彈窗中,將不再提供“始終允許”的選項(xiàng)堡赔,這個(gè)選項(xiàng)只存在于設(shè)置中的應(yīng)用權(quán)限授予頁(yè)面魁袜,并且后臺(tái)位置權(quán)限的申請(qǐng)需要應(yīng)用已經(jīng)擁有前臺(tái)位置權(quán)限析恢。
適配建議:
若您的應(yīng)用確定需要獲得后臺(tái)位置信息訪問(wèn)的權(quán)限咙轩,現(xiàn)在則需要分為兩個(gè)步驟眶明,因?yàn)橐褵o(wú)法在沒(méi)有前臺(tái)位置信息訪問(wèn)權(quán)限的時(shí)候直接申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限惩坑。
先申請(qǐng)前臺(tái)位置信息訪問(wèn)權(quán)限簇搅;
再申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限完域,引導(dǎo)用戶到設(shè)置中進(jìn)行授予。
Android S(12) 獲取后臺(tái)位置權(quán)限:
在搭載 Android 12 或更高版本的設(shè)備上瘩将,用戶可以要求您的應(yīng)用只能訪問(wèn)大致位置信息吟税。
確切位置:可訪問(wèn)確切位置信息(10英尺到160英尺)。
大致位置:只能訪問(wèn)大致位置信息(1 英里)姿现。
注意:如果用戶從權(quán)限對(duì)話框或在系統(tǒng)設(shè)置中將應(yīng)用的位置信息使用權(quán)從確切位置降級(jí)到大致位置肠仪,系統(tǒng)會(huì)重啟應(yīng)用的進(jìn)程。
實(shí)例二:存儲(chǔ)權(quán)限適配
為了讓用戶更好地控制自己的文件并減少混亂备典,Android 10 針對(duì)應(yīng)用推出了一種新的存儲(chǔ)范例异旧,稱為分區(qū)存儲(chǔ)。分區(qū)存儲(chǔ)改變了應(yīng)用在設(shè)備的外部存儲(chǔ)設(shè)備中存儲(chǔ)和訪問(wèn)文件的方式提佣。
AndroidQ(10) 獲取外部存儲(chǔ):
1.應(yīng)用targetSdkVersion<Q(29) 按照請(qǐng)求應(yīng)用權(quán)限中所述的最佳做法吮蛹,請(qǐng)求 READ\WRITE_EXTERNAL_STORAGE 權(quán)限。
或者使用 MediaStore API 修改或刪除媒體文件拌屏。
2.如果您的應(yīng)用以 Android 10(API 級(jí)別 29)為目標(biāo)平臺(tái)targetSdkVersion=Q(29)潮针,請(qǐng)停用分區(qū)存儲(chǔ),繼續(xù)使用適用于 Android 9 及更低版本的方法來(lái)執(zhí)行此操作。
如果您以 Android 10 為目標(biāo)平臺(tái)倚喂,則需要在應(yīng)用的清單文件中將 requestLegacyExternalStorage 的值設(shè)置為 true:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10\. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
AndroidR(11) 及更高版本獲取外部存儲(chǔ):
1.使用 MediaStore.createWriteRequest() 或 MediaStore.createTrashRequest() 為應(yīng)用的寫(xiě)入或刪除請(qǐng)求創(chuàng)建待定 intent每篷,然后通過(guò)調(diào)用該 intent 提示用戶授予修改一組文件的權(quán)限。
注意:在 Android 11 或更高版本(無(wú)論目標(biāo) SDK 級(jí)別是什么)中端圈,其他應(yīng)用無(wú)法訪問(wèn)外部存儲(chǔ)設(shè)備上的應(yīng)用專(zhuān)用目錄中存儲(chǔ)的文件焦读。
Android 存儲(chǔ)用例和最佳做法 :
https://developer.android.com/training/data-storage/use-cases
實(shí)例三:獲取應(yīng)用列表
Android 11 更改了應(yīng)用查詢用戶已在設(shè)備上安裝的其他應(yīng)用以及與之交互的方式。使用 <queries> 元素舱权,應(yīng)用可以定義一組自身可訪問(wèn)的其他軟件包矗晃。通過(guò)告知系統(tǒng)應(yīng)向您的應(yīng)用顯示哪些其他軟件包,此元素有助于鼓勵(lì)最小權(quán)限原則宴倍。
受影響的接口:
.PackageManager.getInstalledApplications
.PackageManager.getInstalledPackages
只返回系統(tǒng)可見(jiàn)以及與應(yīng)用交互授權(quán)的應(yīng)用列表张症。
以 Android 11(API 級(jí)別 30)或更高版本為目標(biāo)平臺(tái),部分類(lèi)型的應(yīng)用也始終對(duì)您的應(yīng)用可見(jiàn):詳見(jiàn)以下文檔
https://developer.android.com/training/basics/intents/package-visibility?hl=zh-cn#automatic
查詢所有應(yīng)用及與之交互:
在極少數(shù)情況下啊楚,您的應(yīng)用可能需要查詢?cè)O(shè)備上的所有已安裝應(yīng)用或與之交互吠冤,不管這些應(yīng)用包含哪些組件浑彰。為了允許您的應(yīng)用看到其他所有已安裝應(yīng)用恭理,系統(tǒng)會(huì)提供 QUERY_ALL_PACKAGES 權(quán)限。
.如果應(yīng)用的target< 30郭变,是兼容之前的邏輯颜价;
.如果應(yīng)用的target>=30涯保,必須要申請(qǐng)android.permission.QUERY_ALL_PACKAGES這個(gè)權(quán)限, 才能查詢所有應(yīng)用。
注意:如果您的應(yīng)用以 Android 10(API 級(jí)別 29)或更低版本為目標(biāo)平臺(tái)周伦,那么全部應(yīng)用均會(huì)自動(dòng)對(duì)您的應(yīng)用可見(jiàn)夕春。
應(yīng)用安裝卸載廣播,仍然受軟件包可見(jiàn)性影響:
如果監(jiān)聽(tīng)安裝/卸載的應(yīng)用不符合可見(jiàn)性原則专挪,或者未聲明QUERY_ALL_PACKAGES權(quán)限, onReceive將不會(huì)回調(diào)及志。
4.默認(rèn)授權(quán)
手機(jī)第一次開(kāi)機(jī)或者fota升級(jí)后第一次開(kāi)機(jī)進(jìn)行的默認(rèn)授權(quán):
系統(tǒng)預(yù)置的默認(rèn)授權(quán)機(jī)制,在Pms systemReady里面會(huì)根據(jù)Build.FINGERPRINT來(lái)判斷是不是第一次開(kāi)機(jī)寨腔,來(lái)做默認(rèn)授權(quán)速侈。
- share systemuid默認(rèn)授權(quán)權(quán)限(一般是在Manifest中配置類(lèi)似的
android:sharedUserId=”android.uid.system”) - 系統(tǒng)特權(quán)應(yīng)用并且是persistent進(jìn)行默認(rèn)授權(quán)危險(xiǎn)權(quán)限;
- 系統(tǒng)默認(rèn)應(yīng)用進(jìn)行局部權(quán)限授權(quán)(例如:開(kāi)機(jī)向?qū)嚷⑾鄼C(jī)倚搬、下載的Provider等)
原生機(jī)制第一次開(kāi)機(jī)默認(rèn)授權(quán)類(lèi):
./frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
public void grantDefaultPermissions(int userId) {
grantPermissionsToSysComponentsAndPrivApps(userId); ---授權(quán)系統(tǒng)&特權(quán)應(yīng)用
grantDefaultSystemHandlerPermissions(userId); --- 授權(quán)默認(rèn)應(yīng)用
}
新應(yīng)用第一次安裝授權(quán):
應(yīng)用安裝會(huì)走Pms,應(yīng)用安裝的過(guò)程中Pms會(huì)根據(jù)應(yīng)用聲明權(quán)限的level(Normal乾蛤、Dangerous每界、Signature),來(lái)決定是否允許應(yīng)用使用該權(quán)限家卖。
Normal:只要應(yīng)用申請(qǐng)眨层,就允許應(yīng)用使用該權(quán)限;
Signature:判斷該應(yīng)用簽名是否和平臺(tái)簽名一樣篡九,如果一樣就允許否則不允許使用該權(quán)限谐岁;
Dangerous:不給應(yīng)用授予該權(quán)限,需要應(yīng)用在用的時(shí)候動(dòng)態(tài)申請(qǐng)?jiān)摍?quán)限榛臼。
5.AppOps機(jī)制
AppOps全稱是Application Operations伊佃,類(lèi)似我們平時(shí)常說(shuō)的應(yīng)用程序的操作(權(quán)限)管理。Google從4.3開(kāi)始推出Appops, 在Settings里面未開(kāi)放Appops的入口沛善,但這套方案卻一直在后臺(tái)默默的運(yùn)行著航揉。
涉及的類(lèi):
android.app.AppOpsManager
com.android.server.AppOpsService
配置文件:appops.xml
appops.xml位于/data/system/目錄下,存儲(chǔ)各個(gè)app的權(quán)限設(shè)置和操作信息金刁。
Android提供了命令行的方式來(lái)更改某個(gè)應(yīng)用的某個(gè)權(quán)限帅涂,進(jìn)入adb shell可以查看相應(yīng)用法:
AppOps權(quán)限檢查流程:
6. Selinux權(quán)限介紹
為什么增加Selinux?
進(jìn)程理論上所擁有的權(quán)限與執(zhí)行它的用戶的權(quán)限相同尤蛮。比如媳友,以root用戶啟動(dòng)FileManager,那么FileManager就有root用戶的權(quán)限产捞,在Linux系統(tǒng)上能干任何事情醇锚。也就是像4.4以前的版本,只要我們對(duì)結(jié)點(diǎn)給予足夠的權(quán)限,就可以隨意的進(jìn)行任意的操作焊唬。
Linux DAC有明顯的不足恋昼,其中一個(gè)重要點(diǎn)就是,Root權(quán)限幾乎可以做任意事情赶促,一旦入侵者拿到root權(quán)限液肌,即已經(jīng)完全掌控了系統(tǒng)。另外每一個(gè)進(jìn)程默認(rèn)都拿到對(duì)應(yīng)這個(gè)用戶的所有權(quán)限鸥滨,可以改動(dòng)/刪除這個(gè)用戶的所有文件資源嗦哆,明顯這個(gè)難以防止惡意軟件。所以在DAC之外設(shè)計(jì)了一個(gè)新的安全模型婿滓,叫MAC(Mandatory Access control)吝秕,強(qiáng)制性訪問(wèn)控制,即系統(tǒng)針對(duì)每一項(xiàng)訪問(wèn)都進(jìn)行嚴(yán)格的限制空幻,具體的限制策略由開(kāi)發(fā)者給出烁峭。MAC:即任何進(jìn)程想在SELinux系統(tǒng)中干任何事情,都必須先在安全策略配置文件中賦予權(quán)限秕铛。凡是沒(méi)有出現(xiàn)在安全策略配置文件中的權(quán)限约郁,進(jìn)程就沒(méi)有該權(quán)限。
打開(kāi)和關(guān)閉selinux功能:
出現(xiàn)了selinux相關(guān)的權(quán)限拒絕但两,則在kernel log 或者android log中都有對(duì)應(yīng)的”avc: denied”鬓梅,當(dāng)然也可能和selinux的模式有關(guān)系,我們需要首先要確認(rèn)當(dāng)時(shí)SELinux 的模式, 是enforcing mode 還是 permissve mode谨湘。
如果問(wèn)題容易復(fù)現(xiàn)绽快,我們可以先將SELinux 模式調(diào)整到Permissive mode,然后再測(cè)試確認(rèn)是否與SELinux 約束相關(guān)紧阔。
可以通過(guò)以下命令設(shè)置:
adb shell setenforce 0
setenforce 0 設(shè)置SELinux 成為permissive模式 臨時(shí)關(guān)閉selinux
setenforce 1 臨時(shí)打開(kāi)selinux
如何配置selinux權(quán)限:
例如報(bào)如下錯(cuò)誤:
TcmReceiver: type=1400 audit(0.0:4214): avc: denied { write } for name="tcmd" dev="tmpfs" ino=1301 scontext=u:r:remote_prov_app:s0:c162,c256,c512,c768 tcontext=u:object_r:vendor_dpmtcm_socket:s0 tclass=sock_file permissive=0 app=com.android.remoteprovisioner
具體參數(shù)表示:
權(quán)限: avc: denied { write } 表示缺少write權(quán)限
哪個(gè)te文件缺少權(quán)限: scontext=u:r:remote_prov_app:s0:c162,c256,c512,c768 ---- remote_prov_app缺少權(quán)限
哪個(gè)文件缺少權(quán)限: tcontext=u:object_r:vendor_dpmtcm_socket:s0 ---- remote_prov_app缺少對(duì)vendor_dpmtcm_socket的權(quán)限配置
文件類(lèi)型: tclass=sock_file 權(quán)限文件類(lèi)型
表達(dá)含義:remote_prov_app文件需要新增類(lèi)型為sock_file的vendor_dpmtcm_socket的write權(quán)限坊罢。
如何修改:配置te文件,添加 tclass=sock_file,編譯selinux_policy擅耽,把system/ect下面的selinux文件夾活孩,push到手機(jī)syste/ect進(jìn)行覆蓋。然后重啟驗(yàn)證修改是否生效乖仇。
注:不要修改neverallow憾儒,會(huì)導(dǎo)致CTS測(cè)試失敗。如果修改了file_contexts,替換selinux是不生效的乃沙。因?yàn)?標(biāo)文件的context已經(jīng)?成了起趾,替換selinux并不會(huì)重新給?標(biāo)文件設(shè)置context。這時(shí)可以通過(guò)chcon命令?動(dòng)修改context警儒。
參考文章:
- 「Android 安全架構(gòu)」你真的了解權(quán)限機(jī)制嗎训裆?http://www.reibang.com/p/a17c8bed79d9
- 「 Android 沙箱機(jī)制」 https://blog.csdn.net/fei20121106/article/details/84023953
- 「 Android 安全架構(gòu)及權(quán)限控制機(jī)制剖析」http://www.uml.org.cn/mobiledev/201303281.asp