1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; 20 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21 22 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; 23 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 24 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 25 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW; 26 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY; 27 28 import static java.lang.annotation.RetentionPolicy.SOURCE; 29 30 import android.annotation.IntDef; 31 import android.annotation.Nullable; 32 import android.app.ActivityManager; 33 import android.app.ActivityOptions; 34 import android.content.ComponentName; 35 import android.content.Intent; 36 import android.content.pm.PackageManager; 37 import android.os.Process; 38 import android.os.UserHandle; 39 import android.util.ArraySet; 40 import android.util.DebugUtils; 41 import android.util.Slog; 42 43 import com.android.internal.util.FrameworkStatsLog; 44 import com.android.server.am.PendingIntentRecord; 45 46 import java.lang.annotation.Retention; 47 48 /** 49 * Helper class to check permissions for starting Activities. 50 * 51 * <p>This class collects all the logic to prevent malicious attempts to start activities. 52 */ 53 public class BackgroundActivityStartController { 54 55 private static final String TAG = 56 TAG_WITH_CLASS_NAME ? "BackgroundActivityStartController" : TAG_ATM; 57 58 private final ActivityTaskManagerService mService; 59 private final ActivityTaskSupervisor mSupervisor; 60 61 // TODO(b/263368846) Rename when ASM logic is moved in 62 @Retention(SOURCE) 63 @IntDef({BAL_BLOCK, 64 BAL_ALLOW_DEFAULT, 65 BAL_ALLOW_ALLOWLISTED_UID, 66 BAL_ALLOW_ALLOWLISTED_COMPONENT, 67 BAL_ALLOW_VISIBLE_WINDOW, 68 BAL_ALLOW_PENDING_INTENT, 69 BAL_ALLOW_BAL_PERMISSION, 70 BAL_ALLOW_SAW_PERMISSION, 71 BAL_ALLOW_GRACE_PERIOD, 72 BAL_ALLOW_FOREGROUND, 73 BAL_ALLOW_SDK_SANDBOX 74 }) 75 public @interface BalCode {} 76 77 static final int BAL_BLOCK = 0; 78 79 static final int BAL_ALLOW_DEFAULT = 1; 80 81 // Following codes are in order of precedence 82 83 /** Important UIDs which should be always allowed to launch activities */ 84 static final int BAL_ALLOW_ALLOWLISTED_UID = 2; 85 86 /** Apps that fulfill a certain role that can can always launch new tasks */ 87 static final int BAL_ALLOW_ALLOWLISTED_COMPONENT = 3; 88 89 /** Apps which currently have a visible window */ 90 static final int BAL_ALLOW_VISIBLE_WINDOW = 4; 91 92 /** Allowed due to the PendingIntent sender */ 93 static final int BAL_ALLOW_PENDING_INTENT = 5; 94 95 /** App has START_ACTIVITIES_FROM_BACKGROUND permission or BAL instrumentation privileges 96 * granted to it */ 97 static final int BAL_ALLOW_BAL_PERMISSION = 6; 98 99 /** Process has SYSTEM_ALERT_WINDOW permission granted to it */ 100 static final int BAL_ALLOW_SAW_PERMISSION = 7; 101 102 /** App is in grace period after an activity was started or finished */ 103 static final int BAL_ALLOW_GRACE_PERIOD = 8; 104 105 /** App is in a foreground task or bound to a foreground service (but not itself visible) */ 106 static final int BAL_ALLOW_FOREGROUND = 9; 107 108 /** Process belongs to a SDK sandbox */ 109 static final int BAL_ALLOW_SDK_SANDBOX = 10; 110 BackgroundActivityStartController( final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor)111 BackgroundActivityStartController( 112 final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) { 113 mService = service; 114 mSupervisor = supervisor; 115 } 116 isHomeApp(int uid, @Nullable String packageName)117 private boolean isHomeApp(int uid, @Nullable String packageName) { 118 if (mService.mHomeProcess != null) { 119 // Fast check 120 return uid == mService.mHomeProcess.mUid; 121 } 122 if (packageName == null) { 123 return false; 124 } 125 ComponentName activity = 126 mService.getPackageManagerInternalLocked() 127 .getDefaultHomeActivity(UserHandle.getUserId(uid)); 128 return activity != null && packageName.equals(activity.getPackageName()); 129 } 130 shouldAbortBackgroundActivityStart( int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions)131 boolean shouldAbortBackgroundActivityStart( 132 int callingUid, 133 int callingPid, 134 final String callingPackage, 135 int realCallingUid, 136 int realCallingPid, 137 WindowProcessController callerApp, 138 PendingIntentRecord originatingPendingIntent, 139 boolean allowBackgroundActivityStart, 140 Intent intent, 141 ActivityOptions checkedOptions) { 142 return checkBackgroundActivityStart(callingUid, callingPid, callingPackage, 143 realCallingUid, realCallingPid, callerApp, originatingPendingIntent, 144 allowBackgroundActivityStart, intent, checkedOptions) == BAL_BLOCK; 145 } 146 147 /** 148 * @return A code denoting which BAL rule allows an activity to be started, 149 * or {@link BAL_BLOCK} if the launch should be blocked 150 */ 151 @BalCode checkBackgroundActivityStart( int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions)152 int checkBackgroundActivityStart( 153 int callingUid, 154 int callingPid, 155 final String callingPackage, 156 int realCallingUid, 157 int realCallingPid, 158 WindowProcessController callerApp, 159 PendingIntentRecord originatingPendingIntent, 160 boolean allowBackgroundActivityStart, 161 Intent intent, 162 ActivityOptions checkedOptions) { 163 // don't abort for the most important UIDs 164 final int callingAppId = UserHandle.getAppId(callingUid); 165 final boolean useCallingUidState = 166 originatingPendingIntent == null 167 || checkedOptions == null 168 || !checkedOptions.getIgnorePendingIntentCreatorForegroundState(); 169 if (useCallingUidState) { 170 if (callingUid == Process.ROOT_UID 171 || callingAppId == Process.SYSTEM_UID 172 || callingAppId == Process.NFC_UID) { 173 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false, 174 callingUid, realCallingUid, intent, "Important callingUid"); 175 } 176 177 // Always allow home application to start activities. 178 if (isHomeApp(callingUid, callingPackage)) { 179 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT, 180 /*background*/ false, callingUid, realCallingUid, intent, 181 "Home app"); 182 } 183 184 // IME should always be allowed to start activity, like IME settings. 185 final WindowState imeWindow = 186 mService.mRootWindowContainer.getCurrentInputMethodWindow(); 187 if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) { 188 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT, 189 /*background*/ false, callingUid, realCallingUid, intent, 190 "Active ime"); 191 } 192 } 193 194 // This is used to block background activity launch even if the app is still 195 // visible to user after user clicking home button. 196 final int appSwitchState = mService.getBalAppSwitchesState(); 197 198 // don't abort if the callingUid has a visible window or is a persistent system process 199 final int callingUidProcState = mService.mActiveUids.getUidState(callingUid); 200 final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid); 201 final boolean isCallingUidForeground = 202 callingUidHasAnyVisibleWindow 203 || callingUidProcState == ActivityManager.PROCESS_STATE_TOP 204 || callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP; 205 final boolean isCallingUidPersistentSystemProcess = 206 callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI; 207 208 // Normal apps with visible app window will be allowed to start activity if app switching 209 // is allowed, or apps like live wallpaper with non app visible window will be allowed. 210 final boolean appSwitchAllowedOrFg = 211 appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY; 212 final boolean allowCallingUidStartActivity = 213 ((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid)) 214 && callingUidHasAnyVisibleWindow) 215 || isCallingUidPersistentSystemProcess; 216 if (useCallingUidState && allowCallingUidStartActivity) { 217 return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW, 218 /*background*/ false, callingUid, realCallingUid, intent, 219 "callingUidHasAnyVisibleWindow = " 220 + callingUid 221 + ", isCallingUidPersistentSystemProcess = " 222 + isCallingUidPersistentSystemProcess); 223 } 224 // take realCallingUid into consideration 225 final int realCallingUidProcState = 226 (callingUid == realCallingUid) 227 ? callingUidProcState 228 : mService.mActiveUids.getUidState(realCallingUid); 229 final boolean realCallingUidHasAnyVisibleWindow = 230 (callingUid == realCallingUid) 231 ? callingUidHasAnyVisibleWindow 232 : mService.hasActiveVisibleWindow(realCallingUid); 233 final boolean isRealCallingUidForeground = 234 (callingUid == realCallingUid) 235 ? isCallingUidForeground 236 : realCallingUidHasAnyVisibleWindow 237 || realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP; 238 final int realCallingAppId = UserHandle.getAppId(realCallingUid); 239 final boolean isRealCallingUidPersistentSystemProcess = 240 (callingUid == realCallingUid) 241 ? isCallingUidPersistentSystemProcess 242 : (realCallingAppId == Process.SYSTEM_UID) 243 || realCallingUidProcState 244 <= ActivityManager.PROCESS_STATE_PERSISTENT_UI; 245 246 // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a 247 // visible window. 248 if (Process.isSdkSandboxUid(realCallingUid)) { 249 int realCallingSdkSandboxUidToAppUid = 250 Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid)); 251 252 if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) { 253 return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX, 254 /*background*/ false, callingUid, realCallingUid, intent, 255 "uid in SDK sandbox has visible (non-toast) window"); 256 } 257 } 258 259 // Legacy behavior allows to use caller foreground state to bypass BAL restriction. 260 final boolean balAllowedByPiSender = 261 PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions); 262 263 if (balAllowedByPiSender && realCallingUid != callingUid) { 264 final boolean useCallerPermission = 265 PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions); 266 if (useCallerPermission 267 && ActivityManager.checkComponentPermission( 268 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, 269 realCallingUid, 270 -1, 271 true) 272 == PackageManager.PERMISSION_GRANTED) { 273 return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT, 274 /*background*/ false, callingUid, realCallingUid, intent, 275 "realCallingUid has BAL permission. realCallingUid: " + realCallingUid); 276 } 277 278 // don't abort if the realCallingUid has a visible window 279 // TODO(b/171459802): We should check appSwitchAllowed also 280 if (realCallingUidHasAnyVisibleWindow) { 281 return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT, 282 /*background*/ false, callingUid, realCallingUid, intent, 283 "realCallingUid has visible (non-toast) window. realCallingUid: " 284 + realCallingUid); 285 } 286 // if the realCallingUid is a persistent system process, abort if the IntentSender 287 // wasn't allowed to start an activity 288 if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) { 289 return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT, 290 /*background*/ false, callingUid, realCallingUid, intent, 291 "realCallingUid is persistent system process AND intent " 292 + "sender allowed (allowBackgroundActivityStart = true). " 293 + "realCallingUid: " + realCallingUid); 294 } 295 // don't abort if the realCallingUid is an associated companion app 296 if (mService.isAssociatedCompanionApp( 297 UserHandle.getUserId(realCallingUid), realCallingUid)) { 298 return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT, 299 /*background*/ false, callingUid, realCallingUid, intent, 300 "realCallingUid is a companion app. " 301 + "realCallingUid: " + realCallingUid); 302 } 303 } 304 if (useCallingUidState) { 305 // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission 306 if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, 307 callingPid, callingUid) == PERMISSION_GRANTED) { 308 return logStartAllowedAndReturnCode(BAL_ALLOW_BAL_PERMISSION, 309 /*background*/ true, callingUid, realCallingUid, intent, 310 "START_ACTIVITIES_FROM_BACKGROUND permission granted"); 311 } 312 // don't abort if the caller has the same uid as the recents component 313 if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) { 314 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT, 315 /*background*/ true, callingUid, realCallingUid, 316 intent, "Recents Component"); 317 } 318 // don't abort if the callingUid is the device owner 319 if (mService.isDeviceOwner(callingUid)) { 320 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT, 321 /*background*/ true, callingUid, realCallingUid, 322 intent, "Device Owner"); 323 } 324 // don't abort if the callingUid has companion device 325 final int callingUserId = UserHandle.getUserId(callingUid); 326 if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) { 327 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT, 328 /*background*/ true, callingUid, realCallingUid, 329 intent, "Companion App"); 330 } 331 // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission 332 if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) { 333 Slog.w( 334 TAG, 335 "Background activity start for " 336 + callingPackage 337 + " allowed because SYSTEM_ALERT_WINDOW permission is granted."); 338 return logStartAllowedAndReturnCode(BAL_ALLOW_SAW_PERMISSION, 339 /*background*/ true, callingUid, realCallingUid, 340 intent, "SYSTEM_ALERT_WINDOW permission is granted"); 341 } 342 } 343 // If we don't have callerApp at this point, no caller was provided to startActivity(). 344 // That's the case for PendingIntent-based starts, since the creator's process might not be 345 // up and alive. If that's the case, we retrieve the WindowProcessController for the send() 346 // caller if caller allows, so that we can make the decision based on its state. 347 int callerAppUid = callingUid; 348 if (callerApp == null && balAllowedByPiSender) { 349 callerApp = mService.getProcessController(realCallingPid, realCallingUid); 350 callerAppUid = realCallingUid; 351 } 352 // don't abort if the callerApp or other processes of that uid are allowed in any way 353 if (callerApp != null && useCallingUidState) { 354 // first check the original calling process 355 @BalCode int balAllowedForCaller = callerApp 356 .areBackgroundActivityStartsAllowed(appSwitchState); 357 if (balAllowedForCaller != BAL_BLOCK) { 358 return logStartAllowedAndReturnCode(balAllowedForCaller, 359 /*background*/ true, callingUid, realCallingUid, intent, 360 "callerApp process (pid = " + callerApp.getPid() 361 + ", uid = " + callerAppUid + ") is allowed"); 362 } 363 // only if that one wasn't allowed, check the other ones 364 final ArraySet<WindowProcessController> uidProcesses = 365 mService.mProcessMap.getProcesses(callerAppUid); 366 if (uidProcesses != null) { 367 for (int i = uidProcesses.size() - 1; i >= 0; i--) { 368 final WindowProcessController proc = uidProcesses.valueAt(i); 369 int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState); 370 if (proc != callerApp 371 && balAllowedForUid != BAL_BLOCK) { 372 return logStartAllowedAndReturnCode(balAllowedForUid, 373 /*background*/ true, callingUid, realCallingUid, intent, 374 "process" + proc.getPid() 375 + " from uid " + callerAppUid + " is allowed"); 376 } 377 } 378 } 379 } 380 // anything that has fallen through would currently be aborted 381 Slog.w( 382 TAG, 383 "Background activity start [callingPackage: " 384 + callingPackage 385 + "; callingUid: " 386 + callingUid 387 + "; appSwitchState: " 388 + appSwitchState 389 + "; isCallingUidForeground: " 390 + isCallingUidForeground 391 + "; callingUidHasAnyVisibleWindow: " 392 + callingUidHasAnyVisibleWindow 393 + "; callingUidProcState: " 394 + DebugUtils.valueToString( 395 ActivityManager.class, "PROCESS_STATE_", callingUidProcState) 396 + "; isCallingUidPersistentSystemProcess: " 397 + isCallingUidPersistentSystemProcess 398 + "; realCallingUid: " 399 + realCallingUid 400 + "; isRealCallingUidForeground: " 401 + isRealCallingUidForeground 402 + "; realCallingUidHasAnyVisibleWindow: " 403 + realCallingUidHasAnyVisibleWindow 404 + "; realCallingUidProcState: " 405 + DebugUtils.valueToString( 406 ActivityManager.class, "PROCESS_STATE_", realCallingUidProcState) 407 + "; isRealCallingUidPersistentSystemProcess: " 408 + isRealCallingUidPersistentSystemProcess 409 + "; originatingPendingIntent: " 410 + originatingPendingIntent 411 + "; allowBackgroundActivityStart: " 412 + allowBackgroundActivityStart 413 + "; intent: " 414 + intent 415 + "; callerApp: " 416 + callerApp 417 + "; inVisibleTask: " 418 + (callerApp != null && callerApp.hasActivityInVisibleTask()) 419 + "]"); 420 // log aborted activity start to TRON 421 if (mService.isActivityStartsLoggingEnabled()) { 422 mSupervisor 423 .getActivityMetricsLogger() 424 .logAbortedBgActivityStart( 425 intent, 426 callerApp, 427 callingUid, 428 callingPackage, 429 callingUidProcState, 430 callingUidHasAnyVisibleWindow, 431 realCallingUid, 432 realCallingUidProcState, 433 realCallingUidHasAnyVisibleWindow, 434 (originatingPendingIntent != null)); 435 } 436 return BAL_BLOCK; 437 } 438 logStartAllowedAndReturnCode(@alCode int code, boolean background, int callingUid, int realCallingUid, Intent intent, int pid, String msg)439 static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background, 440 int callingUid, int realCallingUid, Intent intent, int pid, String msg) { 441 return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent, 442 DEBUG_ACTIVITY_STARTS ? ("[Process(" + pid + ")]" + msg) : ""); 443 } 444 logStartAllowedAndReturnCode(@alCode int code, boolean background, int callingUid, int realCallingUid, Intent intent, String msg)445 static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background, 446 int callingUid, int realCallingUid, Intent intent, String msg) { 447 statsLogBalAllowed(code, callingUid, realCallingUid, intent); 448 if (DEBUG_ACTIVITY_STARTS) { 449 StringBuilder builder = new StringBuilder(); 450 if (background) { 451 builder.append("Background "); 452 } 453 builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". "); 454 builder.append("BAL Code: "); 455 builder.append(code); 456 Slog.d(TAG, builder.toString()); 457 } 458 return code; 459 } 460 statsLogBalAllowed( @alCode int code, int callingUid, int realCallingUid, Intent intent)461 private static void statsLogBalAllowed( 462 @BalCode int code, int callingUid, int realCallingUid, Intent intent) { 463 if (code == BAL_ALLOW_PENDING_INTENT 464 && (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) { 465 String activityName = 466 intent != null ? intent.getComponent().flattenToShortString() : ""; 467 FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED, 468 activityName, 469 code, 470 callingUid, 471 realCallingUid); 472 } 473 if (code == BAL_ALLOW_BAL_PERMISSION || code == BAL_ALLOW_FOREGROUND 474 || code == BAL_ALLOW_SAW_PERMISSION) { 475 // We don't need to know which activity in this case. 476 FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED, 477 /*activityName*/ "", 478 code, 479 callingUid, 480 realCallingUid); 481 } 482 } 483 } 484