From 1b0893eeba2cdee3dcc573ec523ee0199684d6b1 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 13 Dec 2021 23:40:17 +0900 Subject: [PATCH 1/2] Build canned_fs_config using RuleBuilder ... in preparation for adding the support for custom canned fs config Bug: 209971551 Test: m nothing Change-Id: I7f2576ff99c65bdb6c9ce4ace61bc783eea2f0d4 --- apex/apex_test.go | 27 +++++------ apex/builder.go | 118 +++++++++++++++++++++++----------------------- 2 files changed, 72 insertions(+), 73 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index 3cc312dbd..a4b4537db 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -2581,22 +2581,21 @@ func TestFilesInSubDir(t *testing.T) { `) generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig") - dirs := strings.Split(generateFsRule.Args["exec_paths"], " ") + cmd := generateFsRule.RuleParams.Command // Ensure that the subdirectories are all listed - ensureListContains(t, dirs, "etc") - ensureListContains(t, dirs, "etc/foo") - ensureListContains(t, dirs, "etc/foo/bar") - ensureListContains(t, dirs, "lib64") - ensureListContains(t, dirs, "lib64/foo") - ensureListContains(t, dirs, "lib64/foo/bar") - ensureListContains(t, dirs, "lib") - ensureListContains(t, dirs, "lib/foo") - ensureListContains(t, dirs, "lib/foo/bar") - - ensureListContains(t, dirs, "bin") - ensureListContains(t, dirs, "bin/foo") - ensureListContains(t, dirs, "bin/foo/bar") + ensureContains(t, cmd, "/etc ") + ensureContains(t, cmd, "/etc/foo ") + ensureContains(t, cmd, "/etc/foo/bar ") + ensureContains(t, cmd, "/lib64 ") + ensureContains(t, cmd, "/lib64/foo ") + ensureContains(t, cmd, "/lib64/foo/bar ") + ensureContains(t, cmd, "/lib ") + ensureContains(t, cmd, "/lib/foo ") + ensureContains(t, cmd, "/lib/foo/bar ") + ensureContains(t, cmd, "/bin ") + ensureContains(t, cmd, "/bin/foo ") + ensureContains(t, cmd, "/bin/foo/bar ") } func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) { diff --git a/apex/builder.go b/apex/builder.go index 5910784b2..787b2c4b0 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -72,19 +72,6 @@ func init() { } var ( - // Create a canned fs config file where all files and directories are - // by default set to (uid/gid/mode) = (1000/1000/0644) - // TODO(b/113082813) make this configurable using config.fs syntax - generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{ - Command: `( set -e; echo '/ 1000 1000 0755' ` + - `&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` + - `&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` + - `&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`, - Description: "fs_config ${out}", - Rspfile: "$out.apklist", - RspfileContent: "$in", - }, "ro_paths", "exec_paths", "apk_paths") - apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{ Command: `rm -f $out && ${jsonmodify} $in ` + `-a provideNativeLibs ${provideNativeLibs} ` + @@ -583,55 +570,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { // Figure out if need to compress apex. compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.properties.Compressible, false) && !a.testApex && !ctx.Config().UnbundledBuildApps() if apexType == imageApex { + //////////////////////////////////////////////////////////////////////////////////// // Step 2: create canned_fs_config which encodes filemode,uid,gid of each files // in this APEX. The file will be used by apexer in later steps. - // TODO(jiyong): make this as a function - // TODO(jiyong): use the RuleBuilder - var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"} - var executablePaths []string // this also includes dirs - var extractedAppSetPaths android.Paths - var extractedAppSetDirs []string - for _, f := range a.filesInfo { - pathInApex := f.path() - if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") { - executablePaths = append(executablePaths, pathInApex) - for _, d := range f.dataPaths { - readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel())) - } - for _, s := range f.symlinks { - executablePaths = append(executablePaths, filepath.Join(f.installDir, s)) - } - } else if f.class == appSet { - extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile) - extractedAppSetDirs = append(extractedAppSetDirs, f.installDir) - } else { - readOnlyPaths = append(readOnlyPaths, pathInApex) - } - dir := f.installDir - for !android.InList(dir, executablePaths) && dir != "" { - executablePaths = append(executablePaths, dir) - dir, _ = filepath.Split(dir) // move up to the parent - if len(dir) > 0 { - // remove trailing slash - dir = dir[:len(dir)-1] - } - } - } - sort.Strings(readOnlyPaths) - sort.Strings(executablePaths) - cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config") - ctx.Build(pctx, android.BuildParams{ - Rule: generateFsConfig, - Output: cannedFsConfig, - Description: "generate fs config", - Inputs: extractedAppSetPaths, - Args: map[string]string{ - "ro_paths": strings.Join(readOnlyPaths, " "), - "exec_paths": strings.Join(executablePaths, " "), - "apk_paths": strings.Join(extractedAppSetDirs, " "), - }, - }) + cannedFsConfig := a.buildCannedFsConfig(ctx) implicitInputs = append(implicitInputs, cannedFsConfig) //////////////////////////////////////////////////////////////////////////////////// @@ -1072,3 +1015,60 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) } + +func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath { + var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"} + var executablePaths []string // this also includes dirs + var appSetDirs []string + appSetFiles := make(map[string]android.Path) + for _, f := range a.filesInfo { + pathInApex := f.path() + if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") { + executablePaths = append(executablePaths, pathInApex) + for _, d := range f.dataPaths { + readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel())) + } + for _, s := range f.symlinks { + executablePaths = append(executablePaths, filepath.Join(f.installDir, s)) + } + } else if f.class == appSet { + appSetDirs = append(appSetDirs, f.installDir) + appSetFiles[f.installDir] = f.builtFile + } else { + readOnlyPaths = append(readOnlyPaths, pathInApex) + } + dir := f.installDir + for !android.InList(dir, executablePaths) && dir != "" { + executablePaths = append(executablePaths, dir) + dir, _ = filepath.Split(dir) // move up to the parent + if len(dir) > 0 { + // remove trailing slash + dir = dir[:len(dir)-1] + } + } + } + sort.Strings(readOnlyPaths) + sort.Strings(executablePaths) + sort.Strings(appSetDirs) + + cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config") + builder := android.NewRuleBuilder(pctx, ctx) + cmd := builder.Command() + cmd.Text("(") + cmd.Text("echo '/ 1000 1000 0755';") + for _, p := range readOnlyPaths { + cmd.Textf("echo '/%s 1000 1000 0644';", p) + } + for _, p := range executablePaths { + cmd.Textf("echo '/%s 0 2000 0755';", p) + } + for _, dir := range appSetDirs { + cmd.Textf("echo '/%s 0 2000 0755';", dir) + file := appSetFiles[dir] + cmd.Text("zipinfo -1").Input(file).Textf(`| sed "s:\(.*\):/%s/\1 1000 1000 0644:";`, dir) + } + cmd.Text(")").FlagWithOutput("> ", cannedFsConfig) + builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName())) + + return cannedFsConfig.OutputPath +} From 038e852ce10b11f1dfd388f28243cdf5835f2c8f Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 13 Dec 2021 23:56:35 +0900 Subject: [PATCH 2/2] Add canned_fs_config to apex module type The property is used to customize uid/gid/mode/capabilities of files in an APEX. Bug: 209971551 Test: m Change-Id: I484e46ff819a5266c1e8046dae337e18ef3fefea --- apex/apex.go | 8 ++++++++ apex/builder.go | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/apex/apex.go b/apex/apex.go index 0a785f3d0..cedc3b3b9 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -98,6 +98,14 @@ type apexBundleProperties struct { // /system/sepolicy/apex/_file_contexts. File_contexts *string `android:"path"` + // Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The + // format is / [capabilities=0x], where path_or_glob is a + // path or glob pattern for a file or set of files, uid/gid are numerial values of user ID + // and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the + // capability. If this property is not set, or a file is missing in the file, default config + // is used. + Canned_fs_config *string `android:"path"` + ApexNativeDependencies Multilib apexMultilibProperties diff --git a/apex/builder.go b/apex/builder.go index 787b2c4b0..ea25537ca 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -1067,6 +1067,11 @@ func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.Outp file := appSetFiles[dir] cmd.Text("zipinfo -1").Input(file).Textf(`| sed "s:\(.*\):/%s/\1 1000 1000 0644:";`, dir) } + // Custom fs_config is "appended" to the last so that entries from the file are preferred + // over default ones set above. + if a.properties.Canned_fs_config != nil { + cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config)) + } cmd.Text(")").FlagWithOutput("> ", cannedFsConfig) builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))