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

Commit 361db6eb authored by Inseob Kim's avatar Inseob Kim Committed by Android (Google) Code Review
Browse files

Merge "Add preinstalled partition to seinfo"

parents d59cde4e 8bbec9ac
Loading
Loading
Loading
Loading
+35 −9
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ public final class SELinuxMMAC {
    // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
    private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";

    private static final String PARTITION_STR = ":partition=";

    /**
     * Allows opt-in to the latest targetSdkVersion enforced changes without changing target SDK.
     * Turning this change on for an app targeting the latest SDK or higher is a no-op.
@@ -373,13 +375,31 @@ public final class SELinuxMMAC {
        return pkg.getTargetSdkVersion();
    }

    private static String getPartition(PackageState state) {
        if (state.isSystemExt()) {
            return "system_ext";
        } else if (state.isProduct()) {
            return "product";
        } else if (state.isVendor()) {
            return "vendor";
        } else if (state.isOem()) {
            return "oem";
        } else if (state.isOdm()) {
            return "odm";
        } else if (state.isSystem()) {
            return "system";
        }
        return "";
    }

    /**
     * Selects a security label to a package based on input parameters and the seinfo tag taken
     * from a matched policy. All signature based policy stanzas are consulted and, if no match
     * is found, the default seinfo label of 'default' is used. The security label is attached to
     * the ApplicationInfo instance of the package.
     *
     * @param pkg               object representing the package to be labeled.
     * @param packageState  {@link PackageState} object representing the package to be labeled.
     * @param pkg           {@link AndroidPackage} object representing the package to be labeled.
     * @param sharedUser    if the app shares a sharedUserId, then this has the shared setting.
     * @param compatibility the PlatformCompat service to ask about state of compat changes.
     * @return String representing the resulting seinfo.
@@ -393,7 +413,7 @@ public final class SELinuxMMAC {
        final boolean isPrivileged =
                (sharedUser != null) ? sharedUser.isPrivileged() | packageState.isPrivileged()
                        : packageState.isPrivileged();
        return getSeInfo(pkg, isPrivileged, targetSdkVersion);
        return getSeInfo(packageState, pkg, isPrivileged, targetSdkVersion);
    }

    /**
@@ -402,15 +422,16 @@ public final class SELinuxMMAC {
     * is found, the default seinfo label of 'default' is used. The security label is attached to
     * the ApplicationInfo instance of the package.
     *
     * @param pkg object representing the package to be labeled.
     * @param packageState     {@link PackageState} object representing the package to be labeled.
     * @param pkg              {@link AndroidPackage} object representing the package to be labeled.
     * @param isPrivileged     boolean.
     * @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the
     *        greater of: lowest targetSdk for all pkgs in the sharedUser, or
     *        MINIMUM_TARGETSDKVERSION.
     * @return String representing the resulting seinfo.
     */
    public static String getSeInfo(AndroidPackage pkg, boolean isPrivileged,
            int targetSdkVersion) {
    public static String getSeInfo(PackageState packageState, AndroidPackage pkg,
            boolean isPrivileged, int targetSdkVersion) {
        String seInfo = null;
        synchronized (sPolicies) {
            if (!sPolicyRead) {
@@ -437,8 +458,13 @@ public final class SELinuxMMAC {

        seInfo += TARGETSDKVERSION_STR + targetSdkVersion;

        String partition = getPartition(packageState);
        if (!partition.isEmpty()) {
            seInfo += PARTITION_STR + partition;
        }

        if (DEBUG_POLICY_INSTALL) {
            Slog.i(TAG, "package (" + pkg.getPackageName() + ") labeled with "
            Slog.i(TAG, "package (" + packageState.getPackageName() + ") labeled with "
                    + "seinfo=" + seInfo);
        }
        return seInfo;
+1 −1
Original line number Diff line number Diff line
@@ -285,7 +285,7 @@ public final class SharedUserSetting extends SettingBase implements SharedUserAp
                continue;
            }
            final boolean isPrivileged = isPrivileged() | ps.isPrivileged();
            ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps.getPkg(), isPrivileged,
            ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps, ps.getPkg(), isPrivileged,
                    seInfoTargetSdkVersion));
            onChanged();
        }
+118 −17
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.pm;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.StringContains.containsString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@@ -53,7 +55,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoOptInToLatest() {
        var packageState = makePackageState(Build.VERSION_CODES.P);
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.P).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
@@ -64,7 +66,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoOptInToR() {
        var packageState = makePackageState(Build.VERSION_CODES.P);
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.P).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
@@ -75,7 +77,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoNoOptIn() {
        var packageState = makePackageState(Build.VERSION_CODES.P);
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.P).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(false);
@@ -86,7 +88,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoNoOptInButAlreadyLatest() {
        var packageState = makePackageState(LATEST_OPT_IN_VERSION);
        var packageState = new PackageStateBuilder(LATEST_OPT_IN_VERSION).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(false);
@@ -97,7 +99,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoTargetingCurDevelopment() {
        var packageState = makePackageState(Build.VERSION_CODES.CUR_DEVELOPMENT);
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
@@ -108,7 +110,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoNoOptInButAlreadyR() {
        var packageState = makePackageState(R_OPT_IN_VERSION);
        var packageState = new PackageStateBuilder(R_OPT_IN_VERSION).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(false);
@@ -119,7 +121,7 @@ public class SELinuxMMACTest {

    @Test
    public void getSeInfoOptInRButLater() {
        var packageState = makePackageState(R_OPT_IN_VERSION + 1);
        var packageState = new PackageStateBuilder(R_OPT_IN_VERSION + 1).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
@@ -128,15 +130,114 @@ public class SELinuxMMACTest {
                is("default:targetSdkVersion=" + (R_OPT_IN_VERSION + 1)));
    }

    private PackageState makePackageState(int targetSdkVersion) {
    @Test
    public void getSeInfoPreinstalledToSystem() {
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT)
                .setSystem(true).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
        assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
                        mMockCompatibility),
                containsString(":partition=system"));
    }


    @Test
    public void getSeInfoPreinstalledToSystemExt() {
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT)
                .setSystem(true).setSystemExt(true).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
        assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
                        mMockCompatibility),
                containsString(":partition=system_ext"));
    }


    @Test
    public void getSeInfoPreinstalledToProduct() {
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT)
                .setSystem(true).setProduct(true).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
        assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
                        mMockCompatibility),
                containsString(":partition=product"));
    }


    @Test
    public void getSeInfoPreinstalledToVendor() {
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT)
                .setSystem(true).setVendor(true).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
        assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
                        mMockCompatibility),
                containsString(":partition=vendor"));
    }


    @Test
    public void getSeInfoNotPreinstalled() {
        var packageState = new PackageStateBuilder(Build.VERSION_CODES.CUR_DEVELOPMENT).build();
        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
                .thenReturn(true);
        assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
                        mMockCompatibility),
                not(containsString(":partition=")));
    }

    private static class PackageStateBuilder {
        private final int mTargetSdkVersion;
        private boolean mIsSystem = false;
        private boolean mIsSystemExt = false;
        private boolean mIsProduct = false;
        private boolean mIsVendor = false;

        PackageStateBuilder(int targetSdkVersion) {
            mTargetSdkVersion = targetSdkVersion;
        }

        PackageStateBuilder setSystem(boolean isSystem) {
            mIsSystem = isSystem;
            return this;
        }

        PackageStateBuilder setSystemExt(boolean isSystemExt) {
            mIsSystemExt = isSystemExt;
            return this;
        }

        PackageStateBuilder setProduct(boolean isProduct) {
            mIsProduct = isProduct;
            return this;
        }

        PackageStateBuilder setVendor(boolean isVendor) {
            mIsVendor = isVendor;
            return this;
        }

        PackageState build() {
            var packageState = Mockito.mock(PackageState.class);
            when(packageState.getPackageName()).thenReturn(PACKAGE_NAME);
            when(packageState.getAndroidPackage()).thenReturn(
                    ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                        .setTargetSdkVersion(targetSdkVersion)
                            .setTargetSdkVersion(mTargetSdkVersion)
                            .hideAsParsed())
                            .hideAsFinal()
            );
            when(packageState.isSystem()).thenReturn(mIsSystem);
            when(packageState.isSystemExt()).thenReturn(mIsSystemExt);
            when(packageState.isProduct()).thenReturn(mIsProduct);
            when(packageState.isVendor()).thenReturn(mIsVendor);
            return packageState;
        }
    }
}