1// Copyright 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package selinux
16
17import (
18	"path"
19	"path/filepath"
20
21	"android/soong/android"
22)
23
24func init() {
25	android.RegisterModuleType("se_build_files", buildFilesFactory)
26}
27
28// se_build_files gathers policy files from sepolicy dirs, and acts like a filegroup. A tag with
29// partition(plat, system_ext, product) and scope(public, private) is used to select directories.
30// Supported tags are: "plat_public", "plat_private", "system_ext_public", "system_ext_private",
31// "product_public", "product_private", and "reqd_mask".
32func buildFilesFactory() android.Module {
33	module := &buildFiles{}
34	module.AddProperties(&module.properties)
35	android.InitAndroidModule(module)
36	return module
37}
38
39type buildFilesProperties struct {
40	// list of source file suffixes used to collect selinux policy files.
41	// Source files will be looked up in the following local directories:
42	// system/sepolicy/{public, private, vendor, reqd_mask}
43	// and directories specified by following config variables:
44	// BOARD_SEPOLICY_DIRS, BOARD_ODM_SEPOLICY_DIRS
45	// SYSTEM_EXT_PUBLIC_SEPOLICY_DIR, SYSTEM_EXT_PRIVATE_SEPOLICY_DIR
46	Srcs []string
47}
48
49type buildFiles struct {
50	android.ModuleBase
51	properties buildFilesProperties
52
53	srcs map[string]android.Paths
54}
55
56func (b *buildFiles) findSrcsInDirs(ctx android.ModuleContext, dirs ...string) android.Paths {
57	result := android.Paths{}
58	for _, file := range b.properties.Srcs {
59		for _, dir := range dirs {
60			path := filepath.Join(dir, file)
61			files, err := ctx.GlobWithDeps(path, nil)
62			if err != nil {
63				ctx.ModuleErrorf("glob: %s", err.Error())
64			}
65			for _, f := range files {
66				result = append(result, android.PathForSource(ctx, f))
67			}
68		}
69	}
70	return result
71}
72
73func (b *buildFiles) DepsMutator(ctx android.BottomUpMutatorContext) {
74	// do nothing
75}
76
77type sepolicyDir struct {
78	tag   string
79	paths []string
80}
81
82func (b *buildFiles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
83	b.srcs = make(map[string]android.Paths)
84	b.srcs[".reqd_mask"] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "reqd_mask"))
85	b.srcs[".plat_public"] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "public"))
86	b.srcs[".plat_private"] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "private"))
87	b.srcs[".plat_vendor"] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "vendor"))
88	b.srcs[".system_ext_public"] = b.findSrcsInDirs(ctx, ctx.DeviceConfig().SystemExtPublicSepolicyDirs()...)
89	b.srcs[".system_ext_private"] = b.findSrcsInDirs(ctx, ctx.DeviceConfig().SystemExtPrivateSepolicyDirs()...)
90	b.srcs[".product_public"] = b.findSrcsInDirs(ctx, ctx.Config().ProductPublicSepolicyDirs()...)
91	b.srcs[".product_private"] = b.findSrcsInDirs(ctx, ctx.Config().ProductPrivateSepolicyDirs()...)
92	b.srcs[".vendor"] = b.findSrcsInDirs(ctx, ctx.DeviceConfig().VendorSepolicyDirs()...)
93	b.srcs[".odm"] = b.findSrcsInDirs(ctx, ctx.DeviceConfig().OdmSepolicyDirs()...)
94
95	prebuilt_directories, err := ctx.GlobWithDeps("system/sepolicy/prebuilts/api/*", nil)
96	if err != nil {
97		ctx.ModuleErrorf("error while globbing: %w", err)
98		return
99	}
100
101	// directories used for compat tests and Treble tests
102	for _, dir := range prebuilt_directories {
103		ver := path.Base(dir)
104		b.srcs[".plat_public_"+ver] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "prebuilts", "api", ver, "public"))
105		b.srcs[".plat_private_"+ver] = b.findSrcsInDirs(ctx, filepath.Join("system", "sepolicy", "prebuilts", "api", ver, "private"))
106		b.srcs[".system_ext_public_"+ver] = b.findSrcsInDirs(ctx, filepath.Join(ctx.DeviceConfig().SystemExtSepolicyPrebuiltApiDir(), "prebuilts", "api", ver, "public"))
107		b.srcs[".system_ext_private_"+ver] = b.findSrcsInDirs(ctx, filepath.Join(ctx.DeviceConfig().SystemExtSepolicyPrebuiltApiDir(), "prebuilts", "api", ver, "private"))
108		b.srcs[".product_public_"+ver] = b.findSrcsInDirs(ctx, filepath.Join(ctx.DeviceConfig().ProductSepolicyPrebuiltApiDir(), "prebuilts", "api", ver, "public"))
109		b.srcs[".product_private_"+ver] = b.findSrcsInDirs(ctx, filepath.Join(ctx.DeviceConfig().ProductSepolicyPrebuiltApiDir(), "prebuilts", "api", ver, "private"))
110	}
111
112	b.setOutputFiles(ctx)
113}
114
115func (b *buildFiles) setOutputFiles(ctx android.ModuleContext) {
116	for tag, files := range b.srcs {
117		ctx.SetOutputFiles(files, tag)
118	}
119}
120