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

Commit a2163dc8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add preinstalled partition to seinfo" into udc-dev-plus-aosp

parents 212b8814 d2f1a649
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;
        }
    }
}