blob: 5f6323369d0a57289ed3caa86955af4787fadc55 [file] [log] [blame]
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001/*
2 * Copyright (C) 2018 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.uri;
18
19import static android.Manifest.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS;
20import static android.Manifest.permission.FORCE_PERSISTABLE_URI_PERMISSIONS;
21import static android.Manifest.permission.GET_APP_GRANTED_URI_PERMISSIONS;
22import static android.Manifest.permission.INTERACT_ACROSS_USERS;
23import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
Jeff Sharkey51a14c02020-05-06 14:15:44 -060024import static android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
Jeff Sharkey1d194f9232020-04-11 21:12:58 -060025import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070026import static android.content.pm.PackageManager.MATCH_ANY_USER;
27import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
28import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
29import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
30import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
31import static android.content.pm.PackageManager.PERMISSION_GRANTED;
32import static android.os.Process.ROOT_UID;
33import static android.os.Process.SYSTEM_UID;
34import static android.os.Process.myUid;
Felipe Lemecf02e8a2018-08-10 16:48:21 -070035
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070036import static com.android.internal.util.XmlUtils.readBooleanAttribute;
37import static com.android.internal.util.XmlUtils.readIntAttribute;
38import static com.android.internal.util.XmlUtils.readLongAttribute;
39import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
40import static com.android.internal.util.XmlUtils.writeIntAttribute;
41import static com.android.internal.util.XmlUtils.writeLongAttribute;
42import static com.android.server.uri.UriGrantsManagerService.H.PERSIST_URI_GRANTS_MSG;
Felipe Lemecf02e8a2018-08-10 16:48:21 -070043
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070044import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
45import static org.xmlpull.v1.XmlPullParser.START_TAG;
46
47import android.annotation.Nullable;
48import android.app.ActivityManager;
49import android.app.ActivityManagerInternal;
50import android.app.AppGlobals;
51import android.app.GrantedUriPermission;
52import android.app.IUriGrantsManager;
53import android.content.ClipData;
54import android.content.ContentProvider;
55import android.content.ContentResolver;
56import android.content.Context;
57import android.content.Intent;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070058import android.content.pm.PackageManager;
59import android.content.pm.PackageManagerInternal;
60import android.content.pm.ParceledListSlice;
61import android.content.pm.PathPermission;
62import android.content.pm.ProviderInfo;
63import android.net.Uri;
64import android.os.Binder;
65import android.os.Handler;
66import android.os.IBinder;
67import android.os.Looper;
68import android.os.Message;
69import android.os.RemoteException;
70import android.os.SystemClock;
71import android.os.UserHandle;
72import android.provider.Downloads;
73import android.text.format.DateUtils;
74import android.util.ArrayMap;
75import android.util.AtomicFile;
76import android.util.Slog;
77import android.util.SparseArray;
78import android.util.Xml;
Felipe Lemecf02e8a2018-08-10 16:48:21 -070079
Jeff Sharkeya7f0b622020-06-02 12:51:18 -060080import com.android.internal.annotations.GuardedBy;
Jeff Sharkey1d194f9232020-04-11 21:12:58 -060081import com.android.internal.annotations.VisibleForTesting;
82import com.android.internal.util.ArrayUtils;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070083import com.android.internal.util.FastXmlSerializer;
84import com.android.internal.util.Preconditions;
85import com.android.server.IoThread;
86import com.android.server.LocalServices;
87import com.android.server.SystemService;
88import com.android.server.SystemServiceManager;
Felipe Lemecf02e8a2018-08-10 16:48:21 -070089
Jeff Sharkey1d194f9232020-04-11 21:12:58 -060090import libcore.io.IoUtils;
91
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070092import com.google.android.collect.Lists;
93import com.google.android.collect.Maps;
94
95import org.xmlpull.v1.XmlPullParser;
96import org.xmlpull.v1.XmlPullParserException;
97import org.xmlpull.v1.XmlSerializer;
98
99import java.io.File;
100import java.io.FileInputStream;
101import java.io.FileNotFoundException;
102import java.io.FileOutputStream;
103import java.io.IOException;
104import java.io.PrintWriter;
105import java.nio.charset.StandardCharsets;
106import java.util.ArrayList;
107import java.util.Collections;
108import java.util.Iterator;
109import java.util.List;
Daulet Zhanguzinee9d2242020-01-02 17:19:16 +0000110import java.util.Objects;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700111
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700112/** Manages uri grants. */
113public class UriGrantsManagerService extends IUriGrantsManager.Stub {
114 private static final boolean DEBUG = false;
115 private static final String TAG = "UriGrantsManagerService";
116 // Maximum number of persisted Uri grants a package is allowed
117 private static final int MAX_PERSISTED_URI_GRANTS = 128;
Jeff Sharkey5dad7cd2020-06-10 17:17:04 -0600118 private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700119
120 private final Object mLock = new Object();
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700121 private final H mH;
122 ActivityManagerInternal mAmInternal;
123 PackageManagerInternal mPmInternal;
124
125 /** File storing persisted {@link #mGrantedUriPermissions}. */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600126 @GuardedBy("mLock")
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700127 private final AtomicFile mGrantFile;
128
129 /** XML constants used in {@link #mGrantFile} */
130 private static final String TAG_URI_GRANTS = "uri-grants";
131 private static final String TAG_URI_GRANT = "uri-grant";
132 private static final String ATTR_USER_HANDLE = "userHandle";
133 private static final String ATTR_SOURCE_USER_ID = "sourceUserId";
134 private static final String ATTR_TARGET_USER_ID = "targetUserId";
135 private static final String ATTR_SOURCE_PKG = "sourcePkg";
136 private static final String ATTR_TARGET_PKG = "targetPkg";
137 private static final String ATTR_URI = "uri";
138 private static final String ATTR_MODE_FLAGS = "modeFlags";
139 private static final String ATTR_CREATED_TIME = "createdTime";
140 private static final String ATTR_PREFIX = "prefix";
141
142 /**
143 * Global set of specific {@link Uri} permissions that have been granted.
144 * This optimized lookup structure maps from {@link UriPermission#targetUid}
145 * to {@link UriPermission#uri} to {@link UriPermission}.
146 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600147 @GuardedBy("mLock")
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700148 private final SparseArray<ArrayMap<GrantUri, UriPermission>>
149 mGrantedUriPermissions = new SparseArray<>();
150
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600151 private UriGrantsManagerService() {
152 this(SystemServiceManager.ensureSystemDir());
153 }
154
155 private UriGrantsManagerService(File systemDir) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700156 mH = new H(IoThread.get().getLooper());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700157 mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
158 }
159
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600160 @VisibleForTesting
161 static UriGrantsManagerService createForTest(File systemDir) {
162 final UriGrantsManagerService service = new UriGrantsManagerService(systemDir);
163 service.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
164 service.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
165 return service;
166 }
167
168 @VisibleForTesting
169 UriGrantsManagerInternal getLocalService() {
170 return new LocalService();
171 }
172
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700173 private void start() {
174 LocalServices.addService(UriGrantsManagerInternal.class, new LocalService());
175 }
176
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700177 public static final class Lifecycle extends SystemService {
178 private final UriGrantsManagerService mService;
179
180 public Lifecycle(Context context) {
181 super(context);
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600182 mService = new UriGrantsManagerService();
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700183 }
184
185 @Override
186 public void onStart() {
187 publishBinderService(Context.URI_GRANTS_SERVICE, mService);
188 mService.start();
189 }
190
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600191 @Override
192 public void onBootPhase(int phase) {
193 if (phase == PHASE_SYSTEM_SERVICES_READY) {
194 mService.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
195 mService.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
196 }
197 }
198
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700199 public UriGrantsManagerService getService() {
200 return mService;
201 }
202 }
203
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600204 private int checkUidPermission(String permission, int uid) {
205 try {
206 return AppGlobals.getPackageManager().checkUidPermission(permission, uid);
207 } catch (RemoteException e) {
208 throw e.rethrowFromSystemServer();
209 }
210 }
211
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600212 @Override
213 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
214 Uri uri, final int modeFlags, int sourceUserId, int targetUserId) {
215 grantUriPermissionFromOwnerUnlocked(token, fromUid, targetPkg, uri, modeFlags, sourceUserId,
216 targetUserId);
217 }
218
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700219 /**
220 * @param uri This uri must NOT contain an embedded userId.
221 * @param sourceUserId The userId in which the uri is to be resolved.
222 * @param targetUserId The userId of the app that receives the grant.
223 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600224 private void grantUriPermissionFromOwnerUnlocked(IBinder token, int fromUid, String targetPkg,
225 Uri uri, final int modeFlags, int sourceUserId, int targetUserId) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700226 targetUserId = mAmInternal.handleIncomingUser(Binder.getCallingPid(),
227 Binder.getCallingUid(), targetUserId, false, ALLOW_FULL_ONLY,
228 "grantUriPermissionFromOwner", null);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700229
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600230 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
231 if (owner == null) {
232 throw new IllegalArgumentException("Unknown owner: " + token);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700233 }
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600234 if (fromUid != Binder.getCallingUid()) {
235 if (Binder.getCallingUid() != myUid()) {
236 // Only system code can grant URI permissions on behalf
237 // of other users.
238 throw new SecurityException("nice try");
239 }
240 }
241 if (targetPkg == null) {
242 throw new IllegalArgumentException("null target");
243 }
244 if (uri == null) {
245 throw new IllegalArgumentException("null uri");
246 }
247
248 grantUriPermissionUnlocked(fromUid, targetPkg, new GrantUri(sourceUserId, uri, modeFlags),
249 modeFlags, owner, targetUserId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700250 }
251
252 @Override
Sudheer Shanka1b817f62019-05-20 16:54:59 -0700253 public ParceledListSlice<android.content.UriPermission> getUriPermissions(
254 String packageName, boolean incoming, boolean persistedOnly) {
255 enforceNotIsolatedCaller("getUriPermissions");
Daulet Zhanguzinee9d2242020-01-02 17:19:16 +0000256 Objects.requireNonNull(packageName, "packageName");
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700257
258 final int callingUid = Binder.getCallingUid();
259 final int callingUserId = UserHandle.getUserId(callingUid);
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600260 final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
261 final int packageUid = pm.getPackageUidInternal(packageName,
262 MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, callingUserId);
263 if (packageUid != callingUid) {
264 throw new SecurityException(
265 "Package " + packageName + " does not belong to calling UID " + callingUid);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700266 }
267
268 final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
269 synchronized (mLock) {
270 if (incoming) {
271 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
272 callingUid);
273 if (perms == null) {
274 Slog.w(TAG, "No permission grants found for " + packageName);
275 } else {
276 for (int j = 0; j < perms.size(); j++) {
277 final UriPermission perm = perms.valueAt(j);
Sudheer Shanka1b817f62019-05-20 16:54:59 -0700278 if (packageName.equals(perm.targetPkg)
279 && (!persistedOnly || perm.persistedModeFlags != 0)) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700280 result.add(perm.buildPersistedPublicApiObject());
281 }
282 }
283 }
284 } else {
285 final int size = mGrantedUriPermissions.size();
286 for (int i = 0; i < size; i++) {
287 final ArrayMap<GrantUri, UriPermission> perms =
288 mGrantedUriPermissions.valueAt(i);
289 for (int j = 0; j < perms.size(); j++) {
290 final UriPermission perm = perms.valueAt(j);
Sudheer Shanka1b817f62019-05-20 16:54:59 -0700291 if (packageName.equals(perm.sourcePkg)
292 && (!persistedOnly || perm.persistedModeFlags != 0)) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700293 result.add(perm.buildPersistedPublicApiObject());
294 }
295 }
296 }
297 }
298 }
299 return new ParceledListSlice<>(result);
300 }
301
302 @Override
303 public ParceledListSlice<GrantedUriPermission> getGrantedUriPermissions(
304 @Nullable String packageName, int userId) {
305 mAmInternal.enforceCallingPermission(
306 GET_APP_GRANTED_URI_PERMISSIONS, "getGrantedUriPermissions");
307
308 final List<GrantedUriPermission> result = new ArrayList<>();
309 synchronized (mLock) {
310 final int size = mGrantedUriPermissions.size();
311 for (int i = 0; i < size; i++) {
312 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
313 for (int j = 0; j < perms.size(); j++) {
314 final UriPermission perm = perms.valueAt(j);
315 if ((packageName == null || packageName.equals(perm.targetPkg))
316 && perm.targetUserId == userId
317 && perm.persistedModeFlags != 0) {
318 result.add(perm.buildGrantedUriPermission());
319 }
320 }
321 }
322 }
323 return new ParceledListSlice<>(result);
324 }
325
326 /**
327 * @param uri This uri must NOT contain an embedded userId.
328 * @param toPackage Name of package whose uri is being granted to (if {@code null}, uses
329 * calling uid)
330 * @param userId The userId in which the uri is to be resolved.
331 */
332 @Override
333 public void takePersistableUriPermission(Uri uri, final int modeFlags,
334 @Nullable String toPackage, int userId) {
335 final int uid;
336 if (toPackage != null) {
337 mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
338 "takePersistableUriPermission");
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600339 uid = mPmInternal.getPackageUidInternal(toPackage, 0, userId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700340 } else {
341 enforceNotIsolatedCaller("takePersistableUriPermission");
342 uid = Binder.getCallingUid();
343 }
344
345 Preconditions.checkFlagsArgument(modeFlags,
346 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
347
348 synchronized (mLock) {
349 boolean persistChanged = false;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700350
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600351 UriPermission exactPerm = findUriPermissionLocked(uid,
352 new GrantUri(userId, uri, 0));
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700353 UriPermission prefixPerm = findUriPermissionLocked(uid,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600354 new GrantUri(userId, uri, FLAG_GRANT_PREFIX_URI_PERMISSION));
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700355
356 final boolean exactValid = (exactPerm != null)
357 && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
358 final boolean prefixValid = (prefixPerm != null)
359 && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
360
361 if (!(exactValid || prefixValid)) {
362 throw new SecurityException("No persistable permission grants found for UID "
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600363 + uid + " and Uri " + uri.toSafeString());
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700364 }
365
366 if (exactValid) {
367 persistChanged |= exactPerm.takePersistableModes(modeFlags);
368 }
369 if (prefixValid) {
370 persistChanged |= prefixPerm.takePersistableModes(modeFlags);
371 }
372
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600373 persistChanged |= maybePrunePersistedUriGrantsLocked(uid);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700374
375 if (persistChanged) {
376 schedulePersistUriGrants();
377 }
378 }
379 }
380
381 @Override
382 public void clearGrantedUriPermissions(String packageName, int userId) {
383 mAmInternal.enforceCallingPermission(
384 CLEAR_APP_GRANTED_URI_PERMISSIONS, "clearGrantedUriPermissions");
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600385 synchronized (mLock) {
386 removeUriPermissionsForPackageLocked(packageName, userId, true, true);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700387 }
388 }
389
390 /**
391 * @param uri This uri must NOT contain an embedded userId.
392 * @param toPackage Name of the target package whose uri is being released (if {@code null},
393 * uses calling uid)
394 * @param userId The userId in which the uri is to be resolved.
395 */
396 @Override
397 public void releasePersistableUriPermission(Uri uri, final int modeFlags,
398 @Nullable String toPackage, int userId) {
399
400 final int uid;
401 if (toPackage != null) {
402 mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
403 "releasePersistableUriPermission");
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600404 uid = mPmInternal.getPackageUidInternal(toPackage, 0, userId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700405 } else {
406 enforceNotIsolatedCaller("releasePersistableUriPermission");
407 uid = Binder.getCallingUid();
408 }
409
410 Preconditions.checkFlagsArgument(modeFlags,
411 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
412
413 synchronized (mLock) {
414 boolean persistChanged = false;
415
416 UriPermission exactPerm = findUriPermissionLocked(uid,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600417 new GrantUri(userId, uri, 0));
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700418 UriPermission prefixPerm = findUriPermissionLocked(uid,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600419 new GrantUri(userId, uri, FLAG_GRANT_PREFIX_URI_PERMISSION));
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700420 if (exactPerm == null && prefixPerm == null && toPackage == null) {
421 throw new SecurityException("No permission grants found for UID " + uid
422 + " and Uri " + uri.toSafeString());
423 }
424
425 if (exactPerm != null) {
426 persistChanged |= exactPerm.releasePersistableModes(modeFlags);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600427 removeUriPermissionIfNeededLocked(exactPerm);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700428 }
429 if (prefixPerm != null) {
430 persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600431 removeUriPermissionIfNeededLocked(prefixPerm);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700432 }
433
434 if (persistChanged) {
435 schedulePersistUriGrants();
436 }
437 }
438 }
439
440 /**
441 * Remove any {@link UriPermission} granted <em>from</em> or <em>to</em> the
442 * given package.
443 *
444 * @param packageName Package name to match, or {@code null} to apply to all
445 * packages.
446 * @param userHandle User to match, or {@link UserHandle#USER_ALL} to apply
447 * to all users.
448 * @param persistable If persistable grants should be removed.
449 * @param targetOnly When {@code true}, only remove permissions where the app is the target,
450 * not source.
451 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600452 @GuardedBy("mLock")
453 private void removeUriPermissionsForPackageLocked(String packageName, int userHandle,
454 boolean persistable, boolean targetOnly) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700455 if (userHandle == UserHandle.USER_ALL && packageName == null) {
456 throw new IllegalArgumentException("Must narrow by either package or user");
457 }
458
459 boolean persistChanged = false;
460
461 int N = mGrantedUriPermissions.size();
462 for (int i = 0; i < N; i++) {
463 final int targetUid = mGrantedUriPermissions.keyAt(i);
464 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
465
466 // Only inspect grants matching user
467 if (userHandle == UserHandle.USER_ALL
468 || userHandle == UserHandle.getUserId(targetUid)) {
469 for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
470 final UriPermission perm = it.next();
471
472 // Only inspect grants matching package
473 if (packageName == null || (!targetOnly && perm.sourcePkg.equals(packageName))
474 || perm.targetPkg.equals(packageName)) {
475 // Hacky solution as part of fixing a security bug; ignore
476 // grants associated with DownloadManager so we don't have
477 // to immediately launch it to regrant the permissions
478 if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority())
479 && !persistable) continue;
480
481 persistChanged |= perm.revokeModes(persistable
482 ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
483
484 // Only remove when no modes remain; any persisted grants
485 // will keep this alive.
486 if (perm.modeFlags == 0) {
487 it.remove();
488 }
489 }
490 }
491
492 if (perms.isEmpty()) {
493 mGrantedUriPermissions.remove(targetUid);
494 N--;
495 i--;
496 }
497 }
498 }
499
500 if (persistChanged) {
501 schedulePersistUriGrants();
502 }
503 }
504
505 /** Returns if the ContentProvider has granted a uri to callingUid */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600506 @GuardedBy("mLock")
507 private boolean checkAuthorityGrantsLocked(int callingUid, ProviderInfo cpi, int userId,
508 boolean checkUser) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700509 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
510 if (perms != null) {
511 for (int i = perms.size() - 1; i >= 0; i--) {
512 GrantUri grantUri = perms.keyAt(i);
513 if (grantUri.sourceUserId == userId || !checkUser) {
514 if (matchesProvider(grantUri.uri, cpi)) {
515 return true;
516 }
517 }
518 }
519 }
520 return false;
521 }
522
523 /** Returns true if the uri authority is one of the authorities specified in the provider. */
524 private boolean matchesProvider(Uri uri, ProviderInfo cpi) {
525 String uriAuth = uri.getAuthority();
526 String cpiAuth = cpi.authority;
527 if (cpiAuth.indexOf(';') == -1) {
528 return cpiAuth.equals(uriAuth);
529 }
530 String[] cpiAuths = cpiAuth.split(";");
531 int length = cpiAuths.length;
532 for (int i = 0; i < length; i++) {
533 if (cpiAuths[i].equals(uriAuth)) return true;
534 }
535 return false;
536 }
537
538 /**
539 * Prune any older {@link UriPermission} for the given UID until outstanding
540 * persisted grants are below {@link #MAX_PERSISTED_URI_GRANTS}.
541 *
542 * @return if any mutations occured that require persisting.
543 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600544 @GuardedBy("mLock")
545 private boolean maybePrunePersistedUriGrantsLocked(int uid) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700546 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
547 if (perms == null) return false;
548 if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
549
550 final ArrayList<UriPermission> persisted = Lists.newArrayList();
551 for (UriPermission perm : perms.values()) {
552 if (perm.persistedModeFlags != 0) {
553 persisted.add(perm);
554 }
555 }
556
557 final int trimCount = persisted.size() - MAX_PERSISTED_URI_GRANTS;
558 if (trimCount <= 0) return false;
559
560 Collections.sort(persisted, new UriPermission.PersistedTimeComparator());
561 for (int i = 0; i < trimCount; i++) {
562 final UriPermission perm = persisted.get(i);
563
564 if (DEBUG) Slog.v(TAG, "Trimming grant created at " + perm.persistedCreateTime);
565
566 perm.releasePersistableModes(~0);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600567 removeUriPermissionIfNeededLocked(perm);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700568 }
569
570 return true;
571 }
572
573 /** Like checkGrantUriPermission, but takes an Intent. */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600574 private NeededUriGrants checkGrantUriPermissionFromIntentUnlocked(int callingUid,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700575 String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
576 if (DEBUG) Slog.v(TAG,
577 "Checking URI perm to data=" + (intent != null ? intent.getData() : null)
578 + " clip=" + (intent != null ? intent.getClipData() : null)
579 + " from " + intent + "; flags=0x"
580 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
581
582 if (targetPkg == null) {
583 throw new NullPointerException("targetPkg");
584 }
585
586 if (intent == null) {
587 return null;
588 }
589 Uri data = intent.getData();
590 ClipData clip = intent.getClipData();
591 if (data == null && clip == null) {
592 return null;
593 }
594 // Default userId for uris in the intent (if they don't specify it themselves)
595 int contentUserHint = intent.getContentUserHint();
596 if (contentUserHint == UserHandle.USER_CURRENT) {
597 contentUserHint = UserHandle.getUserId(callingUid);
598 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700599 int targetUid;
600 if (needed != null) {
601 targetUid = needed.targetUid;
602 } else {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600603 targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
604 targetUserId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700605 if (targetUid < 0) {
606 if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg
607 + " on user " + targetUserId);
608 return null;
609 }
610 }
611 if (data != null) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600612 GrantUri grantUri = GrantUri.resolve(contentUserHint, data, mode);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600613 targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg, grantUri, mode,
614 targetUid);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700615 if (targetUid > 0) {
616 if (needed == null) {
617 needed = new NeededUriGrants(targetPkg, targetUid, mode);
618 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600619 needed.uris.add(grantUri);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700620 }
621 }
622 if (clip != null) {
623 for (int i=0; i<clip.getItemCount(); i++) {
624 Uri uri = clip.getItemAt(i).getUri();
625 if (uri != null) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600626 GrantUri grantUri = GrantUri.resolve(contentUserHint, uri, mode);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600627 targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700628 grantUri, mode, targetUid);
629 if (targetUid > 0) {
630 if (needed == null) {
631 needed = new NeededUriGrants(targetPkg, targetUid, mode);
632 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600633 needed.uris.add(grantUri);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700634 }
635 } else {
636 Intent clipIntent = clip.getItemAt(i).getIntent();
637 if (clipIntent != null) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600638 NeededUriGrants newNeeded = checkGrantUriPermissionFromIntentUnlocked(
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700639 callingUid, targetPkg, clipIntent, mode, needed, targetUserId);
640 if (newNeeded != null) {
641 needed = newNeeded;
642 }
643 }
644 }
645 }
646 }
647
648 return needed;
649 }
650
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600651 @GuardedBy("mLock")
652 private void readGrantedUriPermissionsLocked() {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700653 if (DEBUG) Slog.v(TAG, "readGrantedUriPermissions()");
654
655 final long now = System.currentTimeMillis();
656
657 FileInputStream fis = null;
658 try {
659 fis = mGrantFile.openRead();
660 final XmlPullParser in = Xml.newPullParser();
661 in.setInput(fis, StandardCharsets.UTF_8.name());
662
663 int type;
664 while ((type = in.next()) != END_DOCUMENT) {
665 final String tag = in.getName();
666 if (type == START_TAG) {
667 if (TAG_URI_GRANT.equals(tag)) {
668 final int sourceUserId;
669 final int targetUserId;
670 final int userHandle = readIntAttribute(in,
671 ATTR_USER_HANDLE, UserHandle.USER_NULL);
672 if (userHandle != UserHandle.USER_NULL) {
673 // For backwards compatibility.
674 sourceUserId = userHandle;
675 targetUserId = userHandle;
676 } else {
677 sourceUserId = readIntAttribute(in, ATTR_SOURCE_USER_ID);
678 targetUserId = readIntAttribute(in, ATTR_TARGET_USER_ID);
679 }
680 final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
681 final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
682 final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
683 final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
684 final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
685 final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
686
687 // Sanity check that provider still belongs to source package
688 // Both direct boot aware and unaware packages are fine as we
689 // will do filtering at query time to avoid multiple parsing.
690 final ProviderInfo pi = getProviderInfo(uri.getAuthority(), sourceUserId,
691 MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
692 if (pi != null && sourcePkg.equals(pi.packageName)) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600693 int targetUid = mPmInternal.getPackageUidInternal(
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700694 targetPkg, MATCH_UNINSTALLED_PACKAGES, targetUserId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700695 if (targetUid != -1) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600696 final GrantUri grantUri = new GrantUri(sourceUserId, uri,
697 prefix ? Intent.FLAG_GRANT_PREFIX_URI_PERMISSION : 0);
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600698 final UriPermission perm = findOrCreateUriPermissionLocked(
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600699 sourcePkg, targetPkg, targetUid, grantUri);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700700 perm.initPersistedModes(modeFlags, createdTime);
701 }
702 } else {
703 Slog.w(TAG, "Persisted grant for " + uri + " had source " + sourcePkg
704 + " but instead found " + pi);
705 }
706 }
707 }
708 }
709 } catch (FileNotFoundException e) {
710 // Missing grants is okay
711 } catch (IOException e) {
712 Slog.wtf(TAG, "Failed reading Uri grants", e);
713 } catch (XmlPullParserException e) {
714 Slog.wtf(TAG, "Failed reading Uri grants", e);
715 } finally {
716 IoUtils.closeQuietly(fis);
717 }
718 }
719
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600720 @GuardedBy("mLock")
721 private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700722 String targetPkg, int targetUid, GrantUri grantUri) {
723 ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
724 if (targetUris == null) {
725 targetUris = Maps.newArrayMap();
726 mGrantedUriPermissions.put(targetUid, targetUris);
727 }
728
729 UriPermission perm = targetUris.get(grantUri);
730 if (perm == null) {
731 perm = new UriPermission(sourcePkg, targetPkg, targetUid, grantUri);
732 targetUris.put(grantUri, perm);
733 }
734
735 return perm;
736 }
737
738 private void grantUriPermissionUnchecked(int targetUid, String targetPkg, GrantUri grantUri,
739 final int modeFlags, UriPermissionOwner owner) {
740 if (!Intent.isAccessUriMode(modeFlags)) {
741 return;
742 }
743
744 // So here we are: the caller has the assumed permission to the uri, and the target doesn't.
745 // Let's now give this to the target.
746
747 if (DEBUG) Slog.v(TAG,
748 "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
749
750 final String authority = grantUri.uri.getAuthority();
751 final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
752 MATCH_DEBUG_TRIAGED_MISSING);
753 if (pi == null) {
754 Slog.w(TAG, "No content provider found for grant: " + grantUri.toSafeString());
755 return;
756 }
757
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600758 final UriPermission perm;
759 synchronized (mLock) {
760 perm = findOrCreateUriPermissionLocked(pi.packageName, targetPkg, targetUid, grantUri);
761 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700762 perm.grantModes(modeFlags, owner);
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600763 mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null,
Patrick Baumann710d7202020-01-09 15:02:14 -0800764 UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700765 }
766
767 /** Like grantUriPermissionUnchecked, but takes an Intent. */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600768 private void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed,
769 UriPermissionOwner owner) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700770 if (needed == null) {
771 return;
772 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600773 final int N = needed.uris.size();
774 for (int i = 0; i < N; i++) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700775 grantUriPermissionUnchecked(needed.targetUid, needed.targetPkg,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600776 needed.uris.valueAt(i), needed.flags, owner);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700777 }
778 }
779
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600780 private void grantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700781 final int modeFlags, UriPermissionOwner owner, int targetUserId) {
782 if (targetPkg == null) {
783 throw new NullPointerException("targetPkg");
784 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600785 int targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
786 targetUserId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700787
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600788 targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg, grantUri, modeFlags,
789 targetUid);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700790 if (targetUid < 0) {
791 return;
792 }
793
794 grantUriPermissionUnchecked(targetUid, targetPkg, grantUri, modeFlags, owner);
795 }
796
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600797 private void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700798 final int modeFlags) {
799 if (DEBUG) Slog.v(TAG, "Revoking all granted permissions to " + grantUri);
800
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700801 final String authority = grantUri.uri.getAuthority();
802 final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
803 MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
804 if (pi == null) {
805 Slog.w(TAG, "No content provider found for permission revoke: "
806 + grantUri.toSafeString());
807 return;
808 }
809
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600810 final boolean callerHoldsPermissions = checkHoldingPermissionsUnlocked(pi, grantUri,
811 callingUid, modeFlags);
812 synchronized (mLock) {
813 revokeUriPermissionLocked(targetPackage, callingUid, grantUri, modeFlags,
814 callerHoldsPermissions);
815 }
816 }
817
818 @GuardedBy("mLock")
819 private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri,
820 final int modeFlags, final boolean callerHoldsPermissions) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700821 // Does the caller have this permission on the URI?
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600822 if (!callerHoldsPermissions) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700823 // If they don't have direct access to the URI, then revoke any
824 // ownerless URI permissions that have been granted to them.
825 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
826 if (perms != null) {
827 boolean persistChanged = false;
828 for (int i = perms.size()-1; i >= 0; i--) {
829 final UriPermission perm = perms.valueAt(i);
830 if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
831 continue;
832 }
833 if (perm.uri.sourceUserId == grantUri.sourceUserId
834 && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
835 if (DEBUG) Slog.v(TAG, "Revoking non-owned "
836 + perm.targetUid + " permission to " + perm.uri);
837 persistChanged |= perm.revokeModes(
838 modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
839 if (perm.modeFlags == 0) {
840 perms.removeAt(i);
841 }
842 }
843 }
844 if (perms.isEmpty()) {
845 mGrantedUriPermissions.remove(callingUid);
846 }
847 if (persistChanged) {
848 schedulePersistUriGrants();
849 }
850 }
851 return;
852 }
853
854 boolean persistChanged = false;
855
856 // Go through all of the permissions and remove any that match.
857 for (int i = mGrantedUriPermissions.size()-1; i >= 0; i--) {
858 final int targetUid = mGrantedUriPermissions.keyAt(i);
859 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
860
861 for (int j = perms.size()-1; j >= 0; j--) {
862 final UriPermission perm = perms.valueAt(j);
863 if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
864 continue;
865 }
866 if (perm.uri.sourceUserId == grantUri.sourceUserId
867 && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
868 if (DEBUG) Slog.v(TAG,
869 "Revoking " + perm.targetUid + " permission to " + perm.uri);
870 persistChanged |= perm.revokeModes(
871 modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION,
872 targetPackage == null);
873 if (perm.modeFlags == 0) {
874 perms.removeAt(j);
875 }
876 }
877 }
878
879 if (perms.isEmpty()) {
880 mGrantedUriPermissions.removeAt(i);
881 }
882 }
883
884 if (persistChanged) {
885 schedulePersistUriGrants();
886 }
887 }
888
889 /**
890 * Determine if UID is holding permissions required to access {@link Uri} in
891 * the given {@link ProviderInfo}. Final permission checking is always done
892 * in {@link ContentProvider}.
893 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600894 private boolean checkHoldingPermissionsUnlocked(
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600895 ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700896 if (DEBUG) Slog.v(TAG, "checkHoldingPermissions: uri=" + grantUri + " uid=" + uid);
897 if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
898 if (ActivityManager.checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
899 != PERMISSION_GRANTED) {
900 return false;
901 }
902 }
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600903 return checkHoldingPermissionsInternalUnlocked(pi, grantUri, uid, modeFlags, true);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700904 }
905
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600906 private boolean checkHoldingPermissionsInternalUnlocked(ProviderInfo pi,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700907 GrantUri grantUri, int uid, final int modeFlags, boolean considerUidPermissions) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -0600908 // We must never hold our local mLock in this method, since we may need
909 // to call into ActivityManager for dynamic permission checks
910 if (Thread.holdsLock(mLock)) {
911 throw new IllegalStateException("Must never hold local mLock");
912 }
913
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700914 if (pi.applicationInfo.uid == uid) {
915 return true;
916 } else if (!pi.exported) {
917 return false;
918 }
919
920 boolean readMet = (modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
921 boolean writeMet = (modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700922
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600923 // check if target holds top-level <provider> permissions
924 if (!readMet && pi.readPermission != null && considerUidPermissions
925 && (checkUidPermission(pi.readPermission, uid) == PERMISSION_GRANTED)) {
926 readMet = true;
927 }
928 if (!writeMet && pi.writePermission != null && considerUidPermissions
929 && (checkUidPermission(pi.writePermission, uid) == PERMISSION_GRANTED)) {
930 writeMet = true;
931 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700932
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600933 // track if unprotected read/write is allowed; any denied
934 // <path-permission> below removes this ability
935 boolean allowDefaultRead = pi.readPermission == null;
936 boolean allowDefaultWrite = pi.writePermission == null;
937
938 // check if target holds any <path-permission> that match uri
939 final PathPermission[] pps = pi.pathPermissions;
940 if (pps != null) {
941 final String path = grantUri.uri.getPath();
942 int i = pps.length;
943 while (i > 0 && (!readMet || !writeMet)) {
944 i--;
945 PathPermission pp = pps[i];
946 if (pp.match(path)) {
947 if (!readMet) {
948 final String pprperm = pp.getReadPermission();
949 if (DEBUG) Slog.v(TAG,
950 "Checking read perm for " + pprperm + " for " + pp.getPath()
951 + ": match=" + pp.match(path)
952 + " check=" + checkUidPermission(pprperm, uid));
953 if (pprperm != null) {
954 if (considerUidPermissions && checkUidPermission(pprperm, uid)
955 == PERMISSION_GRANTED) {
956 readMet = true;
957 } else {
958 allowDefaultRead = false;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700959 }
960 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600961 }
962 if (!writeMet) {
963 final String ppwperm = pp.getWritePermission();
964 if (DEBUG) Slog.v(TAG,
965 "Checking write perm " + ppwperm + " for " + pp.getPath()
966 + ": match=" + pp.match(path)
967 + " check=" + checkUidPermission(ppwperm, uid));
968 if (ppwperm != null) {
969 if (considerUidPermissions && checkUidPermission(ppwperm, uid)
970 == PERMISSION_GRANTED) {
971 writeMet = true;
972 } else {
973 allowDefaultWrite = false;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700974 }
975 }
976 }
977 }
978 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700979 }
980
Jeff Sharkey1d194f9232020-04-11 21:12:58 -0600981 // grant unprotected <provider> read/write, if not blocked by
982 // <path-permission> above
983 if (allowDefaultRead) readMet = true;
984 if (allowDefaultWrite) writeMet = true;
985
Jeff Sharkey9edef252019-05-20 14:00:17 -0600986 // If this provider says that grants are always required, we need to
987 // consult it directly to determine if the UID has permission
988 final boolean forceMet;
Jeff Sharkeyb1c88b72019-07-19 16:23:26 -0600989 if (ENABLE_DYNAMIC_PERMISSIONS && pi.forceUriPermissions) {
Jeff Sharkey9edef252019-05-20 14:00:17 -0600990 final int providerUserId = UserHandle.getUserId(pi.applicationInfo.uid);
991 final int clientUserId = UserHandle.getUserId(uid);
992 if (providerUserId == clientUserId) {
993 forceMet = (mAmInternal.checkContentProviderUriPermission(grantUri.uri,
994 providerUserId, uid, modeFlags) == PackageManager.PERMISSION_GRANTED);
995 } else {
996 // The provider can't track cross-user permissions, so we have
997 // to assume they're always denied
998 forceMet = false;
999 }
1000 } else {
1001 forceMet = true;
1002 }
1003
1004 return readMet && writeMet && forceMet;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001005 }
1006
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001007 @GuardedBy("mLock")
1008 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001009 if (perm.modeFlags != 0) {
1010 return;
1011 }
1012 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
1013 perm.targetUid);
1014 if (perms == null) {
1015 return;
1016 }
1017 if (DEBUG) Slog.v(TAG, "Removing " + perm.targetUid + " permission to " + perm.uri);
1018
1019 perms.remove(perm.uri);
1020 if (perms.isEmpty()) {
1021 mGrantedUriPermissions.remove(perm.targetUid);
1022 }
1023 }
1024
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001025 @GuardedBy("mLock")
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001026 private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
1027 final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
1028 if (targetUris != null) {
1029 return targetUris.get(grantUri);
1030 }
1031 return null;
1032 }
1033
1034 private void schedulePersistUriGrants() {
1035 if (!mH.hasMessages(PERSIST_URI_GRANTS_MSG)) {
1036 mH.sendMessageDelayed(mH.obtainMessage(PERSIST_URI_GRANTS_MSG),
1037 10 * DateUtils.SECOND_IN_MILLIS);
1038 }
1039 }
1040
1041 private void enforceNotIsolatedCaller(String caller) {
1042 if (UserHandle.isIsolated(Binder.getCallingUid())) {
1043 throw new SecurityException("Isolated process not allowed to call " + caller);
1044 }
1045 }
1046
1047 private ProviderInfo getProviderInfo(String authority, int userHandle, int pmFlags) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001048 return mPmInternal.resolveContentProvider(authority,
1049 PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userHandle);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001050 }
1051
1052 /**
1053 * Check if the targetPkg can be granted permission to access uri by
1054 * the callingUid using the given modeFlags. Throws a security exception
1055 * if callingUid is not allowed to do this. Returns the uid of the target
1056 * if the URI permission grant should be performed; returns -1 if it is not
1057 * needed (for example targetPkg already has permission to access the URI).
1058 * If you already know the uid of the target, you can supply it in
1059 * lastTargetUid else set that to -1.
1060 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001061 private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001062 int modeFlags, int lastTargetUid) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001063 if (!Intent.isAccessUriMode(modeFlags)) {
1064 return -1;
1065 }
1066
1067 if (targetPkg != null) {
1068 if (DEBUG) Slog.v(TAG, "Checking grant " + targetPkg + " permission to " + grantUri);
1069 }
1070
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001071 // If this is not a content: uri, we can't do anything with it.
1072 if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
1073 if (DEBUG) Slog.v(TAG, "Can't grant URI permission for non-content URI: " + grantUri);
1074 return -1;
1075 }
1076
1077 // Bail early if system is trying to hand out permissions directly; it
1078 // must always grant permissions on behalf of someone explicit.
1079 final int callingAppId = UserHandle.getAppId(callingUid);
1080 if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
Andrew Sapperstein93f5ed62019-06-20 15:25:19 -07001081 if ("com.android.settings.files".equals(grantUri.uri.getAuthority())
1082 || "com.android.settings.module_licenses".equals(grantUri.uri.getAuthority())) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001083 // Exempted authority for
1084 // 1. cropping user photos and sharing a generated license html
1085 // file in Settings app
1086 // 2. sharing a generated license html file in TvSettings app
Andrew Sapperstein93f5ed62019-06-20 15:25:19 -07001087 // 3. Sharing module license files from Settings app
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001088 } else {
1089 Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
1090 + " grant to " + grantUri + "; use startActivityAsCaller() instead");
1091 return -1;
1092 }
1093 }
1094
1095 final String authority = grantUri.uri.getAuthority();
1096 final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
1097 MATCH_DEBUG_TRIAGED_MISSING);
1098 if (pi == null) {
1099 Slog.w(TAG, "No content provider found for permission check: " +
1100 grantUri.uri.toSafeString());
1101 return -1;
1102 }
1103
1104 int targetUid = lastTargetUid;
1105 if (targetUid < 0 && targetPkg != null) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001106 targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
1107 UserHandle.getUserId(callingUid));
1108 if (targetUid < 0) {
1109 if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001110 return -1;
1111 }
1112 }
1113
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001114 boolean targetHoldsPermission = false;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001115 if (targetUid >= 0) {
1116 // First... does the target actually need this permission?
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001117 if (checkHoldingPermissionsUnlocked(pi, grantUri, targetUid, modeFlags)) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001118 // No need to grant the target this permission.
1119 if (DEBUG) Slog.v(TAG,
1120 "Target " + targetPkg + " already has full permission to " + grantUri);
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001121 targetHoldsPermission = true;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001122 }
1123 } else {
1124 // First... there is no target package, so can anyone access it?
1125 boolean allowed = pi.exported;
1126 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1127 if (pi.readPermission != null) {
1128 allowed = false;
1129 }
1130 }
1131 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1132 if (pi.writePermission != null) {
1133 allowed = false;
1134 }
1135 }
1136 if (pi.pathPermissions != null) {
1137 final int N = pi.pathPermissions.length;
1138 for (int i=0; i<N; i++) {
1139 if (pi.pathPermissions[i] != null
1140 && pi.pathPermissions[i].match(grantUri.uri.getPath())) {
1141 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1142 if (pi.pathPermissions[i].getReadPermission() != null) {
1143 allowed = false;
1144 }
1145 }
1146 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1147 if (pi.pathPermissions[i].getWritePermission() != null) {
1148 allowed = false;
1149 }
1150 }
1151 break;
1152 }
1153 }
1154 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001155 if (allowed) {
1156 targetHoldsPermission = true;
1157 }
1158 }
1159
Jeff Sharkeyedb79a92020-04-24 19:21:20 -06001160 if (pi.forceUriPermissions) {
1161 // When provider requires dynamic permission checks, the only
1162 // way to be safe is to issue permission grants for each item by
1163 // assuming no generic access
1164 targetHoldsPermission = false;
1165 }
1166
Jeff Sharkey51a14c02020-05-06 14:15:44 -06001167 final boolean basicGrant = (modeFlags
1168 & (FLAG_GRANT_PERSISTABLE_URI_PERMISSION | FLAG_GRANT_PREFIX_URI_PERMISSION)) == 0;
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001169 if (basicGrant && targetHoldsPermission) {
1170 // When caller holds permission, and this is a simple permission
1171 // grant, we can skip generating any bookkeeping; when any advanced
1172 // features have been requested, we proceed below to make sure the
1173 // provider supports granting permissions
1174 return -1;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001175 }
1176
1177 /* There is a special cross user grant if:
1178 * - The target is on another user.
1179 * - Apps on the current user can access the uri without any uid permissions.
1180 * In this case, we grant a uri permission, even if the ContentProvider does not normally
1181 * grant uri permissions.
1182 */
Nicholas Sauerfaa877f2018-12-20 19:31:03 -08001183 boolean specialCrossUserGrant = targetUid >= 0
1184 && UserHandle.getUserId(targetUid) != grantUri.sourceUserId
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001185 && checkHoldingPermissionsInternalUnlocked(pi, grantUri, callingUid,
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001186 modeFlags, false /*without considering the uid permissions*/);
1187
1188 // Second... is the provider allowing granting of URI permissions?
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001189 boolean grantAllowed = pi.grantUriPermissions;
1190 if (!ArrayUtils.isEmpty(pi.uriPermissionPatterns)) {
1191 final int N = pi.uriPermissionPatterns.length;
1192 grantAllowed = false;
1193 for (int i = 0; i < N; i++) {
1194 if (pi.uriPermissionPatterns[i] != null
1195 && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) {
1196 grantAllowed = true;
1197 break;
1198 }
1199 }
1200 }
1201 if (!grantAllowed) {
1202 if (specialCrossUserGrant) {
1203 // We're only okay issuing basic grant access across user
1204 // boundaries; advanced flags are blocked here
1205 if (!basicGrant) {
1206 throw new SecurityException("Provider " + pi.packageName
1207 + "/" + pi.name
1208 + " does not allow granting of advanced Uri permissions (uri "
1209 + grantUri + ")");
1210 }
1211 } else {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001212 throw new SecurityException("Provider " + pi.packageName
1213 + "/" + pi.name
1214 + " does not allow granting of Uri permissions (uri "
1215 + grantUri + ")");
1216 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001217 }
1218
1219 // Third... does the caller itself have permission to access this uri?
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001220 if (!checkHoldingPermissionsUnlocked(pi, grantUri, callingUid, modeFlags)) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001221 // Require they hold a strong enough Uri permission
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001222 final boolean res;
1223 synchronized (mLock) {
1224 res = checkUriPermissionLocked(grantUri, callingUid, modeFlags);
1225 }
1226 if (!res) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001227 if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(pi.readPermission)) {
1228 throw new SecurityException(
1229 "UID " + callingUid + " does not have permission to " + grantUri
1230 + "; you could obtain access using ACTION_OPEN_DOCUMENT "
1231 + "or related APIs");
1232 } else {
1233 throw new SecurityException(
1234 "UID " + callingUid + " does not have permission to " + grantUri);
1235 }
1236 }
1237 }
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001238
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001239 return targetUid;
1240 }
1241
1242 /**
1243 * @param userId The userId in which the uri is to be resolved.
1244 */
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001245 private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, Uri uri,
1246 int modeFlags, int userId) {
1247 return checkGrantUriPermissionUnlocked(callingUid, targetPkg,
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001248 new GrantUri(userId, uri, modeFlags), modeFlags, -1);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001249 }
1250
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001251 @GuardedBy("mLock")
1252 private boolean checkUriPermissionLocked(GrantUri grantUri, int uid, final int modeFlags) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001253 final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
1254 final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
1255 : UriPermission.STRENGTH_OWNED;
1256
1257 // Root gets to do everything.
1258 if (uid == 0) {
1259 return true;
1260 }
1261
1262 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
1263 if (perms == null) return false;
1264
1265 // First look for exact match
1266 final UriPermission exactPerm = perms.get(grantUri);
1267 if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
1268 return true;
1269 }
1270
1271 // No exact match, look for prefixes
1272 final int N = perms.size();
1273 for (int i = 0; i < N; i++) {
1274 final UriPermission perm = perms.valueAt(i);
1275 if (perm.uri.prefix && grantUri.uri.isPathPrefixMatch(perm.uri.uri)
1276 && perm.getStrength(modeFlags) >= minStrength) {
1277 return true;
1278 }
1279 }
1280
1281 return false;
1282 }
1283
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001284 @GuardedBy("mLock")
1285 private void writeGrantedUriPermissionsLocked() {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001286 if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");
1287
1288 final long startTime = SystemClock.uptimeMillis();
1289
1290 // Snapshot permissions so we can persist without lock
1291 ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
1292 synchronized (this) {
1293 final int size = mGrantedUriPermissions.size();
1294 for (int i = 0; i < size; i++) {
1295 final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
1296 for (UriPermission perm : perms.values()) {
1297 if (perm.persistedModeFlags != 0) {
1298 persist.add(perm.snapshot());
1299 }
1300 }
1301 }
1302 }
1303
1304 FileOutputStream fos = null;
1305 try {
1306 fos = mGrantFile.startWrite(startTime);
1307
1308 XmlSerializer out = new FastXmlSerializer();
1309 out.setOutput(fos, StandardCharsets.UTF_8.name());
1310 out.startDocument(null, true);
1311 out.startTag(null, TAG_URI_GRANTS);
1312 for (UriPermission.Snapshot perm : persist) {
1313 out.startTag(null, TAG_URI_GRANT);
1314 writeIntAttribute(out, ATTR_SOURCE_USER_ID, perm.uri.sourceUserId);
1315 writeIntAttribute(out, ATTR_TARGET_USER_ID, perm.targetUserId);
1316 out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
1317 out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
1318 out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
1319 writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
1320 writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
1321 writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
1322 out.endTag(null, TAG_URI_GRANT);
1323 }
1324 out.endTag(null, TAG_URI_GRANTS);
1325 out.endDocument();
1326
1327 mGrantFile.finishWrite(fos);
1328 } catch (IOException e) {
1329 if (fos != null) {
1330 mGrantFile.failWrite(fos);
1331 }
1332 }
1333 }
1334
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001335 final class H extends Handler {
1336 static final int PERSIST_URI_GRANTS_MSG = 1;
1337
1338 public H(Looper looper) {
1339 super(looper, null, true);
1340 }
1341
1342 @Override
1343 public void handleMessage(Message msg) {
1344 switch (msg.what) {
1345 case PERSIST_URI_GRANTS_MSG: {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001346 synchronized (mLock) {
1347 writeGrantedUriPermissionsLocked();
1348 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001349 break;
1350 }
1351 }
1352 }
1353 }
1354
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001355 private final class LocalService implements UriGrantsManagerInternal {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001356 @Override
1357 public void removeUriPermissionIfNeeded(UriPermission perm) {
1358 synchronized (mLock) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001359 UriGrantsManagerService.this.removeUriPermissionIfNeededLocked(perm);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001360 }
1361 }
1362
1363 @Override
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001364 public void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
1365 int modeFlags) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001366 UriGrantsManagerService.this.revokeUriPermission(
1367 targetPackage, callingUid, grantUri, modeFlags);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001368 }
1369
1370 @Override
1371 public boolean checkUriPermission(GrantUri grantUri, int uid, int modeFlags) {
1372 synchronized (mLock) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001373 return UriGrantsManagerService.this.checkUriPermissionLocked(grantUri, uid,
1374 modeFlags);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001375 }
1376 }
1377
1378 @Override
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001379 public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, int modeFlags,
1380 int userId) {
1381 enforceNotIsolatedCaller("checkGrantUriPermission");
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001382 return UriGrantsManagerService.this.checkGrantUriPermissionUnlocked(
1383 callingUid, targetPkg, uri, modeFlags, userId);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001384 }
1385
1386 @Override
Jeff Sharkey938089f2020-04-12 16:00:04 -06001387 public NeededUriGrants checkGrantUriPermissionFromIntent(Intent intent, int callingUid,
1388 String targetPkg, int targetUserId) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001389 final int mode = (intent != null) ? intent.getFlags() : 0;
1390 return UriGrantsManagerService.this.checkGrantUriPermissionFromIntentUnlocked(
1391 callingUid, targetPkg, intent, mode, null, targetUserId);
Wale Ogunwale586a8ee2019-06-04 13:44:14 +00001392 }
1393
1394 @Override
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001395 public void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed,
1396 UriPermissionOwner owner) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001397 UriGrantsManagerService.this.grantUriPermissionUncheckedFromIntent(needed, owner);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001398 }
1399
1400 @Override
1401 public void onSystemReady() {
1402 synchronized (mLock) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001403 UriGrantsManagerService.this.readGrantedUriPermissionsLocked();
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001404 }
1405 }
1406
1407 @Override
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001408 public IBinder newUriPermissionOwner(String name) {
1409 enforceNotIsolatedCaller("newUriPermissionOwner");
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001410 UriPermissionOwner owner = new UriPermissionOwner(this, name);
1411 return owner.getExternalToken();
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001412 }
1413
1414 @Override
1415 public void removeUriPermissionsForPackage(String packageName, int userHandle,
1416 boolean persistable, boolean targetOnly) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001417 synchronized (mLock) {
1418 UriGrantsManagerService.this.removeUriPermissionsForPackageLocked(
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001419 packageName, userHandle, persistable, targetOnly);
1420 }
1421 }
1422
1423 @Override
1424 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001425 final UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
1426 if (owner == null) {
1427 throw new IllegalArgumentException("Unknown owner: " + token);
1428 }
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001429
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001430 if (uri == null) {
1431 owner.removeUriPermissions(mode);
1432 } else {
1433 owner.removeUriPermission(new GrantUri(userId, uri, mode), mode);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001434 }
1435 }
1436
1437 @Override
1438 public boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId,
1439 boolean checkUser) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001440 synchronized (mLock) {
1441 return UriGrantsManagerService.this.checkAuthorityGrantsLocked(
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001442 callingUid, cpi, userId, checkUser);
1443 }
1444 }
1445
1446 @Override
1447 public void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
Jeff Sharkeya7f0b622020-06-02 12:51:18 -06001448 synchronized (mLock) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001449 boolean needSep = false;
1450 boolean printedAnything = false;
1451 if (mGrantedUriPermissions.size() > 0) {
1452 boolean printed = false;
1453 int dumpUid = -2;
1454 if (dumpPackage != null) {
Jeff Sharkey1d194f9232020-04-11 21:12:58 -06001455 dumpUid = mPmInternal.getPackageUidInternal(dumpPackage, MATCH_ANY_USER, 0);
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -07001456 }
1457 for (int i = 0; i < mGrantedUriPermissions.size(); i++) {
1458 int uid = mGrantedUriPermissions.keyAt(i);
1459 if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
1460 continue;
1461 }
1462 final ArrayMap<GrantUri, UriPermission> perms =
1463 mGrantedUriPermissions.valueAt(i);
1464 if (!printed) {
1465 if (needSep) pw.println();
1466 needSep = true;
1467 pw.println(" Granted Uri Permissions:");
1468 printed = true;
1469 printedAnything = true;
1470 }
1471 pw.print(" * UID "); pw.print(uid); pw.println(" holds:");
1472 for (UriPermission perm : perms.values()) {
1473 pw.print(" "); pw.println(perm);
1474 if (dumpAll) {
1475 perm.dump(pw, " ");
1476 }
1477 }
1478 }
1479 }
1480
1481 if (!printedAnything) {
1482 pw.println(" (nothing)");
1483 }
1484 }
1485 }
1486 }
1487}