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 UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri)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 updateModeFlags()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 */ initPersistedModes(int modeFlags, long createdTime)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 grantModes(int modeFlags, UriPermissionOwner owner)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 */ takePersistableModes(int modeFlags)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 releasePersistableModes(int modeFlags)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 */ revokeModes(int modeFlags, boolean includingOwners)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 */ getStrength(int modeFlags)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 addReadOwner(UriPermissionOwner owner)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 */ removeReadOwner(UriPermissionOwner owner)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 addWriteOwner(UriPermissionOwner owner)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 */ removeWriteOwner(UriPermissionOwner owner)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 toString()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 dump(PrintWriter pw, String prefix)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 compare(UriPermission lhs, UriPermission rhs)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 Snapshot(UriPermission perm)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 snapshot()381 public Snapshot snapshot() { 382 return new Snapshot(this); 383 } 384 buildPersistedPublicApiObject()385 public android.content.UriPermission buildPersistedPublicApiObject() { 386 return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime); 387 } 388 } 389