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