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