diff options
author | Joman Chu <jcchu@tycho.ncsc.mil> | 2012-11-16 13:09:27 -0500 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-07-18 20:56:46 +0100 |
commit | ae74c84819ce2a174d3df98d9888206938b0ebee (patch) | |
tree | 9367007db64a5744f7966f6d18f5262df20b7c2c /core/java | |
parent | 88aeb650afb72aeff6335ebfc9bfee59ed5751c8 (diff) | |
download | frameworks_base-ae74c84819ce2a174d3df98d9888206938b0ebee.zip frameworks_base-ae74c84819ce2a174d3df98d9888206938b0ebee.tar.gz frameworks_base-ae74c84819ce2a174d3df98d9888206938b0ebee.tar.bz2 |
Add APIs to allow Device Admins to change SELinux settings
These calls, added to the Device Admin API, will allow Device Admin apps
to change various SELinux settings, including:
* Toggling SELinux enforcing and permissive modes
* Toggle SELinux booleans
* Load a new SELinux policy file (sepolicy)
* Load new SELinux context files ({property,file,seapp}_contexts)
In order to use these APIs, a Device Admin must first request
USES_POLICY_ENFORCE_SELINUX, then become a SELinux Admin by calling
setSELinuxAdmin(). All other set* calls relevant to SELinux are guarded
by a check against whether the admin is a SELinux Admin.
Otherwise, the style of the set* calls are very similar to the other
calls setting device policy in the Device Admin API. That is, these
calls change the Admin's internal state and then call a sync method to
update the device's state to the Admin's state.
Change-Id: I01f2a9084dfe7886087b1497070b0d7f2ad8476e
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/admin/DeviceAdminInfo.java | 13 | ||||
-rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 297 | ||||
-rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 13 |
3 files changed, 322 insertions, 1 deletions
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java index 66fc816..6849a96 100644 --- a/core/java/android/app/admin/DeviceAdminInfo.java +++ b/core/java/android/app/admin/DeviceAdminInfo.java @@ -146,6 +146,14 @@ public final class DeviceAdminInfo implements Parcelable { */ public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; + /** + * A type of policy that this device admin can use: enforce SELinux policy. + * + * <p>To control this policy, the device admin must have a "enforce-selinux" + * tag in the "uses-policies" section of its meta-data. + */ + public static final int USES_POLICY_ENFORCE_SELINUX = 10; + /** @hide */ public static class PolicyInfo { public final int ident; @@ -197,6 +205,9 @@ public final class DeviceAdminInfo implements Parcelable { USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features", com.android.internal.R.string.policylab_disableKeyguardFeatures, com.android.internal.R.string.policydesc_disableKeyguardFeatures)); + sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_ENFORCE_SELINUX, "enforce-selinux", + com.android.internal.R.string.policylab_enforceSelinux, + com.android.internal.R.string.policydesc_enforceSelinux)); for (int i=0; i<sPoliciesDisplayOrder.size(); i++) { PolicyInfo pi = sPoliciesDisplayOrder.get(i); @@ -389,7 +400,7 @@ public final class DeviceAdminInfo implements Parcelable { * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK}, * {@link #USES_POLICY_WIPE_DATA}, * {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE}, - * {@link #USES_POLICY_DISABLE_CAMERA}. + * {@link #USES_POLICY_DISABLE_CAMERA}, {@link #USES_POLICY_ENFORCE_SELINUX}. */ public boolean usesPolicy(int policyIdent) { return (mUsesPolicies & (1<<policyIdent)) != 0; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 719f050..a80898e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1421,6 +1421,303 @@ public class DevicePolicyManager { } /** + * Called by an application that is administering the device to start or stop + * controlling SELinux policies, enforcement, booleans, etc. When an admin app + * gives up control of SELinux policies, the policy in place prior to the app + * taking control will be applied. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * <p>When an application gains control of SELinux settings, it is called an + * SELinux administrator. Admistration applications will call this with true and + * ensure this method returned true before attempting to toggle SELinux settings. + * When apps intend to stop controlling SELinux settings, apps should call this + * with false. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated, + * must be self + * @param control true if the admin wishes to control SELinux, false if the admin + * wishes to give back control of SELinux + * @return true if the operation succeeded, false if the operation failed or + * SELinux was not enabled on the device. + */ + public boolean setSELinuxAdmin(ComponentName admin, boolean control) { + return setSELinuxAdmin(admin, control, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean setSELinuxAdmin(ComponentName admin, boolean control, int userHandle) { + if (mService != null) { + try { + return mService.setSELinuxAdmin(admin, control, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** + * Checks whether an admin app has control over SELinux policy. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated, + * must be self + * @return true if admin app can control SELinux policy, false otherwise + */ + public boolean isSELinuxAdmin(ComponentName admin) { + return isSELinuxAdmin(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean isSELinuxAdmin(ComponentName admin, int userHandle) { + if (mService != null) { + try { + return mService.isSELinuxAdmin(admin, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** + * Called by a SELinux admin to set SELinux into enforcing or permissive mode. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param enforcing true for enforcing mode, false for permissive mode. + * @return false if Android was unable to set the desired mode + */ + public boolean setSELinuxEnforcing(ComponentName admin, boolean enforcing) { + return setSELinuxEnforcing(admin, enforcing, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean setSELinuxEnforcing(ComponentName admin, boolean enforcing, int userHandle) { + if (mService != null) { + try { + return mService.setSELinuxEnforcing(admin, enforcing, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; // I guess this doesn't fit the spec, but it never happens... + } + + /** + * Determine whether or not SELinux policies are currently being enforced + * by the current admin. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * <p>The returned value is only meaningful if the current admin is a + * SELinux admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public boolean getSELinuxEnforcing(ComponentName admin) { + return getSELinuxEnforcing(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean getSELinuxEnforcing(ComponentName admin, int userHandle) { + if (mService != null) { + try { + return mService.getSELinuxEnforcing(admin, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** + * Get a list of the SELinux booleans available on the system. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * <p>The returned value is only meaningful if the current admin is a + * SELinux admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public List<String> getSELinuxBooleanNames(ComponentName admin) { + return getSELinuxBooleanNames(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public List<String> getSELinuxBooleanNames(ComponentName admin, int userHandle) { + if (mService != null) { + try { + return mService.getSELinuxBooleanNames(admin, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return null; + } + + /** + * Get the value of a SELinux boolean. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * <p>The returned value is only meaningful if the current admin is a + * SELinux admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param name the name of the SELinux boolean + * @return the value of the SELinux boolean + */ + public boolean getSELinuxBooleanValue(ComponentName admin, String name) { + return getSELinuxBooleanValue(admin, name, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean getSELinuxBooleanValue(ComponentName admin, String name, int userHandle) { + if (mService != null) { + try { + return mService.getSELinuxBooleanValue(admin, name, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** + * Set the value of a SELinux boolean. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * <p>The returned value is only meaningful if the current admin is a + * SELinux admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param name the name of the SELinux boolean + * @param value the desired value for the boolean + * @return false if Android was unable to set the desired mode + */ + public boolean setSELinuxBooleanValue(ComponentName admin, String name, + boolean value) { + return setSELinuxBooleanValue(admin, name, value, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean setSELinuxBooleanValue(ComponentName admin, String name, + boolean value, int userHandle) { + if (mService != null) { + try { + return mService.setSELinuxBooleanValue(admin, name, value, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + // Before changing these values, be sure to update + // DevicePolicyManagerService.java's POLICY_DESCRIPTIONS array. + public static final int SEPOLICY_FILE_SEPOLICY = 0; + public static final int SEPOLICY_FILE_PROPCTXS = 1; + public static final int SEPOLICY_FILE_FILECTXS = 2; + public static final int SEPOLICY_FILE_SEAPPCTXS = 3; + public static final int SEPOLICY_FILE_COUNT = SEPOLICY_FILE_SEAPPCTXS+1; + + /** + * Sets a new policy file and reloads it at the proper time. + * + * <p>For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the admin + * must have requested {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} + * before calling this method. If it has not, a security exception will be + * thrown. + * + * <p>For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, these + * files are reloaded before returning from the DevicePolicyManager. + * + * <p>For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the + * returned value is only meaingful if the current admin is a SELinux + * admin. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with + * @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, or {@link #SEPOLICY_FILE_SEAPPCTXS} + * @param policy the new policy file in bytes, or null if you wish to revert to + * the default policy + * @return false if Android was unable to set the new policy + */ + public boolean setCustomPolicyFile(ComponentName admin, int policyType, byte[] policy) { + return setCustomPolicyFile(admin, policyType, policy, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean setCustomPolicyFile(ComponentName admin, int policyType, byte[] policy, int userHandle) { + if (mService != null) { + try { + return mService.setCustomPolicyFile(admin, policyType, policy, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** + * Determine whether this admin set a custom policy file. + * + * <p>For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the admin + * must have requested {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} + * before calling this method. If it has not, a security exception will be + * thrown. + * + * <p>For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the + * returned value is only meaingful if the current admin is a SELinux + * admin. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with + * @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS}, + * {@link #SEPOLICY_FILE_FILECTXS}, or {@link #SEPOLICY_FILE_SEAPPCTXS} + * @return true if the admin set a custom policy file + */ + public boolean isCustomPolicyFile(ComponentName admin, int policyType) { + return isCustomPolicyFile(admin, policyType, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean isCustomPolicyFile(ComponentName admin, int policyType, int userHandle) { + if (mService != null) { + try { + return mService.isCustomPolicyFile(admin, policyType, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy server", e); + } + } + return false; + } + + /** * @hide */ public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e061ab3..3e998fd 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -93,6 +93,19 @@ interface IDevicePolicyManager { void removeActiveAdmin(in ComponentName policyReceiver, int userHandle); boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle); + boolean setSELinuxAdmin(in ComponentName who, boolean control, int userHandle); + boolean isSELinuxAdmin(in ComponentName who, int userHandle); + + boolean setSELinuxEnforcing(in ComponentName who, boolean enforcing, int userHandle); + boolean getSELinuxEnforcing(in ComponentName who, int userHandle); + + List<String> getSELinuxBooleanNames(in ComponentName who, int userHandle); + boolean getSELinuxBooleanValue(in ComponentName who, String name, int userHandle); + boolean setSELinuxBooleanValue(in ComponentName who, String name, boolean value, int userHandle); + + boolean setCustomPolicyFile(in ComponentName who, int policyType, in byte[] policy, int userHandle); + boolean isCustomPolicyFile(in ComponentName who, int policyType, int userHandle); + void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols, int nonletter, int userHandle); void reportFailedPasswordAttempt(int userHandle); |