• 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.pm;
18 
19 import android.Manifest;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 
25 import com.android.internal.util.ArrayUtils;
26 import com.android.server.pm.parsing.pkg.AndroidPackage;
27 import com.android.server.pm.pkg.PackageStateInternal;
28 import com.android.server.pm.pkg.component.ParsedComponent;
29 import com.android.server.pm.pkg.component.ParsedIntentInfo;
30 import com.android.server.pm.pkg.component.ParsedMainComponent;
31 import com.android.server.pm.pkg.component.ParsedProvider;
32 import com.android.server.utils.WatchedArrayList;
33 
34 import java.util.List;
35 import java.util.Set;
36 import java.util.StringTokenizer;
37 
38 final class AppsFilterUtils {
requestsQueryAllPackages(@onNull AndroidPackage pkg)39     public static boolean requestsQueryAllPackages(@NonNull AndroidPackage pkg) {
40         // we're not guaranteed to have permissions yet analyzed at package add, so we inspect the
41         // package directly
42         return pkg.getRequestedPermissions().contains(
43                 Manifest.permission.QUERY_ALL_PACKAGES);
44     }
45 
46     /** Returns true if the querying package may query for the potential target package */
canQueryViaComponents(AndroidPackage querying, AndroidPackage potentialTarget, WatchedArrayList<String> protectedBroadcasts)47     public static boolean canQueryViaComponents(AndroidPackage querying,
48             AndroidPackage potentialTarget, WatchedArrayList<String> protectedBroadcasts) {
49         if (!querying.getQueriesIntents().isEmpty()) {
50             for (Intent intent : querying.getQueriesIntents()) {
51                 if (matchesPackage(intent, potentialTarget, protectedBroadcasts)) {
52                     return true;
53                 }
54             }
55         }
56         if (!querying.getQueriesProviders().isEmpty()
57                 && matchesProviders(querying.getQueriesProviders(), potentialTarget)) {
58             return true;
59         }
60         return false;
61     }
62 
canQueryViaPackage(AndroidPackage querying, AndroidPackage potentialTarget)63     public static boolean canQueryViaPackage(AndroidPackage querying,
64             AndroidPackage potentialTarget) {
65         return !querying.getQueriesPackages().isEmpty()
66                 && querying.getQueriesPackages().contains(potentialTarget.getPackageName());
67     }
68 
canQueryAsInstaller(PackageStateInternal querying, AndroidPackage potentialTarget)69     public static boolean canQueryAsInstaller(PackageStateInternal querying,
70             AndroidPackage potentialTarget) {
71         final InstallSource installSource = querying.getInstallSource();
72         if (potentialTarget.getPackageName().equals(installSource.installerPackageName)) {
73             return true;
74         }
75         if (!installSource.isInitiatingPackageUninstalled
76                 && potentialTarget.getPackageName().equals(installSource.initiatingPackageName)) {
77             return true;
78         }
79         return false;
80     }
81 
canQueryViaUsesLibrary(AndroidPackage querying, AndroidPackage potentialTarget)82     public static boolean canQueryViaUsesLibrary(AndroidPackage querying,
83             AndroidPackage potentialTarget) {
84         if (potentialTarget.getLibraryNames().isEmpty()) {
85             return false;
86         }
87         final List<String> libNames = potentialTarget.getLibraryNames();
88         for (int i = 0, size = libNames.size(); i < size; i++) {
89             final String libName = libNames.get(i);
90             if (querying.getUsesLibraries().contains(libName)
91                     || querying.getUsesOptionalLibraries().contains(libName)) {
92                 return true;
93             }
94         }
95         return false;
96     }
97 
matchesProviders( Set<String> queriesAuthorities, AndroidPackage potentialTarget)98     private static boolean matchesProviders(
99             Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
100         for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
101             ParsedProvider provider = potentialTarget.getProviders().get(p);
102             if (!provider.isExported()) {
103                 continue;
104             }
105             if (provider.getAuthority() == null) {
106                 continue;
107             }
108             StringTokenizer authorities = new StringTokenizer(provider.getAuthority(), ";",
109                     false);
110             while (authorities.hasMoreElements()) {
111                 if (queriesAuthorities.contains(authorities.nextToken())) {
112                     return true;
113                 }
114             }
115         }
116         return false;
117     }
118 
matchesPackage(Intent intent, AndroidPackage potentialTarget, WatchedArrayList<String> protectedBroadcasts)119     private static boolean matchesPackage(Intent intent, AndroidPackage potentialTarget,
120             WatchedArrayList<String> protectedBroadcasts) {
121         if (matchesAnyComponents(
122                 intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) {
123             return true;
124         }
125         if (matchesAnyComponents(
126                 intent, potentialTarget.getActivities(), null /*protectedBroadcasts*/)) {
127             return true;
128         }
129         if (matchesAnyComponents(intent, potentialTarget.getReceivers(), protectedBroadcasts)) {
130             return true;
131         }
132         if (matchesAnyComponents(
133                 intent, potentialTarget.getProviders(), null /*protectedBroadcasts*/)) {
134             return true;
135         }
136         return false;
137     }
138 
matchesAnyComponents(Intent intent, List<? extends ParsedMainComponent> components, WatchedArrayList<String> protectedBroadcasts)139     private static boolean matchesAnyComponents(Intent intent,
140             List<? extends ParsedMainComponent> components,
141             WatchedArrayList<String> protectedBroadcasts) {
142         for (int i = ArrayUtils.size(components) - 1; i >= 0; i--) {
143             ParsedMainComponent component = components.get(i);
144             if (!component.isExported()) {
145                 continue;
146             }
147             if (matchesAnyFilter(intent, component, protectedBroadcasts)) {
148                 return true;
149             }
150         }
151         return false;
152     }
153 
matchesAnyFilter(Intent intent, ParsedComponent component, WatchedArrayList<String> protectedBroadcasts)154     private static boolean matchesAnyFilter(Intent intent, ParsedComponent component,
155             WatchedArrayList<String> protectedBroadcasts) {
156         List<ParsedIntentInfo> intents = component.getIntents();
157         for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
158             IntentFilter intentFilter = intents.get(i).getIntentFilter();
159             if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) {
160                 return true;
161             }
162         }
163         return false;
164     }
165 
matchesIntentFilter(Intent intent, IntentFilter intentFilter, @Nullable WatchedArrayList<String> protectedBroadcasts)166     private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter,
167             @Nullable WatchedArrayList<String> protectedBroadcasts) {
168         return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
169                 intent.getData(), intent.getCategories(), "AppsFilter", true,
170                 protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;
171     }
172 }
173