Merge "Add compat symlink preferred-arch /system/bin/dalvikvm."
diff --git a/adb/adb.h b/adb/adb.h
index 9209997..3a8cb7b 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -153,7 +153,7 @@
#endif
#if !ADB_HOST
-unique_fd execute_binder_command(std::string_view command);
+unique_fd execute_abb_command(std::string_view command);
#endif
#if !ADB_HOST
diff --git a/adb/daemon/abb.cpp b/adb/daemon/abb.cpp
index d949dd1..4ffa6bb 100644
--- a/adb/daemon/abb.cpp
+++ b/adb/daemon/abb.cpp
@@ -85,7 +85,19 @@
break;
}
- unique_fd result = StartCommandInProcess(std::move(data), &execCmd);
+ std::string_view name = data;
+ auto protocol = SubprocessProtocol::kShell;
+ if (name.starts_with("abb:")) {
+ name.remove_prefix(strlen("abb:"));
+ protocol = SubprocessProtocol::kShell;
+ } else if (name.starts_with("abb_exec:")) {
+ name.remove_prefix(strlen("abb_exec:"));
+ protocol = SubprocessProtocol::kNone;
+ } else {
+ LOG(FATAL) << "Unknown command prefix for abb: " << data;
+ }
+
+ unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol);
if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) {
PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data;
break;
diff --git a/adb/daemon/abb_service.cpp b/adb/daemon/abb_service.cpp
index d32bf52..a435279 100644
--- a/adb/daemon/abb_service.cpp
+++ b/adb/daemon/abb_service.cpp
@@ -86,6 +86,6 @@
} // namespace
-unique_fd execute_binder_command(std::string_view command) {
+unique_fd execute_abb_command(std::string_view command) {
return abbp->sendCommand(command);
}
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index d1f0345..362a987 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -244,9 +244,8 @@
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
- if (name.starts_with("abb:")) {
- name.remove_prefix(strlen("abb:"));
- return execute_binder_command(name);
+ if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
+ return execute_abb_command(name);
}
#endif
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 0794bcd..e9d9c63 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -170,6 +170,8 @@
// Opens the file at |pts_name|.
int OpenPtyChildFd(const char* pts_name, unique_fd* error_sfd);
+ bool ConnectProtocolEndpoints(std::string* _Nonnull error);
+
static void ThreadHandler(void* userdata);
void PassDataStreams();
void WaitForExit();
@@ -383,42 +385,9 @@
}
D("subprocess parent: exec completed");
- if (protocol_ == SubprocessProtocol::kNone) {
- // No protocol: all streams pass through the stdinout FD and hook
- // directly into the local socket for raw data transfer.
- local_socket_sfd_.reset(stdinout_sfd_.release());
- } else {
- // Shell protocol: create another socketpair to intercept data.
- if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) {
- *error = android::base::StringPrintf(
- "failed to create socketpair to intercept data: %s", strerror(errno));
- kill(pid_, SIGKILL);
- return false;
- }
- D("protocol FD = %d", protocol_sfd_.get());
-
- input_ = std::make_unique<ShellProtocol>(protocol_sfd_);
- output_ = std::make_unique<ShellProtocol>(protocol_sfd_);
- if (!input_ || !output_) {
- *error = "failed to allocate shell protocol objects";
- kill(pid_, SIGKILL);
- return false;
- }
-
- // Don't let reads/writes to the subprocess block our thread. This isn't
- // likely but could happen under unusual circumstances, such as if we
- // write a ton of data to stdin but the subprocess never reads it and
- // the pipe fills up.
- for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) {
- if (fd >= 0) {
- if (!set_file_block_mode(fd, false)) {
- *error = android::base::StringPrintf(
- "failed to set non-blocking mode for fd %d", fd);
- kill(pid_, SIGKILL);
- return false;
- }
- }
- }
+ if (!ConnectProtocolEndpoints(error)) {
+ kill(pid_, SIGKILL);
+ return false;
}
D("subprocess parent: completed");
@@ -429,7 +398,6 @@
unique_fd child_stdinout_sfd, child_stderr_sfd;
CHECK(type_ == SubprocessType::kRaw);
- CHECK(protocol_ == SubprocessProtocol::kShell);
__android_log_security_bswrite(SEC_TAG_ADB_SHELL_CMD, command_.c_str());
@@ -448,34 +416,9 @@
D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(),
stderr_sfd_.get());
- // Required for shell protocol: create another socketpair to intercept data.
- if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) {
- *error = android::base::StringPrintf("failed to create socketpair to intercept data: %s",
- strerror(errno));
+ if (!ConnectProtocolEndpoints(error)) {
return false;
}
- D("protocol FD = %d", protocol_sfd_.get());
-
- input_ = std::make_unique<ShellProtocol>(protocol_sfd_);
- output_ = std::make_unique<ShellProtocol>(protocol_sfd_);
- if (!input_ || !output_) {
- *error = "failed to allocate shell protocol objects";
- return false;
- }
-
- // Don't let reads/writes to the subprocess block our thread. This isn't
- // likely but could happen under unusual circumstances, such as if we
- // write a ton of data to stdin but the subprocess never reads it and
- // the pipe fills up.
- for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) {
- if (fd >= 0) {
- if (!set_file_block_mode(fd, false)) {
- *error = android::base::StringPrintf("failed to set non-blocking mode for fd %d",
- fd);
- return false;
- }
- }
- }
std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd),
command = std::move(command),
@@ -486,6 +429,45 @@
return true;
}
+bool Subprocess::ConnectProtocolEndpoints(std::string* _Nonnull error) {
+ if (protocol_ == SubprocessProtocol::kNone) {
+ // No protocol: all streams pass through the stdinout FD and hook
+ // directly into the local socket for raw data transfer.
+ local_socket_sfd_.reset(stdinout_sfd_.release());
+ } else {
+ // Required for shell protocol: create another socketpair to intercept data.
+ if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) {
+ *error = android::base::StringPrintf(
+ "failed to create socketpair to intercept data: %s", strerror(errno));
+ return false;
+ }
+ D("protocol FD = %d", protocol_sfd_.get());
+
+ input_ = std::make_unique<ShellProtocol>(protocol_sfd_);
+ output_ = std::make_unique<ShellProtocol>(protocol_sfd_);
+ if (!input_ || !output_) {
+ *error = "failed to allocate shell protocol objects";
+ return false;
+ }
+
+ // Don't let reads/writes to the subprocess block our thread. This isn't
+ // likely but could happen under unusual circumstances, such as if we
+ // write a ton of data to stdin but the subprocess never reads it and
+ // the pipe fills up.
+ for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) {
+ if (fd >= 0) {
+ if (!set_file_block_mode(fd, false)) {
+ *error = android::base::StringPrintf(
+ "failed to set non-blocking mode for fd %d", fd);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
Subprocess* raw = subprocess.release();
std::thread(ThreadHandler, raw).detach();
@@ -863,12 +845,11 @@
return local_socket;
}
-unique_fd StartCommandInProcess(std::string name, Command command) {
+unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol) {
LOG(INFO) << "StartCommandInProcess(" << dump_hex(name.data(), name.size()) << ")";
constexpr auto terminal_type = "";
constexpr auto type = SubprocessType::kRaw;
- constexpr auto protocol = SubprocessProtocol::kShell;
constexpr auto make_pty_raw = false;
auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol,
diff --git a/adb/daemon/shell_service.h b/adb/daemon/shell_service.h
index fc66377..3abd958 100644
--- a/adb/daemon/shell_service.h
+++ b/adb/daemon/shell_service.h
@@ -49,7 +49,7 @@
//
// Returns an open FD connected to the thread or -1 on failure.
using Command = int(std::string_view args, int in, int out, int err);
-unique_fd StartCommandInProcess(std::string name, Command command);
+unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol);
// Create a pipe containing the error.
unique_fd ReportError(SubprocessProtocol protocol, const std::string& message);
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 0c7b0b6..0b4e084 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -72,6 +72,7 @@
const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
const char* const kFeatureAbb = "abb";
const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
+const char* const kFeatureAbbExec = "abb_exec";
namespace {
@@ -1013,6 +1014,7 @@
kFeatureApex,
kFeatureAbb,
kFeatureFixedPushSymlinkTimestamp,
+ kFeatureAbbExec,
// Increment ADB_SERVER_VERSION when adding a feature that adbd needs
// to know about. Otherwise, the client can be stuck running an old
// version of the server even after upgrading their copy of adb.
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index fa9080e..80fa5c4 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -34,6 +34,19 @@
namespace android {
namespace fs_mgr {
+std::string GetAvbPropertyDescriptor(const std::string& key,
+ const std::vector<VBMetaData>& vbmeta_images) {
+ size_t value_size;
+ for (const auto& vbmeta : vbmeta_images) {
+ const char* value = avb_property_lookup(vbmeta.data(), vbmeta.size(), key.data(),
+ key.size(), &value_size);
+ if (value != nullptr) {
+ return {value, value_size};
+ }
+ }
+ return "";
+}
+
// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
// See the following link for more details:
// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h
index 9babd88..5f413e3 100644
--- a/fs_mgr/libfs_avb/avb_util.h
+++ b/fs_mgr/libfs_avb/avb_util.h
@@ -37,6 +37,9 @@
: partition_name(chain_partition_name), public_key_blob(chain_public_key_blob) {}
};
+std::string GetAvbPropertyDescriptor(const std::string& key,
+ const std::vector<VBMetaData>& vbmeta_images);
+
// AvbHashtreeDescriptor to dm-verity table setup.
std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images);
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index 938e149..02902f0 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -263,6 +263,69 @@
return avb_handle;
}
+AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) {
+ if (fstab_entry.avb_key.empty()) {
+ LERROR << "avb_key=/path/to/key is missing for " << fstab_entry.mount_point;
+ return nullptr;
+ }
+
+ // Binds allow_verification_error and rollback_protection to device unlock state.
+ bool allow_verification_error = IsDeviceUnlocked();
+ bool rollback_protection = !allow_verification_error;
+
+ std::string expected_key_blob;
+ if (!ReadFileToString(fstab_entry.avb_key, &expected_key_blob)) {
+ if (!allow_verification_error) {
+ LERROR << "Failed to load avb_key: " << fstab_entry.avb_key
+ << " for mount point: " << fstab_entry.mount_point;
+ return nullptr;
+ }
+ LWARNING << "Allowing no expected key blob when verification error is permitted";
+ expected_key_blob.clear();
+ }
+
+ bool verification_disabled = false;
+ VBMetaVerifyResult verify_result = VBMetaVerifyResult::kError;
+ std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
+ fstab_entry.blk_device, "" /* partition_name, no need for a standalone path */,
+ expected_key_blob, allow_verification_error, rollback_protection,
+ false /* not is_chained_vbmeta */, nullptr /* out_public_key_data */,
+ &verification_disabled, &verify_result);
+
+ if (!vbmeta) {
+ LERROR << "Failed to load vbmeta: " << fstab_entry.blk_device;
+ return nullptr;
+ }
+
+ AvbUniquePtr avb_handle(new AvbHandle());
+ if (!avb_handle) {
+ LERROR << "Failed to allocate AvbHandle";
+ return nullptr;
+ }
+ avb_handle->vbmeta_images_.emplace_back(std::move(*vbmeta));
+
+ switch (verify_result) {
+ case VBMetaVerifyResult::kSuccess:
+ avb_handle->status_ = AvbHandleStatus::kSuccess;
+ break;
+ case VBMetaVerifyResult::kErrorVerification:
+ avb_handle->status_ = AvbHandleStatus::kVerificationError;
+ break;
+ default:
+ LERROR << "LoadAndVerifyVbmetaByPath failed, result: " << verify_result;
+ return nullptr;
+ }
+
+ if (verification_disabled) {
+ LINFO << "AVB verification disabled on: " << fstab_entry.mount_point;
+ avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
+ }
+
+ LINFO << "Returning avb_handle for '" << fstab_entry.mount_point
+ << "' with status: " << avb_handle->status_;
+ return avb_handle;
+}
+
AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta() {
// Loads inline vbmeta images, starting from /vbmeta.
return LoadAndVerifyVbmeta("vbmeta", fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix(),
@@ -358,52 +421,12 @@
AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
bool wait_for_verity_dev) {
- if (fstab_entry->avb_key.empty()) {
- LERROR << "avb_key=/path/to/key is missing for " << fstab_entry->mount_point;
+ auto avb_handle = LoadAndVerifyVbmeta(*fstab_entry);
+ if (!avb_handle) {
return AvbHashtreeResult::kFail;
}
- // Binds allow_verification_error and rollback_protection to device unlock state.
- bool allow_verification_error = IsDeviceUnlocked();
- bool rollback_protection = !allow_verification_error;
-
- std::string expected_key_blob;
- if (!ReadFileToString(fstab_entry->avb_key, &expected_key_blob)) {
- if (!allow_verification_error) {
- LERROR << "Failed to load avb_key: " << fstab_entry->avb_key
- << " for mount point: " << fstab_entry->mount_point;
- return AvbHashtreeResult::kFail;
- }
- LWARNING << "Allowing no expected key blob when verification error is permitted";
- expected_key_blob.clear();
- }
-
- bool verification_disabled = false;
- std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
- fstab_entry->blk_device, "" /* partition_name, no need for a standalone path */,
- expected_key_blob, allow_verification_error, rollback_protection,
- false /* not is_chained_vbmeta */, nullptr /* out_public_key_data */,
- &verification_disabled, nullptr /* out_verify_result */);
-
- if (!vbmeta) {
- LERROR << "Failed to load vbmeta: " << fstab_entry->blk_device;
- return AvbHashtreeResult::kFail;
- }
-
- if (verification_disabled) {
- LINFO << "AVB verification disabled on: " << fstab_entry->mount_point;
- return AvbHashtreeResult::kDisabled;
- }
-
- // Puts the vbmeta into a vector, for LoadAvbHashtreeToEnableVerity() to use.
- std::vector<VBMetaData> vbmeta_images;
- vbmeta_images.emplace_back(std::move(*vbmeta));
- if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images,
- fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
- return AvbHashtreeResult::kFail;
- }
-
- return AvbHashtreeResult::kSuccess;
+ return avb_handle->SetUpAvbHashtree(fstab_entry, wait_for_verity_dev);
}
AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
@@ -425,5 +448,19 @@
return AvbHashtreeResult::kSuccess;
}
+std::string AvbHandle::GetSecurityPatchLevel(const FstabEntry& fstab_entry) const {
+ if (vbmeta_images_.size() < 1) {
+ return "";
+ }
+ std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
+ fs_mgr_get_other_slot_suffix());
+ auto avb_prop_name = "com.android.build." + avb_partition_name + ".security_patch";
+ return GetAvbPropertyDescriptor(avb_prop_name, vbmeta_images_);
+}
+
+bool AvbHandle::IsDeviceUnlocked() {
+ return android::fs_mgr::IsDeviceUnlocked();
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index d026722..7127fa6 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -85,6 +85,8 @@
// TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta().
static AvbUniquePtr Open(); // loads inline vbmeta, via libavb.
static AvbUniquePtr LoadAndVerifyVbmeta(); // loads inline vbmeta.
+ static AvbUniquePtr LoadAndVerifyVbmeta(
+ const FstabEntry& fstab_entry); // loads offline vbmeta.
static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta.
const std::string& partition_name, const std::string& ab_suffix,
const std::string& ab_other_suffix, const std::string& expected_public_key,
@@ -108,6 +110,10 @@
static AvbHashtreeResult SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
bool wait_for_verity_dev = true);
+ static bool IsDeviceUnlocked();
+
+ std::string GetSecurityPatchLevel(const FstabEntry& fstab_entry) const;
+
const std::string& avb_version() const { return avb_version_; }
const VBMetaInfo& vbmeta_info() const { return vbmeta_info_; }
AvbHandleStatus status() const { return status_; }
diff --git a/fs_mgr/libfs_avb/tests/avb_util_test.cpp b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
index 835410f..e4213b7 100644
--- a/fs_mgr/libfs_avb/tests/avb_util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
@@ -30,6 +30,7 @@
using android::fs_mgr::DeriveAvbPartitionName;
using android::fs_mgr::FstabEntry;
using android::fs_mgr::GetAvbFooter;
+using android::fs_mgr::GetAvbPropertyDescriptor;
using android::fs_mgr::GetChainPartitionInfo;
using android::fs_mgr::GetTotalSize;
using android::fs_mgr::LoadAndVerifyVbmetaByPartition;
@@ -268,6 +269,67 @@
EXPECT_EQ(nullptr, footer);
}
+TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_Basic) {
+ // Makes a vbmeta.img with some properties.
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
+ {}, /* include_descriptor_image_paths */
+ {}, /* chain_partitions */
+ "--prop foo:android "
+ "--prop bar:treble "
+ "--internal_release_string \"unit test\" ");
+ auto vbmeta = LoadVBMetaData("vbmeta.img");
+
+ // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
+ std::vector<VBMetaData> vbmeta_images;
+ vbmeta_images.emplace_back(std::move(vbmeta));
+
+ EXPECT_EQ("android", GetAvbPropertyDescriptor("foo", vbmeta_images));
+ EXPECT_EQ("treble", GetAvbPropertyDescriptor("bar", vbmeta_images));
+ EXPECT_EQ("", GetAvbPropertyDescriptor("non-existent", vbmeta_images));
+}
+
+TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_SecurityPatchLevel) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
+ data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--prop com.android.build.system.security_patch:2019-04-05 "
+ "--internal_release_string \"unit test\"");
+
+ // Generates chain partition descriptors.
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+
+ // Makes a vbmeta.img including the 'system' chained descriptor.
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
+ {boot_path}, /* include_descriptor_image_paths */
+ {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+
+ auto vbmeta = LoadVBMetaData("vbmeta.img");
+ auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img");
+
+ // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
+ std::vector<VBMetaData> vbmeta_images;
+ vbmeta_images.emplace_back(std::move(vbmeta));
+ vbmeta_images.emplace_back(std::move(system_vbmeta));
+
+ EXPECT_EQ("2019-04-05",
+ GetAvbPropertyDescriptor("com.android.build.system.security_patch", vbmeta_images));
+}
+
TEST_F(AvbUtilTest, GetVBMetaHeader) {
// Generates a raw boot.img
const size_t image_size = 5 * 1024 * 1024;
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp
index fc4eb5f..4631330 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp
+++ b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp
@@ -15,6 +15,7 @@
*/
#include <android-base/properties.h>
+#include <fs_avb/fs_avb.h>
#include <fs_avb/fs_avb_util.h>
#include <fstab/fstab.h>
#include <gtest/gtest.h>
@@ -22,6 +23,8 @@
#include <sys/types.h>
#include <unistd.h>
+using android::fs_mgr::AvbHandle;
+using android::fs_mgr::AvbHandleStatus;
using android::fs_mgr::Fstab;
using android::fs_mgr::FstabEntry;
using android::fs_mgr::VBMetaData;
@@ -31,7 +34,7 @@
// system vbmeta might not be at the end of /system when dynamic partition is
// enabled. Therefore, disable it by default.
-TEST(PublicFsAvbDeviceTest, DISABLED_LoadAndVerifyVbmeta_SystemVbmeta) {
+TEST(FsAvbUtilTest, DISABLED_LoadAndVerifyVbmeta_SystemVbmeta) {
Fstab fstab;
EXPECT_TRUE(ReadDefaultFstab(&fstab));
@@ -51,7 +54,7 @@
EXPECT_NE("", out_public_key_data);
}
-TEST(PublicFsAvbDeviceTest, GetHashtreeDescriptor_SystemOther) {
+TEST(FsAvbUtilTest, GetHashtreeDescriptor_SystemOther) {
// Non-A/B device doesn't have system_other partition.
if (fs_mgr_get_slot_suffix() == "") return;
@@ -90,4 +93,55 @@
EXPECT_NE(nullptr, hashtree_desc);
}
+TEST(AvbHandleTest, LoadAndVerifyVbmeta_SystemOther) {
+ // Non-A/B device doesn't have system_other partition.
+ if (fs_mgr_get_slot_suffix() == "") return;
+
+ // Skip running this test if system_other is a logical partition.
+ // Note that system_other is still a physical partition on "retrofit" devices.
+ if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) &&
+ !android::base::GetBoolProperty("ro.boot.dynamic_partitions_retrofit", false)) {
+ return;
+ }
+
+ Fstab fstab;
+ EXPECT_TRUE(ReadFstabFromFile("/system/etc/fstab.postinstall", &fstab));
+
+ // It should have two lines in the fstab, the first for logical system_other,
+ // the other for physical system_other.
+ EXPECT_EQ(2UL, fstab.size());
+
+ // Use the 2nd fstab entry, which is for physical system_other partition.
+ FstabEntry* system_other_entry = &fstab[1];
+ // Assign the default key if it's not specified in the fstab.
+ if (system_other_entry->avb_key.empty()) {
+ system_other_entry->avb_key = "/system/etc/security/avb/system_other.avbpubkey";
+ }
+ auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(*system_other_entry);
+ EXPECT_NE(nullptr, avb_handle) << "Failed to load system_other vbmeta. Try 'adb root'?";
+ EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
+}
+
+TEST(AvbHandleTest, GetSecurityPatchLevel) {
+ Fstab fstab;
+ EXPECT_TRUE(ReadDefaultFstab(&fstab));
+
+ auto avb_handle = AvbHandle::LoadAndVerifyVbmeta();
+ EXPECT_NE(nullptr, avb_handle) << "Failed to load inline vbmeta. Try 'adb root'?";
+ EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
+
+ // Gets security patch level with format: YYYY-MM-DD (e.g., 2019-04-05).
+ FstabEntry* system_entry = GetEntryForMountPoint(&fstab, "/system");
+ EXPECT_NE(nullptr, system_entry);
+ EXPECT_EQ(10UL, avb_handle->GetSecurityPatchLevel(*system_entry).length());
+
+ FstabEntry* vendor_entry = GetEntryForMountPoint(&fstab, "/vendor");
+ EXPECT_NE(nullptr, vendor_entry);
+ EXPECT_EQ(10UL, avb_handle->GetSecurityPatchLevel(*vendor_entry).length());
+
+ FstabEntry* product_entry = GetEntryForMountPoint(&fstab, "/product");
+ EXPECT_NE(nullptr, product_entry);
+ EXPECT_EQ(10UL, avb_handle->GetSecurityPatchLevel(*product_entry).length());
+}
+
} // namespace fs_avb_device_test
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 898e28e..6e55c11a 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -189,6 +189,29 @@
return true;
}
+static bool IsStandaloneImageRollback(const AvbHandle& builtin_vbmeta,
+ const AvbHandle& standalone_vbmeta,
+ const FstabEntry& fstab_entry) {
+ std::string old_spl = builtin_vbmeta.GetSecurityPatchLevel(fstab_entry);
+ std::string new_spl = standalone_vbmeta.GetSecurityPatchLevel(fstab_entry);
+
+ bool rollbacked = false;
+ if (old_spl.empty() || new_spl.empty() || new_spl < old_spl) {
+ rollbacked = true;
+ }
+
+ if (rollbacked) {
+ LOG(ERROR) << "Image rollback detected for " << fstab_entry.mount_point
+ << ", SPL switches from '" << old_spl << "' to '" << new_spl << "'";
+ if (AvbHandle::IsDeviceUnlocked()) {
+ LOG(INFO) << "Allowing rollbacked standalone image when the device is unlocked";
+ return false;
+ }
+ }
+
+ return rollbacked;
+}
+
// Class Definitions
// -----------------
FirstStageMount::FirstStageMount(Fstab fstab)
@@ -746,7 +769,15 @@
<< fstab_entry->mount_point;
return true; // Returns true to mount the partition directly.
} else {
- hashtree_result = AvbHandle::SetUpStandaloneAvbHashtree(
+ auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry);
+ if (!avb_standalone_handle) {
+ LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point;
+ return false;
+ }
+ if (IsStandaloneImageRollback(*avb_handle_, *avb_standalone_handle, *fstab_entry)) {
+ return false;
+ }
+ hashtree_result = avb_standalone_handle->SetUpAvbHashtree(
fstab_entry, false /* wait_for_verity_dev */);
}
} else {
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index f9c161c..043f038 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -115,6 +115,8 @@
static constexpr const char* kVndkNamespaceName = "vndk";
+static constexpr const char* kDefaultNamespaceName = "default";
+static constexpr const char* kPlatformNamespaceName = "platform";
static constexpr const char* kRuntimeNamespaceName = "runtime";
// classloader-namespace is a linker namespace that is created for the loaded
@@ -272,8 +274,19 @@
NativeLoaderNamespace native_loader_ns;
if (!is_native_bridge) {
- android_namespace_t* android_parent_ns =
- parent_ns == nullptr ? nullptr : parent_ns->get_android_ns();
+ android_namespace_t* android_parent_ns;
+ if (parent_ns != nullptr) {
+ android_parent_ns = parent_ns->get_android_ns();
+ } else {
+ // Fall back to the platform namespace if no parent is found. It is
+ // called "default" for binaries in /system and "platform" for those in
+ // the Runtime APEX. Try "platform" first since "default" always exists.
+ android_parent_ns = android_get_exported_namespace(kPlatformNamespaceName);
+ if (android_parent_ns == nullptr) {
+ android_parent_ns = android_get_exported_namespace(kDefaultNamespaceName);
+ }
+ }
+
android_namespace_t* ns = android_create_namespace(namespace_name,
nullptr,
library_path.c_str(),
@@ -322,8 +335,16 @@
native_loader_ns = NativeLoaderNamespace(ns);
} else {
- native_bridge_namespace_t* native_bridge_parent_namespace =
- parent_ns == nullptr ? nullptr : parent_ns->get_native_bridge_ns();
+ native_bridge_namespace_t* native_bridge_parent_namespace;
+ if (parent_ns != nullptr) {
+ native_bridge_parent_namespace = parent_ns->get_native_bridge_ns();
+ } else {
+ native_bridge_parent_namespace = NativeBridgeGetExportedNamespace(kPlatformNamespaceName);
+ if (native_bridge_parent_namespace == nullptr) {
+ native_bridge_parent_namespace = NativeBridgeGetExportedNamespace(kDefaultNamespaceName);
+ }
+ }
+
native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name,
nullptr,
library_path.c_str(),
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index fa0a01a..0cde3f2 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -91,6 +91,8 @@
namespace.media.search.paths = /apex/com.android.media/${LIB}
namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index cf834f0..28703d2 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -169,6 +169,8 @@
namespace.media.search.paths = /apex/com.android.media/${LIB}
namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
@@ -553,6 +555,8 @@
namespace.media.search.paths = /apex/com.android.media/${LIB}
namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 2c6e01f..a5beb4e 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -117,6 +117,8 @@
namespace.media.search.paths = /apex/com.android.media/${LIB}
namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
@@ -434,6 +436,8 @@
namespace.media.search.paths = /apex/com.android.media/${LIB}
namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+
namespace.media.links = default
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so