Skip to content

Commit ee38e8b

Browse files
Manjeet Rulhaniaofficialputuid
authored andcommitted
Fix duplicate permission privilege escalation
Duplicate permissions definition with different group allows privilege permission escalation to a different permission group. Android studio and gradle plugin does not allow duplicate permissions with different attributes, these tools only allow if duplicate permissions are exact copies. Also platform stores permissions in map at multiple places with permission name as key. This suggests that we can disallow duplicate permissions during package install/update Bug: 213323615 Test: AppSecurityTests Change-Id: I1910dca44104e35a57eba4acfa8188cd9b8626ac Merged-Id: I34120fff2ec2a158dfa55779d2afd4bbd49487ff Merged-In: I9bc839836786a0876e67fd73c05f8944bb532249 (cherry picked from commit f9a9dc7) Merged-In: I1910dca44104e35a57eba4acfa8188cd9b8626ac
1 parent cbee4d9 commit ee38e8b

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

core/java/android/content/pm/parsing/ParsingPackageUtils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static android.content.pm.PackageManager.FEATURE_WATCH;
2222
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
2323
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
24+
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2425
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED;
2526
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED;
2627
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
@@ -778,6 +779,13 @@ private ParseResult<ParsingPackage> parseBaseApkTags(ParseInput input, ParsingPa
778779
);
779780
}
780781

782+
if (ParsedPermissionUtils.declareDuplicatePermission(pkg)) {
783+
return input.error(
784+
INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
785+
"Found duplicate permission with a different attribute value."
786+
);
787+
}
788+
781789
convertNewPermissions(pkg);
782790

783791
convertSplitPermissions(pkg);

core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import android.content.res.Resources;
2323
import android.content.res.TypedArray;
2424
import android.content.res.XmlResourceParser;
25+
import android.util.ArrayMap;
26+
import android.util.EventLog;
2527
import android.util.Slog;
2628

2729
import com.android.internal.R;
@@ -32,6 +34,8 @@
3234
import org.xmlpull.v1.XmlPullParserException;
3335

3436
import java.io.IOException;
37+
import java.util.List;
38+
import java.util.Objects;
3539

3640
/** @hide */
3741
public class ParsedPermissionUtils {
@@ -207,4 +211,49 @@ public static ParseResult<ParsedPermissionGroup> parsePermissionGroup(ParsingPac
207211
return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permissionGroup,
208212
input);
209213
}
214+
215+
/**
216+
* Determines if a duplicate permission is malformed .i.e. defines different protection level
217+
* or group.
218+
*/
219+
private static boolean isMalformedDuplicate(ParsedPermission p1, ParsedPermission p2) {
220+
// Since a permission tree is also added as a permission with normal protection
221+
// level, we need to skip if the parsedPermission is a permission tree.
222+
if (p1 == null || p2 == null || p1.isTree() || p2.isTree()) {
223+
return false;
224+
}
225+
226+
if (p1.getProtectionLevel() != p2.getProtectionLevel()) {
227+
return true;
228+
}
229+
if (!Objects.equals(p1.getGroup(), p2.getGroup())) {
230+
return true;
231+
}
232+
233+
return false;
234+
}
235+
236+
/**
237+
* @return {@code true} if the package declares malformed duplicate permissions.
238+
*/
239+
public static boolean declareDuplicatePermission(@NonNull ParsingPackage pkg) {
240+
final List<ParsedPermission> permissions = pkg.getPermissions();
241+
final int size = permissions.size();
242+
if (size > 0) {
243+
final ArrayMap<String, ParsedPermission> checkDuplicatePerm = new ArrayMap<>(size);
244+
for (int i = 0; i < size; i++) {
245+
final ParsedPermission parsedPermission = permissions.get(i);
246+
final String name = parsedPermission.getName();
247+
final ParsedPermission perm = checkDuplicatePerm.get(name);
248+
if (isMalformedDuplicate(parsedPermission, perm)) {
249+
// Fix for b/213323615
250+
EventLog.writeEvent(0x534e4554, "213323615",
251+
"The package " + pkg.getPackageName() + " seems malicious");
252+
return true;
253+
}
254+
checkDuplicatePerm.put(name, parsedPermission);
255+
}
256+
}
257+
return false;
258+
}
210259
}

0 commit comments

Comments
 (0)