Merge "Merge "Solve AppBackupUtils.signaturesMatch() policies" into oc-mr1-dev am: a743c01d00" into oc-mr1-dev-plus-aosp

This commit is contained in:
Android Build Merger (Role)
2017-08-22 19:38:09 +00:00
committed by Android (Google) Code Review
3 changed files with 120 additions and 181 deletions

View File

@@ -119,6 +119,7 @@ import android.util.StringBuilderPrinter;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
@@ -8416,7 +8417,19 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// ----- Restore handling -----
// Old style: directly match the stored vs on device signature blocks
/**
* Returns whether the signatures stored {@param storedSigs}, coming from the source apk, match
* the signatures of the apk installed on the device, the target apk. If the target resides in
* the system partition we return true. Otherwise it's considered a match if both conditions
* hold:
*
* <ul>
* <li>Source and target have at least one signature each
* <li>Target contains all signatures in source
* </ul>
*
* Note that if {@param target} is null we return false.
*/
static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
@@ -8428,26 +8441,24 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// partition will be signed with the device's platform certificate, so on
// different phones the same system app will have different signatures.)
if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (MORE_DEBUG) Slog.v(TAG, "System app " + target.packageName + " - skipping sig check");
if (MORE_DEBUG) {
Slog.v(TAG, "System app " + target.packageName + " - skipping sig check");
}
return true;
}
// Allow unsigned apps, but not signed on one device and unsigned on the other
// !!! TODO: is this the right policy?
Signature[] deviceSigs = target.signatures;
if (MORE_DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs
+ " device=" + deviceSigs);
if ((storedSigs == null || storedSigs.length == 0)
&& (deviceSigs == null || deviceSigs.length == 0)) {
return true;
if (MORE_DEBUG) {
Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs);
}
if (storedSigs == null || deviceSigs == null) {
// Don't allow unsigned apps on either end
if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) {
return false;
}
// !!! TODO: this demands that every stored signature match one
// that is present on device, and does not demand the converse.
// Is this this right policy?
// Signatures can be added over time, so the target-device apk needs to contain all the
// source-device apk signatures, but not necessarily the other way around.
int nStored = storedSigs.length;
int nDevice = deviceSigs.length;

View File

@@ -26,6 +26,8 @@ import android.content.pm.Signature;
import android.os.Process;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
/**
* Utility methods wrapping operations on ApplicationInfo and PackageInfo.
*/
@@ -91,9 +93,18 @@ public class AppBackupUtils {
}
/**
* Old style: directly match the stored vs on device signature blocks.
* Returns whether the signatures stored {@param storedSigs}, coming from the source apk, match
* the signatures of the apk installed on the device, the target apk. If the target resides in
* the system partition we return true. Otherwise it's considered a match if both conditions
* hold:
*
* <ul>
* <li>Source and target have at least one signature each
* <li>Target contains all signatures in source
* </ul>
*
* Note that if {@param target} is null we return false.
*/
// TODO(b/37977154): Resolve questionable policies.
public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
@@ -111,24 +122,18 @@ public class AppBackupUtils {
return true;
}
// Allow unsigned apps, but not signed on one device and unsigned on the other
// TODO(b/37977154): is this the right policy?
Signature[] deviceSigs = target.signatures;
if (MORE_DEBUG) {
Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs);
}
if ((storedSigs == null || storedSigs.length == 0)
&& (deviceSigs == null || deviceSigs.length == 0)) {
return true;
}
// TODO(b/37977154): This allows empty stored signature, is this right?
if (storedSigs == null || deviceSigs == null) {
// Don't allow unsigned apps on either end
if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) {
return false;
}
// TODO(b/37977154): this demands that every stored signature match one
// that is present on device, and does not demand the converse.
// Is this this right policy?
// Signatures can be added over time, so the target-device apk needs to contain all the
// source-device apk signatures, but not necessarily the other way around.
int nStored = storedSigs.length;
int nDevice = deviceSigs.length;

View File

@@ -31,8 +31,6 @@ import com.android.server.backup.RefactoredBackupManagerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Random;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -40,7 +38,10 @@ public class AppBackupUtilsTest {
private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent";
private static final String TEST_PACKAGE_NAME = "test_package";
private final Random mRandom = new Random(1000000009);
private static final Signature SIGNATURE_1 = generateSignature((byte) 1);
private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
@Test
public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception {
@@ -220,7 +221,7 @@ public class AppBackupUtilsTest {
@Test
public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], null);
boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null);
assertThat(result).isFalse();
}
@@ -237,61 +238,10 @@ public class AppBackupUtilsTest {
}
@Test
public void signaturesMatch_allowsUnsignedApps_bothSignaturesNull_returnsTrue()
public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
assertThat(result).isTrue();
}
@Test
public void signaturesMatch_allowsUnsignedApps_bothSignaturesEmpty_returnsTrue()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isTrue();
}
@Test
public void
signaturesMatch_allowsUnsignedApps_storedSignatureNullTargetSignatureEmpty_returnsTrue()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
assertThat(result).isTrue();
}
@Test
public void
signaturesMatch_allowsUnsignedApps_storedSignatureEmptyTargetSignatureNull_returnsTrue()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isTrue();
}
@Test
public void
signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_storedSignatureIsNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{generateRandomSignature()};
packageInfo.signatures = new Signature[] {SIGNATURE_1};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
@@ -300,37 +250,78 @@ public class AppBackupUtilsTest {
}
@Test
public void
signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_targetSignatureIsNull_returnsFalse()
public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = null;
packageInfo.signatures = new Signature[] {SIGNATURE_1};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[]{generateRandomSignature()},
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isFalse();
}
@Test
public void
signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_signaturesMatch_returnsTrue() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
public void
signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
Signature signature1Copy = new Signature(signature1.toByteArray());
Signature signature2Copy = new Signature(signature2.toByteArray());
Signature signature3Copy = new Signature(signature3.toByteArray());
assertThat(signature1Copy).isEqualTo(signature1);
assertThat(signature2Copy).isEqualTo(signature2);
assertThat(signature3Copy).isEqualTo(signature3);
boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_equalSignatures_returnsTrue() throws Exception {
Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
Signature signature3Copy = new Signature(SIGNATURE_3.toByteArray());
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
@@ -341,20 +332,11 @@ public class AppBackupUtilsTest {
@Test
public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
Signature signature1Copy = new Signature(signature1.toByteArray());
Signature signature2Copy = new Signature(signature2.toByteArray());
assertThat(signature1Copy).isEqualTo(signature1);
assertThat(signature2Copy).isEqualTo(signature2);
Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
@@ -365,96 +347,37 @@ public class AppBackupUtilsTest {
@Test
public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
Signature signature1Copy = new Signature(signature1.toByteArray());
Signature signature2Copy = new Signature(signature2.toByteArray());
assertThat(signature1Copy).isEqualTo(signature1);
assertThat(signature2Copy).isEqualTo(signature2);
Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{signature1Copy, signature2Copy};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
new Signature[]{signature1, signature2, signature3}, packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_emptyStoredSignatures_returnsTrue() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isTrue();
}
@Test
public void signaturesMatch_emptyTargetSignatures_returnsFalse() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
new Signature[]{signature1, signature2, signature3}, packageInfo);
new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo);
assertThat(result).isFalse();
}
@Test
public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception {
Signature signature1 = generateRandomSignature();
Signature signature2 = generateRandomSignature();
Signature signature3 = generateRandomSignature();
Signature signature4 = generateRandomSignature();
assertThat(signature1).isNotEqualTo(signature2);
assertThat(signature2).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature3);
assertThat(signature1).isNotEqualTo(signature4);
assertThat(signature2).isNotEqualTo(signature4);
assertThat(signature3).isNotEqualTo(signature4);
Signature signature1Copy = new Signature(signature1.toByteArray());
Signature signature2Copy = new Signature(signature2.toByteArray());
assertThat(signature1Copy).isEqualTo(signature1);
assertThat(signature2Copy).isEqualTo(signature2);
Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
packageInfo.signatures = new Signature[]{signature1, signature2, signature3};
packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
new Signature[]{signature1Copy, signature2Copy, signature4}, packageInfo);
new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo);
assertThat(result).isFalse();
}
private Signature generateRandomSignature() {
private static Signature generateSignature(byte i) {
byte[] signatureBytes = new byte[256];
mRandom.nextBytes(signatureBytes);
signatureBytes[0] = i;
return new Signature(signatureBytes);
}
}