blob: 6b5ec43a2d64602ba930607ac73d0e8aa4852831 [file] [log] [blame]
Todd Kennedy0eb97382017-10-03 16:57:22 -07001/*
2 * Copyright (C) 2017 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.pm.permission;
18
19import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
20import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
21
22import android.Manifest;
23import android.annotation.NonNull;
24import android.annotation.Nullable;
25import android.app.AppOpsManager;
26import android.content.Context;
27import android.content.pm.PackageManager;
28import android.content.pm.PackageManagerInternal;
29import android.content.pm.PackageParser;
Todd Kennedy460f28c2017-10-06 13:46:22 -070030import android.content.pm.PermissionGroupInfo;
Todd Kennedy0eb97382017-10-03 16:57:22 -070031import android.content.pm.PermissionInfo;
32import android.content.pm.PackageParser.Package;
33import android.os.Binder;
34import android.os.Build;
35import android.os.Handler;
36import android.os.HandlerThread;
37import android.os.Process;
38import android.os.UserHandle;
39import android.os.UserManager;
40import android.os.UserManagerInternal;
41import android.os.storage.StorageManagerInternal;
42import android.util.ArrayMap;
43import android.util.ArraySet;
44import android.util.Log;
45import android.util.Slog;
46
47import com.android.internal.R;
48import com.android.internal.logging.MetricsLogger;
49import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
50import com.android.internal.util.ArrayUtils;
51import com.android.server.FgThread;
52import com.android.server.LocalServices;
53import com.android.server.ServiceThread;
54import com.android.server.SystemConfig;
55import com.android.server.Watchdog;
56import com.android.server.pm.PackageManagerService;
57import com.android.server.pm.PackageManagerServiceUtils;
58import com.android.server.pm.PackageSetting;
59import com.android.server.pm.ProcessLoggingHandler;
60import com.android.server.pm.SharedUserSetting;
61import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
62import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
63import com.android.server.pm.permission.PermissionsState.PermissionState;
64
65import libcore.util.EmptyArray;
66
67import java.util.ArrayList;
68import java.util.Arrays;
69import java.util.Collection;
70import java.util.Iterator;
71import java.util.List;
Todd Kennedyc8423932017-10-05 08:58:36 -070072import java.util.Set;
Todd Kennedy0eb97382017-10-03 16:57:22 -070073
74/**
75 * Manages all permissions and handles permissions related tasks.
76 */
77public class PermissionManagerService {
78 private static final String TAG = "PackageManager";
79
80 /** All dangerous permission names in the same order as the events in MetricsEvent */
81 private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
82 Manifest.permission.READ_CALENDAR,
83 Manifest.permission.WRITE_CALENDAR,
84 Manifest.permission.CAMERA,
85 Manifest.permission.READ_CONTACTS,
86 Manifest.permission.WRITE_CONTACTS,
87 Manifest.permission.GET_ACCOUNTS,
88 Manifest.permission.ACCESS_FINE_LOCATION,
89 Manifest.permission.ACCESS_COARSE_LOCATION,
90 Manifest.permission.RECORD_AUDIO,
91 Manifest.permission.READ_PHONE_STATE,
92 Manifest.permission.CALL_PHONE,
93 Manifest.permission.READ_CALL_LOG,
94 Manifest.permission.WRITE_CALL_LOG,
95 Manifest.permission.ADD_VOICEMAIL,
96 Manifest.permission.USE_SIP,
97 Manifest.permission.PROCESS_OUTGOING_CALLS,
98 Manifest.permission.READ_CELL_BROADCASTS,
99 Manifest.permission.BODY_SENSORS,
100 Manifest.permission.SEND_SMS,
101 Manifest.permission.RECEIVE_SMS,
102 Manifest.permission.READ_SMS,
103 Manifest.permission.RECEIVE_WAP_PUSH,
104 Manifest.permission.RECEIVE_MMS,
105 Manifest.permission.READ_EXTERNAL_STORAGE,
106 Manifest.permission.WRITE_EXTERNAL_STORAGE,
107 Manifest.permission.READ_PHONE_NUMBERS,
108 Manifest.permission.ANSWER_PHONE_CALLS);
109
110 /** Cap the size of permission trees that 3rd party apps can define */
111 private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
112
113 /** Lock to protect internal data access */
114 private final Object mLock;
115
116 /** Internal connection to the package manager */
117 private final PackageManagerInternal mPackageManagerInt;
118
119 /** Internal connection to the user manager */
120 private final UserManagerInternal mUserManagerInt;
121
122 /** Default permission policy to provide proper behaviour out-of-the-box */
123 private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
124
125 /** Internal storage for permissions and related settings */
126 private final PermissionSettings mSettings;
127
128 private final HandlerThread mHandlerThread;
129 private final Handler mHandler;
130 private final Context mContext;
131
132 PermissionManagerService(Context context,
133 @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
134 @NonNull Object externalLock) {
135 mContext = context;
136 mLock = externalLock;
137 mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
138 mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
139 mSettings = new PermissionSettings(context, mLock);
140
141 mHandlerThread = new ServiceThread(TAG,
142 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
143 mHandlerThread.start();
144 mHandler = new Handler(mHandlerThread.getLooper());
145 Watchdog.getInstance().addThread(mHandler);
146
147 mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
148 context, mHandlerThread.getLooper(), defaultGrantCallback, this);
149
150 // propagate permission configuration
151 final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
152 SystemConfig.getInstance().getPermissions();
153 synchronized (mLock) {
154 for (int i=0; i<permConfig.size(); i++) {
155 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
156 BasePermission bp = mSettings.getPermissionLocked(perm.name);
157 if (bp == null) {
158 bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
159 mSettings.putPermissionLocked(perm.name, bp);
160 }
161 if (perm.gids != null) {
162 bp.setGids(perm.gids, perm.perUser);
163 }
164 }
165 }
166
167 LocalServices.addService(
168 PermissionManagerInternal.class, new PermissionManagerInternalImpl());
169 }
170
171 /**
172 * Creates and returns an initialized, internal service for use by other components.
173 * <p>
174 * The object returned is identical to the one returned by the LocalServices class using:
175 * {@code LocalServices.getService(PermissionManagerInternal.class);}
176 * <p>
177 * NOTE: The external lock is temporary and should be removed. This needs to be a
178 * lock created by the permission manager itself.
179 */
180 public static PermissionManagerInternal create(Context context,
181 @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
182 @NonNull Object externalLock) {
183 final PermissionManagerInternal permMgrInt =
184 LocalServices.getService(PermissionManagerInternal.class);
185 if (permMgrInt != null) {
186 return permMgrInt;
187 }
188 new PermissionManagerService(context, defaultGrantCallback, externalLock);
189 return LocalServices.getService(PermissionManagerInternal.class);
190 }
191
192 @Nullable BasePermission getPermission(String permName) {
193 synchronized (mLock) {
194 return mSettings.getPermissionLocked(permName);
195 }
196 }
197
198 private int checkPermission(String permName, String pkgName, int callingUid, int userId) {
199 if (!mUserManagerInt.exists(userId)) {
200 return PackageManager.PERMISSION_DENIED;
201 }
202
203 final PackageParser.Package pkg = mPackageManagerInt.getPackage(pkgName);
204 if (pkg != null && pkg.mExtras != null) {
205 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
206 return PackageManager.PERMISSION_DENIED;
207 }
208 final PackageSetting ps = (PackageSetting) pkg.mExtras;
209 final boolean instantApp = ps.getInstantApp(userId);
210 final PermissionsState permissionsState = ps.getPermissionsState();
211 if (permissionsState.hasPermission(permName, userId)) {
212 if (instantApp) {
213 synchronized (mLock) {
214 BasePermission bp = mSettings.getPermissionLocked(permName);
215 if (bp != null && bp.isInstant()) {
216 return PackageManager.PERMISSION_GRANTED;
217 }
218 }
219 } else {
220 return PackageManager.PERMISSION_GRANTED;
221 }
222 }
223 // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
224 if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
225 .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
226 return PackageManager.PERMISSION_GRANTED;
227 }
228 }
229
230 return PackageManager.PERMISSION_DENIED;
231 }
232
Todd Kennedy460f28c2017-10-06 13:46:22 -0700233 private PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
234 int callingUid) {
235 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
236 return null;
237 }
238 synchronized (mLock) {
239 return PackageParser.generatePermissionGroupInfo(
240 mSettings.mPermissionGroups.get(groupName), flags);
241 }
242 }
243
244 private List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
245 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
246 return null;
247 }
248 synchronized (mLock) {
249 final int N = mSettings.mPermissionGroups.size();
250 final ArrayList<PermissionGroupInfo> out
251 = new ArrayList<PermissionGroupInfo>(N);
252 for (PackageParser.PermissionGroup pg : mSettings.mPermissionGroups.values()) {
253 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
254 }
255 return out;
256 }
257 }
258
259 private PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
Todd Kennedy0eb97382017-10-03 16:57:22 -0700260 int callingUid) {
261 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
262 return null;
263 }
264 // reader
265 synchronized (mLock) {
Todd Kennedy460f28c2017-10-06 13:46:22 -0700266 final BasePermission bp = mSettings.getPermissionLocked(permName);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700267 if (bp == null) {
268 return null;
269 }
270 final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
271 bp.getProtectionLevel(), packageName, callingUid);
272 return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
273 }
274 }
275
276 private List<PermissionInfo> getPermissionInfoByGroup(
277 String groupName, int flags, int callingUid) {
278 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
279 return null;
280 }
Todd Kennedy0eb97382017-10-03 16:57:22 -0700281 synchronized (mLock) {
Todd Kennedy460f28c2017-10-06 13:46:22 -0700282 if (groupName != null && !mSettings.mPermissionGroups.containsKey(groupName)) {
283 return null;
284 }
Todd Kennedy0eb97382017-10-03 16:57:22 -0700285 final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
Todd Kennedyc8423932017-10-05 08:58:36 -0700286 for (BasePermission bp : mSettings.mPermissions.values()) {
Todd Kennedy0eb97382017-10-03 16:57:22 -0700287 final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
288 if (pi != null) {
289 out.add(pi);
290 }
291 }
292 return out;
293 }
294 }
295
296 private int adjustPermissionProtectionFlagsLocked(
297 int protectionLevel, String packageName, int uid) {
298 // Signature permission flags area always reported
299 final int protectionLevelMasked = protectionLevel
300 & (PermissionInfo.PROTECTION_NORMAL
301 | PermissionInfo.PROTECTION_DANGEROUS
302 | PermissionInfo.PROTECTION_SIGNATURE);
303 if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
304 return protectionLevel;
305 }
306 // System sees all flags.
307 final int appId = UserHandle.getAppId(uid);
308 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
309 || appId == Process.SHELL_UID) {
310 return protectionLevel;
311 }
312 // Normalize package name to handle renamed packages and static libs
313 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
314 if (pkg == null) {
315 return protectionLevel;
316 }
317 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
318 return protectionLevelMasked;
319 }
320 // Apps that target O see flags for all protection levels.
321 final PackageSetting ps = (PackageSetting) pkg.mExtras;
322 if (ps == null) {
323 return protectionLevel;
324 }
325 if (ps.getAppId() != appId) {
326 return protectionLevel;
327 }
328 return protectionLevel;
329 }
330
Todd Kennedyc8423932017-10-05 08:58:36 -0700331 private void addAllPermissions(PackageParser.Package pkg, boolean chatty) {
332 final int N = pkg.permissions.size();
333 for (int i=0; i<N; i++) {
334 PackageParser.Permission p = pkg.permissions.get(i);
335
336 // Assume by default that we did not install this permission into the system.
337 p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
338
Todd Kennedyc8423932017-10-05 08:58:36 -0700339 synchronized (PermissionManagerService.this.mLock) {
Todd Kennedy460f28c2017-10-06 13:46:22 -0700340 // Now that permission groups have a special meaning, we ignore permission
341 // groups for legacy apps to prevent unexpected behavior. In particular,
342 // permissions for one app being granted to someone just because they happen
343 // to be in a group defined by another app (before this had no implications).
344 if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
345 p.group = mSettings.mPermissionGroups.get(p.info.group);
346 // Warn for a permission in an unknown group.
347 if (PackageManagerService.DEBUG_PERMISSIONS
348 && p.info.group != null && p.group == null) {
349 Slog.i(TAG, "Permission " + p.info.name + " from package "
350 + p.info.packageName + " in an unknown group " + p.info.group);
351 }
352 }
353
Todd Kennedyc8423932017-10-05 08:58:36 -0700354 if (p.tree) {
355 final BasePermission bp = BasePermission.createOrUpdate(
356 mSettings.getPermissionTreeLocked(p.info.name), p, pkg,
357 mSettings.getAllPermissionTreesLocked(), chatty);
358 mSettings.putPermissionTreeLocked(p.info.name, bp);
359 } else {
360 final BasePermission bp = BasePermission.createOrUpdate(
361 mSettings.getPermissionLocked(p.info.name),
362 p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
363 mSettings.putPermissionLocked(p.info.name, bp);
364 }
365 }
366 }
367 }
368
Todd Kennedy460f28c2017-10-06 13:46:22 -0700369 private void addAllPermissionGroups(PackageParser.Package pkg, boolean chatty) {
370 final int N = pkg.permissionGroups.size();
371 StringBuilder r = null;
372 for (int i=0; i<N; i++) {
373 final PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
374 final PackageParser.PermissionGroup cur = mSettings.mPermissionGroups.get(pg.info.name);
375 final String curPackageName = (cur == null) ? null : cur.info.packageName;
376 final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
377 if (cur == null || isPackageUpdate) {
378 mSettings.mPermissionGroups.put(pg.info.name, pg);
379 if (chatty && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
380 if (r == null) {
381 r = new StringBuilder(256);
382 } else {
383 r.append(' ');
384 }
385 if (isPackageUpdate) {
386 r.append("UPD:");
387 }
388 r.append(pg.info.name);
389 }
390 } else {
391 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
392 + pg.info.packageName + " ignored: original from "
393 + cur.info.packageName);
394 if (chatty && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
395 if (r == null) {
396 r = new StringBuilder(256);
397 } else {
398 r.append(' ');
399 }
400 r.append("DUP:");
401 r.append(pg.info.name);
402 }
403 }
404 }
405 if (r != null && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
406 Log.d(TAG, " Permission Groups: " + r);
407 }
408
409 }
410
Todd Kennedyc8423932017-10-05 08:58:36 -0700411 private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
412 synchronized (mLock) {
413 int N = pkg.permissions.size();
414 StringBuilder r = null;
415 for (int i=0; i<N; i++) {
416 PackageParser.Permission p = pkg.permissions.get(i);
417 BasePermission bp = (BasePermission) mSettings.mPermissions.get(p.info.name);
418 if (bp == null) {
419 bp = mSettings.mPermissionTrees.get(p.info.name);
420 }
421 if (bp != null && bp.isPermission(p)) {
422 bp.setPermission(null);
423 if (PackageManagerService.DEBUG_REMOVE && chatty) {
424 if (r == null) {
425 r = new StringBuilder(256);
426 } else {
427 r.append(' ');
428 }
429 r.append(p.info.name);
430 }
431 }
432 if (p.isAppOp()) {
433 ArraySet<String> appOpPkgs =
434 mSettings.mAppOpPermissionPackages.get(p.info.name);
435 if (appOpPkgs != null) {
436 appOpPkgs.remove(pkg.packageName);
437 }
438 }
439 }
440 if (r != null) {
441 if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
442 }
443
444 N = pkg.requestedPermissions.size();
445 r = null;
446 for (int i=0; i<N; i++) {
447 String perm = pkg.requestedPermissions.get(i);
448 if (mSettings.isPermissionAppOp(perm)) {
449 ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
450 if (appOpPkgs != null) {
451 appOpPkgs.remove(pkg.packageName);
452 if (appOpPkgs.isEmpty()) {
453 mSettings.mAppOpPermissionPackages.remove(perm);
454 }
455 }
456 }
457 }
458 if (r != null) {
459 if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
460 }
461 }
462 }
463
464 private boolean addDynamicPermission(
Todd Kennedy0eb97382017-10-03 16:57:22 -0700465 PermissionInfo info, int callingUid, PermissionCallback callback) {
466 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
467 throw new SecurityException("Instant apps can't add permissions");
468 }
469 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
470 throw new SecurityException("Label must be specified in permission");
471 }
Todd Kennedyc8423932017-10-05 08:58:36 -0700472 final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700473 final boolean added;
474 final boolean changed;
475 synchronized (mLock) {
476 BasePermission bp = mSettings.getPermissionLocked(info.name);
477 added = bp == null;
478 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
479 if (added) {
480 enforcePermissionCapLocked(info, tree);
481 bp = new BasePermission(info.name, tree.getSourcePackageName(),
482 BasePermission.TYPE_DYNAMIC);
483 } else if (bp.isDynamic()) {
Jeff Sharkey4dc50522017-10-17 15:29:41 -0600484 // TODO: switch this back to SecurityException
485 Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
Todd Kennedy0eb97382017-10-03 16:57:22 -0700486 + info.name);
487 }
488 changed = bp.addToTree(fixedLevel, info, tree);
489 if (added) {
490 mSettings.putPermissionLocked(info.name, bp);
491 }
492 }
493 if (changed && callback != null) {
494 callback.onPermissionChanged();
495 }
496 return added;
497 }
498
Todd Kennedyc8423932017-10-05 08:58:36 -0700499 private void removeDynamicPermission(
Todd Kennedy0eb97382017-10-03 16:57:22 -0700500 String permName, int callingUid, PermissionCallback callback) {
501 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
502 throw new SecurityException("Instant applications don't have access to this method");
503 }
Todd Kennedyc8423932017-10-05 08:58:36 -0700504 final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
Todd Kennedy0eb97382017-10-03 16:57:22 -0700505 synchronized (mLock) {
506 final BasePermission bp = mSettings.getPermissionLocked(permName);
507 if (bp == null) {
508 return;
509 }
510 if (bp.isDynamic()) {
Jeff Sharkey4dc50522017-10-17 15:29:41 -0600511 // TODO: switch this back to SecurityException
512 Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
Todd Kennedy0eb97382017-10-03 16:57:22 -0700513 + permName);
514 }
515 mSettings.removePermissionLocked(permName);
516 if (callback != null) {
517 callback.onPermissionRemoved();
518 }
519 }
520 }
521
522 private void grantRuntimePermissionsGrantedToDisabledPackageLocked(
523 PackageParser.Package pkg, int callingUid, PermissionCallback callback) {
524 if (pkg.parentPackage == null) {
525 return;
526 }
527 if (pkg.requestedPermissions == null) {
528 return;
529 }
530 final PackageParser.Package disabledPkg =
531 mPackageManagerInt.getDisabledPackage(pkg.parentPackage.packageName);
532 if (disabledPkg == null || disabledPkg.mExtras == null) {
533 return;
534 }
535 final PackageSetting disabledPs = (PackageSetting) disabledPkg.mExtras;
536 if (!disabledPs.isPrivileged() || disabledPs.hasChildPackages()) {
537 return;
538 }
539 final int permCount = pkg.requestedPermissions.size();
540 for (int i = 0; i < permCount; i++) {
541 String permission = pkg.requestedPermissions.get(i);
542 BasePermission bp = mSettings.getPermissionLocked(permission);
543 if (bp == null || !(bp.isRuntime() || bp.isDevelopment())) {
544 continue;
545 }
546 for (int userId : mUserManagerInt.getUserIds()) {
547 if (disabledPs.getPermissionsState().hasRuntimePermission(permission, userId)) {
548 grantRuntimePermission(
549 permission, pkg.packageName, false, callingUid, userId, callback);
550 }
551 }
552 }
553 }
554
555 private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
556 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
557 for (int userId : userIds) {
558 grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid,
559 callback);
560 }
561 }
562
563 private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
564 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
565 PackageSetting ps = (PackageSetting) pkg.mExtras;
566 if (ps == null) {
567 return;
568 }
569
570 PermissionsState permissionsState = ps.getPermissionsState();
571
572 final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
573 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
574
575 final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
576 >= Build.VERSION_CODES.M;
577
578 final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.packageName, userId);
579
580 for (String permission : pkg.requestedPermissions) {
581 final BasePermission bp;
582 synchronized (mLock) {
583 bp = mSettings.getPermissionLocked(permission);
584 }
585 if (bp != null && (bp.isRuntime() || bp.isDevelopment())
586 && (!instantApp || bp.isInstant())
587 && (supportsRuntimePermissions || !bp.isRuntimeOnly())
588 && (grantedPermissions == null
589 || ArrayUtils.contains(grantedPermissions, permission))) {
590 final int flags = permissionsState.getPermissionFlags(permission, userId);
591 if (supportsRuntimePermissions) {
592 // Installer cannot change immutable permissions.
593 if ((flags & immutableFlags) == 0) {
594 grantRuntimePermission(permission, pkg.packageName, false, callingUid,
595 userId, callback);
596 }
597 } else if (mSettings.mPermissionReviewRequired) {
598 // In permission review mode we clear the review flag when we
599 // are asked to install the app with all permissions granted.
600 if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
601 updatePermissionFlags(permission, pkg.packageName,
602 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
603 userId, callback);
604 }
605 }
606 }
607 }
608 }
609
610 private void grantRuntimePermission(String permName, String packageName, boolean overridePolicy,
611 int callingUid, final int userId, PermissionCallback callback) {
612 if (!mUserManagerInt.exists(userId)) {
613 Log.e(TAG, "No such user:" + userId);
614 return;
615 }
616
617 mContext.enforceCallingOrSelfPermission(
618 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
619 "grantRuntimePermission");
620
621 enforceCrossUserPermission(callingUid, userId,
622 true /* requireFullPermission */, true /* checkShell */,
623 "grantRuntimePermission");
624
625 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
626 if (pkg == null || pkg.mExtras == null) {
627 throw new IllegalArgumentException("Unknown package: " + packageName);
628 }
629 final BasePermission bp;
630 synchronized(mLock) {
631 bp = mSettings.getPermissionLocked(permName);
632 }
633 if (bp == null) {
634 throw new IllegalArgumentException("Unknown permission: " + permName);
635 }
636 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
637 throw new IllegalArgumentException("Unknown package: " + packageName);
638 }
639
640 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
641
642 // If a permission review is required for legacy apps we represent
643 // their permissions as always granted runtime ones since we need
644 // to keep the review required permission flag per user while an
645 // install permission's state is shared across all users.
646 if (mSettings.mPermissionReviewRequired
647 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
648 && bp.isRuntime()) {
649 return;
650 }
651
652 final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
653
654 final PackageSetting ps = (PackageSetting) pkg.mExtras;
655 final PermissionsState permissionsState = ps.getPermissionsState();
656
657 final int flags = permissionsState.getPermissionFlags(permName, userId);
658 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
659 throw new SecurityException("Cannot grant system fixed permission "
660 + permName + " for package " + packageName);
661 }
662 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
663 throw new SecurityException("Cannot grant policy fixed permission "
664 + permName + " for package " + packageName);
665 }
666
667 if (bp.isDevelopment()) {
668 // Development permissions must be handled specially, since they are not
669 // normal runtime permissions. For now they apply to all users.
670 if (permissionsState.grantInstallPermission(bp) !=
671 PermissionsState.PERMISSION_OPERATION_FAILURE) {
672 if (callback != null) {
673 callback.onInstallPermissionGranted();
674 }
675 }
676 return;
677 }
678
679 if (ps.getInstantApp(userId) && !bp.isInstant()) {
680 throw new SecurityException("Cannot grant non-ephemeral permission"
681 + permName + " for package " + packageName);
682 }
683
684 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
685 Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
686 return;
687 }
688
689 final int result = permissionsState.grantRuntimePermission(bp, userId);
690 switch (result) {
691 case PermissionsState.PERMISSION_OPERATION_FAILURE: {
692 return;
693 }
694
695 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
696 if (callback != null) {
697 callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
698 }
699 }
700 break;
701 }
702
703 if (bp.isRuntime()) {
704 logPermissionGranted(mContext, permName, packageName);
705 }
706
707 if (callback != null) {
708 callback.onPermissionGranted(uid, userId);
709 }
710
711 // Only need to do this if user is initialized. Otherwise it's a new user
712 // and there are no processes running as the user yet and there's no need
713 // to make an expensive call to remount processes for the changed permissions.
714 if (READ_EXTERNAL_STORAGE.equals(permName)
715 || WRITE_EXTERNAL_STORAGE.equals(permName)) {
716 final long token = Binder.clearCallingIdentity();
717 try {
718 if (mUserManagerInt.isUserInitialized(userId)) {
719 StorageManagerInternal storageManagerInternal = LocalServices.getService(
720 StorageManagerInternal.class);
721 storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
722 }
723 } finally {
724 Binder.restoreCallingIdentity(token);
725 }
726 }
727
728 }
729
730 private void revokeRuntimePermission(String permName, String packageName,
731 boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
732 if (!mUserManagerInt.exists(userId)) {
733 Log.e(TAG, "No such user:" + userId);
734 return;
735 }
736
737 mContext.enforceCallingOrSelfPermission(
738 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
739 "revokeRuntimePermission");
740
741 enforceCrossUserPermission(Binder.getCallingUid(), userId,
742 true /* requireFullPermission */, true /* checkShell */,
743 "revokeRuntimePermission");
744
745 final int appId;
746
747 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
748 if (pkg == null || pkg.mExtras == null) {
749 throw new IllegalArgumentException("Unknown package: " + packageName);
750 }
751 if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
752 throw new IllegalArgumentException("Unknown package: " + packageName);
753 }
754 final BasePermission bp = mSettings.getPermissionLocked(permName);
755 if (bp == null) {
756 throw new IllegalArgumentException("Unknown permission: " + permName);
757 }
758
759 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
760
761 // If a permission review is required for legacy apps we represent
762 // their permissions as always granted runtime ones since we need
763 // to keep the review required permission flag per user while an
764 // install permission's state is shared across all users.
765 if (mSettings.mPermissionReviewRequired
766 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
767 && bp.isRuntime()) {
768 return;
769 }
770
771 final PackageSetting ps = (PackageSetting) pkg.mExtras;
772 final PermissionsState permissionsState = ps.getPermissionsState();
773
774 final int flags = permissionsState.getPermissionFlags(permName, userId);
775 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
776 throw new SecurityException("Cannot revoke system fixed permission "
777 + permName + " for package " + packageName);
778 }
779 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
780 throw new SecurityException("Cannot revoke policy fixed permission "
781 + permName + " for package " + packageName);
782 }
783
784 if (bp.isDevelopment()) {
785 // Development permissions must be handled specially, since they are not
786 // normal runtime permissions. For now they apply to all users.
787 if (permissionsState.revokeInstallPermission(bp) !=
788 PermissionsState.PERMISSION_OPERATION_FAILURE) {
789 if (callback != null) {
790 callback.onInstallPermissionRevoked();
791 }
792 }
793 return;
794 }
795
796 if (permissionsState.revokeRuntimePermission(bp, userId) ==
797 PermissionsState.PERMISSION_OPERATION_FAILURE) {
798 return;
799 }
800
801 if (bp.isRuntime()) {
802 logPermissionRevoked(mContext, permName, packageName);
803 }
804
805 if (callback != null) {
806 final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
807 callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
808 }
809 }
810
811 private int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting, int[] allUserIds) {
812 // Collect all used permissions in the UID
813 final ArraySet<String> usedPermissions = new ArraySet<>();
814 final List<PackageParser.Package> pkgList = suSetting.getPackages();
815 if (pkgList == null || pkgList.size() == 0) {
816 return EmptyArray.INT;
817 }
818 for (PackageParser.Package pkg : pkgList) {
819 final int requestedPermCount = pkg.requestedPermissions.size();
820 for (int j = 0; j < requestedPermCount; j++) {
821 String permission = pkg.requestedPermissions.get(j);
822 BasePermission bp = mSettings.getPermissionLocked(permission);
823 if (bp != null) {
824 usedPermissions.add(permission);
825 }
826 }
827 }
828
829 PermissionsState permissionsState = suSetting.getPermissionsState();
830 // Prune install permissions
831 List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
832 final int installPermCount = installPermStates.size();
833 for (int i = installPermCount - 1; i >= 0; i--) {
834 PermissionState permissionState = installPermStates.get(i);
835 if (!usedPermissions.contains(permissionState.getName())) {
836 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
837 if (bp != null) {
838 permissionsState.revokeInstallPermission(bp);
839 permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
840 PackageManager.MASK_PERMISSION_FLAGS, 0);
841 }
842 }
843 }
844
845 int[] runtimePermissionChangedUserIds = EmptyArray.INT;
846
847 // Prune runtime permissions
848 for (int userId : allUserIds) {
849 List<PermissionState> runtimePermStates = permissionsState
850 .getRuntimePermissionStates(userId);
851 final int runtimePermCount = runtimePermStates.size();
852 for (int i = runtimePermCount - 1; i >= 0; i--) {
853 PermissionState permissionState = runtimePermStates.get(i);
854 if (!usedPermissions.contains(permissionState.getName())) {
855 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
856 if (bp != null) {
857 permissionsState.revokeRuntimePermission(bp, userId);
858 permissionsState.updatePermissionFlags(bp, userId,
859 PackageManager.MASK_PERMISSION_FLAGS, 0);
860 runtimePermissionChangedUserIds = ArrayUtils.appendInt(
861 runtimePermissionChangedUserIds, userId);
862 }
863 }
864 }
865 }
866
867 return runtimePermissionChangedUserIds;
868 }
869
Todd Kennedyc8423932017-10-05 08:58:36 -0700870 private String[] getAppOpPermissionPackages(String permName) {
871 if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
872 return null;
873 }
874 synchronized (mLock) {
875 final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
876 if (pkgs == null) {
877 return null;
878 }
879 return pkgs.toArray(new String[pkgs.size()]);
880 }
881 }
882
883 private int getPermissionFlags(
884 String permName, String packageName, int callingUid, int userId) {
Todd Kennedy0eb97382017-10-03 16:57:22 -0700885 if (!mUserManagerInt.exists(userId)) {
886 return 0;
887 }
888
889 enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
890
891 enforceCrossUserPermission(callingUid, userId,
892 true /* requireFullPermission */, false /* checkShell */,
893 "getPermissionFlags");
894
895 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
896 if (pkg == null || pkg.mExtras == null) {
897 return 0;
898 }
899 synchronized (mLock) {
900 if (mSettings.getPermissionLocked(permName) == null) {
901 return 0;
902 }
903 }
904 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
905 return 0;
906 }
907 final PackageSetting ps = (PackageSetting) pkg.mExtras;
908 PermissionsState permissionsState = ps.getPermissionsState();
909 return permissionsState.getPermissionFlags(permName, userId);
910 }
911
Todd Kennedyc8423932017-10-05 08:58:36 -0700912 private int updatePermissions(String packageName, PackageParser.Package pkgInfo, int flags) {
913 Set<BasePermission> needsUpdate = null;
914 synchronized (mLock) {
915 final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
916 while (it.hasNext()) {
917 final BasePermission bp = it.next();
918 if (bp.isDynamic()) {
919 bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
920 }
921 if (bp.getSourcePackageSetting() != null) {
922 if (packageName != null && packageName.equals(bp.getSourcePackageName())
923 && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
924 Slog.i(TAG, "Removing old permission tree: " + bp.getName()
925 + " from package " + bp.getSourcePackageName());
926 flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
927 it.remove();
928 }
929 continue;
930 }
931 if (needsUpdate == null) {
932 needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
933 }
934 needsUpdate.add(bp);
935 }
936 }
937 if (needsUpdate != null) {
938 for (final BasePermission bp : needsUpdate) {
939 final PackageParser.Package pkg =
940 mPackageManagerInt.getPackage(bp.getSourcePackageName());
941 synchronized (mLock) {
942 if (pkg != null && pkg.mExtras != null) {
943 final PackageSetting ps = (PackageSetting) pkg.mExtras;
944 if (bp.getSourcePackageSetting() == null) {
945 bp.setSourcePackageSetting(ps);
946 }
947 continue;
948 }
949 Slog.w(TAG, "Removing dangling permission: " + bp.getName()
950 + " from package " + bp.getSourcePackageName());
951 mSettings.removePermissionLocked(bp.getName());
952 }
953 }
954 }
955 return flags;
956 }
957
958 private int updatePermissionTrees(String packageName, PackageParser.Package pkgInfo,
959 int flags) {
960 Set<BasePermission> needsUpdate = null;
961 synchronized (mLock) {
962 final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
963 while (it.hasNext()) {
964 final BasePermission bp = it.next();
965 if (bp.getSourcePackageSetting() != null) {
966 if (packageName != null && packageName.equals(bp.getSourcePackageName())
967 && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
968 Slog.i(TAG, "Removing old permission tree: " + bp.getName()
969 + " from package " + bp.getSourcePackageName());
970 flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
971 it.remove();
972 }
973 continue;
974 }
975 if (needsUpdate == null) {
976 needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
977 }
978 needsUpdate.add(bp);
979 }
980 }
981 if (needsUpdate != null) {
982 for (final BasePermission bp : needsUpdate) {
983 final PackageParser.Package pkg =
984 mPackageManagerInt.getPackage(bp.getSourcePackageName());
985 synchronized (mLock) {
986 if (pkg != null && pkg.mExtras != null) {
987 final PackageSetting ps = (PackageSetting) pkg.mExtras;
988 if (bp.getSourcePackageSetting() == null) {
989 bp.setSourcePackageSetting(ps);
990 }
991 continue;
992 }
993 Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
994 + " from package " + bp.getSourcePackageName());
995 mSettings.removePermissionLocked(bp.getName());
996 }
997 }
998 }
999 return flags;
1000 }
1001
Todd Kennedy0eb97382017-10-03 16:57:22 -07001002 private void updatePermissionFlags(String permName, String packageName, int flagMask,
1003 int flagValues, int callingUid, int userId, PermissionCallback callback) {
1004 if (!mUserManagerInt.exists(userId)) {
1005 return;
1006 }
1007
1008 enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
1009
1010 enforceCrossUserPermission(callingUid, userId,
1011 true /* requireFullPermission */, true /* checkShell */,
1012 "updatePermissionFlags");
1013
1014 // Only the system can change these flags and nothing else.
1015 if (callingUid != Process.SYSTEM_UID) {
1016 flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1017 flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1018 flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
1019 flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
1020 flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
1021 }
1022
1023 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
1024 if (pkg == null || pkg.mExtras == null) {
1025 throw new IllegalArgumentException("Unknown package: " + packageName);
1026 }
1027 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1028 throw new IllegalArgumentException("Unknown package: " + packageName);
1029 }
1030
1031 final BasePermission bp;
1032 synchronized (mLock) {
1033 bp = mSettings.getPermissionLocked(permName);
1034 }
1035 if (bp == null) {
1036 throw new IllegalArgumentException("Unknown permission: " + permName);
1037 }
1038
1039 final PackageSetting ps = (PackageSetting) pkg.mExtras;
1040 final PermissionsState permissionsState = ps.getPermissionsState();
1041 final boolean hadState =
1042 permissionsState.getRuntimePermissionState(permName, userId) != null;
1043 final boolean permissionUpdated =
1044 permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
1045 if (permissionUpdated && callback != null) {
1046 // Install and runtime permissions are stored in different places,
1047 // so figure out what permission changed and persist the change.
1048 if (permissionsState.getInstallPermissionState(permName) != null) {
1049 callback.onInstallPermissionUpdated();
1050 } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
1051 || hadState) {
1052 callback.onPermissionUpdated(userId);
1053 }
1054 }
1055 }
1056
1057 private boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
1058 int userId, Collection<Package> packages, PermissionCallback callback) {
1059 if (!mUserManagerInt.exists(userId)) {
1060 return false;
1061 }
1062
1063 enforceGrantRevokeRuntimePermissionPermissions(
1064 "updatePermissionFlagsForAllApps");
1065 enforceCrossUserPermission(callingUid, userId,
1066 true /* requireFullPermission */, true /* checkShell */,
1067 "updatePermissionFlagsForAllApps");
1068
1069 // Only the system can change system fixed flags.
1070 if (callingUid != Process.SYSTEM_UID) {
1071 flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1072 flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1073 }
1074
1075 boolean changed = false;
1076 for (PackageParser.Package pkg : packages) {
1077 final PackageSetting ps = (PackageSetting) pkg.mExtras;
1078 if (ps == null) {
1079 continue;
1080 }
1081 PermissionsState permissionsState = ps.getPermissionsState();
1082 changed |= permissionsState.updatePermissionFlagsForAllPermissions(
1083 userId, flagMask, flagValues);
1084 }
1085 return changed;
1086 }
1087
1088 private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
1089 if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
1090 != PackageManager.PERMISSION_GRANTED
1091 && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
1092 != PackageManager.PERMISSION_GRANTED) {
1093 throw new SecurityException(message + " requires "
1094 + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
1095 + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
1096 }
1097 }
1098
1099 /**
1100 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
1101 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
1102 * @param checkShell whether to prevent shell from access if there's a debugging restriction
1103 * @param message the message to log on security exception
1104 */
1105 private void enforceCrossUserPermission(int callingUid, int userId,
1106 boolean requireFullPermission, boolean checkShell, String message) {
1107 if (userId < 0) {
1108 throw new IllegalArgumentException("Invalid userId " + userId);
1109 }
1110 if (checkShell) {
1111 PackageManagerServiceUtils.enforceShellRestriction(
1112 UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
1113 }
1114 if (userId == UserHandle.getUserId(callingUid)) return;
1115 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
1116 if (requireFullPermission) {
1117 mContext.enforceCallingOrSelfPermission(
1118 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
1119 } else {
1120 try {
1121 mContext.enforceCallingOrSelfPermission(
1122 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
1123 } catch (SecurityException se) {
1124 mContext.enforceCallingOrSelfPermission(
1125 android.Manifest.permission.INTERACT_ACROSS_USERS, message);
1126 }
1127 }
1128 }
1129 }
1130
1131 private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
1132 int size = 0;
Todd Kennedyc8423932017-10-05 08:58:36 -07001133 for (BasePermission perm : mSettings.mPermissions.values()) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07001134 size += tree.calculateFootprint(perm);
1135 }
1136 return size;
1137 }
1138
1139 private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
1140 // We calculate the max size of permissions defined by this uid and throw
1141 // if that plus the size of 'info' would exceed our stated maximum.
1142 if (tree.getUid() != Process.SYSTEM_UID) {
1143 final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
1144 if (curTreeSize + info.calculateFootprint() > MAX_PERMISSION_TREE_FOOTPRINT) {
1145 throw new SecurityException("Permission tree size cap exceeded");
1146 }
1147 }
1148 }
1149
Todd Kennedyc8423932017-10-05 08:58:36 -07001150 private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) {
1151 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
1152 if (pkgInfo.permissions.get(i).info.name.equals(permName)) {
1153 return true;
1154 }
1155 }
1156 return false;
1157 }
1158
Todd Kennedy0eb97382017-10-03 16:57:22 -07001159 /**
1160 * Get the first event id for the permission.
1161 *
1162 * <p>There are four events for each permission: <ul>
1163 * <li>Request permission: first id + 0</li>
1164 * <li>Grant permission: first id + 1</li>
1165 * <li>Request for permission denied: first id + 2</li>
1166 * <li>Revoke permission: first id + 3</li>
1167 * </ul></p>
1168 *
1169 * @param name name of the permission
1170 *
1171 * @return The first event id for the permission
1172 */
1173 private static int getBaseEventId(@NonNull String name) {
1174 int eventIdIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name);
1175
1176 if (eventIdIndex == -1) {
1177 if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE
1178 || Build.IS_USER) {
1179 Log.i(TAG, "Unknown permission " + name);
1180
1181 return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN;
1182 } else {
1183 // Most likely #ALL_DANGEROUS_PERMISSIONS needs to be updated.
1184 //
1185 // Also update
1186 // - EventLogger#ALL_DANGEROUS_PERMISSIONS
1187 // - metrics_constants.proto
1188 throw new IllegalStateException("Unknown permission " + name);
1189 }
1190 }
1191
1192 return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + eventIdIndex * 4;
1193 }
1194
1195 /**
1196 * Log that a permission was revoked.
1197 *
1198 * @param context Context of the caller
1199 * @param name name of the permission
1200 * @param packageName package permission if for
1201 */
1202 private static void logPermissionRevoked(@NonNull Context context, @NonNull String name,
1203 @NonNull String packageName) {
1204 MetricsLogger.action(context, getBaseEventId(name) + 3, packageName);
1205 }
1206
1207 /**
1208 * Log that a permission request was granted.
1209 *
1210 * @param context Context of the caller
1211 * @param name name of the permission
1212 * @param packageName package permission if for
1213 */
1214 private static void logPermissionGranted(@NonNull Context context, @NonNull String name,
1215 @NonNull String packageName) {
1216 MetricsLogger.action(context, getBaseEventId(name) + 1, packageName);
1217 }
1218
1219 private class PermissionManagerInternalImpl extends PermissionManagerInternal {
1220 @Override
Todd Kennedyc8423932017-10-05 08:58:36 -07001221 public void addAllPermissions(Package pkg, boolean chatty) {
1222 PermissionManagerService.this.addAllPermissions(pkg, chatty);
Todd Kennedy0eb97382017-10-03 16:57:22 -07001223 }
1224 @Override
Todd Kennedy460f28c2017-10-06 13:46:22 -07001225 public void addAllPermissionGroups(Package pkg, boolean chatty) {
1226 PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
1227 }
1228 @Override
Todd Kennedyc8423932017-10-05 08:58:36 -07001229 public void removeAllPermissions(Package pkg, boolean chatty) {
1230 PermissionManagerService.this.removeAllPermissions(pkg, chatty);
1231 }
1232 @Override
1233 public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
Todd Kennedy0eb97382017-10-03 16:57:22 -07001234 PermissionCallback callback) {
Todd Kennedyc8423932017-10-05 08:58:36 -07001235 return PermissionManagerService.this.addDynamicPermission(info, callingUid, callback);
1236 }
1237 @Override
1238 public void removeDynamicPermission(String permName, int callingUid,
1239 PermissionCallback callback) {
1240 PermissionManagerService.this.removeDynamicPermission(permName, callingUid, callback);
Todd Kennedy0eb97382017-10-03 16:57:22 -07001241 }
1242 @Override
1243 public void grantRuntimePermission(String permName, String packageName,
1244 boolean overridePolicy, int callingUid, int userId,
1245 PermissionCallback callback) {
1246 PermissionManagerService.this.grantRuntimePermission(
1247 permName, packageName, overridePolicy, callingUid, userId, callback);
1248 }
1249 @Override
1250 public void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
1251 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
1252 PermissionManagerService.this.grantRequestedRuntimePermissions(
1253 pkg, userIds, grantedPermissions, callingUid, callback);
1254 }
1255 @Override
1256 public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg,
1257 int callingUid, PermissionCallback callback) {
1258 PermissionManagerService.this.grantRuntimePermissionsGrantedToDisabledPackageLocked(
1259 pkg, callingUid, callback);
1260 }
1261 @Override
1262 public void revokeRuntimePermission(String permName, String packageName,
1263 boolean overridePolicy, int callingUid, int userId,
1264 PermissionCallback callback) {
1265 PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
1266 overridePolicy, callingUid, userId, callback);
1267 }
1268 @Override
1269 public int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting,
1270 int[] allUserIds) {
1271 return PermissionManagerService.this.revokeUnusedSharedUserPermissions(
1272 (SharedUserSetting) suSetting, allUserIds);
1273 }
1274 @Override
Todd Kennedyc8423932017-10-05 08:58:36 -07001275 public String[] getAppOpPermissionPackages(String permName) {
1276 return PermissionManagerService.this.getAppOpPermissionPackages(permName);
1277 }
1278 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07001279 public int getPermissionFlags(String permName, String packageName, int callingUid,
1280 int userId) {
1281 return PermissionManagerService.this.getPermissionFlags(permName, packageName,
1282 callingUid, userId);
1283 }
1284 @Override
Todd Kennedyc8423932017-10-05 08:58:36 -07001285 public int updatePermissions(String packageName,
1286 PackageParser.Package pkgInfo, int flags) {
1287 return PermissionManagerService.this.updatePermissions(packageName, pkgInfo, flags);
1288 }
1289 @Override
1290 public int updatePermissionTrees(String packageName,
1291 PackageParser.Package pkgInfo, int flags) {
1292 return PermissionManagerService.this.updatePermissionTrees(packageName, pkgInfo, flags);
1293 }
1294 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07001295 public void updatePermissionFlags(String permName, String packageName, int flagMask,
1296 int flagValues, int callingUid, int userId, PermissionCallback callback) {
1297 PermissionManagerService.this.updatePermissionFlags(
1298 permName, packageName, flagMask, flagValues, callingUid, userId, callback);
1299 }
1300 @Override
1301 public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
1302 int userId, Collection<Package> packages, PermissionCallback callback) {
1303 return PermissionManagerService.this.updatePermissionFlagsForAllApps(
1304 flagMask, flagValues, callingUid, userId, packages, callback);
1305 }
1306 @Override
1307 public void enforceCrossUserPermission(int callingUid, int userId,
1308 boolean requireFullPermission, boolean checkShell, String message) {
1309 PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
1310 requireFullPermission, checkShell, message);
1311 }
1312 @Override
1313 public void enforceGrantRevokeRuntimePermissionPermissions(String message) {
1314 PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
1315 }
1316 @Override
1317 public int checkPermission(String permName, String packageName, int callingUid,
1318 int userId) {
1319 return PermissionManagerService.this.checkPermission(
1320 permName, packageName, callingUid, userId);
1321 }
1322 @Override
Todd Kennedy460f28c2017-10-06 13:46:22 -07001323 public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
1324 int callingUid) {
1325 return PermissionManagerService.this.getPermissionGroupInfo(
1326 groupName, flags, callingUid);
1327 }
1328 @Override
1329 public List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
1330 return PermissionManagerService.this.getAllPermissionGroups(flags, callingUid);
1331 }
1332 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07001333 public PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
1334 int callingUid) {
1335 return PermissionManagerService.this.getPermissionInfo(
1336 permName, packageName, flags, callingUid);
1337 }
1338 @Override
1339 public List<PermissionInfo> getPermissionInfoByGroup(String group, int flags,
1340 int callingUid) {
1341 return PermissionManagerService.this.getPermissionInfoByGroup(group, flags, callingUid);
1342 }
1343 @Override
Todd Kennedy0eb97382017-10-03 16:57:22 -07001344 public PermissionSettings getPermissionSettings() {
1345 return mSettings;
1346 }
1347 @Override
1348 public DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
1349 return mDefaultPermissionGrantPolicy;
1350 }
1351 @Override
1352 public BasePermission getPermissionTEMP(String permName) {
1353 synchronized (PermissionManagerService.this.mLock) {
1354 return mSettings.getPermissionLocked(permName);
1355 }
1356 }
1357 @Override
1358 public void putPermissionTEMP(String permName, BasePermission permission) {
1359 synchronized (PermissionManagerService.this.mLock) {
1360 mSettings.putPermissionLocked(permName, (BasePermission) permission);
1361 }
1362 }
1363 @Override
1364 public Iterator<BasePermission> getPermissionIteratorTEMP() {
1365 synchronized (PermissionManagerService.this.mLock) {
1366 return mSettings.getAllPermissionsLocked().iterator();
1367 }
1368 }
1369 }
1370}