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