1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static com.android.internal.util.ArrayUtils.appendInt; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.ActivityManager; 24 import android.content.ComponentName; 25 import android.content.pm.FeatureInfo; 26 import android.content.pm.PackageManager; 27 import android.os.Build; 28 import android.os.CarrierAssociatedAppEntry; 29 import android.os.Environment; 30 import android.os.FileUtils; 31 import android.os.Process; 32 import android.os.SystemProperties; 33 import android.os.Trace; 34 import android.os.VintfRuntimeInfo; 35 import android.os.incremental.IncrementalManager; 36 import android.os.storage.StorageManager; 37 import android.permission.PermissionManager.SplitPermissionInfo; 38 import android.sysprop.ApexProperties; 39 import android.text.TextUtils; 40 import android.util.ArrayMap; 41 import android.util.ArraySet; 42 import android.util.Slog; 43 import android.util.SparseArray; 44 import android.util.TimingsTraceLog; 45 import android.util.Xml; 46 47 import com.android.internal.annotations.VisibleForTesting; 48 import com.android.internal.util.XmlUtils; 49 import com.android.modules.utils.build.UnboundedSdkLevel; 50 51 import libcore.io.IoUtils; 52 import libcore.util.EmptyArray; 53 54 import org.xmlpull.v1.XmlPullParser; 55 import org.xmlpull.v1.XmlPullParserException; 56 57 import java.io.BufferedReader; 58 import java.io.File; 59 import java.io.FileNotFoundException; 60 import java.io.FileReader; 61 import java.io.IOException; 62 import java.nio.file.Files; 63 import java.nio.file.Path; 64 import java.nio.file.Paths; 65 import java.util.ArrayList; 66 import java.util.Collections; 67 import java.util.List; 68 import java.util.Map; 69 import java.util.Set; 70 71 /** 72 * Loads global system configuration info. 73 * Note: Initializing this class hits the disk and is slow. This class should generally only be 74 * accessed by the system_server process. 75 */ 76 public class SystemConfig { 77 static final String TAG = "SystemConfig"; 78 79 static SystemConfig sInstance; 80 81 // permission flag, determines which types of configuration are allowed to be read 82 private static final int ALLOW_FEATURES = 0x001; 83 private static final int ALLOW_LIBS = 0x002; 84 private static final int ALLOW_PERMISSIONS = 0x004; 85 private static final int ALLOW_APP_CONFIGS = 0x008; 86 private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x010; 87 private static final int ALLOW_OEM_PERMISSIONS = 0x020; 88 private static final int ALLOW_HIDDENAPI_WHITELISTING = 0x040; 89 private static final int ALLOW_ASSOCIATIONS = 0x080; 90 // ALLOW_OVERRIDE_APP_RESTRICTIONS allows to use "allow-in-power-save-except-idle", 91 // "allow-in-power-save", "allow-in-data-usage-save","allow-unthrottled-location", 92 // "allow-ignore-location-settings" and "allow-adas-location-settings". 93 private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100; 94 private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200; 95 private static final int ALLOW_VENDOR_APEX = 0x400; 96 private static final int ALLOW_ALL = ~0; 97 98 // property for runtime configuration differentiation 99 private static final String SKU_PROPERTY = "ro.boot.product.hardware.sku"; 100 101 // property for runtime configuration differentiation in vendor 102 private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; 103 104 private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS = 105 new ArrayMap<>(); 106 107 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 108 int[] mGlobalGids = EmptyArray.INT; 109 110 // These are the built-in uid -> permission mappings that were read from the 111 // system configuration files. 112 final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>(); 113 114 final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>(); 115 isAtLeastSdkLevel(String version)116 private static boolean isAtLeastSdkLevel(String version) { 117 try { 118 return UnboundedSdkLevel.isAtLeast(version); 119 } catch (IllegalArgumentException e) { 120 // UnboundedSdkLevel throws when it sees a known old codename 121 return false; 122 } 123 } 124 isAtMostSdkLevel(String version)125 private static boolean isAtMostSdkLevel(String version) { 126 try { 127 return UnboundedSdkLevel.isAtMost(version); 128 } catch (IllegalArgumentException e) { 129 // UnboundedSdkLevel throws when it sees a known old codename 130 return true; 131 } 132 } 133 134 public static final class SharedLibraryEntry { 135 public final String name; 136 public final String filename; 137 public final String[] dependencies; 138 139 /** 140 * SDK version this library was added to the BOOTCLASSPATH. 141 * 142 * <p>At the SDK level specified in this field and higher, the apps' uses-library tags for 143 * this library will be ignored, since the library is always available on BOOTCLASSPATH. 144 * 145 * <p>0 means not specified. 146 */ 147 public final String onBootclasspathSince; 148 149 /** 150 * SDK version this library was removed from the BOOTCLASSPATH. 151 * 152 * <p>At the SDK level specified in this field and higher, this library needs to be 153 * explicitly added by apps. For compatibility reasons, when an app 154 * targets an SDK less than the value of this attribute, this library is automatically 155 * added. 156 * 157 * <p>0 means not specified. 158 */ 159 public final String onBootclasspathBefore; 160 161 /** 162 * Declares whether this library can be safely ignored from <uses-library> tags. 163 * 164 * <p> This can happen if the library initially had to be explicitly depended-on using that 165 * tag but has since been moved to the BOOTCLASSPATH which means now is always available 166 * and the tag is no longer required. 167 */ 168 public final boolean canBeSafelyIgnored; 169 170 public final boolean isNative; 171 172 173 @VisibleForTesting SharedLibraryEntry(String name, String filename, String[] dependencies, boolean isNative)174 public SharedLibraryEntry(String name, String filename, String[] dependencies, 175 boolean isNative) { 176 this(name, filename, dependencies, null /* onBootclasspathSince */, 177 null /* onBootclasspathBefore */, isNative); 178 } 179 180 @VisibleForTesting SharedLibraryEntry(String name, String filename, String[] dependencies, String onBootclasspathSince, String onBootclasspathBefore)181 public SharedLibraryEntry(String name, String filename, String[] dependencies, 182 String onBootclasspathSince, String onBootclasspathBefore) { 183 this(name, filename, dependencies, onBootclasspathSince, onBootclasspathBefore, 184 false /* isNative */); 185 } 186 SharedLibraryEntry(String name, String filename, String[] dependencies, String onBootclasspathSince, String onBootclasspathBefore, boolean isNative)187 SharedLibraryEntry(String name, String filename, String[] dependencies, 188 String onBootclasspathSince, String onBootclasspathBefore, boolean isNative) { 189 this.name = name; 190 this.filename = filename; 191 this.dependencies = dependencies; 192 this.onBootclasspathSince = onBootclasspathSince; 193 this.onBootclasspathBefore = onBootclasspathBefore; 194 this.isNative = isNative; 195 196 // this entry can be ignored if either: 197 // - onBootclasspathSince is set and we are at or past that SDK 198 // - onBootclasspathBefore is set and we are before that SDK 199 canBeSafelyIgnored = 200 (this.onBootclasspathSince != null 201 && isAtLeastSdkLevel(this.onBootclasspathSince)) 202 || (this.onBootclasspathBefore != null 203 && !isAtLeastSdkLevel(this.onBootclasspathBefore)); 204 } 205 } 206 207 // These are the built-in shared libraries that were read from the 208 // system configuration files. Keys are the library names; values are 209 // the individual entries that contain information such as filename 210 // and dependencies. 211 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries = new ArrayMap<>(); 212 213 // These are the features this devices supports that were read from the 214 // system configuration files. 215 final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>(); 216 217 // These are the features which this device doesn't support; the OEM 218 // partition uses these to opt-out of features from the system image. 219 final ArraySet<String> mUnavailableFeatures = new ArraySet<>(); 220 221 public static final class PermissionEntry { 222 public final String name; 223 public int[] gids; 224 public boolean perUser; 225 PermissionEntry(String name, boolean perUser)226 PermissionEntry(String name, boolean perUser) { 227 this.name = name; 228 this.perUser = perUser; 229 } 230 } 231 232 // These are the permission -> gid mappings that were read from the 233 // system configuration files. 234 final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>(); 235 236 // These are the packages that are white-listed to be able to run in the 237 // background while in power save mode (but not whitelisted from device idle modes), 238 // as read from the configuration files. 239 final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>(); 240 241 // These are the packages that are white-listed to be able to run in the 242 // background while in power save mode, as read from the configuration files. 243 final ArraySet<String> mAllowInPowerSave = new ArraySet<>(); 244 245 // These are the packages that are white-listed to be able to run in the 246 // background while in data-usage save mode, as read from the configuration files. 247 final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>(); 248 249 // These are the packages that are white-listed to be able to run background location 250 // without throttling, as read from the configuration files. 251 final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>(); 252 253 // These are the packages that are allow-listed to be able to retrieve location when 254 // the location state is driver assistance only. 255 final ArrayMap<String, ArraySet<String>> mAllowAdasSettings = new ArrayMap<>(); 256 257 // These are the packages that are white-listed to be able to retrieve location even when user 258 // location settings are off, for emergency purposes, as read from the configuration files. 259 final ArrayMap<String, ArraySet<String>> mAllowIgnoreLocationSettings = new ArrayMap<>(); 260 261 // These are the action strings of broadcasts which are whitelisted to 262 // be delivered anonymously even to apps which target O+. 263 final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>(); 264 265 // These are the packages that are exempted from the background restriction applied 266 // by the system automatically, i.e., due to high background current drain. 267 final ArraySet<String> mBgRestrictionExemption = new ArraySet<>(); 268 269 // These are the package names of apps which should be automatically granted domain verification 270 // for all of their domains. The only way these apps can be overridden by the user is by 271 // explicitly disabling overall link handling support in app info. 272 final ArraySet<String> mLinkedApps = new ArraySet<>(); 273 274 // These are the components that are enabled by default as VR mode listener services. 275 final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>(); 276 277 // These are the permitted backup transport service components 278 final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); 279 280 // These are packages mapped to maps of component class name to default enabled state. 281 final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState = 282 new ArrayMap<>(); 283 284 // Package names that are exempted from private API blacklisting 285 final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>(); 286 287 // The list of carrier applications which should be disabled until used. 288 // This function suppresses update notifications for these pre-installed apps. 289 // In SubscriptionInfoUpdater, the listed applications are disabled until used when all of the 290 // following conditions are met. 291 // 1. Not currently carrier-privileged according to the inserted SIM 292 // 2. Pre-installed 293 // 3. In the default state (enabled but not explicitly) 294 // And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted 295 // that marks the app as carrier privileged. It also grants the app default permissions 296 // for Phone and Location. As such, apps MUST only ever be added to this list if they 297 // obtain user consent to access their location through other means. 298 final ArraySet<String> mDisabledUntilUsedPreinstalledCarrierApps = new ArraySet<>(); 299 300 // These are the packages of carrier-associated apps which should be disabled until used until 301 // a SIM is inserted which grants carrier privileges to that carrier app. 302 final ArrayMap<String, List<CarrierAssociatedAppEntry>> 303 mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>(); 304 305 final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); 306 final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); 307 308 final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>(); 309 final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>(); 310 311 final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>(); 312 final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>(); 313 314 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>(); 315 final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>(); 316 317 final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppPermissions = 318 new ArrayMap<>(); 319 final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppDenyPermissions = 320 new ArrayMap<>(); 321 322 final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); 323 324 // Allowed associations between applications. If there are any entries 325 // for an app, those are the only associations allowed; otherwise, all associations 326 // are allowed. Allowing an association from app A to app B means app A can not 327 // associate with any other apps, but does not limit what apps B can associate with. 328 final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>(); 329 330 private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>(); 331 private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>(); 332 333 // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService(). 334 private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>(); 335 private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>(); 336 337 private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>(); 338 private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>(); 339 // A map from package name of vendor APEXes that can be updated to an installer package name 340 // allowed to install updates for it. 341 private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>(); 342 // A set of package names that are allowed to use <install-constraints> manifest tag. 343 private final Set<String> mInstallConstraintsAllowlist = new ArraySet<>(); 344 345 private String mModulesInstallerPackageName; 346 347 /** 348 * Map of system pre-defined, uniquely named actors; keys are namespace, 349 * value maps actor name to package name. 350 */ 351 private Map<String, Map<String, String>> mNamedActors = null; 352 353 // Package name of the package pre-installed on a read-only 354 // partition that is used to verify if an overlay package fulfills 355 // the 'config_signature' policy by comparing their signatures: 356 // if the overlay package is signed with the same certificate as 357 // the package declared in 'overlay-config-signature' tag, then the 358 // overlay package fulfills the 'config_signature' policy. 359 private String mOverlayConfigSignaturePackage; 360 getInstance()361 public static SystemConfig getInstance() { 362 if (!isSystemProcess()) { 363 Slog.wtf(TAG, "SystemConfig is being accessed by a process other than " 364 + "system_server."); 365 } 366 367 synchronized (SystemConfig.class) { 368 if (sInstance == null) { 369 sInstance = new SystemConfig(); 370 } 371 return sInstance; 372 } 373 } 374 getGlobalGids()375 public int[] getGlobalGids() { 376 return mGlobalGids; 377 } 378 getSystemPermissions()379 public SparseArray<ArraySet<String>> getSystemPermissions() { 380 return mSystemPermissions; 381 } 382 getSplitPermissions()383 public ArrayList<SplitPermissionInfo> getSplitPermissions() { 384 return mSplitPermissions; 385 } 386 getSharedLibraries()387 public ArrayMap<String, SharedLibraryEntry> getSharedLibraries() { 388 return mSharedLibraries; 389 } 390 getAvailableFeatures()391 public ArrayMap<String, FeatureInfo> getAvailableFeatures() { 392 return mAvailableFeatures; 393 } 394 getPermissions()395 public ArrayMap<String, PermissionEntry> getPermissions() { 396 return mPermissions; 397 } 398 getAllowImplicitBroadcasts()399 public ArraySet<String> getAllowImplicitBroadcasts() { 400 return mAllowImplicitBroadcasts; 401 } 402 getAllowInPowerSaveExceptIdle()403 public ArraySet<String> getAllowInPowerSaveExceptIdle() { 404 return mAllowInPowerSaveExceptIdle; 405 } 406 getAllowInPowerSave()407 public ArraySet<String> getAllowInPowerSave() { 408 return mAllowInPowerSave; 409 } 410 getAllowInDataUsageSave()411 public ArraySet<String> getAllowInDataUsageSave() { 412 return mAllowInDataUsageSave; 413 } 414 getAllowUnthrottledLocation()415 public ArraySet<String> getAllowUnthrottledLocation() { 416 return mAllowUnthrottledLocation; 417 } 418 getAllowAdasLocationSettings()419 public ArrayMap<String, ArraySet<String>> getAllowAdasLocationSettings() { 420 return mAllowAdasSettings; 421 } 422 getAllowIgnoreLocationSettings()423 public ArrayMap<String, ArraySet<String>> getAllowIgnoreLocationSettings() { 424 return mAllowIgnoreLocationSettings; 425 } 426 getBgRestrictionExemption()427 public ArraySet<String> getBgRestrictionExemption() { 428 return mBgRestrictionExemption; 429 } 430 getLinkedApps()431 public ArraySet<String> getLinkedApps() { 432 return mLinkedApps; 433 } 434 getHiddenApiWhitelistedApps()435 public ArraySet<String> getHiddenApiWhitelistedApps() { 436 return mHiddenApiPackageWhitelist; 437 } 438 getDefaultVrComponents()439 public ArraySet<ComponentName> getDefaultVrComponents() { 440 return mDefaultVrComponents; 441 } 442 getBackupTransportWhitelist()443 public ArraySet<ComponentName> getBackupTransportWhitelist() { 444 return mBackupTransportWhitelist; 445 } 446 getComponentsEnabledStates(String packageName)447 public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) { 448 return mPackageComponentEnabledState.get(packageName); 449 } 450 getDisabledUntilUsedPreinstalledCarrierApps()451 public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() { 452 return mDisabledUntilUsedPreinstalledCarrierApps; 453 } 454 455 public ArrayMap<String, List<CarrierAssociatedAppEntry>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps()456 getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { 457 return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; 458 } 459 getPrivAppPermissions(String packageName)460 public ArraySet<String> getPrivAppPermissions(String packageName) { 461 return mPrivAppPermissions.get(packageName); 462 } 463 getPrivAppDenyPermissions(String packageName)464 public ArraySet<String> getPrivAppDenyPermissions(String packageName) { 465 return mPrivAppDenyPermissions.get(packageName); 466 } 467 468 /** Get privapp permission allowlist for an apk-in-apex. */ getApexPrivAppPermissions(String apexName, String apkPackageName)469 public ArraySet<String> getApexPrivAppPermissions(String apexName, String apkPackageName) { 470 return mApexPrivAppPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) 471 .get(apkPackageName); 472 } 473 474 /** Get privapp permissions denylist for an apk-in-apex. */ getApexPrivAppDenyPermissions(String apexName, String apkPackageName)475 public ArraySet<String> getApexPrivAppDenyPermissions(String apexName, String apkPackageName) { 476 return mApexPrivAppDenyPermissions.getOrDefault(apexName, EMPTY_PERMISSIONS) 477 .get(apkPackageName); 478 } 479 getVendorPrivAppPermissions(String packageName)480 public ArraySet<String> getVendorPrivAppPermissions(String packageName) { 481 return mVendorPrivAppPermissions.get(packageName); 482 } 483 getVendorPrivAppDenyPermissions(String packageName)484 public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) { 485 return mVendorPrivAppDenyPermissions.get(packageName); 486 } 487 getProductPrivAppPermissions(String packageName)488 public ArraySet<String> getProductPrivAppPermissions(String packageName) { 489 return mProductPrivAppPermissions.get(packageName); 490 } 491 getProductPrivAppDenyPermissions(String packageName)492 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) { 493 return mProductPrivAppDenyPermissions.get(packageName); 494 } 495 496 /** 497 * Read from "permission" tags in /system_ext/etc/permissions/*.xml 498 * @return Set of privileged permissions that are explicitly granted. 499 */ getSystemExtPrivAppPermissions(String packageName)500 public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) { 501 return mSystemExtPrivAppPermissions.get(packageName); 502 } 503 504 /** 505 * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml 506 * @return Set of privileged permissions that are explicitly denied. 507 */ getSystemExtPrivAppDenyPermissions(String packageName)508 public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) { 509 return mSystemExtPrivAppDenyPermissions.get(packageName); 510 } 511 getOemPermissions(String packageName)512 public Map<String, Boolean> getOemPermissions(String packageName) { 513 final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName); 514 if (oemPermissions != null) { 515 return oemPermissions; 516 } 517 return Collections.emptyMap(); 518 } 519 getAllowedAssociations()520 public ArrayMap<String, ArraySet<String>> getAllowedAssociations() { 521 return mAllowedAssociations; 522 } 523 getBugreportWhitelistedPackages()524 public ArraySet<String> getBugreportWhitelistedPackages() { 525 return mBugreportWhitelistedPackages; 526 } 527 getRollbackWhitelistedPackages()528 public Set<String> getRollbackWhitelistedPackages() { 529 return mRollbackWhitelistedPackages; 530 } 531 getWhitelistedStagedInstallers()532 public Set<String> getWhitelistedStagedInstallers() { 533 return mWhitelistedStagedInstallers; 534 } 535 getAllowedVendorApexes()536 public Map<String, String> getAllowedVendorApexes() { 537 return mAllowedVendorApexes; 538 } 539 getInstallConstraintsAllowlist()540 public Set<String> getInstallConstraintsAllowlist() { 541 return mInstallConstraintsAllowlist; 542 } 543 getModulesInstallerPackageName()544 public String getModulesInstallerPackageName() { 545 return mModulesInstallerPackageName; 546 } 547 getAppDataIsolationWhitelistedApps()548 public ArraySet<String> getAppDataIsolationWhitelistedApps() { 549 return mAppDataIsolationWhitelistedApps; 550 } 551 552 /** 553 * Gets map of packagesNames to userTypes, dictating on which user types each package should be 554 * initially installed, and then removes this map from SystemConfig. 555 * Called by UserManagerService when it is constructed. 556 */ getAndClearPackageToUserTypeWhitelist()557 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeWhitelist() { 558 ArrayMap<String, Set<String>> r = mPackageToUserTypeWhitelist; 559 mPackageToUserTypeWhitelist = new ArrayMap<>(0); 560 return r; 561 } 562 563 /** 564 * Gets map of packagesNames to userTypes, dictating on which user types each package should NOT 565 * be initially installed, even if they are whitelisted, and then removes this map from 566 * SystemConfig. 567 * Called by UserManagerService when it is constructed. 568 */ getAndClearPackageToUserTypeBlacklist()569 public ArrayMap<String, Set<String>> getAndClearPackageToUserTypeBlacklist() { 570 ArrayMap<String, Set<String>> r = mPackageToUserTypeBlacklist; 571 mPackageToUserTypeBlacklist = new ArrayMap<>(0); 572 return r; 573 } 574 575 @NonNull getNamedActors()576 public Map<String, Map<String, String>> getNamedActors() { 577 return mNamedActors != null ? mNamedActors : Collections.emptyMap(); 578 } 579 580 @Nullable getOverlayConfigSignaturePackage()581 public String getOverlayConfigSignaturePackage() { 582 return TextUtils.isEmpty(mOverlayConfigSignaturePackage) 583 ? null : mOverlayConfigSignaturePackage; 584 } 585 586 /** 587 * Only use for testing. Do NOT use in production code. 588 * @param readPermissions false to create an empty SystemConfig; true to read the permissions. 589 */ 590 @VisibleForTesting SystemConfig(boolean readPermissions)591 public SystemConfig(boolean readPermissions) { 592 if (readPermissions) { 593 Slog.w(TAG, "Constructing a test SystemConfig"); 594 readAllPermissions(); 595 } else { 596 Slog.w(TAG, "Constructing an empty test SystemConfig"); 597 } 598 } 599 SystemConfig()600 SystemConfig() { 601 TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); 602 log.traceBegin("readAllPermissions"); 603 try { 604 readAllPermissions(); 605 readPublicNativeLibrariesList(); 606 } finally { 607 log.traceEnd(); 608 } 609 } 610 readAllPermissions()611 private void readAllPermissions() { 612 final XmlPullParser parser = Xml.newPullParser(); 613 614 // Read configuration from system 615 readPermissions(parser, Environment.buildPath( 616 Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); 617 618 // Read configuration from the old permissions dir 619 readPermissions(parser, Environment.buildPath( 620 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); 621 622 // Vendors are only allowed to customize these 623 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS 624 | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX; 625 if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) { 626 // For backward compatibility 627 vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); 628 } 629 readPermissions(parser, Environment.buildPath( 630 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); 631 readPermissions(parser, Environment.buildPath( 632 Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); 633 634 String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, ""); 635 if (!vendorSkuProperty.isEmpty()) { 636 String vendorSkuDir = "sku_" + vendorSkuProperty; 637 readPermissions(parser, Environment.buildPath( 638 Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir), 639 vendorPermissionFlag); 640 readPermissions(parser, Environment.buildPath( 641 Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir), 642 vendorPermissionFlag); 643 } 644 645 // Allow ODM to customize system configs as much as Vendor, because /odm is another 646 // vendor partition other than /vendor. 647 int odmPermissionFlag = vendorPermissionFlag; 648 readPermissions(parser, Environment.buildPath( 649 Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); 650 readPermissions(parser, Environment.buildPath( 651 Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); 652 653 String skuProperty = SystemProperties.get(SKU_PROPERTY, ""); 654 if (!skuProperty.isEmpty()) { 655 String skuDir = "sku_" + skuProperty; 656 657 readPermissions(parser, Environment.buildPath( 658 Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag); 659 readPermissions(parser, Environment.buildPath( 660 Environment.getOdmDirectory(), "etc", "permissions", skuDir), 661 odmPermissionFlag); 662 } 663 664 // Allow OEM to customize these 665 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS 666 | ALLOW_VENDOR_APEX; 667 readPermissions(parser, Environment.buildPath( 668 Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); 669 readPermissions(parser, Environment.buildPath( 670 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); 671 672 // Allow Product to customize these configs 673 // TODO(b/157203468): ALLOW_HIDDENAPI_WHITELISTING must be removed because we prohibited 674 // the use of hidden APIs from the product partition. 675 int productPermissionFlag = ALLOW_FEATURES | ALLOW_LIBS | ALLOW_PERMISSIONS 676 | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_HIDDENAPI_WHITELISTING 677 | ALLOW_ASSOCIATIONS | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS 678 | ALLOW_VENDOR_APEX; 679 if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) { 680 // TODO(b/157393157): This must check product interface enforcement instead of 681 // DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement. 682 productPermissionFlag = ALLOW_ALL; 683 } 684 readPermissions(parser, Environment.buildPath( 685 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag); 686 readPermissions(parser, Environment.buildPath( 687 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag); 688 689 // Allow /system_ext to customize all system configs 690 readPermissions(parser, Environment.buildPath( 691 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL); 692 readPermissions(parser, Environment.buildPath( 693 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL); 694 695 // Skip loading configuration from apex if it is not a system process. 696 if (!isSystemProcess()) { 697 return; 698 } 699 // Read configuration of features, libs and priv-app permissions from apex module. 700 int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; 701 // TODO: Use a solid way to filter apex module folders? 702 for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) { 703 if (f.isFile() || f.getPath().contains("@")) { 704 continue; 705 } 706 readPermissions(parser, Environment.buildPath(f, "etc", "permissions"), 707 apexPermissionFlag); 708 } 709 } 710 711 @VisibleForTesting readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag)712 public void readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag) { 713 // Read permissions from given directory. 714 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 715 if (permissionFlag == ALLOW_ALL) { 716 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 717 } 718 return; 719 } 720 if (!libraryDir.canRead()) { 721 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 722 return; 723 } 724 725 // Iterate over the files in the directory and scan .xml files 726 File platformFile = null; 727 for (File f : libraryDir.listFiles()) { 728 if (!f.isFile()) { 729 continue; 730 } 731 732 // We'll read platform.xml last 733 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 734 platformFile = f; 735 continue; 736 } 737 738 if (!f.getPath().endsWith(".xml")) { 739 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 740 continue; 741 } 742 if (!f.canRead()) { 743 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 744 continue; 745 } 746 747 readPermissionsFromXml(parser, f, permissionFlag); 748 } 749 750 // Read platform permissions last so it will take precedence 751 if (platformFile != null) { 752 readPermissionsFromXml(parser, platformFile, permissionFlag); 753 } 754 } 755 logNotAllowedInPartition(String name, File permFile, XmlPullParser parser)756 private void logNotAllowedInPartition(String name, File permFile, XmlPullParser parser) { 757 Slog.w(TAG, "<" + name + "> not allowed in partition of " 758 + permFile + " at " + parser.getPositionDescription()); 759 } 760 readPermissionsFromXml(final XmlPullParser parser, File permFile, int permissionFlag)761 private void readPermissionsFromXml(final XmlPullParser parser, File permFile, 762 int permissionFlag) { 763 final FileReader permReader; 764 try { 765 permReader = new FileReader(permFile); 766 } catch (FileNotFoundException e) { 767 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 768 return; 769 } 770 Slog.i(TAG, "Reading permissions from " + permFile); 771 772 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); 773 774 try { 775 parser.setInput(permReader); 776 777 int type; 778 while ((type=parser.next()) != parser.START_TAG 779 && type != parser.END_DOCUMENT) { 780 ; 781 } 782 783 if (type != parser.START_TAG) { 784 throw new XmlPullParserException("No start tag found"); 785 } 786 787 if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { 788 throw new XmlPullParserException("Unexpected start tag in " + permFile 789 + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); 790 } 791 792 final boolean allowAll = permissionFlag == ALLOW_ALL; 793 final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0; 794 final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0; 795 final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0; 796 final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; 797 final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) 798 != 0; 799 final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0; 800 final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) 801 != 0; 802 final boolean allowAssociations = (permissionFlag & ALLOW_ASSOCIATIONS) != 0; 803 final boolean allowOverrideAppRestrictions = 804 (permissionFlag & ALLOW_OVERRIDE_APP_RESTRICTIONS) != 0; 805 final boolean allowImplicitBroadcasts = (permissionFlag & ALLOW_IMPLICIT_BROADCASTS) 806 != 0; 807 final boolean allowVendorApex = (permissionFlag & ALLOW_VENDOR_APEX) != 0; 808 while (true) { 809 XmlUtils.nextElement(parser); 810 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 811 break; 812 } 813 814 String name = parser.getName(); 815 if (name == null) { 816 XmlUtils.skipCurrentTag(parser); 817 continue; 818 } 819 switch (name) { 820 case "group": { 821 if (allowAll) { 822 String gidStr = parser.getAttributeValue(null, "gid"); 823 if (gidStr != null) { 824 int gid = android.os.Process.getGidForName(gidStr); 825 mGlobalGids = appendInt(mGlobalGids, gid); 826 } else { 827 Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at " 828 + parser.getPositionDescription()); 829 } 830 } else { 831 logNotAllowedInPartition(name, permFile, parser); 832 } 833 XmlUtils.skipCurrentTag(parser); 834 } break; 835 case "permission": { 836 if (allowPermissions) { 837 String perm = parser.getAttributeValue(null, "name"); 838 if (perm == null) { 839 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 840 + parser.getPositionDescription()); 841 XmlUtils.skipCurrentTag(parser); 842 break; 843 } 844 perm = perm.intern(); 845 readPermission(parser, perm); 846 } else { 847 logNotAllowedInPartition(name, permFile, parser); 848 XmlUtils.skipCurrentTag(parser); 849 } 850 } break; 851 case "assign-permission": { 852 if (allowPermissions) { 853 String perm = parser.getAttributeValue(null, "name"); 854 if (perm == null) { 855 Slog.w(TAG, "<" + name + "> without name in " + permFile 856 + " at " + parser.getPositionDescription()); 857 XmlUtils.skipCurrentTag(parser); 858 break; 859 } 860 String uidStr = parser.getAttributeValue(null, "uid"); 861 if (uidStr == null) { 862 Slog.w(TAG, "<" + name + "> without uid in " + permFile 863 + " at " + parser.getPositionDescription()); 864 XmlUtils.skipCurrentTag(parser); 865 break; 866 } 867 int uid = Process.getUidForName(uidStr); 868 if (uid < 0) { 869 Slog.w(TAG, "<" + name + "> with unknown uid \"" 870 + uidStr + " in " + permFile + " at " 871 + parser.getPositionDescription()); 872 XmlUtils.skipCurrentTag(parser); 873 break; 874 } 875 perm = perm.intern(); 876 ArraySet<String> perms = mSystemPermissions.get(uid); 877 if (perms == null) { 878 perms = new ArraySet<String>(); 879 mSystemPermissions.put(uid, perms); 880 } 881 perms.add(perm); 882 } else { 883 logNotAllowedInPartition(name, permFile, parser); 884 } 885 XmlUtils.skipCurrentTag(parser); 886 } break; 887 case "split-permission": { 888 if (allowPermissions) { 889 readSplitPermission(parser, permFile); 890 } else { 891 logNotAllowedInPartition(name, permFile, parser); 892 XmlUtils.skipCurrentTag(parser); 893 } 894 } break; 895 case "apex-library": 896 // "apex-library" is meant to behave exactly like "library" 897 case "library": { 898 if (allowLibs) { 899 String lname = parser.getAttributeValue(null, "name"); 900 String lfile = parser.getAttributeValue(null, "file"); 901 String ldependency = parser.getAttributeValue(null, "dependency"); 902 String minDeviceSdk = parser.getAttributeValue(null, "min-device-sdk"); 903 String maxDeviceSdk = parser.getAttributeValue(null, "max-device-sdk"); 904 if (lname == null) { 905 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 906 + parser.getPositionDescription()); 907 } else if (lfile == null) { 908 Slog.w(TAG, "<" + name + "> without file in " + permFile + " at " 909 + parser.getPositionDescription()); 910 } else { 911 boolean allowedMinSdk = 912 minDeviceSdk == null || isAtLeastSdkLevel(minDeviceSdk); 913 boolean allowedMaxSdk = 914 maxDeviceSdk == null || isAtMostSdkLevel(maxDeviceSdk); 915 final boolean exists = new File(lfile).exists(); 916 if (allowedMinSdk && allowedMaxSdk && exists) { 917 String bcpSince = parser.getAttributeValue(null, 918 "on-bootclasspath-since"); 919 String bcpBefore = parser.getAttributeValue(null, 920 "on-bootclasspath-before"); 921 SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile, 922 ldependency == null 923 ? new String[0] : ldependency.split(":"), 924 bcpSince, bcpBefore); 925 mSharedLibraries.put(lname, entry); 926 } else { 927 final StringBuilder msg = new StringBuilder( 928 "Ignore shared library ").append(lname).append(":"); 929 if (!allowedMinSdk) { 930 msg.append(" min-device-sdk=").append(minDeviceSdk); 931 } 932 if (!allowedMaxSdk) { 933 msg.append(" max-device-sdk=").append(maxDeviceSdk); 934 } 935 if (!exists) { 936 msg.append(" ").append(lfile).append(" does not exist"); 937 } 938 Slog.i(TAG, msg.toString()); 939 } 940 } 941 } else { 942 logNotAllowedInPartition(name, permFile, parser); 943 } 944 XmlUtils.skipCurrentTag(parser); 945 } break; 946 case "feature": { 947 if (allowFeatures) { 948 String fname = parser.getAttributeValue(null, "name"); 949 int fversion = XmlUtils.readIntAttribute(parser, "version", 0); 950 boolean allowed; 951 if (!lowRam) { 952 allowed = true; 953 } else { 954 String notLowRam = parser.getAttributeValue(null, "notLowRam"); 955 allowed = !"true".equals(notLowRam); 956 } 957 if (fname == null) { 958 Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " 959 + parser.getPositionDescription()); 960 } else if (allowed) { 961 addFeature(fname, fversion); 962 } 963 } else { 964 logNotAllowedInPartition(name, permFile, parser); 965 } 966 XmlUtils.skipCurrentTag(parser); 967 } break; 968 case "unavailable-feature": { 969 if (allowFeatures) { 970 String fname = parser.getAttributeValue(null, "name"); 971 if (fname == null) { 972 Slog.w(TAG, "<" + name + "> without name in " + permFile 973 + " at " + parser.getPositionDescription()); 974 } else { 975 mUnavailableFeatures.add(fname); 976 } 977 } else { 978 logNotAllowedInPartition(name, permFile, parser); 979 } 980 XmlUtils.skipCurrentTag(parser); 981 } break; 982 case "allow-in-power-save-except-idle": { 983 if (allowOverrideAppRestrictions) { 984 String pkgname = parser.getAttributeValue(null, "package"); 985 if (pkgname == null) { 986 Slog.w(TAG, "<" + name + "> without package in " 987 + permFile + " at " + parser.getPositionDescription()); 988 } else { 989 mAllowInPowerSaveExceptIdle.add(pkgname); 990 } 991 } else { 992 logNotAllowedInPartition(name, permFile, parser); 993 } 994 XmlUtils.skipCurrentTag(parser); 995 } break; 996 case "allow-in-power-save": { 997 if (allowOverrideAppRestrictions) { 998 String pkgname = parser.getAttributeValue(null, "package"); 999 if (pkgname == null) { 1000 Slog.w(TAG, "<" + name + "> without package in " 1001 + permFile + " at " + parser.getPositionDescription()); 1002 } else { 1003 mAllowInPowerSave.add(pkgname); 1004 } 1005 } else { 1006 logNotAllowedInPartition(name, permFile, parser); 1007 } 1008 XmlUtils.skipCurrentTag(parser); 1009 } break; 1010 case "allow-in-data-usage-save": { 1011 if (allowOverrideAppRestrictions) { 1012 String pkgname = parser.getAttributeValue(null, "package"); 1013 if (pkgname == null) { 1014 Slog.w(TAG, "<" + name + "> without package in " 1015 + permFile + " at " + parser.getPositionDescription()); 1016 } else { 1017 mAllowInDataUsageSave.add(pkgname); 1018 } 1019 } else { 1020 logNotAllowedInPartition(name, permFile, parser); 1021 } 1022 XmlUtils.skipCurrentTag(parser); 1023 } break; 1024 case "allow-unthrottled-location": { 1025 if (allowOverrideAppRestrictions) { 1026 String pkgname = parser.getAttributeValue(null, "package"); 1027 if (pkgname == null) { 1028 Slog.w(TAG, "<" + name + "> without package in " 1029 + permFile + " at " + parser.getPositionDescription()); 1030 } else { 1031 mAllowUnthrottledLocation.add(pkgname); 1032 } 1033 } else { 1034 logNotAllowedInPartition(name, permFile, parser); 1035 } 1036 XmlUtils.skipCurrentTag(parser); 1037 } break; 1038 case "allow-adas-location-settings" : { 1039 if (allowOverrideAppRestrictions) { 1040 String pkgname = parser.getAttributeValue(null, "package"); 1041 String attributionTag = parser.getAttributeValue(null, 1042 "attributionTag"); 1043 if (pkgname == null) { 1044 Slog.w(TAG, "<" + name + "> without package in " 1045 + permFile + " at " + parser.getPositionDescription()); 1046 } else { 1047 ArraySet<String> tags = mAllowAdasSettings.get(pkgname); 1048 if (tags == null || !tags.isEmpty()) { 1049 if (tags == null) { 1050 tags = new ArraySet<>(1); 1051 mAllowAdasSettings.put(pkgname, tags); 1052 } 1053 if (!"*".equals(attributionTag)) { 1054 if ("null".equals(attributionTag)) { 1055 attributionTag = null; 1056 } 1057 tags.add(attributionTag); 1058 } 1059 } 1060 } 1061 } else { 1062 logNotAllowedInPartition(name, permFile, parser); 1063 } 1064 XmlUtils.skipCurrentTag(parser); 1065 } break; 1066 case "allow-ignore-location-settings": { 1067 if (allowOverrideAppRestrictions) { 1068 String pkgname = parser.getAttributeValue(null, "package"); 1069 String attributionTag = parser.getAttributeValue(null, 1070 "attributionTag"); 1071 if (pkgname == null) { 1072 Slog.w(TAG, "<" + name + "> without package in " 1073 + permFile + " at " + parser.getPositionDescription()); 1074 } else { 1075 ArraySet<String> tags = mAllowIgnoreLocationSettings.get(pkgname); 1076 if (tags == null || !tags.isEmpty()) { 1077 if (tags == null) { 1078 tags = new ArraySet<>(1); 1079 mAllowIgnoreLocationSettings.put(pkgname, tags); 1080 } 1081 if (!"*".equals(attributionTag)) { 1082 if ("null".equals(attributionTag)) { 1083 attributionTag = null; 1084 } 1085 tags.add(attributionTag); 1086 } 1087 } 1088 } 1089 } else { 1090 logNotAllowedInPartition(name, permFile, parser); 1091 } 1092 XmlUtils.skipCurrentTag(parser); 1093 } break; 1094 case "allow-implicit-broadcast": { 1095 if (allowImplicitBroadcasts) { 1096 String action = parser.getAttributeValue(null, "action"); 1097 if (action == null) { 1098 Slog.w(TAG, "<" + name + "> without action in " 1099 + permFile + " at " + parser.getPositionDescription()); 1100 } else { 1101 mAllowImplicitBroadcasts.add(action); 1102 } 1103 } else { 1104 logNotAllowedInPartition(name, permFile, parser); 1105 } 1106 XmlUtils.skipCurrentTag(parser); 1107 } break; 1108 case "app-link": { 1109 if (allowAppConfigs) { 1110 String pkgname = parser.getAttributeValue(null, "package"); 1111 if (pkgname == null) { 1112 Slog.w(TAG, "<" + name + "> without package in " + permFile 1113 + " at " + parser.getPositionDescription()); 1114 } else { 1115 mLinkedApps.add(pkgname); 1116 } 1117 } else { 1118 logNotAllowedInPartition(name, permFile, parser); 1119 } 1120 XmlUtils.skipCurrentTag(parser); 1121 } break; 1122 case "bg-restriction-exemption": { 1123 if (allowOverrideAppRestrictions) { 1124 String pkgname = parser.getAttributeValue(null, "package"); 1125 if (pkgname == null) { 1126 Slog.w(TAG, "<" + name + "> without package in " 1127 + permFile + " at " + parser.getPositionDescription()); 1128 } else { 1129 mBgRestrictionExemption.add(pkgname); 1130 } 1131 } else { 1132 logNotAllowedInPartition(name, permFile, parser); 1133 } 1134 XmlUtils.skipCurrentTag(parser); 1135 } break; 1136 case "default-enabled-vr-app": { 1137 if (allowAppConfigs) { 1138 String pkgname = parser.getAttributeValue(null, "package"); 1139 String clsname = parser.getAttributeValue(null, "class"); 1140 if (pkgname == null) { 1141 Slog.w(TAG, "<" + name + "> without package in " 1142 + permFile + " at " + parser.getPositionDescription()); 1143 } else if (clsname == null) { 1144 Slog.w(TAG, "<" + name + "> without class in " 1145 + permFile + " at " + parser.getPositionDescription()); 1146 } else { 1147 mDefaultVrComponents.add(new ComponentName(pkgname, clsname)); 1148 } 1149 } else { 1150 logNotAllowedInPartition(name, permFile, parser); 1151 } 1152 XmlUtils.skipCurrentTag(parser); 1153 } break; 1154 case "component-override": { 1155 readComponentOverrides(parser, permFile); 1156 } break; 1157 case "backup-transport-whitelisted-service": { 1158 if (allowFeatures) { 1159 String serviceName = parser.getAttributeValue(null, "service"); 1160 if (serviceName == null) { 1161 Slog.w(TAG, "<" + name + "> without service in " 1162 + permFile + " at " + parser.getPositionDescription()); 1163 } else { 1164 ComponentName cn = ComponentName.unflattenFromString(serviceName); 1165 if (cn == null) { 1166 Slog.w(TAG, "<" + name + "> with invalid service name " 1167 + serviceName + " in " + permFile 1168 + " at " + parser.getPositionDescription()); 1169 } else { 1170 mBackupTransportWhitelist.add(cn); 1171 } 1172 } 1173 } else { 1174 logNotAllowedInPartition(name, permFile, parser); 1175 } 1176 XmlUtils.skipCurrentTag(parser); 1177 } break; 1178 case "disabled-until-used-preinstalled-carrier-associated-app": { 1179 if (allowAppConfigs) { 1180 String pkgname = parser.getAttributeValue(null, "package"); 1181 String carrierPkgname = parser.getAttributeValue(null, 1182 "carrierAppPackage"); 1183 if (pkgname == null || carrierPkgname == null) { 1184 Slog.w(TAG, "<" + name 1185 + "> without package or carrierAppPackage in " + permFile 1186 + " at " + parser.getPositionDescription()); 1187 } else { 1188 // APKs added to system images via OTA should specify the addedInSdk 1189 // attribute, otherwise they may be enabled-by-default in too many 1190 // cases. See CarrierAppUtils for more info. 1191 int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED; 1192 String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk"); 1193 if (!TextUtils.isEmpty(addedInSdkStr)) { 1194 try { 1195 addedInSdk = Integer.parseInt(addedInSdkStr); 1196 } catch (NumberFormatException e) { 1197 Slog.w(TAG, "<" + name + "> addedInSdk not an integer in " 1198 + permFile + " at " 1199 + parser.getPositionDescription()); 1200 XmlUtils.skipCurrentTag(parser); 1201 break; 1202 } 1203 } 1204 List<CarrierAssociatedAppEntry> associatedPkgs = 1205 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( 1206 carrierPkgname); 1207 if (associatedPkgs == null) { 1208 associatedPkgs = new ArrayList<>(); 1209 mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( 1210 carrierPkgname, associatedPkgs); 1211 } 1212 associatedPkgs.add( 1213 new CarrierAssociatedAppEntry(pkgname, addedInSdk)); 1214 } 1215 } else { 1216 logNotAllowedInPartition(name, permFile, parser); 1217 } 1218 XmlUtils.skipCurrentTag(parser); 1219 } break; 1220 case "disabled-until-used-preinstalled-carrier-app": { 1221 if (allowAppConfigs) { 1222 String pkgname = parser.getAttributeValue(null, "package"); 1223 if (pkgname == null) { 1224 Slog.w(TAG, 1225 "<" + name + "> without " 1226 + "package in " + permFile + " at " 1227 + parser.getPositionDescription()); 1228 } else { 1229 mDisabledUntilUsedPreinstalledCarrierApps.add(pkgname); 1230 } 1231 } else { 1232 logNotAllowedInPartition(name, permFile, parser); 1233 } 1234 XmlUtils.skipCurrentTag(parser); 1235 } break; 1236 case "privapp-permissions": { 1237 if (allowPrivappPermissions) { 1238 // privapp permissions from system, apex, vendor, product and 1239 // system_ext partitions are stored separately. This is to 1240 // prevent xml files in the vendor partition from granting 1241 // permissions to priv apps in the system partition and vice versa. 1242 boolean vendor = permFile.toPath().startsWith( 1243 Environment.getVendorDirectory().toPath() + "/") 1244 || permFile.toPath().startsWith( 1245 Environment.getOdmDirectory().toPath() + "/"); 1246 boolean product = permFile.toPath().startsWith( 1247 Environment.getProductDirectory().toPath() + "/"); 1248 boolean systemExt = permFile.toPath().startsWith( 1249 Environment.getSystemExtDirectory().toPath() + "/"); 1250 boolean apex = permFile.toPath().startsWith( 1251 Environment.getApexDirectory().toPath() + "/") 1252 && ApexProperties.updatable().orElse(false); 1253 if (vendor) { 1254 readPrivAppPermissions(parser, mVendorPrivAppPermissions, 1255 mVendorPrivAppDenyPermissions); 1256 } else if (product) { 1257 readPrivAppPermissions(parser, mProductPrivAppPermissions, 1258 mProductPrivAppDenyPermissions); 1259 } else if (systemExt) { 1260 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, 1261 mSystemExtPrivAppDenyPermissions); 1262 } else if (apex) { 1263 readApexPrivAppPermissions(parser, permFile, 1264 Environment.getApexDirectory().toPath()); 1265 } else { 1266 readPrivAppPermissions(parser, mPrivAppPermissions, 1267 mPrivAppDenyPermissions); 1268 } 1269 } else { 1270 logNotAllowedInPartition(name, permFile, parser); 1271 XmlUtils.skipCurrentTag(parser); 1272 } 1273 } break; 1274 case "oem-permissions": { 1275 if (allowOemPermissions) { 1276 readOemPermissions(parser); 1277 } else { 1278 logNotAllowedInPartition(name, permFile, parser); 1279 XmlUtils.skipCurrentTag(parser); 1280 } 1281 } break; 1282 case "hidden-api-whitelisted-app": { 1283 if (allowApiWhitelisting) { 1284 String pkgname = parser.getAttributeValue(null, "package"); 1285 if (pkgname == null) { 1286 Slog.w(TAG, "<" + name + "> without package in " 1287 + permFile + " at " + parser.getPositionDescription()); 1288 } else { 1289 mHiddenApiPackageWhitelist.add(pkgname); 1290 } 1291 } else { 1292 logNotAllowedInPartition(name, permFile, parser); 1293 } 1294 XmlUtils.skipCurrentTag(parser); 1295 } break; 1296 case "allow-association": { 1297 if (allowAssociations) { 1298 String target = parser.getAttributeValue(null, "target"); 1299 if (target == null) { 1300 Slog.w(TAG, "<" + name + "> without target in " + permFile 1301 + " at " + parser.getPositionDescription()); 1302 XmlUtils.skipCurrentTag(parser); 1303 break; 1304 } 1305 String allowed = parser.getAttributeValue(null, "allowed"); 1306 if (allowed == null) { 1307 Slog.w(TAG, "<" + name + "> without allowed in " + permFile 1308 + " at " + parser.getPositionDescription()); 1309 XmlUtils.skipCurrentTag(parser); 1310 break; 1311 } 1312 target = target.intern(); 1313 allowed = allowed.intern(); 1314 ArraySet<String> associations = mAllowedAssociations.get(target); 1315 if (associations == null) { 1316 associations = new ArraySet<>(); 1317 mAllowedAssociations.put(target, associations); 1318 } 1319 Slog.i(TAG, "Adding association: " + target + " <- " + allowed); 1320 associations.add(allowed); 1321 } else { 1322 logNotAllowedInPartition(name, permFile, parser); 1323 } 1324 XmlUtils.skipCurrentTag(parser); 1325 } break; 1326 case "app-data-isolation-whitelisted-app": { 1327 String pkgname = parser.getAttributeValue(null, "package"); 1328 if (pkgname == null) { 1329 Slog.w(TAG, "<" + name + "> without package in " + permFile 1330 + " at " + parser.getPositionDescription()); 1331 } else { 1332 mAppDataIsolationWhitelistedApps.add(pkgname); 1333 } 1334 XmlUtils.skipCurrentTag(parser); 1335 } break; 1336 case "bugreport-whitelisted": { 1337 String pkgname = parser.getAttributeValue(null, "package"); 1338 if (pkgname == null) { 1339 Slog.w(TAG, "<" + name + "> without package in " + permFile 1340 + " at " + parser.getPositionDescription()); 1341 } else { 1342 mBugreportWhitelistedPackages.add(pkgname); 1343 } 1344 XmlUtils.skipCurrentTag(parser); 1345 } break; 1346 case "install-in-user-type": { 1347 // NB: We allow any directory permission to declare install-in-user-type. 1348 readInstallInUserType(parser, 1349 mPackageToUserTypeWhitelist, mPackageToUserTypeBlacklist); 1350 } break; 1351 case "named-actor": { 1352 String namespace = TextUtils.safeIntern( 1353 parser.getAttributeValue(null, "namespace")); 1354 String actorName = parser.getAttributeValue(null, "name"); 1355 String pkgName = TextUtils.safeIntern( 1356 parser.getAttributeValue(null, "package")); 1357 if (TextUtils.isEmpty(namespace)) { 1358 Slog.wtf(TAG, "<" + name + "> without namespace in " + permFile 1359 + " at " + parser.getPositionDescription()); 1360 } else if (TextUtils.isEmpty(actorName)) { 1361 Slog.wtf(TAG, "<" + name + "> without actor name in " + permFile 1362 + " at " + parser.getPositionDescription()); 1363 } else if (TextUtils.isEmpty(pkgName)) { 1364 Slog.wtf(TAG, "<" + name + "> without package name in " + permFile 1365 + " at " + parser.getPositionDescription()); 1366 } else if ("android".equalsIgnoreCase(namespace)) { 1367 throw new IllegalStateException("Defining " + actorName + " as " 1368 + pkgName + " for the android namespace is not allowed"); 1369 } else { 1370 if (mNamedActors == null) { 1371 mNamedActors = new ArrayMap<>(); 1372 } 1373 1374 Map<String, String> nameToPkgMap = mNamedActors.get(namespace); 1375 if (nameToPkgMap == null) { 1376 nameToPkgMap = new ArrayMap<>(); 1377 mNamedActors.put(namespace, nameToPkgMap); 1378 } else if (nameToPkgMap.containsKey(actorName)) { 1379 String existing = nameToPkgMap.get(actorName); 1380 throw new IllegalStateException("Duplicate actor definition for " 1381 + namespace + "/" + actorName 1382 + "; defined as both " + existing + " and " + pkgName); 1383 } 1384 1385 nameToPkgMap.put(actorName, pkgName); 1386 } 1387 XmlUtils.skipCurrentTag(parser); 1388 } break; 1389 case "overlay-config-signature": { 1390 if (allowAll) { 1391 String pkgName = parser.getAttributeValue(null, "package"); 1392 if (pkgName == null) { 1393 Slog.w(TAG, "<" + name + "> without package in " + permFile 1394 + " at " + parser.getPositionDescription()); 1395 } else { 1396 if (TextUtils.isEmpty(mOverlayConfigSignaturePackage)) { 1397 mOverlayConfigSignaturePackage = pkgName.intern(); 1398 } else { 1399 throw new IllegalStateException("Reference signature package " 1400 + "defined as both " 1401 + mOverlayConfigSignaturePackage 1402 + " and " + pkgName); 1403 } 1404 } 1405 } else { 1406 logNotAllowedInPartition(name, permFile, parser); 1407 } 1408 XmlUtils.skipCurrentTag(parser); 1409 } break; 1410 case "rollback-whitelisted-app": { 1411 String pkgname = parser.getAttributeValue(null, "package"); 1412 if (pkgname == null) { 1413 Slog.w(TAG, "<" + name + "> without package in " + permFile 1414 + " at " + parser.getPositionDescription()); 1415 } else { 1416 mRollbackWhitelistedPackages.add(pkgname); 1417 } 1418 XmlUtils.skipCurrentTag(parser); 1419 } break; 1420 case "whitelisted-staged-installer": { 1421 if (allowAppConfigs) { 1422 String pkgname = parser.getAttributeValue(null, "package"); 1423 boolean isModulesInstaller = XmlUtils.readBooleanAttribute( 1424 parser, "isModulesInstaller", false); 1425 if (pkgname == null) { 1426 Slog.w(TAG, "<" + name + "> without package in " + permFile 1427 + " at " + parser.getPositionDescription()); 1428 } else { 1429 mWhitelistedStagedInstallers.add(pkgname); 1430 } 1431 if (isModulesInstaller) { 1432 if (mModulesInstallerPackageName != null) { 1433 throw new IllegalStateException( 1434 "Multiple modules installers"); 1435 } 1436 mModulesInstallerPackageName = pkgname; 1437 } 1438 } else { 1439 logNotAllowedInPartition(name, permFile, parser); 1440 } 1441 XmlUtils.skipCurrentTag(parser); 1442 } break; 1443 case "allowed-vendor-apex": { 1444 if (allowVendorApex) { 1445 String pkgName = parser.getAttributeValue(null, "package"); 1446 String installerPkgName = parser.getAttributeValue( 1447 null, "installerPackage"); 1448 if (pkgName == null) { 1449 Slog.w(TAG, "<" + name + "> without package in " + permFile 1450 + " at " + parser.getPositionDescription()); 1451 } 1452 if (installerPkgName == null) { 1453 Slog.w(TAG, "<" + name + "> without installerPackage in " + permFile 1454 + " at " + parser.getPositionDescription()); 1455 } 1456 if (pkgName != null && installerPkgName != null) { 1457 mAllowedVendorApexes.put(pkgName, installerPkgName); 1458 } 1459 } else { 1460 logNotAllowedInPartition(name, permFile, parser); 1461 } 1462 XmlUtils.skipCurrentTag(parser); 1463 } break; 1464 case "install-constraints-allowed": { 1465 if (allowAppConfigs) { 1466 String packageName = parser.getAttributeValue(null, "package"); 1467 if (packageName == null) { 1468 Slog.w(TAG, "<" + name + "> without package in " + permFile 1469 + " at " + parser.getPositionDescription()); 1470 } else { 1471 mInstallConstraintsAllowlist.add(packageName); 1472 } 1473 } else { 1474 logNotAllowedInPartition(name, permFile, parser); 1475 } 1476 XmlUtils.skipCurrentTag(parser); 1477 } break; 1478 default: { 1479 Slog.w(TAG, "Tag " + name + " is unknown in " 1480 + permFile + " at " + parser.getPositionDescription()); 1481 XmlUtils.skipCurrentTag(parser); 1482 } break; 1483 } 1484 } 1485 } catch (XmlPullParserException e) { 1486 Slog.w(TAG, "Got exception parsing permissions.", e); 1487 } catch (IOException e) { 1488 Slog.w(TAG, "Got exception parsing permissions.", e); 1489 } finally { 1490 IoUtils.closeQuietly(permReader); 1491 } 1492 1493 // Some devices can be field-converted to FBE, so offer to splice in 1494 // those features if not already defined by the static config 1495 if (StorageManager.isFileEncryptedNativeOnly()) { 1496 addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0); 1497 addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0); 1498 } 1499 1500 // Help legacy devices that may not have updated their static config 1501 if (StorageManager.hasAdoptable()) { 1502 addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0); 1503 } 1504 1505 if (ActivityManager.isLowRamDeviceStatic()) { 1506 addFeature(PackageManager.FEATURE_RAM_LOW, 0); 1507 } else { 1508 addFeature(PackageManager.FEATURE_RAM_NORMAL, 0); 1509 } 1510 1511 final int incrementalVersion = IncrementalManager.getVersion(); 1512 if (incrementalVersion > 0) { 1513 addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, incrementalVersion); 1514 } 1515 1516 if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) { 1517 addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0); 1518 } 1519 1520 if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.Q) { 1521 addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0); 1522 } 1523 1524 if (isErofsSupported()) { 1525 if (isKernelVersionAtLeast(5, 10)) { 1526 addFeature(PackageManager.FEATURE_EROFS, 0); 1527 } else if (isKernelVersionAtLeast(4, 19)) { 1528 addFeature(PackageManager.FEATURE_EROFS_LEGACY, 0); 1529 } 1530 } 1531 1532 for (String featureName : mUnavailableFeatures) { 1533 removeFeature(featureName); 1534 } 1535 } 1536 addFeature(String name, int version)1537 private void addFeature(String name, int version) { 1538 FeatureInfo fi = mAvailableFeatures.get(name); 1539 if (fi == null) { 1540 fi = new FeatureInfo(); 1541 fi.name = name; 1542 fi.version = version; 1543 mAvailableFeatures.put(name, fi); 1544 } else { 1545 fi.version = Math.max(fi.version, version); 1546 } 1547 } 1548 removeFeature(String name)1549 private void removeFeature(String name) { 1550 if (mAvailableFeatures.remove(name) != null) { 1551 Slog.d(TAG, "Removed unavailable feature " + name); 1552 } 1553 } 1554 readPermission(XmlPullParser parser, String name)1555 void readPermission(XmlPullParser parser, String name) 1556 throws IOException, XmlPullParserException { 1557 if (mPermissions.containsKey(name)) { 1558 throw new IllegalStateException("Duplicate permission definition for " + name); 1559 } 1560 1561 final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); 1562 final PermissionEntry perm = new PermissionEntry(name, perUser); 1563 mPermissions.put(name, perm); 1564 1565 int outerDepth = parser.getDepth(); 1566 int type; 1567 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 1568 && (type != XmlPullParser.END_TAG 1569 || parser.getDepth() > outerDepth)) { 1570 if (type == XmlPullParser.END_TAG 1571 || type == XmlPullParser.TEXT) { 1572 continue; 1573 } 1574 1575 String tagName = parser.getName(); 1576 if ("group".equals(tagName)) { 1577 String gidStr = parser.getAttributeValue(null, "gid"); 1578 if (gidStr != null) { 1579 int gid = Process.getGidForName(gidStr); 1580 perm.gids = appendInt(perm.gids, gid); 1581 } else { 1582 Slog.w(TAG, "<group> without gid at " 1583 + parser.getPositionDescription()); 1584 } 1585 } 1586 XmlUtils.skipCurrentTag(parser); 1587 } 1588 } 1589 readPrivAppPermissions(XmlPullParser parser, ArrayMap<String, ArraySet<String>> grantMap, ArrayMap<String, ArraySet<String>> denyMap)1590 private void readPrivAppPermissions(XmlPullParser parser, 1591 ArrayMap<String, ArraySet<String>> grantMap, 1592 ArrayMap<String, ArraySet<String>> denyMap) 1593 throws IOException, XmlPullParserException { 1594 String packageName = parser.getAttributeValue(null, "package"); 1595 if (TextUtils.isEmpty(packageName)) { 1596 Slog.w(TAG, "package is required for <privapp-permissions> in " 1597 + parser.getPositionDescription()); 1598 return; 1599 } 1600 1601 ArraySet<String> permissions = grantMap.get(packageName); 1602 if (permissions == null) { 1603 permissions = new ArraySet<>(); 1604 } 1605 ArraySet<String> denyPermissions = denyMap.get(packageName); 1606 int depth = parser.getDepth(); 1607 while (XmlUtils.nextElementWithin(parser, depth)) { 1608 String name = parser.getName(); 1609 if ("permission".equals(name)) { 1610 String permName = parser.getAttributeValue(null, "name"); 1611 if (TextUtils.isEmpty(permName)) { 1612 Slog.w(TAG, "name is required for <permission> in " 1613 + parser.getPositionDescription()); 1614 continue; 1615 } 1616 permissions.add(permName); 1617 } else if ("deny-permission".equals(name)) { 1618 String permName = parser.getAttributeValue(null, "name"); 1619 if (TextUtils.isEmpty(permName)) { 1620 Slog.w(TAG, "name is required for <deny-permission> in " 1621 + parser.getPositionDescription()); 1622 continue; 1623 } 1624 if (denyPermissions == null) { 1625 denyPermissions = new ArraySet<>(); 1626 } 1627 denyPermissions.add(permName); 1628 } 1629 } 1630 grantMap.put(packageName, permissions); 1631 if (denyPermissions != null) { 1632 denyMap.put(packageName, denyPermissions); 1633 } 1634 } 1635 readInstallInUserType(XmlPullParser parser, Map<String, Set<String>> doInstallMap, Map<String, Set<String>> nonInstallMap)1636 private void readInstallInUserType(XmlPullParser parser, 1637 Map<String, Set<String>> doInstallMap, 1638 Map<String, Set<String>> nonInstallMap) 1639 throws IOException, XmlPullParserException { 1640 final String packageName = parser.getAttributeValue(null, "package"); 1641 if (TextUtils.isEmpty(packageName)) { 1642 Slog.w(TAG, "package is required for <install-in-user-type> in " 1643 + parser.getPositionDescription()); 1644 return; 1645 } 1646 1647 Set<String> userTypesYes = doInstallMap.get(packageName); 1648 Set<String> userTypesNo = nonInstallMap.get(packageName); 1649 final int depth = parser.getDepth(); 1650 while (XmlUtils.nextElementWithin(parser, depth)) { 1651 final String name = parser.getName(); 1652 if ("install-in".equals(name)) { 1653 final String userType = parser.getAttributeValue(null, "user-type"); 1654 if (TextUtils.isEmpty(userType)) { 1655 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1656 + parser.getPositionDescription()); 1657 continue; 1658 } 1659 if (userTypesYes == null) { 1660 userTypesYes = new ArraySet<>(); 1661 doInstallMap.put(packageName, userTypesYes); 1662 } 1663 userTypesYes.add(userType); 1664 } else if ("do-not-install-in".equals(name)) { 1665 final String userType = parser.getAttributeValue(null, "user-type"); 1666 if (TextUtils.isEmpty(userType)) { 1667 Slog.w(TAG, "user-type is required for <install-in-user-type> in " 1668 + parser.getPositionDescription()); 1669 continue; 1670 } 1671 if (userTypesNo == null) { 1672 userTypesNo = new ArraySet<>(); 1673 nonInstallMap.put(packageName, userTypesNo); 1674 } 1675 userTypesNo.add(userType); 1676 } else { 1677 Slog.w(TAG, "unrecognized tag in <install-in-user-type> in " 1678 + parser.getPositionDescription()); 1679 } 1680 } 1681 } 1682 readOemPermissions(XmlPullParser parser)1683 void readOemPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { 1684 final String packageName = parser.getAttributeValue(null, "package"); 1685 if (TextUtils.isEmpty(packageName)) { 1686 Slog.w(TAG, "package is required for <oem-permissions> in " 1687 + parser.getPositionDescription()); 1688 return; 1689 } 1690 1691 ArrayMap<String, Boolean> permissions = mOemPermissions.get(packageName); 1692 if (permissions == null) { 1693 permissions = new ArrayMap<>(); 1694 } 1695 final int depth = parser.getDepth(); 1696 while (XmlUtils.nextElementWithin(parser, depth)) { 1697 final String name = parser.getName(); 1698 if ("permission".equals(name)) { 1699 final String permName = parser.getAttributeValue(null, "name"); 1700 if (TextUtils.isEmpty(permName)) { 1701 Slog.w(TAG, "name is required for <permission> in " 1702 + parser.getPositionDescription()); 1703 continue; 1704 } 1705 permissions.put(permName, Boolean.TRUE); 1706 } else if ("deny-permission".equals(name)) { 1707 String permName = parser.getAttributeValue(null, "name"); 1708 if (TextUtils.isEmpty(permName)) { 1709 Slog.w(TAG, "name is required for <deny-permission> in " 1710 + parser.getPositionDescription()); 1711 continue; 1712 } 1713 permissions.put(permName, Boolean.FALSE); 1714 } 1715 } 1716 mOemPermissions.put(packageName, permissions); 1717 } 1718 readSplitPermission(XmlPullParser parser, File permFile)1719 private void readSplitPermission(XmlPullParser parser, File permFile) 1720 throws IOException, XmlPullParserException { 1721 String splitPerm = parser.getAttributeValue(null, "name"); 1722 if (splitPerm == null) { 1723 Slog.w(TAG, "<split-permission> without name in " + permFile + " at " 1724 + parser.getPositionDescription()); 1725 XmlUtils.skipCurrentTag(parser); 1726 return; 1727 } 1728 String targetSdkStr = parser.getAttributeValue(null, "targetSdk"); 1729 int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT + 1; 1730 if (!TextUtils.isEmpty(targetSdkStr)) { 1731 try { 1732 targetSdk = Integer.parseInt(targetSdkStr); 1733 } catch (NumberFormatException e) { 1734 Slog.w(TAG, "<split-permission> targetSdk not an integer in " + permFile + " at " 1735 + parser.getPositionDescription()); 1736 XmlUtils.skipCurrentTag(parser); 1737 return; 1738 } 1739 } 1740 final int depth = parser.getDepth(); 1741 List<String> newPermissions = new ArrayList<>(); 1742 while (XmlUtils.nextElementWithin(parser, depth)) { 1743 String name = parser.getName(); 1744 if ("new-permission".equals(name)) { 1745 final String newName = parser.getAttributeValue(null, "name"); 1746 if (TextUtils.isEmpty(newName)) { 1747 Slog.w(TAG, "name is required for <new-permission> in " 1748 + parser.getPositionDescription()); 1749 continue; 1750 } 1751 newPermissions.add(newName); 1752 } else { 1753 XmlUtils.skipCurrentTag(parser); 1754 } 1755 } 1756 if (!newPermissions.isEmpty()) { 1757 mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk)); 1758 } 1759 } 1760 readComponentOverrides(XmlPullParser parser, File permFile)1761 private void readComponentOverrides(XmlPullParser parser, File permFile) 1762 throws IOException, XmlPullParserException { 1763 String pkgname = parser.getAttributeValue(null, "package"); 1764 if (pkgname == null) { 1765 Slog.w(TAG, "<component-override> without package in " 1766 + permFile + " at " + parser.getPositionDescription()); 1767 return; 1768 } 1769 1770 pkgname = pkgname.intern(); 1771 1772 final int depth = parser.getDepth(); 1773 while (XmlUtils.nextElementWithin(parser, depth)) { 1774 if ("component".equals(parser.getName())) { 1775 String clsname = parser.getAttributeValue(null, "class"); 1776 String enabled = parser.getAttributeValue(null, "enabled"); 1777 if (clsname == null) { 1778 Slog.w(TAG, "<component> without class in " 1779 + permFile + " at " + parser.getPositionDescription()); 1780 return; 1781 } else if (enabled == null) { 1782 Slog.w(TAG, "<component> without enabled in " 1783 + permFile + " at " + parser.getPositionDescription()); 1784 return; 1785 } 1786 1787 if (clsname.startsWith(".")) { 1788 clsname = pkgname + clsname; 1789 } 1790 1791 clsname = clsname.intern(); 1792 1793 ArrayMap<String, Boolean> componentEnabledStates = 1794 mPackageComponentEnabledState.get(pkgname); 1795 if (componentEnabledStates == null) { 1796 componentEnabledStates = new ArrayMap<>(); 1797 mPackageComponentEnabledState.put(pkgname, 1798 componentEnabledStates); 1799 } 1800 1801 componentEnabledStates.put(clsname, !"false".equals(enabled)); 1802 } 1803 } 1804 } 1805 readPublicNativeLibrariesList()1806 private void readPublicNativeLibrariesList() { 1807 readPublicLibrariesListFile(new File("/vendor/etc/public.libraries.txt")); 1808 String[] dirs = {"/system/etc", "/system_ext/etc", "/product/etc"}; 1809 for (String dir : dirs) { 1810 File[] files = new File(dir).listFiles(); 1811 if (files == null) { 1812 Slog.w(TAG, "Public libraries file folder missing: " + dir); 1813 continue; 1814 } 1815 for (File f : files) { 1816 String name = f.getName(); 1817 if (name.startsWith("public.libraries-") && name.endsWith(".txt")) { 1818 readPublicLibrariesListFile(f); 1819 } 1820 } 1821 } 1822 } 1823 readPublicLibrariesListFile(File listFile)1824 private void readPublicLibrariesListFile(File listFile) { 1825 try (BufferedReader br = new BufferedReader(new FileReader(listFile))) { 1826 String line; 1827 while ((line = br.readLine()) != null) { 1828 if (line.isEmpty() || line.startsWith("#")) { 1829 continue; 1830 } 1831 // Line format is <soname> [abi]. We take the soname part. 1832 String soname = line.trim().split(" ")[0]; 1833 SharedLibraryEntry entry = new SharedLibraryEntry( 1834 soname, soname, new String[0], true); 1835 mSharedLibraries.put(entry.name, entry); 1836 } 1837 } catch (IOException e) { 1838 Slog.w(TAG, "Failed to read public libraries file " + listFile, e); 1839 } 1840 } 1841 1842 1843 /** 1844 * Returns the module name for a file in the apex module's partition. 1845 */ getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath)1846 private String getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath) { 1847 if (!path.startsWith(apexDirectoryPath)) { 1848 throw new IllegalArgumentException("File " + path + " is not part of an APEX."); 1849 } 1850 // File must be in <apex_directory>/<module_name>/[extra_paths/]<xml_file> 1851 if (path.getNameCount() <= (apexDirectoryPath.getNameCount() + 1)) { 1852 throw new IllegalArgumentException("File " + path + " is in the APEX partition," 1853 + " but not inside a module."); 1854 } 1855 return path.getName(apexDirectoryPath.getNameCount()).toString(); 1856 } 1857 1858 /** 1859 * Reads the contents of the privileged permission allowlist stored inside an APEX. 1860 */ 1861 @VisibleForTesting readApexPrivAppPermissions(XmlPullParser parser, File permFile, Path apexDirectoryPath)1862 public void readApexPrivAppPermissions(XmlPullParser parser, File permFile, 1863 Path apexDirectoryPath) throws IOException, XmlPullParserException { 1864 final String moduleName = 1865 getApexModuleNameFromFilePath(permFile.toPath(), apexDirectoryPath); 1866 final ArrayMap<String, ArraySet<String>> privAppPermissions; 1867 if (mApexPrivAppPermissions.containsKey(moduleName)) { 1868 privAppPermissions = mApexPrivAppPermissions.get(moduleName); 1869 } else { 1870 privAppPermissions = new ArrayMap<>(); 1871 mApexPrivAppPermissions.put(moduleName, privAppPermissions); 1872 } 1873 final ArrayMap<String, ArraySet<String>> privAppDenyPermissions; 1874 if (mApexPrivAppDenyPermissions.containsKey(moduleName)) { 1875 privAppDenyPermissions = mApexPrivAppDenyPermissions.get(moduleName); 1876 } else { 1877 privAppDenyPermissions = new ArrayMap<>(); 1878 mApexPrivAppDenyPermissions.put(moduleName, privAppDenyPermissions); 1879 } 1880 readPrivAppPermissions(parser, privAppPermissions, privAppDenyPermissions); 1881 } 1882 isSystemProcess()1883 private static boolean isSystemProcess() { 1884 return Process.myUid() == Process.SYSTEM_UID; 1885 } 1886 isErofsSupported()1887 private static boolean isErofsSupported() { 1888 try { 1889 final Path path = Paths.get("/sys/fs/erofs"); 1890 return Files.exists(path); 1891 } catch (Exception e) { 1892 return false; 1893 } 1894 } 1895 isKernelVersionAtLeast(int major, int minor)1896 private static boolean isKernelVersionAtLeast(int major, int minor) { 1897 final String kernelVersion = VintfRuntimeInfo.getKernelVersion(); 1898 final String[] parts = kernelVersion.split("\\."); 1899 if (parts.length < 2) { 1900 return false; 1901 } 1902 try { 1903 final int majorVersion = Integer.parseInt(parts[0]); 1904 final int minorVersion = Integer.parseInt(parts[1]); 1905 return majorVersion > major || (majorVersion == major && minorVersion >= minor); 1906 } catch (NumberFormatException e) { 1907 return false; 1908 } 1909 } 1910 } 1911