1 /* 2 * Copyright (C) 2017 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.pm.permission; 18 19 import static android.Manifest.permission.CAMERA; 20 import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD; 21 import static android.Manifest.permission.CAPTURE_AUDIO_OUTPUT; 22 import static android.Manifest.permission.RECORD_AUDIO; 23 import static android.Manifest.permission.UPDATE_APP_OPS_STATS; 24 import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; 25 import static android.app.AppOpsManager.ATTRIBUTION_FLAGS_NONE; 26 import static android.app.AppOpsManager.MODE_ALLOWED; 27 import static android.app.AppOpsManager.MODE_ERRORED; 28 import static android.app.AppOpsManager.MODE_IGNORED; 29 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED; 30 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED; 31 32 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 33 34 import android.Manifest; 35 import android.annotation.AppIdInt; 36 import android.annotation.NonNull; 37 import android.annotation.Nullable; 38 import android.annotation.UserIdInt; 39 import android.app.ActivityManager; 40 import android.app.AppOpsManager; 41 import android.app.AppOpsManager.AttributionFlags; 42 import android.app.IActivityManager; 43 import android.content.AttributionSource; 44 import android.content.AttributionSourceState; 45 import android.content.Context; 46 import android.content.PermissionChecker; 47 import android.content.pm.FeatureInfo; 48 import android.content.pm.PackageManager; 49 import android.content.pm.PackageManagerInternal; 50 import android.content.pm.ParceledListSlice; 51 import android.content.pm.PermissionGroupInfo; 52 import android.content.pm.PermissionInfo; 53 import android.content.pm.permission.SplitPermissionInfoParcelable; 54 import android.health.connect.HealthConnectManager; 55 import android.os.Binder; 56 import android.os.IBinder; 57 import android.os.Process; 58 import android.os.RemoteException; 59 import android.os.ServiceManager; 60 import android.os.UserHandle; 61 import android.permission.IOnPermissionsChangeListener; 62 import android.permission.IPermissionChecker; 63 import android.permission.IPermissionManager; 64 import android.permission.PermissionCheckerManager; 65 import android.permission.PermissionManager; 66 import android.permission.PermissionManagerInternal; 67 import android.service.voice.VoiceInteractionManagerInternal; 68 import android.util.ArrayMap; 69 import android.util.Slog; 70 import android.util.SparseArray; 71 72 import com.android.internal.annotations.GuardedBy; 73 import com.android.internal.util.Preconditions; 74 import com.android.internal.util.function.TriFunction; 75 import com.android.server.LocalServices; 76 import com.android.server.pm.UserManagerInternal; 77 import com.android.server.pm.UserManagerService; 78 import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider; 79 import com.android.server.pm.pkg.AndroidPackage; 80 import com.android.server.pm.pkg.PackageState; 81 82 import java.util.ArrayList; 83 import java.util.Collections; 84 import java.util.List; 85 import java.util.Map; 86 import java.util.NoSuchElementException; 87 import java.util.Objects; 88 import java.util.Set; 89 import java.util.WeakHashMap; 90 import java.util.concurrent.ConcurrentHashMap; 91 import java.util.concurrent.atomic.AtomicBoolean; 92 import java.util.concurrent.atomic.AtomicInteger; 93 import java.util.function.BiFunction; 94 95 /** 96 * Manages all permissions and handles permissions related tasks. 97 */ 98 public class PermissionManagerService extends IPermissionManager.Stub { 99 100 private static final String LOG_TAG = PermissionManagerService.class.getSimpleName(); 101 102 /** Map of IBinder -> Running AttributionSource */ 103 private static final ConcurrentHashMap<IBinder, RegisteredAttribution> 104 sRunningAttributionSources = new ConcurrentHashMap<>(); 105 106 /** Lock to protect internal data access */ 107 private final Object mLock = new Object(); 108 109 /** Internal connection to the package manager */ 110 private final PackageManagerInternal mPackageManagerInt; 111 112 /** Internal connection to the user manager */ 113 private final UserManagerInternal mUserManagerInt; 114 115 /** Map of OneTimePermissionUserManagers keyed by userId */ 116 @GuardedBy("mLock") 117 @NonNull 118 private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers = 119 new SparseArray<>(); 120 121 /** App ops manager */ 122 private final AppOpsManager mAppOpsManager; 123 124 private final Context mContext; 125 private final PermissionManagerServiceInterface mPermissionManagerServiceImpl; 126 127 @NonNull 128 private final AttributionSourceRegistry mAttributionSourceRegistry; 129 130 @GuardedBy("mLock") 131 private CheckPermissionDelegate mCheckPermissionDelegate; 132 133 @Nullable 134 private HotwordDetectionServiceProvider mHotwordDetectionServiceProvider; 135 PermissionManagerService(@onNull Context context, @NonNull ArrayMap<String, FeatureInfo> availableFeatures)136 PermissionManagerService(@NonNull Context context, 137 @NonNull ArrayMap<String, FeatureInfo> availableFeatures) { 138 // The package info cache is the cache for package and permission information. 139 // Disable the package info and package permission caches locally but leave the 140 // checkPermission cache active. 141 PackageManager.invalidatePackageInfoCache(); 142 PermissionManager.disablePackageNamePermissionCache(); 143 144 mContext = context; 145 mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class); 146 mUserManagerInt = LocalServices.getService(UserManagerInternal.class); 147 mAppOpsManager = context.getSystemService(AppOpsManager.class); 148 149 mAttributionSourceRegistry = new AttributionSourceRegistry(context); 150 151 PermissionManagerServiceInternalImpl localService = 152 new PermissionManagerServiceInternalImpl(); 153 LocalServices.addService(PermissionManagerServiceInternal.class, localService); 154 LocalServices.addService(PermissionManagerInternal.class, localService); 155 156 mPermissionManagerServiceImpl = new PermissionManagerServiceImpl(context, 157 availableFeatures); 158 //mPermissionManagerServiceImpl = new PermissionManagerServiceLoggingDecorator( 159 // LocalServices.getService(PermissionManagerServiceInterface.class)); 160 } 161 162 /** 163 * Creates and returns an initialized, internal service for use by other components. 164 * <p> 165 * The object returned is identical to the one returned by the LocalServices class using: 166 * {@code LocalServices.getService(PermissionManagerServiceInternal.class);} 167 * <p> 168 * NOTE: The external lock is temporary and should be removed. This needs to be a 169 * lock created by the permission manager itself. 170 */ 171 @NonNull create(@onNull Context context, ArrayMap<String, FeatureInfo> availableFeatures)172 public static PermissionManagerServiceInternal create(@NonNull Context context, 173 ArrayMap<String, FeatureInfo> availableFeatures) { 174 final PermissionManagerServiceInternal permMgrInt = 175 LocalServices.getService(PermissionManagerServiceInternal.class); 176 if (permMgrInt != null) { 177 return permMgrInt; 178 } 179 PermissionManagerService permissionService = 180 (PermissionManagerService) ServiceManager.getService("permissionmgr"); 181 if (permissionService == null) { 182 permissionService = new PermissionManagerService(context, availableFeatures); 183 ServiceManager.addService("permissionmgr", permissionService); 184 ServiceManager.addService("permission_checker", new PermissionCheckerService(context)); 185 } 186 return LocalServices.getService(PermissionManagerServiceInternal.class); 187 } 188 189 /** 190 * TODO: theianchen we want to remove this method in the future. 191 * There's a complete copy of this method in PermissionManagerServiceImpl 192 * 193 * This method should typically only be used when granting or revoking 194 * permissions, since the app may immediately restart after this call. 195 * <p> 196 * If you're doing surgery on app code/data, use {@link PackageFreezer} to 197 * guard your work against the app being relaunched. 198 */ killUid(int appId, int userId, String reason)199 public static void killUid(int appId, int userId, String reason) { 200 final long identity = Binder.clearCallingIdentity(); 201 try { 202 IActivityManager am = ActivityManager.getService(); 203 if (am != null) { 204 try { 205 am.killUidForPermissionChange(appId, userId, reason); 206 } catch (RemoteException e) { 207 /* ignore - same process */ 208 } 209 } 210 } finally { 211 Binder.restoreCallingIdentity(identity); 212 } 213 } 214 checkPermission(String pkgName, String permName, @UserIdInt int userId)215 private int checkPermission(String pkgName, String permName, @UserIdInt int userId) { 216 // Not using Objects.requireNonNull() here for compatibility reasons. 217 if (pkgName == null || permName == null) { 218 return PackageManager.PERMISSION_DENIED; 219 } 220 221 final CheckPermissionDelegate checkPermissionDelegate; 222 synchronized (mLock) { 223 checkPermissionDelegate = mCheckPermissionDelegate; 224 } 225 226 if (checkPermissionDelegate == null) { 227 return mPermissionManagerServiceImpl.checkPermission(pkgName, permName, userId); 228 } 229 return checkPermissionDelegate.checkPermission(pkgName, permName, userId, 230 mPermissionManagerServiceImpl::checkPermission); 231 } 232 checkUidPermission(int uid, String permName)233 private int checkUidPermission(int uid, String permName) { 234 // Not using Objects.requireNonNull() here for compatibility reasons. 235 if (permName == null) { 236 return PackageManager.PERMISSION_DENIED; 237 } 238 239 final CheckPermissionDelegate checkPermissionDelegate; 240 synchronized (mLock) { 241 checkPermissionDelegate = mCheckPermissionDelegate; 242 } 243 244 if (checkPermissionDelegate == null) { 245 return mPermissionManagerServiceImpl.checkUidPermission(uid, permName); 246 } 247 return checkPermissionDelegate.checkUidPermission(uid, permName, 248 mPermissionManagerServiceImpl::checkUidPermission); 249 } 250 251 @Override setAutoRevokeExempted( @onNull String packageName, boolean exempted, int userId)252 public boolean setAutoRevokeExempted( 253 @NonNull String packageName, boolean exempted, int userId) { 254 Objects.requireNonNull(packageName); 255 256 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); 257 final int callingUid = Binder.getCallingUid(); 258 259 if (!checkAutoRevokeAccess(pkg, callingUid)) { 260 return false; 261 } 262 263 return setAutoRevokeExemptedInternal(pkg, exempted, userId); 264 } 265 setAutoRevokeExemptedInternal(@onNull AndroidPackage pkg, boolean exempted, @UserIdInt int userId)266 private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted, 267 @UserIdInt int userId) { 268 final int packageUid = UserHandle.getUid(userId, pkg.getUid()); 269 if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER, 270 packageUid, pkg.getPackageName()) != MODE_ALLOWED) { 271 // Allowlist user set - don't override 272 return false; 273 } 274 275 final long identity = Binder.clearCallingIdentity(); 276 try { 277 mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid, 278 pkg.getPackageName(), exempted ? MODE_IGNORED : MODE_ALLOWED); 279 } finally { 280 Binder.restoreCallingIdentity(identity); 281 } 282 return true; 283 } 284 checkAutoRevokeAccess(AndroidPackage pkg, int callingUid)285 private boolean checkAutoRevokeAccess(AndroidPackage pkg, int callingUid) { 286 final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission( 287 Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS) 288 == PackageManager.PERMISSION_GRANTED; 289 final boolean isCallerInstallerOnRecord = 290 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid); 291 292 if (!isCallerPrivileged && !isCallerInstallerOnRecord) { 293 throw new SecurityException("Caller must either hold " 294 + Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS 295 + " or be the installer on record"); 296 } 297 298 if (pkg == null || mPackageManagerInt.filterAppAccess(pkg, callingUid, 299 UserHandle.getUserId(callingUid))) { 300 return false; 301 } 302 303 return true; 304 } 305 306 @Override isAutoRevokeExempted(@onNull String packageName, int userId)307 public boolean isAutoRevokeExempted(@NonNull String packageName, int userId) { 308 Objects.requireNonNull(packageName); 309 310 final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); 311 final int callingUid = Binder.getCallingUid(); 312 313 if (!checkAutoRevokeAccess(pkg, callingUid)) { 314 return false; 315 } 316 317 final int packageUid = UserHandle.getUid(userId, pkg.getUid()); 318 319 final long identity = Binder.clearCallingIdentity(); 320 try { 321 return mAppOpsManager.checkOpNoThrow( 322 AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid, packageName) 323 == MODE_IGNORED; 324 } finally { 325 Binder.restoreCallingIdentity(identity); 326 } 327 } 328 startShellPermissionIdentityDelegationInternal(int uid, @NonNull String packageName, @Nullable List<String> permissionNames)329 private void startShellPermissionIdentityDelegationInternal(int uid, 330 @NonNull String packageName, @Nullable List<String> permissionNames) { 331 synchronized (mLock) { 332 final CheckPermissionDelegate oldDelegate = mCheckPermissionDelegate; 333 if (oldDelegate != null && oldDelegate.getDelegatedUid() != uid) { 334 throw new SecurityException( 335 "Shell can delegate permissions only to one UID at a time"); 336 } 337 final ShellDelegate delegate = new ShellDelegate(uid, packageName, permissionNames); 338 setCheckPermissionDelegateLocked(delegate); 339 } 340 } 341 stopShellPermissionIdentityDelegationInternal()342 private void stopShellPermissionIdentityDelegationInternal() { 343 synchronized (mLock) { 344 setCheckPermissionDelegateLocked(null); 345 } 346 } 347 348 @Nullable getDelegatedShellPermissionsInternal()349 private List<String> getDelegatedShellPermissionsInternal() { 350 synchronized (mLock) { 351 if (mCheckPermissionDelegate == null) { 352 return Collections.EMPTY_LIST; 353 } 354 return mCheckPermissionDelegate.getDelegatedPermissionNames(); 355 } 356 } 357 setCheckPermissionDelegateLocked(@ullable CheckPermissionDelegate delegate)358 private void setCheckPermissionDelegateLocked(@Nullable CheckPermissionDelegate delegate) { 359 if (delegate != null || mCheckPermissionDelegate != null) { 360 PackageManager.invalidatePackageInfoCache(); 361 } 362 mCheckPermissionDelegate = delegate; 363 } 364 365 @NonNull getOneTimePermissionUserManager(@serIdInt int userId)366 private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) { 367 OneTimePermissionUserManager oneTimePermissionUserManager; 368 synchronized (mLock) { 369 oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId); 370 if (oneTimePermissionUserManager != null) { 371 return oneTimePermissionUserManager; 372 } 373 } 374 // We cannot create a new instance of OneTimePermissionUserManager while holding our own 375 // lock, which may lead to a deadlock with the package manager lock. So we do it in a 376 // retry-like way, and just discard the newly created instance if someone else managed to be 377 // a little bit faster than us when we dropped our own lock. 378 final OneTimePermissionUserManager newOneTimePermissionUserManager = 379 new OneTimePermissionUserManager(mContext.createContextAsUser(UserHandle.of(userId), 380 /*flags*/ 0)); 381 synchronized (mLock) { 382 oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId); 383 if (oneTimePermissionUserManager != null) { 384 return oneTimePermissionUserManager; 385 } 386 oneTimePermissionUserManager = newOneTimePermissionUserManager; 387 mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager); 388 } 389 oneTimePermissionUserManager.registerUninstallListener(); 390 return oneTimePermissionUserManager; 391 } 392 393 @Override startOneTimePermissionSession(String packageName, @UserIdInt int userId, long timeoutMillis, long revokeAfterKilledDelayMillis)394 public void startOneTimePermissionSession(String packageName, @UserIdInt int userId, 395 long timeoutMillis, long revokeAfterKilledDelayMillis) { 396 mContext.enforceCallingOrSelfPermission( 397 Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, 398 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS 399 + " to register permissions as one time."); 400 Objects.requireNonNull(packageName); 401 402 final long token = Binder.clearCallingIdentity(); 403 try { 404 getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName, 405 timeoutMillis, revokeAfterKilledDelayMillis); 406 } finally { 407 Binder.restoreCallingIdentity(token); 408 } 409 } 410 411 @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) 412 @Override stopOneTimePermissionSession(String packageName, @UserIdInt int userId)413 public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) { 414 super.stopOneTimePermissionSession_enforcePermission(); 415 416 Objects.requireNonNull(packageName); 417 418 final long token = Binder.clearCallingIdentity(); 419 try { 420 getOneTimePermissionUserManager(userId).stopPackageOneTimeSession(packageName); 421 } finally { 422 Binder.restoreCallingIdentity(token); 423 } 424 } 425 426 @Override registerAttributionSource(@onNull AttributionSourceState source)427 public void registerAttributionSource(@NonNull AttributionSourceState source) { 428 mAttributionSourceRegistry 429 .registerAttributionSource(new AttributionSource(source)); 430 } 431 432 @Override isRegisteredAttributionSource(@onNull AttributionSourceState source)433 public boolean isRegisteredAttributionSource(@NonNull AttributionSourceState source) { 434 return mAttributionSourceRegistry 435 .isRegisteredAttributionSource(new AttributionSource(source)); 436 } 437 438 @Override getAutoRevokeExemptionRequestedPackages(int userId)439 public List<String> getAutoRevokeExemptionRequestedPackages(int userId) { 440 return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId); 441 } 442 443 @Override getAutoRevokeExemptionGrantedPackages(int userId)444 public List<String> getAutoRevokeExemptionGrantedPackages(int userId) { 445 return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISALLOWED, userId); 446 } 447 448 @NonNull getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId)449 private List<String> getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId) { 450 mContext.enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 451 "Must hold " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY); 452 453 List<String> result = new ArrayList<>(); 454 mPackageManagerInt.forEachInstalledPackage(pkg -> { 455 if (pkg.getAutoRevokePermissions() == autoRevokePolicy) { 456 result.add(pkg.getPackageName()); 457 } 458 }, userId); 459 return result; 460 } 461 462 /* Start of delegate methods to PermissionManagerServiceInterface */ 463 464 @Override getAllPermissionGroups(int flags)465 public ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) { 466 return new ParceledListSlice<>(mPermissionManagerServiceImpl.getAllPermissionGroups(flags)); 467 } 468 469 @Override getPermissionGroupInfo(String groupName, int flags)470 public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) { 471 return mPermissionManagerServiceImpl.getPermissionGroupInfo(groupName, flags); 472 } 473 474 @Override getPermissionInfo(String permissionName, String packageName, int flags)475 public PermissionInfo getPermissionInfo(String permissionName, String packageName, int flags) { 476 return mPermissionManagerServiceImpl.getPermissionInfo(permissionName, flags, packageName); 477 } 478 479 @Override queryPermissionsByGroup(String groupName, int flags)480 public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) { 481 List<PermissionInfo> permissionInfo = 482 mPermissionManagerServiceImpl.queryPermissionsByGroup(groupName, flags); 483 if (permissionInfo == null) { 484 return null; 485 } 486 487 return new ParceledListSlice<>(permissionInfo); 488 } 489 490 @Override addPermission(PermissionInfo permissionInfo, boolean async)491 public boolean addPermission(PermissionInfo permissionInfo, boolean async) { 492 return mPermissionManagerServiceImpl.addPermission(permissionInfo, async); 493 } 494 495 @Override removePermission(String permissionName)496 public void removePermission(String permissionName) { 497 mPermissionManagerServiceImpl.removePermission(permissionName); 498 } 499 500 @Override getPermissionFlags(String packageName, String permissionName, int userId)501 public int getPermissionFlags(String packageName, String permissionName, int userId) { 502 return mPermissionManagerServiceImpl 503 .getPermissionFlags(packageName, permissionName, userId); 504 } 505 506 @Override updatePermissionFlags(String packageName, String permissionName, int flagMask, int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)507 public void updatePermissionFlags(String packageName, String permissionName, int flagMask, 508 int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) { 509 mPermissionManagerServiceImpl.updatePermissionFlags(packageName, permissionName, flagMask, 510 flagValues, checkAdjustPolicyFlagPermission, userId); 511 } 512 513 @Override updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId)514 public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) { 515 mPermissionManagerServiceImpl.updatePermissionFlagsForAllApps(flagMask, flagValues, userId); 516 } 517 518 @Override addOnPermissionsChangeListener(IOnPermissionsChangeListener listener)519 public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { 520 mPermissionManagerServiceImpl.addOnPermissionsChangeListener(listener); 521 } 522 523 @Override removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener)524 public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { 525 mPermissionManagerServiceImpl.removeOnPermissionsChangeListener(listener); 526 } 527 528 @Override getAllowlistedRestrictedPermissions(String packageName, int flags, int userId)529 public List<String> getAllowlistedRestrictedPermissions(String packageName, 530 int flags, int userId) { 531 return mPermissionManagerServiceImpl.getAllowlistedRestrictedPermissions(packageName, 532 flags, userId); 533 } 534 535 @Override addAllowlistedRestrictedPermission(String packageName, String permissionName, int flags, int userId)536 public boolean addAllowlistedRestrictedPermission(String packageName, String permissionName, 537 int flags, int userId) { 538 return mPermissionManagerServiceImpl.addAllowlistedRestrictedPermission(packageName, 539 permissionName, flags, userId); 540 } 541 542 @Override removeAllowlistedRestrictedPermission(String packageName, String permissionName, int flags, int userId)543 public boolean removeAllowlistedRestrictedPermission(String packageName, String permissionName, 544 int flags, int userId) { 545 return mPermissionManagerServiceImpl.removeAllowlistedRestrictedPermission(packageName, 546 permissionName, flags, userId); 547 } 548 549 @Override grantRuntimePermission(String packageName, String permissionName, int userId)550 public void grantRuntimePermission(String packageName, String permissionName, int userId) { 551 mPermissionManagerServiceImpl.grantRuntimePermission(packageName, permissionName, userId); 552 } 553 554 @Override revokeRuntimePermission(String packageName, String permissionName, int userId, String reason)555 public void revokeRuntimePermission(String packageName, String permissionName, int userId, 556 String reason) { 557 mPermissionManagerServiceImpl.revokeRuntimePermission(packageName, permissionName, userId, 558 reason); 559 } 560 561 @Override revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId)562 public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) { 563 mPermissionManagerServiceImpl.revokePostNotificationPermissionWithoutKillForTest( 564 packageName, userId); 565 } 566 567 @Override shouldShowRequestPermissionRationale(String packageName, String permissionName, int userId)568 public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName, 569 int userId) { 570 return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName, 571 permissionName, userId); 572 } 573 574 @Override isPermissionRevokedByPolicy(String packageName, String permissionName, int userId)575 public boolean isPermissionRevokedByPolicy(String packageName, String permissionName, 576 int userId) { 577 return mPermissionManagerServiceImpl 578 .isPermissionRevokedByPolicy(packageName, permissionName, userId); 579 } 580 581 @Override getSplitPermissions()582 public List<SplitPermissionInfoParcelable> getSplitPermissions() { 583 return mPermissionManagerServiceImpl.getSplitPermissions(); 584 } 585 586 /* End of delegate methods to PermissionManagerServiceInterface */ 587 588 private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal { 589 @Override checkPermission(@onNull String packageName, @NonNull String permissionName, @UserIdInt int userId)590 public int checkPermission(@NonNull String packageName, @NonNull String permissionName, 591 @UserIdInt int userId) { 592 return PermissionManagerService.this.checkPermission(packageName, permissionName, 593 userId); 594 } 595 596 @Override checkUidPermission(int uid, @NonNull String permissionName)597 public int checkUidPermission(int uid, @NonNull String permissionName) { 598 return PermissionManagerService.this.checkUidPermission(uid, permissionName); 599 } 600 601 @Override startShellPermissionIdentityDelegation(int uid, @NonNull String packageName, @Nullable List<String> permissionNames)602 public void startShellPermissionIdentityDelegation(int uid, @NonNull String packageName, 603 @Nullable List<String> permissionNames) { 604 Objects.requireNonNull(packageName, "packageName"); 605 startShellPermissionIdentityDelegationInternal(uid, packageName, permissionNames); 606 } 607 608 @Override stopShellPermissionIdentityDelegation()609 public void stopShellPermissionIdentityDelegation() { 610 stopShellPermissionIdentityDelegationInternal(); 611 } 612 613 @Override 614 @NonNull getDelegatedShellPermissions()615 public List<String> getDelegatedShellPermissions() { 616 return getDelegatedShellPermissionsInternal(); 617 } 618 619 @Override setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider)620 public void setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider) { 621 mHotwordDetectionServiceProvider = provider; 622 } 623 624 @Override getHotwordDetectionServiceProvider()625 public HotwordDetectionServiceProvider getHotwordDetectionServiceProvider() { 626 return mHotwordDetectionServiceProvider; 627 } 628 629 /* Start of delegate methods to PermissionManagerServiceInterface */ 630 631 @NonNull 632 @Override getGidsForUid(int uid)633 public int[] getGidsForUid(int uid) { 634 return mPermissionManagerServiceImpl.getGidsForUid(uid); 635 } 636 637 @NonNull 638 @Override getAllAppOpPermissionPackages()639 public Map<String, Set<String>> getAllAppOpPermissionPackages() { 640 return mPermissionManagerServiceImpl.getAllAppOpPermissionPackages(); 641 } 642 643 @Override onUserCreated(@serIdInt int userId)644 public void onUserCreated(@UserIdInt int userId) { 645 mPermissionManagerServiceImpl.onUserCreated(userId); 646 } 647 648 @NonNull 649 @Override getLegacyPermissions()650 public List<LegacyPermission> getLegacyPermissions() { 651 return mPermissionManagerServiceImpl.getLegacyPermissions(); 652 } 653 654 @NonNull 655 @Override getLegacyPermissionState(@ppIdInt int appId)656 public LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) { 657 return mPermissionManagerServiceImpl.getLegacyPermissionState(appId); 658 } 659 660 @Nullable 661 @Override backupRuntimePermissions(@serIdInt int userId)662 public byte[] backupRuntimePermissions(@UserIdInt int userId) { 663 return mPermissionManagerServiceImpl.backupRuntimePermissions(userId); 664 } 665 666 @Override restoreRuntimePermissions(@onNull byte[] backup, @UserIdInt int userId)667 public void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) { 668 mPermissionManagerServiceImpl.restoreRuntimePermissions(backup, userId); 669 } 670 671 @Override restoreDelayedRuntimePermissions(@onNull String packageName, @UserIdInt int userId)672 public void restoreDelayedRuntimePermissions(@NonNull String packageName, 673 @UserIdInt int userId) { 674 mPermissionManagerServiceImpl.restoreDelayedRuntimePermissions(packageName, userId); 675 } 676 677 @Override readLegacyPermissionsTEMP( @onNull LegacyPermissionSettings legacyPermissionSettings)678 public void readLegacyPermissionsTEMP( 679 @NonNull LegacyPermissionSettings legacyPermissionSettings) { 680 mPermissionManagerServiceImpl.readLegacyPermissionsTEMP(legacyPermissionSettings); 681 } 682 683 @Override writeLegacyPermissionsTEMP( @onNull LegacyPermissionSettings legacyPermissionSettings)684 public void writeLegacyPermissionsTEMP( 685 @NonNull LegacyPermissionSettings legacyPermissionSettings) { 686 mPermissionManagerServiceImpl.writeLegacyPermissionsTEMP(legacyPermissionSettings); 687 } 688 689 @Override onPackageAdded(@onNull PackageState packageState, boolean isInstantApp, @Nullable AndroidPackage oldPkg)690 public void onPackageAdded(@NonNull PackageState packageState, boolean isInstantApp, 691 @Nullable AndroidPackage oldPkg) { 692 mPermissionManagerServiceImpl.onPackageAdded(packageState, isInstantApp, oldPkg); 693 } 694 695 @Override onPackageInstalled(@onNull AndroidPackage pkg, int previousAppId, @NonNull PackageInstalledParams params, @UserIdInt int rawUserId)696 public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId, 697 @NonNull PackageInstalledParams params, @UserIdInt int rawUserId) { 698 Objects.requireNonNull(pkg, "pkg"); 699 Objects.requireNonNull(params, "params"); 700 Preconditions.checkArgument(rawUserId >= UserHandle.USER_SYSTEM 701 || rawUserId == UserHandle.USER_ALL, "userId"); 702 703 mPermissionManagerServiceImpl.onPackageInstalled(pkg, previousAppId, params, rawUserId); 704 final int[] userIds = rawUserId == UserHandle.USER_ALL ? getAllUserIds() 705 : new int[] { rawUserId }; 706 for (final int userId : userIds) { 707 final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode(); 708 if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED 709 || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) { 710 setAutoRevokeExemptedInternal(pkg, 711 autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId); 712 } 713 } 714 } 715 716 @Override onPackageRemoved(@onNull AndroidPackage pkg)717 public void onPackageRemoved(@NonNull AndroidPackage pkg) { 718 mPermissionManagerServiceImpl.onPackageRemoved(pkg); 719 } 720 721 @Override onPackageUninstalled(@onNull String packageName, int appId, @NonNull PackageState packageState, @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId)722 public void onPackageUninstalled(@NonNull String packageName, int appId, 723 @NonNull PackageState packageState, @Nullable AndroidPackage pkg, 724 @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId) { 725 mPermissionManagerServiceImpl.onPackageUninstalled(packageName, appId, packageState, 726 pkg, sharedUserPkgs, userId); 727 } 728 729 @Override addOnRuntimePermissionStateChangedListener( OnRuntimePermissionStateChangedListener listener)730 public void addOnRuntimePermissionStateChangedListener( 731 OnRuntimePermissionStateChangedListener listener) { 732 mPermissionManagerServiceImpl.addOnRuntimePermissionStateChangedListener(listener); 733 } 734 735 @Override removeOnRuntimePermissionStateChangedListener( OnRuntimePermissionStateChangedListener listener)736 public void removeOnRuntimePermissionStateChangedListener( 737 OnRuntimePermissionStateChangedListener listener) { 738 mPermissionManagerServiceImpl.removeOnRuntimePermissionStateChangedListener(listener); 739 } 740 741 @Override onSystemReady()742 public void onSystemReady() { 743 mPermissionManagerServiceImpl.onSystemReady(); 744 } 745 746 @Override isPermissionsReviewRequired(@onNull String packageName, @UserIdInt int userId)747 public boolean isPermissionsReviewRequired(@NonNull String packageName, 748 @UserIdInt int userId) { 749 return mPermissionManagerServiceImpl.isPermissionsReviewRequired(packageName, userId); 750 } 751 752 @Override readLegacyPermissionStateTEMP()753 public void readLegacyPermissionStateTEMP() { 754 mPermissionManagerServiceImpl.readLegacyPermissionStateTEMP(); 755 } 756 @Override writeLegacyPermissionStateTEMP()757 public void writeLegacyPermissionStateTEMP() { 758 mPermissionManagerServiceImpl.writeLegacyPermissionStateTEMP(); 759 } 760 @Override onUserRemoved(@serIdInt int userId)761 public void onUserRemoved(@UserIdInt int userId) { 762 mPermissionManagerServiceImpl.onUserRemoved(userId); 763 } 764 @NonNull 765 @Override getInstalledPermissions(@onNull String packageName)766 public Set<String> getInstalledPermissions(@NonNull String packageName) { 767 return mPermissionManagerServiceImpl.getInstalledPermissions(packageName); 768 } 769 @NonNull 770 @Override getGrantedPermissions(@onNull String packageName, @UserIdInt int userId)771 public Set<String> getGrantedPermissions(@NonNull String packageName, 772 @UserIdInt int userId) { 773 return mPermissionManagerServiceImpl.getGrantedPermissions(packageName, userId); 774 } 775 @NonNull 776 @Override getPermissionGids(@onNull String permissionName, @UserIdInt int userId)777 public int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) { 778 return mPermissionManagerServiceImpl.getPermissionGids(permissionName, userId); 779 } 780 @NonNull 781 @Override getAppOpPermissionPackages(@onNull String permissionName)782 public String[] getAppOpPermissionPackages(@NonNull String permissionName) { 783 return mPermissionManagerServiceImpl.getAppOpPermissionPackages(permissionName); 784 } 785 @Override onStorageVolumeMounted(@ullable String volumeUuid, boolean fingerprintChanged)786 public void onStorageVolumeMounted(@Nullable String volumeUuid, 787 boolean fingerprintChanged) { 788 mPermissionManagerServiceImpl.onStorageVolumeMounted(volumeUuid, fingerprintChanged); 789 } 790 @Override resetRuntimePermissions(@onNull AndroidPackage pkg, @UserIdInt int userId)791 public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) { 792 mPermissionManagerServiceImpl.resetRuntimePermissions(pkg, userId); 793 } 794 @Override resetRuntimePermissionsForUser(@serIdInt int userId)795 public void resetRuntimePermissionsForUser(@UserIdInt int userId) { 796 mPermissionManagerServiceImpl.resetRuntimePermissionsForUser(userId); 797 } 798 799 @Override getPermissionTEMP(String permName)800 public Permission getPermissionTEMP(String permName) { 801 return mPermissionManagerServiceImpl.getPermissionTEMP(permName); 802 } 803 804 @NonNull 805 @Override getAllPermissionsWithProtection( @ermissionInfo.Protection int protection)806 public List<PermissionInfo> getAllPermissionsWithProtection( 807 @PermissionInfo.Protection int protection) { 808 return mPermissionManagerServiceImpl.getAllPermissionsWithProtection(protection); 809 } 810 811 @NonNull 812 @Override getAllPermissionsWithProtectionFlags( @ermissionInfo.ProtectionFlags int protectionFlags)813 public List<PermissionInfo> getAllPermissionsWithProtectionFlags( 814 @PermissionInfo.ProtectionFlags int protectionFlags) { 815 return mPermissionManagerServiceImpl 816 .getAllPermissionsWithProtectionFlags(protectionFlags); 817 } 818 819 /* End of delegate methods to PermissionManagerServiceInterface */ 820 } 821 822 /** 823 * Returns all relevant user ids. This list include the current set of created user ids as well 824 * as pre-created user ids. 825 * @return user ids for created users and pre-created users 826 */ getAllUserIds()827 private int[] getAllUserIds() { 828 return UserManagerService.getInstance().getUserIdsIncludingPreCreated(); 829 } 830 831 /** 832 * Interface to intercept permission checks and optionally pass through to the original 833 * implementation. 834 */ 835 private interface CheckPermissionDelegate { 836 /** 837 * Get the UID whose permission checks is being delegated. 838 * 839 * @return the UID 840 */ getDelegatedUid()841 int getDelegatedUid(); 842 843 /** 844 * Check whether the given package has been granted the specified permission. 845 * 846 * @param packageName the name of the package to be checked 847 * @param permissionName the name of the permission to be checked 848 * @param userId the user ID 849 * @param superImpl the original implementation that can be delegated to 850 * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has 851 * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise 852 * 853 * @see android.content.pm.PackageManager#checkPermission(String, String) 854 */ checkPermission(@onNull String packageName, @NonNull String permissionName, @UserIdInt int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl)855 int checkPermission(@NonNull String packageName, @NonNull String permissionName, 856 @UserIdInt int userId, 857 @NonNull TriFunction<String, String, Integer, Integer> superImpl); 858 859 /** 860 * Check whether the given UID has been granted the specified permission. 861 * 862 * @param uid the UID to be checked 863 * @param permissionName the name of the permission to be checked 864 * @param superImpl the original implementation that can be delegated to 865 * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has 866 * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise 867 */ checkUidPermission(int uid, @NonNull String permissionName, BiFunction<Integer, String, Integer> superImpl)868 int checkUidPermission(int uid, @NonNull String permissionName, 869 BiFunction<Integer, String, Integer> superImpl); 870 871 /** 872 * @return list of delegated permissions 873 */ getDelegatedPermissionNames()874 List<String> getDelegatedPermissionNames(); 875 } 876 877 private class ShellDelegate implements CheckPermissionDelegate { 878 private final int mDelegatedUid; 879 @NonNull 880 private final String mDelegatedPackageName; 881 @Nullable 882 private final List<String> mDelegatedPermissionNames; 883 ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName, @Nullable List<String> delegatedPermissionNames)884 public ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName, 885 @Nullable List<String> delegatedPermissionNames) { 886 mDelegatedUid = delegatedUid; 887 mDelegatedPackageName = delegatedPackageName; 888 mDelegatedPermissionNames = delegatedPermissionNames; 889 } 890 891 @Override getDelegatedUid()892 public int getDelegatedUid() { 893 return mDelegatedUid; 894 } 895 896 @Override checkPermission(@onNull String packageName, @NonNull String permissionName, int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl)897 public int checkPermission(@NonNull String packageName, @NonNull String permissionName, 898 int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl) { 899 if (mDelegatedPackageName.equals(packageName) 900 && isDelegatedPermission(permissionName)) { 901 final long identity = Binder.clearCallingIdentity(); 902 try { 903 return superImpl.apply("com.android.shell", permissionName, userId); 904 } finally { 905 Binder.restoreCallingIdentity(identity); 906 } 907 } 908 return superImpl.apply(packageName, permissionName, userId); 909 } 910 911 @Override checkUidPermission(int uid, @NonNull String permissionName, @NonNull BiFunction<Integer, String, Integer> superImpl)912 public int checkUidPermission(int uid, @NonNull String permissionName, 913 @NonNull BiFunction<Integer, String, Integer> superImpl) { 914 if (uid == mDelegatedUid && isDelegatedPermission(permissionName)) { 915 final long identity = Binder.clearCallingIdentity(); 916 try { 917 return superImpl.apply(Process.SHELL_UID, permissionName); 918 } finally { 919 Binder.restoreCallingIdentity(identity); 920 } 921 } 922 return superImpl.apply(uid, permissionName); 923 } 924 925 @Override getDelegatedPermissionNames()926 public List<String> getDelegatedPermissionNames() { 927 return mDelegatedPermissionNames == null 928 ? null 929 : new ArrayList<>(mDelegatedPermissionNames); 930 } 931 isDelegatedPermission(@onNull String permissionName)932 private boolean isDelegatedPermission(@NonNull String permissionName) { 933 // null permissions means all permissions are targeted 934 return mDelegatedPermissionNames == null 935 || mDelegatedPermissionNames.contains(permissionName); 936 } 937 } 938 939 private static final class AttributionSourceRegistry { 940 private final Object mLock = new Object(); 941 942 private final Context mContext; 943 AttributionSourceRegistry(@onNull Context context)944 AttributionSourceRegistry(@NonNull Context context) { 945 mContext = context; 946 } 947 948 private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>(); 949 registerAttributionSource(@onNull AttributionSource source)950 public void registerAttributionSource(@NonNull AttributionSource source) { 951 // Here we keep track of attribution sources that were created by an app 952 // from an attribution chain that called into the app and the apps's 953 // own attribution source. An app can register an attribution chain up 954 // to itself inclusive if and only if it is adding a node for itself which 955 // optionally points to an attribution chain that was created by each 956 // preceding app recursively up to the beginning of the chain. 957 // The only special case is when the first app in the attribution chain 958 // creates a source that points to another app (not a chain of apps). We 959 // allow this even if the source the app points to is not registered since 960 // in app ops we allow every app to blame every other app (untrusted if not 961 // holding a special permission). 962 // This technique ensures that a bad actor in the middle of the attribution 963 // chain can neither prepend nor append an invalid attribution sequence, i.e. 964 // a sequence that is not constructed by trusted sources up to the that bad 965 // actor's app. 966 // Note that passing your attribution source to another app means you allow 967 // it to blame private data access on your app. This can be mediated by the OS 968 // in, which case security is already enforced; by other app's code running in 969 // your process calling into the other app, in which case it can already access 970 // the private data in your process; or by you explicitly calling to another 971 // app passing the source, in which case you must trust the other side; 972 973 final int callingUid = resolveUid(Binder.getCallingUid()); 974 final int sourceUid = resolveUid(source.getUid()); 975 if (sourceUid != callingUid && mContext.checkPermission( 976 Manifest.permission.UPDATE_APP_OPS_STATS, /*pid*/ -1, callingUid) 977 != PackageManager.PERMISSION_GRANTED) { 978 throw new SecurityException("Cannot register attribution source for uid:" 979 + sourceUid + " from uid:" + callingUid); 980 } 981 982 final PackageManagerInternal packageManagerInternal = LocalServices.getService( 983 PackageManagerInternal.class); 984 985 // TODO(b/234653108): Clean up this UID/package & cross-user check. 986 // If calling from the system process, allow registering attribution for package from 987 // any user 988 int userId = UserHandle.getUserId((callingUid == Process.SYSTEM_UID ? sourceUid 989 : callingUid)); 990 if (packageManagerInternal.getPackageUid(source.getPackageName(), 0, userId) 991 != sourceUid) { 992 throw new SecurityException("Cannot register attribution source for package:" 993 + source.getPackageName() + " from uid:" + callingUid); 994 } 995 996 final AttributionSource next = source.getNext(); 997 if (next != null && next.getNext() != null 998 && !isRegisteredAttributionSource(next)) { 999 throw new SecurityException("Cannot register forged attribution source:" 1000 + source); 1001 } 1002 1003 synchronized (mLock) { 1004 // Change the token for the AttributionSource we're storing, so that we don't store 1005 // a strong reference to the original token inside the map itself. 1006 mAttributions.put(source.getToken(), source.withDefaultToken()); 1007 } 1008 } 1009 isRegisteredAttributionSource(@onNull AttributionSource source)1010 public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) { 1011 synchronized (mLock) { 1012 final AttributionSource cachedSource = mAttributions.get(source.getToken()); 1013 if (cachedSource != null) { 1014 return cachedSource.equalsExceptToken(source); 1015 } 1016 return false; 1017 } 1018 } 1019 resolveUid(int uid)1020 private int resolveUid(int uid) { 1021 final VoiceInteractionManagerInternal vimi = LocalServices 1022 .getService(VoiceInteractionManagerInternal.class); 1023 if (vimi == null) { 1024 return uid; 1025 } 1026 final VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity 1027 hotwordDetectionServiceIdentity = vimi.getHotwordDetectionServiceIdentity(); 1028 if (hotwordDetectionServiceIdentity != null 1029 && uid == hotwordDetectionServiceIdentity.getIsolatedUid()) { 1030 return hotwordDetectionServiceIdentity.getOwnerUid(); 1031 } 1032 return uid; 1033 } 1034 } 1035 1036 /** 1037 * TODO: We need to consolidate these APIs either on PermissionManager or an extension 1038 * object or a separate PermissionChecker service in context. The impartant part is to 1039 * keep a single impl that is exposed to Java and native. We are not sure about the 1040 * API shape so let is soak a bit. 1041 */ 1042 private static final class PermissionCheckerService extends IPermissionChecker.Stub { 1043 // Cache for platform defined runtime permissions to avoid multi lookup (name -> info) 1044 private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions 1045 = new ConcurrentHashMap<>(); 1046 1047 private static final AtomicInteger sAttributionChainIds = new AtomicInteger(0); 1048 1049 private final @NonNull Context mContext; 1050 private final @NonNull AppOpsManager mAppOpsManager; 1051 private final @NonNull PermissionManagerServiceInternal mPermissionManagerServiceInternal; 1052 PermissionCheckerService(@onNull Context context)1053 PermissionCheckerService(@NonNull Context context) { 1054 mContext = context; 1055 mAppOpsManager = mContext.getSystemService(AppOpsManager.class); 1056 mPermissionManagerServiceInternal = 1057 LocalServices.getService(PermissionManagerServiceInternal.class); 1058 } 1059 1060 @Override 1061 @PermissionCheckerManager.PermissionResult checkPermission(@onNull String permission, @NonNull AttributionSourceState attributionSourceState, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1062 public int checkPermission(@NonNull String permission, 1063 @NonNull AttributionSourceState attributionSourceState, @Nullable String message, 1064 boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, 1065 int attributedOp) { 1066 Objects.requireNonNull(permission); 1067 Objects.requireNonNull(attributionSourceState); 1068 final AttributionSource attributionSource = new AttributionSource( 1069 attributionSourceState); 1070 final int result = checkPermission(mContext, mPermissionManagerServiceInternal, 1071 permission, attributionSource, message, forDataDelivery, startDataDelivery, 1072 fromDatasource, attributedOp); 1073 // Finish any started op if some step in the attribution chain failed. 1074 if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED 1075 && result != PermissionChecker.PERMISSION_SOFT_DENIED) { 1076 if (attributedOp == AppOpsManager.OP_NONE) { 1077 finishDataDelivery(AppOpsManager.permissionToOpCode(permission), 1078 attributionSource.asState(), fromDatasource); 1079 } else { 1080 finishDataDelivery(attributedOp, attributionSource.asState(), fromDatasource); 1081 } 1082 } 1083 return result; 1084 } 1085 1086 @Override finishDataDelivery(int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource)1087 public void finishDataDelivery(int op, 1088 @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) { 1089 finishDataDelivery(mContext, op, attributionSourceState, 1090 fromDataSource); 1091 } 1092 finishDataDelivery(Context context, int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource)1093 private static void finishDataDelivery(Context context, int op, 1094 @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { 1095 Objects.requireNonNull(attributionSourceState); 1096 AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 1097 1098 if (op == AppOpsManager.OP_NONE) { 1099 return; 1100 } 1101 1102 AttributionSource current = new AttributionSource(attributionSourceState); 1103 AttributionSource next = null; 1104 1105 while (true) { 1106 final boolean skipCurrentFinish = (fromDatasource || next != null); 1107 1108 next = current.getNext(); 1109 1110 // If the call is from a datasource we need to vet only the chain before it. This 1111 // way we can avoid the datasource creating an attribution context for every call. 1112 if (!(fromDatasource && current.asState() == attributionSourceState) 1113 && next != null && !current.isTrusted(context)) { 1114 return; 1115 } 1116 1117 // The access is for oneself if this is the single receiver of data 1118 // after the data source or if this is the single attribution source 1119 // in the chain if not from a datasource. 1120 final boolean singleReceiverFromDatasource = (fromDatasource 1121 && current.asState() == attributionSourceState && next != null 1122 && next.getNext() == null); 1123 final boolean selfAccess = singleReceiverFromDatasource || next == null; 1124 1125 final AttributionSource accessorSource = (!singleReceiverFromDatasource) 1126 ? current : next; 1127 1128 if (selfAccess) { 1129 final String resolvedPackageName = resolvePackageName(context, accessorSource); 1130 if (resolvedPackageName == null) { 1131 return; 1132 } 1133 appOpsManager.finishOp(attributionSourceState.token, op, 1134 accessorSource.getUid(), resolvedPackageName, 1135 accessorSource.getAttributionTag()); 1136 } else { 1137 final AttributionSource resolvedAttributionSource = 1138 resolveAttributionSource(context, accessorSource); 1139 if (resolvedAttributionSource.getPackageName() == null) { 1140 return; 1141 } 1142 appOpsManager.finishProxyOp(attributionSourceState.token, 1143 AppOpsManager.opToPublicName(op), resolvedAttributionSource, 1144 skipCurrentFinish); 1145 } 1146 RegisteredAttribution registered = 1147 sRunningAttributionSources.remove(current.getToken()); 1148 if (registered != null) { 1149 registered.unregister(); 1150 } 1151 1152 if (next == null || next.getNext() == null) { 1153 if (next != null) { 1154 registered = sRunningAttributionSources.remove(next.getToken()); 1155 if (registered != null) { 1156 registered.unregister(); 1157 } 1158 } 1159 return; 1160 } 1161 current = next; 1162 } 1163 } 1164 1165 @Override 1166 @PermissionCheckerManager.PermissionResult checkOp(int op, AttributionSourceState attributionSource, String message, boolean forDataDelivery, boolean startDataDelivery)1167 public int checkOp(int op, AttributionSourceState attributionSource, 1168 String message, boolean forDataDelivery, boolean startDataDelivery) { 1169 int result = checkOp(mContext, op, mPermissionManagerServiceInternal, 1170 new AttributionSource(attributionSource), message, forDataDelivery, 1171 startDataDelivery); 1172 if (result != PermissionChecker.PERMISSION_GRANTED && startDataDelivery) { 1173 // Finish any started op if some step in the attribution chain failed. 1174 finishDataDelivery(op, attributionSource, /*fromDatasource*/ false); 1175 } 1176 return result; 1177 } 1178 1179 @PermissionCheckerManager.PermissionResult checkPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1180 private static int checkPermission(@NonNull Context context, 1181 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, 1182 @NonNull String permission, @NonNull AttributionSource attributionSource, 1183 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, 1184 boolean fromDatasource, int attributedOp) { 1185 PermissionInfo permissionInfo = sPlatformPermissions.get(permission); 1186 1187 if (permissionInfo == null) { 1188 try { 1189 permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0); 1190 if (PLATFORM_PACKAGE_NAME.equals(permissionInfo.packageName) 1191 || HealthConnectManager.isHealthPermission(context, permission)) { 1192 // Double addition due to concurrency is fine - the backing 1193 // store is concurrent. 1194 sPlatformPermissions.put(permission, permissionInfo); 1195 } 1196 } catch (PackageManager.NameNotFoundException ignored) { 1197 return PermissionChecker.PERMISSION_HARD_DENIED; 1198 } 1199 } 1200 1201 if (permissionInfo.isAppOp()) { 1202 return checkAppOpPermission(context, permissionManagerServiceInt, permission, 1203 attributionSource, message, forDataDelivery, fromDatasource); 1204 } 1205 if (permissionInfo.isRuntime()) { 1206 return checkRuntimePermission(context, permissionManagerServiceInt, permission, 1207 attributionSource, message, forDataDelivery, startDataDelivery, 1208 fromDatasource, attributedOp); 1209 } 1210 1211 if (!fromDatasource && !checkPermission(context, permissionManagerServiceInt, 1212 permission, attributionSource.getUid(), 1213 attributionSource.getRenouncedPermissions())) { 1214 return PermissionChecker.PERMISSION_HARD_DENIED; 1215 } 1216 1217 if (attributionSource.getNext() != null) { 1218 return checkPermission(context, permissionManagerServiceInt, permission, 1219 attributionSource.getNext(), message, forDataDelivery, startDataDelivery, 1220 /*fromDatasource*/ false, attributedOp); 1221 } 1222 1223 return PermissionChecker.PERMISSION_GRANTED; 1224 } 1225 1226 @PermissionCheckerManager.PermissionResult checkAppOpPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean fromDatasource)1227 private static int checkAppOpPermission(@NonNull Context context, 1228 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, 1229 @NonNull String permission, @NonNull AttributionSource attributionSource, 1230 @Nullable String message, boolean forDataDelivery, boolean fromDatasource) { 1231 final int op = AppOpsManager.permissionToOpCode(permission); 1232 if (op < 0) { 1233 Slog.wtf(LOG_TAG, "Appop permission " + permission + " with no app op defined!"); 1234 return PermissionChecker.PERMISSION_HARD_DENIED; 1235 } 1236 1237 AttributionSource current = attributionSource; 1238 AttributionSource next = null; 1239 1240 while (true) { 1241 final boolean skipCurrentChecks = (fromDatasource || next != null); 1242 1243 next = current.getNext(); 1244 1245 // If the call is from a datasource we need to vet only the chain before it. This 1246 // way we can avoid the datasource creating an attribution context for every call. 1247 if (!(fromDatasource && current.equals(attributionSource)) 1248 && next != null && !current.isTrusted(context)) { 1249 return PermissionChecker.PERMISSION_HARD_DENIED; 1250 } 1251 1252 // The access is for oneself if this is the single receiver of data 1253 // after the data source or if this is the single attribution source 1254 // in the chain if not from a datasource. 1255 final boolean singleReceiverFromDatasource = (fromDatasource 1256 && current.equals(attributionSource) && next != null 1257 && next.getNext() == null); 1258 final boolean selfAccess = singleReceiverFromDatasource || next == null; 1259 1260 final int opMode = performOpTransaction(context, attributionSource.getToken(), op, 1261 current, message, forDataDelivery, /*startDataDelivery*/ false, 1262 skipCurrentChecks, selfAccess, singleReceiverFromDatasource, 1263 AppOpsManager.OP_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE, 1264 AppOpsManager.ATTRIBUTION_FLAGS_NONE, 1265 AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); 1266 1267 switch (opMode) { 1268 case AppOpsManager.MODE_IGNORED: 1269 case AppOpsManager.MODE_ERRORED: { 1270 return PermissionChecker.PERMISSION_HARD_DENIED; 1271 } 1272 case AppOpsManager.MODE_DEFAULT: { 1273 if (!skipCurrentChecks && !checkPermission(context, 1274 permissionManagerServiceInt, permission, attributionSource.getUid(), 1275 attributionSource.getRenouncedPermissions())) { 1276 return PermissionChecker.PERMISSION_HARD_DENIED; 1277 } 1278 if (next != null && !checkPermission(context, permissionManagerServiceInt, 1279 permission, next.getUid(), next.getRenouncedPermissions())) { 1280 return PermissionChecker.PERMISSION_HARD_DENIED; 1281 } 1282 } 1283 } 1284 1285 if (next == null || next.getNext() == null) { 1286 return PermissionChecker.PERMISSION_GRANTED; 1287 } 1288 1289 current = next; 1290 } 1291 } 1292 checkRuntimePermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1293 private static int checkRuntimePermission(@NonNull Context context, 1294 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, 1295 @NonNull String permission, @NonNull AttributionSource attributionSource, 1296 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, 1297 boolean fromDatasource, int attributedOp) { 1298 // Now let's check the identity chain... 1299 final int op = AppOpsManager.permissionToOpCode(permission); 1300 final int attributionChainId = 1301 getAttributionChainId(startDataDelivery, attributionSource); 1302 final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE; 1303 AttributionSource current = attributionSource; 1304 AttributionSource next = null; 1305 // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and 1306 // every attributionSource in the chain is registered with the system. 1307 final boolean isChainStartTrusted = !hasChain || checkPermission(context, 1308 permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(), 1309 current.getRenouncedPermissions()); 1310 1311 while (true) { 1312 final boolean skipCurrentChecks = (fromDatasource || next != null); 1313 next = current.getNext(); 1314 1315 // If the call is from a datasource we need to vet only the chain before it. This 1316 // way we can avoid the datasource creating an attribution context for every call. 1317 if (!(fromDatasource && current.equals(attributionSource)) 1318 && next != null && !current.isTrusted(context)) { 1319 return PermissionChecker.PERMISSION_HARD_DENIED; 1320 } 1321 1322 // If we already checked the permission for this one, skip the work 1323 if (!skipCurrentChecks && !checkPermission(context, permissionManagerServiceInt, 1324 permission, current.getUid(), current.getRenouncedPermissions())) { 1325 return PermissionChecker.PERMISSION_HARD_DENIED; 1326 } 1327 1328 if (next != null && !checkPermission(context, permissionManagerServiceInt, 1329 permission, next.getUid(), next.getRenouncedPermissions())) { 1330 return PermissionChecker.PERMISSION_HARD_DENIED; 1331 } 1332 1333 if (op < 0) { 1334 // Bg location is one-off runtime modifier permission and has no app op 1335 if (sPlatformPermissions.containsKey(permission) 1336 && !Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission) 1337 && !Manifest.permission.BODY_SENSORS_BACKGROUND.equals(permission)) { 1338 Slog.wtf(LOG_TAG, "Platform runtime permission " + permission 1339 + " with no app op defined!"); 1340 } 1341 if (next == null) { 1342 return PermissionChecker.PERMISSION_GRANTED; 1343 } 1344 current = next; 1345 continue; 1346 } 1347 1348 // The access is for oneself if this is the single receiver of data 1349 // after the data source or if this is the single attribution source 1350 // in the chain if not from a datasource. 1351 final boolean singleReceiverFromDatasource = (fromDatasource 1352 && current.equals(attributionSource) 1353 && next != null && next.getNext() == null); 1354 final boolean selfAccess = singleReceiverFromDatasource || next == null; 1355 final boolean isLinkTrusted = isChainStartTrusted 1356 && (current.isTrusted(context) || current.equals(attributionSource)) 1357 && (next == null || next.isTrusted(context)); 1358 1359 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain) 1360 ? resolveProxyAttributionFlags(attributionSource, current, fromDatasource, 1361 startDataDelivery, selfAccess, isLinkTrusted) 1362 : ATTRIBUTION_FLAGS_NONE; 1363 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags( 1364 attributionSource, next, fromDatasource, startDataDelivery, selfAccess, 1365 isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; 1366 1367 final int opMode = performOpTransaction(context, attributionSource.getToken(), op, 1368 current, message, forDataDelivery, startDataDelivery, skipCurrentChecks, 1369 selfAccess, singleReceiverFromDatasource, attributedOp, 1370 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); 1371 1372 switch (opMode) { 1373 case AppOpsManager.MODE_ERRORED: { 1374 return PermissionChecker.PERMISSION_HARD_DENIED; 1375 } 1376 case AppOpsManager.MODE_IGNORED: { 1377 return PermissionChecker.PERMISSION_SOFT_DENIED; 1378 } 1379 } 1380 1381 if (startDataDelivery) { 1382 RegisteredAttribution registered = new RegisteredAttribution(context, op, 1383 current, fromDatasource); 1384 sRunningAttributionSources.put(current.getToken(), registered); 1385 } 1386 1387 if (next == null || next.getNext() == null) { 1388 return PermissionChecker.PERMISSION_GRANTED; 1389 } 1390 1391 current = next; 1392 } 1393 } 1394 checkPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions)1395 private static boolean checkPermission(@NonNull Context context, 1396 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, 1397 @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions) { 1398 boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1, 1399 uid) == PackageManager.PERMISSION_GRANTED; 1400 1401 // Override certain permissions checks for the shared isolated process for both 1402 // HotwordDetectionService and VisualQueryDetectionService, which ordinarily cannot hold 1403 // any permissions. 1404 // There's probably a cleaner, more generalizable way to do this. For now, this is 1405 // the only use case for this, so simply override here. 1406 if (!permissionGranted 1407 && Process.isIsolated(uid) // simple check which fails-fast for the common case 1408 && (permission.equals(RECORD_AUDIO) || permission.equals(CAPTURE_AUDIO_HOTWORD) 1409 || permission.equals(CAPTURE_AUDIO_OUTPUT) || permission.equals(CAMERA))) { 1410 HotwordDetectionServiceProvider hotwordServiceProvider = 1411 permissionManagerServiceInt.getHotwordDetectionServiceProvider(); 1412 permissionGranted = hotwordServiceProvider != null 1413 && uid == hotwordServiceProvider.getUid(); 1414 } 1415 1416 if (permissionGranted && renouncedPermissions.contains(permission) 1417 && context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS, 1418 /*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) { 1419 return false; 1420 } 1421 return permissionGranted; 1422 } 1423 resolveProxyAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted)1424 private static @AttributionFlags int resolveProxyAttributionFlags( 1425 @NonNull AttributionSource attributionChain, 1426 @NonNull AttributionSource current, boolean fromDatasource, 1427 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) { 1428 return resolveAttributionFlags(attributionChain, current, fromDatasource, 1429 startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ true); 1430 } 1431 resolveProxiedAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted)1432 private static @AttributionFlags int resolveProxiedAttributionFlags( 1433 @NonNull AttributionSource attributionChain, 1434 @NonNull AttributionSource current, boolean fromDatasource, 1435 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) { 1436 return resolveAttributionFlags(attributionChain, current, fromDatasource, 1437 startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ false); 1438 } 1439 resolveAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted, boolean flagsForProxy)1440 private static @AttributionFlags int resolveAttributionFlags( 1441 @NonNull AttributionSource attributionChain, 1442 @NonNull AttributionSource current, boolean fromDatasource, 1443 boolean startDataDelivery, boolean selfAccess, boolean isTrusted, 1444 boolean flagsForProxy) { 1445 if (current == null || !startDataDelivery) { 1446 return AppOpsManager.ATTRIBUTION_FLAGS_NONE; 1447 } 1448 int trustedFlag = isTrusted 1449 ? AppOpsManager.ATTRIBUTION_FLAG_TRUSTED : AppOpsManager.ATTRIBUTION_FLAGS_NONE; 1450 if (flagsForProxy) { 1451 if (selfAccess) { 1452 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR; 1453 } else if (!fromDatasource && current.equals(attributionChain)) { 1454 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR; 1455 } 1456 } else { 1457 if (selfAccess) { 1458 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER; 1459 } else if (fromDatasource && current.equals(attributionChain.getNext())) { 1460 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR; 1461 } else if (current.getNext() == null) { 1462 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER; 1463 } 1464 } 1465 if (fromDatasource && current.equals(attributionChain)) { 1466 return AppOpsManager.ATTRIBUTION_FLAGS_NONE; 1467 } 1468 return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY; 1469 } 1470 checkOp(@onNull Context context, @NonNull int op, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery)1471 private static int checkOp(@NonNull Context context, @NonNull int op, 1472 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, 1473 @NonNull AttributionSource attributionSource, @Nullable String message, 1474 boolean forDataDelivery, boolean startDataDelivery) { 1475 if (op < 0 || attributionSource.getPackageName() == null) { 1476 return PermissionChecker.PERMISSION_HARD_DENIED; 1477 } 1478 1479 final int attributionChainId = 1480 getAttributionChainId(startDataDelivery, attributionSource); 1481 final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE; 1482 1483 AttributionSource current = attributionSource; 1484 AttributionSource next = null; 1485 1486 // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and 1487 // every attributionSource in the chain is registered with the system. 1488 final boolean isChainStartTrusted = !hasChain || checkPermission(context, 1489 permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(), 1490 current.getRenouncedPermissions()); 1491 1492 while (true) { 1493 final boolean skipCurrentChecks = (next != null); 1494 next = current.getNext(); 1495 1496 // If the call is from a datasource we need to vet only the chain before it. This 1497 // way we can avoid the datasource creating an attribution context for every call. 1498 if (next != null && !current.isTrusted(context)) { 1499 return PermissionChecker.PERMISSION_HARD_DENIED; 1500 } 1501 1502 // The access is for oneself if this is the single attribution source in the chain. 1503 final boolean selfAccess = (next == null); 1504 final boolean isLinkTrusted = isChainStartTrusted 1505 && (current.isTrusted(context) || current.equals(attributionSource)) 1506 && (next == null || next.isTrusted(context)); 1507 1508 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain) 1509 ? resolveProxyAttributionFlags(attributionSource, current, 1510 /*fromDatasource*/ false, startDataDelivery, selfAccess, 1511 isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; 1512 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags( 1513 attributionSource, next, /*fromDatasource*/ false, startDataDelivery, 1514 selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; 1515 1516 final int opMode = performOpTransaction(context, current.getToken(), op, current, 1517 message, forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, 1518 /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags, 1519 proxiedAttributionFlags, attributionChainId); 1520 1521 switch (opMode) { 1522 case AppOpsManager.MODE_ERRORED: { 1523 return PermissionChecker.PERMISSION_HARD_DENIED; 1524 } 1525 case AppOpsManager.MODE_IGNORED: { 1526 return PermissionChecker.PERMISSION_SOFT_DENIED; 1527 } 1528 } 1529 1530 if (next == null || next.getNext() == null) { 1531 return PermissionChecker.PERMISSION_GRANTED; 1532 } 1533 1534 current = next; 1535 } 1536 } 1537 1538 @SuppressWarnings("ConstantConditions") performOpTransaction(@onNull Context context, @NonNull IBinder chainStartToken, int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation, boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId)1539 private static int performOpTransaction(@NonNull Context context, 1540 @NonNull IBinder chainStartToken, int op, 1541 @NonNull AttributionSource attributionSource, @Nullable String message, 1542 boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation, 1543 boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp, 1544 @AttributionFlags int proxyAttributionFlags, 1545 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { 1546 // We cannot perform app ops transactions without a package name. In all relevant 1547 // places we pass the package name but just in case there is a bug somewhere we 1548 // do a best effort to resolve the package from the UID (pick first without a loss 1549 // of generality - they are in the same security sandbox). 1550 final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 1551 final AttributionSource accessorSource = (!singleReceiverFromDatasource) 1552 ? attributionSource : attributionSource.getNext(); 1553 if (!forDataDelivery) { 1554 final String resolvedAccessorPackageName = resolvePackageName(context, 1555 accessorSource); 1556 if (resolvedAccessorPackageName == null) { 1557 return AppOpsManager.MODE_ERRORED; 1558 } 1559 final int opMode = appOpsManager.unsafeCheckOpRawNoThrow(op, 1560 accessorSource.getUid(), resolvedAccessorPackageName); 1561 final AttributionSource next = accessorSource.getNext(); 1562 if (!selfAccess && opMode == AppOpsManager.MODE_ALLOWED && next != null) { 1563 final String resolvedNextPackageName = resolvePackageName(context, next); 1564 if (resolvedNextPackageName == null) { 1565 return AppOpsManager.MODE_ERRORED; 1566 } 1567 return appOpsManager.unsafeCheckOpRawNoThrow(op, next.getUid(), 1568 resolvedNextPackageName); 1569 } 1570 return opMode; 1571 } else if (startDataDelivery) { 1572 final AttributionSource resolvedAttributionSource = resolveAttributionSource( 1573 context, accessorSource); 1574 if (resolvedAttributionSource.getPackageName() == null) { 1575 return AppOpsManager.MODE_ERRORED; 1576 } 1577 // If the datasource is not in a trusted platform component then in would not 1578 // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that 1579 // an app is exposing runtime permission protected data but cannot blame others 1580 // in a trusted way which would not properly show in permission usage UIs. 1581 // As a fallback we note a proxy op that blames the app and the datasource. 1582 int startedOp = op; 1583 int checkedOpResult = MODE_ALLOWED; 1584 int startedOpResult; 1585 1586 // If the datasource wants to attribute to another app op we need to 1587 // make sure the op for the permission and the attributed ops allow 1588 // the operation. We return the less permissive of the two and check 1589 // the permission op while start the attributed op. 1590 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) { 1591 checkedOpResult = appOpsManager.checkOpNoThrow(op, 1592 resolvedAttributionSource.getUid(), resolvedAttributionSource 1593 .getPackageName()); 1594 if (checkedOpResult == MODE_ERRORED) { 1595 return checkedOpResult; 1596 } 1597 startedOp = attributedOp; 1598 } 1599 if (selfAccess) { 1600 try { 1601 startedOpResult = appOpsManager.startOpNoThrow( 1602 chainStartToken, startedOp, 1603 resolvedAttributionSource.getUid(), 1604 resolvedAttributionSource.getPackageName(), 1605 /*startIfModeDefault*/ false, 1606 resolvedAttributionSource.getAttributionTag(), 1607 message, proxyAttributionFlags, attributionChainId); 1608 } catch (SecurityException e) { 1609 Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with" 1610 + " platform defined runtime permission " 1611 + AppOpsManager.opToPermission(op) + " while not having " 1612 + Manifest.permission.UPDATE_APP_OPS_STATS); 1613 startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, 1614 attributedOp, attributionSource, message, skipProxyOperation, 1615 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); 1616 } 1617 } else { 1618 try { 1619 startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, 1620 startedOp, resolvedAttributionSource, message, skipProxyOperation, 1621 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); 1622 } catch (SecurityException e) { 1623 //TODO 195339480: remove 1624 String msg = "Security exception for op " + startedOp + " with source " 1625 + attributionSource.getUid() + ":" 1626 + attributionSource.getPackageName() + ", " 1627 + attributionSource.getNextUid() + ":" 1628 + attributionSource.getNextPackageName(); 1629 if (attributionSource.getNext() != null) { 1630 AttributionSource next = attributionSource.getNext(); 1631 msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid(); 1632 } 1633 throw new SecurityException(msg + ":" + e.getMessage()); 1634 } 1635 } 1636 return Math.max(checkedOpResult, startedOpResult); 1637 } else { 1638 final AttributionSource resolvedAttributionSource = resolveAttributionSource( 1639 context, accessorSource); 1640 if (resolvedAttributionSource.getPackageName() == null) { 1641 return AppOpsManager.MODE_ERRORED; 1642 } 1643 int notedOp = op; 1644 int checkedOpResult = MODE_ALLOWED; 1645 int notedOpResult; 1646 1647 // If the datasource wants to attribute to another app op we need to 1648 // make sure the op for the permission and the attributed ops allow 1649 // the operation. We return the less permissive of the two and check 1650 // the permission op while start the attributed op. 1651 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) { 1652 checkedOpResult = appOpsManager.checkOpNoThrow(op, 1653 resolvedAttributionSource.getUid(), resolvedAttributionSource 1654 .getPackageName()); 1655 if (checkedOpResult == MODE_ERRORED) { 1656 return checkedOpResult; 1657 } 1658 notedOp = attributedOp; 1659 } 1660 if (selfAccess) { 1661 // If the datasource is not in a trusted platform component then in would not 1662 // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that 1663 // an app is exposing runtime permission protected data but cannot blame others 1664 // in a trusted way which would not properly show in permission usage UIs. 1665 // As a fallback we note a proxy op that blames the app and the datasource. 1666 try { 1667 notedOpResult = appOpsManager.noteOpNoThrow(notedOp, 1668 resolvedAttributionSource.getUid(), 1669 resolvedAttributionSource.getPackageName(), 1670 resolvedAttributionSource.getAttributionTag(), 1671 message); 1672 } catch (SecurityException e) { 1673 Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with" 1674 + " platform defined runtime permission " 1675 + AppOpsManager.opToPermission(op) + " while not having " 1676 + Manifest.permission.UPDATE_APP_OPS_STATS); 1677 notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp, attributionSource, 1678 message, skipProxyOperation); 1679 } 1680 } else { 1681 try { 1682 notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp, 1683 resolvedAttributionSource, message, skipProxyOperation); 1684 } catch (SecurityException e) { 1685 //TODO 195339480: remove 1686 String msg = "Security exception for op " + notedOp + " with source " 1687 + attributionSource.getUid() + ":" 1688 + attributionSource.getPackageName() + ", " 1689 + attributionSource.getNextUid() + ":" 1690 + attributionSource.getNextPackageName(); 1691 if (attributionSource.getNext() != null) { 1692 AttributionSource next = attributionSource.getNext(); 1693 msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid(); 1694 } 1695 throw new SecurityException(msg + ":" + e.getMessage()); 1696 } 1697 } 1698 return Math.max(checkedOpResult, notedOpResult); 1699 } 1700 } 1701 getAttributionChainId(boolean startDataDelivery, AttributionSource source)1702 private static int getAttributionChainId(boolean startDataDelivery, 1703 AttributionSource source) { 1704 if (source == null || source.getNext() == null || !startDataDelivery) { 1705 return AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; 1706 } 1707 int attributionChainId = sAttributionChainIds.incrementAndGet(); 1708 1709 // handle overflow 1710 if (attributionChainId < 0) { 1711 attributionChainId = 0; 1712 sAttributionChainIds.set(0); 1713 } 1714 return attributionChainId; 1715 } 1716 resolvePackageName(@onNull Context context, @NonNull AttributionSource attributionSource)1717 private static @Nullable String resolvePackageName(@NonNull Context context, 1718 @NonNull AttributionSource attributionSource) { 1719 if (attributionSource.getPackageName() != null) { 1720 return attributionSource.getPackageName(); 1721 } 1722 final String[] packageNames = context.getPackageManager().getPackagesForUid( 1723 attributionSource.getUid()); 1724 if (packageNames != null) { 1725 // This is best effort if the caller doesn't pass a package. The security 1726 // sandbox is UID, therefore we pick an arbitrary package. 1727 return packageNames[0]; 1728 } 1729 // Last resort to handle special UIDs like root, etc. 1730 return AppOpsManager.resolvePackageName(attributionSource.getUid(), 1731 attributionSource.getPackageName()); 1732 } 1733 resolveAttributionSource( @onNull Context context, @NonNull AttributionSource attributionSource)1734 private static @NonNull AttributionSource resolveAttributionSource( 1735 @NonNull Context context, @NonNull AttributionSource attributionSource) { 1736 if (attributionSource.getPackageName() != null) { 1737 return attributionSource; 1738 } 1739 return attributionSource.withPackageName(resolvePackageName(context, 1740 attributionSource)); 1741 } 1742 } 1743 1744 private static final class RegisteredAttribution { 1745 private final DeathRecipient mDeathRecipient; 1746 private final IBinder mToken; 1747 private final AtomicBoolean mFinished; 1748 RegisteredAttribution(Context context, int op, AttributionSource source, boolean fromDatasource)1749 RegisteredAttribution(Context context, int op, AttributionSource source, 1750 boolean fromDatasource) { 1751 mFinished = new AtomicBoolean(false); 1752 mDeathRecipient = () -> { 1753 if (unregister()) { 1754 PermissionCheckerService 1755 .finishDataDelivery(context, op, source.asState(), fromDatasource); 1756 } 1757 }; 1758 mToken = source.getToken(); 1759 if (mToken != null) { 1760 try { 1761 mToken.linkToDeath(mDeathRecipient, 0); 1762 } catch (RemoteException e) { 1763 mDeathRecipient.binderDied(); 1764 } 1765 } 1766 } 1767 unregister()1768 public boolean unregister() { 1769 if (mFinished.compareAndSet(false, true)) { 1770 try { 1771 if (mToken != null) { 1772 mToken.unlinkToDeath(mDeathRecipient, 0); 1773 } 1774 } catch (NoSuchElementException e) { 1775 // do nothing 1776 } 1777 return true; 1778 } 1779 return false; 1780 } 1781 } 1782 } 1783