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