summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSudheer Shanka <sudheersai@google.com>2016-06-08 17:13:24 -0700
committergitbuildkicker <android-build@google.com>2016-08-17 15:02:49 -0700
commit5a110cf4720b74526880f78056bff863b3954c19 (patch)
tree8a171d8f4950e9d5514f6cfbfb20e9200caaedfb
parent43b5aa6bd6263e8ea87bda8f718eb3b080eed62b (diff)
downloadframeworks_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.xml8
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java80
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.");