diff --git a/android/container.go b/android/container.go index 05897dd6c..1a8041872 100644 --- a/android/container.go +++ b/android/container.go @@ -43,16 +43,86 @@ var depIsStubsModule exceptionHandleFunc = func(_ ModuleContext, _, dep Module) return false } +// Returns true if the dependency module belongs to any of the apexes. +var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _, dep Module) bool { + depContainersInfo, _ := getContainerModuleInfo(mctx, dep) + return InList(ApexContainer, depContainersInfo.belongingContainers) +} + +// Returns true if the module and the dependent module belongs to common apexes. +var belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m, dep Module) bool { + mContainersInfo, _ := getContainerModuleInfo(mctx, m) + depContainersInfo, _ := getContainerModuleInfo(mctx, dep) + + return HasIntersection(mContainersInfo.ApexNames(), depContainersInfo.ApexNames()) +} + +// Returns true when all apexes that the module belongs to are non updatable. +// For an apex module to be allowed to depend on a non-apex partition module, +// all apexes that the module belong to must be non updatable. +var belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m, _ Module) bool { + mContainersInfo, _ := getContainerModuleInfo(mctx, m) + + return !mContainersInfo.UpdatableApex() +} + +// Returns true if the dependency is added via dependency tags that are not used to tag dynamic +// dependency tags. +var depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool { + mInstallable, _ := m.(InstallableModule) + depTag := ctx.OtherModuleDependencyTag(dep) + return !InList(depTag, mInstallable.DynamicDependencyTags()) +} + +// Returns true if the dependency is added via dependency tags that are not used to tag static +// or dynamic dependency tags. These dependencies do not affect the module in compile time or in +// runtime, thus are not significant enough to raise an error. +var depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool { + mInstallable, _ := m.(InstallableModule) + depTag := ctx.OtherModuleDependencyTag(dep) + return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...)) +} + +var globallyAllowlistedDependencies = []string{ + // Modules that provide annotations used within the platform and apexes. + "aconfig-annotations-lib", + "framework-annotations-lib", + "unsupportedappusage", + + // framework-res provides core resources essential for building apps and system UI. + // This module is implicitly added as a dependency for java modules even when the + // dependency specifies sdk_version. + "framework-res", +} + +// Returns true when the dependency is globally allowlisted for inter-container dependency +var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool { + return InList(dep.Name(), globallyAllowlistedDependencies) +} + // Labels of exception functions, which are used to determine special dependencies that allow // otherwise restricted inter-container dependencies type exceptionHandleFuncLabel int const ( checkStubs exceptionHandleFuncLabel = iota + checkApexModule + checkInCommonApexes + checkApexIsNonUpdatable + checkNotDynamicDepTag + checkNotStaticOrDynamicDepTag + checkGlobalAllowlistedDep ) +// Map of [exceptionHandleFuncLabel] to the [exceptionHandleFunc] var exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]exceptionHandleFunc{ - checkStubs: depIsStubsModule, + checkStubs: depIsStubsModule, + checkApexModule: depIsApexModule, + checkInCommonApexes: belongsToCommonApexes, + checkApexIsNonUpdatable: belongsToNonUpdatableApex, + checkNotDynamicDepTag: depIsNotDynamicDepTag, + checkNotStaticOrDynamicDepTag: depIsNotStaticOrDynamicDepTag, + checkGlobalAllowlistedDep: depIsGloballyAllowlisted, } // ---------------------------------------------------------------------------- @@ -122,7 +192,9 @@ var containerBoundaryFunctionsTable = map[*container]containerBoundaryFunc{ // ---------------------------------------------------------------------------- type InstallableModule interface { - EnforceApiContainerChecks() bool + ContainersInfo() ContainersInfo + StaticDependencyTags() []blueprint.DependencyTag + DynamicDependencyTags() []blueprint.DependencyTag } type restriction struct { @@ -160,7 +232,11 @@ var ( "not allowed to depend on the vendor partition module, in order to support " + "independent development/update cycles and to support the Generic System " + "Image. Try depending on HALs, VNDK or AIDL instead.", - allowedExceptions: []exceptionHandleFuncLabel{}, + allowedExceptions: []exceptionHandleFuncLabel{ + checkStubs, + checkNotDynamicDepTag, + checkGlobalAllowlistedDep, + }, }, }, } @@ -173,7 +249,11 @@ var ( errorMessage: "Module belonging to the product partition is not allowed to " + "depend on the vendor partition module, as this may lead to security " + "vulnerabilities. Try depending on the HALs or utilize AIDL instead.", - allowedExceptions: []exceptionHandleFuncLabel{}, + allowedExceptions: []exceptionHandleFuncLabel{ + checkStubs, + checkNotDynamicDepTag, + checkGlobalAllowlistedDep, + }, }, }, } @@ -189,7 +269,11 @@ var ( "system partition, including \"framework\". Depending on the system " + "partition may lead to disclosure of implementation details and regression " + "due to API changes across platform versions. Try depending on the stubs instead.", - allowedExceptions: []exceptionHandleFuncLabel{checkStubs}, + allowedExceptions: []exceptionHandleFuncLabel{ + checkStubs, + checkNotStaticOrDynamicDepTag, + checkGlobalAllowlistedDep, + }, }, }, } @@ -213,7 +297,14 @@ func initializeApexContainer() *container { "modules belonging to the system partition. Either statically depend on the " + "module or convert the depending module to java_sdk_library and depend on " + "the stubs.", - allowedExceptions: []exceptionHandleFuncLabel{checkStubs}, + allowedExceptions: []exceptionHandleFuncLabel{ + checkStubs, + checkApexModule, + checkInCommonApexes, + checkApexIsNonUpdatable, + checkNotStaticOrDynamicDepTag, + checkGlobalAllowlistedDep, + }, }, }, } @@ -224,7 +315,12 @@ func initializeApexContainer() *container { "modules belonging to other Apex(es). Either include the depending " + "module in the Apex or convert the depending module to java_sdk_library " + "and depend on its stubs.", - allowedExceptions: []exceptionHandleFuncLabel{checkStubs}, + allowedExceptions: []exceptionHandleFuncLabel{ + checkStubs, + checkInCommonApexes, + checkNotStaticOrDynamicDepTag, + checkGlobalAllowlistedDep, + }, }) return apexContainer @@ -280,9 +376,18 @@ func generateContainerInfo(ctx ModuleContext) ContainersInfo { } } +func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) { + if ctx.Module() == module { + return module.ContainersInfo(), true + } + + return OtherModuleProvider(ctx, module, ContainersInfoProvider) +} + func setContainerInfo(ctx ModuleContext) { if _, ok := ctx.Module().(InstallableModule); ok { containersInfo := generateContainerInfo(ctx) + ctx.Module().base().containersInfo = containersInfo SetProvider(ctx, ContainersInfoProvider, containersInfo) } } diff --git a/android/module.go b/android/module.go index d548b83c5..0c2434164 100644 --- a/android/module.go +++ b/android/module.go @@ -119,6 +119,9 @@ type Module interface { TransitivePackagingSpecs() []PackagingSpec ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator + + // Get the information about the containers this module belongs to. + ContainersInfo() ContainersInfo } // Qualified id for a module @@ -898,6 +901,10 @@ type ModuleBase struct { // complianceMetadataInfo is for different module types to dump metadata. // See android.ModuleContext interface. complianceMetadataInfo *ComplianceMetadataInfo + + // containersInfo stores the information about the containers and the information of the + // apexes the module belongs to. + containersInfo ContainersInfo } func (m *ModuleBase) AddJSONData(d *map[string]interface{}) { @@ -2083,6 +2090,10 @@ func (m *ModuleBase) moduleInfoVariant(ctx ModuleContext) string { return variant } +func (m *ModuleBase) ContainersInfo() ContainersInfo { + return m.containersInfo +} + // Check the supplied dist structure to make sure that it is valid. // // property - the base property, e.g. dist or dists[1], which is combined with the diff --git a/java/base.go b/java/base.go index 8a4c64d71..7efd0f2c8 100644 --- a/java/base.go +++ b/java/base.go @@ -563,8 +563,14 @@ type Module struct { var _ android.InstallableModule = (*Module)(nil) // To satisfy the InstallableModule interface -func (j *Module) EnforceApiContainerChecks() bool { - return true +func (j *Module) StaticDependencyTags() []blueprint.DependencyTag { + return []blueprint.DependencyTag{staticLibTag} +} + +// To satisfy the InstallableModule interface +func (j *Module) DynamicDependencyTags() []blueprint.DependencyTag { + return []blueprint.DependencyTag{libTag, sdkLibTag, bootClasspathTag, systemModulesTag, + instrumentationForTag, java9LibTag} } // Overrides android.ModuleBase.InstallInProduct()