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

Commit 6158528e authored by Cole Faust's avatar Cole Faust
Browse files

Only allow setting presigned without preprocessed on targetSdk < 30

When targetSdk is >= 30, the system verifies that you use a valid
signature V2+ certificate. Uncompressing ndk/dex files or aligning
the zip file will break a signature V2, so these apks should really
just set preprocessed: true.

Fixes: 185811447
Test: Presubmits
Change-Id: Id89c42bcd5b5daa6eda1716bff4023423298036b
parent 4e6c42d4
Loading
Loading
Loading
Loading
+26 −4
Original line number Diff line number Diff line
@@ -277,6 +277,14 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
		a.hideApexVariantFromMake = true
	}

	if Bool(a.properties.Preprocessed) {
		if a.properties.Presigned != nil && !*a.properties.Presigned {
			ctx.ModuleErrorf("Setting preprocessed: true implies presigned: true, so you cannot set presigned to false")
		}
		t := true
		a.properties.Presigned = &t
	}

	numCertPropsSet := 0
	if String(a.properties.Certificate) != "" {
		numCertPropsSet++
@@ -288,11 +296,9 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
		numCertPropsSet++
	}
	if numCertPropsSet != 1 {
		ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
		ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set")
	}

	_, _, certificates := collectAppDeps(ctx, a, false, false)

	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
	// TODO: LOCAL_PACKAGE_SPLITS

@@ -365,6 +371,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
	} else if !Bool(a.properties.Presigned) {
		// If the certificate property is empty at this point, default_dev_cert must be set to true.
		// Which makes processMainCert's behavior for the empty cert string WAI.
		_, _, certificates := collectAppDeps(ctx, a, false, false)
		a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
		signed := android.PathForModuleOut(ctx, "signed", apkFilename)
		var lineageFile android.Path
@@ -377,8 +384,13 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
		SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile, rotationMinSdkVersion)
		a.outputFile = signed
	} else {
		// Presigned without Preprocessed shouldn't really be a thing, currently we disallow
		// it for apps with targetSdk >= 30, because on those targetSdks you must be using signature
		// v2 or later, and signature v2 would be wrecked by uncompressing libs / zipaligning.
		// But ideally we would disallow it for all prebuilt apks, and remove the presigned property.
		targetSdkCheck := a.validateTargetSdkLessThan30(ctx, srcApk)
		alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
		TransformZipAlign(ctx, alignedApk, jnisUncompressed)
		TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{targetSdkCheck})
		a.outputFile = alignedApk
		a.certificate = PresignedCertificate
	}
@@ -432,6 +444,16 @@ func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, sr
	})
}

func (a *AndroidAppImport) validateTargetSdkLessThan30(ctx android.ModuleContext, srcApk android.Path) android.Path {
	alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "old_target_sdk.stamp")
	ctx.Build(pctx, android.BuildParams{
		Rule:   checkBelowTargetSdk30ForNonPreprocessedApks,
		Input:  srcApk,
		Output: alignmentStamp,
	})
	return alignmentStamp
}

func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
	return &a.prebuilt
}
+12 −22
Original line number Diff line number Diff line
@@ -629,19 +629,10 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) {
			presigned: true,
			preprocessed: true,
		}

		android_test_import {
			name: "foo_cert",
			apk: "prebuilts/apk/app.apk",
			certificate: "cert/new_cert",
			preprocessed: true,
		}
		`)

	testModules := []string{"foo", "foo_cert"}
	for _, m := range testModules {
		apkName := m + ".apk"
		variant := ctx.ModuleForTests(m, "android_common")
	apkName := "foo.apk"
	variant := ctx.ModuleForTests("foo", "android_common")
	jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
	if jniRule != android.Cp.String() {
		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
@@ -655,7 +646,6 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) {
		t.Errorf("aligning rule shouldn't be for preprocessed")
	}
}
}

func TestAndroidAppImport_Preprocessed(t *testing.T) {
	ctx, _ := testJava(t, `
+1 −1
Original line number Diff line number Diff line
@@ -1608,7 +1608,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
					false, nil, nil)
				if *j.dexProperties.Uncompress_dex {
					combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
					TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
					TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
					dexOutputFile = combinedAlignedJar
				} else {
					dexOutputFile = combinedJar
+10 −1
Original line number Diff line number Diff line
@@ -277,6 +277,14 @@ var (
			Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
			CommandDeps: []string{"${config.Zip2ZipCmd}"},
		})

	checkBelowTargetSdk30ForNonPreprocessedApks = pctx.AndroidStaticRule("checkBelowTargetSdk30ForNonPreprocessedApks",
		blueprint.RuleParams{
			Command:     "build/soong/scripts/check_target_sdk_less_than_30.py ${config.Aapt2Cmd} $in $out",
			CommandDeps: []string{"build/soong/scripts/check_target_sdk_less_than_30.py", "${config.Aapt2Cmd}"},
			Description: "Check prebuilt target sdk version",
		},
	)
)

func init() {
@@ -689,12 +697,13 @@ func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.Wri
	android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
}

func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {
func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path, validations android.Paths) {
	ctx.Build(pctx, android.BuildParams{
		Rule:        zipalign,
		Description: "align",
		Input:       inputFile,
		Output:      outputFile,
		Validations: validations,
	})
}

+1 −1
Original line number Diff line number Diff line
@@ -438,7 +438,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
	}
	if proptools.Bool(d.dexProperties.Uncompress_dex) {
		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
		TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
		TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
		javalibJar = alignedJavalibJar
	}

Loading