Merge "storaged: Fix double ownership for HealthInfoCallback."
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index 4e8fdf9..8241f0e 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -25,7 +25,7 @@
rt_sigprocmask: 1
rt_sigaction: 1
rt_tgsigqueueinfo: 1
-prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS || arg0 == PR_GET_TAGGED_ADDR_CTRL || arg0 == PR_PAC_GET_ENABLED_KEYS
+prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS || arg0 == 56 || arg0 == 61
madvise: 1
mprotect: arg2 in 0x1|0x2
munmap: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index 4eb996e..0cb8e08 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -34,7 +34,15 @@
rt_sigaction: 1
rt_tgsigqueueinfo: 1
+// this is referenced from mainline modules running on Q devices, where not all
+// of the constants used here are defined in headers, so minijail rejects them.
+// we define them here to avoid those errors.
+ // constants introduced in R
#define PR_SET_VMA 0x53564d41
+#define PR_GET_TAGGED_ADDR_CTRL 56
+ // constants introduced in S
+#define PR_PAC_GET_ENABLED_KEYS 61
+
#if defined(__aarch64__)
// PR_PAC_RESET_KEYS happens on aarch64 in pthread_create path.
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA || arg0 == PR_PAC_RESET_KEYS || arg0 == PR_GET_TAGGED_ADDR_CTRL || arg0 == PR_PAC_GET_ENABLED_KEYS
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 76e9889..0cf4699 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -332,8 +332,8 @@
auto fastboot_hal = device->fastboot_hal();
if (!fastboot_hal) {
- *message = "Fastboot HAL not found";
- return false;
+ *message = "raw";
+ return true;
}
FileSystemType type;
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index e3e3af8..71fe124 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -267,8 +267,8 @@
return AssertionFailure() << "Temp file allocated to " << big_file_->path << ", not in "
<< kUserDataDevice;
}
- uint64_t next_consume =
- std::min(free_space_ - max_free_space, (uint64_t)std::numeric_limits<off_t>::max());
+ uint64_t next_consume = std::min(available_space_ - max_free_space,
+ (uint64_t)std::numeric_limits<off_t>::max());
off_t allocated = 0;
while (next_consume > 0 && free_space_ > max_free_space) {
int status = fallocate(big_file_->fd, 0, allocated, next_consume);
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 52e3995..13ee37d 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -157,7 +157,7 @@
}
#define MODULE_BASE_DIR "/lib/modules"
-bool LoadKernelModules(bool recovery, bool want_console, int& modules_loaded) {
+bool LoadKernelModules(bool recovery, bool want_console, bool want_parallel, int& modules_loaded) {
struct utsname uts;
if (uname(&uts)) {
LOG(FATAL) << "Failed to get kernel version.";
@@ -206,7 +206,8 @@
}
Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(recovery, MODULE_BASE_DIR));
- bool retval = m.LoadListedModules(!want_console);
+ bool retval = (want_parallel) ? m.LoadModulesParallel(std::thread::hardware_concurrency())
+ : m.LoadListedModules(!want_console);
modules_loaded = m.GetModuleCount();
if (modules_loaded > 0) {
return retval;
@@ -319,11 +320,13 @@
}
auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0;
+ auto want_parallel =
+ bootconfig.find("androidboot.load_modules_parallel = \"true\"") != std::string::npos;
boot_clock::time_point module_start_time = boot_clock::now();
int module_count = 0;
if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline, bootconfig), want_console,
- module_count)) {
+ want_parallel, module_count)) {
if (want_console != FirstStageConsoleParam::DISABLED) {
LOG(ERROR) << "Failed to load kernel modules, starting console";
} else {
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c89c5ab..be8c554 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -762,6 +762,7 @@
void SelinuxRestoreContext() {
LOG(INFO) << "Running restorecon...";
selinux_android_restorecon("/dev", 0);
+ selinux_android_restorecon("/dev/console", 0);
selinux_android_restorecon("/dev/kmsg", 0);
if constexpr (WORLD_WRITABLE_KMSG) {
selinux_android_restorecon("/dev/kmsg_debug", 0);
diff --git a/libmodprobe/TEST_MAPPING b/libmodprobe/TEST_MAPPING
index 526b1e4..888593e 100644
--- a/libmodprobe/TEST_MAPPING
+++ b/libmodprobe/TEST_MAPPING
@@ -3,5 +3,10 @@
{
"name": "libmodprobe_tests"
}
+ ],
+ "hwasan-postsubmit": [
+ {
+ "name": "libmodprobe_tests"
+ }
]
}
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index c934860..5d79d6a 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -16,17 +16,21 @@
#pragma once
+#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <android-base/thread_annotations.h>
+
class Modprobe {
public:
Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load",
bool use_blocklist = true);
+ bool LoadModulesParallel(int num_threads);
bool LoadListedModules(bool strict = true);
bool LoadWithAliases(const std::string& module_name, bool strict,
const std::string& parameters = "");
@@ -66,7 +70,9 @@
std::vector<std::string> module_load_;
std::unordered_map<std::string, std::string> module_options_;
std::set<std::string> module_blocklist_;
+ std::mutex module_loaded_lock_;
std::unordered_set<std::string> module_loaded_;
+ std::unordered_set<std::string> module_loaded_paths_;
int module_count_ = 0;
bool blocklist_enabled = false;
};
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 1a9d364..3054d2b 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -21,8 +21,10 @@
#include <sys/syscall.h>
#include <algorithm>
+#include <map>
#include <set>
#include <string>
+#include <thread>
#include <vector>
#include <android-base/chrono_utils.h>
@@ -437,6 +439,97 @@
return module_blocklist_.count(canonical_name) > 0;
}
+// Another option to load kernel modules. load in independent modules in parallel
+// and then load modules which only have soft dependency, third update dependency list of other
+// remaining modules, repeat these steps until all modules are loaded.
+bool Modprobe::LoadModulesParallel(int num_threads) {
+ bool ret = true;
+ std::map<std::string, std::set<std::string>> mod_with_deps;
+ std::map<std::string, std::set<std::string>> mod_with_softdeps;
+
+ // Get dependencies
+ for (const auto& module : module_load_) {
+ auto dependencies = GetDependencies(MakeCanonical(module));
+
+ for (auto dep = dependencies.rbegin(); dep != dependencies.rend(); dep++) {
+ mod_with_deps[module].emplace(*dep);
+ }
+ }
+
+ // Get soft dependencies
+ for (const auto& [it_mod, it_softdep] : module_pre_softdep_) {
+ mod_with_softdeps[MakeCanonical(it_mod)].emplace(it_softdep);
+ }
+
+ // Get soft post dependencies
+ for (const auto& [it_mod, it_softdep] : module_post_softdep_) {
+ mod_with_softdeps[MakeCanonical(it_mod)].emplace(it_softdep);
+ }
+
+ while (!mod_with_deps.empty()) {
+ std::vector<std::thread> threads;
+ std::vector<std::string> mods_path_to_load;
+ std::vector<std::string> mods_with_softdep_to_load;
+ std::mutex vector_lock;
+
+ // Find independent modules and modules only having soft dependencies
+ for (const auto& [it_mod, it_dep] : mod_with_deps) {
+ if (it_dep.size() == 1 && mod_with_softdeps[it_mod].empty()) {
+ mods_path_to_load.emplace_back(*(it_dep.begin()));
+ } else if (it_dep.size() == 1) {
+ mods_with_softdep_to_load.emplace_back(it_mod);
+ }
+ }
+
+ // Load independent modules in parallel
+ auto thread_function = [&] {
+ std::unique_lock lk(vector_lock);
+ while (!mods_path_to_load.empty()) {
+ auto mod_path_to_load = std::move(mods_path_to_load.back());
+ mods_path_to_load.pop_back();
+
+ lk.unlock();
+ ret &= Insmod(mod_path_to_load, "");
+ lk.lock();
+ }
+ };
+
+ std::generate_n(std::back_inserter(threads), num_threads,
+ [&] { return std::thread(thread_function); });
+
+ // Wait for the threads.
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ // Since we cannot assure if these soft dependencies tree are overlap,
+ // we loaded these modules one by one.
+ for (auto dep = mods_with_softdep_to_load.rbegin(); dep != mods_with_softdep_to_load.rend();
+ dep++) {
+ ret &= LoadWithAliases(*dep, true);
+ }
+
+ std::lock_guard guard(module_loaded_lock_);
+ // Remove loaded module form mod_with_deps and soft dependencies of other modules
+ for (const auto& module_loaded : module_loaded_) {
+ mod_with_deps.erase(module_loaded);
+
+ for (auto& [mod, softdeps] : mod_with_softdeps) {
+ softdeps.erase(module_loaded);
+ }
+ }
+
+ // Remove loaded module form dependencies of other modules which are not loaded yet
+ for (const auto& module_loaded_path : module_loaded_paths_) {
+ for (auto& [mod, deps] : mod_with_deps) {
+ deps.erase(module_loaded_path);
+ }
+ }
+ }
+
+ return ret;
+}
+
bool Modprobe::LoadListedModules(bool strict) {
auto ret = true;
for (const auto& module : module_load_) {
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index fb1f5e7..94a1dc4 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -54,6 +54,8 @@
if (ret != 0) {
if (errno == EEXIST) {
// Module already loaded
+ std::lock_guard guard(module_loaded_lock_);
+ module_loaded_paths_.emplace(path_name);
module_loaded_.emplace(canonical_name);
return true;
}
@@ -62,6 +64,8 @@
}
LOG(INFO) << "Loaded kernel module " << path_name;
+ std::lock_guard guard(module_loaded_lock_);
+ module_loaded_paths_.emplace(path_name);
module_loaded_.emplace(canonical_name);
module_count_++;
return true;
@@ -74,6 +78,7 @@
PLOG(ERROR) << "Failed to remove module '" << module_name << "'";
return false;
}
+ std::lock_guard guard(module_loaded_lock_);
module_loaded_.erase(canonical_name);
return true;
}
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index f960b61..f92a2b6 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -188,10 +188,11 @@
EXPECT_TRUE(modules_loaded == expected_after_remove);
- m = Modprobe({dir.path});
- EXPECT_FALSE(m.LoadWithAliases("test4", true));
- while (modules_loaded.size() > 0) EXPECT_TRUE(m.Remove(modules_loaded.front()));
- EXPECT_TRUE(m.LoadListedModules());
+ Modprobe m2({dir.path});
+
+ EXPECT_FALSE(m2.LoadWithAliases("test4", true));
+ while (modules_loaded.size() > 0) EXPECT_TRUE(m2.Remove(modules_loaded.front()));
+ EXPECT_TRUE(m2.LoadListedModules());
GTEST_LOG_(INFO) << "Expected modules loaded after enabling blocklist (in order):";
for (auto i = expected_modules_blocklist_enabled.begin();
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 96b5537..b0fcb5f 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -69,6 +69,23 @@
return true;
}
+static bool CgroupGetMemcgAppsPath(std::string* path) {
+ CgroupController controller = CgroupMap::GetInstance().FindController("memory");
+
+ if (!controller.HasValue()) {
+ return false;
+ }
+
+ if (path) {
+ *path = controller.path();
+ if (controller.version() == 1) {
+ *path += "/apps";
+ }
+ }
+
+ return true;
+}
+
bool CgroupGetControllerFromPath(const std::string& path, std::string* cgroup_name) {
auto controller = CgroupMap::GetInstance().FindControllerByPath(path);
@@ -199,13 +216,13 @@
LOG(VERBOSE) << "removeAllProcessGroups()";
std::vector<std::string> cgroups;
- std::string path;
+ std::string path, memcg_apps_path;
if (CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &path)) {
cgroups.push_back(path);
}
- if (CgroupGetControllerPath("memory", &path)) {
- cgroups.push_back(path + "/apps");
+ if (CgroupGetMemcgAppsPath(&memcg_apps_path) && memcg_apps_path != path) {
+ cgroups.push_back(memcg_apps_path);
}
for (std::string cgroup_root_path : cgroups) {
@@ -411,10 +428,11 @@
int err = RemoveProcessGroup(cgroup, uid, initialPid, retries);
if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
- std::string memory_path;
- CgroupGetControllerPath("memory", &memory_path);
- memory_path += "/apps";
- if (RemoveProcessGroup(memory_path.c_str(), uid, initialPid, retries)) return -1;
+ std::string memcg_apps_path;
+ if (CgroupGetMemcgAppsPath(&memcg_apps_path) &&
+ RemoveProcessGroup(memcg_apps_path.c_str(), uid, initialPid, retries) < 0) {
+ return -1;
+ }
}
return err;
@@ -491,10 +509,12 @@
return -EINVAL;
}
- if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
- CgroupGetControllerPath("memory", &cgroup);
- cgroup += "/apps";
- int ret = createProcessGroupInternal(uid, initialPid, cgroup, false);
+ if (std::string memcg_apps_path;
+ isMemoryCgroupSupported() && UsePerAppMemcg() && CgroupGetMemcgAppsPath(&memcg_apps_path)) {
+ // Note by bvanassche: passing 'false' as fourth argument below implies that the v1
+ // hierarchy is used. It is not clear to me whether the above conditions guarantee that the
+ // v1 hierarchy is used.
+ int ret = createProcessGroupInternal(uid, initialPid, memcg_apps_path, false);
if (ret != 0) {
return ret;
}
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index b668dcb..7e03964 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -16,14 +16,21 @@
"File": "top-app/cpus"
},
{
+ "Name": "MemStats",
+ "Controller": "memory",
+ "File": "memory.stat"
+ },
+ {
"Name": "MemLimit",
"Controller": "memory",
- "File": "memory.limit_in_bytes"
+ "File": "memory.limit_in_bytes",
+ "FileV2": "memory.max"
},
{
"Name": "MemSoftLimit",
"Controller": "memory",
- "File": "memory.soft_limit_in_bytes"
+ "File": "memory.soft_limit_in_bytes",
+ "FileV2": "memory.low"
},
{
"Name": "MemSwappiness",
@@ -31,6 +38,26 @@
"File": "memory.swappiness"
},
{
+ "Name": "MemUsage",
+ "Controller": "memory",
+ "File": "memory.usage_in_bytes"
+ },
+ {
+ "Name": "MemAndSwapUsage",
+ "Controller": "memory",
+ "File": "memory.memsw.usage_in_bytes"
+ },
+ {
+ "Name": "MemPressureLevel",
+ "Controller": "memory",
+ "File": "memory.pressure_level"
+ },
+ {
+ "Name": "MemCgroupEventControl",
+ "Controller": "memory",
+ "File": "cgroup.event_control"
+ },
+ {
"Name": "UClampMin",
"Controller": "cpu",
"File": "cpu.uclamp.min"
diff --git a/libprocessgroup/profiles/task_profiles.proto b/libprocessgroup/profiles/task_profiles.proto
index 2a09217..ebcd9b5 100644
--- a/libprocessgroup/profiles/task_profiles.proto
+++ b/libprocessgroup/profiles/task_profiles.proto
@@ -25,12 +25,13 @@
repeated AggregateProfiles aggregateprofiles = 3 [json_name = "AggregateProfiles"];
}
-// Next: 5
+// Next: 6
message Attribute {
string name = 1 [json_name = "Name"];
string controller = 2 [json_name = "Controller"];
string file = 3 [json_name = "File"];
- string optional = 4 [json_name = "Optional"];
+ string filev2 = 4 [json_name = "FileV2"];
+ string optional = 5 [json_name = "Optional"];
}
// Next: 3
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index 3121d24..992cc2e 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -263,8 +263,18 @@
return false;
}
- result = mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
- nullptr);
+ // The memory_recursiveprot mount option has been introduced by kernel commit
+ // 8a931f801340 ("mm: memcontrol: recursive memory.low protection"; v5.7). Try first to
+ // mount with that option enabled. If mounting fails because the kernel is too old,
+ // retry without that mount option.
+ if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+ "memory_recursiveprot") < 0) {
+ LOG(INFO) << "Mounting memcg with memory_recursiveprot failed. Retrying without.";
+ if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+ nullptr) < 0) {
+ PLOG(ERROR) << "Failed to mount cgroup v2";
+ }
+ }
// selinux permissions change after mounting, so it's ok to change mode and owner now
if (!ChangeDirModeAndOwner(controller->path(), descriptor.mode(), descriptor.uid(),
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 4a2bf38..78a316a 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -129,11 +129,12 @@
return true;
}
+ const std::string& file_name =
+ controller()->version() == 2 && !file_v2_name_.empty() ? file_v2_name_ : file_name_;
if (subgroup.empty()) {
- *path = StringPrintf("%s/%s", controller()->path(), file_name_.c_str());
+ *path = StringPrintf("%s/%s", controller()->path(), file_name.c_str());
} else {
- *path = StringPrintf("%s/%s/%s", controller()->path(), subgroup.c_str(),
- file_name_.c_str());
+ *path = StringPrintf("%s/%s/%s", controller()->path(), subgroup.c_str(), file_name.c_str());
}
return true;
}
@@ -633,12 +634,19 @@
std::string name = attr[i]["Name"].asString();
std::string controller_name = attr[i]["Controller"].asString();
std::string file_attr = attr[i]["File"].asString();
+ std::string file_v2_attr = attr[i]["FileV2"].asString();
+
+ if (!file_v2_attr.empty() && file_attr.empty()) {
+ LOG(ERROR) << "Attribute " << name << " has FileV2 but no File property";
+ return false;
+ }
auto controller = cg_map.FindController(controller_name);
if (controller.HasValue()) {
auto iter = attributes_.find(name);
if (iter == attributes_.end()) {
- attributes_[name] = std::make_unique<ProfileAttribute>(controller, file_attr);
+ attributes_[name] =
+ std::make_unique<ProfileAttribute>(controller, file_attr, file_v2_attr);
} else {
iter->second->Reset(controller, file_attr);
}
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 4747511..df08f65 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -37,8 +37,12 @@
class ProfileAttribute : public IProfileAttribute {
public:
- ProfileAttribute(const CgroupController& controller, const std::string& file_name)
- : controller_(controller), file_name_(file_name) {}
+ // Cgroup attributes may have different names in the v1 and v2 hierarchies. If `file_v2_name` is
+ // not empty, `file_name` is the name for the v1 hierarchy and `file_v2_name` is the name for
+ // the v2 hierarchy. If `file_v2_name` is empty, `file_name` is used for both hierarchies.
+ ProfileAttribute(const CgroupController& controller, const std::string& file_name,
+ const std::string& file_v2_name)
+ : controller_(controller), file_name_(file_name), file_v2_name_(file_v2_name) {}
~ProfileAttribute() = default;
const CgroupController* controller() const override { return &controller_; }
@@ -50,6 +54,7 @@
private:
CgroupController controller_;
std::string file_name_;
+ std::string file_v2_name_;
};
// Abstract profile element
diff --git a/rootdir/etc/TEST_MAPPING b/rootdir/etc/TEST_MAPPING
index e4d3d5e..1c7b716 100644
--- a/rootdir/etc/TEST_MAPPING
+++ b/rootdir/etc/TEST_MAPPING
@@ -3,5 +3,10 @@
{
"name": "CtsBionicTestCases"
}
+ ],
+ "hwasan-postsubmit": [
+ {
+ "name": "CtsBionicTestCases"
+ }
]
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 404d7ae..7ad1c3c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1008,12 +1008,6 @@
# module, delete if not.
exec - system system -- /system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo
- # If there is no post-fs-data action in the init.<device>.rc file, you
- # must uncomment this line, otherwise encrypted filesystems
- # won't work.
- # Set indication (checked by vold) that we have finished this action
- #setprop vold.post_fs_data_done 1
-
# sys.memfd_use set to false by default, which keeps it disabled
# until it is confirmed that apps and vendor processes don't make
# IOCTLs on ashmem fds any more.
diff --git a/trusty/keymaster/keymint/TEST_MAPPING b/trusty/keymaster/keymint/TEST_MAPPING
index 2400ccd..ae24fb4 100644
--- a/trusty/keymaster/keymint/TEST_MAPPING
+++ b/trusty/keymaster/keymint/TEST_MAPPING
@@ -3,5 +3,10 @@
{
"name" : "vts_treble_vintf_framework_test"
}
+ ],
+ "hwasan-postsubmit" : [
+ {
+ "name" : "vts_treble_vintf_framework_test"
+ }
]
}
\ No newline at end of file