OSDN Git Service

Add optional logging to investigate URI grants.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / UriPermission.java
1 /*
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
17 package com.android.server.am;
18
19 import android.content.Intent;
20 import android.os.UserHandle;
21 import android.util.ArraySet;
22 import android.util.Log;
23 import android.util.Slog;
24
25 import com.android.server.am.ActivityManagerService.GrantUri;
26 import com.google.android.collect.Sets;
27
28 import java.io.PrintWriter;
29 import java.util.Comparator;
30
31 /**
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  *
36  * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
37  *      src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
38  */
39 final class UriPermission {
40     private static final String TAG = "UriPermission";
41
42     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
47     final int targetUserId;
48     final String sourcePkg;
49     final String targetPkg;
50
51     /** Cached UID of {@link #targetPkg}; should not be persisted */
52     final int targetUid;
53
54     final GrantUri uri;
55
56     /**
57      * Allowed modes. All permission enforcement should use this field. Must
58      * 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.
62      */
63     int modeFlags = 0;
64
65     /** Allowed modes with active owner. */
66     int ownedModeFlags = 0;
67     /** Allowed modes without explicit owner. */
68     int globalModeFlags = 0;
69     /** Allowed modes that have been offered for possible persisting. */
70     int persistableModeFlags = 0;
71
72     /** Allowed modes that should be persisted across device boots. */
73     int persistedModeFlags = 0;
74
75     /**
76      * Timestamp when {@link #persistedModeFlags} was first defined in
77      * {@link System#currentTimeMillis()} time base.
78      */
79     long persistedCreateTime = INVALID_TIME;
80
81     private static final long INVALID_TIME = Long.MIN_VALUE;
82
83     private ArraySet<UriPermissionOwner> mReadOwners;
84     private ArraySet<UriPermissionOwner> mWriteOwners;
85
86     private String stringName;
87
88     UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
89         this.targetUserId = UserHandle.getUserId(targetUid);
90         this.sourcePkg = sourcePkg;
91         this.targetPkg = targetPkg;
92         this.targetUid = targetUid;
93         this.uri = uri;
94     }
95
96     private void updateModeFlags() {
97         final int oldModeFlags = modeFlags;
98         modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
99
100         if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) {
101             Slog.d(TAG,
102                     "Permission for " + targetPkg + " to " + uri + " is changing from 0x"
103                             + Integer.toHexString(oldModeFlags) + " to 0x"
104                             + Integer.toHexString(modeFlags),
105                     new Throwable());
106         }
107     }
108
109     /**
110      * Initialize persisted modes as read from file. This doesn't issue any
111      * global or owner grants.
112      */
113     void initPersistedModes(int modeFlags, long createdTime) {
114         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
115                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
116
117         persistableModeFlags = modeFlags;
118         persistedModeFlags = modeFlags;
119         persistedCreateTime = createdTime;
120
121         updateModeFlags();
122     }
123
124     void grantModes(int modeFlags, UriPermissionOwner owner) {
125         final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
126         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
127                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
128
129         if (persistable) {
130             persistableModeFlags |= modeFlags;
131         }
132
133         if (owner == null) {
134             globalModeFlags |= modeFlags;
135         } else {
136             if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
137                 addReadOwner(owner);
138             }
139             if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
140                 addWriteOwner(owner);
141             }
142         }
143
144         updateModeFlags();
145     }
146
147     /**
148      * @return if mode changes should trigger persisting.
149      */
150     boolean takePersistableModes(int modeFlags) {
151         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
152                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
153
154         if ((modeFlags & persistableModeFlags) != modeFlags) {
155             Slog.w(TAG, "Requested flags 0x"
156                     + Integer.toHexString(modeFlags) + ", but only 0x"
157                     + Integer.toHexString(persistableModeFlags) + " are allowed");
158             return false;
159         }
160
161         final int before = persistedModeFlags;
162         persistedModeFlags |= (persistableModeFlags & modeFlags);
163
164         if (persistedModeFlags != 0) {
165             persistedCreateTime = System.currentTimeMillis();
166         }
167
168         updateModeFlags();
169         return persistedModeFlags != before;
170     }
171
172     boolean releasePersistableModes(int modeFlags) {
173         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
174                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
175
176         final int before = persistedModeFlags;
177
178         persistableModeFlags &= ~modeFlags;
179         persistedModeFlags &= ~modeFlags;
180
181         if (persistedModeFlags == 0) {
182             persistedCreateTime = INVALID_TIME;
183         }
184
185         updateModeFlags();
186         return persistedModeFlags != before;
187     }
188
189     /**
190      * @return if mode changes should trigger persisting.
191      */
192     boolean revokeModes(int modeFlags, boolean includingOwners) {
193         final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
194         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
195                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
196
197         final int before = persistedModeFlags;
198
199         if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
200             if (persistable) {
201                 persistableModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
202                 persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
203             }
204             globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
205             if (mReadOwners != null && includingOwners) {
206                 ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
207                 for (UriPermissionOwner r : mReadOwners) {
208                     r.removeReadPermission(this);
209                 }
210                 mReadOwners = null;
211             }
212         }
213         if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
214             if (persistable) {
215                 persistableModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
216                 persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
217             }
218             globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
219             if (mWriteOwners != null && includingOwners) {
220                 ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
221                 for (UriPermissionOwner r : mWriteOwners) {
222                     r.removeWritePermission(this);
223                 }
224                 mWriteOwners = null;
225             }
226         }
227
228         if (persistedModeFlags == 0) {
229             persistedCreateTime = INVALID_TIME;
230         }
231
232         updateModeFlags();
233         return persistedModeFlags != before;
234     }
235
236     /**
237      * Return strength of this permission grant for the given flags.
238      */
239     public int getStrength(int modeFlags) {
240         modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
241                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
242         if ((persistableModeFlags & modeFlags) == modeFlags) {
243             return STRENGTH_PERSISTABLE;
244         } else if ((globalModeFlags & modeFlags) == modeFlags) {
245             return STRENGTH_GLOBAL;
246         } else if ((ownedModeFlags & modeFlags) == modeFlags) {
247             return STRENGTH_OWNED;
248         } else {
249             return STRENGTH_NONE;
250         }
251     }
252
253     private void addReadOwner(UriPermissionOwner owner) {
254         if (mReadOwners == null) {
255             mReadOwners = Sets.newArraySet();
256             ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
257             updateModeFlags();
258         }
259         if (mReadOwners.add(owner)) {
260             owner.addReadPermission(this);
261         }
262     }
263
264     /**
265      * Remove given read owner, updating {@Link #modeFlags} as needed.
266      */
267     void removeReadOwner(UriPermissionOwner owner) {
268         if (!mReadOwners.remove(owner)) {
269             Slog.wtf(TAG, "Unknown read owner " + owner + " in " + this);
270         }
271         if (mReadOwners.size() == 0) {
272             mReadOwners = null;
273             ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
274             updateModeFlags();
275         }
276     }
277
278     private void addWriteOwner(UriPermissionOwner owner) {
279         if (mWriteOwners == null) {
280             mWriteOwners = Sets.newArraySet();
281             ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
282             updateModeFlags();
283         }
284         if (mWriteOwners.add(owner)) {
285             owner.addWritePermission(this);
286         }
287     }
288
289     /**
290      * Remove given write owner, updating {@Link #modeFlags} as needed.
291      */
292     void removeWriteOwner(UriPermissionOwner owner) {
293         if (!mWriteOwners.remove(owner)) {
294             Slog.wtf(TAG, "Unknown write owner " + owner + " in " + this);
295         }
296         if (mWriteOwners.size() == 0) {
297             mWriteOwners = null;
298             ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
299             updateModeFlags();
300         }
301     }
302
303     @Override
304     public String toString() {
305         if (stringName != null) {
306             return stringName;
307         }
308         StringBuilder sb = new StringBuilder(128);
309         sb.append("UriPermission{");
310         sb.append(Integer.toHexString(System.identityHashCode(this)));
311         sb.append(' ');
312         sb.append(uri);
313         sb.append('}');
314         return stringName = sb.toString();
315     }
316
317     void dump(PrintWriter pw, String prefix) {
318         pw.print(prefix);
319         pw.print("targetUserId=" + targetUserId);
320         pw.print(" sourcePkg=" + sourcePkg);
321         pw.println(" targetPkg=" + targetPkg);
322
323         pw.print(prefix);
324         pw.print("mode=0x" + Integer.toHexString(modeFlags));
325         pw.print(" owned=0x" + Integer.toHexString(ownedModeFlags));
326         pw.print(" global=0x" + Integer.toHexString(globalModeFlags));
327         pw.print(" persistable=0x" + Integer.toHexString(persistableModeFlags));
328         pw.print(" persisted=0x" + Integer.toHexString(persistedModeFlags));
329         if (persistedCreateTime != INVALID_TIME) {
330             pw.print(" persistedCreate=" + persistedCreateTime);
331         }
332         pw.println();
333
334         if (mReadOwners != null) {
335             pw.print(prefix);
336             pw.println("readOwners:");
337             for (UriPermissionOwner owner : mReadOwners) {
338                 pw.print(prefix);
339                 pw.println("  * " + owner);
340             }
341         }
342         if (mWriteOwners != null) {
343             pw.print(prefix);
344             pw.println("writeOwners:");
345             for (UriPermissionOwner owner : mReadOwners) {
346                 pw.print(prefix);
347                 pw.println("  * " + owner);
348             }
349         }
350     }
351
352     public static class PersistedTimeComparator implements Comparator<UriPermission> {
353         @Override
354         public int compare(UriPermission lhs, UriPermission rhs) {
355             return Long.compare(lhs.persistedCreateTime, rhs.persistedCreateTime);
356         }
357     }
358
359     /**
360      * Snapshot of {@link UriPermission} with frozen
361      * {@link UriPermission#persistedModeFlags} state.
362      */
363     public static class Snapshot {
364         final int targetUserId;
365         final String sourcePkg;
366         final String targetPkg;
367         final GrantUri uri;
368         final int persistedModeFlags;
369         final long persistedCreateTime;
370
371         private Snapshot(UriPermission perm) {
372             this.targetUserId = perm.targetUserId;
373             this.sourcePkg = perm.sourcePkg;
374             this.targetPkg = perm.targetPkg;
375             this.uri = perm.uri;
376             this.persistedModeFlags = perm.persistedModeFlags;
377             this.persistedCreateTime = perm.persistedCreateTime;
378         }
379     }
380
381     public Snapshot snapshot() {
382         return new Snapshot(this);
383     }
384
385     public android.content.UriPermission buildPersistedPublicApiObject() {
386         return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
387     }
388 }