Merge "Allow map_file_generator to use host tools"
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index d837c6e..252e812 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -140,6 +140,10 @@
$(PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS)
combined_exclude_paths := $(MEMTAG_HEAP_EXCLUDE_PATHS) \
$(PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS)
+ ifneq ($(PRODUCT_MEMTAG_HEAP_SKIP_DEFAULT_PATHS),true)
+ combined_sync_include_paths += $(PRODUCT_MEMTAG_HEAP_SYNC_DEFAULT_INCLUDE_PATHS)
+ combined_async_include_paths += $(PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS)
+ endif
ifeq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
$(filter $(dir)%,$(LOCAL_PATH)))),)
diff --git a/core/product.mk b/core/product.mk
index 6f54b78..7e67dcd 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -247,6 +247,16 @@
# Whether any paths should have HWASan enabled for components
_product_list_vars += PRODUCT_HWASAN_INCLUDE_PATHS
+# Whether any paths should have Memtag_heap enabled for components
+_product_list_vars += PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
+_product_list_vars += PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS
+_product_list_vars += PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS
+_product_list_vars += PRODUCT_MEMTAG_HEAP_SYNC_DEFAULT_INCLUDE_PATHS
+_product_list_vars += PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS
+
+# Whether this product wants to start with an empty list of default memtag_heap include paths
+_product_single_value_vars += PRODUCT_MEMTAG_HEAP_SKIP_DEFAULT_PATHS
+
# Whether the Scudo hardened allocator is disabled platform-wide
_product_single_value_vars += PRODUCT_DISABLE_SCUDO
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 6383393..6c613d6 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -116,8 +116,8 @@
$(call add_json_list, HWASanIncludePaths, $(HWASAN_INCLUDE_PATHS) $(PRODUCT_HWASAN_INCLUDE_PATHS))
$(call add_json_list, MemtagHeapExcludePaths, $(MEMTAG_HEAP_EXCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS))
-$(call add_json_list, MemtagHeapAsyncIncludePaths, $(MEMTAG_HEAP_ASYNC_INCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS))
-$(call add_json_list, MemtagHeapSyncIncludePaths, $(MEMTAG_HEAP_SYNC_INCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS))
+$(call add_json_list, MemtagHeapAsyncIncludePaths, $(MEMTAG_HEAP_ASYNC_INCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS) $(if $(filter true,$(PRODUCT_MEMTAG_HEAP_SKIP_DEFAULT_PATHS)),,$(PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS)))
+$(call add_json_list, MemtagHeapSyncIncludePaths, $(MEMTAG_HEAP_SYNC_INCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS) $(if $(filter true,$(PRODUCT_MEMTAG_HEAP_SKIP_DEFAULT_PATHS)),,$(PRODUCT_MEMTAG_HEAP_SYNC_DEFAULT_INCLUDE_PATHS)))
$(call add_json_bool, DisableScudo, $(filter true,$(PRODUCT_DISABLE_SCUDO)))
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index 79bd74a..38ba219 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -76,3 +76,7 @@
# Enable CFI for security-sensitive components
$(call inherit-product, $(SRC_TARGET_DIR)/product/cfi-common.mk)
$(call inherit-product-if-exists, vendor/google/products/cfi-vendor.mk)
+
+# Enable MTE for security-sensitive components
+$(call inherit-product, $(SRC_TARGET_DIR)/product/memtag-common.mk)
+$(call inherit-product-if-exists, vendor/google/products/memtag-vendor.mk)
diff --git a/target/product/memtag-common.mk b/target/product/memtag-common.mk
new file mode 100644
index 0000000..829cb41
--- /dev/null
+++ b/target/product/memtag-common.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This is a recommended set of common components to enable MTE for.
+
+PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS := \
+ external/android-clat \
+ external/iproute2 \
+ external/iptables \
+ external/mtpd \
+ external/ppp \
+ hardware/st/nfc \
+ hardware/st/secure_element \
+ hardware/st/secure_element2 \
+ packages/modules/StatsD \
+ system/bpf \
+ system/netd/netutil_wrappers \
+ system/netd/server
diff --git a/target/product/module_common.mk b/target/product/module_common.mk
index 84bd799..53b2ca6 100644
--- a/target/product/module_common.mk
+++ b/target/product/module_common.mk
@@ -17,6 +17,7 @@
$(call inherit-product, $(SRC_TARGET_DIR)/product/default_art_config.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/cfi-common.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/memtag-common.mk)
# Enables treble, which enabled certain -D compilation flags. In particular, libhidlbase
# uses -DENFORCE_VINTF_MANIFEST. See b/185759877
diff --git a/tools/aconfig/src/codegen.rs b/tools/aconfig/src/codegen.rs
index fea9961..d96d4f9 100644
--- a/tools/aconfig/src/codegen.rs
+++ b/tools/aconfig/src/codegen.rs
@@ -17,7 +17,10 @@
use anyhow::{ensure, Result};
pub fn is_valid_name_ident(s: &str) -> bool {
- // Identifiers must match [a-z][a-z0-9_]*
+ // Identifiers must match [a-z][a-z0-9_]*, except consecutive underscores are not allowed
+ if s.contains("__") {
+ return false;
+ }
let mut chars = s.chars();
let Some(first) = chars.next() else {
return false;
@@ -46,11 +49,14 @@
fn test_is_valid_name_ident() {
assert!(is_valid_name_ident("foo"));
assert!(is_valid_name_ident("foo_bar_123"));
+ assert!(is_valid_name_ident("foo_"));
assert!(!is_valid_name_ident(""));
assert!(!is_valid_name_ident("123_foo"));
assert!(!is_valid_name_ident("foo-bar"));
assert!(!is_valid_name_ident("foo-b\u{00e5}r"));
+ assert!(!is_valid_name_ident("foo__bar"));
+ assert!(!is_valid_name_ident("_foo"));
}
#[test]
@@ -59,6 +65,7 @@
assert!(is_valid_package_ident("foo_bar_123"));
assert!(is_valid_package_ident("foo.bar"));
assert!(is_valid_package_ident("foo.bar.a123"));
+ assert!(!is_valid_package_ident("foo._bar"));
assert!(!is_valid_package_ident(""));
assert!(!is_valid_package_ident("123_foo"));
@@ -69,6 +76,7 @@
assert!(!is_valid_package_ident("foo.bar."));
assert!(!is_valid_package_ident("."));
assert!(!is_valid_package_ident("foo..bar"));
+ assert!(!is_valid_package_ident("foo.__bar"));
}
#[test]
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index cf025cb..54fa0dc 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -24,43 +24,59 @@
use crate::codegen;
use crate::commands::OutputFile;
-pub fn generate_java_code(cache: &Cache) -> Result<OutputFile> {
+pub fn generate_java_code(cache: &Cache) -> Result<Vec<OutputFile>> {
let package = cache.package();
let class_elements: Vec<ClassElement> =
cache.iter().map(|item| create_class_element(package, item)).collect();
- let readwrite = class_elements.iter().any(|item| item.readwrite);
- let context = Context { package: package.to_string(), readwrite, class_elements };
+ let is_read_write = class_elements.iter().any(|item| item.is_read_write);
+ let context = Context { package_name: package.to_string(), is_read_write, class_elements };
+
+ let java_files = vec!["Flags.java", "FeatureFlagsImpl.java", "FeatureFlags.java"];
+
let mut template = TinyTemplate::new();
- template.add_template("java_code_gen", include_str!("../templates/java.template"))?;
- let contents = template.render("java_code_gen", &context)?;
- let mut path: PathBuf = package.split('.').collect();
- // TODO: Allow customization of the java class name
- path.push("Flags.java");
- Ok(OutputFile { contents: contents.into(), path })
+ template.add_template("Flags.java", include_str!("../templates/Flags.java.template"))?;
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../templates/FeatureFlagsImpl.java.template"),
+ )?;
+ template.add_template(
+ "FeatureFlags.java",
+ include_str!("../templates/FeatureFlags.java.template"),
+ )?;
+
+ let path: PathBuf = package.split('.').collect();
+ java_files
+ .iter()
+ .map(|file| {
+ Ok(OutputFile {
+ contents: template.render(file, &context)?.into(),
+ path: path.join(file),
+ })
+ })
+ .collect::<Result<Vec<OutputFile>>>()
}
#[derive(Serialize)]
struct Context {
- pub package: String,
- pub readwrite: bool,
+ pub package_name: String,
+ pub is_read_write: bool,
pub class_elements: Vec<ClassElement>,
}
#[derive(Serialize)]
struct ClassElement {
- pub method_name: String,
- pub readwrite: bool,
pub default_value: String,
pub device_config_namespace: String,
pub device_config_flag: String,
+ pub flag_name_constant_suffix: String,
+ pub is_read_write: bool,
+ pub method_name: String,
}
fn create_class_element(package: &str, item: &Item) -> ClassElement {
let device_config_flag = codegen::create_device_config_ident(package, &item.name)
.expect("values checked at cache creation time");
ClassElement {
- method_name: item.name.replace('-', "_"),
- readwrite: item.permission == Permission::ReadWrite,
default_value: if item.state == FlagState::Enabled {
"true".to_string()
} else {
@@ -68,78 +84,100 @@
},
device_config_namespace: item.namespace.clone(),
device_config_flag,
+ flag_name_constant_suffix: item.name.to_ascii_uppercase(),
+ is_read_write: item.permission == Permission::ReadWrite,
+ method_name: item.name.clone(),
}
}
#[cfg(test)]
mod tests {
use super::*;
- use crate::aconfig::{FlagDeclaration, FlagValue};
- use crate::cache::CacheBuilder;
- use crate::commands::Source;
+ use std::collections::HashMap;
#[test]
fn test_generate_java_code() {
- let package = "com.example";
- let mut builder = CacheBuilder::new(package.to_string()).unwrap();
- builder
- .add_flag_declaration(
- Source::File("test.txt".to_string()),
- FlagDeclaration {
- name: "test".to_string(),
- namespace: "ns".to_string(),
- description: "buildtime enable".to_string(),
- },
- )
- .unwrap()
- .add_flag_declaration(
- Source::File("test2.txt".to_string()),
- FlagDeclaration {
- name: "test2".to_string(),
- namespace: "ns".to_string(),
- description: "runtime disable".to_string(),
- },
- )
- .unwrap()
- .add_flag_value(
- Source::Memory,
- FlagValue {
- package: package.to_string(),
- name: "test".to_string(),
- state: FlagState::Disabled,
- permission: Permission::ReadOnly,
- },
- )
- .unwrap();
- let cache = builder.build();
- let expect_content = r#"package com.example;
-
- import android.provider.DeviceConfig;
-
+ let cache = crate::test::create_cache();
+ let generated_files = generate_java_code(&cache).unwrap();
+ let expect_flags_content = r#"
+ package com.android.aconfig.test;
public final class Flags {
-
- public static boolean test() {
- return false;
+ public static boolean disabled_ro() {
+ return FEATURE_FLAGS.disabled_ro();
}
-
- public static boolean test2() {
- return DeviceConfig.getBoolean(
- "ns",
- "com.example.test2",
- false
- );
+ public static boolean disabled_rw() {
+ return FEATURE_FLAGS.disabled_rw();
}
+ public static boolean enabled_ro() {
+ return FEATURE_FLAGS.enabled_ro();
+ }
+ public static boolean enabled_rw() {
+ return FEATURE_FLAGS.enabled_rw();
+ }
+ private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
}
"#;
- let file = generate_java_code(&cache).unwrap();
- assert_eq!("com/example/Flags.java", file.path.to_str().unwrap());
- assert_eq!(
- None,
- crate::test::first_significant_code_diff(
- expect_content,
- &String::from_utf8(file.contents).unwrap()
- )
- );
+ let expected_featureflagsimpl_content = r#"
+ package com.android.aconfig.test;
+ import android.provider.DeviceConfig;
+ public final class FeatureFlagsImpl implements FeatureFlags {
+ @Override
+ public boolean disabled_ro() {
+ return false;
+ }
+ @Override
+ public boolean disabled_rw() {
+ return DeviceConfig.getBoolean(
+ "aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ false
+ );
+ }
+ @Override
+ public boolean enabled_ro() {
+ return true;
+ }
+ @Override
+ public boolean enabled_rw() {
+ return DeviceConfig.getBoolean(
+ "aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ true
+ );
+ }
+ }
+ "#;
+ let expected_featureflags_content = r#"
+ package com.android.aconfig.test;
+ public interface FeatureFlags {
+ boolean disabled_ro();
+ boolean disabled_rw();
+ boolean enabled_ro();
+ boolean enabled_rw();
+ }
+ "#;
+ let mut file_set = HashMap::from([
+ ("com/android/aconfig/test/Flags.java", expect_flags_content),
+ ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsimpl_content),
+ ("com/android/aconfig/test/FeatureFlags.java", expected_featureflags_content),
+ ]);
+
+ for file in generated_files {
+ let file_path = file.path.to_str().unwrap();
+ assert!(file_set.contains_key(file_path), "Cannot find {}", file_path);
+ assert_eq!(
+ None,
+ crate::test::first_significant_code_diff(
+ file_set.get(file_path).unwrap(),
+ &String::from_utf8(file.contents.clone()).unwrap()
+ ),
+ "File {} content is not correct",
+ file_path
+ );
+ file_set.remove(file_path);
+ }
+
+ assert!(file_set.is_empty());
}
}
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index 586ba04..eb860b0 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -89,7 +89,7 @@
Ok(builder.build())
}
-pub fn create_java_lib(cache: Cache) -> Result<OutputFile> {
+pub fn create_java_lib(cache: Cache) -> Result<Vec<OutputFile>> {
generate_java_code(&cache)
}
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 5a820d9..3a9a573 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -147,8 +147,10 @@
let file = fs::File::open(path)?;
let cache = Cache::read_from_reader(file)?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
- let generated_file = commands::create_java_lib(cache)?;
- write_output_file_realtive_to_dir(&dir, &generated_file)?;
+ let generated_files = commands::create_java_lib(cache)?;
+ generated_files
+ .iter()
+ .try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
}
Some(("create-cpp-lib", sub_matches)) => {
let path = get_required_arg::<String>(sub_matches, "cache")?;
diff --git a/tools/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/templates/FeatureFlags.java.template
new file mode 100644
index 0000000..b9e2cc7
--- /dev/null
+++ b/tools/aconfig/templates/FeatureFlags.java.template
@@ -0,0 +1,7 @@
+package {package_name};
+
+public interface FeatureFlags \{
+ {{ for item in class_elements}}
+ boolean {item.method_name}();
+ {{ endfor }}
+}
\ No newline at end of file
diff --git a/tools/aconfig/templates/java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
similarity index 63%
rename from tools/aconfig/templates/java.template
rename to tools/aconfig/templates/FeatureFlagsImpl.java.template
index a3d3319..2b031f1 100644
--- a/tools/aconfig/templates/java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -1,11 +1,12 @@
-package {package};
-{{ if readwrite }}
+package {package_name};
+{{ if is_read_write }}
import android.provider.DeviceConfig;
{{ endif }}
-public final class Flags \{
+public final class FeatureFlagsImpl implements FeatureFlags \{
{{ for item in class_elements}}
- public static boolean {item.method_name}() \{
- {{ if item.readwrite- }}
+ @Override
+ public boolean {item.method_name}() \{
+ {{ if item.is_read_write- }}
return DeviceConfig.getBoolean(
"{item.device_config_namespace}",
"{item.device_config_flag}",
@@ -16,4 +17,4 @@
{{ -endif }}
}
{{ endfor }}
-}
+}
\ No newline at end of file
diff --git a/tools/aconfig/templates/Flags.java.template b/tools/aconfig/templates/Flags.java.template
new file mode 100644
index 0000000..752a469
--- /dev/null
+++ b/tools/aconfig/templates/Flags.java.template
@@ -0,0 +1,11 @@
+package {package_name};
+
+public final class Flags \{
+ {{ for item in class_elements}}
+ public static boolean {item.method_name}() \{
+ return FEATURE_FLAGS.{item.method_name}();
+ }
+ {{ endfor }}
+ private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
+
+}