Loading core/java/android/content/pm/ApplicationInfo.java +5 −3 Original line number Diff line number Diff line Loading @@ -531,12 +531,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * String retrieved from the seinfo tag found in selinux policy. This value * is useful in setting an SELinux security context on the process as well * as its data directory. * can be overridden with a value set through the mac_permissions.xml policy * construct. This value is useful in setting an SELinux security context on * the process as well as its data directory. The String default is being used * here to represent a catchall label when no policy matches. * * {@hide} */ public String seinfo; public String seinfo = "default"; /** * Paths to all shared libraries this application is linked against. This Loading services/core/java/com/android/server/pm/SELinuxMMAC.java +48 −184 Original line number Diff line number Diff line Loading @@ -136,9 +136,6 @@ public final class SELinuxMMAC { case "signer": policies.add(readSignerOrThrow(parser)); break; case "default": policies.add(readDefaultOrThrow(parser)); break; default: skip(parser); } Loading Loading @@ -232,45 +229,6 @@ public final class SELinuxMMAC { return pb.build(); } /** * Loop over a default element looking for seinfo child tags. A {@link Policy} * instance will be created and returned in the process. All other tags encountered * will be skipped. * * @param parser an XmlPullParser object representing a default element. * @return the constructed {@link Policy} instance * @throws IOException * @throws XmlPullParserException * @throws IllegalArgumentException if any of the validation checks fail while * parsing tag values. * @throws IllegalStateException if any of the invariants fail when constructing * the {@link Policy} instance. */ private static Policy readDefaultOrThrow(XmlPullParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, null, "default"); Policy.PolicyBuilder pb = new Policy.PolicyBuilder(); pb.setAsDefaultPolicy(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String tagName = parser.getName(); if ("seinfo".equals(tagName)) { String seinfo = parser.getAttributeValue(null, "value"); pb.setGlobalSeinfoOrThrow(seinfo); readSeinfo(parser); } else { skip(parser); } } return pb.build(); } /** * Loop over a package element looking for seinfo child tags. If found return the * value attribute of the seinfo tag, otherwise return null. All other tags encountered Loading Loading @@ -337,35 +295,28 @@ public final class SELinuxMMAC { /** * Applies a security label to a package based on an seinfo tag taken from a matched * policy. All signature based policy stanzas are consulted first and, if no match * is found, the default policy stanza is then consulted. The security label is * attached to the ApplicationInfo instance of the package in the event that a matching * policy was found. * policy. All signature based policy stanzas are consulted and, if no match is * found, the default seinfo label of 'default' (set in ApplicationInfo object) is * used. The security label is attached to the ApplicationInfo instance of the package * in the event that a matching policy was found. * * @param pkg object representing the package to be labeled. * @return boolean which determines whether a non null seinfo label was assigned * to the package. A null value simply represents that no policy matched. */ public static boolean assignSeinfoValue(PackageParser.Package pkg) { public static void assignSeinfoValue(PackageParser.Package pkg) { synchronized (sPolicies) { for (Policy policy : sPolicies) { String seinfo = policy.getMatchedSeinfo(pkg); if (seinfo != null) { pkg.applicationInfo.seinfo = seinfo; if (DEBUG_POLICY_INSTALL) { Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + "seinfo=" + seinfo); } return true; break; } } } if (DEBUG_POLICY_INSTALL) { Slog.i(TAG, "package (" + pkg.packageName + ") doesn't match any policy; " + "seinfo will remain null"); Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + "seinfo=" + pkg.applicationInfo.seinfo); } return false; } /** Loading Loading @@ -506,30 +457,16 @@ public final class SELinuxMMAC { * .build(); * } * </pre> * <p> * The following is an example of how to use {@link Policy.PolicyBuilder} to create a * default based Policy instance. * </p> * <pre> * {@code * Policy policy = new Policy.PolicyBuilder() * .setAsDefaultPolicy() * .setGlobalSeinfoOrThrow("default") * .build(); * } * </pre> */ final class Policy { private final String mSeinfo; private final boolean mDefaultStanza; private final Set<Signature> mCerts; private final Map<String, String> mPkgMap; // Use the PolicyBuilder pattern to instantiate private Policy(PolicyBuilder builder) { mSeinfo = builder.mSeinfo; mDefaultStanza = builder.mDefaultStanza; mCerts = Collections.unmodifiableSet(builder.mCerts); mPkgMap = Collections.unmodifiableMap(builder.mPkgMap); } Loading @@ -544,15 +481,6 @@ final class Policy { return mCerts; } /** * Return whether this policy object represents a default stanza. * * @return A boolean indicating if this object represents a default policy stanza. */ public boolean isDefaultStanza() { return mDefaultStanza; } /** * Return whether this policy object contains package name mapping refinements. * Loading Loading @@ -584,10 +512,6 @@ final class Policy { @Override public String toString() { StringBuilder sb = new StringBuilder(); if (mDefaultStanza) { sb.append("defaultStanza=true "); } for (Signature cert : mCerts) { sb.append("cert=" + cert.toCharsString().substring(0, 11) + "... "); } Loading @@ -609,11 +533,6 @@ final class Policy { * is determined using the following steps: * </p> * <ul> * <li> If this Policy instance is defined as a default stanza: * <ul><li>Return the global seinfo value</li></ul> * </li> * <li> If this Policy instance is defined as a signer stanza: * <ul> * <li> All certs used to sign the apk and all certs stored with this policy * instance are tested for set equality. If this fails then null is returned. * </li> Loading @@ -625,8 +544,6 @@ final class Policy { * the global seinfo value. The returned value can be null in this case. * </li> * </ul> * </li> * </ul> * <p> * In all cases, a return value of null should be interpreted as the apk failing * to match this Policy instance; i.e. failing this policy stanza. Loading @@ -636,7 +553,6 @@ final class Policy { * A value of null can also be returned if no match occured. */ public String getMatchedSeinfo(PackageParser.Package pkg) { if (!mDefaultStanza) { // Check for exact signature matches across all certs. Signature[] certs = mCerts.toArray(new Signature[0]); if (!Signature.areExactMatch(certs, pkg.mSignatures)) { Loading @@ -649,24 +565,22 @@ final class Policy { if (seinfoValue != null) { return seinfoValue; } } // Return the global seinfo value (even if it's null). // Return the global seinfo value. return mSeinfo; } /** * A nested builder class to create {@link Policy} instances. A {@link Policy} * class instance represents one valid policy stanza found in a mac_permissions.xml * file. A valid policy stanza is defined to be either a signer or default stanza * which obeys the rules outlined in external/sepolicy/mac_permissions.xml. The * {@link #build} method ensures a set of invariants are upheld enforcing the correct * stanza structure before returning a valid Policy object. * file. A valid policy stanza is defined to be a signer stanza which obeys the rules * outlined in external/sepolicy/mac_permissions.xml. The {@link #build} method * ensures a set of invariants are upheld enforcing the correct stanza structure * before returning a valid Policy object. */ public static final class PolicyBuilder { private String mSeinfo; private boolean mDefaultStanza; private final Set<Signature> mCerts; private final Map<String, String> mPkgMap; Loading @@ -675,19 +589,6 @@ final class Policy { mPkgMap = new HashMap<String, String>(2); } /** * Sets this stanza as a default stanza. All policy stanzas are assumed to * be signer stanzas unless this method is explicitly called. Default stanzas * are treated differently with respect to allowable child tags, ordering and * when and how policy decisions are enforced. * * @return The reference to this PolicyBuilder. */ public PolicyBuilder setAsDefaultPolicy() { mDefaultStanza = true; return this; } /** * Adds a signature to the set of certs used for validation checks. The purpose * being that all contained certs will need to be matched against all certs Loading @@ -710,11 +611,8 @@ final class Policy { /** * Set the global seinfo tag for this policy stanza. The global seinfo tag * represents the seinfo element that is used in one of two ways depending on * its context. When attached to a signer tag the global seinfo represents an * assignment when there isn't a further inner package refinement in policy. * When used with a default tag, it represents the only allowable assignment * value. * when attached to a signer tag represents the assignment when there isn't a * further inner package refinement in policy. * * @param seinfo the seinfo value given as a String. * @return The reference to this PolicyBuilder. Loading @@ -740,9 +638,7 @@ final class Policy { /** * Create a package name to seinfo value mapping. Each mapping represents * the seinfo value that will be assigned to the described package name. * These localized mappings allow the global seinfo to be overriden. This * mapping provides no value when used in conjunction with a default stanza; * enforced through the {@link #build} method. * These localized mappings allow the global seinfo to be overriden. * * @param pkgName the android package name given to the app * @param seinfo the seinfo value that will be assigned to the passed pkgName Loading Loading @@ -800,42 +696,17 @@ final class Policy { * Those invariants are: * </p> * <ul> * <li> If a default stanza * <ul> * <li> an attached global seinfo tag must be present </li> * <li> no signatures and no package names can be present </li> * </ul> * </li> * <li> If a signer stanza * <ul> * <li> at least one cert must be found </li> * <li> either a global seinfo value is present OR at least one * inner package mapping must be present BUT not both. </li> * </ul> * </li> * </ul> * * @return an instance of {@link Policy} with the options set from this builder * @throws IllegalStateException if an invariant is violated. */ public Policy build() { Policy p = new Policy(this); if (p.mDefaultStanza) { if (p.mSeinfo == null) { String err = "Missing global seinfo tag with default stanza."; throw new IllegalStateException(err); } if (p.mCerts.size() != 0) { String err = "Certs not allowed with default stanza."; throw new IllegalStateException(err); } if (!p.mPkgMap.isEmpty()) { String err = "Inner package mappings not allowed with default stanza."; throw new IllegalStateException(err); } } else { if (p.mCerts.size() == 0) { if (p.mCerts.isEmpty()) { String err = "Missing certs with signer tag. Expecting at least one."; throw new IllegalStateException(err); } Loading @@ -844,7 +715,6 @@ final class Policy { "a signer stanza."; throw new IllegalStateException(err); } } return p; } Loading @@ -858,7 +728,6 @@ final class Policy { * <ul> * <li> signer stanzas with inner package mappings </li> * <li> signer stanzas with global seinfo tags </li> * <li> default stanza </li> * </ul> * This comparison also checks for duplicate entries on the input selectors. Any * found duplicates will be flagged and can be checked with {@link #foundDuplicate}. Loading @@ -875,11 +744,6 @@ final class PolicyComparator implements Comparator<Policy> { @Override public int compare(Policy p1, Policy p2) { // Give precedence to signature stanzas over default stanzas if (p1.isDefaultStanza() != p2.isDefaultStanza()) { return p1.isDefaultStanza() ? 1 : -1; } // Give precedence to stanzas with inner package mappings if (p1.hasInnerPackages() != p2.hasInnerPackages()) { return p1.hasInnerPackages() ? -1 : 1; Loading @@ -887,7 +751,7 @@ final class PolicyComparator implements Comparator<Policy> { // Check for duplicate entries if (p1.getSignatures().equals(p2.getSignatures())) { // Checks if default stanza or a signer w/o inner package names // Checks if signer w/o inner package names if (p1.hasGlobalSeinfo()) { duplicateFound = true; Slog.e(SELinuxMMAC.TAG, "Duplicate policy entry: " + p1.toString()); Loading Loading
core/java/android/content/pm/ApplicationInfo.java +5 −3 Original line number Diff line number Diff line Loading @@ -531,12 +531,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * String retrieved from the seinfo tag found in selinux policy. This value * is useful in setting an SELinux security context on the process as well * as its data directory. * can be overridden with a value set through the mac_permissions.xml policy * construct. This value is useful in setting an SELinux security context on * the process as well as its data directory. The String default is being used * here to represent a catchall label when no policy matches. * * {@hide} */ public String seinfo; public String seinfo = "default"; /** * Paths to all shared libraries this application is linked against. This Loading
services/core/java/com/android/server/pm/SELinuxMMAC.java +48 −184 Original line number Diff line number Diff line Loading @@ -136,9 +136,6 @@ public final class SELinuxMMAC { case "signer": policies.add(readSignerOrThrow(parser)); break; case "default": policies.add(readDefaultOrThrow(parser)); break; default: skip(parser); } Loading Loading @@ -232,45 +229,6 @@ public final class SELinuxMMAC { return pb.build(); } /** * Loop over a default element looking for seinfo child tags. A {@link Policy} * instance will be created and returned in the process. All other tags encountered * will be skipped. * * @param parser an XmlPullParser object representing a default element. * @return the constructed {@link Policy} instance * @throws IOException * @throws XmlPullParserException * @throws IllegalArgumentException if any of the validation checks fail while * parsing tag values. * @throws IllegalStateException if any of the invariants fail when constructing * the {@link Policy} instance. */ private static Policy readDefaultOrThrow(XmlPullParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, null, "default"); Policy.PolicyBuilder pb = new Policy.PolicyBuilder(); pb.setAsDefaultPolicy(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String tagName = parser.getName(); if ("seinfo".equals(tagName)) { String seinfo = parser.getAttributeValue(null, "value"); pb.setGlobalSeinfoOrThrow(seinfo); readSeinfo(parser); } else { skip(parser); } } return pb.build(); } /** * Loop over a package element looking for seinfo child tags. If found return the * value attribute of the seinfo tag, otherwise return null. All other tags encountered Loading Loading @@ -337,35 +295,28 @@ public final class SELinuxMMAC { /** * Applies a security label to a package based on an seinfo tag taken from a matched * policy. All signature based policy stanzas are consulted first and, if no match * is found, the default policy stanza is then consulted. The security label is * attached to the ApplicationInfo instance of the package in the event that a matching * policy was found. * policy. All signature based policy stanzas are consulted and, if no match is * found, the default seinfo label of 'default' (set in ApplicationInfo object) is * used. The security label is attached to the ApplicationInfo instance of the package * in the event that a matching policy was found. * * @param pkg object representing the package to be labeled. * @return boolean which determines whether a non null seinfo label was assigned * to the package. A null value simply represents that no policy matched. */ public static boolean assignSeinfoValue(PackageParser.Package pkg) { public static void assignSeinfoValue(PackageParser.Package pkg) { synchronized (sPolicies) { for (Policy policy : sPolicies) { String seinfo = policy.getMatchedSeinfo(pkg); if (seinfo != null) { pkg.applicationInfo.seinfo = seinfo; if (DEBUG_POLICY_INSTALL) { Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + "seinfo=" + seinfo); } return true; break; } } } if (DEBUG_POLICY_INSTALL) { Slog.i(TAG, "package (" + pkg.packageName + ") doesn't match any policy; " + "seinfo will remain null"); Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + "seinfo=" + pkg.applicationInfo.seinfo); } return false; } /** Loading Loading @@ -506,30 +457,16 @@ public final class SELinuxMMAC { * .build(); * } * </pre> * <p> * The following is an example of how to use {@link Policy.PolicyBuilder} to create a * default based Policy instance. * </p> * <pre> * {@code * Policy policy = new Policy.PolicyBuilder() * .setAsDefaultPolicy() * .setGlobalSeinfoOrThrow("default") * .build(); * } * </pre> */ final class Policy { private final String mSeinfo; private final boolean mDefaultStanza; private final Set<Signature> mCerts; private final Map<String, String> mPkgMap; // Use the PolicyBuilder pattern to instantiate private Policy(PolicyBuilder builder) { mSeinfo = builder.mSeinfo; mDefaultStanza = builder.mDefaultStanza; mCerts = Collections.unmodifiableSet(builder.mCerts); mPkgMap = Collections.unmodifiableMap(builder.mPkgMap); } Loading @@ -544,15 +481,6 @@ final class Policy { return mCerts; } /** * Return whether this policy object represents a default stanza. * * @return A boolean indicating if this object represents a default policy stanza. */ public boolean isDefaultStanza() { return mDefaultStanza; } /** * Return whether this policy object contains package name mapping refinements. * Loading Loading @@ -584,10 +512,6 @@ final class Policy { @Override public String toString() { StringBuilder sb = new StringBuilder(); if (mDefaultStanza) { sb.append("defaultStanza=true "); } for (Signature cert : mCerts) { sb.append("cert=" + cert.toCharsString().substring(0, 11) + "... "); } Loading @@ -609,11 +533,6 @@ final class Policy { * is determined using the following steps: * </p> * <ul> * <li> If this Policy instance is defined as a default stanza: * <ul><li>Return the global seinfo value</li></ul> * </li> * <li> If this Policy instance is defined as a signer stanza: * <ul> * <li> All certs used to sign the apk and all certs stored with this policy * instance are tested for set equality. If this fails then null is returned. * </li> Loading @@ -625,8 +544,6 @@ final class Policy { * the global seinfo value. The returned value can be null in this case. * </li> * </ul> * </li> * </ul> * <p> * In all cases, a return value of null should be interpreted as the apk failing * to match this Policy instance; i.e. failing this policy stanza. Loading @@ -636,7 +553,6 @@ final class Policy { * A value of null can also be returned if no match occured. */ public String getMatchedSeinfo(PackageParser.Package pkg) { if (!mDefaultStanza) { // Check for exact signature matches across all certs. Signature[] certs = mCerts.toArray(new Signature[0]); if (!Signature.areExactMatch(certs, pkg.mSignatures)) { Loading @@ -649,24 +565,22 @@ final class Policy { if (seinfoValue != null) { return seinfoValue; } } // Return the global seinfo value (even if it's null). // Return the global seinfo value. return mSeinfo; } /** * A nested builder class to create {@link Policy} instances. A {@link Policy} * class instance represents one valid policy stanza found in a mac_permissions.xml * file. A valid policy stanza is defined to be either a signer or default stanza * which obeys the rules outlined in external/sepolicy/mac_permissions.xml. The * {@link #build} method ensures a set of invariants are upheld enforcing the correct * stanza structure before returning a valid Policy object. * file. A valid policy stanza is defined to be a signer stanza which obeys the rules * outlined in external/sepolicy/mac_permissions.xml. The {@link #build} method * ensures a set of invariants are upheld enforcing the correct stanza structure * before returning a valid Policy object. */ public static final class PolicyBuilder { private String mSeinfo; private boolean mDefaultStanza; private final Set<Signature> mCerts; private final Map<String, String> mPkgMap; Loading @@ -675,19 +589,6 @@ final class Policy { mPkgMap = new HashMap<String, String>(2); } /** * Sets this stanza as a default stanza. All policy stanzas are assumed to * be signer stanzas unless this method is explicitly called. Default stanzas * are treated differently with respect to allowable child tags, ordering and * when and how policy decisions are enforced. * * @return The reference to this PolicyBuilder. */ public PolicyBuilder setAsDefaultPolicy() { mDefaultStanza = true; return this; } /** * Adds a signature to the set of certs used for validation checks. The purpose * being that all contained certs will need to be matched against all certs Loading @@ -710,11 +611,8 @@ final class Policy { /** * Set the global seinfo tag for this policy stanza. The global seinfo tag * represents the seinfo element that is used in one of two ways depending on * its context. When attached to a signer tag the global seinfo represents an * assignment when there isn't a further inner package refinement in policy. * When used with a default tag, it represents the only allowable assignment * value. * when attached to a signer tag represents the assignment when there isn't a * further inner package refinement in policy. * * @param seinfo the seinfo value given as a String. * @return The reference to this PolicyBuilder. Loading @@ -740,9 +638,7 @@ final class Policy { /** * Create a package name to seinfo value mapping. Each mapping represents * the seinfo value that will be assigned to the described package name. * These localized mappings allow the global seinfo to be overriden. This * mapping provides no value when used in conjunction with a default stanza; * enforced through the {@link #build} method. * These localized mappings allow the global seinfo to be overriden. * * @param pkgName the android package name given to the app * @param seinfo the seinfo value that will be assigned to the passed pkgName Loading Loading @@ -800,42 +696,17 @@ final class Policy { * Those invariants are: * </p> * <ul> * <li> If a default stanza * <ul> * <li> an attached global seinfo tag must be present </li> * <li> no signatures and no package names can be present </li> * </ul> * </li> * <li> If a signer stanza * <ul> * <li> at least one cert must be found </li> * <li> either a global seinfo value is present OR at least one * inner package mapping must be present BUT not both. </li> * </ul> * </li> * </ul> * * @return an instance of {@link Policy} with the options set from this builder * @throws IllegalStateException if an invariant is violated. */ public Policy build() { Policy p = new Policy(this); if (p.mDefaultStanza) { if (p.mSeinfo == null) { String err = "Missing global seinfo tag with default stanza."; throw new IllegalStateException(err); } if (p.mCerts.size() != 0) { String err = "Certs not allowed with default stanza."; throw new IllegalStateException(err); } if (!p.mPkgMap.isEmpty()) { String err = "Inner package mappings not allowed with default stanza."; throw new IllegalStateException(err); } } else { if (p.mCerts.size() == 0) { if (p.mCerts.isEmpty()) { String err = "Missing certs with signer tag. Expecting at least one."; throw new IllegalStateException(err); } Loading @@ -844,7 +715,6 @@ final class Policy { "a signer stanza."; throw new IllegalStateException(err); } } return p; } Loading @@ -858,7 +728,6 @@ final class Policy { * <ul> * <li> signer stanzas with inner package mappings </li> * <li> signer stanzas with global seinfo tags </li> * <li> default stanza </li> * </ul> * This comparison also checks for duplicate entries on the input selectors. Any * found duplicates will be flagged and can be checked with {@link #foundDuplicate}. Loading @@ -875,11 +744,6 @@ final class PolicyComparator implements Comparator<Policy> { @Override public int compare(Policy p1, Policy p2) { // Give precedence to signature stanzas over default stanzas if (p1.isDefaultStanza() != p2.isDefaultStanza()) { return p1.isDefaultStanza() ? 1 : -1; } // Give precedence to stanzas with inner package mappings if (p1.hasInnerPackages() != p2.hasInnerPackages()) { return p1.hasInnerPackages() ? -1 : 1; Loading @@ -887,7 +751,7 @@ final class PolicyComparator implements Comparator<Policy> { // Check for duplicate entries if (p1.getSignatures().equals(p2.getSignatures())) { // Checks if default stanza or a signer w/o inner package names // Checks if signer w/o inner package names if (p1.hasGlobalSeinfo()) { duplicateFound = true; Slog.e(SELinuxMMAC.TAG, "Duplicate policy entry: " + p1.toString()); Loading