Privileged Permission開機授權時序圖 SourceCode android-10.0.0_r36 2020 年 10 月 17 日 筆記 Android Privileged Permission開機授權時序圖 | SourceCode:android-10.0.0_r36 | Author:秋城 | v1.1SystemServerSystemServerSystemServerInitThreadPoolSystemServerInitThreadPoolSystemConfigSystemConfigPackageManagerServicePackageManagerServicePermissionManagerServicePermissionManagerServicePermissionSettingsPermissionSettingsParallelPackageParserParallelPackageParserPackageParserPackageParserPackageParser.PackagePackageParser.PackagePermissionManagerService.PermissionManagerServiceInternalImplPermissionManagerService.PermissionManagerServiceInternalImpl1main()2run()3startBootstrapServices()↓Step 讀取配置好的特權白名單4get.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG)5getInstance()6new SystemConfig()讀取配置好的特權白名單到記憶體。涉及7個路徑下/xxx/etc/permissions/*xml文件過濾標籤「privapp-permissions」中「許可」:”permission”與「拒絕」:”deny-permission”路徑定義在Environment.javaENV_ANDROID_ROOT, “/system“ENV_OEM_ROOT, “/oem“ENV_ODM_ROOT, “/odm“Environment.getOdmDirectory(), “etc”, “permissions”,skuDirENV_VENDOR_ROOT, “/vendor“ENV_PRODUCT_ROOT, “/product“ENV_PRODUCT_SERVICES_ROOT,”/product_services“7readPermissions()8readPermissionsFromXml()9readPermission()10readPrivAppPermissions(parser,mPrivAppPermissions,mPrivAppDenyPermissions)private void readPrivAppPermissions(XmlPullParser parser,ArrayMap<String, ArraySet<String>>grantMap,ArrayMap<String, ArraySet<String>>denyMap)while (XmlUtils.nextElementWithin(parser, depth)) {String name = parser.getName();if (“permission”.equals(name)) {String permName = parser.getAttributeValue(null, “name”);permissions.add(permName);} else if (“deny-permission”.equals(name)) {String permName = parser.getAttributeValue(null, “name”);denyPermissions.add(permName);}}grantMap.put(packageName,permissions);denyMap.put(packageName,denyPermissions);↓Step 讀取”privileged”許可權定義11main(mSystemContext, installer,<factoryTest>, mOnlyCore)12new PackageManagerService(context, installer,factoryTest, onlyCore)13create(context,mPackages /*externalLock*/)14new PermissionManagerService()15new PermissionSettings()16mSettingsAll of the permissions known to the system.系統中所有通過<permission>標籤聲明的許可權(FrameWork及App定義的許可權都在這個map中存儲)public class PermissionSettings {final ArrayMap<String, BasePermission>mPermissions=new ArrayMap<String, BasePermission>();}17scanDirTracedLI(frameworkDir,…)掃描/system/framework/目錄的apk,其中我們的privileged許可權定義在system/framework/framework-res.apk中程式碼是frameworks/base/core/res/AndroidManifest.xml文件的<permission>標籤其中protectionLevel=”signature|privileged”是特權標誌,共216個$ ag android:protectionLevel=signature|privileged frameworks/base/core/res/AndroidManifest.xml |wc -l216例如重啟許可權:3714 <!– Required to be able to reboot the device.3715 <p>Not for use by third-party applications. –>3716 <permission android:name=”android.permission.REBOOT”3717 android:protectionLevel=”signature|privileged” />18scanDirLI()19submit()20parsePackage()21parsePackage(scanFile, parseFlags, true /* useCaches */)此處關註解析單個apk,parseMonolithicPackage()方法其實parseClusterPackage內部也是遍歷來調parseMonolithicPackagepublic Package parsePackage(File packageFile, int flags, boolean useCaches){Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;if (packageFile.isDirectory()) {parsed = parseClusterPackage(packageFile, flags);} else {parsed = parseMonolithicPackage(packageFile, flags);}return parsed;}22parseMonolithicPackage()23parseBaseApk(,,)24parseBaseApk(,,,)25new Package(pkgName)26pkg27parseBaseApkCommon(pkg,,,,,)讀取整個AndroidManifest.xml,此處關注<permission>:許可權定義標籤} else if (tagName.equals(TAG_PERMISSION)) {if (!parsePermission(pkg, res, parser, outError)) {return null;}} else if …28parsePermission(pkg,,,)private boolean parsePermission(Package owner, Resources res,XmlResourceParser parser, String[] outError)TypedArray sa = res.obtainAttributes(parser,com.android.internal.R.styleable.AndroidManifestPermission);Permission perm = newPermission(owner, backgroundPermission);perm.info.protectionLevel= sa.getInt(com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,PermissionInfo.PROTECTION_NORMAL);owner.permissions.add(perm);frameworks/base/core/java/android/content/pm/PackageParser.javapublic final static classPermissionextends Component<IntentInfo>implements Parcelable {public finalPermissionInfoinfo;}frameworks/base/core/java/android/content/pm/PermissionInfo.javapublic classPermissionInfoextends PackageItemInfoimplements Parcelable {public intprotectionLevel;}frameworks/base/core/java/android/content/pm/PackageParser.javaPackageParser$Package代表記憶體中安裝後apk每個apk聲明的許可權都存放在其permissions這個ArrayList中public final static class Package implements Parcelable {public final ArrayList<Permission>permissions= new ArrayList<Permission>(0);}多執行緒並發掃描安裝apk。並發解析工具類:ParallelPackageParser.java入隊出隊方法:submit/take// Submit files for parsing in parallelint fileCount = 0;for (File file : files) {…parallelPackageParser.submit(file, parseFlags);fileCount++;}// Process results one by onefor (; fileCount > 0; fileCount–) {ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();…}29scanPackageChildLI(,,,,)30addForInitLI(,,,,)31commitReconciledScanResultLocked()32commitPackageSettings(,,,,,)33addAllPermissions(,)34addAllPermissions(,)private void addAllPermissions(PackageParser.Package pkg, boolean chatty) {final int N = pkg.permissions.size();for (int i=0; i<N; i++) {PackageParser.Permission p = pkg.permissions.get(i);…final BasePermission bp = BasePermission.createOrUpdate(mSettings.getPermissionLocked(p.info.name),p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);mSettings.putPermissionLocked(p.info.name, bp);…35putPermissionLocked(,)@GuardedBy(“mLock”)void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {mPermissions.put(permName, permission);}↓Step 讀取應用所申請許可權(apk安裝)36scanDirTracedLI(xxxDir)掃描如下11個路徑下的系統apk。Environment.getRootDirectory():”priv-app”&&”app”Environment.getVendorDirectory(): “priv-app”&&”app”Environment.getOdmDirectory():”priv-app”&&”app”Environment.getOemDirectory():”app”Environment.getProductDirectory():”priv-app”&&”app”Environment.getProductServicesDirectory():”priv-app”&&”app”通過存放路徑來分配FLAG是方式之一priv-app/授予“SYSTEM|PRIVILEGED”,app/授予“SYSTEM”即我們俗稱的系統應用和特權應用37scanDirLI()38submit()39parsePackage()40parsePackage(scanFile, parseFlags, true /* useCaches */)41parseMonolithicPackage()42parseBaseApk(,,)43parseBaseApk(,,,)44new Package(pkgName)45pkgPackageParser$Package代表記憶體中安裝後apk每個apk所申請的許可權都將存儲在其PackageParser$PackagerequestedPermissions數據結構中public final ArrayList<String>requestedPermissions= new ArrayList<String>();46parseBaseApkCommon(pkg,,,,,)讀取整個AndroidManifest.xml,此處關注<uses-permission>許可權申請標籤} else if (tagName.equals(TAG_USES_PERMISSION)) {if (!parseUsesPermission(pkg, res, parser)) {return null;}} else if…47parseUsesPermission()private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser){TypedArray sa = res.obtainAttributes(parser,com.android.internal.R.styleable.AndroidManifestUsesPermission);String name = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestUsesPermission_name);…pkg.requestedPermissions.add(name.intern());}↓Step 給應用授權48startOtherServices()49systemReady()50updateAllPermissions(,,Collection<PackageParser.Package> allPackages,)51updateAllPermissions()52updatePermissions(,,,,,)53restorePermissionState(,,,)private void restorePermissionState(@NonNull PackageParser.Package pkg, boolean replace,@Nullable String packageOfInterest, @Nullable PermissionCallback callback) {final int N = pkg.requestedPermissions.size();for (int i = 0; i < N; i++) {final String permName = pkg.requestedPermissions.get(i);final BasePermission bp = mSettings.getPermissionLocked(permName);else if (bp.isSignature()) {allowedSig = grantSignaturePermission(…)if (allowedSig) {grant = GRANT_INSTALL;}54grantSignaturePermission(…)55hasPrivappWhitelistEntry()56getPrivAppPermissions(packageName)57mPrivAppPermissions.get(packageName)private boolean grantSignaturePermission(String perm,PackageParser.Package> pkg,BasePermission bp, PermissionsState origPermissions) {boolean privappPermissionsDisable =RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;if (!privappPermissionsDisable&&privilegedPermission&&pkg.isPrivileged()&&!platformPackage&&platformPermission) {if (!hasPrivappWhitelistEntry(perm, pkg)) {// Only report violations for apps on system imageif (!mSystemReady&&!pkg.isUpdatedSystemApp()) {// it’s only a reportable violation if the permission isn’t explicitly deniedfinal boolean permissionViolation =deniedPermissions == null || !deniedPermissions.contains(perm);if (permissionViolation) {Slog.w(TAG, “Privileged permission ” + perm + ” for package “+ pkg.packageName + ” – not in privapp-permissions whitelist”);if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {mPrivappPermissionsViolations.add(pkg.packageName + “: ” + perm);//滿足以上十條才會將強制crash開關打開。此外return true/false:授權/不授權↓Step SystemServer Crash58systemReady()59systemReady()private void systemReady() {mSystemReady = true;if (mPrivappPermissionsViolations!= null) {throw new IllegalStateException(“Signature|privileged permissions not in “+ “privapp-permissions whitelist: ” + mPrivappPermissionsViolations);}} 分享此文:分享到 Twitter(在新視窗中開啟)按一下以分享至 Facebook(在新視窗中開啟)按一下以分享到 Telegram(在新視窗中開啟)分享到 Pinterest(在新視窗中開啟)更多點這裡列印(在新視窗中開啟)分享到 LinkedIn(在新視窗中開啟)分享到 Reddit(在新視窗中開啟)分享到 Tumblr(在新視窗中開啟)分享到 Pocket(在新視窗中開啟)分享到 WhatsApp(在新視窗中開啟)按一下即可分享至 Skype(在新視窗中開啟) Tags: Android Related Posts 2019 年 10 月 3 日 Consul的反熵 2022 年 3 月 7 日 ABP 使用ElasticSearch、Kibana、Docker 進行日誌收集