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

Commit 0033c65a authored by Jackal Guo's avatar Jackal Guo
Browse files

Add enforcement for duplicate permissions

Declaring duplicate permissions with different protection levels is
not allowed. Add the scheme enforcement for manifest during parsing.

Bug: 211934395
Test: atest AppSecurityTests
Change-Id: Ieb006ab4abf19baf949e9b5bfd3e3fea16237527
parent d1ab4a85
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED;
@@ -934,6 +935,13 @@ public class ParsingPackageUtils {
            );
        }

        if (ParsedPermissionUtils.declareDuplicatePermission(pkg)) {
            return input.error(
                    INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "Declare duplicate permissions with different protection levels."
            );
        }

        convertCompatPermissions(pkg);

        convertSplitPermissions(pkg);
+27 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.internal.R;
@@ -34,6 +35,7 @@ import com.android.internal.R;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.List;

/** @hide */
public class ParsedPermissionUtils {
@@ -271,4 +273,29 @@ public class ParsedPermissionUtils {
        }
        return size;
    }

    /**
     * @return {@code true} if the package declares duplicate permissions with different
     * protection levels.
     */
    public static boolean declareDuplicatePermission(@NonNull ParsingPackage pkg) {
        final List<ParsedPermission> permissions = pkg.getPermissions();
        final int size = permissions.size();
        if (size > 0) {
            final ArrayMap<String, ParsedPermission> checkDuplicatePerm = new ArrayMap<>(size);
            for (int i = 0; i < size; i++) {
                final ParsedPermission parsedPermission = permissions.get(i);
                final String name = parsedPermission.getName();
                final ParsedPermission perm = checkDuplicatePerm.get(name);
                // Since a permission tree is also added as a permission with normal protection
                // level, we need to skip if the parsedPermission is a permission tree.
                if (perm != null && !(perm.isTree() || parsedPermission.isTree())
                        && perm.getProtectionLevel() != parsedPermission.getProtectionLevel()) {
                    return true;
                }
                checkDuplicatePerm.put(name, parsedPermission);
            }
        }
        return false;
    }
}