diff options
author | Sudheer Shanka <sudheersai@google.com> | 2016-06-08 17:13:24 -0700 |
---|---|---|
committer | gitbuildkicker <android-build@google.com> | 2016-08-17 15:02:49 -0700 |
commit | 5a110cf4720b74526880f78056bff863b3954c19 (patch) | |
tree | 8a171d8f4950e9d5514f6cfbfb20e9200caaedfb | |
parent | 43b5aa6bd6263e8ea87bda8f718eb3b080eed62b (diff) | |
download | frameworks_base-5a110cf4720b74526880f78056bff863b3954c19.zip frameworks_base-5a110cf4720b74526880f78056bff863b3954c19.tar.gz frameworks_base-5a110cf4720b74526880f78056bff863b3954c19.tar.bz2 |
Reduce shell power over user management.
Remove MANAGE_USERS permission from shell and whitelist it for
some specific functionality.
Bug: 29189712
Change-Id: Ifb37448c091af91991964511e3efb1bb4dea1ff3
-rw-r--r-- | core/res/AndroidManifest.xml | 8 | ||||
-rw-r--r-- | packages/Shell/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 80 |
3 files changed, 84 insertions, 6 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 08bccc1..4b54459 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1392,6 +1392,14 @@ <permission android:name="android.permission.MANAGE_USERS" android:protectionLevel="signature|privileged" /> + <!-- @hide Allows an application to create, remove users and get the list of + users on the device. Applications holding this permission can only create restricted, + guest, and managed users. For creating other kind of users, + {@link android.Manifest.permission#MANAGE_USERS} is needed. + This permission is not available to third party applications. --> + <permission android:name="android.permission.CREATE_USERS" + android:protectionLevel="signature" /> + <!-- @hide Allows an application to set the profile owners and the device owner. This permission is not available to third party applications.--> <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index b9daf59..6a20733 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -89,7 +89,7 @@ <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.CREATE_USERS" /> <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" /> <uses-permission android:name="android.permission.BLUETOOTH_STACK" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index c5669cc..583d764 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -125,6 +125,11 @@ public class UserManagerService extends IUserManager.Stub { private static final String RESTRICTIONS_FILE_PREFIX = "res_"; private static final String XML_SUFFIX = ".xml"; + private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION = + UserInfo.FLAG_MANAGED_PROFILE + | UserInfo.FLAG_RESTRICTED + | UserInfo.FLAG_GUEST; + private static final int MIN_USER_ID = 10; private static final int USER_VERSION = 5; @@ -277,7 +282,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public List<UserInfo> getUsers(boolean excludeDying) { - checkManageUsersPermission("query users"); + checkManageOrCreateUsersPermission("query users"); synchronized (mPackagesLock) { ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); for (int i = 0; i < mUsers.size(); i++) { @@ -388,7 +393,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo getUserInfo(int userId) { - checkManageUsersPermission("query user"); + checkManageOrCreateUsersPermission("query user"); synchronized (mPackagesLock) { return getUserInfoLocked(userId); } @@ -676,6 +681,71 @@ public class UserManagerService extends IUserManager.Stub { } } + /** + * Enforces that only the system UID or root's UID or apps that have the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} + * can make certain calls to the UserManager. + * + * @param message used as message if SecurityException is thrown + * @throws SecurityException if the caller is not system or root + * @see #hasManageOrCreateUsersPermission() + */ + private static final void checkManageOrCreateUsersPermission(String message) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException( + "You either need MANAGE_USERS or CREATE_USERS permission to: " + message); + } + } + + /** + * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries + * to create user/profiles other than what is allowed for + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only + * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission. + */ + private static final void checkManageOrCreateUsersPermission(int creationFlags) { + if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS " + + "permission to create an user with flags: " + creationFlags); + } + } else if (!hasManageUsersPermission()) { + throw new SecurityException("You need MANAGE_USERS permission to create an user " + + " with flags: " + creationFlags); + } + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}. + */ + private static final boolean hasManageUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}. + */ + private static final boolean hasManageOrCreateUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED + || ActivityManager.checkComponentPermission( + android.Manifest.permission.CREATE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + private static void checkSystemOrRoot(String message) { final int uid = Binder.getCallingUid(); if (uid != Process.SYSTEM_UID && uid != 0) { @@ -1227,7 +1297,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createProfileForUser(String name, int flags, int userId) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); if (userId != UserHandle.USER_OWNER) { Slog.w(LOG_TAG, "Only user owner can have profiles"); return null; @@ -1237,7 +1307,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createUser(String name, int flags) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); return createUserInternal(name, flags, UserHandle.USER_NULL); } @@ -1402,7 +1472,7 @@ public class UserManagerService extends IUserManager.Stub { * @param userHandle the user's id */ public boolean removeUser(int userHandle) { - checkManageUsersPermission("Only the system can remove users"); + checkManageOrCreateUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); |