1// Copyright (C) 2019 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	"fmt"
19	"io"
20
21	"github.com/google/blueprint/proptools"
22
23	"android/soong/android"
24)
25
26var (
27	// Should be synced with keys.conf.
28	AllPlatformKeys = []string{
29		"platform",
30		"sdk_sandbox",
31		"media",
32		"networkstack",
33		"shared",
34		"testkey",
35		"bluetooth",
36	}
37)
38
39type macPermissionsProperties struct {
40	// keys.conf files to control the mapping of "tags" found in the mac_permissions.xml files.
41	Keys []string `android:"path"`
42
43	// Source files for the generated mac_permissions.xml file.
44	Srcs []string `android:"path"`
45
46	// Output file name. Defaults to module name
47	Stem *string
48}
49
50type macPermissionsModule struct {
51	android.ModuleBase
52
53	properties  macPermissionsProperties
54	outputPath  android.ModuleOutPath
55	installPath android.InstallPath
56}
57
58func init() {
59	android.RegisterModuleType("mac_permissions", macPermissionsFactory)
60}
61
62func getAllPlatformKeyPaths(ctx android.ModuleContext) android.Paths {
63	var platformKeys android.Paths
64
65	defaultCertificateDir := ctx.Config().DefaultAppCertificateDir(ctx)
66	for _, key := range AllPlatformKeys {
67		platformKeys = append(platformKeys, defaultCertificateDir.Join(ctx, key+".x509.pem"))
68	}
69
70	return platformKeys
71}
72
73func (m *macPermissionsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
74	// do nothing
75}
76
77func (m *macPermissionsModule) stem() string {
78	return proptools.StringDefault(m.properties.Stem, m.Name())
79}
80
81func buildVariant(ctx android.ModuleContext) string {
82	if ctx.Config().Eng() {
83		return "eng"
84	}
85	if ctx.Config().Debuggable() {
86		return "userdebug"
87	}
88	return "user"
89}
90
91func (m *macPermissionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
92	platformKeys := getAllPlatformKeyPaths(ctx)
93	keys := android.PathsForModuleSrc(ctx, m.properties.Keys)
94	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
95
96	m4Keys := android.PathForModuleGen(ctx, "mac_perms_keys.tmp")
97	rule := android.NewRuleBuilder(pctx, ctx)
98	rule.Command().
99		Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
100		Text("--fatal-warnings -s").
101		FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
102		Inputs(keys).
103		FlagWithOutput("> ", m4Keys).
104		Implicits(platformKeys)
105
106	m.outputPath = android.PathForModuleOut(ctx, m.stem())
107	rule.Command().Text("DEFAULT_SYSTEM_DEV_CERTIFICATE="+ctx.Config().DefaultAppCertificateDir(ctx).String()).
108		Text("MAINLINE_SEPOLICY_DEV_CERTIFICATES="+ctx.Config().MainlineSepolicyDevCertificatesDir(ctx).String()).
109		BuiltTool("insertkeys").
110		FlagWithArg("-t ", buildVariant(ctx)).
111		Input(m4Keys).
112		FlagWithOutput("-o ", m.outputPath).
113		Inputs(srcs)
114
115	rule.Build("mac_permission", "build "+m.Name())
116
117	m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
118	ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
119}
120
121func (m *macPermissionsModule) AndroidMk() android.AndroidMkData {
122	return android.AndroidMkData{
123		Class:      "ETC",
124		OutputFile: android.OptionalPathForPath(m.outputPath),
125		Extra: []android.AndroidMkExtraFunc{
126			func(w io.Writer, outputFile android.Path) {
127				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
128				fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
129			},
130		},
131	}
132}
133
134// mac_permissions module generates a mac_permissions.xml file from given keys.conf and
135// source files. The following variables are supported for keys.conf files.
136//
137//	DEFAULT_SYSTEM_DEV_CERTIFICATE
138//	MAINLINE_SEPOLICY_DEV_CERTIFICATES
139func macPermissionsFactory() android.Module {
140	m := &macPermissionsModule{}
141	m.AddProperties(&m.properties)
142	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
143	return m
144}
145