Merge "[owners] Remove eugenis@google.com from init/test_upgrade_mte/OWNERS" into main
diff --git a/bootstat/OWNERS b/bootstat/OWNERS
index f66b309..71b4e0b 100644
--- a/bootstat/OWNERS
+++ b/bootstat/OWNERS
@@ -1,2 +1,3 @@
-jhawkins@google.com
dvander@google.com
+achant@google.com
+markcheng@google.com
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index d476d36..96c5b81 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -467,8 +467,9 @@
{"reboot,longkey,master_dc", 235},
{"reboot,ocp2,pmic,if", 236},
{"reboot,ocp,pmic,if", 237},
- {"reboot,fship", 238},
+ {"reboot,fship.*", 238},
{"reboot,ocp,.*", 239},
+ {"reboot,ntc,pmic,sub", 240},
};
// Converts a string value representing the reason the system booted to an
@@ -912,6 +913,19 @@
void BootReasonAddToHistory(const std::string& system_boot_reason) {
if (system_boot_reason.empty()) return;
LOG(INFO) << "Canonical boot reason: " << system_boot_reason;
+
+ // skip system_boot_reason(factory_reset, ota) shift since device boot up from shipmode
+ const auto bootloader_boot_reason =
+ android::base::GetProperty(bootloader_reboot_reason_property, "");
+ const char reg_fship[] = ".*fship.*";
+ if (std::regex_search(bootloader_boot_reason, std::regex(reg_fship)) != 0) {
+ if (system_boot_reason == "reboot,factory_reset" || system_boot_reason == "reboot,ota") {
+ LOG(INFO) << "skip boot reason (" << system_boot_reason
+ << ") shift since device boot up from shipmode.";
+ return;
+ }
+ }
+
auto old_system_boot_reason = android::base::GetProperty(system_reboot_reason_property, "");
if (!android::base::SetProperty(system_reboot_reason_property, system_boot_reason)) {
android::base::SetProperty(system_reboot_reason_property,
@@ -953,6 +967,14 @@
std::string BootReasonStrToReason(const std::string& boot_reason) {
auto ret = android::base::GetProperty(system_reboot_reason_property, "");
std::string reason(boot_reason);
+
+ // skip BootReasonStrToReason() if device boot up from shipmode
+ const char reg_fship[] = ".*fship.*";
+ if (reason == ret && std::regex_search(reason, std::regex(reg_fship)) != 0) {
+ LOG(INFO) << "skip boot reason enhancement if device boot up from shipmode";
+ return ret;
+ }
+
// If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
if (reason == ret) ret = "";
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 7d3830c..92d81b3 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -451,10 +451,8 @@
return false;
}
#elif defined(__arm__)
- if (ptrace(PTRACE_GET_THREAD_AREA, tid, nullptr, &base) == 0) {
- PLOG(ERROR) << "failed to get thread area for thread " << tid;
- return false;
- }
+ // Arm doesn't support any guest architectures yet.
+ return false;
#elif defined(__i386__)
struct user_regs_struct regs;
struct iovec pt_iov = {.iov_base = ®s, .iov_len = sizeof(regs)};
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 4c6a400..3af806b 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -15,7 +15,6 @@
"-fstack-protector-all",
"-Wno-date-time",
],
- tidy: false, // crasher.cpp tests many memory access errors
srcs: ["crasher.cpp"],
arch: {
arm: {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
index d47f2dd..12a425e 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <map>
+#include <memory>
#include <optional>
#include <string>
#include <utility>
diff --git a/debuggerd/test_permissive_mte/Android.bp b/debuggerd/test_permissive_mte/Android.bp
index f333242..4403b8a 100644
--- a/debuggerd/test_permissive_mte/Android.bp
+++ b/debuggerd/test_permissive_mte/Android.bp
@@ -18,7 +18,6 @@
cc_binary {
name: "mte_crash",
- tidy: false,
srcs: ["mte_crash.cpp"],
sanitize: {
memtag_heap: true,
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index d3e0581..6e47a08 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -307,12 +307,6 @@
generated_headers: ["platform_tools_version"],
- tidy_flags: [
- // DO NOT add quotes around header-filter flag regex argument,
- // because build/soong will add quotes around the whole flag.
- "-header-filter=(system/core/fastboot/|development/host/windows/usb/api/)",
- ],
-
target: {
windows: {
srcs: ["usb_windows.cpp"],
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 156dc3b..1c52da2 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -638,7 +638,10 @@
" --disable-verification Sets disable-verification when flashing vbmeta.\n"
" --disable-super-optimization\n"
" Disables optimizations on flashing super partition.\n"
- " --disable-fastboot-info Will collects tasks from image list rather than $OUT/fastboot-info.txt.\n"
+ " --exclude-dynamic-partitions\n"
+ " Excludes flashing of dynamic partitions.\n"
+ " --disable-fastboot-info Will collects tasks from image list rather than \n"
+ " $OUT/fastboot-info.txt.\n"
" --fs-options=OPTION[,OPTION]\n"
" Enable filesystem features. OPTION supports casefold, projid, compress\n"
// TODO: remove --unbuffered?
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 79f3939..9eabbd3 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -33,6 +33,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
+#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <fstream>
diff --git a/fastboot/fuzzy_fastboot/test_utils.cpp b/fastboot/fuzzy_fastboot/test_utils.cpp
index 9ad98be..b80db23 100644
--- a/fastboot/fuzzy_fastboot/test_utils.cpp
+++ b/fastboot/fuzzy_fastboot/test_utils.cpp
@@ -28,6 +28,8 @@
#include "test_utils.h"
#include <fcntl.h>
#include <termios.h>
+#include <algorithm>
+#include <iterator>
#include <sstream>
namespace fastboot {
diff --git a/fastboot/fuzzy_fastboot/transport_sniffer.cpp b/fastboot/fuzzy_fastboot/transport_sniffer.cpp
index 0aef350..fffa9a2 100644
--- a/fastboot/fuzzy_fastboot/transport_sniffer.cpp
+++ b/fastboot/fuzzy_fastboot/transport_sniffer.cpp
@@ -3,6 +3,7 @@
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <algorithm>
#include <iomanip>
#include <sstream>
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9f52f44..275bc80 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -858,6 +858,10 @@
if (!android::base::Realpath(source, &real_source)) {
real_source = source;
}
+
+ // Clear errno prior to calling `mount`, to avoid clobbering with any errno that
+ // may have been set from prior calls (e.g. realpath).
+ errno = 0;
ret = mount(real_source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
opts.c_str());
save_errno = errno;
@@ -2331,6 +2335,11 @@
if (!fs_mgr_filesystem_available("overlay")) {
return {.supported = false};
}
+
+ if (!use_override_creds) {
+ return {.supported = true, ",userxattr"};
+ }
+
struct utsname uts;
if (uname(&uts) == -1) {
return {.supported = false};
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index bf68b2c..253013b 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -43,5 +43,11 @@
// overlays if any partition is flashed or updated.
void TeardownAllOverlayForMountPoint(const std::string& mount_point = {});
+// Are we using overlayfs's non-upstreamed override_creds feature?
+// b/388912628 removes the need for override_creds
+// Once this bug is fixed and has had enough soak time, remove this variable and hard code to false
+// where it used
+constexpr bool use_override_creds = false;
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/fuzzer/liblp_builder_fuzzer.cpp b/fs_mgr/liblp/fuzzer/liblp_builder_fuzzer.cpp
index 162c9fc..2e59332 100644
--- a/fs_mgr/liblp/fuzzer/liblp_builder_fuzzer.cpp
+++ b/fs_mgr/liblp/fuzzer/liblp_builder_fuzzer.cpp
@@ -15,6 +15,7 @@
*
*/
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
#include <liblp/builder.h>
#include <liblp/property_fetcher.h>
diff --git a/fs_mgr/liblp/fuzzer/liblp_super_layout_builder_fuzzer.cpp b/fs_mgr/liblp/fuzzer/liblp_super_layout_builder_fuzzer.cpp
index a6642d7..a93e68e 100644
--- a/fs_mgr/liblp/fuzzer/liblp_super_layout_builder_fuzzer.cpp
+++ b/fs_mgr/liblp/fuzzer/liblp_super_layout_builder_fuzzer.cpp
@@ -17,6 +17,7 @@
#include <android-base/unique_fd.h>
#include <fcntl.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
#include <liblp/metadata_format.h>
#include <liblp/super_layout_builder.h>
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index b5b976a..af1991a 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -308,17 +308,15 @@
"vts",
"general-tests",
],
- compile_multilib: "both",
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
+ compile_multilib: "first",
test_options: {
min_shipping_api_level: 30,
+ test_runner_options: [
+ {
+ name: "force-no-test-error",
+ value: "false",
+ },
+ ],
},
}
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index 6516499..127735d 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -17,6 +17,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <algorithm>
#include <optional>
#include <unordered_map>
#include <unordered_set>
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/create_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/create_cow.cpp
index fd4e7da..b15e6ab 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/create_cow.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/create_cow.cpp
@@ -36,6 +36,10 @@
DEFINE_string(source, "", "Source partition image");
DEFINE_string(target, "", "Target partition image");
+DEFINE_string(
+ output_dir, "",
+ "Output directory to write the patch file to. Defaults to current working directory if "
+ "not set.");
DEFINE_string(compression, "lz4",
"Compression algorithm. Default is set to lz4. Available options: lz4, zstd, gz");
DEFINE_bool(merkel_tree, false, "If true, source image hash is obtained from verity merkel tree");
@@ -474,11 +478,12 @@
if (create_snapshot_patch_ && use_merkel_tree_) {
std::vector<uint8_t> digest(32, 0);
- CalculateDigest(bufptr, BLOCK_SZ, target_salt_.data(), target_salt_.size(),
+ CalculateDigest(bufptr, BLOCK_SZ, source_salt_.data(), source_salt_.size(),
digest.data());
std::vector<uint8_t> final_digest(32, 0);
- CalculateDigest(digest.data(), digest.size(), source_salt_.data(),
- source_salt_.size(), final_digest.data());
+ CalculateDigest(digest.data(), digest.size(), target_salt_.data(),
+ target_salt_.size(), final_digest.data());
+
hash = ToHexString(final_digest.data(), final_digest.size());
} else {
uint8_t checksum[32];
@@ -569,12 +574,15 @@
source.img -> Source partition image
target.img -> Target partition image
- compressoin -> compression algorithm. Default set to lz4. Supported types are gz, lz4, zstd.
+ compression -> compression algorithm. Default set to lz4. Supported types are gz, lz4, zstd.
+ merkel_tree -> If true, source image hash is obtained from verity merkel tree.
+ output_dir -> Output directory to write the patch file to. Defaults to current working directory if not set.
EXAMPLES
$ create_snapshot $SOURCE_BUILD/system.img $TARGET_BUILD/system.img
$ create_snapshot $SOURCE_BUILD/product.img $TARGET_BUILD/product.img --compression="zstd"
+ $ create_snapshot $SOURCE_BUILD/product.img $TARGET_BUILD/product.img --merkel_tree --output_dir=/tmp/create_snapshot_output
)";
@@ -591,6 +599,9 @@
std::string fname = android::base::Basename(FLAGS_target.c_str());
auto parts = android::base::Split(fname, ".");
std::string snapshotfile = parts[0] + ".patch";
+ if (!FLAGS_output_dir.empty()) {
+ snapshotfile = FLAGS_output_dir + "/" + snapshotfile;
+ }
android::snapshot::CreateSnapshot snapshot(FLAGS_source, FLAGS_target, snapshotfile,
FLAGS_compression, FLAGS_merkel_tree);
diff --git a/fs_mgr/libsnapshot/scratch_super.cpp b/fs_mgr/libsnapshot/scratch_super.cpp
index 2036905..2d19123 100644
--- a/fs_mgr/libsnapshot/scratch_super.cpp
+++ b/fs_mgr/libsnapshot/scratch_super.cpp
@@ -396,7 +396,7 @@
}
// Entry point to create a scratch device on super partition
-// This will create a 1MB space in super. The space will be
+// This will create a 2MB space in super. The space will be
// from the current active slot. Ext4 filesystem will be created
// on this scratch device and all the OTA related directories
// will be created.
diff --git a/fs_mgr/libsnapshot/scratch_super.h b/fs_mgr/libsnapshot/scratch_super.h
index 3e6fe70..7a16f97 100644
--- a/fs_mgr/libsnapshot/scratch_super.h
+++ b/fs_mgr/libsnapshot/scratch_super.h
@@ -20,7 +20,7 @@
constexpr char kMkExt4[] = "/system/bin/mke2fs";
constexpr char kOtaMetadataFileContext[] = "u:object_r:ota_metadata_file:s0";
constexpr char kOtaMetadataMount[] = "/mnt/scratch_ota_metadata_super";
-const size_t kOtaMetadataPartitionSize = uint64_t(1 * 1024 * 1024);
+const size_t kOtaMetadataPartitionSize = uint64_t(2 * 1024 * 1024);
constexpr char kPhysicalDevice[] = "/dev/block/by-name/";
bool IsScratchOtaMetadataOnSuper();
diff --git a/fs_mgr/libsnapshot/scripts/apply-update.sh b/fs_mgr/libsnapshot/scripts/apply-update.sh
index 0b10721..2a5a8a2 100755
--- a/fs_mgr/libsnapshot/scripts/apply-update.sh
+++ b/fs_mgr/libsnapshot/scripts/apply-update.sh
@@ -52,13 +52,16 @@
# Function to flash static partitions
flash_static_partitions() {
local wipe_flag="$1"
+ local flash_bootloader="$2"
- fastboot flash bootloader "$OUT"/bootloader.img
- fastboot reboot bootloader
- sleep 1
- fastboot flash radio "$OUT"/radio.img
- fastboot reboot bootloader
- sleep 1
+ if (( flash_bootloader )); then
+ fastboot flash bootloader "$OUT"/bootloader.img
+ fastboot reboot bootloader
+ sleep 1
+ fastboot flash radio "$OUT"/radio.img
+ fastboot reboot bootloader
+ sleep 1
+ fi
fastboot flashall --exclude-dynamic-partitions --disable-super-optimization --skip-reboot
if (( wipe_flag )); then
@@ -120,6 +123,7 @@
}
skip_static_partitions=0
+flash_bootloader=1
wipe_flag=0
help_flag=0
@@ -132,6 +136,9 @@
--wipe)
wipe_flag=1
;;
+ --skip_bootloader)
+ flash_bootloader=0
+ ;;
--help)
help_flag=1
;;
@@ -214,7 +221,7 @@
log_message "Rebooting device to bootloader"
adb reboot bootloader
log_message "Waiting to enter fastboot bootloader"
- flash_static_partitions "$wipe_flag"
+ flash_static_partitions "$wipe_flag" "$flash_bootloader"
fi
log_message "Update completed"
diff --git a/fs_mgr/libsnapshot/snapuserd/testing/dm_user_harness.h b/fs_mgr/libsnapshot/snapuserd/testing/dm_user_harness.h
index cf26bed..507e8f3 100644
--- a/fs_mgr/libsnapshot/snapuserd/testing/dm_user_harness.h
+++ b/fs_mgr/libsnapshot/snapuserd/testing/dm_user_harness.h
@@ -19,13 +19,13 @@
#include "harness.h"
#include "temp_device.h"
+#include <snapuserd/dm_user_block_server.h>
+
namespace android {
namespace snapshot {
using android::base::unique_fd;
-class DmUserBlockServerFactory;
-
class DmUserDevice final : public IUserDevice {
public:
explicit DmUserDevice(std::unique_ptr<Tempdevice>&& dev);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
index ecf5d5c..c6301d4 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -15,6 +15,7 @@
#pragma once
#include <memory>
+#include <mutex>
#include <queue>
#include <string>
#include <thread>
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 526c761..139ac92 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1360,6 +1360,14 @@
# Properties added by adb remount test
test.adb.remount.system.build.prop=true
EOF
+
+# Move /system/build.prop to make sure we can move and then replace files
+# Note that as of kernel 6.1 mv creates the char_file that whites out the lower
+# file with different selabels than rm does
+# See b/394290609
+adb shell mv /system/build.prop /system/build.prop.backup >/dev/null ||
+ die "adb shell rm /system/build.prop"
+
adb push "${system_build_prop_modified}" /system/build.prop >/dev/null ||
die "adb push /system/build.prop"
adb pull /system/build.prop "${system_build_prop_fromdevice}" >/dev/null ||
diff --git a/init/Android.bp b/init/Android.bp
index ed19b4b..dbdf80b 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -136,6 +136,8 @@
"-DWORLD_WRITABLE_KMSG=1",
"-UDUMP_ON_UMOUNT_FAILURE",
"-DDUMP_ON_UMOUNT_FAILURE=1",
+ "-UALLOW_REMOUNT_OVERLAYS",
+ "-DALLOW_REMOUNT_OVERLAYS=1",
],
},
eng: {
@@ -263,7 +265,10 @@
name: "init",
required: [
"init_second_stage",
- ],
+ ] + select(product_variable("debuggable"), {
+ true: ["overlay_remounter"],
+ false: [],
+ }),
}
cc_defaults {
diff --git a/init/capabilities.h b/init/capabilities.h
index fc80c98..b71d2cb 100644
--- a/init/capabilities.h
+++ b/init/capabilities.h
@@ -18,6 +18,7 @@
#include <sys/capability.h>
#include <bitset>
+#include <memory>
#include <string>
#include <type_traits>
diff --git a/init/devices.cpp b/init/devices.cpp
index aeaa431..cead726 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -599,7 +599,22 @@
PLOG(ERROR) << "Failed to create directory " << Dirname(link);
}
- if (symlink(target.c_str(), link.c_str())) {
+ // Create symlink and make sure it's correctly labeled
+ std::string secontext;
+ // Passing 0 for mode should work.
+ if (SelabelLookupFileContext(link, 0, &secontext) && !secontext.empty()) {
+ setfscreatecon(secontext.c_str());
+ }
+
+ int rc = symlink(target.c_str(), link.c_str());
+
+ if (!secontext.empty()) {
+ int save_errno = errno;
+ setfscreatecon(nullptr);
+ errno = save_errno;
+ }
+
+ if (rc < 0) {
if (errno != EEXIST) {
PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link;
} else if (std::string link_path;
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index e06a645..6bb0ad7 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -402,7 +402,7 @@
// /second_stage_resources is used to preserve files from first to second
// stage init
- CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+ CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
diff --git a/init/libprefetch/prefetch/prefetch.rc b/init/libprefetch/prefetch/prefetch.rc
index fb3fb3b..dee37bb 100644
--- a/init/libprefetch/prefetch/prefetch.rc
+++ b/init/libprefetch/prefetch/prefetch.rc
@@ -8,7 +8,7 @@
disabled
oneshot
-on property:ro.prefetch_boot.record=true
+on property:prefetch_boot.record=true
start prefetch_record
service prefetch_record /system/bin/prefetch record --duration ${ro.prefetch_boot.duration_s:-0}
@@ -18,7 +18,7 @@
disabled
oneshot
-on property:ro.prefetch_boot.replay=true
+on property:prefetch_boot.replay=true
start prefetch_replay
service prefetch_replay /system/bin/prefetch replay --io-depth ${ro.prefetch_boot.io_depth:-2} --max-fds ${ro.prefetch_boot.max_fds:-128}
diff --git a/init/libprefetch/prefetch/src/arch/android.rs b/init/libprefetch/prefetch/src/arch/android.rs
index 3404e42..a11767e 100644
--- a/init/libprefetch/prefetch/src/arch/android.rs
+++ b/init/libprefetch/prefetch/src/arch/android.rs
@@ -13,7 +13,7 @@
const PREFETCH_RECORD_PROPERTY: &str = "prefetch_boot.record";
const PREFETCH_REPLAY_PROPERTY: &str = "prefetch_boot.replay";
-const PREFETCH_RECORD_PROPERTY_STOP: &str = "ro.prefetch_boot.record_stop";
+const PREFETCH_RECORD_PROPERTY_STOP: &str = "prefetch_boot.record_stop";
fn wait_for_property_true(
property_name: &str,
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 31af94e..83e9a0d 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -103,8 +103,6 @@
namespace android {
namespace init {
-class PersistWriteThread;
-
constexpr auto FINGERPRINT_PROP = "ro.build.fingerprint";
constexpr auto LEGACY_FINGERPRINT_PROP = "ro.build.legacy.fingerprint";
constexpr auto ID_PROP = "ro.build.id";
@@ -122,8 +120,6 @@
static std::thread property_service_thread;
static std::thread property_service_for_system_thread;
-static std::unique_ptr<PersistWriteThread> persist_write_thread;
-
static PropertyInfoAreaFile property_info_area;
struct PropertyAuditData {
@@ -384,6 +380,8 @@
std::deque<std::tuple<std::string, std::string, SocketConnection>> work_;
};
+static std::unique_ptr<PersistWriteThread> persist_write_thread;
+
static std::optional<uint32_t> PropertySet(const std::string& name, const std::string& value,
SocketConnection* socket, std::string* error) {
size_t valuelen = value.size();
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 6316b4d..8bdf5b6 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -69,6 +69,7 @@
#include <android/avf_cc_flags.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
+#include <fs_mgr_overlayfs.h>
#include <genfslabelsversion.h>
#include <libgsi/libgsi.h>
#include <libsnapshot/snapshot.h>
@@ -77,6 +78,7 @@
#include "block_dev_initializer.h"
#include "debug_ramdisk.h"
#include "reboot_utils.h"
+#include "second_stage_resources.h"
#include "snapuserd_transition.h"
#include "util.h"
@@ -698,6 +700,65 @@
}
}
+#ifdef ALLOW_REMOUNT_OVERLAYS
+void SetupOverlays() {
+ if (android::fs_mgr::use_override_creds) return;
+
+ bool has_overlays = false;
+ std::string contents;
+ auto result = android::base::ReadFileToString("/proc/mounts", &contents, true);
+
+ auto lines = android::base::Split(contents, "\n");
+ for (auto const& line : lines)
+ if (android::base::StartsWith(line, "overlay")) {
+ has_overlays = true;
+ break;
+ }
+
+ if (!has_overlays) return;
+
+ // After adb remount, we mount all r/o volumes with overlayfs to allow writing.
+ // However, since overlayfs performs its file operations in the context of the
+ // mounting process, this will not work as is - init is in the kernel domain in
+ // first stage, which has very limited permissions.
+
+ // In order to fix this, we need to unmount remount all these volumes from a process
+ // with sufficient privileges to be able to perform these operations. The
+ // overlay_remounter domain has those privileges on debuggable devices.
+ // We will call overlay_remounter which will do the unmounts/mounts.
+ // But for that to work, the volumes must not be busy, so we need to copy
+ // overlay_remounter from system to a ramdisk and run it from there.
+
+ const char* kOverlayRemounter = "overlay_remounter";
+ auto or_src = std::filesystem::path("/system/xbin/") / kOverlayRemounter;
+ auto or_dest = std::filesystem::path(kSecondStageRes) / kOverlayRemounter;
+ std::error_code ec;
+ std::filesystem::copy(or_src, or_dest, ec);
+ if (ec) {
+ LOG(FATAL) << "Failed to copy " << or_src << " to " << or_dest << " " << ec.message();
+ }
+
+ if (selinux_android_restorecon(or_dest.c_str(), 0) == -1) {
+ PLOG(FATAL) << "restorecon of " << or_dest << " failed";
+ }
+ auto dest = unique_fd(open(or_dest.c_str(), O_RDONLY | O_CLOEXEC));
+ if (dest.get() == -1) {
+ PLOG(FATAL) << "Failed to reopen " << or_dest;
+ }
+ if (unlink(or_dest.c_str()) == -1) {
+ PLOG(FATAL) << "Failed to unlink " << or_dest;
+ }
+ const char* args[] = {or_dest.c_str(), nullptr};
+ fexecve(dest.get(), const_cast<char**>(args), nullptr);
+
+ // execv() only returns if an error happened, in which case we
+ // panic and never return from this function.
+ PLOG(FATAL) << "execv(\"" << or_dest << "\") failed";
+}
+#else
+void SetupOverlays() {}
+#endif
+
int SetupSelinux(char** argv) {
SetStdioToDevNull(argv);
InitKernelLogging(argv);
@@ -738,6 +799,10 @@
setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);
+ // SetupOverlays does not return if overlays exist, instead it execs overlay_remounter
+ // which then execs second stage init
+ SetupOverlays();
+
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 4c31718..bd69300 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -315,6 +315,7 @@
}
Result<void> ServiceParser::ParseMemcgSwappiness(std::vector<std::string>&& args) {
+ LOG(WARNING) << "memcg.swappiness is unsupported with memcg v2 and will be deprecated";
if (!ParseInt(args[1], &service_->swappiness_, 0)) {
return Error() << "swappiness value must be equal or greater than 0";
}
diff --git a/init/ueventd_test.cpp b/init/ueventd_test.cpp
index 1ac6d8e..5921ece 100644
--- a/init/ueventd_test.cpp
+++ b/init/ueventd_test.cpp
@@ -19,6 +19,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <algorithm>
#include <atomic>
#include <chrono>
#include <string>
diff --git a/libcutils/android_get_control_file_test.cpp b/libcutils/android_get_control_file_test.cpp
index 8de8530..e57af5e 100644
--- a/libcutils/android_get_control_file_test.cpp
+++ b/libcutils/android_get_control_file_test.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <time.h>
+#include <algorithm>
#include <string>
#include <android-base/file.h>
diff --git a/libcutils/ashmem_base_test.cpp b/libcutils/ashmem_base_test.cpp
index c9b14e5..d60a973 100644
--- a/libcutils/ashmem_base_test.cpp
+++ b/libcutils/ashmem_base_test.cpp
@@ -16,6 +16,8 @@
#include <gtest/gtest.h>
+#include <algorithm>
+
#include <unistd.h>
#include <android-base/mapped_file.h>
diff --git a/libcutils/ashmem_test.cpp b/libcutils/ashmem_test.cpp
index ccbb8c9..96f20db 100644
--- a/libcutils/ashmem_test.cpp
+++ b/libcutils/ashmem_test.cpp
@@ -31,7 +31,7 @@
using android::base::unique_fd;
-void TestCreateRegion(size_t size, unique_fd &fd, int prot) {
+static void TestCreateRegion(size_t size, unique_fd &fd, int prot) {
fd = unique_fd(ashmem_create_region(nullptr, size));
ASSERT_TRUE(fd >= 0);
ASSERT_TRUE(ashmem_valid(fd));
@@ -44,63 +44,75 @@
ASSERT_EQ(FD_CLOEXEC, (fcntl(fd, F_GETFD) & FD_CLOEXEC));
}
-void TestMmap(const unique_fd& fd, size_t size, int prot, void** region, off_t off = 0) {
+static void TestMmap(const unique_fd& fd, size_t size, int prot, void** region, off_t off = 0) {
ASSERT_TRUE(fd >= 0);
ASSERT_TRUE(ashmem_valid(fd));
*region = mmap(nullptr, size, prot, MAP_SHARED, fd, off);
ASSERT_NE(MAP_FAILED, *region);
}
-void TestProtDenied(const unique_fd &fd, size_t size, int prot) {
+static void TestProtDenied(const unique_fd &fd, size_t size, int prot) {
ASSERT_TRUE(fd >= 0);
ASSERT_TRUE(ashmem_valid(fd));
EXPECT_EQ(MAP_FAILED, mmap(nullptr, size, prot, MAP_SHARED, fd, 0));
}
-void TestProtIs(const unique_fd& fd, int prot) {
+static void TestProtIs(const unique_fd& fd, int prot) {
ASSERT_TRUE(fd >= 0);
ASSERT_TRUE(ashmem_valid(fd));
EXPECT_EQ(prot, ioctl(fd, ASHMEM_GET_PROT_MASK));
}
-void FillData(std::vector<uint8_t>& data) {
+static void FillData(std::vector<uint8_t>& data) {
for (size_t i = 0; i < data.size(); i++) {
data[i] = i & 0xFF;
}
}
-TEST(AshmemTest, ForkTest) {
- const size_t size = getpagesize();
+static void waitForChildProcessExit(pid_t pid) {
+ int exitStatus;
+ pid_t childPid = waitpid(pid, &exitStatus, 0);
+
+ ASSERT_GT(childPid, 0);
+ ASSERT_TRUE(WIFEXITED(exitStatus));
+ ASSERT_EQ(0, WEXITSTATUS(exitStatus));
+}
+
+static void ForkTest(const unique_fd &fd, size_t size) {
+ void* region1 = nullptr;
std::vector<uint8_t> data(size);
FillData(data);
- unique_fd fd;
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
-
- void* region1 = nullptr;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1));
memcpy(region1, data.data(), size);
ASSERT_EQ(0, memcmp(region1, data.data(), size));
EXPECT_EQ(0, munmap(region1, size));
- ASSERT_EXIT(
- {
- if (!ashmem_valid(fd)) {
- _exit(3);
- }
- void* region2 = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (region2 == MAP_FAILED) {
- _exit(1);
- }
- if (memcmp(region2, data.data(), size) != 0) {
- _exit(2);
- }
- memset(region2, 0, size);
- munmap(region2, size);
- _exit(0);
- },
- ::testing::ExitedWithCode(0), "");
+
+ pid_t pid = fork();
+ if (!pid) {
+ if (!ashmem_valid(fd)) {
+ _exit(3);
+ }
+
+ void *region2 = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (region2 == MAP_FAILED) {
+ _exit(1);
+ } else if (memcmp(region2, data.data(), size) != 0){
+ _exit(2);
+ }
+
+ // Clear the ashmem buffer here to ensure that updates to the contents
+ // of the buffer are visible across processes with a reference to the
+ // buffer.
+ memset(region2, 0, size);
+ munmap(region2, size);
+ _exit(0);
+ } else {
+ ASSERT_GT(pid, 0);
+ ASSERT_NO_FATAL_FAILURE(waitForChildProcessExit(pid));
+ }
memset(data.data(), 0, size);
void *region2;
@@ -109,16 +121,12 @@
EXPECT_EQ(0, munmap(region2, size));
}
-TEST(AshmemTest, FileOperationsTest) {
- unique_fd fd;
+static void FileOperationsTest(const unique_fd &fd, size_t size) {
void* region = nullptr;
- // Allocate a 4-page buffer, but leave page-sized holes on either side
const size_t pageSize = getpagesize();
- const size_t size = pageSize * 4;
const size_t dataSize = pageSize * 2;
const size_t holeSize = pageSize;
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, dataSize, PROT_READ | PROT_WRITE, ®ion, holeSize));
std::vector<uint8_t> data(dataSize);
@@ -171,78 +179,68 @@
EXPECT_EQ(0, munmap(region, dataSize));
}
-TEST(AshmemTest, ProtTest) {
- unique_fd fd;
- const size_t size = getpagesize();
+static void ProtTestROBuffer(const unique_fd &fd, size_t size) {
void *region;
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ));
TestProtDenied(fd, size, PROT_WRITE);
- TestProtIs(fd, PROT_READ);
+ TestProtIs(fd, PROT_READ | PROT_EXEC);
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, ®ion));
EXPECT_EQ(0, munmap(region, size));
+}
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_WRITE));
- TestProtDenied(fd, size, PROT_READ);
- TestProtIs(fd, PROT_WRITE);
- ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_WRITE, ®ion));
- EXPECT_EQ(0, munmap(region, size));
-
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
- TestProtIs(fd, PROT_READ | PROT_WRITE);
- ASSERT_EQ(0, ashmem_set_prot_region(fd, PROT_READ));
+static void ProtTestRWBuffer(const unique_fd &fd, size_t size) {
+ TestProtIs(fd, PROT_READ | PROT_WRITE | PROT_EXEC);
+ ASSERT_EQ(0, ashmem_set_prot_region(fd, PROT_READ | PROT_EXEC));
errno = 0;
- ASSERT_EQ(-1, ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE))
+ ASSERT_EQ(-1, ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE |
+ PROT_EXEC))
<< "kernel shouldn't allow adding protection bits";
EXPECT_EQ(EINVAL, errno);
- TestProtIs(fd, PROT_READ);
+ TestProtIs(fd, PROT_READ | PROT_EXEC);
TestProtDenied(fd, size, PROT_WRITE);
}
-TEST(AshmemTest, ForkProtTest) {
- unique_fd fd;
- const size_t size = getpagesize();
-
- int protFlags[] = { PROT_READ, PROT_WRITE };
- for (size_t i = 0; i < arraysize(protFlags); i++) {
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
- ASSERT_EXIT(
- {
- if (!ashmem_valid(fd)) {
- _exit(3);
- } else if (ashmem_set_prot_region(fd, protFlags[i]) >= 0) {
- _exit(0);
- } else {
- _exit(1);
- }
- },
- ::testing::ExitedWithCode(0), "");
- ASSERT_NO_FATAL_FAILURE(TestProtDenied(fd, size, protFlags[1-i]));
+static void ForkProtTest(const unique_fd &fd, size_t size) {
+ pid_t pid = fork();
+ if (!pid) {
+ // Change buffer mapping permissions to read-only to ensure that
+ // updates to the buffer's mapping permissions are visible across
+ // processes that reference the buffer.
+ if (!ashmem_valid(fd)) {
+ _exit(3);
+ } else if (ashmem_set_prot_region(fd, PROT_READ) == -1) {
+ _exit(1);
+ }
+ _exit(0);
+ } else {
+ ASSERT_GT(pid, 0);
+ ASSERT_NO_FATAL_FAILURE(waitForChildProcessExit(pid));
}
+
+ ASSERT_NO_FATAL_FAILURE(TestProtDenied(fd, size, PROT_WRITE));
}
-TEST(AshmemTest, ForkMultiRegionTest) {
- const size_t size = getpagesize();
+static void ForkMultiRegionTest(unique_fd fds[], int nRegions, size_t size) {
std::vector<uint8_t> data(size);
FillData(data);
- constexpr int nRegions = 16;
- unique_fd fd[nRegions];
for (int i = 0; i < nRegions; i++) {
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
void* region = nullptr;
- ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, ®ion));
+ ASSERT_NO_FATAL_FAILURE(TestMmap(fds[i], size, PROT_READ | PROT_WRITE, ®ion));
memcpy(region, data.data(), size);
ASSERT_EQ(0, memcmp(region, data.data(), size));
EXPECT_EQ(0, munmap(region, size));
}
- ASSERT_EXIT({
+ pid_t pid = fork();
+ if (!pid) {
+ // Clear each ashmem buffer in the context of the child process to
+ // ensure that the updates are visible to the parent process later.
for (int i = 0; i < nRegions; i++) {
- if (!ashmem_valid(fd[i])) {
+ if (!ashmem_valid(fds[i])) {
_exit(3);
}
- void *region = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0);
+ void *region = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fds[i], 0);
if (region == MAP_FAILED) {
_exit(1);
}
@@ -254,13 +252,67 @@
munmap(region, size);
}
_exit(0);
- }, ::testing::ExitedWithCode(0), "");
+ } else {
+ ASSERT_GT(pid, 0);
+ ASSERT_NO_FATAL_FAILURE(waitForChildProcessExit(pid));
+ }
memset(data.data(), 0, size);
for (int i = 0; i < nRegions; i++) {
void *region;
- ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, ®ion));
+ ASSERT_NO_FATAL_FAILURE(TestMmap(fds[i], size, PROT_READ | PROT_WRITE, ®ion));
ASSERT_EQ(0, memcmp(region, data.data(), size));
EXPECT_EQ(0, munmap(region, size));
}
+
+}
+
+TEST(AshmemTest, ForkTest) {
+ const size_t size = getpagesize();
+ unique_fd fd;
+
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
+ ASSERT_NO_FATAL_FAILURE(ForkTest(fd, size));
+}
+
+TEST(AshmemTest, FileOperationsTest) {
+ const size_t pageSize = getpagesize();
+ // Allocate a 4-page buffer, but leave page-sized holes on either side in
+ // the test.
+ const size_t size = pageSize * 4;
+ unique_fd fd;
+
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
+ ASSERT_NO_FATAL_FAILURE(FileOperationsTest(fd, size));
+}
+
+TEST(AshmemTest, ProtTest) {
+ unique_fd fd;
+ const size_t size = getpagesize();
+
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_EXEC));
+ ASSERT_NO_FATAL_FAILURE(ProtTestROBuffer(fd, size));
+
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE | PROT_EXEC));
+ ASSERT_NO_FATAL_FAILURE(ProtTestRWBuffer(fd, size));
+}
+
+TEST(AshmemTest, ForkProtTest) {
+ unique_fd fd;
+ const size_t size = getpagesize();
+
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
+ ASSERT_NO_FATAL_FAILURE(ForkProtTest(fd, size));
+}
+
+TEST(AshmemTest, ForkMultiRegionTest) {
+ const size_t size = getpagesize();
+ constexpr int nRegions = 16;
+ unique_fd fds[nRegions];
+
+ for (int i = 0; i < nRegions; i++) {
+ ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fds[i], PROT_READ | PROT_WRITE));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(ForkMultiRegionTest(fds, nRegions, size));
}
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 2e4b9b4..00a1114 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -205,6 +205,7 @@
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/fsck.f2fs" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage.sh"},
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
{ 00750, AID_ROOT, AID_SHELL, 0, "init*" },
{ 00644, AID_ROOT, AID_ROOT, 0, "*.rc" },
diff --git a/libmodprobe/include/exthandler/exthandler.h b/libmodprobe/include/exthandler/exthandler.h
index 232aa95..a619f81 100644
--- a/libmodprobe/include/exthandler/exthandler.h
+++ b/libmodprobe/include/exthandler/exthandler.h
@@ -17,6 +17,7 @@
#pragma once
#include <android-base/result.h>
#include <string>
+#include <sys/types.h>
android::base::Result<std::string> RunExternalHandler(
const std::string& handler, uid_t uid, gid_t gid,
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index 7b691b1..d33e17d 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -16,6 +16,7 @@
#pragma once
+#include <functional>
#include <mutex>
#include <set>
#include <string>
diff --git a/libpackagelistparser/packagelistparser.cpp b/libpackagelistparser/packagelistparser.cpp
index 638cc43..5517b68 100644
--- a/libpackagelistparser/packagelistparser.cpp
+++ b/libpackagelistparser/packagelistparser.cpp
@@ -21,6 +21,7 @@
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/limits.h>
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 98179e8..0aa14ba 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -79,6 +79,7 @@
// Set various properties of a process group. For these functions to work, the process group must
// have been created by passing memControl=true to createProcessGroup.
+[[deprecated("Unsupported in memcg v2")]]
bool setProcessGroupSwappiness(uid_t uid, pid_t initialPid, int swappiness);
bool setProcessGroupSoftLimit(uid_t uid, pid_t initialPid, int64_t softLimitInBytes);
bool setProcessGroupLimit(uid_t uid, pid_t initialPid, int64_t limitInBytes);
diff --git a/libprocessgroup/vts/vts_libprocessgroup.cpp b/libprocessgroup/vts/vts_libprocessgroup.cpp
index af0b0af..e51fa3d 100644
--- a/libprocessgroup/vts/vts_libprocessgroup.cpp
+++ b/libprocessgroup/vts/vts_libprocessgroup.cpp
@@ -15,18 +15,14 @@
*/
#include <cerrno>
-#include <chrono>
#include <cstdio>
#include <filesystem>
-#include <future>
#include <iostream>
#include <optional>
#include <random>
#include <string>
#include <vector>
-#include <unistd.h>
-
#include <android-base/file.h>
#include <android-base/strings.h>
using android::base::ReadFileToString;
@@ -83,16 +79,6 @@
} // anonymous namespace
-
-class MemcgV2Test : public testing::Test {
- protected:
- void SetUp() override {
- std::optional<bool> memcgV2Enabled = isMemcgV2Enabled();
- ASSERT_NE(memcgV2Enabled, std::nullopt);
- if (!*memcgV2Enabled) GTEST_SKIP() << "Memcg v2 not enabled";
- }
-};
-
class MemcgV2SubdirTest : public testing::Test {
protected:
std::optional<std::string> mRandDir;
@@ -150,26 +136,3 @@
ASSERT_TRUE(WriteStringToFile("+memory", *mRandDir + "/cgroup.subtree_control"))
<< "Could not enable memcg under child cgroup subtree";
}
-
-// Test for fix: mm: memcg: use larger batches for proactive reclaim
-// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=287d5fedb377ddc232b216b882723305b27ae31a
-TEST_F(MemcgV2Test, ProactiveReclaimDoesntTakeForever) {
- // Not all kernels have memory.reclaim
- const std::filesystem::path reclaim(CGROUP_V2_ROOT_PATH + "/memory.reclaim");
- if (!std::filesystem::exists(reclaim)) GTEST_SKIP() << "memory.reclaim not found";
-
- // Use the total device memory as the amount to reclaim
- const long numPages = sysconf(_SC_PHYS_PAGES);
- const long pageSize = sysconf(_SC_PAGE_SIZE);
- ASSERT_GT(numPages, 0);
- ASSERT_GT(pageSize, 0);
- const unsigned long long totalMem =
- static_cast<unsigned long long>(numPages) * static_cast<unsigned long long>(pageSize);
-
- auto fut = std::async(std::launch::async,
- [&]() { WriteStringToFile(std::to_string(totalMem), reclaim); });
-
- // This is a test for completion within the timeout. The command is likely to "fail" since we
- // are asking to reclaim all device memory.
- ASSERT_NE(fut.wait_for(std::chrono::seconds(20)), std::future_status::timeout);
-}
diff --git a/libstats/bootstrap/BootstrapClientInternal.h b/libstats/bootstrap/BootstrapClientInternal.h
index 96238da..7879d01 100644
--- a/libstats/bootstrap/BootstrapClientInternal.h
+++ b/libstats/bootstrap/BootstrapClientInternal.h
@@ -18,6 +18,8 @@
#include <android/os/IStatsBootstrapAtomService.h>
+#include <mutex>
+
namespace android {
namespace os {
namespace stats {
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 2a8939e..ae00e75 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -24,7 +24,7 @@
crate_name: "statspull_bindgen",
visibility: [
"//frameworks/proto_logging/stats/stats_log_api_gen",
- "//packages/modules/Virtualization/libs/statslog_virtualization",
+ "//packages/modules:__subpackages__",
],
source_stem: "bindings",
bindgen_flags: [
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index 842db40..18a6aa6 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -32,18 +32,6 @@
export_include_dirs: ["include"],
- tidy: true,
- tidy_checks: [
- "-*",
- "cert-*",
- "clang-analyzer-security*",
- "android-*",
- ],
- tidy_checks_as_errors: [
- "cert-*",
- "clang-analyzer-security*",
- "android-*",
- ],
apex_available: [
"//apex_available:anyapex",
"//apex_available:platform",
diff --git a/libutils/binder/RefBase.cpp b/libutils/binder/RefBase.cpp
index 4291f1e..bf803e7 100644
--- a/libutils/binder/RefBase.cpp
+++ b/libutils/binder/RefBase.cpp
@@ -492,7 +492,10 @@
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
- LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
+ LOG_ALWAYS_FATAL_IF(
+ BAD_STRONG(c),
+ "decStrong() called on %p too many times, possible memory corruption. Consider "
+ "compiling with ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for better errors",
refs);
if (c == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
@@ -576,7 +579,10 @@
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
- LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
+ LOG_ALWAYS_FATAL_IF(
+ BAD_WEAK(c),
+ "decWeak called on %p too many times, possible memory corruption. Consider compiling "
+ "with ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for better errors",
this);
if (c != 1) return;
atomic_thread_fence(std::memory_order_acquire);
diff --git a/libutils/binder/String8_test.cpp b/libutils/binder/String8_test.cpp
index fc3c329..ff9bc8d 100644
--- a/libutils/binder/String8_test.cpp
+++ b/libutils/binder/String8_test.cpp
@@ -176,3 +176,11 @@
EXPECT_TRUE(pair1 < pair2);
EXPECT_FALSE(pair1 > pair2);
}
+
+TEST_F(String8Test, SvCtor) {
+ const char* expected = "abc";
+ std::string s{expected};
+ EXPECT_STREQ(String8{s}.c_str(), expected);
+ EXPECT_STREQ(String8{std::string_view{s}}.c_str(), expected);
+ EXPECT_STREQ(String8{expected}.c_str(), expected);
+}
diff --git a/libutils/binder/include/utils/String16.h b/libutils/binder/include/utils/String16.h
index 867dbac..20de647 100644
--- a/libutils/binder/include/utils/String16.h
+++ b/libutils/binder/include/utils/String16.h
@@ -19,16 +19,12 @@
#include <iostream>
#include <string>
+#include <string_view>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/TypeHelpers.h>
-#if __has_include(<string_view>)
-#include <string_view>
-#define HAS_STRING_VIEW
-#endif
-
#if __cplusplus >= 202002L
#include <compare>
#endif
@@ -125,11 +121,9 @@
inline operator const char16_t*() const;
-#ifdef HAS_STRING_VIEW
// Implicit cast to std::u16string is not implemented on purpose - u16string_view is much
// lighter and if one needs, they can still create u16string from u16string_view.
inline operator std::u16string_view() const;
-#endif
// Static and non-static String16 behave the same for the users, so
// this method isn't of much use for the users. It is public for testing.
@@ -414,6 +408,4 @@
// ---------------------------------------------------------------------------
-#undef HAS_STRING_VIEW
-
#endif // ANDROID_STRING16_H
diff --git a/libutils/binder/include/utils/String8.h b/libutils/binder/include/utils/String8.h
index e0d7588..404f8a0 100644
--- a/libutils/binder/include/utils/String8.h
+++ b/libutils/binder/include/utils/String8.h
@@ -18,6 +18,8 @@
#define ANDROID_STRING8_H
#include <iostream>
+#include <string>
+#include <string_view>
#include <utils/Errors.h>
#include <utils/Unicode.h>
@@ -26,16 +28,6 @@
#include <string.h> // for strcmp
#include <stdarg.h>
-#if __has_include(<string>)
-#include <string>
-#define HAS_STRING
-#endif
-
-#if __has_include(<string_view>)
-#include <string_view>
-#define HAS_STRING_VIEW
-#endif
-
#if __cplusplus >= 202002L
#include <compare>
#endif
@@ -57,6 +49,7 @@
String8(const String8& o);
explicit String8(const char* o);
explicit String8(const char* o, size_t numChars);
+ explicit String8(std::string_view o);
explicit String8(const String16& o);
explicit String8(const char16_t* o);
@@ -126,9 +119,7 @@
inline operator const char*() const;
-#ifdef HAS_STRING_VIEW
inline explicit operator std::string_view() const;
-#endif
char* lockBuffer(size_t size);
void unlockBuffer();
@@ -373,18 +364,15 @@
return mString;
}
-#ifdef HAS_STRING_VIEW
+inline String8::String8(std::string_view o) : String8(o.data(), o.length()) { }
+
inline String8::operator std::string_view() const
{
return {mString, length()};
}
-#endif
} // namespace android
// ---------------------------------------------------------------------------
-#undef HAS_STRING
-#undef HAS_STRING_VIEW
-
#endif // ANDROID_STRING8_H
diff --git a/overlay_remounter/Android.bp b/overlay_remounter/Android.bp
new file mode 100644
index 0000000..d74f7da
--- /dev/null
+++ b/overlay_remounter/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2025 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.
+//
+
+cc_binary {
+ name: "overlay_remounter",
+ srcs: [
+ "overlay_remounter.cpp",
+ ],
+ cflags: [
+ "-D_FILE_OFFSET_BITS=64",
+ "-Wall",
+ "-Werror",
+ ],
+ static_libs: [
+ "libbase",
+ "liblog",
+ ],
+ system_shared_libs: [],
+ static_executable: true,
+ install_in_xbin: true,
+}
diff --git a/overlay_remounter/overlay_remounter.cpp b/overlay_remounter/overlay_remounter.cpp
new file mode 100644
index 0000000..ddf97fa
--- /dev/null
+++ b/overlay_remounter/overlay_remounter.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+#include <sys/mount.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+
+int main(int /*argc*/, char** argv) {
+ android::base::InitLogging(argv, &android::base::KernelLogger);
+ LOG(INFO) << "Overlay remounter will remount all overlay mount points in the overlay_remounter "
+ "domain";
+
+ // Remount ouerlayfs
+ std::string contents;
+ auto result = android::base::ReadFileToString("/proc/mounts", &contents, true);
+
+ auto lines = android::base::Split(contents, "\n");
+ for (auto const& line : lines) {
+ if (!android::base::StartsWith(line, "overlay")) {
+ continue;
+ }
+ auto bits = android::base::Split(line, " ");
+ if (int result = umount(bits[1].c_str()); result == -1) {
+ PLOG(FATAL) << "umount FAILED: " << bits[1];
+ }
+ std::string options;
+ for (auto const& option : android::base::Split(bits[3], ",")) {
+ if (option == "ro" || option == "seclabel" || option == "noatime") continue;
+ if (!options.empty()) options += ',';
+ options += option;
+ }
+ result = mount("overlay", bits[1].c_str(), "overlay", MS_RDONLY | MS_NOATIME,
+ options.c_str());
+ if (result == 0) {
+ LOG(INFO) << "mount succeeded: " << bits[1] << " " << options;
+ } else {
+ PLOG(FATAL) << "mount FAILED: " << bits[1] << " " << bits[3];
+ }
+ }
+
+ const char* path = "/system/bin/init";
+ const char* args[] = {path, "second_stage", nullptr};
+ execv(path, const_cast<char**>(args));
+
+ // execv() only returns if an error happened, in which case we
+ // panic and never return from this function.
+ PLOG(FATAL) << "execv(\"" << path << "\") failed";
+
+ return 1;
+}
diff --git a/rootdir/create_root_structure.mk b/rootdir/create_root_structure.mk
index d0be897..15d78a6 100644
--- a/rootdir/create_root_structure.mk
+++ b/rootdir/create_root_structure.mk
@@ -41,7 +41,8 @@
$(TARGET_ROOT_OUT)/etc \
$(TARGET_ROOT_OUT)/bugreports \
$(TARGET_ROOT_OUT)/d \
- $(TARGET_ROOT_OUT)/sdcard
+ $(TARGET_ROOT_OUT)/sdcard \
+ $(TARGET_ROOT_OUT)/adb_keys \
ifdef BOARD_USES_VENDORIMAGE
LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/vendor
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f1670ae..734197b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -902,7 +902,7 @@
mkdir /data/system/users 0775 system system
# Mkdir and set SELinux security contexts for shutdown-checkpoints.
# TODO(b/270286197): remove these after couple releases.
- mkdir /data/system/shutdown-checkpoints 0700 system system
+ mkdir /data/system/shutdown-checkpoints 0755 system system
restorecon_recursive /data/system/shutdown-checkpoints
# Create the parent directories of the user CE and DE storage directories.
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 3142542..5169aa1 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -84,3 +84,22 @@
vendor: true,
defaults: ["toolbox_binary_defaults"],
}
+
+// This one is installed in the generic ramdisk, and can be executed during
+// init-first-stage.
+// As there are no dynamic linker available, this must be statically linked.
+cc_binary {
+ name: "toolbox_ramdisk",
+ defaults: ["toolbox_binary_defaults"],
+ ramdisk: true,
+ static_executable: true,
+ system_shared_libs: [],
+ exclude_shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+ static_libs: [
+ "libbase",
+ "liblog",
+ ],
+}
diff --git a/toolbox/getprop.cpp b/toolbox/getprop.cpp
index ca345cb..7c3d94c 100644
--- a/toolbox/getprop.cpp
+++ b/toolbox/getprop.cpp
@@ -17,6 +17,7 @@
#include <getopt.h>
#include <sys/system_properties.h>
+#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 8ebfc1a..31187f5 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -80,13 +80,9 @@
vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"],
}
-cc_binary {
- name: "android.hardware.security.keymint-service.trusty",
+cc_defaults {
+ name: "android.hardware.security.keymint-service.trusty.defaults",
relative_install_path: "hw",
- init_rc: ["keymint/android.hardware.security.keymint-service.trusty.rc"],
- vintf_fragments: [
- "keymint/android.hardware.security.keymint-service.trusty.xml",
- ],
vendor: true,
cflags: [
"-Wall",
@@ -120,10 +116,38 @@
"libtrusty",
"libutils",
],
- required: select(release_flag("RELEASE_AIDL_USE_UNFROZEN"), {
- true: ["android.hardware.hardware_keystore.xml"],
- default: ["android.hardware.hardware_keystore_V3.xml"],
- }),
+}
+
+// keymint hal binary for keymint in Trusty TEE prebuilt
+cc_binary {
+ name: "android.hardware.security.keymint-service.trusty",
+ defaults: ["android.hardware.security.keymint-service.trusty.defaults"],
+ init_rc: ["keymint/android.hardware.security.keymint-service.trusty.rc"],
+ vintf_fragments: [
+ "keymint/android.hardware.security.keymint-service.trusty.xml",
+ ],
+ required: ["android.hardware.hardware_keystore.xml"],
+}
+
+// Keymint hal service in vendor, enabled by vendor apex.
+// This service is disabled by default and does not package a VINTF fragment.
+// This service can be enabled at boot via vendor apex:
+// - at boot, mount a vendor apex for module `com.android.hardware.keymint`
+// - have the vendor init.rc file enable the service when the associated
+// apex is selected
+// - have the vendor apex package the vintf fragment and the required permissions
+cc_binary {
+ name: "android.hardware.security.keymint-service.trusty_tee.cpp",
+ defaults: ["android.hardware.security.keymint-service.trusty.defaults"],
+ init_rc: ["keymint/android.hardware.security.keymint-service.trusty_tee.cpp.rc"],
+}
+
+// vintf fragment packaged in vendor apex
+prebuilt_etc {
+ name: "android.hardware.security.keymint-service.trusty.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "keymint/android.hardware.security.keymint-service.trusty.xml",
}
prebuilt_etc {
diff --git a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty_tee.cpp.rc b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty_tee.cpp.rc
new file mode 100644
index 0000000..61ae8ae
--- /dev/null
+++ b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty_tee.cpp.rc
@@ -0,0 +1,11 @@
+# service started when selecting `com.android.hardware.keymint.trusty_tee.cpp` vendor apex
+service vendor.keymint-service.trusty_tee.cpp \
+ /vendor/bin/hw/android.hardware.security.keymint-service.trusty_tee.cpp \
+ --dev ${ro.hardware.trusty_ipc_dev.keymint:-/dev/trusty-ipc-dev0}
+ disabled
+ class early_hal
+ user nobody
+ group drmrpc
+ # The keymint service is not allowed to restart.
+ # If it crashes, a device restart is required.
+ oneshot
diff --git a/trusty/keymint/Android.bp b/trusty/keymint/Android.bp
index 36efb1b..d1cd71b 100644
--- a/trusty/keymint/Android.bp
+++ b/trusty/keymint/Android.bp
@@ -36,25 +36,60 @@
prefer_rlib: true,
}
+// keymint hal binary for keymint in Trusty TEE (legacy approach not using apex)
rust_binary {
name: "android.hardware.security.keymint-service.rust.trusty",
vendor: true,
defaults: ["android.hardware.security.keymint-service.rust.trusty.default"],
init_rc: ["android.hardware.security.keymint-service.rust.trusty.rc"],
vintf_fragments: ["android.hardware.security.keymint-service.rust.trusty.xml"],
- required: select(release_flag("RELEASE_AIDL_USE_UNFROZEN"), {
- true: ["android.hardware.hardware_keystore.xml"],
- default: ["android.hardware.hardware_keystore_V3.xml"],
- }),
+ required: ["android.hardware.hardware_keystore.xml"],
}
+// Keymint hal service in vendor, enabled by vendor apex.
+// This service is disabled by default and does not package a VINTF fragment.
+// This service can be enabled at boot via vendor apex:
+// - at boot, mount a vendor apex for module `com.android.hardware.keymint`
+// - have the vendor apex init.rc file to start the service when the apex is selected
+// - have the vendor apex package the vintf fragment
rust_binary {
- name: "android.hardware.security.keymint-service.rust.trusty.system.nonsecure",
+ name: "android.hardware.security.keymint-service.trusty_tee",
+ vendor: true,
+ defaults: ["android.hardware.security.keymint-service.rust.trusty.default"],
+ init_rc: ["android.hardware.security.keymint-service.trusty_tee.rc"],
+}
+
+// Keymint hal service in system_ext, interacting with the Trusty Security VM.
+// This service is disabled by default and does not package a VINTF fragment.
+// This service can be enabled at boot via vendor apex:
+// - at boot, mount a vendor apex for module `com.android.hardware.keymint`
+// - have the vendor apex init.rc file to start the service when the apex is selected
+// - have the vendor apex package the vintf fragment
+rust_binary {
+ name: "android.hardware.security.keymint-service.trusty_system_vm",
system_ext_specific: true,
defaults: ["android.hardware.security.keymint-service.rust.trusty.default"],
- init_rc: ["android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc"],
- features: ["nonsecure"],
+ init_rc: ["android.hardware.security.keymint-service.trusty_system_vm.rc"],
+ features: select(soong_config_variable("trusty_system_vm", "placeholder_trusted_hal"), {
+ true: ["nonsecure"],
+ default: [],
+ }),
rustlibs: [
"libkmr_hal_nonsecure",
],
}
+
+// vintf fragment packaged in vendor apex
+prebuilt_etc {
+ name: "android.hardware.security.keymint-service.rust.trusty.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "android.hardware.security.keymint-service.rust.trusty.xml",
+}
+
+prebuilt_etc {
+ name: "android.hardware.security.keymint-service.trusty_system_vm.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "android.hardware.security.keymint-service.trusty_system_vm.xml",
+}
diff --git a/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
deleted file mode 100644
index cd656b2..0000000
--- a/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2021 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.
--->
-<permissions>
- <feature name="android.hardware.hardware_keystore" version="300" />
-</permissions>
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc
deleted file mode 100644
index e580651..0000000
--- a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc
+++ /dev/null
@@ -1,17 +0,0 @@
-service system.keymint.rust-trusty.nonsecure \
- /system_ext/bin/hw/android.hardware.security.keymint-service.rust.trusty.system.nonsecure \
- --dev ${system.keymint.trusty_ipc_dev:-/dev/trusty-ipc-dev0}
- disabled
- user nobody
- group drmrpc
- # The keymint service is not allowed to restart.
- # If it crashes, a device restart is required.
- oneshot
-
-# Only starts the non-secure KeyMint HALs when the KeyMint VM feature is enabled
-# TODO(b/357821690): Start the KeyMint HALs when the KeyMint VM is ready once the Trusty VM
-# has a mechanism to notify the host.
-on late-fs && property:trusty.security_vm.keymint.enabled=1 && \
- property:trusty.security_vm.vm_cid=*
- setprop system.keymint.trusty_ipc_dev VSOCK:${trusty.security_vm.vm_cid}:1
- start system.keymint.rust-trusty.nonsecure
diff --git a/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.rc b/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.rc
new file mode 100644
index 0000000..2e8ad00
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.rc
@@ -0,0 +1,17 @@
+# service started when selecting `com.android.hardware.keymint.trusty_system_vm` vendor apex
+service system.keymint-service.trusty_system_vm \
+ /system_ext/bin/hw/android.hardware.security.keymint-service.trusty_system_vm \
+ --dev ${system.keymint.trusty_ipc_dev}
+ disabled
+ user nobody
+ group drmrpc
+ # The keymint service is not allowed to restart.
+ # If it crashes, a device restart is required.
+ oneshot
+
+# TODO(b/357821690): Start the KeyMint HALs when the KeyMint VM is ready once the Trusty VM
+# has a mechanism to notify the host.
+on post-fs && property:trusty.security_vm.keymint.enabled=1 && \
+ property:trusty.security_vm.vm_cid=*
+ setprop system.keymint.trusty_ipc_dev VSOCK:${trusty.security_vm.vm_cid}:1
+ start system.keymint-service.trusty_system_vm
diff --git a/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.xml b/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.xml
new file mode 100644
index 0000000..c35c843
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.trusty_system_vm.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl" updatable-via-system="true">
+ <name>android.hardware.security.keymint</name>
+ <version>4</version>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+ <hal format="aidl" updatable-via-system="true">
+ <name>android.hardware.security.secureclock</name>
+ <fqname>ISecureClock/default</fqname>
+ </hal>
+ <hal format="aidl" updatable-via-system="true">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/default</fqname>
+ </hal>
+ <hal format="aidl" updatable-via-system="true">
+ <name>android.hardware.security.keymint</name>
+ <version>3</version>
+ <fqname>IRemotelyProvisionedComponent/default</fqname>
+ </hal>
+</manifest>
diff --git a/trusty/keymint/android.hardware.security.keymint-service.trusty_tee.rc b/trusty/keymint/android.hardware.security.keymint-service.trusty_tee.rc
new file mode 100644
index 0000000..694c9ce
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.trusty_tee.rc
@@ -0,0 +1,11 @@
+# service started when selecting `com.android.hardware.keymint.trusty_tee` vendor apex
+service vendor.keymint-service.trusty_tee \
+ /vendor/bin/hw/android.hardware.security.keymint-service.trusty_tee \
+ --dev ${ro.hardware.trusty_ipc_dev.keymint:-/dev/trusty-ipc-dev0}
+ disabled
+ class early_hal
+ user nobody
+ group drmrpc
+ # The keymint service is not allowed to restart.
+ # If it crashes, a device restart is required.
+ oneshot
diff --git a/trusty/keymint/trusty-keymint-apex.mk b/trusty/keymint/trusty-keymint-apex.mk
new file mode 100644
index 0000000..8b7f4d0
--- /dev/null
+++ b/trusty/keymint/trusty-keymint-apex.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2024 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 makefile should be included by devices that choose to integrate
+# Keymint HAL via vendor apex
+
+PRODUCT_PACKAGES += \
+ android.hardware.security.keymint-service.trusty_tee.cpp \
+ android.hardware.security.keymint-service.trusty_tee \
+
+ifeq ($(findstring $(TRUSTY_SYSTEM_VM),enabled),enabled)
+ PRODUCT_PACKAGES += \
+ android.hardware.security.keymint-service.trusty_system_vm \
+
+endif
diff --git a/trusty/keymint/trusty-keymint.mk b/trusty/keymint/trusty-keymint.mk
index d5791ea..43cc186 100644
--- a/trusty/keymint/trusty-keymint.mk
+++ b/trusty/keymint/trusty-keymint.mk
@@ -21,19 +21,14 @@
# Allow KeyMint HAL service implementation selection at build time. This must be
# synchronized with the TA implementation included in Trusty. Possible values:
#
-# - Rust implementation for Trusty VM (requires Trusty VM support):
+# - Rust implementation for Trusty TEE
# export TRUSTY_KEYMINT_IMPL=rust
-# export TRUSTY_SYSTEM_VM=nonsecure
-# - Rust implementation for Trusty TEE (no Trusty VM support):
-# export TRUSTY_KEYMINT_IMPL=rust
-# - C++ implementation (default): (any other value or unset TRUSTY_KEYMINT_IMPL)
+# - C++ implementation (default):
+# any other value or unset TRUSTY_KEYMINT_IMPL
ifeq ($(TRUSTY_KEYMINT_IMPL),rust)
- ifeq ($(TRUSTY_SYSTEM_VM),nonsecure)
- LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty.system.nonsecure
- else
- LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
- endif
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
+
else
# Default to the C++ implementation
LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
diff --git a/trusty/storage/proxy/watchdog.cpp b/trusty/storage/proxy/watchdog.cpp
index 6c09e26..f042fdc 100644
--- a/trusty/storage/proxy/watchdog.cpp
+++ b/trusty/storage/proxy/watchdog.cpp
@@ -18,6 +18,7 @@
#include <chrono>
#include <cstdint>
+#include <mutex>
#include <optional>
#include <thread>
#include <vector>
diff --git a/trusty/sysprops/Android.bp b/trusty/sysprops/Android.bp
new file mode 100644
index 0000000..ec27f51
--- /dev/null
+++ b/trusty/sysprops/Android.bp
@@ -0,0 +1,15 @@
+sysprop_library {
+ name: "trusty-properties",
+ srcs: ["android/sysprop/trusty/security_vm.sysprop"],
+ property_owner: "Platform",
+ api_packages: ["android.sysprop.trusty"],
+ apex_available: [
+ "//apex_available:platform",
+ ],
+}
+
+rust_binary {
+ name: "trusty-properties-example",
+ srcs: ["example.rs"],
+ rustlibs: ["libtrusty_properties_rust"],
+}
diff --git a/trusty/sysprops/android/sysprop/trusty/security_vm.sysprop b/trusty/sysprops/android/sysprop/trusty/security_vm.sysprop
new file mode 100644
index 0000000..a079ecf
--- /dev/null
+++ b/trusty/sysprops/android/sysprop/trusty/security_vm.sysprop
@@ -0,0 +1,67 @@
+# Copyright (C) 2025 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 module accesses properties regarding the Trusty VM that runs apps
+# used to provide security for the system, such as Keymint or Gatekeeper.
+
+module: "android.sysprop.trusty.security_vm"
+owner: Platform
+
+# The default Context Identifier to connect to Trusty over vsock.
+prop {
+ api_name: "vm_cid"
+ prop_name: "trusty.security_vm.vm_cid"
+ type: Integer
+ scope: Internal
+ access: Readonly
+}
+
+# Signals when a nonsecure VM is ready.
+#
+# This is used to launch dependent HALs.
+#
+# Trusty security VMs come in two flavors: non-secure and secure.
+#
+# 1. Non-secure VMs run on emulated environments like Cuttlefish, which lack
+# pVM firmware and TEE support. Consequently, KeyMint's root-of-trust data
+# is passed into the VM from the host's HAL, and an RPMB proxy provides
+# secure storage.
+# 2. Secure VMs run on physical devices. Here, pVM firmware handles the
+# transfer of root-of-trust data via DeviceTree, and a TEE provides secure
+# storage.
+prop {
+ api_name: "nonsecure_vm_ready"
+ prop_name: "trusty.security_vm.nonsecure_vm_ready"
+ type: Boolean
+ scope: Internal
+ access: Readonly
+}
+
+# The Trusty Security VM is enabled.
+prop {
+ api_name: "enabled"
+ prop_name: "trusty.security_vm.enabled"
+ type: Boolean
+ scope: Public
+ access: Readonly
+}
+
+# KeyMint is enabled in the Trusty Security VM.
+prop {
+ api_name: "keymint_enabled"
+ prop_name: "trusty.security_vm.keymint.enabled"
+ type: Boolean
+ scope: Public
+ access: Readonly
+}
diff --git a/trusty/sysprops/api/trusty-properties-current.txt b/trusty/sysprops/api/trusty-properties-current.txt
new file mode 100644
index 0000000..aa792fc
--- /dev/null
+++ b/trusty/sysprops/api/trusty-properties-current.txt
@@ -0,0 +1,11 @@
+props {
+ module: "android.sysprop.trusty.security_vm"
+ prop {
+ api_name: "enabled"
+ prop_name: "trusty.security_vm.enabled"
+ }
+ prop {
+ api_name: "keymint_enabled"
+ prop_name: "trusty.security_vm.keymint.enabled"
+ }
+}
diff --git a/trusty/sysprops/api/trusty-properties-latest.txt b/trusty/sysprops/api/trusty-properties-latest.txt
new file mode 100644
index 0000000..aa792fc
--- /dev/null
+++ b/trusty/sysprops/api/trusty-properties-latest.txt
@@ -0,0 +1,11 @@
+props {
+ module: "android.sysprop.trusty.security_vm"
+ prop {
+ api_name: "enabled"
+ prop_name: "trusty.security_vm.enabled"
+ }
+ prop {
+ api_name: "keymint_enabled"
+ prop_name: "trusty.security_vm.keymint.enabled"
+ }
+}
diff --git a/trusty/sysprops/example.rs b/trusty/sysprops/example.rs
new file mode 100644
index 0000000..f21e779
--- /dev/null
+++ b/trusty/sysprops/example.rs
@@ -0,0 +1,11 @@
+//! Example showing how to access the `trusty.security_vm.vm_cid` system property with Rust.
+
+use trusty_properties::security_vm;
+
+fn main() {
+ match security_vm::vm_cid() {
+ Ok(Some(cid)) => println!("CID: {cid}"),
+ Ok(None) => println!("CID property not set"),
+ Err(e) => println!("Error: {e:?}"),
+ }
+}
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 9d810dc..fcde61d 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -22,7 +22,13 @@
# For gatekeeper, we include the generic -service and -impl to use legacy
# HAL loading of gatekeeper.trusty.
-$(call inherit-product, system/core/trusty/keymint/trusty-keymint.mk)
+ifeq ($(KEYMINT_HAL_VENDOR_APEX_SELECT),true)
+ $(call inherit-product, system/core/trusty/keymint/trusty-keymint-apex.mk)
+
+else
+ $(call inherit-product, system/core/trusty/keymint/trusty-keymint.mk)
+
+endif
ifeq ($(SECRETKEEPER_ENABLED),true)
LOCAL_SECRETKEEPER_PRODUCT_PACKAGE := android.hardware.security.secretkeeper.trusty
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc b/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc
index 003b6fe..4e42d46 100644
--- a/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc
+++ b/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc
@@ -1,5 +1,5 @@
service storageproxyd_wv_system /system_ext/bin/storageproxyd.system \
- -d ${storageproxyd_wv_system.trusty_ipc_dev:-/dev/trusty-ipc-dev0} \
+ -d VSOCK:${trusty.widevine_vm.vm_cid}:1 \
-r /dev/socket/rpmb_mock_wv_system \
-p /data/secure_storage_wv_system \
-t sock
@@ -23,20 +23,8 @@
group system
socket rpmb_mock_wv_system stream 660 system system
-# storageproxyd
-on boot && \
- property:trusty.widevine_vm.nonsecure_vm_ready=1 && \
- property:storageproxyd_wv_system.trusty_ipc_dev=*
- wait /dev/socket/rpmb_mock_wv_system
- enable storageproxyd_wv_system
-
-
# RPMB Mock
-on early-boot && \
- property:trusty.widevine_vm.enabled=1 && \
- property:trusty.widevine_vm.vm_cid=* && \
- property:ro.boot.vendor.apex.com.android.services.widevine=\
-com.android.services.widevine.cf_guest_trusty_nonsecure
+on early-boot
# Create a persistent location for the RPMB data
# (work around lack of RPMb block device on CF).
# file contexts secure_storage_rpmb_system_file
@@ -57,6 +45,5 @@
symlink /mnt/secure_storage_persist_wv_system/persist \
/data/secure_storage_wv_system/persist
chown root system /data/secure_storage_wv_system/persist
- setprop storageproxyd_wv_system.trusty_ipc_dev VSOCK:${trusty.widevine_vm.vm_cid}:1
exec_start rpmb_mock_init_wv_system
start rpmb_mock_wv_system