• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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