Add cfi static libraries to vendor snapshot

CFI modules can't link against non-CFI static libraries, and vice versa.
So without capturing both CFI and non-CFI static libraries, vendor
modules won't be able to use CFI, which will be a critical security
hole.

This captures both CFI and non-CFI variants of all static libraries for
vendor snapshot, except for those whose cfi are explicitly disabled.

For example, suppose that "libfoo" is defined as follows.

cc_library_static {
    name: "libfoo",
    vendor_available: true,
}

As it doesn't have cfi disabled, two libraries "libfoo.a" and
"libfoo.cfi.a" will be captured. When installed, vendor snapshot module
for "libfoo" will look like:

vendor_snapshot_static {
    name: "libfoo",
    src: "libfoo.a",
    cfi: {
        src: "libfoo.cfi.a",
    },
}

The build system will recognize the "cfi" property, and will create both
CFI and non-CFI variant, allowing any modules to link against "libfoo"
safely, no matter whether CFI is enabled or not.

Two clarification:

1) The reason why we don't create separate modules is that DepsMutator
runs before sanitize mutators. CFI and non-CFI variant of a library
should exist in a single module.

2) We can't capture CFI variant if the source module explicitly disables
cfi variant by specifying the following.

sanitize: {
    cfi: false,
}

In this case, only non-CFI variant will be created for the vendor
snapshot module.

Bug: 65377115
Test: m dist vendor-snapshot && install && build against snapshot
Change-Id: Idbf3e3205d581800d6093c8d6cf6152374129ba4
This commit is contained in:
Inseob Kim
2020-07-29 20:32:10 +09:00
committed by Bill Peckham
parent 2d34ad94f9
commit c42f2f2e9d
5 changed files with 206 additions and 45 deletions

View File

@@ -1013,17 +1013,25 @@ func TestVendorSnapshot(t *testing.T) {
filepath.Join(sharedDir, "libvendor_available.so.json"))
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
// Also cfi variants are captured, except for prebuilts like toolchain_library
staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
staticCfiVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static_cfi", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
jsonFiles = append(jsonFiles,
filepath.Join(staticDir, "libb.a.json"),
filepath.Join(staticDir, "libvndk.a.json"),
filepath.Join(staticDir, "libvndk.cfi.a.json"),
filepath.Join(staticDir, "libvendor.a.json"),
filepath.Join(staticDir, "libvendor_available.a.json"))
filepath.Join(staticDir, "libvendor.cfi.a.json"),
filepath.Join(staticDir, "libvendor_available.a.json"),
filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
// For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
@@ -1055,6 +1063,39 @@ func TestVendorSnapshot(t *testing.T) {
}
}
func TestVendorSnapshotSanitizer(t *testing.T) {
bp := `
vendor_snapshot_static {
name: "libsnapshot",
vendor: true,
target_arch: "arm64",
version: "BOARD",
arch: {
arm64: {
src: "libsnapshot.a",
cfi: {
src: "libsnapshot.cfi.a",
}
},
},
}
`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
// Check non-cfi and cfi variant.
staticVariant := "android_vendor.BOARD_arm64_armv8-a_static"
staticCfiVariant := "android_vendor.BOARD_arm64_armv8-a_static_cfi"
staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticVariant).Module().(*Module)
assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticCfiVariant).Module().(*Module)
assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
}
func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `