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
This commit is contained in:
Jackal Guo
2021-12-22 09:46:15 +08:00
parent d1ab4a85eb
commit 0033c65aa9
2 changed files with 35 additions and 0 deletions

View File

@@ -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);

View File

@@ -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;
}
}