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