blob: 8374ee63e07ea227563a60f1d99f17397f64b474 [file] [log] [blame]
Patrick Baumann6c1c8092019-06-27 14:55:44 -07001/*
2 * Copyright (C) 2019 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
17package com.android.server.pm;
18
Ram Muthiah637138d2019-12-11 17:37:37 -080019import static android.content.pm.PackageParser.Component;
20import static android.content.pm.PackageParser.IntentInfo;
Patrick Baumann88318e02019-11-04 14:22:25 -080021import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Patrick Baumanndfb121d2019-08-05 14:36:19 -070022import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
23
Patrick Baumann6c1c8092019-06-27 14:55:44 -070024import android.Manifest;
25import android.annotation.Nullable;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070026import android.content.Intent;
Patrick Baumann0c9257b2019-08-20 12:50:37 -070027import android.content.IntentFilter;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070028import android.content.pm.PackageManager;
Ram Muthiah637138d2019-12-11 17:37:37 -080029import android.content.pm.PackageParser;
Winson14ff7172019-10-23 10:42:27 -070030import android.content.pm.parsing.AndroidPackage;
31import android.content.pm.parsing.ComponentParseUtils;
Winson655a5b92019-10-23 10:49:32 -070032import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
Winson14ff7172019-10-23 10:42:27 -070033import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
34import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
35import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
Winson655a5b92019-10-23 10:49:32 -070036import android.content.pm.parsing.ComponentParseUtils.ParsedService;
Patrick Baumann0c9257b2019-08-20 12:50:37 -070037import android.net.Uri;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070038import android.os.Process;
Patrick Baumann88318e02019-11-04 14:22:25 -080039import android.os.Trace;
Patrick Baumannb9a49f42019-11-13 16:42:18 -080040import android.os.UserHandle;
Patrick Baumanndfb121d2019-08-05 14:36:19 -070041import android.provider.DeviceConfig;
Patrick Baumannb9a49f42019-11-13 16:42:18 -080042import android.text.TextUtils;
43import android.util.ArrayMap;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070044import android.util.ArraySet;
45import android.util.Slog;
46import android.util.SparseArray;
Patrick Baumannb9a49f42019-11-13 16:42:18 -080047import android.util.SparseSetArray;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070048
49import com.android.internal.R;
Patrick Baumanna94cbc12019-09-17 08:08:10 -070050import com.android.internal.annotations.VisibleForTesting;
Patrick Baumannb9a49f42019-11-13 16:42:18 -080051import com.android.internal.util.ArrayUtils;
Patrick Baumanndfb121d2019-08-05 14:36:19 -070052import com.android.server.FgThread;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070053
Patrick Baumanna7ad66d2019-08-12 11:11:08 -070054import java.io.PrintWriter;
Ram Muthiah637138d2019-12-11 17:37:37 -080055import java.util.ArrayList;
Winson655a5b92019-10-23 10:49:32 -070056import java.util.List;
Patrick Baumanna7ad66d2019-08-12 11:11:08 -070057import java.util.Objects;
Patrick Baumann6c1c8092019-06-27 14:55:44 -070058import java.util.Set;
59
60/**
61 * The entity responsible for filtering visibility between apps based on declarations in their
62 * manifests.
63 */
Patrick Baumanna94cbc12019-09-17 08:08:10 -070064@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
65public class AppsFilter {
Patrick Baumann6c1c8092019-06-27 14:55:44 -070066
Patrick Baumannb9a49f42019-11-13 16:42:18 -080067 private static final String TAG = "AppsFilter";
Patrick Baumannaf9c3fe2019-08-12 08:13:32 -070068
Patrick Baumann40ed99a2019-08-12 09:43:10 -070069 // Logs all filtering instead of enforcing
70 private static final boolean DEBUG_ALLOW_ALL = false;
71
72 @SuppressWarnings("ConstantExpression")
Patrick Baumann0c9257b2019-08-20 12:50:37 -070073 private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL;
Patrick Baumann40ed99a2019-08-12 09:43:10 -070074
Patrick Baumann6c1c8092019-06-27 14:55:44 -070075 /**
Patrick Baumannb9a49f42019-11-13 16:42:18 -080076 * This contains a list of app UIDs that are implicitly queryable because another app explicitly
Patrick Baumann6c1c8092019-06-27 14:55:44 -070077 * interacted with it. For example, if application A starts a service in application B,
78 * application B is implicitly allowed to query for application A; regardless of any manifest
79 * entries.
80 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -080081 private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
Patrick Baumann6c1c8092019-06-27 14:55:44 -070082
83 /**
Patrick Baumannb9a49f42019-11-13 16:42:18 -080084 * A mapping from the set of App IDs that query other App IDs via package name to the
Patrick Baumann6c1c8092019-06-27 14:55:44 -070085 * list of packages that they can see.
86 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -080087 private final SparseSetArray<Integer> mQueriesViaPackage = new SparseSetArray<>();
Patrick Baumann6c1c8092019-06-27 14:55:44 -070088
89 /**
Patrick Baumannb9a49f42019-11-13 16:42:18 -080090 * A mapping from the set of App IDs that query others via intent to the list
Patrick Baumann6c1c8092019-06-27 14:55:44 -070091 * of packages that the intents resolve to.
92 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -080093 private final SparseSetArray<Integer> mQueriesViaIntent = new SparseSetArray<>();
Patrick Baumann6c1c8092019-06-27 14:55:44 -070094
95 /**
Patrick Baumannb9a49f42019-11-13 16:42:18 -080096 * A set of App IDs that are always queryable by any package, regardless of their manifest
Patrick Baumann6c1c8092019-06-27 14:55:44 -070097 * content.
98 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -080099 private final ArraySet<Integer> mForceQueryable = new ArraySet<>();
100
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700101 /**
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800102 * The set of package names provided by the device that should be force queryable regardless of
103 * their manifest contents.
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700104 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800105 private final String[] mForceQueryableByDevicePackageNames;
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700106
107 /** True if all system apps should be made queryable by default. */
108 private final boolean mSystemAppsQueryable;
109
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700110 private final FeatureConfig mFeatureConfig;
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700111
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800112 AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
Ram Muthiah637138d2019-12-11 17:37:37 -0800113 boolean systemAppsQueryable) {
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700114 mFeatureConfig = featureConfig;
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800115 mForceQueryableByDevicePackageNames = forceQueryableWhitelist;
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700116 mSystemAppsQueryable = systemAppsQueryable;
117 }
118
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700119 public interface FeatureConfig {
120 /** Called when the system is ready and components can be queried. */
121 void onSystemReady();
Patrick Baumannaf9c3fe2019-08-12 08:13:32 -0700122
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700123 /** @return true if we should filter apps at all. */
124 boolean isGloballyEnabled();
125
126 /** @return true if the feature is enabled for the given package. */
Winson655a5b92019-10-23 10:49:32 -0700127 boolean packageIsEnabled(AndroidPackage pkg);
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700128 }
129
130 private static class FeatureConfigImpl implements FeatureConfig {
131 private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled";
Anna Trostanetski66bb1662019-10-29 16:44:25 +0000132 private final PackageManagerService.Injector mInjector;
Patrick Baumann9f463ad2019-10-15 10:11:10 -0700133 private volatile boolean mFeatureEnabled = false;
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700134
135 private FeatureConfigImpl(PackageManagerService.Injector injector) {
Anna Trostanetski66bb1662019-10-29 16:44:25 +0000136 mInjector = injector;
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700137 }
138
139 @Override
140 public void onSystemReady() {
141 mFeatureEnabled = DeviceConfig.getBoolean(
Patrick Baumann9f463ad2019-10-15 10:11:10 -0700142 NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, false);
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700143 DeviceConfig.addOnPropertiesChangedListener(
144 NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(),
145 properties -> {
Linus Tufvesson87776d62019-12-05 16:15:10 +0000146 if (properties.getKeyset().contains(FILTERING_ENABLED_NAME)) {
147 synchronized (FeatureConfigImpl.this) {
148 mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME,
149 false);
150 }
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700151 }
152 });
153 }
154
155 @Override
156 public boolean isGloballyEnabled() {
Patrick Baumann88318e02019-11-04 14:22:25 -0800157 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "isGloballyEnabled");
158 try {
159 return mFeatureEnabled;
160 } finally {
161 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
162 }
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700163 }
164
165 @Override
Winson655a5b92019-10-23 10:49:32 -0700166 public boolean packageIsEnabled(AndroidPackage pkg) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800167 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled");
168 try {
Winson655a5b92019-10-23 10:49:32 -0700169 // TODO(b/135203078): Do not use toAppInfo
Patrick Baumann88318e02019-11-04 14:22:25 -0800170 return mInjector.getCompatibility().isChangeEnabled(
Winson6571c8a2019-10-23 17:00:42 -0700171 PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
Patrick Baumann88318e02019-11-04 14:22:25 -0800172 } finally {
173 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
174 }
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700175 }
176 }
177
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700178 public static AppsFilter create(PackageManagerService.Injector injector) {
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700179 final boolean forceSystemAppsQueryable =
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700180 injector.getContext().getResources()
181 .getBoolean(R.bool.config_forceSystemPackagesQueryable);
182 final FeatureConfig featureConfig = new FeatureConfigImpl(injector);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700183 final String[] forcedQueryablePackageNames;
184 if (forceSystemAppsQueryable) {
185 // all system apps already queryable, no need to read and parse individual exceptions
186 forcedQueryablePackageNames = new String[]{};
187 } else {
188 forcedQueryablePackageNames =
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700189 injector.getContext().getResources()
190 .getStringArray(R.array.config_forceQueryablePackages);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700191 for (int i = 0; i < forcedQueryablePackageNames.length; i++) {
192 forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
193 }
194 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800195 return new AppsFilter(featureConfig, forcedQueryablePackageNames,
Ram Muthiah637138d2019-12-11 17:37:37 -0800196 forceSystemAppsQueryable);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700197 }
198
199 /** Returns true if the querying package may query for the potential target package */
Winson655a5b92019-10-23 10:49:32 -0700200 private static boolean canQueryViaIntent(AndroidPackage querying,
201 AndroidPackage potentialTarget) {
202 if (querying.getQueriesIntents() == null) {
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700203 return false;
204 }
Winson655a5b92019-10-23 10:49:32 -0700205 for (Intent intent : querying.getQueriesIntents()) {
Patrick Baumann58632332019-10-09 10:12:10 -0700206 if (matches(intent, potentialTarget)) {
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700207 return true;
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700208 }
209 }
210 return false;
211 }
212
Winson655a5b92019-10-23 10:49:32 -0700213 private static boolean matches(Intent intent, AndroidPackage potentialTarget) {
214 for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
215 ParsedProvider provider = potentialTarget.getProviders().get(p);
216 if (!provider.isExported()) {
Patrick Baumann58632332019-10-09 10:12:10 -0700217 continue;
218 }
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700219 final Uri data = intent.getData();
220 if ("content".equalsIgnoreCase(intent.getScheme())
221 && data != null
Winson655a5b92019-10-23 10:49:32 -0700222 && Objects.equals(provider.getAuthority(), data.getAuthority())) {
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700223 return true;
224 }
225 }
Winson655a5b92019-10-23 10:49:32 -0700226 for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) {
227 ParsedService service = potentialTarget.getServices().get(s);
228 if (!service.exported) {
Patrick Baumann58632332019-10-09 10:12:10 -0700229 continue;
230 }
231 if (matchesAnyFilter(intent, service)) {
232 return true;
233 }
234 }
Winson655a5b92019-10-23 10:49:32 -0700235 for (int a = ArrayUtils.size(potentialTarget.getActivities()) - 1; a >= 0; a--) {
236 ParsedActivity activity = potentialTarget.getActivities().get(a);
237 if (!activity.exported) {
Patrick Baumann58632332019-10-09 10:12:10 -0700238 continue;
239 }
240 if (matchesAnyFilter(intent, activity)) {
241 return true;
242 }
243 }
Winson655a5b92019-10-23 10:49:32 -0700244 for (int r = ArrayUtils.size(potentialTarget.getReceivers()) - 1; r >= 0; r--) {
245 ParsedActivity receiver = potentialTarget.getReceivers().get(r);
246 if (!receiver.exported) {
Patrick Baumann58632332019-10-09 10:12:10 -0700247 continue;
248 }
249 if (matchesAnyFilter(intent, receiver)) {
250 return true;
251 }
252 }
253 return false;
254 }
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700255
Patrick Baumann58632332019-10-09 10:12:10 -0700256 private static boolean matchesAnyFilter(
Winson655a5b92019-10-23 10:49:32 -0700257 Intent intent, ParsedComponent<? extends ParsedIntentInfo> component) {
258 List<? extends ParsedIntentInfo> intents = component.intents;
259 for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
Patrick Baumann58632332019-10-09 10:12:10 -0700260 IntentFilter intentFilter = intents.get(i);
261 if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
262 intent.getData(), intent.getCategories(), "AppsFilter") > 0) {
263 return true;
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700264 }
265 }
266 return false;
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700267 }
268
269 /**
Patrick Baumannde37e432019-08-28 09:51:29 -0700270 * Grants access based on an interaction between a calling and target package, granting
271 * visibility of the caller from the target.
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700272 *
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800273 * @param callingUid the uid initiating the interaction
274 * @param targetUid the uid being interacted with and thus gaining visibility of the
275 * initiating uid.
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700276 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800277 public void grantImplicitAccess(int callingUid, int targetUid) {
278 if (mImplicitlyQueryable.add(targetUid, callingUid) && DEBUG_LOGGING) {
279 Slog.wtf(TAG, "implicit access granted: " + callingUid + " -> " + targetUid);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700280 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700281 }
282
Patrick Baumanndfb121d2019-08-05 14:36:19 -0700283 public void onSystemReady() {
284 mFeatureConfig.onSystemReady();
285 }
286
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700287 /**
288 * Adds a package that should be considered when filtering visibility between apps.
289 *
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800290 * @param newPkgSetting the new setting being added
291 * @param existingSettings all other settings currently on the device.
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700292 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800293 public void addPackage(PackageSetting newPkgSetting,
294 ArrayMap<String, PackageSetting> existingSettings) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800295 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
296 try {
Winson655a5b92019-10-23 10:49:32 -0700297 final AndroidPackage newPkg = newPkgSetting.pkg;
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800298 if (newPkg == null) {
299 // nothing to add
300 return;
301 }
302
303 final boolean newIsForceQueryable =
304 mForceQueryable.contains(newPkgSetting.appId)
305 /* shared user that is already force queryable */
Winson655a5b92019-10-23 10:49:32 -0700306 || newPkg.isForceQueryable()
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800307 || (newPkgSetting.isSystem() && (mSystemAppsQueryable
308 || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
Winson655a5b92019-10-23 10:49:32 -0700309 newPkg.getPackageName())));
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800310 if (newIsForceQueryable) {
311 mForceQueryable.add(newPkgSetting.appId);
312 }
313
314 for (int i = existingSettings.size() - 1; i >= 0; i--) {
315 final PackageSetting existingSetting = existingSettings.valueAt(i);
316 if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) {
317 continue;
318 }
Winson655a5b92019-10-23 10:49:32 -0700319 final AndroidPackage existingPkg = existingSetting.pkg;
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800320 // let's evaluate the ability of already added packages to see this new package
321 if (!newIsForceQueryable) {
322 if (canQueryViaIntent(existingPkg, newPkg)) {
323 mQueriesViaIntent.add(existingSetting.appId, newPkgSetting.appId);
Patrick Baumann88318e02019-11-04 14:22:25 -0800324 }
Winson655a5b92019-10-23 10:49:32 -0700325 if (existingPkg.getQueriesPackages() != null
326 && existingPkg.getQueriesPackages().contains(newPkg.getPackageName())) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800327 mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
328 }
329 }
330 // now we'll evaluate our new package's ability to see existing packages
331 if (!mForceQueryable.contains(existingSetting.appId)) {
332 if (canQueryViaIntent(newPkg, existingPkg)) {
333 mQueriesViaIntent.add(newPkgSetting.appId, existingSetting.appId);
334 }
Winson655a5b92019-10-23 10:49:32 -0700335 if (newPkg.getQueriesPackages() != null
336 && newPkg.getQueriesPackages().contains(existingPkg.getPackageName())) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800337 mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
Patrick Baumann88318e02019-11-04 14:22:25 -0800338 }
339 }
340 }
Patrick Baumann88318e02019-11-04 14:22:25 -0800341 } finally {
342 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700343 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700344 }
345
346 /**
347 * Removes a package for consideration when filtering visibility between apps.
348 *
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800349 * @param setting the setting of the package being removed.
350 * @param allUsers array of all current users on device.
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700351 */
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800352 public void removePackage(PackageSetting setting, int[] allUsers,
353 ArrayMap<String, PackageSetting> existingSettings) {
354 mForceQueryable.remove(setting.appId);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700355
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800356 for (int u = 0; u < allUsers.length; u++) {
357 final int userId = allUsers[u];
358 final int removingUid = UserHandle.getUid(userId, setting.appId);
359 mImplicitlyQueryable.remove(removingUid);
360 for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
361 mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700362 }
363 }
364
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800365 mQueriesViaIntent.remove(setting.appId);
366 for (int i = mQueriesViaIntent.size() - 1; i >= 0; i--) {
367 mQueriesViaIntent.remove(mQueriesViaIntent.keyAt(i), setting.appId);
368 }
369 mQueriesViaPackage.remove(setting.appId);
370 for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
371 mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700372 }
373
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800374 // re-add other shared user members to re-establish visibility between them and other
375 // packages
376 if (setting.sharedUser != null) {
377 for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
378 if (setting.sharedUser.packages.valueAt(i) == setting) {
379 continue;
380 }
381 addPackage(setting.sharedUser.packages.valueAt(i), existingSettings);
382 }
383 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700384 }
385
386 /**
387 * Returns true if the calling package should not be able to see the target package, false if no
388 * filtering should be done.
389 *
390 * @param callingUid the uid of the caller attempting to access a package
391 * @param callingSetting the setting attempting to access a package or null if it could not be
392 * found
393 * @param targetPkgSetting the package being accessed
394 * @param userId the user in which this access is being attempted
395 */
396 public boolean shouldFilterApplication(int callingUid, @Nullable SettingBase callingSetting,
397 PackageSetting targetPkgSetting, int userId) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800398 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
399 try {
Ram Muthiah637138d2019-12-11 17:37:37 -0800400 if (!shouldFilterApplicationInternal(callingUid, callingSetting,
401 targetPkgSetting,
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800402 userId)) {
403 return false;
404 }
405 if (DEBUG_LOGGING) {
406 log(callingSetting, targetPkgSetting,
407 DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED", new RuntimeException());
408 }
409 return !DEBUG_ALLOW_ALL;
410 } finally {
411 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
412 }
413 }
414
Ram Muthiah637138d2019-12-11 17:37:37 -0800415 private boolean shouldFilterApplicationInternal(int callingUid,
416 SettingBase callingSetting, PackageSetting targetPkgSetting, int userId) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800417 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
418 try {
Patrick Baumann88318e02019-11-04 14:22:25 -0800419 final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
420 if (!featureEnabled) {
421 if (DEBUG_LOGGING) {
422 Slog.d(TAG, "filtering disabled; skipped");
423 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700424 return false;
425 }
Patrick Baumann88318e02019-11-04 14:22:25 -0800426 if (callingUid < Process.FIRST_APPLICATION_UID) {
427 if (DEBUG_LOGGING) {
428 Slog.d(TAG, "filtering skipped; " + callingUid + " is system");
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700429 }
Patrick Baumann88318e02019-11-04 14:22:25 -0800430 return false;
431 }
432 if (callingSetting == null) {
433 Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700434 return true;
435 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800436 final PackageSetting callingPkgSetting;
437 final ArraySet<PackageSetting> callingSharedPkgSettings;
Patrick Baumann88318e02019-11-04 14:22:25 -0800438 if (callingSetting instanceof PackageSetting) {
439 callingPkgSetting = (PackageSetting) callingSetting;
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800440 callingSharedPkgSettings = null;
441 } else {
442 callingPkgSetting = null;
443 callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
444 }
445
446 if (callingPkgSetting != null) {
447 if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
448 if (DEBUG_LOGGING) {
449 log(callingSetting, targetPkgSetting, "DISABLED");
450 }
Patrick Baumann88318e02019-11-04 14:22:25 -0800451 return false;
452 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800453 } else {
454 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
455 if (!mFeatureConfig.packageIsEnabled(callingSharedPkgSettings.valueAt(i).pkg)) {
456 if (DEBUG_LOGGING) {
457 log(callingSetting, targetPkgSetting, "DISABLED");
Patrick Baumann88318e02019-11-04 14:22:25 -0800458 }
Patrick Baumanna72e6742019-11-06 08:26:56 -0800459 return false;
460 }
461 }
Patrick Baumanna72e6742019-11-06 08:26:56 -0800462 }
463
Patrick Baumann88318e02019-11-04 14:22:25 -0800464 // This package isn't technically installed and won't be written to settings, so we can
465 // treat it as filtered until it's available again.
Winson655a5b92019-10-23 10:49:32 -0700466 final AndroidPackage targetPkg = targetPkgSetting.pkg;
Patrick Baumann88318e02019-11-04 14:22:25 -0800467 if (targetPkg == null) {
468 if (DEBUG_LOGGING) {
469 Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null");
470 }
471 return true;
472 }
Winson655a5b92019-10-23 10:49:32 -0700473 final String targetName = targetPkg.getPackageName();
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800474 final int callingAppId;
475 if (callingPkgSetting != null) {
476 callingAppId = callingPkgSetting.appId;
477 } else {
478 callingAppId = callingSharedPkgSettings.valueAt(0).appId; // all should be the same
479 }
480 final int targetAppId = targetPkgSetting.appId;
481 if (callingAppId == targetAppId) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800482 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800483 log(callingSetting, targetPkgSetting, "same app id");
Patrick Baumann88318e02019-11-04 14:22:25 -0800484 }
485 return false;
486 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800487
488 if (callingSetting.getPermissionsState().hasPermission(
489 Manifest.permission.QUERY_ALL_PACKAGES, UserHandle.getUserId(callingUid))) {
Patrick Baumanna72e6742019-11-06 08:26:56 -0800490 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800491 log(callingSetting, targetPkgSetting, "has query-all permission");
Patrick Baumanna72e6742019-11-06 08:26:56 -0800492 }
493 return false;
494 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800495 if (mForceQueryable.contains(targetAppId)) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800496 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800497 log(callingSetting, targetPkgSetting, "force queryable");
Patrick Baumann88318e02019-11-04 14:22:25 -0800498 }
499 return false;
500 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800501 if (mQueriesViaPackage.contains(callingAppId, targetAppId)) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800502 // the calling package has explicitly declared the target package; allow
503 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800504 log(callingSetting, targetPkgSetting, "queries package");
Patrick Baumann88318e02019-11-04 14:22:25 -0800505 }
506 return false;
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800507 } else if (mQueriesViaIntent.contains(callingAppId, targetAppId)) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800508 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800509 log(callingSetting, targetPkgSetting, "queries intent");
Patrick Baumann88318e02019-11-04 14:22:25 -0800510 }
511 return false;
512 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800513
514 final int targetUid = UserHandle.getUid(userId, targetAppId);
515 if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800516 if (DEBUG_LOGGING) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800517 log(callingSetting, targetPkgSetting, "implicitly queryable for user");
Patrick Baumann88318e02019-11-04 14:22:25 -0800518 }
519 return false;
520 }
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800521 if (callingPkgSetting != null) {
522 if (callingPkgInstruments(callingPkgSetting, targetPkgSetting, targetName)) {
523 return false;
524 }
525 } else {
526 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
527 if (callingPkgInstruments(callingSharedPkgSettings.valueAt(i),
528 targetPkgSetting, targetName)) {
Patrick Baumann88318e02019-11-04 14:22:25 -0800529 return false;
530 }
531 }
532 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700533 return true;
Patrick Baumann88318e02019-11-04 14:22:25 -0800534 } finally {
535 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700536 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700537 }
538
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800539 private static boolean callingPkgInstruments(PackageSetting callingPkgSetting,
540 PackageSetting targetPkgSetting,
541 String targetName) {
Winson655a5b92019-10-23 10:49:32 -0700542 final List<ComponentParseUtils.ParsedInstrumentation> inst =
543 callingPkgSetting.pkg.getInstrumentations();
544 for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) {
545 if (Objects.equals(inst.get(i).getTargetPackage(), targetName)) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800546 if (DEBUG_LOGGING) {
547 log(callingPkgSetting, targetPkgSetting, "instrumentation");
548 }
549 return true;
550 }
551 }
552 return false;
Patrick Baumann0c9257b2019-08-20 12:50:37 -0700553 }
554
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800555 private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
556 String description) {
557 log(callingPkgSetting, targetPkgSetting, description, null);
558 }
559
560 private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
561 String description, Throwable throwable) {
562 Slog.wtf(TAG,
563 "interaction: " + callingPkgSetting.toString()
564 + " -> " + targetPkgSetting.name + " "
565 + description, throwable);
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700566 }
567
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700568 public void dumpQueries(
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800569 PrintWriter pw, PackageManagerService pms, @Nullable Integer filteringAppId,
570 DumpState dumpState,
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700571 int[] users) {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800572 final SparseArray<String> cache = new SparseArray<>();
573 ToString<Integer> expandPackages = input -> {
574 String cachedValue = cache.get(input);
575 if (cachedValue == null) {
576 final String[] packagesForUid = pms.getPackagesForUid(input);
577 if (packagesForUid == null) {
578 cachedValue = "[unknown app id " + input + "]";
579 } else {
580 cachedValue = packagesForUid.length == 1 ? packagesForUid[0]
581 : "[" + TextUtils.join(",", packagesForUid) + "]";
582 }
583 cache.put(input, cachedValue);
584 }
585 return cachedValue;
586 };
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700587 pw.println();
588 pw.println("Queries:");
589 dumpState.onTitlePrinted();
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800590 if (!mFeatureConfig.isGloballyEnabled()) {
591 pw.println(" DISABLED");
592 if (!DEBUG_LOGGING) {
593 return;
594 }
595 }
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700596 pw.println(" system apps queryable: " + mSystemAppsQueryable);
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800597 dumpPackageSet(pw, filteringAppId, mForceQueryable, "forceQueryable", " ", expandPackages);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700598 pw.println(" queries via package name:");
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800599 dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700600 pw.println(" queries via intent:");
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800601 dumpQueriesMap(pw, filteringAppId, mQueriesViaIntent, " ", expandPackages);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700602 pw.println(" queryable via interaction:");
603 for (int user : users) {
604 pw.append(" User ").append(Integer.toString(user)).println(":");
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800605 dumpQueriesMap(pw,
606 filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
607 mImplicitlyQueryable, " ", expandPackages);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700608 }
609 }
610
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800611 private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
612 SparseSetArray<Integer> queriesMap, String spacing,
613 @Nullable ToString<Integer> toString) {
614 for (int i = 0; i < queriesMap.size(); i++) {
615 Integer callingId = queriesMap.keyAt(i);
616 if (Objects.equals(callingId, filteringId)) {
617 // don't filter target package names if the calling is filteringId
618 dumpPackageSet(
619 pw, null /*filteringId*/, queriesMap.get(callingId),
620 toString == null
621 ? callingId.toString()
622 : toString.toString(callingId),
623 spacing, toString);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700624 } else {
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800625 dumpPackageSet(
626 pw, filteringId, queriesMap.get(callingId),
627 toString == null
628 ? callingId.toString()
629 : toString.toString(callingId),
630 spacing, toString);
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700631 }
632 }
633 }
634
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800635 private interface ToString<T> {
636 String toString(T input);
637 }
638
639 private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,
640 Set<T> targetPkgSet, String subTitle, String spacing,
641 @Nullable ToString<T> toString) {
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700642 if (targetPkgSet != null && targetPkgSet.size() > 0
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800643 && (filteringId == null || targetPkgSet.contains(filteringId))) {
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700644 pw.append(spacing).append(subTitle).println(":");
Patrick Baumannb9a49f42019-11-13 16:42:18 -0800645 for (T item : targetPkgSet) {
646 if (filteringId == null || Objects.equals(filteringId, item)) {
647 pw.append(spacing).append(" ")
648 .println(toString == null ? item : toString.toString(item));
Patrick Baumanna7ad66d2019-08-12 11:11:08 -0700649 }
650 }
651 }
652 }
Patrick Baumann6c1c8092019-06-27 14:55:44 -0700653}