Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b00a063e authored by Stephen Smalley's avatar Stephen Smalley Committed by Ricardo Cerqueira
Browse files

Apply MMAC changes from master.

Change-Id: I01f2a9084dfe7886087b1497070b0d7f2ad8477e
parent 36d685c5
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -645,6 +645,14 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;

    /**
     * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
     * if the system failed to install the package because of a policy denial.
     * @hide
     */
    public static final int INSTALL_FAILED_POLICY_REJECTED_PERMISSION = -111;

    /**
     * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
     * package's data directory.
+288 −54
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.content.pm.Signature;
import android.os.Environment;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Slog;
import android.util.Xml;

@@ -32,6 +34,9 @@ import java.io.FileReader;
import java.io.IOException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -43,17 +48,18 @@ import org.xmlpull.v1.XmlPullParserException;
public final class SELinuxMMAC {

    private static final String TAG = "SELinuxMMAC";
    private static final String MMAC_DENY = "MMAC_DENIAL:";

    private static final boolean DEBUG_POLICY = false;
    private static final boolean DEBUG_POLICY = true;
    private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false;

    // Signature seinfo values read from policy.
    private static final HashMap<Signature, String> sSigSeinfo =
        new HashMap<Signature, String>();
    // Signature based policy.
    private static final HashMap<Signature, InstallPolicy> SIG_POLICY =
        new HashMap<Signature, InstallPolicy>();

    // Package name seinfo values read from policy.
    private static final HashMap<String, String> sPackageSeinfo =
        new HashMap<String, String>();
    // Package name based policy.
    private static final HashMap<String, InstallPolicy> PKG_POLICY =
        new HashMap<String, InstallPolicy>();

    // Locations of potential install policy files.
    private static final File[] INSTALL_POLICY_FILE = {
@@ -62,8 +68,8 @@ public final class SELinuxMMAC {
        null};

    private static void flushInstallPolicy() {
        sSigSeinfo.clear();
        sPackageSeinfo.clear();
        SIG_POLICY.clear();
        PKG_POLICY.clear();
    }

    /**
@@ -101,11 +107,15 @@ public final class SELinuxMMAC {
        }

        if (policyFile == null) {
            Slog.d(TAG, "No policy file found. All seinfo values will be null.");
            Slog.d(TAG, "MMAC install disabled.");
            return false;
        }

        Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath());
        Slog.d(TAG, "MMAC install enabled using file " + policyFiles[i].getPath());

        boolean enforcing = SystemProperties.getBoolean("persist.mac_enforcing_mode", false);
        String mode = enforcing ? "enforcing" : "permissive";
        Slog.d(TAG, "MMAC install starting in " + mode + " mode.");

        flushInstallPolicy();

@@ -138,22 +148,39 @@ public final class SELinuxMMAC {
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String seinfo = readSeinfoTag(parser);
                    if (seinfo != null) {
                        if (DEBUG_POLICY_INSTALL)
                            Slog.i(TAG, "<signer> tag: (" + cert + ") assigned seinfo="
                                   + seinfo);
                    if (signature == null) {
                        Slog.w(TAG, "<signer> with null signature at "
                               + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    InstallPolicy type = determineInstallPolicyType(parser, true);
                    if (type != null) {
                        if (DEBUG_POLICY_INSTALL) {
                            // Pretty print the cert
                            int rowLength = 75;
                            int certLength = cert.length();
                            int rows = certLength / rowLength;
                            Slog.i(TAG, "<signer> tag:");
                            for (int j = 0; j <= rows; j++) {
                                int start = rowLength * j;
                                int rowEndIndex = (rowLength * j) + rowLength;
                                int end = rowEndIndex < certLength ? rowEndIndex : certLength;
                                Slog.i(TAG,  cert.substring(start, end));
                            }
                            Slog.i(TAG,  "    Assigned: " + type);
                        }

                        sSigSeinfo.put(signature, seinfo);
                        SIG_POLICY.put(signature, type);
                    }
                } else if ("default".equals(tagName)) {
                    String seinfo = readSeinfoTag(parser);
                    if (seinfo != null) {
                    InstallPolicy type = determineInstallPolicyType(parser, true);
                    if (type != null) {
                        if (DEBUG_POLICY_INSTALL)
                            Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo);
                            Slog.i(TAG, "<default> tag assigned " + type);

                        // The 'null' signature is the default seinfo value
                        sSigSeinfo.put(null, seinfo);
                        SIG_POLICY.put(null, type);
                    }
                } else if ("package".equals(tagName)) {
                    String pkgName = parser.getAttributeValue(null, "name");
@@ -163,13 +190,13 @@ public final class SELinuxMMAC {
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    String seinfo = readSeinfoTag(parser);
                    if (seinfo != null) {
                    InstallPolicy type = determineInstallPolicyType(parser, false);
                    if (type != null) {
                        if (DEBUG_POLICY_INSTALL)
                            Slog.i(TAG, "<package> tag: (" + pkgName +
                                   ") assigned seinfo=" + seinfo);
                            Slog.i(TAG, "<package> outer tag: (" + pkgName +
                                   ") assigned " + type);

                        sPackageSeinfo.put(pkgName, seinfo);
                        PKG_POLICY.put(pkgName, type);
                    }
                } else {
                    XmlUtils.skipCurrentTag(parser);
@@ -189,11 +216,18 @@ public final class SELinuxMMAC {
        return true;
    }

    private static String readSeinfoTag(XmlPullParser parser) throws
    private static InstallPolicy determineInstallPolicyType(XmlPullParser parser,
                                                            boolean notInsidePackageTag) throws
            IOException, XmlPullParserException {

        final HashSet<String> denyPolicyPerms  = new HashSet<String>();
        final HashSet<String> allowPolicyPerms = new HashSet<String>();

        final HashMap<String, InstallPolicy> pkgPolicy = new HashMap<String, InstallPolicy>();

        int type;
        int outerDepth = parser.getDepth();
        boolean allowAll = false;
        String seinfo = null;
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
               && (type != XmlPullParser.END_TAG
@@ -212,21 +246,203 @@ public final class SELinuxMMAC {
                    Slog.w(TAG, "<seinfo> without value at "
                           + parser.getPositionDescription());
                }
            } else if ("allow-permission".equals(tagName)) {
                String permName = parser.getAttributeValue(null, "name");
                if (permName != null) {
                    allowPolicyPerms.add(permName);
                } else {
                    Slog.w(TAG, "<allow-permission> without name at "
                           + parser.getPositionDescription());
                }
            } else if ("deny-permission".equals(tagName)) {
                String permName = parser.getAttributeValue(null, "name");
                if (permName != null) {
                    denyPolicyPerms.add(permName);
                } else {
                    Slog.w(TAG, "<deny-permission> without name at "
                           + parser.getPositionDescription());
                }
            } else if ("allow-all".equals(tagName)) {
                allowAll = true;
            } else if ("package".equals(tagName) && notInsidePackageTag) {
                String pkgName = parser.getAttributeValue(null, "name");
                if (pkgName != null) {
                    InstallPolicy policyType = determineInstallPolicyType(parser, false);
                    if (policyType != null) {
                        pkgPolicy.put(pkgName, policyType);
                        if (DEBUG_POLICY_INSTALL) {
                            Slog.i(TAG, "<package> inner tag: (" + pkgName +
                                   ") assigned " + policyType);
                        }
                    }
                    continue;
                } else {
                    Slog.w(TAG, "<package> inner tag without name at " +
                           parser.getPositionDescription());
                }
            }
            XmlUtils.skipCurrentTag(parser);
        }

        // Order is important. Provide the least amount of privilege.
        InstallPolicy permPolicyType = null;
        if (denyPolicyPerms.size() > 0) {
            permPolicyType = new BlackListPolicy(denyPolicyPerms, pkgPolicy, seinfo);
        } else if (allowPolicyPerms.size() > 0) {
            permPolicyType = new WhiteListPolicy(allowPolicyPerms, pkgPolicy, seinfo);
        } else if (allowAll) {
            permPolicyType = new InstallPolicy(null, pkgPolicy, seinfo);
        } else if (!pkgPolicy.isEmpty()) {
            // Consider the case where outside tag has no perms attached
            // but has an inner package stanza. All the above cases assume that
            // the outer stanza has permission tags, but here we want to ensure
            // we capture the inner but deny all outer.
            permPolicyType = new DenyPolicy(null, pkgPolicy, seinfo);
        }

        return permPolicyType;
    }

    static class InstallPolicy {

        final HashSet<String> policyPerms;
        final HashMap<String, InstallPolicy> pkgPolicy;
        final private String seinfo;

        InstallPolicy(HashSet<String> policyPerms, HashMap<String, InstallPolicy> pkgPolicy,
                      String seinfo) {

            this.policyPerms = policyPerms;
            this.pkgPolicy = pkgPolicy;
            this.seinfo = seinfo;
        }

        boolean passedPolicyChecks(PackageParser.Package pkg) {
            // ensure that local package policy takes precedence
            if (pkgPolicy.containsKey(pkg.packageName)) {
                return pkgPolicy.get(pkg.packageName).passedPolicyChecks(pkg);
            }
            return true;
        }

        String getSEinfo(String pkgName) {
            if (pkgPolicy.containsKey(pkgName)) {
                return pkgPolicy.get(pkgName).getSEinfo(pkgName);
            }
            return seinfo;
        }

        public String toString() {
            StringBuilder out = new StringBuilder();
            out.append("[");
            if (policyPerms != null) {
                out.append(TextUtils.join(",\n", new TreeSet<String>(policyPerms)));
            } else {
                out.append("allow-all");
            }
            out.append("]");
            return out.toString();
        }
    }

    static class WhiteListPolicy extends InstallPolicy {

        WhiteListPolicy(HashSet<String> policyPerms, HashMap<String, InstallPolicy> pkgPolicy,
                        String seinfo) {

            super(policyPerms, pkgPolicy, seinfo);
        }

        @Override
        public boolean passedPolicyChecks(PackageParser.Package pkg) {
            // ensure that local package policy takes precedence
            if (pkgPolicy.containsKey(pkg.packageName)) {
                return pkgPolicy.get(pkg.packageName).passedPolicyChecks(pkg);
            }

            Iterator itr = pkg.requestedPermissions.iterator();
            while (itr.hasNext()) {
                String perm = (String)itr.next();
                if (!policyPerms.contains(perm)) {
                    Slog.w(TAG, MMAC_DENY + " Policy whitelist rejected package "
                           + pkg.packageName + ". The rejected permission is " + perm +
                           " The maximal set allowed is: " + toString());
                    return false;
                }
            }
            return true;
        }

        @Override
        public String toString() {
            return "allowed-permissions => \n" + super.toString();
        }
    }

    static class BlackListPolicy extends InstallPolicy {

        BlackListPolicy(HashSet<String> policyPerms, HashMap<String, InstallPolicy> pkgPolicy,
                        String seinfo) {

            super(policyPerms, pkgPolicy, seinfo);
        }

        @Override
        public boolean passedPolicyChecks(PackageParser.Package pkg) {
            // ensure that local package policy takes precedence
            if (pkgPolicy.containsKey(pkg.packageName)) {
                return pkgPolicy.get(pkg.packageName).passedPolicyChecks(pkg);
            }

            Iterator itr = pkg.requestedPermissions.iterator();
            while (itr.hasNext()) {
                String perm = (String)itr.next();
                if (policyPerms.contains(perm)) {
                    Slog.w(TAG, MMAC_DENY + " Policy blacklisted permission " + perm +
                           " for package " + pkg.packageName);
                    return false;
                }
            }
            return true;
        }

        @Override
        public String toString() {
            return "denied-permissions => \n" + super.toString();
        }
    }

    static class DenyPolicy extends InstallPolicy {

        DenyPolicy(HashSet<String> policyPerms, HashMap<String, InstallPolicy> pkgPolicy,
                        String seinfo) {

            super(policyPerms, pkgPolicy, seinfo);
        }

        @Override
        public boolean passedPolicyChecks(PackageParser.Package pkg) {
            // ensure that local package policy takes precedence
            if (pkgPolicy.containsKey(pkg.packageName)) {
                return pkgPolicy.get(pkg.packageName).passedPolicyChecks(pkg);
            }
            return false;
        }

        @Override
        public String toString() {
            return "deny-all";
        }
    }

    /**
     * Labels a package based on an seinfo tag from install policy.
     * The label is attached to the ApplicationInfo instance of the package.
     * Detemines if the package passes policy. If the package does pass
     * policy checks then an seinfo label is also assigned to the package.
     * @param PackageParser.Package object representing the package
     *         to labeled.
     * @return String holding the value of the seinfo label that was assigned.
     *         Value may be null which indicates no seinfo label was assigned.
     *         to installed and labeled.
     * @return boolean Indicates whether the package passed policy.
     */
    public static void assignSeinfoValue(PackageParser.Package pkg) {
    public static boolean passInstallPolicyChecks(PackageParser.Package pkg) {

        // We just want one of the signatures to match.
        for (Signature s : pkg.mSignatures) {
@@ -234,30 +450,48 @@ public final class SELinuxMMAC {
                continue;
            }

            if (sSigSeinfo.containsKey(s)) {
                String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s);
            // Check for a non default signature policy.
            if (SIG_POLICY.containsKey(s)) {
                InstallPolicy policy = SIG_POLICY.get(s);
                if (policy.passedPolicyChecks(pkg)) {
                    String seinfo = pkg.applicationInfo.seinfo = policy.getSEinfo(pkg.packageName);
                    if (DEBUG_POLICY_INSTALL)
                    Slog.i(TAG, "package (" + pkg.packageName +
                           ") labeled with seinfo=" + seinfo);

                return;
                        Slog.i(TAG, "package (" + pkg.packageName + ") installed with " +
                               " seinfo=" + (seinfo == null ? "null" : seinfo));
                    return true;
                }
            }
        }

        // Check for seinfo labeled by package.
        if (sPackageSeinfo.containsKey(pkg.packageName)) {
            String seinfo = pkg.applicationInfo.seinfo = sPackageSeinfo.get(pkg.packageName);
        // Check for a global per-package policy.
        if (PKG_POLICY.containsKey(pkg.packageName)) {
            boolean passed = false;
            InstallPolicy policy = PKG_POLICY.get(pkg.packageName);
            if (policy.passedPolicyChecks(pkg)) {
                String seinfo = pkg.applicationInfo.seinfo = policy.getSEinfo(pkg.packageName);
                if (DEBUG_POLICY_INSTALL)
                Slog.i(TAG, "package (" + pkg.packageName +
                       ") labeled with seinfo=" + seinfo);
            return;
                    Slog.i(TAG, "package (" + pkg.packageName + ") installed with " +
                           " seinfo=" + (seinfo == null ? "null" : seinfo));
                passed = true;
            }
            return passed;
        }

        // If we have a default seinfo value then great, otherwise
        // we set a null object and that is what we started with.
        String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null);
        // Check for a default policy.
        if (SIG_POLICY.containsKey(null)) {
            boolean passed = false;
            InstallPolicy policy = SIG_POLICY.get(null);
            if (policy.passedPolicyChecks(pkg)) {
                String seinfo = pkg.applicationInfo.seinfo = policy.getSEinfo(pkg.packageName);
                if (DEBUG_POLICY_INSTALL)
            Slog.i(TAG, "package (" + pkg.packageName +
                   ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo));
                    Slog.i(TAG, "package (" + pkg.packageName + ") installed with " +
                           " seinfo=" + (seinfo == null ? "null" : seinfo));
                passed = true;
            }
            return passed;
        }

        // If we get here it's because this package had no policy.
        return false;
    }
}
+10 −0
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_PACKAGE_NAME := signed_media

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_CERTIFICATE := media

include $(FrameworkCoreTests_BUILD_PACKAGE)
+27 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.frameworks.coretests.mmac_install_media">

    <uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />

    <application android:hasCode="false">
    </application>


</manifest>
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.frameworks.coretests;

public class DoNothing {

}
 No newline at end of file
Loading