blob: 6c031a6a32af3492c18cd183af479a06268bab26 [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;
30import android.content.pm.ParceledListSlice;
31import 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;
72
73/**
74 * Manages all permissions and handles permissions related tasks.
75 */
76public class PermissionManagerService {
77 private static final String TAG = "PackageManager";
78
79 /** All dangerous permission names in the same order as the events in MetricsEvent */
80 private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
81 Manifest.permission.READ_CALENDAR,
82 Manifest.permission.WRITE_CALENDAR,
83 Manifest.permission.CAMERA,
84 Manifest.permission.READ_CONTACTS,
85 Manifest.permission.WRITE_CONTACTS,
86 Manifest.permission.GET_ACCOUNTS,
87 Manifest.permission.ACCESS_FINE_LOCATION,
88 Manifest.permission.ACCESS_COARSE_LOCATION,
89 Manifest.permission.RECORD_AUDIO,
90 Manifest.permission.READ_PHONE_STATE,
91 Manifest.permission.CALL_PHONE,
92 Manifest.permission.READ_CALL_LOG,
93 Manifest.permission.WRITE_CALL_LOG,
94 Manifest.permission.ADD_VOICEMAIL,
95 Manifest.permission.USE_SIP,
96 Manifest.permission.PROCESS_OUTGOING_CALLS,
97 Manifest.permission.READ_CELL_BROADCASTS,
98 Manifest.permission.BODY_SENSORS,
99 Manifest.permission.SEND_SMS,
100 Manifest.permission.RECEIVE_SMS,
101 Manifest.permission.READ_SMS,
102 Manifest.permission.RECEIVE_WAP_PUSH,
103 Manifest.permission.RECEIVE_MMS,
104 Manifest.permission.READ_EXTERNAL_STORAGE,
105 Manifest.permission.WRITE_EXTERNAL_STORAGE,
106 Manifest.permission.READ_PHONE_NUMBERS,
107 Manifest.permission.ANSWER_PHONE_CALLS);
108
109 /** Cap the size of permission trees that 3rd party apps can define */
110 private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
111
112 /** Lock to protect internal data access */
113 private final Object mLock;
114
115 /** Internal connection to the package manager */
116 private final PackageManagerInternal mPackageManagerInt;
117
118 /** Internal connection to the user manager */
119 private final UserManagerInternal mUserManagerInt;
120
121 /** Default permission policy to provide proper behaviour out-of-the-box */
122 private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
123
124 /** Internal storage for permissions and related settings */
125 private final PermissionSettings mSettings;
126
127 private final HandlerThread mHandlerThread;
128 private final Handler mHandler;
129 private final Context mContext;
130
131 PermissionManagerService(Context context,
132 @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
133 @NonNull Object externalLock) {
134 mContext = context;
135 mLock = externalLock;
136 mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
137 mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
138 mSettings = new PermissionSettings(context, mLock);
139
140 mHandlerThread = new ServiceThread(TAG,
141 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
142 mHandlerThread.start();
143 mHandler = new Handler(mHandlerThread.getLooper());
144 Watchdog.getInstance().addThread(mHandler);
145
146 mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
147 context, mHandlerThread.getLooper(), defaultGrantCallback, this);
148
149 // propagate permission configuration
150 final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
151 SystemConfig.getInstance().getPermissions();
152 synchronized (mLock) {
153 for (int i=0; i<permConfig.size(); i++) {
154 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
155 BasePermission bp = mSettings.getPermissionLocked(perm.name);
156 if (bp == null) {
157 bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
158 mSettings.putPermissionLocked(perm.name, bp);
159 }
160 if (perm.gids != null) {
161 bp.setGids(perm.gids, perm.perUser);
162 }
163 }
164 }
165
166 LocalServices.addService(
167 PermissionManagerInternal.class, new PermissionManagerInternalImpl());
168 }
169
170 /**
171 * Creates and returns an initialized, internal service for use by other components.
172 * <p>
173 * The object returned is identical to the one returned by the LocalServices class using:
174 * {@code LocalServices.getService(PermissionManagerInternal.class);}
175 * <p>
176 * NOTE: The external lock is temporary and should be removed. This needs to be a
177 * lock created by the permission manager itself.
178 */
179 public static PermissionManagerInternal create(Context context,
180 @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
181 @NonNull Object externalLock) {
182 final PermissionManagerInternal permMgrInt =
183 LocalServices.getService(PermissionManagerInternal.class);
184 if (permMgrInt != null) {
185 return permMgrInt;
186 }
187 new PermissionManagerService(context, defaultGrantCallback, externalLock);
188 return LocalServices.getService(PermissionManagerInternal.class);
189 }
190
191 @Nullable BasePermission getPermission(String permName) {
192 synchronized (mLock) {
193 return mSettings.getPermissionLocked(permName);
194 }
195 }
196
197 private int checkPermission(String permName, String pkgName, int callingUid, int userId) {
198 if (!mUserManagerInt.exists(userId)) {
199 return PackageManager.PERMISSION_DENIED;
200 }
201
202 final PackageParser.Package pkg = mPackageManagerInt.getPackage(pkgName);
203 if (pkg != null && pkg.mExtras != null) {
204 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
205 return PackageManager.PERMISSION_DENIED;
206 }
207 final PackageSetting ps = (PackageSetting) pkg.mExtras;
208 final boolean instantApp = ps.getInstantApp(userId);
209 final PermissionsState permissionsState = ps.getPermissionsState();
210 if (permissionsState.hasPermission(permName, userId)) {
211 if (instantApp) {
212 synchronized (mLock) {
213 BasePermission bp = mSettings.getPermissionLocked(permName);
214 if (bp != null && bp.isInstant()) {
215 return PackageManager.PERMISSION_GRANTED;
216 }
217 }
218 } else {
219 return PackageManager.PERMISSION_GRANTED;
220 }
221 }
222 // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
223 if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
224 .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
225 return PackageManager.PERMISSION_GRANTED;
226 }
227 }
228
229 return PackageManager.PERMISSION_DENIED;
230 }
231
232 private PermissionInfo getPermissionInfo(String name, String packageName, int flags,
233 int callingUid) {
234 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
235 return null;
236 }
237 // reader
238 synchronized (mLock) {
239 final BasePermission bp = mSettings.getPermissionLocked(name);
240 if (bp == null) {
241 return null;
242 }
243 final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
244 bp.getProtectionLevel(), packageName, callingUid);
245 return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
246 }
247 }
248
249 private List<PermissionInfo> getPermissionInfoByGroup(
250 String groupName, int flags, int callingUid) {
251 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
252 return null;
253 }
254 // reader
255 synchronized (mLock) {
256 // TODO Uncomment when mPermissionGroups moves to this class
257// if (groupName != null && !mPermissionGroups.containsKey(groupName)) {
258// // This is thrown as NameNotFoundException
259// return null;
260// }
261
262 final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
263 for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
264 final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
265 if (pi != null) {
266 out.add(pi);
267 }
268 }
269 return out;
270 }
271 }
272
273 private int adjustPermissionProtectionFlagsLocked(
274 int protectionLevel, String packageName, int uid) {
275 // Signature permission flags area always reported
276 final int protectionLevelMasked = protectionLevel
277 & (PermissionInfo.PROTECTION_NORMAL
278 | PermissionInfo.PROTECTION_DANGEROUS
279 | PermissionInfo.PROTECTION_SIGNATURE);
280 if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
281 return protectionLevel;
282 }
283 // System sees all flags.
284 final int appId = UserHandle.getAppId(uid);
285 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
286 || appId == Process.SHELL_UID) {
287 return protectionLevel;
288 }
289 // Normalize package name to handle renamed packages and static libs
290 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
291 if (pkg == null) {
292 return protectionLevel;
293 }
294 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
295 return protectionLevelMasked;
296 }
297 // Apps that target O see flags for all protection levels.
298 final PackageSetting ps = (PackageSetting) pkg.mExtras;
299 if (ps == null) {
300 return protectionLevel;
301 }
302 if (ps.getAppId() != appId) {
303 return protectionLevel;
304 }
305 return protectionLevel;
306 }
307
308 private boolean addPermission(
309 PermissionInfo info, int callingUid, PermissionCallback callback) {
310 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
311 throw new SecurityException("Instant apps can't add permissions");
312 }
313 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
314 throw new SecurityException("Label must be specified in permission");
315 }
316 final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
317 info.name, callingUid);
318 final boolean added;
319 final boolean changed;
320 synchronized (mLock) {
321 BasePermission bp = mSettings.getPermissionLocked(info.name);
322 added = bp == null;
323 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
324 if (added) {
325 enforcePermissionCapLocked(info, tree);
326 bp = new BasePermission(info.name, tree.getSourcePackageName(),
327 BasePermission.TYPE_DYNAMIC);
328 } else if (bp.isDynamic()) {
329 throw new SecurityException(
330 "Not allowed to modify non-dynamic permission "
331 + info.name);
332 }
333 changed = bp.addToTree(fixedLevel, info, tree);
334 if (added) {
335 mSettings.putPermissionLocked(info.name, bp);
336 }
337 }
338 if (changed && callback != null) {
339 callback.onPermissionChanged();
340 }
341 return added;
342 }
343
344 private void removePermission(
345 String permName, int callingUid, PermissionCallback callback) {
346 if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
347 throw new SecurityException("Instant applications don't have access to this method");
348 }
349 final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
350 permName, callingUid);
351 synchronized (mLock) {
352 final BasePermission bp = mSettings.getPermissionLocked(permName);
353 if (bp == null) {
354 return;
355 }
356 if (bp.isDynamic()) {
357 throw new SecurityException(
358 "Not allowed to modify non-dynamic permission "
359 + permName);
360 }
361 mSettings.removePermissionLocked(permName);
362 if (callback != null) {
363 callback.onPermissionRemoved();
364 }
365 }
366 }
367
368 private void grantRuntimePermissionsGrantedToDisabledPackageLocked(
369 PackageParser.Package pkg, int callingUid, PermissionCallback callback) {
370 if (pkg.parentPackage == null) {
371 return;
372 }
373 if (pkg.requestedPermissions == null) {
374 return;
375 }
376 final PackageParser.Package disabledPkg =
377 mPackageManagerInt.getDisabledPackage(pkg.parentPackage.packageName);
378 if (disabledPkg == null || disabledPkg.mExtras == null) {
379 return;
380 }
381 final PackageSetting disabledPs = (PackageSetting) disabledPkg.mExtras;
382 if (!disabledPs.isPrivileged() || disabledPs.hasChildPackages()) {
383 return;
384 }
385 final int permCount = pkg.requestedPermissions.size();
386 for (int i = 0; i < permCount; i++) {
387 String permission = pkg.requestedPermissions.get(i);
388 BasePermission bp = mSettings.getPermissionLocked(permission);
389 if (bp == null || !(bp.isRuntime() || bp.isDevelopment())) {
390 continue;
391 }
392 for (int userId : mUserManagerInt.getUserIds()) {
393 if (disabledPs.getPermissionsState().hasRuntimePermission(permission, userId)) {
394 grantRuntimePermission(
395 permission, pkg.packageName, false, callingUid, userId, callback);
396 }
397 }
398 }
399 }
400
401 private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
402 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
403 for (int userId : userIds) {
404 grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid,
405 callback);
406 }
407 }
408
409 private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
410 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
411 PackageSetting ps = (PackageSetting) pkg.mExtras;
412 if (ps == null) {
413 return;
414 }
415
416 PermissionsState permissionsState = ps.getPermissionsState();
417
418 final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
419 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
420
421 final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
422 >= Build.VERSION_CODES.M;
423
424 final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.packageName, userId);
425
426 for (String permission : pkg.requestedPermissions) {
427 final BasePermission bp;
428 synchronized (mLock) {
429 bp = mSettings.getPermissionLocked(permission);
430 }
431 if (bp != null && (bp.isRuntime() || bp.isDevelopment())
432 && (!instantApp || bp.isInstant())
433 && (supportsRuntimePermissions || !bp.isRuntimeOnly())
434 && (grantedPermissions == null
435 || ArrayUtils.contains(grantedPermissions, permission))) {
436 final int flags = permissionsState.getPermissionFlags(permission, userId);
437 if (supportsRuntimePermissions) {
438 // Installer cannot change immutable permissions.
439 if ((flags & immutableFlags) == 0) {
440 grantRuntimePermission(permission, pkg.packageName, false, callingUid,
441 userId, callback);
442 }
443 } else if (mSettings.mPermissionReviewRequired) {
444 // In permission review mode we clear the review flag when we
445 // are asked to install the app with all permissions granted.
446 if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
447 updatePermissionFlags(permission, pkg.packageName,
448 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
449 userId, callback);
450 }
451 }
452 }
453 }
454 }
455
456 private void grantRuntimePermission(String permName, String packageName, boolean overridePolicy,
457 int callingUid, final int userId, PermissionCallback callback) {
458 if (!mUserManagerInt.exists(userId)) {
459 Log.e(TAG, "No such user:" + userId);
460 return;
461 }
462
463 mContext.enforceCallingOrSelfPermission(
464 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
465 "grantRuntimePermission");
466
467 enforceCrossUserPermission(callingUid, userId,
468 true /* requireFullPermission */, true /* checkShell */,
469 "grantRuntimePermission");
470
471 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
472 if (pkg == null || pkg.mExtras == null) {
473 throw new IllegalArgumentException("Unknown package: " + packageName);
474 }
475 final BasePermission bp;
476 synchronized(mLock) {
477 bp = mSettings.getPermissionLocked(permName);
478 }
479 if (bp == null) {
480 throw new IllegalArgumentException("Unknown permission: " + permName);
481 }
482 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
483 throw new IllegalArgumentException("Unknown package: " + packageName);
484 }
485
486 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
487
488 // If a permission review is required for legacy apps we represent
489 // their permissions as always granted runtime ones since we need
490 // to keep the review required permission flag per user while an
491 // install permission's state is shared across all users.
492 if (mSettings.mPermissionReviewRequired
493 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
494 && bp.isRuntime()) {
495 return;
496 }
497
498 final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
499
500 final PackageSetting ps = (PackageSetting) pkg.mExtras;
501 final PermissionsState permissionsState = ps.getPermissionsState();
502
503 final int flags = permissionsState.getPermissionFlags(permName, userId);
504 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
505 throw new SecurityException("Cannot grant system fixed permission "
506 + permName + " for package " + packageName);
507 }
508 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
509 throw new SecurityException("Cannot grant policy fixed permission "
510 + permName + " for package " + packageName);
511 }
512
513 if (bp.isDevelopment()) {
514 // Development permissions must be handled specially, since they are not
515 // normal runtime permissions. For now they apply to all users.
516 if (permissionsState.grantInstallPermission(bp) !=
517 PermissionsState.PERMISSION_OPERATION_FAILURE) {
518 if (callback != null) {
519 callback.onInstallPermissionGranted();
520 }
521 }
522 return;
523 }
524
525 if (ps.getInstantApp(userId) && !bp.isInstant()) {
526 throw new SecurityException("Cannot grant non-ephemeral permission"
527 + permName + " for package " + packageName);
528 }
529
530 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
531 Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
532 return;
533 }
534
535 final int result = permissionsState.grantRuntimePermission(bp, userId);
536 switch (result) {
537 case PermissionsState.PERMISSION_OPERATION_FAILURE: {
538 return;
539 }
540
541 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
542 if (callback != null) {
543 callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
544 }
545 }
546 break;
547 }
548
549 if (bp.isRuntime()) {
550 logPermissionGranted(mContext, permName, packageName);
551 }
552
553 if (callback != null) {
554 callback.onPermissionGranted(uid, userId);
555 }
556
557 // Only need to do this if user is initialized. Otherwise it's a new user
558 // and there are no processes running as the user yet and there's no need
559 // to make an expensive call to remount processes for the changed permissions.
560 if (READ_EXTERNAL_STORAGE.equals(permName)
561 || WRITE_EXTERNAL_STORAGE.equals(permName)) {
562 final long token = Binder.clearCallingIdentity();
563 try {
564 if (mUserManagerInt.isUserInitialized(userId)) {
565 StorageManagerInternal storageManagerInternal = LocalServices.getService(
566 StorageManagerInternal.class);
567 storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
568 }
569 } finally {
570 Binder.restoreCallingIdentity(token);
571 }
572 }
573
574 }
575
576 private void revokeRuntimePermission(String permName, String packageName,
577 boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
578 if (!mUserManagerInt.exists(userId)) {
579 Log.e(TAG, "No such user:" + userId);
580 return;
581 }
582
583 mContext.enforceCallingOrSelfPermission(
584 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
585 "revokeRuntimePermission");
586
587 enforceCrossUserPermission(Binder.getCallingUid(), userId,
588 true /* requireFullPermission */, true /* checkShell */,
589 "revokeRuntimePermission");
590
591 final int appId;
592
593 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
594 if (pkg == null || pkg.mExtras == null) {
595 throw new IllegalArgumentException("Unknown package: " + packageName);
596 }
597 if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
598 throw new IllegalArgumentException("Unknown package: " + packageName);
599 }
600 final BasePermission bp = mSettings.getPermissionLocked(permName);
601 if (bp == null) {
602 throw new IllegalArgumentException("Unknown permission: " + permName);
603 }
604
605 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
606
607 // If a permission review is required for legacy apps we represent
608 // their permissions as always granted runtime ones since we need
609 // to keep the review required permission flag per user while an
610 // install permission's state is shared across all users.
611 if (mSettings.mPermissionReviewRequired
612 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
613 && bp.isRuntime()) {
614 return;
615 }
616
617 final PackageSetting ps = (PackageSetting) pkg.mExtras;
618 final PermissionsState permissionsState = ps.getPermissionsState();
619
620 final int flags = permissionsState.getPermissionFlags(permName, userId);
621 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
622 throw new SecurityException("Cannot revoke system fixed permission "
623 + permName + " for package " + packageName);
624 }
625 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
626 throw new SecurityException("Cannot revoke policy fixed permission "
627 + permName + " for package " + packageName);
628 }
629
630 if (bp.isDevelopment()) {
631 // Development permissions must be handled specially, since they are not
632 // normal runtime permissions. For now they apply to all users.
633 if (permissionsState.revokeInstallPermission(bp) !=
634 PermissionsState.PERMISSION_OPERATION_FAILURE) {
635 if (callback != null) {
636 callback.onInstallPermissionRevoked();
637 }
638 }
639 return;
640 }
641
642 if (permissionsState.revokeRuntimePermission(bp, userId) ==
643 PermissionsState.PERMISSION_OPERATION_FAILURE) {
644 return;
645 }
646
647 if (bp.isRuntime()) {
648 logPermissionRevoked(mContext, permName, packageName);
649 }
650
651 if (callback != null) {
652 final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
653 callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
654 }
655 }
656
657 private int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting, int[] allUserIds) {
658 // Collect all used permissions in the UID
659 final ArraySet<String> usedPermissions = new ArraySet<>();
660 final List<PackageParser.Package> pkgList = suSetting.getPackages();
661 if (pkgList == null || pkgList.size() == 0) {
662 return EmptyArray.INT;
663 }
664 for (PackageParser.Package pkg : pkgList) {
665 final int requestedPermCount = pkg.requestedPermissions.size();
666 for (int j = 0; j < requestedPermCount; j++) {
667 String permission = pkg.requestedPermissions.get(j);
668 BasePermission bp = mSettings.getPermissionLocked(permission);
669 if (bp != null) {
670 usedPermissions.add(permission);
671 }
672 }
673 }
674
675 PermissionsState permissionsState = suSetting.getPermissionsState();
676 // Prune install permissions
677 List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
678 final int installPermCount = installPermStates.size();
679 for (int i = installPermCount - 1; i >= 0; i--) {
680 PermissionState permissionState = installPermStates.get(i);
681 if (!usedPermissions.contains(permissionState.getName())) {
682 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
683 if (bp != null) {
684 permissionsState.revokeInstallPermission(bp);
685 permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
686 PackageManager.MASK_PERMISSION_FLAGS, 0);
687 }
688 }
689 }
690
691 int[] runtimePermissionChangedUserIds = EmptyArray.INT;
692
693 // Prune runtime permissions
694 for (int userId : allUserIds) {
695 List<PermissionState> runtimePermStates = permissionsState
696 .getRuntimePermissionStates(userId);
697 final int runtimePermCount = runtimePermStates.size();
698 for (int i = runtimePermCount - 1; i >= 0; i--) {
699 PermissionState permissionState = runtimePermStates.get(i);
700 if (!usedPermissions.contains(permissionState.getName())) {
701 BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
702 if (bp != null) {
703 permissionsState.revokeRuntimePermission(bp, userId);
704 permissionsState.updatePermissionFlags(bp, userId,
705 PackageManager.MASK_PERMISSION_FLAGS, 0);
706 runtimePermissionChangedUserIds = ArrayUtils.appendInt(
707 runtimePermissionChangedUserIds, userId);
708 }
709 }
710 }
711 }
712
713 return runtimePermissionChangedUserIds;
714 }
715
716 private int getPermissionFlags(String permName, String packageName, int callingUid, int userId) {
717 if (!mUserManagerInt.exists(userId)) {
718 return 0;
719 }
720
721 enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
722
723 enforceCrossUserPermission(callingUid, userId,
724 true /* requireFullPermission */, false /* checkShell */,
725 "getPermissionFlags");
726
727 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
728 if (pkg == null || pkg.mExtras == null) {
729 return 0;
730 }
731 synchronized (mLock) {
732 if (mSettings.getPermissionLocked(permName) == null) {
733 return 0;
734 }
735 }
736 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
737 return 0;
738 }
739 final PackageSetting ps = (PackageSetting) pkg.mExtras;
740 PermissionsState permissionsState = ps.getPermissionsState();
741 return permissionsState.getPermissionFlags(permName, userId);
742 }
743
744 private void updatePermissionFlags(String permName, String packageName, int flagMask,
745 int flagValues, int callingUid, int userId, PermissionCallback callback) {
746 if (!mUserManagerInt.exists(userId)) {
747 return;
748 }
749
750 enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
751
752 enforceCrossUserPermission(callingUid, userId,
753 true /* requireFullPermission */, true /* checkShell */,
754 "updatePermissionFlags");
755
756 // Only the system can change these flags and nothing else.
757 if (callingUid != Process.SYSTEM_UID) {
758 flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
759 flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
760 flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
761 flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
762 flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
763 }
764
765 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
766 if (pkg == null || pkg.mExtras == null) {
767 throw new IllegalArgumentException("Unknown package: " + packageName);
768 }
769 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
770 throw new IllegalArgumentException("Unknown package: " + packageName);
771 }
772
773 final BasePermission bp;
774 synchronized (mLock) {
775 bp = mSettings.getPermissionLocked(permName);
776 }
777 if (bp == null) {
778 throw new IllegalArgumentException("Unknown permission: " + permName);
779 }
780
781 final PackageSetting ps = (PackageSetting) pkg.mExtras;
782 final PermissionsState permissionsState = ps.getPermissionsState();
783 final boolean hadState =
784 permissionsState.getRuntimePermissionState(permName, userId) != null;
785 final boolean permissionUpdated =
786 permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
787 if (permissionUpdated && callback != null) {
788 // Install and runtime permissions are stored in different places,
789 // so figure out what permission changed and persist the change.
790 if (permissionsState.getInstallPermissionState(permName) != null) {
791 callback.onInstallPermissionUpdated();
792 } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
793 || hadState) {
794 callback.onPermissionUpdated(userId);
795 }
796 }
797 }
798
799 private boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
800 int userId, Collection<Package> packages, PermissionCallback callback) {
801 if (!mUserManagerInt.exists(userId)) {
802 return false;
803 }
804
805 enforceGrantRevokeRuntimePermissionPermissions(
806 "updatePermissionFlagsForAllApps");
807 enforceCrossUserPermission(callingUid, userId,
808 true /* requireFullPermission */, true /* checkShell */,
809 "updatePermissionFlagsForAllApps");
810
811 // Only the system can change system fixed flags.
812 if (callingUid != Process.SYSTEM_UID) {
813 flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
814 flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
815 }
816
817 boolean changed = false;
818 for (PackageParser.Package pkg : packages) {
819 final PackageSetting ps = (PackageSetting) pkg.mExtras;
820 if (ps == null) {
821 continue;
822 }
823 PermissionsState permissionsState = ps.getPermissionsState();
824 changed |= permissionsState.updatePermissionFlagsForAllPermissions(
825 userId, flagMask, flagValues);
826 }
827 return changed;
828 }
829
830 private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
831 if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
832 != PackageManager.PERMISSION_GRANTED
833 && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
834 != PackageManager.PERMISSION_GRANTED) {
835 throw new SecurityException(message + " requires "
836 + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
837 + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
838 }
839 }
840
841 /**
842 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
843 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
844 * @param checkShell whether to prevent shell from access if there's a debugging restriction
845 * @param message the message to log on security exception
846 */
847 private void enforceCrossUserPermission(int callingUid, int userId,
848 boolean requireFullPermission, boolean checkShell, String message) {
849 if (userId < 0) {
850 throw new IllegalArgumentException("Invalid userId " + userId);
851 }
852 if (checkShell) {
853 PackageManagerServiceUtils.enforceShellRestriction(
854 UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
855 }
856 if (userId == UserHandle.getUserId(callingUid)) return;
857 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
858 if (requireFullPermission) {
859 mContext.enforceCallingOrSelfPermission(
860 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
861 } else {
862 try {
863 mContext.enforceCallingOrSelfPermission(
864 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
865 } catch (SecurityException se) {
866 mContext.enforceCallingOrSelfPermission(
867 android.Manifest.permission.INTERACT_ACROSS_USERS, message);
868 }
869 }
870 }
871 }
872
873 private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
874 int size = 0;
875 for (BasePermission perm : mSettings.getAllPermissionsLocked()) {
876 size += tree.calculateFootprint(perm);
877 }
878 return size;
879 }
880
881 private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
882 // We calculate the max size of permissions defined by this uid and throw
883 // if that plus the size of 'info' would exceed our stated maximum.
884 if (tree.getUid() != Process.SYSTEM_UID) {
885 final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
886 if (curTreeSize + info.calculateFootprint() > MAX_PERMISSION_TREE_FOOTPRINT) {
887 throw new SecurityException("Permission tree size cap exceeded");
888 }
889 }
890 }
891
892 /**
893 * Get the first event id for the permission.
894 *
895 * <p>There are four events for each permission: <ul>
896 * <li>Request permission: first id + 0</li>
897 * <li>Grant permission: first id + 1</li>
898 * <li>Request for permission denied: first id + 2</li>
899 * <li>Revoke permission: first id + 3</li>
900 * </ul></p>
901 *
902 * @param name name of the permission
903 *
904 * @return The first event id for the permission
905 */
906 private static int getBaseEventId(@NonNull String name) {
907 int eventIdIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name);
908
909 if (eventIdIndex == -1) {
910 if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE
911 || Build.IS_USER) {
912 Log.i(TAG, "Unknown permission " + name);
913
914 return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN;
915 } else {
916 // Most likely #ALL_DANGEROUS_PERMISSIONS needs to be updated.
917 //
918 // Also update
919 // - EventLogger#ALL_DANGEROUS_PERMISSIONS
920 // - metrics_constants.proto
921 throw new IllegalStateException("Unknown permission " + name);
922 }
923 }
924
925 return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + eventIdIndex * 4;
926 }
927
928 /**
929 * Log that a permission was revoked.
930 *
931 * @param context Context of the caller
932 * @param name name of the permission
933 * @param packageName package permission if for
934 */
935 private static void logPermissionRevoked(@NonNull Context context, @NonNull String name,
936 @NonNull String packageName) {
937 MetricsLogger.action(context, getBaseEventId(name) + 3, packageName);
938 }
939
940 /**
941 * Log that a permission request was granted.
942 *
943 * @param context Context of the caller
944 * @param name name of the permission
945 * @param packageName package permission if for
946 */
947 private static void logPermissionGranted(@NonNull Context context, @NonNull String name,
948 @NonNull String packageName) {
949 MetricsLogger.action(context, getBaseEventId(name) + 1, packageName);
950 }
951
952 private class PermissionManagerInternalImpl extends PermissionManagerInternal {
953 @Override
954 public boolean addPermission(PermissionInfo info, boolean async, int callingUid,
955 PermissionCallback callback) {
956 return PermissionManagerService.this.addPermission(info, callingUid, callback);
957 }
958 @Override
959 public void removePermission(String permName, int callingUid,
960 PermissionCallback callback) {
961 PermissionManagerService.this.removePermission(permName, callingUid, callback);
962 }
963 @Override
964 public void grantRuntimePermission(String permName, String packageName,
965 boolean overridePolicy, int callingUid, int userId,
966 PermissionCallback callback) {
967 PermissionManagerService.this.grantRuntimePermission(
968 permName, packageName, overridePolicy, callingUid, userId, callback);
969 }
970 @Override
971 public void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
972 String[] grantedPermissions, int callingUid, PermissionCallback callback) {
973 PermissionManagerService.this.grantRequestedRuntimePermissions(
974 pkg, userIds, grantedPermissions, callingUid, callback);
975 }
976 @Override
977 public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg,
978 int callingUid, PermissionCallback callback) {
979 PermissionManagerService.this.grantRuntimePermissionsGrantedToDisabledPackageLocked(
980 pkg, callingUid, callback);
981 }
982 @Override
983 public void revokeRuntimePermission(String permName, String packageName,
984 boolean overridePolicy, int callingUid, int userId,
985 PermissionCallback callback) {
986 PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
987 overridePolicy, callingUid, userId, callback);
988 }
989 @Override
990 public int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting,
991 int[] allUserIds) {
992 return PermissionManagerService.this.revokeUnusedSharedUserPermissions(
993 (SharedUserSetting) suSetting, allUserIds);
994 }
995 @Override
996 public int getPermissionFlags(String permName, String packageName, int callingUid,
997 int userId) {
998 return PermissionManagerService.this.getPermissionFlags(permName, packageName,
999 callingUid, userId);
1000 }
1001 @Override
1002 public void updatePermissionFlags(String permName, String packageName, int flagMask,
1003 int flagValues, int callingUid, int userId, PermissionCallback callback) {
1004 PermissionManagerService.this.updatePermissionFlags(
1005 permName, packageName, flagMask, flagValues, callingUid, userId, callback);
1006 }
1007 @Override
1008 public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
1009 int userId, Collection<Package> packages, PermissionCallback callback) {
1010 return PermissionManagerService.this.updatePermissionFlagsForAllApps(
1011 flagMask, flagValues, callingUid, userId, packages, callback);
1012 }
1013 @Override
1014 public void enforceCrossUserPermission(int callingUid, int userId,
1015 boolean requireFullPermission, boolean checkShell, String message) {
1016 PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
1017 requireFullPermission, checkShell, message);
1018 }
1019 @Override
1020 public void enforceGrantRevokeRuntimePermissionPermissions(String message) {
1021 PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
1022 }
1023 @Override
1024 public int checkPermission(String permName, String packageName, int callingUid,
1025 int userId) {
1026 return PermissionManagerService.this.checkPermission(
1027 permName, packageName, callingUid, userId);
1028 }
1029 @Override
1030 public PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
1031 int callingUid) {
1032 return PermissionManagerService.this.getPermissionInfo(
1033 permName, packageName, flags, callingUid);
1034 }
1035 @Override
1036 public List<PermissionInfo> getPermissionInfoByGroup(String group, int flags,
1037 int callingUid) {
1038 return PermissionManagerService.this.getPermissionInfoByGroup(group, flags, callingUid);
1039 }
1040 @Override
1041 public boolean isPermissionInstant(String permName) {
1042 synchronized (PermissionManagerService.this.mLock) {
1043 final BasePermission bp = mSettings.getPermissionLocked(permName);
1044 return (bp != null && bp.isInstant());
1045 }
1046 }
1047 @Override
1048 public boolean isPermissionAppOp(String permName) {
1049 synchronized (PermissionManagerService.this.mLock) {
1050 final BasePermission bp = mSettings.getPermissionLocked(permName);
1051 return (bp != null && bp.isAppOp());
1052 }
1053 }
1054 @Override
1055 public PermissionSettings getPermissionSettings() {
1056 return mSettings;
1057 }
1058 @Override
1059 public DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
1060 return mDefaultPermissionGrantPolicy;
1061 }
1062 @Override
1063 public BasePermission getPermissionTEMP(String permName) {
1064 synchronized (PermissionManagerService.this.mLock) {
1065 return mSettings.getPermissionLocked(permName);
1066 }
1067 }
1068 @Override
1069 public void putPermissionTEMP(String permName, BasePermission permission) {
1070 synchronized (PermissionManagerService.this.mLock) {
1071 mSettings.putPermissionLocked(permName, (BasePermission) permission);
1072 }
1073 }
1074 @Override
1075 public Iterator<BasePermission> getPermissionIteratorTEMP() {
1076 synchronized (PermissionManagerService.this.mLock) {
1077 return mSettings.getAllPermissionsLocked().iterator();
1078 }
1079 }
1080 }
1081}