blob: 284086dcbd799fcb71e881fb201accb12be6dfed [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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.am;
18
19import android.content.Intent;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070020import android.os.UserHandle;
Jeff Sharkey846318a2014-04-04 12:12:41 -070021import android.util.ArraySet;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070022import android.util.Log;
Jeff Sharkey846318a2014-04-04 12:12:41 -070023import android.util.Slog;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070024
Jeff Sharkey846318a2014-04-04 12:12:41 -070025import com.android.server.am.ActivityManagerService.GrantUri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070026import com.google.android.collect.Sets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28import java.io.PrintWriter;
Jeff Sharkeye66c1772013-09-20 14:30:59 -070029import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Dianne Hackborn7e269642010-08-25 19:50:20 -070031/**
32 * Description of a permission granted to an app to access a particular URI.
33 *
34 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
35 *
Dianne Hackborncca1f0e2010-09-26 18:34:53 -070036 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
37 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
Dianne Hackborn7e269642010-08-25 19:50:20 -070038 */
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070039final class UriPermission {
Jeff Sharkey328ebf22013-03-21 18:09:39 -070040 private static final String TAG = "UriPermission";
41
Jeff Sharkeye66c1772013-09-20 14:30:59 -070042 public static final int STRENGTH_NONE = 0;
43 public static final int STRENGTH_OWNED = 1;
44 public static final int STRENGTH_GLOBAL = 2;
45 public static final int STRENGTH_PERSISTABLE = 3;
46
Nicolas Prevotd85fc722014-04-16 19:52:08 +010047 final int targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070048 final String sourcePkg;
49 final String targetPkg;
50
51 /** Cached UID of {@link #targetPkg}; should not be persisted */
52 final int targetUid;
53
Jeff Sharkey846318a2014-04-04 12:12:41 -070054 final GrantUri uri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070055
56 /**
57 * Allowed modes. All permission enforcement should use this field. Must
Jeff Sharkeye66c1772013-09-20 14:30:59 -070058 * always be a combination of {@link #ownedModeFlags},
59 * {@link #globalModeFlags}, {@link #persistableModeFlags}, and
60 * {@link #persistedModeFlags}. Mutations <em>must</em> only be performed by
61 * the owning class.
Jeff Sharkey328ebf22013-03-21 18:09:39 -070062 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 int modeFlags = 0;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070064
Jeff Sharkey846318a2014-04-04 12:12:41 -070065 /** Allowed modes with active owner. */
Jeff Sharkeye66c1772013-09-20 14:30:59 -070066 int ownedModeFlags = 0;
67 /** Allowed modes without explicit owner. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 int globalModeFlags = 0;
Jeff Sharkeye66c1772013-09-20 14:30:59 -070069 /** Allowed modes that have been offered for possible persisting. */
70 int persistableModeFlags = 0;
Jeff Sharkey846318a2014-04-04 12:12:41 -070071
Jeff Sharkeye66c1772013-09-20 14:30:59 -070072 /** Allowed modes that should be persisted across device boots. */
73 int persistedModeFlags = 0;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070074
75 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -070076 * Timestamp when {@link #persistedModeFlags} was first defined in
77 * {@link System#currentTimeMillis()} time base.
Jeff Sharkey328ebf22013-03-21 18:09:39 -070078 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -070079 long persistedCreateTime = INVALID_TIME;
80
81 private static final long INVALID_TIME = Long.MIN_VALUE;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070082
Jeff Sharkey846318a2014-04-04 12:12:41 -070083 private ArraySet<UriPermissionOwner> mReadOwners;
84 private ArraySet<UriPermissionOwner> mWriteOwners;
Jeff Sharkey328ebf22013-03-21 18:09:39 -070085
86 private String stringName;
87
Jeff Sharkey846318a2014-04-04 12:12:41 -070088 UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
Nicolas Prevotd85fc722014-04-16 19:52:08 +010089 this.targetUserId = UserHandle.getUserId(targetUid);
Jeff Sharkey328ebf22013-03-21 18:09:39 -070090 this.sourcePkg = sourcePkg;
91 this.targetPkg = targetPkg;
92 this.targetUid = targetUid;
93 this.uri = uri;
94 }
95
Jeff Sharkeye66c1772013-09-20 14:30:59 -070096 private void updateModeFlags() {
97 modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
98 }
99
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700100 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700101 * Initialize persisted modes as read from file. This doesn't issue any
102 * global or owner grants.
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700103 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700104 void initPersistedModes(int modeFlags, long createdTime) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700105 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
106 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
107
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700108 persistableModeFlags = modeFlags;
109 persistedModeFlags = modeFlags;
110 persistedCreateTime = createdTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700111
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700112 updateModeFlags();
113 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700114
Jeff Sharkey846318a2014-04-04 12:12:41 -0700115 void grantModes(int modeFlags, UriPermissionOwner owner) {
116 final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
117 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
118 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
119
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700120 if (persistable) {
121 persistableModeFlags |= modeFlags;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700122 }
123
124 if (owner == null) {
125 globalModeFlags |= modeFlags;
126 } else {
127 if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
128 addReadOwner(owner);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700129 }
130 if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
131 addWriteOwner(owner);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700132 }
133 }
134
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700135 updateModeFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700137
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700138 /**
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700139 * @return if mode changes should trigger persisting.
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700140 */
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700141 boolean takePersistableModes(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700142 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
143 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
144
Jeff Sharkey582f7122013-10-11 17:46:47 -0700145 if ((modeFlags & persistableModeFlags) != modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700146 Slog.w(TAG, "Requested flags 0x"
Jeff Sharkey582f7122013-10-11 17:46:47 -0700147 + Integer.toHexString(modeFlags) + ", but only 0x"
148 + Integer.toHexString(persistableModeFlags) + " are allowed");
Jeff Sharkey846318a2014-04-04 12:12:41 -0700149 return false;
Jeff Sharkey582f7122013-10-11 17:46:47 -0700150 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700151
152 final int before = persistedModeFlags;
153 persistedModeFlags |= (persistableModeFlags & modeFlags);
154
155 if (persistedModeFlags != 0) {
156 persistedCreateTime = System.currentTimeMillis();
157 }
158
159 updateModeFlags();
160 return persistedModeFlags != before;
161 }
162
163 boolean releasePersistableModes(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700164 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
165 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
166
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700167 final int before = persistedModeFlags;
168
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700169 persistableModeFlags &= ~modeFlags;
170 persistedModeFlags &= ~modeFlags;
171
172 if (persistedModeFlags == 0) {
173 persistedCreateTime = INVALID_TIME;
174 }
175
176 updateModeFlags();
177 return persistedModeFlags != before;
178 }
179
180 /**
181 * @return if mode changes should trigger persisting.
182 */
Jeff Sharkey846318a2014-04-04 12:12:41 -0700183 boolean revokeModes(int modeFlags) {
184 final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
185 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
186 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
187
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700188 final int before = persistedModeFlags;
189
190 if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
191 if (persistable) {
192 persistableModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700193 persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700196 if (mReadOwners != null) {
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700197 ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700198 for (UriPermissionOwner r : mReadOwners) {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700199 r.removeReadPermission(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700201 mReadOwners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 }
203 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700204 if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
205 if (persistable) {
206 persistableModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700207 persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700210 if (mWriteOwners != null) {
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700211 ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700212 for (UriPermissionOwner r : mWriteOwners) {
Dianne Hackborn39792d22010-08-19 18:01:52 -0700213 r.removeWritePermission(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700215 mWriteOwners = null;
216 }
217 }
218
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700219 if (persistedModeFlags == 0) {
220 persistedCreateTime = INVALID_TIME;
221 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700222
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700223 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700224 return persistedModeFlags != before;
225 }
226
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700227 /**
228 * Return strength of this permission grant for the given flags.
229 */
230 public int getStrength(int modeFlags) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700231 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
232 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700233 if ((persistableModeFlags & modeFlags) == modeFlags) {
234 return STRENGTH_PERSISTABLE;
235 } else if ((globalModeFlags & modeFlags) == modeFlags) {
236 return STRENGTH_GLOBAL;
237 } else if ((ownedModeFlags & modeFlags) == modeFlags) {
238 return STRENGTH_OWNED;
239 } else {
240 return STRENGTH_NONE;
241 }
242 }
243
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700244 private void addReadOwner(UriPermissionOwner owner) {
245 if (mReadOwners == null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700246 mReadOwners = Sets.newArraySet();
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700247 ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
248 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700249 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700250 if (mReadOwners.add(owner)) {
251 owner.addReadPermission(this);
252 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700253 }
254
255 /**
256 * Remove given read owner, updating {@Link #modeFlags} as needed.
257 */
258 void removeReadOwner(UriPermissionOwner owner) {
259 if (!mReadOwners.remove(owner)) {
260 Log.wtf(TAG, "Unknown read owner " + owner + " in " + this);
261 }
262 if (mReadOwners.size() == 0) {
263 mReadOwners = null;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700264 ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
265 updateModeFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 }
267 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700268
269 private void addWriteOwner(UriPermissionOwner owner) {
270 if (mWriteOwners == null) {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700271 mWriteOwners = Sets.newArraySet();
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700272 ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
273 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700274 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700275 if (mWriteOwners.add(owner)) {
276 owner.addWritePermission(this);
277 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700278 }
279
280 /**
281 * Remove given write owner, updating {@Link #modeFlags} as needed.
282 */
283 void removeWriteOwner(UriPermissionOwner owner) {
284 if (!mWriteOwners.remove(owner)) {
285 Log.wtf(TAG, "Unknown write owner " + owner + " in " + this);
286 }
287 if (mWriteOwners.size() == 0) {
288 mWriteOwners = null;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700289 ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
290 updateModeFlags();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700291 }
292 }
293
294 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700296 if (stringName != null) {
297 return stringName;
298 }
299 StringBuilder sb = new StringBuilder(128);
300 sb.append("UriPermission{");
301 sb.append(Integer.toHexString(System.identityHashCode(this)));
302 sb.append(' ');
303 sb.append(uri);
304 sb.append('}');
305 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 }
307
308 void dump(PrintWriter pw, String prefix) {
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700309 pw.print(prefix);
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100310 pw.print("targetUserId=" + targetUserId);
Jeff Sharkey9e0036e2013-04-26 16:54:55 -0700311 pw.print(" sourcePkg=" + sourcePkg);
312 pw.println(" targetPkg=" + targetPkg);
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700313
314 pw.print(prefix);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700315 pw.print("mode=0x" + Integer.toHexString(modeFlags));
316 pw.print(" owned=0x" + Integer.toHexString(ownedModeFlags));
317 pw.print(" global=0x" + Integer.toHexString(globalModeFlags));
318 pw.print(" persistable=0x" + Integer.toHexString(persistableModeFlags));
319 pw.print(" persisted=0x" + Integer.toHexString(persistedModeFlags));
320 if (persistedCreateTime != INVALID_TIME) {
321 pw.print(" persistedCreate=" + persistedCreateTime);
322 }
323 pw.println();
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700324
325 if (mReadOwners != null) {
326 pw.print(prefix);
327 pw.println("readOwners:");
328 for (UriPermissionOwner owner : mReadOwners) {
329 pw.print(prefix);
330 pw.println(" * " + owner);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700331 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700332 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700333 if (mWriteOwners != null) {
334 pw.print(prefix);
335 pw.println("writeOwners:");
336 for (UriPermissionOwner owner : mReadOwners) {
337 pw.print(prefix);
338 pw.println(" * " + owner);
Dianne Hackborn39792d22010-08-19 18:01:52 -0700339 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700342
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700343 public static class PersistedTimeComparator implements Comparator<UriPermission> {
344 @Override
345 public int compare(UriPermission lhs, UriPermission rhs) {
346 return Long.compare(lhs.persistedCreateTime, rhs.persistedCreateTime);
347 }
348 }
349
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700350 /**
351 * Snapshot of {@link UriPermission} with frozen
352 * {@link UriPermission#persistedModeFlags} state.
353 */
354 public static class Snapshot {
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100355 final int targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700356 final String sourcePkg;
357 final String targetPkg;
Jeff Sharkey846318a2014-04-04 12:12:41 -0700358 final GrantUri uri;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700359 final int persistedModeFlags;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700360 final long persistedCreateTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700361
362 private Snapshot(UriPermission perm) {
Nicolas Prevotd85fc722014-04-16 19:52:08 +0100363 this.targetUserId = perm.targetUserId;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700364 this.sourcePkg = perm.sourcePkg;
365 this.targetPkg = perm.targetPkg;
366 this.uri = perm.uri;
367 this.persistedModeFlags = perm.persistedModeFlags;
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700368 this.persistedCreateTime = perm.persistedCreateTime;
Jeff Sharkey328ebf22013-03-21 18:09:39 -0700369 }
370 }
371
372 public Snapshot snapshot() {
373 return new Snapshot(this);
374 }
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700375
376 public android.content.UriPermission buildPersistedPublicApiObject() {
Jeff Sharkey846318a2014-04-04 12:12:41 -0700377 return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
Jeff Sharkeye66c1772013-09-20 14:30:59 -0700378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379}